简体   繁体   English

使用MediaCodec和MTK编解码器编码时选择H264配置文件

[英]Select H264 Profile when encoding with MediaCodec and MTK Codec

We have an Android app that encodes video into H264. 我们有一个Android应用程序,可将视频编码为H264。 On all previously tried Android devices this encodes to Baseline profile which is what I need. 在所有以前尝试过的Android设备上,这都编码为Baseline配置文件,这正是我所需要的。

On the Lenovo Yoga 10 the codec is OMX.MTK.VIDEO.ENCODER.AVC. 在Lenovo Yoga 10上,编解码器为OMX.MTK.VIDEO.ENCODER.AVC。 This encodes the video as High Profile which gives a problem for the receiving device. 这会将视频编码为High Profile,这给接收设备带来了问题。

I am using MediaCodec. 我正在使用MediaCodec。 There seems to be no way to set the profile to be used. 似乎没有办法设置要使用的配置文件。

Is there any way of doing this ? 有什么办法吗? The codec does claim to support Baseline profile but gives no way of using it. 编解码器确实声称支持基准配置文件,但是没有使用它的方式。 Is there a codec specific parameter for this? 是否有特定的编解码器参数?

What you could try is to add the key profile to your MediaFormat, with a value of 1 ( OMX_VIDEO_AVCProfileBaseline ). 您可以尝试将密钥profile添加到MediaFormat中,值为1OMX_VIDEO_AVCProfileBaseline )。 If you do this, you probably also need to add the key level with a level value matching your resolution as well (with a value from the OMX AVC level constants). 如果这样做,您可能还需要添加具有与分辨率匹配的级别值的键level (带有来自OMX AVC级别常量的值)。

I'm not sure if this codec actually honors the requested value though, but it might be worth a try. 我不确定该编解码器是否实际上遵守要求的值,但是可能值得尝试。

See the setupAVCEncoderParameters function in https://android.googlesource.com/platform/frameworks/av/+/6ade04174/media/libstagefright/ACodec.cpp for an example on the setup procedure. 有关设置步骤的示例,请参见https://android.googlesource.com/platform/frameworks/av/+/6ade04174/media/libstagefright/ACodec.cpp中setupAVCEncoderParameters函数。 It looks for the profile key in the input parameters (which are copied from the MediaFormat that you've provided), but if this is present you also need to provide a level parameter, and what level to use depends on your resolution. 它会在输入参数(从您提供的MediaFormat复制的参数)中寻找profile密钥,但是如果存在,则还需要提供一个level参数,使用的级别取决于您的分辨率。 See https://android.googlesource.com/platform/frameworks/native/+/cde4b13a/include/media/openmax/OMX_Video.h for constant values you can use for the parameters. 有关可用于参数的常量值,请参见https://android.googlesource.com/platform/frameworks/native/+/cde4b13a/include/media/openmax/OMX_Video.h

But after checking for the profile and level parameters, it also seems to override the profile to baseline regardless of what was set. 但是在检查了配置文件和级别参数之后,无论设置了什么,它似乎也将配置文件覆盖为基线。 So either these lines have been removed from your device, or the encoder disregards the h264type.eProfile field altogether. 因此,这些行已从设备中删除,或者编码器完全忽略了h264type.eProfile字段。

If someone has got a source tree closer to what actually is used on the devices, it would be even better to inspect that. 如果某人的源树更接近设备上实际使用的树,则最好检查一下。

As an example on how to pick a suitable level for your resolution, have a look at x264_validate_levels in http://git.videolan.org/?p=x264.git;a=blob;f=encoder/set.c;h=1a40b71284 (but the level passed to MediaFormat needs to be expressed using the OMX_VIDEO_AVCLEVELTYPE constants). 作为有关如何为您的分辨率选择合适的级别的示例,请查看http://git.videolan.org/?p=x264.git;a=blob;f=encoder/set.c;h中的x264_validate_levels= 1a40b71284 (但是传递给MediaFormat的级别需要使用OMX_VIDEO_AVCLEVELTYPE常量表示)。

Not sure if anything of this helps, but it's at least worth a try. 不知道这是否有帮助,但是至少值得一试。

Here's a snippet of what I did in my app : 这是我在应用程序中所做的摘要:

mediaFormat.setInteger("profile", 8); // Profile HIGH
mediaFormat.setInteger("level", 0x200); // Level 3.1

And here are the profile values you can choose from : 这是您可以选择的配置文件值:

OMX_VIDEO_AVCProfileBaseline = 0x01,   /**< Baseline profile */
OMX_VIDEO_AVCProfileMain     = 0x02,   /**< Main profile */
OMX_VIDEO_AVCProfileExtended = 0x04,   /**< Extended profile */
OMX_VIDEO_AVCProfileHigh     = 0x08,   /**< High profile */
OMX_VIDEO_AVCProfileHigh10   = 0x10,   /**< High 10 profile */
OMX_VIDEO_AVCProfileHigh422  = 0x20,   /**< High 4:2:2 profile */
OMX_VIDEO_AVCProfileHigh444  = 0x40,   /**< High 4:4:4 profile */
OMX_VIDEO_AVCProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
OMX_VIDEO_AVCProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_VIDEO_AVCProfileMax      = 0x7FFFFFFF  

And the levels : 和水平:

OMX_VIDEO_AVCLevel1   = 0x01,     /**< Level 1 */
OMX_VIDEO_AVCLevel1b  = 0x02,     /**< Level 1b */
OMX_VIDEO_AVCLevel11  = 0x04,     /**< Level 1.1 */
OMX_VIDEO_AVCLevel12  = 0x08,     /**< Level 1.2 */
OMX_VIDEO_AVCLevel13  = 0x10,     /**< Level 1.3 */
OMX_VIDEO_AVCLevel2   = 0x20,     /**< Level 2 */
OMX_VIDEO_AVCLevel21  = 0x40,     /**< Level 2.1 */
OMX_VIDEO_AVCLevel22  = 0x80,     /**< Level 2.2 */
OMX_VIDEO_AVCLevel3   = 0x100,    /**< Level 3 */
OMX_VIDEO_AVCLevel31  = 0x200,    /**< Level 3.1 */
OMX_VIDEO_AVCLevel32  = 0x400,    /**< Level 3.2 */
OMX_VIDEO_AVCLevel4   = 0x800,    /**< Level 4 */
OMX_VIDEO_AVCLevel41  = 0x1000,   /**< Level 4.1 */
OMX_VIDEO_AVCLevel42  = 0x2000,   /**< Level 4.2 */
OMX_VIDEO_AVCLevel5   = 0x4000,   /**< Level 5 */
OMX_VIDEO_AVCLevel51  = 0x8000,   /**< Level 5.1 */
OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF  

It's important to set both. 两者都设置很重要。

I have tried this on Nexus 9 with Nvidia HW encoder. 我已经在配备Nvidia硬件编码器的Nexus 9上进行了尝试。 Only thing that works for me is to select the encoder by name. 对我来说唯一有效的方法是按名称选择编码器。 I am able to set the profile to chosen value for encoder level is always set to 13. 我可以将配置文件设置为所选值,因为编码器级别始终设置为13。

Please note that if you select encoder by type, it selects google encoder and as mentioned above, it forces profile to baseline. 请注意,如果您按类型选择编码器,则会选择google编码器,如上所述,它将配置文件强制设为基线。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM