diff options
author | James Dong <jdong@google.com> | 2010-07-01 15:02:14 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2010-07-07 12:11:53 -0700 |
commit | 145bfe5eb3e08c9689c28f6bf3287a979438b04b (patch) | |
tree | ba140d50bbed7d0f8cb76fb3bd7920ecc5c4a6ce | |
parent | 91952e5221d2151e10738d7228575c4afe444f5e (diff) | |
download | frameworks_av-145bfe5eb3e08c9689c28f6bf3287a979438b04b.zip frameworks_av-145bfe5eb3e08c9689c28f6bf3287a979438b04b.tar.gz frameworks_av-145bfe5eb3e08c9689c28f6bf3287a979438b04b.tar.bz2 |
Allow application to set two more encoding paramters: video profile and level
Change-Id: I673e681cefe184d5c556c612c54600a24a2143e5
-rw-r--r-- | include/media/stagefright/MetaData.h | 4 | ||||
-rw-r--r-- | include/media/stagefright/OMXCodec.h | 7 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 38 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 4 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 105 |
5 files changed, 143 insertions, 15 deletions
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 95fe6f6..73f5547 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -69,6 +69,10 @@ enum { kKeyDate = 'date', // cstring kKeyWriter = 'writ', // cstring + // video profile and level + kKeyVideoProfile = 'vprf', // int32_t + kKeyVideoLevel = 'vlev', // int32_t + // Set this key to enable authoring files in 64-bit offset kKey64BitFileOffset = 'fobt', // int32_t (bool) diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 99ec8e6..214f43a 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -27,6 +27,7 @@ namespace android { class MemoryDealer; struct OMXCodecObserver; +struct CodecProfileLevel; struct OMXCodec : public MediaSource, public MediaBufferObserver { @@ -178,6 +179,12 @@ private: status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta); status_t setupAVCEncoderParameters(const sp<MetaData>& meta); + // If profile/level is set in the meta data, its value in the meta + // data will be used; otherwise, the default value will be used. + status_t getVideoProfileLevel(const sp<MetaData>& meta, + const CodecProfileLevel& defaultProfileLevel, + CodecProfileLevel& profileLevel); + status_t setVideoOutputFormat( const char *mime, OMX_U32 width, OMX_U32 height); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 91c5b92..50f74f2 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -426,6 +426,24 @@ status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { return OK; } +status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) { + LOGV("setParamVideoEncoderProfile: %d", profile); + + // Additional check will be done later when we load the encoder. + // For now, we are accepting values defined in OpenMAX IL. + mVideoEncoderProfile = profile; + return OK; +} + +status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) { + LOGV("setParamVideoEncoderLevel: %d", level); + + // Additional check will be done later when we load the encoder. + // For now, we are accepting values defined in OpenMAX IL. + mVideoEncoderLevel = level; + return OK; +} + status_t StagefrightRecorder::setParameter( const String8 &key, const String8 &value) { LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); @@ -484,6 +502,16 @@ status_t StagefrightRecorder::setParameter( if (safe_strtoi32(value.string(), &interval)) { return setParamVideoIFramesInterval(interval); } + } else if (key == "video-param-encoder-profile") { + int32_t profile; + if (safe_strtoi32(value.string(), &profile)) { + return setParamVideoEncoderProfile(profile); + } + } else if (key == "video-param-encoder-level") { + int32_t level; + if (safe_strtoi32(value.string(), &level)) { + return setParamVideoEncoderLevel(level); + } } else if (key == "video-param-camera-id") { int32_t cameraId; if (safe_strtoi32(value.string(), &cameraId)) { @@ -851,6 +879,12 @@ status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) { enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval); enc_meta->setInt32(kKeyStride, stride); enc_meta->setInt32(kKeySliceHeight, sliceHeight); + if (mVideoEncoderProfile != -1) { + enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile); + } + if (mVideoEncoderLevel != -1) { + enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel); + } OMXClient client; CHECK_EQ(client.connect(), OK); @@ -992,6 +1026,10 @@ status_t StagefrightRecorder::reset() { mAudioSourceNode = 0; mUse64BitFileOffset = false; mCameraId = 0; + mVideoEncoderProfile = -1; + mVideoEncoderLevel = -1; + mMaxFileDurationUs = 0; + mMaxFileSizeBytes = 0; mTrackEveryNumberOfFrames = 0; mTrackEveryTimeDurationUs = 0; mEncoderProfiles = MediaProfiles::getInstance(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index cb05571..85d2557 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -82,6 +82,8 @@ private: int32_t mInterleaveDurationUs; int32_t mIFramesInterval; int32_t mCameraId; + int32_t mVideoEncoderProfile; + int32_t mVideoEncoderLevel; int64_t mMaxFileSizeBytes; int64_t mMaxFileDurationUs; int32_t mTrackEveryNumberOfFrames; @@ -108,6 +110,8 @@ private: status_t setParamAudioSamplingRate(int32_t sampleRate); status_t setParamVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoIFramesInterval(int32_t interval); + status_t setParamVideoEncoderProfile(int32_t profile); + status_t setParamVideoEncoderLevel(int32_t level); status_t setParamVideoCameraId(int32_t cameraId); status_t setParamTrackTimeStatus(int64_t timeDurationUs); status_t setParamTrackFrameStatus(int32_t nFrames); diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index dacb8d3..83f7040 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -831,7 +831,7 @@ void OMXCodec::setVideoInputFormat( video_def->nFrameWidth = width; video_def->nFrameHeight = height; - video_def->xFramerate = (frameRate << 16); // Q16 format + video_def->xFramerate = 0; // No need for output port video_def->nBitrate = bitRate; // Q16 format video_def->eCompressionFormat = compressionFormat; video_def->eColorFormat = OMX_COLOR_FormatUnused; @@ -918,6 +918,52 @@ status_t OMXCodec::setupBitRate(int32_t bitRate) { return OK; } +status_t OMXCodec::getVideoProfileLevel( + const sp<MetaData>& meta, + const CodecProfileLevel& defaultProfileLevel, + CodecProfileLevel &profileLevel) { + CODEC_LOGV("Default profile: %ld, level %ld", + defaultProfileLevel.mProfile, defaultProfileLevel.mLevel); + + // Are the default profile and level overwriten? + int32_t profile, level; + if (!meta->findInt32(kKeyVideoProfile, &profile)) { + profile = defaultProfileLevel.mProfile; + } + if (!meta->findInt32(kKeyVideoLevel, &level)) { + level = defaultProfileLevel.mLevel; + } + CODEC_LOGV("Target profile: %d, level: %d", profile, level); + + // Are the target profile and level supported by the encoder? + OMX_VIDEO_PARAM_PROFILELEVELTYPE param; + InitOMXParams(¶m); + param.nPortIndex = kPortIndexOutput; + for (param.nProfileIndex = 0;; ++param.nProfileIndex) { + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoProfileLevelQuerySupported, + ¶m, sizeof(param)); + + if (err != OK) return err; + + int32_t supportedProfile = static_cast<int32_t>(param.eProfile); + int32_t supportedLevel = static_cast<int32_t>(param.eLevel); + CODEC_LOGV("Supported profile: %ld, level %ld", + supportedProfile, supportedLevel); + + if (profile == supportedProfile && + level == supportedLevel) { + profileLevel.mProfile = profile; + profileLevel.mLevel = level; + return OK; + } + } + + CODEC_LOGE("Target profile (%d) and level (%d) is not supported", + profile, level); + return BAD_VALUE; +} + status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { int32_t iFramesInterval, frameRate, bitRate; bool success = meta->findInt32(kKeyBitRate, &bitRate); @@ -941,8 +987,14 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { } h263type.nBFrames = 0; - h263type.eProfile = OMX_VIDEO_H263ProfileBaseline; - h263type.eLevel = OMX_VIDEO_H263Level45; + // Check profile and level parameters + CodecProfileLevel defaultProfileLevel, profileLevel; + defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline; + defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45; + err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); + if (err != OK) return err; + h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile); + h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel); h263type.bPLUSPTYPEAllowed = OMX_FALSE; h263type.bForceRoundingTypeToZero = OMX_FALSE; @@ -992,8 +1044,14 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { mpeg4type.nHeaderExtension = 0; mpeg4type.bReversibleVLC = OMX_FALSE; - mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileSimple; - mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2; + // Check profile and level parameters + CodecProfileLevel defaultProfileLevel, profileLevel; + defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple; + defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2; + err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); + if (err != OK) return err; + mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile); + mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel); err = mOMX->setParameter( mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); @@ -1029,22 +1087,39 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { if (h264type.nPFrames == 0) { h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; } - h264type.bUseHadamard = OMX_TRUE; - h264type.nRefFrames = 1; - h264type.nRefIdx10ActiveMinus1 = 0; - h264type.nRefIdx11ActiveMinus1 = 0; + + // Check profile and level parameters + CodecProfileLevel defaultProfileLevel, profileLevel; + defaultProfileLevel.mProfile = h264type.eProfile; + defaultProfileLevel.mLevel = h264type.eLevel; + err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); + if (err != OK) return err; + h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile); + h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel); + + if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { + h264type.bUseHadamard = OMX_TRUE; + h264type.nRefFrames = 1; + h264type.nRefIdx10ActiveMinus1 = 0; + h264type.nRefIdx11ActiveMinus1 = 0; + h264type.bEntropyCodingCABAC = OMX_FALSE; + h264type.bWeightedPPrediction = OMX_FALSE; + h264type.bconstIpred = OMX_FALSE; + h264type.bDirect8x8Inference = OMX_FALSE; + h264type.bDirectSpatialTemporal = OMX_FALSE; + h264type.nCabacInitIdc = 0; + } + + if (h264type.nBFrames != 0) { + h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; + } + h264type.bEnableUEP = OMX_FALSE; h264type.bEnableFMO = OMX_FALSE; h264type.bEnableASO = OMX_FALSE; h264type.bEnableRS = OMX_FALSE; h264type.bFrameMBsOnly = OMX_TRUE; h264type.bMBAFF = OMX_FALSE; - h264type.bEntropyCodingCABAC = OMX_FALSE; - h264type.bWeightedPPrediction = OMX_FALSE; - h264type.bconstIpred = OMX_FALSE; - h264type.bDirect8x8Inference = OMX_FALSE; - h264type.bDirectSpatialTemporal = OMX_FALSE; - h264type.nCabacInitIdc = 0; h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; err = mOMX->setParameter( |