diff options
author | Andreas Huber <andih@google.com> | 2013-04-30 16:08:47 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2013-04-30 16:11:50 -0700 |
commit | e96ee699aca0f711d41e6c0833e5de2341c4a36d (patch) | |
tree | 98644c0a023592c279075dc36ccae40fc8a9505d /media/libstagefright/MediaCodec.cpp | |
parent | b7e2ef14a93974935783e71829f4b3174001a0fb (diff) | |
download | frameworks_av-e96ee699aca0f711d41e6c0833e5de2341c4a36d.zip frameworks_av-e96ee699aca0f711d41e6c0833e5de2341c4a36d.tar.gz frameworks_av-e96ee699aca0f711d41e6c0833e5de2341c4a36d.tar.bz2 |
Support MediaCodec::getOutputFormat for encoders
codec specific data is provided as part of the MediaFormat if available.
Change-Id: I5a79c936e2411fe66ebc694791071faefc33941e
related-to-bug: 8616651
Diffstat (limited to 'media/libstagefright/MediaCodec.cpp')
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index ae7bb17..714da55 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -31,10 +31,13 @@ #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/ACodec.h> #include <media/stagefright/BufferProducerWrapper.h> +#include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/NativeWindowWrapper.h> +#include "include/avc_utils.h" + namespace android { // static @@ -741,8 +744,16 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } mOutputFormat = msg; - mFlags |= kFlagOutputFormatChanged; - postActivityNotificationIfPossible(); + + if (mFlags & kFlagIsEncoder) { + // Before we announce the format change we should + // collect codec specific data and amend the output + // format as necessary. + mFlags |= kFlagGatherCodecSpecificData; + } else { + mFlags |= kFlagOutputFormatChanged; + postActivityNotificationIfPossible(); + } break; } @@ -812,6 +823,25 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { buffer->meta()->setInt32("omxFlags", omxFlags); + if (mFlags & kFlagGatherCodecSpecificData) { + // This is the very first output buffer after a + // format change was signalled, it'll either contain + // the one piece of codec specific data we can expect + // or there won't be codec specific data. + if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { + status_t err = + amendOutputFormatWithCodecSpecificData(buffer); + + if (err != OK) { + ALOGE("Codec spit out malformed codec " + "specific data!"); + } + } + + mFlags &= ~kFlagGatherCodecSpecificData; + mFlags |= kFlagOutputFormatChanged; + } + if (mFlags & kFlagDequeueOutputPending) { CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); @@ -955,6 +985,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { if (flags & CONFIGURE_FLAG_ENCODE) { format->setInt32("encoder", true); + mFlags |= kFlagIsEncoder; } extractCSD(format); @@ -1413,6 +1444,8 @@ void MediaCodec::setState(State newState) { mFlags &= ~kFlagOutputFormatChanged; mFlags &= ~kFlagOutputBuffersChanged; mFlags &= ~kFlagStickyError; + mFlags &= ~kFlagIsEncoder; + mFlags &= ~kFlagGatherCodecSpecificData; mActivityNotify.clear(); } @@ -1720,4 +1753,45 @@ status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { return OK; } +status_t MediaCodec::amendOutputFormatWithCodecSpecificData( + const sp<ABuffer> &buffer) { + AString mime; + CHECK(mOutputFormat->findString("mime", &mime)); + + if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { + // Codec specific data should be SPS and PPS in a single buffer, + // each prefixed by a startcode (0x00 0x00 0x00 0x01). + // We separate the two and put them into the output format + // under the keys "csd-0" and "csd-1". + + unsigned csdIndex = 0; + + const uint8_t *data = buffer->data(); + size_t size = buffer->size(); + + const uint8_t *nalStart; + size_t nalSize; + while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { + sp<ABuffer> csd = new ABuffer(nalSize + 4); + memcpy(csd->data(), "\x00\x00\x00\x01", 4); + memcpy(csd->data() + 4, nalStart, nalSize); + + mOutputFormat->setBuffer( + StringPrintf("csd-%u", csdIndex).c_str(), csd); + + ++csdIndex; + } + + if (csdIndex != 2) { + return ERROR_MALFORMED; + } + } else { + // For everything else we just stash the codec specific data into + // the output format as a single piece of csd under "csd-0". + mOutputFormat->setBuffer("csd-0", buffer); + } + + return OK; +} + } // namespace android |