本文章只从framework层介绍,omx层和kernel层涉及芯片厂商,代码不便写到这里!!!
sourcecode:http://androidxref.com/
1.[Profile&Level]
1.1 framework层
line4333:可以在此层强制修改profile&level进行验证
line4608与line4609之间加debug log:可以获取支持哪些profile&level
frameworks/av/media/libstagefright/ACodec.cpp
4282 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
...
4326 int32_t profile;
4327 if (msg->findInt32("profile", &profile)) {
4328 int32_t level;
4329 if (!msg->findInt32("level", &level)) {
4330 return INVALID_OPERATION;
4331 }
4332
4333 err = verifySupportForProfileAndLevel(profile, level);
4334
4335 if (err != OK) {
4336 ALOGE("%s does not support profile %x @ level %x",
4337 mComponentName.c_str(), profile, level);
4338 return err;
4339 }
4340
4341 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
4342 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
4343 } else {
4344 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
4345 #if 0 /* DON'T YET DEFAULT TO HIGHEST PROFILE */
4346 // Use largest supported profile for AVC recording if profile is not specified.
4347 for (OMX_VIDEO_AVCPROFILETYPE profile : {
4348 OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) {
4349 if (verifySupportForProfileAndLevel(profile, 0) == OK) {
4350 h264type.eProfile = profile;
4351 break;
4352 }
4353 }
4354 #endif
4355 }
4356
4357 ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]",
4358 asString(h264type.eProfile), asString(h264type.eLevel));
4359
4604 status_t ACodec::verifySupportForProfileAndLevel(
4605 int32_t profile, int32_t level) {
4606 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
4607 InitOMXParams(¶ms);
4608 params.nPortIndex = kPortIndexOutput;
>>>>begin to debug log
for (OMX_U32 idx = 0; idx <= kMaxIndicesToCheck; ++idx) {
params.nProfileIndex = idx;
status_t err = mOMX->getParameter(
mNode,
OMX_IndexParamVideoProfileLevelQuerySupported,
¶ms,
sizeof(params));
if (err != OK) {
return err;
}
int32_t supportedProfileTmp = static_cast<int32_t>(params.eProfile);
int32_t supportedLevelTmp = static_cast<int32_t>(params.eLevel);
ALOGD("[%d]supported Profile:%d,Level:%d",idx,supportedProfileTmp,supportedLevelTmp);
}
>>>>end to debug log
4609
4610 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
4611 params.nProfileIndex = index;
4612 status_t err = mOMX->getParameter(
4613 mNode,
4614 OMX_IndexParamVideoProfileLevelQuerySupported,
4615 ¶ms,
4616 sizeof(params));
4617
4618 if (err != OK) {
4619 return err;
4620 }
4621
4622 int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
4623 int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
4624
4625 if (profile == supportedProfile && level <= supportedLevel) {
4626 return OK;
4627 }
4628
4629 if (index == kMaxIndicesToCheck) {
4630 ALOGW("[%s] stopping checking profiles after %u: %x/%x",
4631 mComponentName.c_str(), index,
4632 params.eProfile, params.eLevel);
4633 }
4634 }
4635 return ERROR_UNSUPPORTED;
4636 }
1.2 omx 层
可以看到profile&level的组合
2.[I/B/P frame]
2.1 带有什么帧
默认I帧与P帧
(1)AVCProfileBaseline
line4364:h264type.nBFrames = 0 =>无B帧
line4366:if (h264type.nPFrames == 0)=>可有/可无P帧
(2) AVCProfileMain || AVCProfileHigh
line4382:h264type.nBFrames = 1 => B帧
/frameworks/av/media/libstagefright/ACodec.cpp
4282 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
...
4323 h264type.nAllowedPictureTypes =
4324 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
...
4360 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
4361 h264type.nSliceHeaderSpacing = 0;
4362 h264type.bUseHadamard = OMX_TRUE;
4363 h264type.nRefFrames = 1;
4364 h264type.nBFrames = 0;
4365 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4366 if (h264type.nPFrames == 0) {
4367 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4368 }
4369 h264type.nRefIdx10ActiveMinus1 = 0;
4370 h264type.nRefIdx11ActiveMinus1 = 0;
4371 h264type.bEntropyCodingCABAC = OMX_FALSE;
4372 h264type.bWeightedPPrediction = OMX_FALSE;
4373 h264type.bconstIpred = OMX_FALSE;
4374 h264type.bDirect8x8Inference = OMX_FALSE;
4375 h264type.bDirectSpatialTemporal = OMX_FALSE;
4376 h264type.nCabacInitIdc = 0;
4377 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4378 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
4379 h264type.nSliceHeaderSpacing = 0;
4380 h264type.bUseHadamard = OMX_TRUE;
4381 h264type.nRefFrames = 2;
4382 h264type.nBFrames = 1;
4383 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4384 h264type.nAllowedPictureTypes =
4385 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
4386 h264type.nRefIdx10ActiveMinus1 = 0;
4387 h264type.nRefIdx11ActiveMinus1 = 0;
4388 h264type.bEntropyCodingCABAC = OMX_TRUE;
4389 h264type.bWeightedPPrediction = OMX_TRUE;
4390 h264type.bconstIpred = OMX_TRUE;
4391 h264type.bDirect8x8Inference = OMX_TRUE;
4392 h264type.bDirectSpatialTemporal = OMX_TRUE;
4393 h264type.nCabacInitIdc = 1;
4394 }
4395
4396 setBFrames(&h264type, iFrameInterval, frameRate);
4397 if (h264type.nBFrames != 0) {
4398 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
4399 }
2.2 I,B,P之间的数量关系
4034 static OMX_U32 setPFramesSpacing(
4035 float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) {
4036 // BFramesSpacing is the number of B frames between I/P frames
4037 // PFramesSpacing (the value to be returned) is the number of P frames between I frames
4038 //
4039 // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1
4040 // ^^^ ^^^ ^^^
4041 // number of B frames number of P I frame
4042 //
4043 // = (PFramesSpacing + 1) * (BFramesSpacing + 1)
4044 //
4045 // E.g.
4046 // I P I : I-interval: 8, nPFrames 1, nBFrames 3
4047 // BBB BBB
4048
4049 if (iFramesInterval < 0) { // just 1 key frame
4050 return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1
4051 } else if (iFramesInterval == 0) { // just key frames
4052 return 0;
4053 }
4054
4055 // round down as key-frame-interval is an upper limit
4056 uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval);
4057 OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1);
4058 return ret > 0 ? ret - 1 : 0;
4059 }
3.[ControlRate]
3.1 frameworks
frameworks/native/include/media/openmax/OMX_Video.h
typedef enum OMX_VIDEO_CONTROLRATETYPE {
OMX_Video_ControlRateDisable,
OMX_Video_ControlRateVariable, >>>>D
OMX_Video_ControlRateConstant, >>>>A
OMX_Video_ControlRateVariableSkipFrames,>>>>B
OMX_Video_ControlRateConstantSkipFrames, >>>>C
OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_Video_ControlRateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_Video_ControlRateMax = 0x7FFFFFFF
} OMX_VIDEO_CONTROLRATETYPE;
frameworks/av/media/libstagefright/ACodec.cpp
static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
int32_t tmp;
if (!msg->findInt32("bitrate-mode", &tmp)) {
return OMX_Video_ControlRateVariable;
}
return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
}
3.2 omx
frameworks和omx层的值不是一致的.
4.[intraRefresh]
/frameworks/av/media/libstagefright/ACodec.cpp
4282 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
...
4302 int32_t intraRefreshMode = 0;
4303 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
4304 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
4305 if (err != OK) {
4306 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
4307 err, intraRefreshMode);
4308 return err;
4309 }
4310 }
5.[QP]
5.1 omx
6.[CodingCABAC]
frameworks/av/media/libstagefright/ACodec.cpp
4360 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
...
4371 h264type.bEntropyCodingCABAC = OMX_FALSE;
...
4377 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4378 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
...
4388 h264type.bEntropyCodingCABAC = OMX_TRUE;
...
4394 }