summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp124
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h30
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp15
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp28
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h7
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp89
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h28
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp2
-rw-r--r--media/libstagefright/ACodec.cpp19
-rw-r--r--media/libstagefright/SampleTable.cpp101
-rw-r--r--media/libstagefright/avc_utils.cpp22
-rw-r--r--media/libstagefright/chromium_http/support.cpp22
-rw-r--r--media/libstagefright/foundation/AMessage.cpp9
-rw-r--r--media/libstagefright/include/SampleTable.h6
-rw-r--r--media/libstagefright/include/avc_utils.h1
-rw-r--r--media/libstagefright/omx/OMX.cpp2
-rw-r--r--media/libstagefright/omx/SimpleSoftOMXComponent.cpp2
18 files changed, 384 insertions, 126 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index ee77f47..7218faf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -34,17 +34,21 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/ACodec.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <surfaceflinger/Surface.h>
#include <gui/ISurfaceTexture.h>
+#include "avc_utils.h"
+
namespace android {
////////////////////////////////////////////////////////////////////////////////
NuPlayer::NuPlayer()
: mUIDValid(false),
+ mVideoIsAVC(false),
mAudioEOS(false),
mVideoEOS(false),
mScanSourcesPending(false),
@@ -52,7 +56,12 @@ NuPlayer::NuPlayer()
mFlushingAudio(NONE),
mFlushingVideo(NONE),
mResetInProgress(false),
- mResetPostponed(false) {
+ mResetPostponed(false),
+ mSkipRenderingAudioUntilMediaTimeUs(-1ll),
+ mSkipRenderingVideoUntilMediaTimeUs(-1ll),
+ mVideoLateByUs(0ll),
+ mNumFramesTotal(0ll),
+ mNumFramesDropped(0ll) {
}
NuPlayer::~NuPlayer() {
@@ -185,10 +194,14 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
{
LOGV("kWhatStart");
+ mVideoIsAVC = false;
mAudioEOS = false;
mVideoEOS = false;
mSkipRenderingAudioUntilMediaTimeUs = -1;
mSkipRenderingVideoUntilMediaTimeUs = -1;
+ mVideoLateByUs = 0;
+ mNumFramesTotal = 0;
+ mNumFramesDropped = 0;
mSource->start();
@@ -269,6 +282,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
} else {
CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
mFlushingVideo = FLUSHED;
+
+ mVideoLateByUs = 0;
}
LOGV("decoder %s flush completed", audio ? "audio" : "video");
@@ -299,7 +314,12 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
sampleRate, numChannels);
mAudioSink->close();
- CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
+ CHECK_EQ(mAudioSink->open(
+ sampleRate,
+ numChannels,
+ AUDIO_FORMAT_PCM_16_BIT,
+ 8 /* bufferCount */),
+ (status_t)OK);
mAudioSink->start();
mRenderer->signalAudioSinkChanged();
@@ -392,13 +412,18 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
int64_t positionUs;
CHECK(msg->findInt64("positionUs", &positionUs));
+ CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
+
if (mDriver != NULL) {
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
driver->notifyPosition(positionUs);
+
+ driver->notifyFrameStats(
+ mNumFramesTotal, mNumFramesDropped);
}
}
- } else {
+ } else if (what == Renderer::kWhatFlushComplete) {
CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
int32_t audio;
@@ -560,6 +585,12 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
return -EWOULDBLOCK;
}
+ if (!audio) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime);
+ }
+
sp<AMessage> notify =
new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
id());
@@ -593,53 +624,70 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
}
sp<ABuffer> accessUnit;
- status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
- if (err == -EWOULDBLOCK) {
- return err;
- } else if (err != OK) {
- if (err == INFO_DISCONTINUITY) {
- int32_t type;
- CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
+ bool dropAccessUnit;
+ do {
+ status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
- bool formatChange =
- type == ATSParser::DISCONTINUITY_FORMATCHANGE;
+ if (err == -EWOULDBLOCK) {
+ return err;
+ } else if (err != OK) {
+ if (err == INFO_DISCONTINUITY) {
+ int32_t type;
+ CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
- LOGV("%s discontinuity (formatChange=%d)",
- audio ? "audio" : "video", formatChange);
+ bool formatChange =
+ type == ATSParser::DISCONTINUITY_FORMATCHANGE;
- if (audio) {
- mSkipRenderingAudioUntilMediaTimeUs = -1;
- } else {
- mSkipRenderingVideoUntilMediaTimeUs = -1;
- }
+ LOGV("%s discontinuity (formatChange=%d)",
+ audio ? "audio" : "video", formatChange);
- sp<AMessage> extra;
- if (accessUnit->meta()->findMessage("extra", &extra)
- && extra != NULL) {
- int64_t resumeAtMediaTimeUs;
- if (extra->findInt64(
- "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
- LOGI("suppressing rendering of %s until %lld us",
- audio ? "audio" : "video", resumeAtMediaTimeUs);
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs = -1;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs = -1;
+ }
- if (audio) {
- mSkipRenderingAudioUntilMediaTimeUs =
- resumeAtMediaTimeUs;
- } else {
- mSkipRenderingVideoUntilMediaTimeUs =
- resumeAtMediaTimeUs;
+ sp<AMessage> extra;
+ if (accessUnit->meta()->findMessage("extra", &extra)
+ && extra != NULL) {
+ int64_t resumeAtMediaTimeUs;
+ if (extra->findInt64(
+ "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+ LOGI("suppressing rendering of %s until %lld us",
+ audio ? "audio" : "video", resumeAtMediaTimeUs);
+
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ }
}
}
+
+ flushDecoder(audio, formatChange);
}
- flushDecoder(audio, formatChange);
+ reply->setInt32("err", err);
+ reply->post();
+ return OK;
}
- reply->setInt32("err", err);
- reply->post();
- return OK;
- }
+ if (!audio) {
+ ++mNumFramesTotal;
+ }
+
+ dropAccessUnit = false;
+ if (!audio
+ && mVideoLateByUs > 100000ll
+ && mVideoIsAVC
+ && !IsAVCReferenceFrame(accessUnit)) {
+ dropAccessUnit = true;
+ ++mNumFramesDropped;
+ }
+ } while (dropAccessUnit);
// LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index cf9185b..a5382b4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -70,19 +70,19 @@ private:
struct StreamingSource;
enum {
- kWhatSetDataSource,
- kWhatSetVideoNativeWindow,
- kWhatSetAudioSink,
- kWhatMoreDataQueued,
- kWhatStart,
- kWhatScanSources,
- kWhatVideoNotify,
- kWhatAudioNotify,
- kWhatRendererNotify,
- kWhatReset,
- kWhatSeek,
- kWhatPause,
- kWhatResume,
+ kWhatSetDataSource = '=DaS',
+ kWhatSetVideoNativeWindow = '=NaW',
+ kWhatSetAudioSink = '=AuS',
+ kWhatMoreDataQueued = 'more',
+ kWhatStart = 'strt',
+ kWhatScanSources = 'scan',
+ kWhatVideoNotify = 'vidN',
+ kWhatAudioNotify = 'audN',
+ kWhatRendererNotify = 'renN',
+ kWhatReset = 'rset',
+ kWhatSeek = 'seek',
+ kWhatPause = 'paus',
+ kWhatResume = 'rsme',
};
wp<NuPlayerDriver> mDriver;
@@ -92,6 +92,7 @@ private:
sp<NativeWindowWrapper> mNativeWindow;
sp<MediaPlayerBase::AudioSink> mAudioSink;
sp<Decoder> mVideoDecoder;
+ bool mVideoIsAVC;
sp<Decoder> mAudioDecoder;
sp<Renderer> mRenderer;
@@ -119,6 +120,9 @@ private:
int64_t mSkipRenderingAudioUntilMediaTimeUs;
int64_t mSkipRenderingVideoUntilMediaTimeUs;
+ int64_t mVideoLateByUs;
+ int64_t mNumFramesTotal, mNumFramesDropped;
+
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 81b41ef..56c2773 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -59,8 +59,21 @@ void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
format->setObject("native-window", mNativeWindow);
}
+ // Current video decoders do not return from OMX_FillThisBuffer
+ // quickly, violating the OpenMAX specs, until that is remedied
+ // we need to invest in an extra looper to free the main event
+ // queue.
+ bool needDedicatedLooper = !strncasecmp(mime, "video/", 6);
+
mCodec = new ACodec;
- looper()->registerHandler(mCodec);
+
+ if (needDedicatedLooper && mCodecLooper == NULL) {
+ mCodecLooper = new ALooper;
+ mCodecLooper->setName("NuPlayerDecoder");
+ mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+ }
+
+ (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec);
mCodec->setNotificationMessage(notifyMsg);
mCodec->initiateSetup(format);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index fabc606..3ab1fcf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -43,13 +43,14 @@ protected:
private:
enum {
- kWhatCodecNotify,
+ kWhatCodecNotify = 'cdcN',
};
sp<AMessage> mNotify;
sp<NativeWindowWrapper> mNativeWindow;
sp<ACodec> mCodec;
+ sp<ALooper> mCodecLooper;
Vector<sp<ABuffer> > mCSD;
size_t mCSDIndex;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index c6fca2c..b1e917d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -31,6 +31,8 @@ NuPlayerDriver::NuPlayerDriver()
: mResetInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
+ mNumFramesTotal(0),
+ mNumFramesDropped(0),
mLooper(new ALooper),
mState(UNINITIALIZED),
mStartupSeekTimeUs(-1) {
@@ -292,4 +294,30 @@ void NuPlayerDriver::notifySeekComplete() {
sendEvent(MEDIA_SEEK_COMPLETE);
}
+void NuPlayerDriver::notifyFrameStats(
+ int64_t numFramesTotal, int64_t numFramesDropped) {
+ Mutex::Autolock autoLock(mLock);
+ mNumFramesTotal = numFramesTotal;
+ mNumFramesDropped = numFramesDropped;
+}
+
+status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
+ Mutex::Autolock autoLock(mLock);
+
+ FILE *out = fdopen(dup(fd), "w");
+
+ fprintf(out, " NuPlayer\n");
+ fprintf(out, " numFramesTotal(%lld), numFramesDropped(%lld), "
+ "percentageDropped(%.2f)\n",
+ mNumFramesTotal,
+ mNumFramesDropped,
+ mNumFramesTotal == 0
+ ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
+
+ fclose(out);
+ out = NULL;
+
+ return OK;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 1bb7ca2..181c37d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -60,16 +60,19 @@ struct NuPlayerDriver : public MediaPlayerInterface {
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
+ virtual status_t dump(int fd, const Vector<String16> &args) const;
+
void notifyResetComplete();
void notifyDuration(int64_t durationUs);
void notifyPosition(int64_t positionUs);
void notifySeekComplete();
+ void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
protected:
virtual ~NuPlayerDriver();
private:
- Mutex mLock;
+ mutable Mutex mLock;
Condition mCondition;
// The following are protected through "mLock"
@@ -77,6 +80,8 @@ private:
bool mResetInProgress;
int64_t mDurationUs;
int64_t mPositionUs;
+ int64_t mNumFramesTotal;
+ int64_t mNumFramesDropped;
// <<<
sp<ALooper> mLooper;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index bf83849..07e347e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -47,7 +47,8 @@ NuPlayer::Renderer::Renderer(
mHasVideo(false),
mSyncQueues(false),
mPaused(false),
- mLastPositionUpdateUs(-1ll) {
+ mLastPositionUpdateUs(-1ll),
+ mVideoLateByUs(0ll) {
}
NuPlayer::Renderer::~Renderer() {
@@ -118,9 +119,24 @@ void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
mDrainAudioQueuePending = false;
- onDrainAudioQueue();
+ if (onDrainAudioQueue()) {
+ uint32_t numFramesPlayed;
+ CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
+ (status_t)OK);
- postDrainAudioQueue();
+ uint32_t numFramesPendingPlayout =
+ mNumFramesWritten - numFramesPlayed;
+
+ // This is how long the audio sink will have data to
+ // play back.
+ int64_t delayUs =
+ mAudioSink->msecsPerFrame()
+ * numFramesPendingPlayout * 1000ll;
+
+ // Let's give it more data after about half that time
+ // has elapsed.
+ postDrainAudioQueue(delayUs / 2);
+ }
break;
}
@@ -182,7 +198,7 @@ void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
}
}
-void NuPlayer::Renderer::postDrainAudioQueue() {
+void NuPlayer::Renderer::postDrainAudioQueue(int64_t delayUs) {
if (mDrainAudioQueuePending || mSyncQueues || mPaused) {
return;
}
@@ -194,19 +210,33 @@ void NuPlayer::Renderer::postDrainAudioQueue() {
mDrainAudioQueuePending = true;
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
msg->setInt32("generation", mAudioQueueGeneration);
- msg->post();
+ msg->post(delayUs);
}
void NuPlayer::Renderer::signalAudioSinkChanged() {
(new AMessage(kWhatAudioSinkChanged, id()))->post();
}
-void NuPlayer::Renderer::onDrainAudioQueue() {
- for (;;) {
- if (mAudioQueue.empty()) {
- break;
- }
+bool NuPlayer::Renderer::onDrainAudioQueue() {
+ uint32_t numFramesPlayed;
+ CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
+
+ ssize_t numFramesAvailableToWrite =
+ mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
+#if 0
+ if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
+ LOGI("audio sink underrun");
+ } else {
+ LOGV("audio queue has %d frames left to play",
+ mAudioSink->frameCount() - numFramesAvailableToWrite);
+ }
+#endif
+
+ size_t numBytesAvailableToWrite =
+ numFramesAvailableToWrite * mAudioSink->frameSize();
+
+ while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
QueueEntry *entry = &*mAudioQueue.begin();
if (entry->mBuffer == NULL) {
@@ -216,20 +246,7 @@ void NuPlayer::Renderer::onDrainAudioQueue() {
mAudioQueue.erase(mAudioQueue.begin());
entry = NULL;
- return;
- }
-
- uint32_t numFramesPlayed;
- CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
-
- ssize_t numFramesAvailableToWrite =
- mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
-
- size_t numBytesAvailableToWrite =
- numFramesAvailableToWrite * mAudioSink->frameSize();
-
- if (numBytesAvailableToWrite == 0) {
- break;
+ return false;
}
if (entry->mOffset == 0) {
@@ -274,10 +291,14 @@ void NuPlayer::Renderer::onDrainAudioQueue() {
entry = NULL;
}
- mNumFramesWritten += copy / mAudioSink->frameSize();
+ numBytesAvailableToWrite -= copy;
+ size_t copiedFrames = copy / mAudioSink->frameSize();
+ mNumFramesWritten += copiedFrames;
}
notifyPosition();
+
+ return !mAudioQueue.empty();
}
void NuPlayer::Renderer::postDrainVideoQueue() {
@@ -337,15 +358,26 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
mVideoQueue.erase(mVideoQueue.begin());
entry = NULL;
+
+ mVideoLateByUs = 0ll;
+
+ notifyPosition();
return;
}
-#if 0
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
- LOGI("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
-#endif
+ int64_t realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
+ mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
+
+ bool tooLate = (mVideoLateByUs > 40000);
+
+ if (tooLate) {
+ LOGV("video late by %lld us (%.2f secs)", lateByUs, lateByUs / 1E6);
+ } else {
+ LOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
+ }
entry->mNotifyConsumed->setInt32("render", true);
entry->mNotifyConsumed->post();
@@ -577,6 +609,7 @@ void NuPlayer::Renderer::notifyPosition() {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatPosition);
notify->setInt64("positionUs", positionUs);
+ notify->setInt64("videoLateByUs", mVideoLateByUs);
notify->post();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 3a641a2..268628b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -45,9 +45,9 @@ struct NuPlayer::Renderer : public AHandler {
void resume();
enum {
- kWhatEOS,
- kWhatFlushComplete,
- kWhatPosition,
+ kWhatEOS = 'eos ',
+ kWhatFlushComplete = 'fluC',
+ kWhatPosition = 'posi',
};
protected:
@@ -57,14 +57,14 @@ protected:
private:
enum {
- kWhatDrainAudioQueue,
- kWhatDrainVideoQueue,
- kWhatQueueBuffer,
- kWhatQueueEOS,
- kWhatFlush,
- kWhatAudioSinkChanged,
- kWhatPause,
- kWhatResume,
+ kWhatDrainAudioQueue = 'draA',
+ kWhatDrainVideoQueue = 'draV',
+ kWhatQueueBuffer = 'queB',
+ kWhatQueueEOS = 'qEOS',
+ kWhatFlush = 'flus',
+ kWhatAudioSinkChanged = 'auSC',
+ kWhatPause = 'paus',
+ kWhatResume = 'resm',
};
struct QueueEntry {
@@ -101,9 +101,10 @@ private:
bool mPaused;
int64_t mLastPositionUpdateUs;
+ int64_t mVideoLateByUs;
- void onDrainAudioQueue();
- void postDrainAudioQueue();
+ bool onDrainAudioQueue();
+ void postDrainAudioQueue(int64_t delayUs = 0);
void onDrainVideoQueue();
void postDrainVideoQueue();
@@ -118,6 +119,7 @@ private:
void notifyEOS(bool audio, status_t finalResult);
void notifyFlushComplete(bool audio);
void notifyPosition();
+ void notifyVideoLateBy(int64_t lateByUs);
void flushQueue(List<QueueEntry> *queue);
bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index a741987..7319e4c 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -52,7 +52,7 @@ bool NuPlayer::StreamingSource::feedMoreTSData() {
return false;
}
- for (int32_t i = 0; i < 10; ++i) {
+ for (int32_t i = 0; i < 50; ++i) {
char buffer[188];
sp<AMessage> extra;
ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2ba2273..a2d9e59 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1377,8 +1377,13 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
memcpy(info->mData->data(), buffer->data(), buffer->size());
}
- LOGV("[%s] calling emptyBuffer %p",
- mCodec->mComponentName.c_str(), bufferID);
+ if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
+ LOGV("[%s] calling emptyBuffer %p w/ codec specific data",
+ mCodec->mComponentName.c_str(), bufferID);
+ } else {
+ LOGV("[%s] calling emptyBuffer %p w/ time %lld us",
+ mCodec->mComponentName.c_str(), bufferID, timeUs);
+ }
CHECK_EQ(mCodec->mOMX->emptyBuffer(
mCodec->mNode,
@@ -1396,7 +1401,7 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
LOGV("[%s] Signalling EOS on the input port",
mCodec->mComponentName.c_str());
- LOGV("[%s] calling emptyBuffer %p",
+ LOGV("[%s] calling emptyBuffer %p signalling EOS",
mCodec->mComponentName.c_str(), bufferID);
CHECK_EQ(mCodec->mOMX->emptyBuffer(
@@ -1457,8 +1462,8 @@ bool ACodec::BaseState::onOMXFillBufferDone(
int64_t timeUs,
void *platformPrivate,
void *dataPtr) {
- LOGV("[%s] onOMXFillBufferDone %p",
- mCodec->mComponentName.c_str(), bufferID);
+ LOGV("[%s] onOMXFillBufferDone %p time %lld us",
+ mCodec->mComponentName.c_str(), bufferID, timeUs);
ssize_t index;
BufferInfo *info =
@@ -1686,7 +1691,11 @@ void ACodec::UninitializedState::onSetup(
++matchIndex) {
componentName = matchingCodecs.itemAt(matchIndex).string();
+ pid_t tid = androidGetTid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+ androidSetThreadPriority(tid, prevPriority);
if (err == OK) {
break;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 2b9d99b..ebad321 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -23,8 +23,8 @@
#include <arpa/inet.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/Utils.h>
namespace android {
@@ -40,6 +40,71 @@ const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
////////////////////////////////////////////////////////////////////////////////
+struct SampleTable::CompositionDeltaLookup {
+ CompositionDeltaLookup();
+
+ void setEntries(
+ const uint32_t *deltaEntries, size_t numDeltaEntries);
+
+ uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+
+private:
+ Mutex mLock;
+
+ const uint32_t *mDeltaEntries;
+ size_t mNumDeltaEntries;
+
+ size_t mCurrentDeltaEntry;
+ size_t mCurrentEntrySampleIndex;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
+};
+
+SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
+ : mDeltaEntries(NULL),
+ mNumDeltaEntries(0),
+ mCurrentDeltaEntry(0),
+ mCurrentEntrySampleIndex(0) {
+}
+
+void SampleTable::CompositionDeltaLookup::setEntries(
+ const uint32_t *deltaEntries, size_t numDeltaEntries) {
+ Mutex::Autolock autolock(mLock);
+
+ mDeltaEntries = deltaEntries;
+ mNumDeltaEntries = numDeltaEntries;
+ mCurrentDeltaEntry = 0;
+ mCurrentEntrySampleIndex = 0;
+}
+
+uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
+ uint32_t sampleIndex) {
+ Mutex::Autolock autolock(mLock);
+
+ if (mDeltaEntries == NULL) {
+ return 0;
+ }
+
+ if (sampleIndex < mCurrentEntrySampleIndex) {
+ mCurrentDeltaEntry = 0;
+ mCurrentEntrySampleIndex = 0;
+ }
+
+ while (mCurrentDeltaEntry < mNumDeltaEntries) {
+ uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
+ if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
+ return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
+ }
+
+ mCurrentEntrySampleIndex += sampleCount;
+ ++mCurrentDeltaEntry;
+ }
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
SampleTable::SampleTable(const sp<DataSource> &source)
: mDataSource(source),
mChunkOffsetOffset(-1),
@@ -56,6 +121,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
mSampleTimeEntries(NULL),
mCompositionTimeDeltaEntries(NULL),
mNumCompositionTimeDeltaEntries(0),
+ mCompositionDeltaLookup(new CompositionDeltaLookup),
mSyncSampleOffset(-1),
mNumSyncSamples(0),
mSyncSamples(NULL),
@@ -71,6 +137,9 @@ SampleTable::~SampleTable() {
delete[] mSyncSamples;
mSyncSamples = NULL;
+ delete mCompositionDeltaLookup;
+ mCompositionDeltaLookup = NULL;
+
delete[] mCompositionTimeDeltaEntries;
mCompositionTimeDeltaEntries = NULL;
@@ -318,6 +387,9 @@ status_t SampleTable::setCompositionTimeToSampleParams(
mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
}
+ mCompositionDeltaLookup->setEntries(
+ mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
+
return OK;
}
@@ -430,8 +502,12 @@ void SampleTable::buildSampleEntriesTable() {
mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
+ uint32_t compTimeDelta =
+ mCompositionDeltaLookup->getCompositionTimeOffset(
+ sampleIndex);
+
mSampleTimeEntries[sampleIndex].mCompositionTime =
- sampleTime + getCompositionTimeOffset(sampleIndex);
+ sampleTime + compTimeDelta;
}
++sampleIndex;
@@ -739,25 +815,8 @@ status_t SampleTable::getMetaDataForSample(
return OK;
}
-uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) const {
- if (mCompositionTimeDeltaEntries == NULL) {
- return 0;
- }
-
- uint32_t curSample = 0;
- for (size_t i = 0; i < mNumCompositionTimeDeltaEntries; ++i) {
- uint32_t sampleCount = mCompositionTimeDeltaEntries[2 * i];
-
- if (sampleIndex < curSample + sampleCount) {
- uint32_t sampleDelta = mCompositionTimeDeltaEntries[2 * i + 1];
-
- return sampleDelta;
- }
-
- curSample += sampleCount;
- }
-
- return 0;
+uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
+ return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}
} // namespace android
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 8a42e8b..07aa140 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -329,6 +329,28 @@ bool IsIDR(const sp<ABuffer> &buffer) {
return foundIDR;
}
+bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
+ const uint8_t *data = accessUnit->data();
+ size_t size = accessUnit->size();
+
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+ CHECK_GT(nalSize, 0u);
+
+ unsigned nalType = nalStart[0] & 0x1f;
+
+ if (nalType == 5) {
+ return true;
+ } else if (nalType == 1) {
+ unsigned nal_ref_idc = (nalStart[0] >> 5) & 3;
+ return nal_ref_idc != 0;
+ }
+ }
+
+ return true;
+}
+
sp<MetaData> MakeAACCodecSpecificData(
unsigned profile, unsigned sampling_freq_index,
unsigned channel_configuration) {
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index de936c4..f15014e 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -74,10 +74,32 @@ bool logMessageHandler(
return false;
}
+struct AutoPrioritySaver {
+ AutoPrioritySaver()
+ : mTID(androidGetTid()),
+ mPrevPriority(androidGetThreadPriority(mTID)) {
+ androidSetThreadPriority(mTID, ANDROID_PRIORITY_NORMAL);
+ }
+
+ ~AutoPrioritySaver() {
+ androidSetThreadPriority(mTID, mPrevPriority);
+ }
+
+private:
+ pid_t mTID;
+ int mPrevPriority;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutoPrioritySaver);
+};
static void InitializeNetworkThreadIfNecessary() {
Mutex::Autolock autoLock(gNetworkThreadLock);
+
if (gNetworkThread == NULL) {
+ // Make sure any threads spawned by the chromium framework are
+ // running at normal priority instead of inheriting this thread's.
+ AutoPrioritySaver saver;
+
gNetworkThread = new base::Thread("network");
base::Thread::Options options;
options.message_loop_type = MessageLoop::TYPE_IO;
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 582bdba..f039bc1 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -385,6 +385,15 @@ AString AMessage::debugString(int32_t indent) const {
item.u.refValue)->debugString(
indent + strlen(item.mName) + 14).c_str());
break;
+ case kTypeRect:
+ tmp = StringPrintf(
+ "Rect %s(%d, %d, %d, %d)",
+ item.mName,
+ item.u.rectValue.mLeft,
+ item.u.rectValue.mTop,
+ item.u.rectValue.mRight,
+ item.u.rectValue.mBottom);
+ break;
default:
TRESPASS();
}
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index a6a6524..847dff7 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -86,6 +86,8 @@ protected:
~SampleTable();
private:
+ struct CompositionDeltaLookup;
+
static const uint32_t kChunkOffsetType32;
static const uint32_t kChunkOffsetType64;
static const uint32_t kSampleSizeType32;
@@ -117,6 +119,7 @@ private:
uint32_t *mCompositionTimeDeltaEntries;
size_t mNumCompositionTimeDeltaEntries;
+ CompositionDeltaLookup *mCompositionDeltaLookup;
off64_t mSyncSampleOffset;
uint32_t mNumSyncSamples;
@@ -135,8 +138,7 @@ private:
friend struct SampleIterator;
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
-
- uint32_t getCompositionTimeOffset(uint32_t sampleIndex) const;
+ uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
static int CompareIncreasingTime(const void *, const void *);
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index 15cd4d4..e418822 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -50,6 +50,7 @@ struct MetaData;
sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
bool IsIDR(const sp<ABuffer> &accessUnit);
+bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit);
const char *AVCProfileToString(uint8_t profile);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index bc24dbb..33d3f30 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -85,7 +85,7 @@ OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
: mOwner(owner),
mDone(false) {
mThread = new CallbackDispatcherThread(this);
- mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_AUDIO);
+ mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
}
OMX::CallbackDispatcher::~CallbackDispatcher() {
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index f7330f3..b705d00 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -42,7 +42,7 @@ SimpleSoftOMXComponent::SimpleSoftOMXComponent(
mLooper->start(
false, // runOnCallingThread
false, // canCallJava
- PRIORITY_AUDIO);
+ ANDROID_PRIORITY_FOREGROUND);
}
void SimpleSoftOMXComponent::prepareForDestruction() {