Android MediaCodec设置H264 Profile到High

     H264 High Profile压缩率高,能降低码率,这里记录下MediaCodec Profile设置到High遇到的一些问题。

     Android 4.1 就引入了MediaCodecInfo.CodecProfileLevel类,下面截取H264(AVC)的Profile和Level定义:

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package android.media;

public final class MediaCodecInfo {

    /**
     * Encapsulates the profiles available for a codec component.
     */
    public static final class CodecProfileLevel {
        // These constants were originally in-line with OMX values, but this
        // correspondence is no longer maintained.

        // Profiles and levels for AVC Codec, corresponding to the definitions in
        // "SERIES H: AUDIOVISUAL AND MULTIMEDIA SYSTEMS,
        // Infrastructure of audiovisual services – Coding of moving video
        // Advanced video coding for generic audiovisual services"
        // found at
        // https://www.itu.int/rec/T-REC-H.264-201704-I

        /**
         * AVC Baseline profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileBaseline = 0x01;

        /**
         * AVC Main profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileMain     = 0x02;

        /**
         * AVC Extended profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileExtended = 0x04;

        /**
         * AVC High profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileHigh     = 0x08;

        /**
         * AVC High 10 profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileHigh10   = 0x10;

        /**
         * AVC High 4:2:2 profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileHigh422  = 0x20;

        /**
         * AVC High 4:4:4 profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileHigh444  = 0x40;

        /**
         * AVC Constrained Baseline profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileConstrainedBaseline = 0x10000;

        /**
         * AVC Constrained High profile.
         * See definition in
         * H.264 recommendation,
         * Annex A.
         */
        public static final int AVCProfileConstrainedHigh     = 0x80000;

        public static final int AVCLevel1       = 0x01;
        public static final int AVCLevel1b      = 0x02;
        public static final int AVCLevel11      = 0x04;
        public static final int AVCLevel12      = 0x08;
        public static final int AVCLevel13      = 0x10;
        public static final int AVCLevel2       = 0x20;
        public static final int AVCLevel21      = 0x40;
        public static final int AVCLevel22      = 0x80;
        public static final int AVCLevel3       = 0x100;
        public static final int AVCLevel31      = 0x200;
        public static final int AVCLevel32      = 0x400;
        public static final int AVCLevel4       = 0x800;
        public static final int AVCLevel41      = 0x1000;
        public static final int AVCLevel42      = 0x2000;
        public static final int AVCLevel5       = 0x4000;
        public static final int AVCLevel51      = 0x8000;
        public static final int AVCLevel52      = 0x10000;
        public static final int AVCLevel6       = 0x20000;
        public static final int AVCLevel61      = 0x40000;
        public static final int AVCLevel62      = 0x80000;
 }
}

     其中AVCProfileConstrainedBaseline 和 AVCProfileConstrainedHigh 是安卓8.1 引入的; AVCLevel52 是安卓5.0 引入的; AVCLevel6, AVCLevel61, AVCLevel62 是安卓10 引入的;

     AVC High profile 和 AVC Constrained High profile的区别: 1. 从名字就可以看出Constrained High是High的子集;  2. Constrained High 不支持B slice(B帧); 3.  Constrained High 只支持帧编码,不支持场编码和帧场自适应编码; 

    另外Level也要选择合适的,  GB28181-2016要求本地录像帧率不低于25fps, 网络传输时重要图像帧率宜25fps. GB28181-2022要求一类视频监控点、二类视频监控点的本地录像和网络传输的最大视频帧率应不低于25fps. 这里以视频30fps为例, 安卓摄像头常用的几个分辨率最小支持的Level如下:

分辨率 最小支持的Level
640*480 3
1280*720(720p) 3.1
1920*1280(1080p)

4

3840*2160(4k) 5.1

   虽然安卓5.0已引入android.media.MediaFormat.KEY_PROFILE, 安卓6.0 引入android.media.MediaFormat.KEY_LEVEL. 但安卓7.0及以上AVC Profile设置才有效, 并且要求Profile和Level必须一起设置.

   我的代码也提供了Mediacode编码参数设置接口, Java 和 NDK 两种MediaCodec接口方式都支持:

    // Copyright (C) [email protected]
   
    /**
	 * 设置视频硬编码是否使用Native Media NDK, 默认是不使用, 安卓5.0以下设备不支持
	 * @param handle
	 * @param is_native: 0表示不使用, 1表示使用, sdk默认是0.
	 * @return {0} if successful
	 */
	public native int SetNativeMediaNDK(long handle, int is_native);


	/*
	* 设置视频硬编码码率控制模式
	* @param hw_bitrate_mode: -1表示使用默认值,不设置也会使用默认值, 0:CQ, 1:VBR, 2:CBR, 3:CBR_FD, 请参考:android.media.MediaCodecInfo.EncoderCapabilities
	* 注意硬编码和手机硬件有关,多数手机只支持部分码率模式, 另外硬编码设备差异很大,不同设备同一码率控制模式效果可能不一样
	* @return {0} if successful
	*/
	public native int SetVideoHWEncoderBitrateMode(long handle, int hw_bitrate_mode);


	/*
	 * 设置视频硬编码质量, 安卓9及以上支持, 仅当硬编码器码率控制模式(BitrateMode)是CQ(constant-quality mode)时才有效
	 * @param hw_quality: -1表示不设置, 请参考:android.media.MediaFormat.KEY_QUALITY
	 * 注意硬编码和手机硬件有关,部分手机可能不支持此设置
	 * @return {0} if successful
	 */
	public native int SetVideoHWEncoderQuality(long handle, int hw_quality);

	/*
	 * 设置H.264硬编码Profile, 安卓7及以上支持
	 * @param hw_avc_profile: 0表示使用默认值, 0x01: Baseline, 0x02: Main, 0x08: High, 0x10000: ConstrainedBaseline, 0x80000: ConstrainedHigh;
	 * 注意: ConstrainedBaseline 和 ConstrainedHigh 可能多数设备不支持,
	 * H.264推荐使用 High 或者 ConstrainedHigh, 如果您使用的手机硬解码解不了,那还是设置Baseline
	 * 如果设置的Profile硬编码器不支持,应编码器会使用默认值
	 * 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
	 * @return {0} if successful
	 */
	public native int SetAVCHWEncoderProfile(long handle, int hw_avc_profile);

	/*
	 * 设置H.264硬编码Level, 这个只有在设置了Profile的情况下才有效, 安卓7及以上支持
	 * @param hw_avc_level: 0表示使用默认值, 0x100: Level3, 0x200: Level3.1, 0x400: Level3.2,
	 * 0x800: Level4, 0x1000: Level4.1, 0x2000: Level4.2,
	 * 0x4000: Level5, 0x8000: Level5.1,  0x10000: Level5.2,
	 * 0x20000: Level6, 0x40000: Level6.1,  0x80000: Level6.2,
	 * 如果设置的level太高硬编码器不支持,SDK内部会做相应调整
	 * 注意: 640*480@25fps最小支持的是Level3, 720p最小支持的是Level3.1, 1080p最小支持的是Level4
	 * 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
	 * @return {0} if successful
	 */
	public native int SetAVCHWEncoderLevel(long handle, int hw_avc_level);

	/*
	 * 设置视频硬编码最大码率, 安卓没有相关文档说明, 所以不建议设置,
	 * @param hw_max_bitrate: 每秒最大码率, 单位bps
	 * @return {0} if successful
	 */
	public native int SetVideoHWEncoderMaxBitrate(long handle, long hw_max_bitrate);

  经测试MTK、 海思(鸿蒙系统)、 三星、全志、晶晨、瑞芯微等编码器AVC Profile设置都可以成功。更多问题联系qq: 1130758427

你可能感兴趣的:(MediaCodecLevel,MediaCodecAVC,MediaCodecHEVC,MediaCodecH264,安卓AVCHighProfil)