Android 硬編硬解退坑指南

抖音刃滓、快手在國內(nèi)迅速走紅仁烹,也帶動了國內(nèi)短視頻的熱潮。短視頻錄制咧虎、編輯等等功能卓缰,是一項系統(tǒng)性、專業(yè)性很強(qiáng)的領(lǐng)域砰诵。經(jīng)過一段時間發(fā)展后征唬,有多種方式可以通向羅馬,但并不是每一條路都好走茁彭。這篇文章將重點(diǎn)介紹下总寒,硬編硬解過程中遇到的坑,也給讀者朋友架構(gòu)方案時提供一點(diǎn)參考理肺。

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


Camera 使用的坑

雖然和硬編硬解沒有關(guān)系摄闸,但短視頻客戶端不可能繞過這個,這里也列舉下我所遇到的問題哲嘲。

API 使用上的一些坑

Camera API 是 Android 碎片化嚴(yán)重的體現(xiàn)贪薪,不同于 iOS 系列,一共就那幾種機(jī)型眠副。Android 廠商眾多画切,ROM 也百花齊放,同樣的 API 在不同機(jī)型上提現(xiàn)可能完全不同囱怕,也是我們需要在開發(fā)過程中留意的霍弹。下面簡單列舉兩個可能會導(dǎo)致畫面異常的 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耍缴,但實(shí)際上卻暗藏殺機(jī)砾肺。此方法需要你設(shè)置 video-size,如果不設(shè)置這個防嗡,將會在某些機(jī)型(OPPO A37f, MI 2 , LG 部分手機(jī))上造成拉伸的后果变汪。


圖片來源于網(wǎng)絡(luò)

RecordingHint 的目的是幫助更快速地進(jìn)行錄制,某些 ROM 在實(shí)現(xiàn)的時候蚁趁,沒有考慮到 Preview Size 和 Video Size 之間的區(qū)別裙盾,例如使用 480 * 864 的分辨率進(jìn)行錄制,輸出的文件大小為 400 * 800他嫡,那么勢必會使得整體畫面出現(xiàn)拉伸的情況番官。

  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.

官方文檔上寫著,這個方法可以幫助提高錄制視頻的穩(wěn)定性钢属。使用的時候通過 #isVideoStabilizationSupported 來判斷是否可以使用徘熔。如果妄自使用的話,會造成頁面黑屏淆党,PreviewCallback 沒有任何回調(diào)近顷。這兩個 API 都是官方文檔中提及,但完全沒有任何隱患說明的地方宁否,Camera API 調(diào)用的坑可見一斑。

Camera 效果不一致

如果 UI 妹子對畫面要求比較高缀遍,需要在各大手機(jī)品牌上取得一致效果慕匠,那對于 Android Developer 簡直是一場災(zāi)難。例如同樣的白平衡效果域醇,在 google 旗艦機(jī)型 Pixel 2XL 與 Huawei Honor 的差異就很明顯台谊。一般對于 Android 端,我們不能強(qiáng)求一致的效果譬挚,而是要提供給用戶足夠的自由度锅铅,讓他們在機(jī)器提供的能力范圍內(nèi)拍出較為滿意的效果。

Oppo 的部分機(jī)型自帶美顏效果减宣,而其他較為老舊的機(jī)型則沒有這樣的功能盐须,因而我們對于這些機(jī)型上的默認(rèn)美顏處理可以有不同的策略。

并不是所有機(jī)型都對拍出的照片添加了 Exif 信息漆腌,所以我們不能默認(rèn)照片都是豎直方向的贼邓。如果照片中含有 Exif阶冈,還是要根據(jù)這個來判斷照片方向。

總結(jié)起來說塑径,我們在使用 Android Camera API 時女坑,需要對曝光、色溫统舀、快門這些基本的拍攝概念有一個了解匆骗,這樣才能在遇到各種奇怪情況的時候找到合適的解決方案。


硬編硬解的若干坑

MediaCodec 不一定支持

首當(dāng)其沖的就是 MediaCodec 不一定支持誉简!特別是一些老舊機(jī)型比較突出碉就,在引入 CTS 測試之前,那簡直了(手動微笑)描融。建議在合適的地方铝噩,判斷硬編硬解支持的程度。

這里列舉出 CTS 中測試 MediaCodec 支持程度的鏈接窿克,tests/tests/media/src/android/media/cts/EncodeDecodeTest.java - platform/cts - Git at Google骏庸,大家可以參考這其中的代碼來判斷用戶機(jī)型的支持程度。 如果機(jī)型不支持年叮,大概率在創(chuàng)建 Encoder 的時候就會崩潰具被。

Surface 也不一定支持

MediaCodec 支持的數(shù)據(jù)類型中,有一項就是 Surface只损。Surface 直接使用 native 層的 Buffer一姿,這樣避免映射和拷貝,效率上能高不少跃惫。然而并不是每一種機(jī)型都支持 Surface 格式的叮叹。

create inputsurface

我們可以在 createInputSurface 的時候 catch 下異常,如果代碼上沒有問題爆存,那真的就是機(jī)型上不支持 Surface 了蛉顽,那只能老老實(shí)實(shí)用 ByteBuffer 吧(手動扇子臉)。

虛晃一槍的 API

備注:筆者使用的是 Google Pixel 2XL (Version 8.1) 進(jìn)行地測試先较。

編解碼本身靈活性就相對欠缺携冤,可配置的地方就少,但就算在這種情況下那些看上去不錯的接口闲勺,很大概率上只是鏡中月曾棕,水中花,夢里人菜循。

  1. BitMode
    文檔上寫著三種支持三種碼率模式翘地,CQ的意思是盡量保證幀率,保證圖片質(zhì)量;CBR 則是盡量保證每一幀的碼率子眶,但在一些動作比較大的Video中瀑凝,就很容易模糊;VBR 則是前兩者之間一個中庸的方案臭杰。
    但是粤咪,絕大多數(shù)機(jī)型都只支持 VRB 一種。(如果有錯誤渴杆,歡迎指正)


    bit mode
  2. CodecLevel寥枝、CodecProfile
    設(shè)置這兩個值,可以改變編碼級別磁奖,不同編碼級別得出的效果不一樣囊拜,級別越高,效果越好比搭。我們可以通過 ffmpeg冠跷,或者 mediaInfo 來查看視頻的編碼級別。筆者在 Pixel 2XL 支持的 level身诺、profile 中蜜托,分別進(jìn)行測試,發(fā)現(xiàn)所有視頻編碼出的效果霉赡,都是 Base Media/ Version 2橄务。又一個并沒有什么卵用的 API,筆者只能認(rèn)為這是 Google 為日后埋下的伏筆了穴亏。同理 getComplexityRange 這個 API蜂挪,可以有 low、upper兩種級別嗓化,但它們的值都是0棠涮,可能 low 和 upper 是雙胞胎吧(手動扇子臉)。

codec profile

隱式限制很多

MediaCodec 在 Configure 的過程中刺覆,可以設(shè)置各種各樣的顏色格式故爵。但實(shí)際上支持的種類非常有限,調(diào)用前一定要通過 getCapabilitiesForType來確認(rèn)下隅津。

一般來說,絕大多數(shù)相機(jī)的 Preview 輸出都支持 NV21劲室,因此我們在使用 Camera API 的時候伦仍,可以放心地在 Camera#Parameters setPreviewFormat 使用 NV21 格式。然鵝很洋,MediaCodec 不一定支持 NV21 哦充蓝!這些支持的格式里面,不同廠商表現(xiàn)不一樣哦,高通支持的別家還真不一定支持谓苟。底層在使用的時候官脓,一定要做好判斷。忘了說啦涝焙, getCapabilitiesForType這個 API 也要處理好異常(手動扇子臉 X3)卑笨。

寫到這里,還需要額外指出一點(diǎn)仑撞,16位對齊的事情赤兴。軟編軟解的時候,可以放心使用 540 * 960 這樣的分辨率隧哮,但在硬編硬解的時候桶良,一定要用 544 * 960,如果沒有16位對齊沮翔,才不說什么 MOTO 機(jī)型直接花屏給你看 的事情陨帆。


結(jié)語

出了上述的問題以外,其他 API 的限制(坑)都不少采蚀,例如 MediaMuxer 基本上和 MPEG-4 綁定死了疲牵。那這么說起來,硬編硬解在 Android 上是不是就不能用呢搏存。其實(shí)也沒那么不堪瑰步,在編解碼速度上比軟編軟解快上不少,筆者簡單進(jìn)行了下對比璧眠,能快上50%(不具有參考性缩焦,機(jī)型越好,差距越少)责静。這里只是寫一篇文章袁滥,分享下在實(shí)際開發(fā)中遇到的坑,給各位讀者大大一點(diǎn)參考灾螃。


文檔信息


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末题翻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子腰鬼,更是在濱河造成了極大的恐慌嵌赠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熄赡,死亡現(xiàn)場離奇詭異姜挺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)彼硫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門炊豪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凌箕,“玉大人,你說我怎么就攤上這事词渤∏2眨” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵缺虐,是天一觀的道長芜壁。 經(jīng)常有香客問我,道長志笼,這世上最難降的妖魔是什么沿盅? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮纫溃,結(jié)果婚禮上腰涧,老公的妹妹穿的比我還像新娘。我一直安慰自己紊浩,他們只是感情好窖铡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坊谁,像睡著了一般费彼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上口芍,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天箍铲,我揣著相機(jī)與錄音,去河邊找鬼鬓椭。 笑死颠猴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的小染。 我是一名探鬼主播翘瓮,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裤翩!你這毒婦竟也來了资盅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤踊赠,失蹤者是張志新(化名)和其女友劉穎呵扛,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筐带,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡今穿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了烫堤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鸽斟,靈堂內(nèi)的尸體忽然破棺而出拔创,到底是詐尸還是另有隱情,我是刑警寧澤富蓄,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布剩燥,位于F島的核電站,受9級特大地震影響立倍,放射性物質(zhì)發(fā)生泄漏灭红。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一口注、第九天 我趴在偏房一處隱蔽的房頂上張望变擒。 院中可真熱鬧,春花似錦寝志、人聲如沸娇斑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毫缆。三九已至,卻和暖如春乐导,著一層夾襖步出監(jiān)牢的瞬間苦丁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工物臂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旺拉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓鹦聪,卻偏偏與公主長得像账阻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泽本,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容