Merge "Allow application to set two more encoding paramters: video profile and level" into gingerbread

This commit is contained in:
James Dong
2010-07-07 14:56:33 -07:00
committed by Android (Google) Code Review
5 changed files with 143 additions and 15 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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(&param);
param.nPortIndex = kPortIndexOutput;
for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
status_t err = mOMX->getParameter(
mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
&param, 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;
}
// 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.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;
}
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.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
err = mOMX->setParameter(