From 8ee516a515c70a492c395b67ce12e19e7d159804 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 8 May 2012 11:21:26 -0700 Subject: Submit codec specific data automatically if it is contained in the format passed to MediaCodec::configure. Change-Id: I8ef6755e8389ec47b44a9c70904ea6c03a00f4f2 related-to-bug: 6364139 --- cmds/stagefright/codec.cpp | 35 ----------------- include/media/stagefright/MediaCodec.h | 5 +++ media/libstagefright/MediaCodec.cpp | 72 ++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 35 deletions(-) diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp index 5a43829..f3370a5 100644 --- a/cmds/stagefright/codec.cpp +++ b/cmds/stagefright/codec.cpp @@ -50,8 +50,6 @@ namespace android { struct CodecState { sp mCodec; - Vector > mCSD; - size_t mCSDIndex; Vector > mInBuffers; Vector > mOutBuffers; bool mSignalledInputEOS; @@ -126,19 +124,8 @@ static int decode( CHECK_EQ(err, (status_t)OK); - size_t j = 0; - sp buffer; - while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { - state->mCSD.push_back(buffer); - - ++j; - } - - state->mCSDIndex = 0; state->mSignalledInputEOS = false; state->mSawOutputEOS = false; - - ALOGV("got %d pieces of codec specific data.", state->mCSD.size()); } CHECK(!stateByTrack.isEmpty()); @@ -157,28 +144,6 @@ static int decode( ALOGV("got %d input and %d output buffers", state->mInBuffers.size(), state->mOutBuffers.size()); - - while (state->mCSDIndex < state->mCSD.size()) { - size_t index; - status_t err = codec->dequeueInputBuffer(&index, -1ll); - CHECK_EQ(err, (status_t)OK); - - const sp &srcBuffer = - state->mCSD.itemAt(state->mCSDIndex++); - - const sp &buffer = state->mInBuffers.itemAt(index); - - memcpy(buffer->data(), srcBuffer->data(), srcBuffer->size()); - - err = codec->queueInputBuffer( - index, - 0 /* offset */, - srcBuffer->size(), - 0ll /* timeUs */, - MediaCodec::BUFFER_FLAG_CODECCONFIG); - - CHECK_EQ(err, (status_t)OK); - } } bool sawInputEOS = false; diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index d09049e..d96007b 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -186,6 +186,8 @@ private: sp mCrypto; + List > mCSD; + MediaCodec(const sp &looper); static status_t PostAndAwaitResponse( @@ -205,6 +207,9 @@ private: bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false); void cancelPendingDequeueOperations(); + void extractCSD(const sp &format); + status_t queueCSDInputBuffer(size_t bufferIndex); + DISALLOW_EVIL_CONSTRUCTORS(MediaCodec); }; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 2df0dd2..e032cfc 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -646,6 +646,28 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } + if (!mCSD.empty()) { + ssize_t index = dequeuePortBuffer(kPortIndexInput); + CHECK_GE(index, 0); + + // If codec specific data had been specified as + // part of the format in the call to configure and + // if there's more csd left, we submit it here + // clients only get access to input buffers once + // this data has been exhausted. + + status_t err = queueCSDInputBuffer(index); + + if (err != OK) { + ALOGE("queueCSDInputBuffer failed w/ error %d", + err); + + mFlags |= kFlagStickyError; + cancelPendingDequeueOperations(); + } + break; + } + if (mFlags & kFlagDequeueInputPending) { CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); @@ -811,6 +833,8 @@ void MediaCodec::onMessageReceived(const sp &msg) { format->setInt32("encoder", true); } + extractCSD(format); + mCodec->initiateConfigureComponent(format); break; } @@ -1107,6 +1131,54 @@ void MediaCodec::onMessageReceived(const sp &msg) { } } +void MediaCodec::extractCSD(const sp &format) { + mCSD.clear(); + + size_t i = 0; + for (;;) { + sp csd; + if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) { + break; + } + + mCSD.push_back(csd); + ++i; + } + + ALOGV("Found %u pieces of codec specific data.", mCSD.size()); +} + +status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { + CHECK(!mCSD.empty()); + + BufferInfo *info = + &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex); + + sp csd = *mCSD.begin(); + mCSD.erase(mCSD.begin()); + + const sp &codecInputData = + (mCrypto != NULL) ? info->mEncryptedData : info->mData; + + if (csd->size() > codecInputData->capacity()) { + return -EINVAL; + } + + memcpy(codecInputData->data(), csd->data(), csd->size()); + + AString errorDetailMsg; + + sp msg = new AMessage(kWhatQueueInputBuffer, id()); + msg->setSize("index", bufferIndex); + msg->setSize("offset", 0); + msg->setSize("size", csd->size()); + msg->setInt64("timeUs", 0ll); + msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); + msg->setPointer("errorDetailMsg", &errorDetailMsg); + + return onQueueInputBuffer(msg); +} + void MediaCodec::setState(State newState) { if (newState == INITIALIZED) { delete mSoftRenderer; -- cgit v1.1