Android 硬编硬解退坑指南

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

原文链接: https://mp.weixin.qq.com/s/SqP-AcEh5EMbkVDP83cCrw


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 部分手机)上造成拉伸的后果。


图片来源于网络

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 格式的。

create inputsurface

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

虚晃一枪的 API

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

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

  1. BitMode
    文档上写着三种支持三种码率模式,CQ的意思是尽量保证帧率,保证图片质量;CBR 则是尽量保证每一帧的码率,但在一些动作比较大的Video中,就很容易模糊;VBR 则是前两者之间一个中庸的方案。
    但是,绝大多数机型都只支持 VRB 一种。(如果有错误,欢迎指正)


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

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%(不具有参考性,机型越好,差距越少)。这里只是写一篇文章,分享下在实际开发中遇到的坑,给各位读者大大一点参考。


文档信息


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容