diff options
Diffstat (limited to 'media')
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() { |