Loading include/media/stagefright/MediaCodec.h +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,8 @@ private: kFlagDequeueOutputPending = 32, kFlagIsSecure = 64, kFlagSawMediaServerDie = 128, kFlagIsEncoder = 256, kFlagGatherCodecSpecificData = 512, }; struct BufferInfo { Loading Loading @@ -244,6 +246,8 @@ private: status_t onSetParameters(const sp<AMessage> ¶ms); status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer); DISALLOW_EVIL_CONSTRUCTORS(MediaCodec); }; Loading media/libstagefright/ACodec.cpp +185 −83 Original line number Diff line number Diff line Loading @@ -1470,25 +1470,48 @@ status_t ACodec::setSupportedOutputFormat() { &format, sizeof(format)); } static const struct VideoCodingMapEntry { const char *mMime; OMX_VIDEO_CODINGTYPE mVideoCodingType; } kVideoCodingMapEntry[] = { { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, { MEDIA_MIMETYPE_VIDEO_VPX, OMX_VIDEO_CodingVPX }, }; static status_t GetVideoCodingTypeFromMime( const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { *codingType = OMX_VIDEO_CodingAVC; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { *codingType = OMX_VIDEO_CodingMPEG4; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { *codingType = OMX_VIDEO_CodingH263; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { *codingType = OMX_VIDEO_CodingMPEG2; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { *codingType = OMX_VIDEO_CodingVPX; } else { for (size_t i = 0; i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); ++i) { if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { *codingType = kVideoCodingMapEntry[i].mVideoCodingType; return OK; } } *codingType = OMX_VIDEO_CodingUnused; return ERROR_UNSUPPORTED; } static status_t GetMimeTypeForVideoCoding( OMX_VIDEO_CODINGTYPE codingType, AString *mime) { for (size_t i = 0; i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); ++i) { if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { *mime = kVideoCodingMapEntry[i].mMime; return OK; } } mime->clear(); return ERROR_UNSUPPORTED; } status_t ACodec::setupVideoDecoder( const char *mime, int32_t width, int32_t height) { Loading Loading @@ -2227,9 +2250,20 @@ void ACodec::sendFormatChange() { { OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; AString mime; if (!mIsEncoder) { notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); } else if (GetMimeTypeForVideoCoding( videoDef->eCompressionFormat, &mime) != OK) { notify->setString("mime", "application/octet-stream"); } else { notify->setString("mime", mime.c_str()); } notify->setInt32("width", videoDef->nFrameWidth); notify->setInt32("height", videoDef->nFrameHeight); if (!mIsEncoder) { notify->setInt32("stride", videoDef->nStride); notify->setInt32("slice-height", videoDef->nSliceHeight); notify->setInt32("color-format", videoDef->eColorFormat); Loading Loading @@ -2271,14 +2305,17 @@ void ACodec::sendFormatChange() { CHECK_EQ(0, native_window_set_crop( mNativeWindow.get(), &crop)); } } break; } case OMX_PortDomainAudio: { OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); switch (audioDef->eEncoding) { case OMX_AUDIO_CodingPCM: { OMX_AUDIO_PARAM_PCMMODETYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; Loading Loading @@ -2311,7 +2348,72 @@ void ACodec::sendFormatChange() { if (mChannelMaskPresent) { notify->setInt32("channel-mask", mChannelMask); } break; } case OMX_AUDIO_CodingAAC: { OMX_AUDIO_PARAM_AACPROFILETYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)), (status_t)OK); notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); notify->setInt32("channel-count", params.nChannels); notify->setInt32("sample-rate", params.nSampleRate); break; } case OMX_AUDIO_CodingAMR: { OMX_AUDIO_PARAM_AMRTYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)), (status_t)OK); notify->setInt32("channel-count", 1); if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { notify->setString( "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); notify->setInt32("sample-rate", 16000); } else { notify->setString( "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); notify->setInt32("sample-rate", 8000); } break; } case OMX_AUDIO_CodingFLAC: { OMX_AUDIO_PARAM_FLACTYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)), (status_t)OK); notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); notify->setInt32("channel-count", params.nChannels); notify->setInt32("sample-rate", params.nSampleRate); break; } default: TRESPASS(); } break; } Loading Loading @@ -2957,7 +3059,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( break; } if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { if (!mCodec->mSentFormat) { mCodec->sendFormatChange(); } Loading media/libstagefright/MediaCodec.cpp +76 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -741,8 +744,16 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } mOutputFormat = msg; 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; } Loading Loading @@ -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)); Loading Loading @@ -955,6 +985,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { if (flags & CONFIGURE_FLAG_ENCODE) { format->setInt32("encoder", true); mFlags |= kFlagIsEncoder; } extractCSD(format); Loading Loading @@ -1413,6 +1444,8 @@ void MediaCodec::setState(State newState) { mFlags &= ~kFlagOutputFormatChanged; mFlags &= ~kFlagOutputBuffersChanged; mFlags &= ~kFlagStickyError; mFlags &= ~kFlagIsEncoder; mFlags &= ~kFlagGatherCodecSpecificData; mActivityNotify.clear(); } Loading Loading @@ -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 Loading
include/media/stagefright/MediaCodec.h +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,8 @@ private: kFlagDequeueOutputPending = 32, kFlagIsSecure = 64, kFlagSawMediaServerDie = 128, kFlagIsEncoder = 256, kFlagGatherCodecSpecificData = 512, }; struct BufferInfo { Loading Loading @@ -244,6 +246,8 @@ private: status_t onSetParameters(const sp<AMessage> ¶ms); status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer); DISALLOW_EVIL_CONSTRUCTORS(MediaCodec); }; Loading
media/libstagefright/ACodec.cpp +185 −83 Original line number Diff line number Diff line Loading @@ -1470,25 +1470,48 @@ status_t ACodec::setSupportedOutputFormat() { &format, sizeof(format)); } static const struct VideoCodingMapEntry { const char *mMime; OMX_VIDEO_CODINGTYPE mVideoCodingType; } kVideoCodingMapEntry[] = { { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, { MEDIA_MIMETYPE_VIDEO_VPX, OMX_VIDEO_CodingVPX }, }; static status_t GetVideoCodingTypeFromMime( const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { *codingType = OMX_VIDEO_CodingAVC; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { *codingType = OMX_VIDEO_CodingMPEG4; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { *codingType = OMX_VIDEO_CodingH263; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { *codingType = OMX_VIDEO_CodingMPEG2; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { *codingType = OMX_VIDEO_CodingVPX; } else { for (size_t i = 0; i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); ++i) { if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { *codingType = kVideoCodingMapEntry[i].mVideoCodingType; return OK; } } *codingType = OMX_VIDEO_CodingUnused; return ERROR_UNSUPPORTED; } static status_t GetMimeTypeForVideoCoding( OMX_VIDEO_CODINGTYPE codingType, AString *mime) { for (size_t i = 0; i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); ++i) { if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { *mime = kVideoCodingMapEntry[i].mMime; return OK; } } mime->clear(); return ERROR_UNSUPPORTED; } status_t ACodec::setupVideoDecoder( const char *mime, int32_t width, int32_t height) { Loading Loading @@ -2227,9 +2250,20 @@ void ACodec::sendFormatChange() { { OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; AString mime; if (!mIsEncoder) { notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); } else if (GetMimeTypeForVideoCoding( videoDef->eCompressionFormat, &mime) != OK) { notify->setString("mime", "application/octet-stream"); } else { notify->setString("mime", mime.c_str()); } notify->setInt32("width", videoDef->nFrameWidth); notify->setInt32("height", videoDef->nFrameHeight); if (!mIsEncoder) { notify->setInt32("stride", videoDef->nStride); notify->setInt32("slice-height", videoDef->nSliceHeight); notify->setInt32("color-format", videoDef->eColorFormat); Loading Loading @@ -2271,14 +2305,17 @@ void ACodec::sendFormatChange() { CHECK_EQ(0, native_window_set_crop( mNativeWindow.get(), &crop)); } } break; } case OMX_PortDomainAudio: { OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); switch (audioDef->eEncoding) { case OMX_AUDIO_CodingPCM: { OMX_AUDIO_PARAM_PCMMODETYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; Loading Loading @@ -2311,7 +2348,72 @@ void ACodec::sendFormatChange() { if (mChannelMaskPresent) { notify->setInt32("channel-mask", mChannelMask); } break; } case OMX_AUDIO_CodingAAC: { OMX_AUDIO_PARAM_AACPROFILETYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)), (status_t)OK); notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); notify->setInt32("channel-count", params.nChannels); notify->setInt32("sample-rate", params.nSampleRate); break; } case OMX_AUDIO_CodingAMR: { OMX_AUDIO_PARAM_AMRTYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)), (status_t)OK); notify->setInt32("channel-count", 1); if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { notify->setString( "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); notify->setInt32("sample-rate", 16000); } else { notify->setString( "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); notify->setInt32("sample-rate", 8000); } break; } case OMX_AUDIO_CodingFLAC: { OMX_AUDIO_PARAM_FLACTYPE params; InitOMXParams(¶ms); params.nPortIndex = kPortIndexOutput; CHECK_EQ(mOMX->getParameter( mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)), (status_t)OK); notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); notify->setInt32("channel-count", params.nChannels); notify->setInt32("sample-rate", params.nSampleRate); break; } default: TRESPASS(); } break; } Loading Loading @@ -2957,7 +3059,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( break; } if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { if (!mCodec->mSentFormat) { mCodec->sendFormatChange(); } Loading
media/libstagefright/MediaCodec.cpp +76 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -741,8 +744,16 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } mOutputFormat = msg; 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; } Loading Loading @@ -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)); Loading Loading @@ -955,6 +985,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { if (flags & CONFIGURE_FLAG_ENCODE) { format->setInt32("encoder", true); mFlags |= kFlagIsEncoder; } extractCSD(format); Loading Loading @@ -1413,6 +1444,8 @@ void MediaCodec::setState(State newState) { mFlags &= ~kFlagOutputFormatChanged; mFlags &= ~kFlagOutputBuffersChanged; mFlags &= ~kFlagStickyError; mFlags &= ~kFlagIsEncoder; mFlags &= ~kFlagGatherCodecSpecificData; mActivityNotify.clear(); } Loading Loading @@ -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