智能客服
你问我答,随时在线为你解决问题

在新建的Android Studio中,定义一些变量和key,关于key值的详细解释,请参见API参考。
// 定义一些基础变量 private MediaCodec mMediaCodec; private MediaFormat mOutputFormat; private boolean bScaleSupported; private boolean bCropSupported; private boolean bQPRegulationSupported; private boolean bNonRefPFrameSupported; private boolean bLTRSupported; private boolean bROISupported; // 查询codec vendor能力集的key private static final String KEY_HISI_EXT_CODEC_VENDOR_CONFIGURE = "vendor.hisi.hisi-ext-codec-vendor-configure"; // scale功能相关的key private static final String KEY_HISI_EXT_CODEC_SCALE_SUPPORTED = "vendor.hisi.hisi-ext-codec-scale-supported"; private static final String KEY_HISI_EXT_CODEC_SCALE_ENABLE = "vendor.hisi.hisi-ext-codec-scale-enable"; private static final String KEY_HISI_EXT_CODEC_SCALE_WIDTH = "vendor.hisi.hisi-ext-codec-scale-width"; private static final String KEY_HISI_EXT_CODEC_SCALE_HEIGHT = "vendor.hisi.hisi-ext-codec-scale-height"; // crop功能相关的key private static final String KEY_HISI_EXT_CODEC_CROP_SUPPORTED = "vendor.hisi.hisi-ext-codec-crop-supported"; private static final String KEY_HISI_EXT_CODEC_CROP_ENABLE = "vendor.hisi.hisi-ext-codec-crop-enable"; private static final String KEY_HISI_EXT_CODEC_CROP_LEFT = "vendor.hisi.hisi-ext-codec-crop-left"; private static final String KEY_HISI_EXT_CODEC_CROP_TOP = "vendor.hisi.hisi-ext-codec-crop-top"; private static final String KEY_HISI_EXT_CODEC_CROP_RIGHT = "vendor.hisi.hisi-ext-codec-crop-right"; private static final String KEY_HISI_EXT_CODEC_CROP_BOTTOM = "vendor.hisi.hisi-ext-codec-crop-bottom"; // QP码控调节功能相关的key private static final String KEY_HISI_EXT_CODEC_QP_REGULATION_SUPPORETD = "vendor.hisi.hisi-ext-codec-qp-regulation-supported"; private static final String KEY_HISI_EXT_CODEC_MAX_QP = "vendor.hisi.hisi-ext-codec-max-qp"; private static final String KEY_HISI_EXT_CODEC_MIN_QP = "vendor.hisi.hisi-ext-codec-min-qp"; // 非参考P帧编码功能相关的key private static final String KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES_SUPPORTED = "vendor.hisi.hisi-ext-codec-non-ref-p-frames-supported"; private static final String KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES = "vendor.hisi.hisi-ext-codec-non-ref-p-frames"; // 长期参考帧编码相关的key private static final String KEY_HISI_EXT_CODEC_LTR_SUPPORTED = "vendor.hisi.hisi-ext-codec-ltr-supported"; private static final String KEY_HISI_EXT_CODEC_LTR_NUMS = "vendor.hisi.hisi-ext-codec-ltr-nums"; private static final String KEY_HISI_EXT_CODEC_LTR_PARAMS = "vendor.hisi.hisi-ext-codec-ltr-params"; // ROI编码相关的key private static final String KEY_HISI_EXT_CODEC_ROI_SUPPORTED = "vendor.hisi.hisi-ext-codec-roi-supported"; private static final String KEY_HISI_EXT_CODEC_ROI_0_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-0-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_1_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-1-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_2_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-2-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_3_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-3-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_4_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-4-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_5_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-5-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_6_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-6-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_7_QP_MODE = "vendor.hisi.hisi-ext-codec-roi-7-qp-mode"; private static final String KEY_HISI_EXT_CODEC_ROI_0_QP = "vendor.hisi.hisi-ext-codec-roi-0-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_1_QP = "vendor.hisi.hisi-ext-codec-roi-1-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_2_QP = "vendor.hisi.hisi-ext-codec-roi-2-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_3_QP = "vendor.hisi.hisi-ext-codec-roi-3-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_4_QP = "vendor.hisi.hisi-ext-codec-roi-4-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_5_QP = "vendor.hisi.hisi-ext-codec-roi-5-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_6_QP = "vendor.hisi.hisi-ext-codec-roi-6-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_7_QP = "vendor.hisi.hisi-ext-codec-roi-7-qp"; private static final String KEY_HISI_EXT_CODEC_ROI_0_PARAMS = "vendor.hisi.hisi-ext-codec-roi-0-params"; private static final String KEY_HISI_EXT_CODEC_ROI_1_PARAMS = "vendor.hisi.hisi-ext-codec-roi-1-params"; private static final String KEY_HISI_EXT_CODEC_ROI_2_PARAMS = "vendor.hisi.hisi-ext-codec-roi-2-params"; private static final String KEY_HISI_EXT_CODEC_ROI_3_PARAMS = "vendor.hisi.hisi-ext-codec-roi-3-params"; private static final String KEY_HISI_EXT_CODEC_ROI_4_PARAMS = "vendor.hisi.hisi-ext-codec-roi-4-params"; private static final String KEY_HISI_EXT_CODEC_ROI_5_PARAMS = "vendor.hisi.hisi-ext-codec-roi-5-params"; private static final String KEY_HISI_EXT_CODEC_ROI_6_PARAMS = "vendor.hisi.hisi-ext-codec-roi-6-params"; private static final String KEY_HISI_EXT_CODEC_ROI_7_PARAMS = "vendor.hisi.hisi-ext-codec-roi-7-params";
以H.264编码器为例,示例代码如下:
mMediaCodec = MediaCodec.createEncoderByType("video/avc");
如果要查询codec的高级编码特性能力集,请设置KEY_HISI_EXT_CODEC_VENDOR_CONFIGURE的value为1。
如果要使能LTR(Long-Term-Reference,长期参考)帧编码功能,请通过KEY_HISI_EXT_CODEC_LTR_NUMS来设置LTR buffer的数量(1~10)。
// 创建 MediaFormat
int width = 1920;
int height = 1080;
MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
// 基础参数设置
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 17000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);
// 必须设置此key,才能查询到codec的vendor能力集
format.setInteger(KEY_HISI_EXT_CODEC_VENDOR_CONFIGURE, 1);
// 如果要使用长期参考帧编码,必须在configure阶段设置buffer数量, 取值范围 [1, 10]
format.setInteger(KEY_HISI_EXT_CODEC_LTR_NUMS, 5);
// 配置编码器
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
配置编码器后,获取output format来判断codec支持哪些高级编码特性,然后决定是否要启用该特性。
// 获取output format
mOutputFormat = mMediaCodec.getOutputFormat();
// 依次获取codec的各项高级特性的能力
bScaleSupported = mOutputFormat.containsKey(KEY_HISI_EXT_CODEC_SCALE_SUPPORTED)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_SCALE_SUPPORTED) == 1;
bCropSupported = mOutputFormat.containsKey(KEY_HISI_EXT_CODEC_CROP_SUPPORTED)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_CROP_SUPPORTED) == 1;
bQPRegulationSupported = OutputFormat.containsKey(KEY_HISI_EXT_CODEC_QP_REGULATION_SUPPORETD)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_QP_REGULATION_SUPPORETD) == 1;
bNonRefPFrameSupported = OutputFormat.containsKey(KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES_SUPPORTED)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES_SUPPORTED) == 1;
bLTRSupported = mOutputFormat.containsKey(KEY_HISI_EXT_CODEC_LTR_SUPPORTED)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_LTR_SUPPORTED) == 1;
bROISupported = mOutputFormat.containsKey(KEY_HISI_EXT_CODEC_ROI_SUPPORTED)
&& mOutputFormat.getInteger(KEY_HISI_EXT_CODEC_ROI_SUPPORTED) == 1;
获取编码器能力支持情况之后,启动编码器。
mMediaCodec.start();
编码过程中,可以设置各项参数来使能高级编码功能。
Bundle bundle = new Bundle();
使用高级编码功能之前请判断codec是否支持此功能。
各高级编码功能均支持帧级设置。
直播或视频通话中,在需要改变分辨率的场景(仅限高分辨率向低分辨率转换)时,开发者可以调用此接口,无须重启编码器,实现分辨率的无缝切换。
缩放的宽度取值范围为176~原始帧的宽度,并且为2的倍数。
缩放的高度取值范围为144~原始帧的高度,并且为2的倍数。
// 如果codec支持scale功能,可以设置scale的参数
if (bScaleSupported) {
// 使能scale功能
bundle.putInt(KEY_HISI_EXT_CODEC_SCALE_ENABLE, 1);
// 设置scale的宽度,取值范围 [176, width]
bundle.putInt(KEY_HISI_EXT_CODEC_SCALE_WIDTH, 960);
// 设置scale的高度,取值范围 [144, height]
bundle.putInt(KEY_HISI_EXT_CODEC_SCALE_HEIGHT, 540);
}
裁剪功能一般与缩放功能一起使用,实现分辨率的无缝切换。
设置的裁剪区域的边界以及宽高不能超出原frame区域。
裁剪宽高的计算方式如下:
cropWidth = cropRight – cropLeft + 1; cropHeight = cropBottom – cropTop + 1;
cropWidth的取值范围为176~原始帧的宽度,要求为2的倍数。
cropHeight的取值范围为144~原始帧的高度,要求为2的倍数。
// 如果codec支持crop功能,可以设置crop的参数
if (bCropSupported) {
// 使能crop功能
bundle.putInt(KEY_HISI_EXT_CODEC_CROP_ENABLE, 1);
// 设置crop的左边界, 取值范围[0, width - 176]
bundle.putInt(KEY_HISI_EXT_CODEC_CROP_LEFT, 0);
// 设置crop的顶边界, 取值范围[0, height - 144]
bundle.putInt(KEY_HISI_EXT_CODEC_CROP_TOP, 0);
// 设置crop的右边界,取值范围[176, width]
bundle.putInt(KEY_HISI_EXT_CODEC_CROP_RIGHT, 959);
// 设置crop的底边界 , 取值范围[144, height]
bundle.putInt(KEY_HISI_EXT_CODEC_CROP_BOTTOM, 539);
}
视频通话过程中,开发者可以动态调节某些编码帧的QP值,以实现更清晰或者更模糊的效果。
设置的QP范围为[0, 51],且二者的差值至少为6。
编码器内部会对过大(超过43)或过小(低于12)的QP做微调,从而保证编码效果。
如果codec支持动态调节QP,可以设置相关参数。
if (bQPRegulationSupported) {
// 设置最大QP, 取值范围[0, 51]
bundle.putInt(KEY_HISI_EXT_CODEC_MAX_QP, 43);
// 设置最小QP, 取值范围[0, 51]
bundle.putInt(KEY_HISI_EXT_CODEC_MIN_QP, 16);
}
视频通话过程中,网络状况波动较大时,开发者可以启用此功能来编码非参考P帧,随后适当地丢弃非参考P帧,降低带宽,增加解码端的流畅性。
开发者通过KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES设置I帧或参考P帧之间的非参考P帧的数量来启用此功能(配置阶段设置的帧率必须小于120fps,此设置项才会使能非参考P帧编码特性)。
非参考P帧的数量取值范围为[0, 2]。
// 如果codec支持非参考P帧编码,可以设置I帧或参考P帧之间非参考P帧的数量
if (bNonRefPFrameSupported) {
// 设置最大非参考P帧数量,取值范围[0, 2]
bundle.putInt(KEY_HISI_EXT_CODEC_NON_REF_P_FRAMES, 1);
}
长期参考帧功能可以减少因发送数据量较大的I帧造成的视频卡顿,也可以根据具体场景,灵活设置编码帧的参考关系。
LTR涉及三个子参数:
LTR参数仅配置给当前编码帧,编码后会自动清除LTR参数。
// 如果codec支持长期参考帧编码,可以设置相关参数
if (bLTRSupported) {
// 编码时将此帧标记为长期参考帧
int isLTRFrame = 1;
// 编码时要参考之前的长期参考帧
int use = 1;
// 被参考的长期参考帧的POC (只有use为1时,此参数有效)
short refLTRPoc = 0;
// 组合配置参数并下发
int params = (isLTRFrame << 24) | (use << 16) | refLTRPoc;
bundle.putInt(KEY_HISI_EXT_CODEC_LTR_PARAMS, params);
}
直播场景下,开发者可以对特定区域的QP做调整,编码器可以给该区域分配更多或更少的比特数,达到更清晰或更模糊的效果。
开发者可以通过设置QP编码模式,QP值以及ROI(region of interest,感兴趣区域)的位置来使能此功能。
ROI支持两种QP编码模式:
// 如果codec支持ROI编码,可以设置相关参数
if (bROISupported) {
// 设定区域0的范围
short region0StartX = 100;
short region0StartY = 120;
short region0Width = 640;
short region0Height = 480;
long params0 = region0StartX |
(((long)region0StartY) << 16) |
(((long)region0Width) << 32) |
(((long)region0Height) << 48);
// 指定区域0编码的QP模式,取值范围 0:相对QP, 1: 绝对QP
bundle.putInt(KEY_HISI_EXT_CODEC_ROI_0_QP_MODE, 1);
// 指定区域0编码的QP值,取值范围:相对QP编码时 [-51, 51], 绝对QP编码时 [0, 51]
bundle.putInt(KEY_HISI_EXT_CODEC_ROI_0_QP, 26);
// 设置区域0的编码范围
bundle.putLong(KEY_HISI_EXT_CODEC_ROI_0_PARAMS, params0);
// 设定其他区域的参数, 最多可以设置8个区域
// ...
}
随后通过setParameters将Bundle里面的参数传递给codec。
// 编码前给底层设置参数 mMediaCodec.setParameters(bundle);
请参考Android的MediaCodec接口进行编码。