使用MediaCodec API在Android中编码视频时设置AVC / H.264配置文件

时间:2014-03-24 13:55:35

标签: android mediacodec

Android提供了一种查询支持的编码配置文件的方法。但是在设置编码器时,我找不到指定要使用的所需配置文件的方法。

查找支持的个人资料/关卡对

在Android中使用MediaCodec API,一旦选择了编码器组件,就可以调用getCodecInfo()。这将返回一个MediaCodecInfo对象,该对象提供有关正在使用的编解码器组件的详细信息。 getCapabilitiesForType()返回一个CodecCapabilities对象,详细说明了编解码器的功能。它包含一个CodecProfileLevel数组,详细说明了支持的配置文件和支持的级别。

尝试设置个人资料

我无法看到一个字段来设置MedieCodecMediaFormat的个人资料。

KEY_AAC_PROFILEMediaFormat,但在参考文献中明确指出这仅适用于aac音频。

MediaCodec中,有一种方法可以使用BundlesetParameters()个额外参数传递给编解码器。这似乎没有通用文档,并且接受的参数在编解码器(不同设备)之间会有所不同。

背景

配置文件指定要使用的一组编码功能。简单的配置文件计算量较小,但通常牺牲了给定比特率的质量。级别指定给定配置文件支持的最大分辨率/比特率。我希望水平通常与解码能力相关联,但由于它描述的是必须实时运行的硬件编码器,因此具有最大设置对我来说很有意义。

META :(我最初有更多关于我提到的每个课程+功能的链接,但我不得不删除它们,因为我还没有让代表发布超过2个链接。)

4 个答案:

答案 0 :(得分:4)

对于Android Kitkat设备,我们可以根据下面的代码片段将所需的AVC配置文件和级别设置为媒体格式(设置基准级别为1.3)。请在启动MediaCodec之前设置此项。

    format.setInteger("profile",MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
    format.setInteger("level", MediaCodecInfo.CodecProfileLevel.AVCLevel13);

答案 1 :(得分:3)

MediaCodec API中没有明确的配置文件选择。 Codec将自行选择一个配置文件。它还将根据输入宽度/高度和帧速率数选择一个级别,但它可以选择一个高于配置所需最小级别的级别。

您可以在编码器编解码器中查询支持的级别,以查看它可能生成的配置文件,但您将无法选择首选的配置文件。编解码器很可能会选择它可以处理给定级别的最高配置文件,但不能保证。

答案 2 :(得分:2)

从Android 5.0开始,可以设置配置文件(SDK级别21)和级别(SDK级别23)。

http://developer.android.com/reference/android/media/MediaFormat.html#KEY_PROFILE http://developer.android.com/reference/android/media/MediaFormat.html#KEY_LEVEL

Haven尚未尝试过这些在实践中的效果。

答案 3 :(得分:0)

给定的AVC编码器可以忽略配置文件和级别提示。

为了确保AVC编码器选择了哪个配置文件和级别,您可以在启动后从其MediaFormat实时查询SPS(如初始格式更改事件期间)。

参见spec的第7节。

这张海报展示了从这些base64字符串中提取个人资料和关卡(请注意他!):

Can profile-level-id and sprop-parameter-sets be extracted from an RTP stream?

以下是Base64编码的SPS和PPS:

...
mIndex = mMediaEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT);

// First buffer encoded is the NAL frame metadata
if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
{
    Log.i("PPS: "+getParameterSetAsString(mMediaEncoder, "csd-0");
    Log.i("SPS: "+getParameterSetAsString(mMediaEncoder, "csd-1");
}
...

private String getParameterSetAsString(MediaCodec encoder, String csd)
{
    MediaFormat mMediaFormat = encoder.getOutputFormat();
    ByteBuffer ps = mMediaFormat.getByteBuffer(csd);

    // The actual SPS and PPS byte codes
    byte[] mPS = new byte[ps.capacity()-4];
    ps.position(4);
    ps.get(mPS,0,mPS.length);

    //Covert to String
    return Base64.encodeToString(mPS, 0, mPS.length, Base64.NO_WRAP);
}