Android 硬编硬解退坑指南

栏目: IOS · Android · 发布时间: 5年前

抖音、快手在国内迅速走红,也带动了国内短视频的热潮。短视频录制、编辑等等功能,是一项系统性、专业性很强的领域。经过一段时间发展后,有多种方式可以通向罗马,但并不是每一条路都好走。这篇文章将重点介绍下,硬编硬解过程中遇到的坑,也给读者朋友架构方案时提供一点参考。

Camera 使用的坑

虽然和硬编硬解没有关系,但短视频客户端不可能绕过这个,这里也列举下我所遇到的问题。

API 使用上的一些坑

Camera API 是 Android 碎片化严重的体现,不同于 iOS 系列,一共就那几种机型。Android 厂商众多,ROM 也百花齐放,同样的 API 在不同机型上提现可能完全不同,也是我们需要在开发过程中留意的。下面简单列举两个可能会导致画面异常的 API。

  1. setRecordingHint
Sets recording mode hint. This tells the camera that the intent of the application is to record videos MediaRecorder.start(), not to take still pictures Camera.takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback). Using this hint can allow MediaRecorder.start() to start faster or with fewer glitches on output. This should be called before starting preview for the best result, but can be changed while the preview is active. The default value is false. The app can still call takePicture() when the hint is true or call MediaRecorder.start() when the hint is false. But the performance may be worse. 

官方的注释如上,英文很简单,就不翻译了。看上去是一个很人畜无害的 API,但实际上却暗藏杀机。此方法需要你设置 video-size,如果不设置这个,将会在某些机型(OPPO A37f, MI 2 , LG 部分手机)上造成拉伸的后果。

Android 硬编硬解退坑指南

图片来源于网络

RecordingHint 的目的是帮助更快速地进行录制,某些 ROM 在实现的时候,没有考虑到 Preview Size 和 Video Size 之间的区别,例如使用 480 864 的分辨率进行录制,输出的文件大小为 400 800,那么势必会使得整体画面出现拉伸的情况。

  1. setVideoStabilization
Enables and disables video stabilization. Use isVideoStabilizationSupported() to determine if calling this method is valid. Video stabilization reduces the shaking due to the motion of the camera in both the preview stream and in recorded videos, including data received from the preview callback. It does not reduce motion blur in images captured with takePicture. Video stabilization can be enabled and disabled while preview or recording is active, but toggling it may cause a jump in the video stream that may be undesirable in a recorded video. 

官方文档上写着,这个方法可以帮助提高录制视频的稳定性。使用的时候通过 #isVideoStabilizationSupported 来判断是否可以使用。如果妄自使用的话,会造成页面黑屏,PreviewCallback 没有任何回调。这两个 API 都是官方文档中提及,但完全没有任何隐患说明的地方,Camera API 调用的坑可见一斑。

Camera 效果不一致

如果 UI 妹子对画面要求比较高,需要在各大手机品牌上取得一致效果,那对于 Android Developer 简直是一场灾难。例如同样的白平衡效果,在 google 旗舰机型 Pixel 2XL 与 Huawei Honor 的差异就很明显。一般对于 Android 端,我们不能强求一致的效果,而是要提供给用户足够的自由度,让他们在机器提供的能力范围内拍出较为满意的效果。

Oppo 的部分机型自带美颜效果,而其他较为老旧的机型则没有这样的功能,因而我们对于这些机型上的默认美颜处理可以有不同的策略。

并不是所有机型都对拍出的照片添加了 Exif 信息,所以我们不能默认照片都是竖直方向的。如果照片中含有 Exif,还是要根据这个来判断照片方向。

总结起来说,我们在使用 Android Camera API 时,需要对曝光、色温、快门这些基本的拍摄概念有一个了解,这样才能在遇到各种奇怪情况的时候找到合适的解决方案。

硬编硬解的若干坑

MediaCodec 不一定支持

首当其冲的就是 MediaCodec 不一定支持!特别是一些老旧机型比较突出,在引入 CTS 测试之前,那简直了(手动微笑)。建议在合适的地方,判断硬编硬解支持的程度。

这里列举出 CTS 中测试 MediaCodec 支持程度的链接, tests/tests/media/src/android/media/cts/EncodeDecodeTest.java - platform/cts - Git at Google ,大家可以参考这其中的代码来判断用户机型的支持程度。

如果机型不支持,大概率在创建 Encoder 的时候就会崩溃。

Surface 也不一定支持

MediaCodec 支持的数据类型中,有一项就是 Surface。Surface 直接使用 native 层的 Buffer,这样避免映射和拷贝,效率上能高不少。然而并不是每一种机型都支持 Surface 格式的。

Android 硬编硬解退坑指南

create inputsurface

我们可以在 createInputSurface 的时候 catch 下异常,如果代码上没有问题,那真的就是机型上不支持 Surface 了,那只能老老实实用 ByteBuffer 吧(手动扇子脸)。

虚晃一枪的 API

备注:笔者使用的是 Google Pixel 2XL (Version 8.1) 进行地测试。

编解码本身灵活性就相对欠缺,可配置的地方就少,但就算在这种情况下那些看上去不错的接口,很大概率上只是镜中月,水中花,梦里人。

  1. BitMode

    文档上写着三种支持三种码率模式,CQ的意思是尽量保证帧率,保证图片质量;CBR 则是尽量保证每一帧的码率,但在一些动作比较大的Video中,就很容易模糊;VBR 则是前两者之间一个中庸的方案。

    但是,绝大多数机型都只支持 VRB 一种。(如果有错误,欢迎指正)

    Android 硬编硬解退坑指南

    bit mode

  2. CodecLevel、CodecProfile

    设置这两个值,可以改变编码级别,不同编码级别得出的效果不一样,级别越高,效果越好。我们可以通过 ffmpeg,或者 mediaInfo 来查看视频的编码级别。笔者在 Pixel 2XL 支持的 level、profile 中,分别进行测试,发现所有视频编码出的效果,都是 Base Media/ Version 2 。又一个并没有什么卵用的 API,笔者只能认为这是 Google 为日后埋下的伏笔了。同理 getComplexityRange 这个 API,可以有 low、upper两种级别,但它们的值都是0,可能 low 和 upper 是双胞胎吧(手动扇子脸)。

Android 硬编硬解退坑指南

codec profile

隐式限制很多

MediaCodec 在 Configure 的过程中,可以设置各种各样的颜色格式。但实际上支持的种类非常有限,调用前一定要通过 getCapabilitiesForType 来确认下。

一般来说,绝大多数相机的 Preview 输出都支持 NV21,因此我们在使用 Camera API 的时候,可以放心地在 Camera#Parameters setPreviewFormat 使用 NV21 格式。然鹅,MediaCodec 不一定支持 NV21 哦!这些支持的格式里面,不同厂商表现不一样哦,高通支持的别家还真不一定支持。底层在使用的时候,一定要做好判断。忘了说啦, getCapabilitiesForType 这个 API 也要处理好异常(手动扇子脸 X3)。

写到这里,还需要额外指出一点,16位对齐的事情。软编软解的时候,可以放心使用 540 960 这样的分辨率,但在硬编硬解的时候,一定要用 544 960,如果没有16位对齐,才不说什么 MOTO 机型直接花屏给你看 的事情。

结语

出了上述的问题以外,其他 API 的限制(坑)都不少,例如 MediaMuxer 基本上和 MPEG-4 绑定死了。那这么说起来,硬编硬解在 Android 上是不是就不能用呢。其实也没那么不堪,在编解码速度上比软编软解快上不少,笔者简单进行了下对比,能快上50%(不具有参考性,机型越好,差距越少)。这里只是写一篇文章,分享下在实际开发中遇到的坑,给各位读者大大一点参考。

文档信息

Last updated:

Android 硬编硬解退坑指南


以上所述就是小编给大家介绍的《Android 硬编硬解退坑指南》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

赢在设计

赢在设计

[美] 洛芙迪 (Lance Loveday)、[美] 尼豪斯 (Sandra Niehaus) / 刘淼、枊靖、王卓昊 / 人民邮电出版社 / 2010-8 / 55.00

企业总是面临在网站设计和改进方面进行投资的抉择。怎样才能让有限的资金发挥出最大的效益呢?网站设计不应只是把网站做得赏心悦目,它更应该是提高经济收益和获得竞争优势的战略利器。是时候让网站发挥其潜能,以业务指标为导向来做设计决策,为提升网站收益而设计了。 作者凭借多年为众多网站做咨询工作的经验,为我们揭示了赢在设计的奥秘。它针对目前网站设计中存在的典型问题,先从宏观上探讨解决问题的战略手段,围绕......一起来看看 《赢在设计》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试