summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MediaCodec.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2013-04-30 16:08:47 -0700
committerAndreas Huber <andih@google.com>2013-04-30 16:11:50 -0700
commite96ee699aca0f711d41e6c0833e5de2341c4a36d (patch)
tree98644c0a023592c279075dc36ccae40fc8a9505d /media/libstagefright/MediaCodec.cpp
parentb7e2ef14a93974935783e71829f4b3174001a0fb (diff)
downloadframeworks_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.cpp78
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> &params) {
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