[Android] Codec paramter

文章从framework层介绍Android视频编码相关内容,omx层和kernel层因涉及芯片厂商未详细写代码。具体分析了Profile&Level在framework和omx层情况,I/B/P帧的类型、数量关系,还提及ControlRate、intraRefresh、QP、CodingCABAC等参数在不同层的表现。

Please note that:本文章为原创,若需转载,请指明该出处. =================================================================================

本文章只从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(&params);
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,
                 &params,
                 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                 &params,
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     }

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值