Select H264 profile when encoding with MediaCodec and MTK Codec

We have an Android app that encodes video in H264. On all previously proven Android devices, this encodes the base profile that I need.

In Lenovo Yoga 10, the codec is OMX.MTK.VIDEO.ENCODER.AVC. This encodes the video as a high profile, which creates a problem for the receiving device.

I am using MediaCodec. There seems to be no way to set the profile to use.

Is there any way to do this? The codec claims to support the basic profile, but does not use it. Is there a specific codec parameter for this?

+5
source share
3 answers

What you could try is to add the profile key to your MediaFormat with a value of 1 ( OMX_VIDEO_AVCProfileBaseline ). If you do this, you probably also need to add a level key with a level that matches your resolution (with a value from the OMX AVC level constants).

I'm not sure if this codec really honors the requested value, but it might be worth a try.

See the setupAVCEncoderParameters function at https://android.googlesource.com/platform/frameworks/av/+/6ade04174/media/libstagefright/ACodec.cpp for an example installation procedure. It looks for the profile key of input parameters (which are copied from the MediaFormat you provided), but if it is present, you also need to provide the level parameter, and what level of use depends on your resolution. See https://android.googlesource.com/platform/frameworks/native/+/cde4b13a/include/media/openmax/OMX_Video.h for constant values ​​that you can use for parameters.

But after checking the profile and level parameters, it also seems to redefine the profile to the base level no matter what was installed. Thus, either these lines were deleted from your device, or the encoder generally ignores the h264type.eProfile field.

If someone has a source tree, closer to what is actually used on devices, it would be even better to check this out.

For an example of how to choose the appropriate level for your resolution, see x264_validate_levels at http://git.videolan.org/?p=x264.git;a=blob;f=encoder/set.c;h=1a40b71284 (but the level passed by MediaFormat must be expressed using the OMX_VIDEO_AVCLEVELTYPE constant).

Not sure if any of this helps, but at least it's worth a try.

+3
source

Here is a snippet of what I did in my application:

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

And here are the profile values ​​you can choose:

 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 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 is important to set both parameters.

+1
source

I tried this on a Nexus 9 with an Nvidia HW encoder. The only thing that works for me is to choose an encoder by name. I can set the profile to the selected value for the encoder level always equal 13.

Note that if you select an encoder by type, it selects a google encoder and, as mentioned above, it forces the profile to refer to a basic level.

0
source

Source: https://habr.com/ru/post/1204254/


All Articles