当前位置: 首页 > 知识库问答 >
问题:

如何判断Android设备上的视频编码支持哪些MediaFormats?

柯书
2023-03-14

我正在开发一个视频/照片处理库(添加Instagram/Snapchat等过滤器)。到目前为止,核心功能运行得非常好。

然而,我发现视频处理(对输入视频重新编码)非常令人沮丧。似乎存在一些边缘情况和设备特定问题,使库无法100%工作。

我想知道如何选择/创建可在设备上使用的MediaFormat。

目前,我正在设置将用于对视频进行编码的MediaFormat,如下所示:

// assume that "extractor" is a media extractor wrapper, which holds a 
// reference to the MediaFormat of the input video
fun getOutputVideoFormat(): MediaFormat {
    val mimeType = MediaFormat.MIMETYPE_VIDEO_H263
    var width = -1
    var height = -1
    var frameRate = 30
    var bitrate = 10_000_000
    val colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface

    if (extractor.videoFormat.containsKey(MediaFormat.KEY_WIDTH)) {
        width = extractor.videoFormat.getInteger(MediaFormat.KEY_WIDTH)
    }

    if (extractor.videoFormat.containsKey(MediaFormat.KEY_HEIGHT)) {
        height = extractor.videoFormat.getInteger(MediaFormat.KEY_HEIGHT)
    }

    if(extractor.videoFormat.containsKey(MediaFormat.KEY_FRAME_RATE)){
        frameRate = extractor.videoFormat.getInteger(MediaFormat.KEY_FRAME_RATE)
    }

    if(extractor.videoFormat.containsKey(MediaFormat.KEY_BIT_RATE)){
        bitrate = extractor.videoFormat.getInteger(MediaFormat.KEY_BIT_RATE)
    }

    val format = MediaFormat.createVideoFormat(mimeType, width, height)
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat)
    format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate)
    format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
    format.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate)

    // prevent crash on some Samsung devices
    // http://stackoverflow.com/questions/21284874/illegal-state-exception-when-calling-mediacodec-configure?answertab=votes#tab-top
    format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height)
    format.setInteger(MediaFormat.KEY_MAX_WIDTH, width)
    format.setInteger(MediaFormat.KEY_MAX_HEIGHT, height)
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0)
    return format
}

到目前为止,这在我测试过的所有主要设备上都有效,但有一些设备,比如三星A5,使用这种格式时被报告在无提示下失败,只需使用在所有其他设备上正常工作的输入视频创建损坏的输出视频。

如何判断MediaFormat是否真的会在给定设备上成功?

我从三星A5设备上获得的唯一日志表明,当MediaCodec通过“INFO_OUTPUT_FORMAT_CHANGED”信号发送时,会返回以下媒体格式:

csd-1=java.nio.ByteArrayBuffer[position=0,limit=8,capacity=8], 
mime=video/avc,  
frame-rate=30,  
remained_resource=2549760,  
height=480,  
width=480,  
max_capacity=3010560, what=1869968451,  
bitrate=10000000,  
csd-0=java.nio.ByteArrayBuffer[position=0,limit=17,capacity=17]

鉴于输入视频的分辨率为1280x720,这种格式对我来说似乎无效

共有2个答案

解柏
2023-03-14

原来我的问题与设备上可用的视频编解码器无关。问题不是来自MediaCodec或MediaFormat,而是来自MediaMuxer。

我通过MediaExtractor读取视频和音频,通过配置为解码的MediaCodec推送,处理数据,然后通过配置为编码的MediaCodec推送处理后的数据,来处理视频和音频。然后我将编码数据推送到MediaMuxer(并最终将其写入文件)。这与在https://bigflake.com/mediacodec/。我只是在视频轨道上进行处理,但我使用了类似的解码/编码方法,从输入文件中获取音频并将其放入输出文件。

我最初以为问题是设备特有的,但事实证明问题实际上是输入。导致处理问题的视频非常短——不到2秒长。对于如此短的视频,解码和重新编码音频无法正常工作,MediaMuxer也没有注册任何音频帧。这就是导致最终输出损坏的原因。

我找到了以下CTS测试:https://android.googlesource.com/platform/cts/ /jb-mr2-release/tests/tests/media/src/android/media/cts/MediaMuxerTest.java,以及它的cloneMediaUsingMuxer方法,它展示了如何将音频直接从MediaExtractor复制到MediaMuxer。

我修改了我的处理方法(继续)对视频使用解码/编辑/编码方法,并使用CTS测试中演示的直通方法编写音频。这就解决了问题,我能够正确地处理短视频。

黄德明
2023-03-14

您可以使用MediaCodecList API查询并列出可用的编解码器及其支持的格式。

同样对于你的代码示例,你真的在使用MediaFormat。MIMETYPE_VIDEO_H263还是错别字?这是一种非常古老的格式。(不是“支持良好且可靠”的方式,而是“旧的、未经测试且可能已损坏”的方式。)最安全的方法是使用MediaFormat。MIMETYPE_VIDEO_AVC,它是Android兼容性测试套件和第三方应用程序测试最多的一种。

 类似资料:
  • 问题内容: 是的,我知道FAQ会假装回答此问题,但实际上并非如此。相反,它指示您从源代码构建项目(并且构建说明非常复杂)。那种打败了整个观点:) 让我们省去世界上每个人的麻烦,即不必再构建另一个开源项目,以了解它是否真正解决了他们的问题。Xuggler支持哪些编解码器? 问题答案: FAQ不能回答这个问题的原因是,随着我们发布新版本,它会不断变化,并且要使文档中的列表保持最新状态会花费很长时间。但

  • 我需要有一个功能,告诉我是否手机的摄像头视频支持至少30fps。我同时使用camera1和camera2 api,这取决于手机对camera2的支持(或不支持) 我想用这个: 但我不确定这是否是正确的解决方案,我不明白我得到的范围,以及我是否选择了正确的摄像学。

  • 问题内容: 我正在为Android SDK 2.3.3编写一个Android应用程序,但随后我被要求在运行Android 2.2.1的设备上对其进行测试。因此,我将目标设置为8而不是10。但是java.util.concurrent.TimeUnit仅具有Java 1.5功能集,而不是java.util.concurrent.TimeUnit的Java 1.6 / 1.7功能集。因此,我将Time

  • 我正在尝试在我的项目中使用材料设计,但我没有找到一种方法来导入它。我花了很多时间在互联网和stackoverflow中尝试用户的建议,但无论我尝试什么都不起作用。 我在Mac OSX 10.10上使用Android Studio 0.8.14。使用gradle 13.2和JDK jdk1.8.0_25.JDK。从图片中可以看到,我的android SDK是最新的 这是我的卷轴 有人能帮我吗?我做错

  • 我有比赛的要求。Android设备上的m3u8视频url我正在尝试执行以下代码,但它不工作,我得到的视频无法播放? 有人能帮忙吗? 源代码: 注: 我在Android 3.0上关注了这个链接HLS(http直播)并寻找

  • 本文向大家介绍jquery判断iPhone、Android设备类型,包括了jquery判断iPhone、Android设备类型的使用技巧和注意事项,需要的朋友参考一下 最近做了一版微信宣传页,通过JQ来判断设备,并进行下载  微信内置浏览器对下载链接进行了屏蔽,所以先进行判断,如果是微信内置浏览器,则跳转应用宝链接,如果不是,则判断是iPhone/Adroid/PC 并进行跳转  代码如下: 以上