Merge "Allow application to set two more encoding paramters: video profile and level" into gingerbread
This commit is contained in:
@ -69,6 +69,10 @@ enum {
|
|||||||
kKeyDate = 'date', // cstring
|
kKeyDate = 'date', // cstring
|
||||||
kKeyWriter = 'writ', // 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
|
// Set this key to enable authoring files in 64-bit offset
|
||||||
kKey64BitFileOffset = 'fobt', // int32_t (bool)
|
kKey64BitFileOffset = 'fobt', // int32_t (bool)
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ namespace android {
|
|||||||
|
|
||||||
class MemoryDealer;
|
class MemoryDealer;
|
||||||
struct OMXCodecObserver;
|
struct OMXCodecObserver;
|
||||||
|
struct CodecProfileLevel;
|
||||||
|
|
||||||
struct OMXCodec : public MediaSource,
|
struct OMXCodec : public MediaSource,
|
||||||
public MediaBufferObserver {
|
public MediaBufferObserver {
|
||||||
@ -178,6 +179,12 @@ private:
|
|||||||
status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta);
|
status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta);
|
||||||
status_t setupAVCEncoderParameters(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(
|
status_t setVideoOutputFormat(
|
||||||
const char *mime, OMX_U32 width, OMX_U32 height);
|
const char *mime, OMX_U32 width, OMX_U32 height);
|
||||||
|
|
||||||
|
@ -426,6 +426,24 @@ status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
|
|||||||
return OK;
|
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(
|
status_t StagefrightRecorder::setParameter(
|
||||||
const String8 &key, const String8 &value) {
|
const String8 &key, const String8 &value) {
|
||||||
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
|
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
|
||||||
@ -484,6 +502,16 @@ status_t StagefrightRecorder::setParameter(
|
|||||||
if (safe_strtoi32(value.string(), &interval)) {
|
if (safe_strtoi32(value.string(), &interval)) {
|
||||||
return setParamVideoIFramesInterval(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") {
|
} else if (key == "video-param-camera-id") {
|
||||||
int32_t cameraId;
|
int32_t cameraId;
|
||||||
if (safe_strtoi32(value.string(), &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(kKeyIFramesInterval, mIFramesInterval);
|
||||||
enc_meta->setInt32(kKeyStride, stride);
|
enc_meta->setInt32(kKeyStride, stride);
|
||||||
enc_meta->setInt32(kKeySliceHeight, sliceHeight);
|
enc_meta->setInt32(kKeySliceHeight, sliceHeight);
|
||||||
|
if (mVideoEncoderProfile != -1) {
|
||||||
|
enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
|
||||||
|
}
|
||||||
|
if (mVideoEncoderLevel != -1) {
|
||||||
|
enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
|
||||||
|
}
|
||||||
|
|
||||||
OMXClient client;
|
OMXClient client;
|
||||||
CHECK_EQ(client.connect(), OK);
|
CHECK_EQ(client.connect(), OK);
|
||||||
@ -992,6 +1026,10 @@ status_t StagefrightRecorder::reset() {
|
|||||||
mAudioSourceNode = 0;
|
mAudioSourceNode = 0;
|
||||||
mUse64BitFileOffset = false;
|
mUse64BitFileOffset = false;
|
||||||
mCameraId = 0;
|
mCameraId = 0;
|
||||||
|
mVideoEncoderProfile = -1;
|
||||||
|
mVideoEncoderLevel = -1;
|
||||||
|
mMaxFileDurationUs = 0;
|
||||||
|
mMaxFileSizeBytes = 0;
|
||||||
mTrackEveryNumberOfFrames = 0;
|
mTrackEveryNumberOfFrames = 0;
|
||||||
mTrackEveryTimeDurationUs = 0;
|
mTrackEveryTimeDurationUs = 0;
|
||||||
mEncoderProfiles = MediaProfiles::getInstance();
|
mEncoderProfiles = MediaProfiles::getInstance();
|
||||||
|
@ -82,6 +82,8 @@ private:
|
|||||||
int32_t mInterleaveDurationUs;
|
int32_t mInterleaveDurationUs;
|
||||||
int32_t mIFramesInterval;
|
int32_t mIFramesInterval;
|
||||||
int32_t mCameraId;
|
int32_t mCameraId;
|
||||||
|
int32_t mVideoEncoderProfile;
|
||||||
|
int32_t mVideoEncoderLevel;
|
||||||
int64_t mMaxFileSizeBytes;
|
int64_t mMaxFileSizeBytes;
|
||||||
int64_t mMaxFileDurationUs;
|
int64_t mMaxFileDurationUs;
|
||||||
int32_t mTrackEveryNumberOfFrames;
|
int32_t mTrackEveryNumberOfFrames;
|
||||||
@ -108,6 +110,8 @@ private:
|
|||||||
status_t setParamAudioSamplingRate(int32_t sampleRate);
|
status_t setParamAudioSamplingRate(int32_t sampleRate);
|
||||||
status_t setParamVideoEncodingBitRate(int32_t bitRate);
|
status_t setParamVideoEncodingBitRate(int32_t bitRate);
|
||||||
status_t setParamVideoIFramesInterval(int32_t interval);
|
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 setParamVideoCameraId(int32_t cameraId);
|
||||||
status_t setParamTrackTimeStatus(int64_t timeDurationUs);
|
status_t setParamTrackTimeStatus(int64_t timeDurationUs);
|
||||||
status_t setParamTrackFrameStatus(int32_t nFrames);
|
status_t setParamTrackFrameStatus(int32_t nFrames);
|
||||||
|
@ -831,7 +831,7 @@ void OMXCodec::setVideoInputFormat(
|
|||||||
|
|
||||||
video_def->nFrameWidth = width;
|
video_def->nFrameWidth = width;
|
||||||
video_def->nFrameHeight = height;
|
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->nBitrate = bitRate; // Q16 format
|
||||||
video_def->eCompressionFormat = compressionFormat;
|
video_def->eCompressionFormat = compressionFormat;
|
||||||
video_def->eColorFormat = OMX_COLOR_FormatUnused;
|
video_def->eColorFormat = OMX_COLOR_FormatUnused;
|
||||||
@ -918,6 +918,52 @@ status_t OMXCodec::setupBitRate(int32_t bitRate) {
|
|||||||
return OK;
|
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) {
|
status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
|
||||||
int32_t iFramesInterval, frameRate, bitRate;
|
int32_t iFramesInterval, frameRate, bitRate;
|
||||||
bool success = meta->findInt32(kKeyBitRate, &bitRate);
|
bool success = meta->findInt32(kKeyBitRate, &bitRate);
|
||||||
@ -941,8 +987,14 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
|
|||||||
}
|
}
|
||||||
h263type.nBFrames = 0;
|
h263type.nBFrames = 0;
|
||||||
|
|
||||||
h263type.eProfile = OMX_VIDEO_H263ProfileBaseline;
|
// Check profile and level parameters
|
||||||
h263type.eLevel = OMX_VIDEO_H263Level45;
|
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.bPLUSPTYPEAllowed = OMX_FALSE;
|
||||||
h263type.bForceRoundingTypeToZero = OMX_FALSE;
|
h263type.bForceRoundingTypeToZero = OMX_FALSE;
|
||||||
@ -992,8 +1044,14 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
|
|||||||
mpeg4type.nHeaderExtension = 0;
|
mpeg4type.nHeaderExtension = 0;
|
||||||
mpeg4type.bReversibleVLC = OMX_FALSE;
|
mpeg4type.bReversibleVLC = OMX_FALSE;
|
||||||
|
|
||||||
mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
|
// Check profile and level parameters
|
||||||
mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;
|
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(
|
err = mOMX->setParameter(
|
||||||
mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
|
mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
|
||||||
@ -1029,22 +1087,39 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
|
|||||||
if (h264type.nPFrames == 0) {
|
if (h264type.nPFrames == 0) {
|
||||||
h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
|
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.bUseHadamard = OMX_TRUE;
|
||||||
h264type.nRefFrames = 1;
|
h264type.nRefFrames = 1;
|
||||||
h264type.nRefIdx10ActiveMinus1 = 0;
|
h264type.nRefIdx10ActiveMinus1 = 0;
|
||||||
h264type.nRefIdx11ActiveMinus1 = 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.bEntropyCodingCABAC = OMX_FALSE;
|
||||||
h264type.bWeightedPPrediction = OMX_FALSE;
|
h264type.bWeightedPPrediction = OMX_FALSE;
|
||||||
h264type.bconstIpred = OMX_FALSE;
|
h264type.bconstIpred = OMX_FALSE;
|
||||||
h264type.bDirect8x8Inference = OMX_FALSE;
|
h264type.bDirect8x8Inference = OMX_FALSE;
|
||||||
h264type.bDirectSpatialTemporal = OMX_FALSE;
|
h264type.bDirectSpatialTemporal = OMX_FALSE;
|
||||||
h264type.nCabacInitIdc = 0;
|
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;
|
h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
|
||||||
|
|
||||||
err = mOMX->setParameter(
|
err = mOMX->setParameter(
|
||||||
|
Reference in New Issue
Block a user