Android硬編轉(zhuǎn)碼相關(guān)問(wèn)題

Android MediaCodec轉(zhuǎn)碼相關(guān)問(wèn)題


最近在測(cè)試各種編碼的性能的時(shí)候涉及到了android硬編,由于測(cè)試的指標(biāo)有PSNR、SSIM等質(zhì)量指標(biāo),中間遇到了一些坑,稍微記錄一下。

硬編的常見用法

大多數(shù)實(shí)際工程中,硬解或者硬編都是通過(guò)Surface中轉(zhuǎn)來(lái)做的,經(jīng)過(guò)Surface我們可以做很多事情,比如這個(gè)Surface可以是SurfaceView的Surface,或者我們想用Opengl作一些事情,加濾鏡或者編輯視頻,Surface的方式都提供了方便的解決方式,這也是我們搜索MediaCodec,最常見的使用方式。bigflake(http://bigflake.com/mediacodec)列舉出了很多示例代碼,其中有一個(gè)google CTS代碼DecodeEditEncode對(duì)于Surface的使用給出了很好的例子。

如果我們想做一個(gè)硬解硬編的加速轉(zhuǎn)碼(至少相較ffmpeg軟解軟編還是快一些的),可以參考github項(xiàng)目android-transcoder,這里給出了比較完整的transcode的示例,但是真正想用起來(lái)還是需要不少改動(dòng)的,比如給出的Strategy只支持幾個(gè)簡(jiǎn)單的比例,Cancel接口有些問(wèn)題,這里不具體說(shuō)了。

我最初測(cè)試的有一個(gè)很主要的目的是測(cè)試PSNR等指標(biāo),最初使用了ypresto的demo,但是最終得到的結(jié)果總是特別差,比如x264轉(zhuǎn)碼psnr能維持在40db的情況,經(jīng)過(guò)Surface android硬解然后硬編基本智能再25db左右(我們最終對(duì)比PSNR是將結(jié)果mp4解碼為YUV,然后直接再YUV三個(gè)channel上計(jì)算平均PSNR)。但是肉眼看起來(lái)其實(shí)硬編結(jié)果和x264甚至和原視頻相差并不大,

硬編轉(zhuǎn)碼PSNR很低的問(wèn)題所在

想到自己平時(shí)寫shader用gpu加速來(lái)進(jìn)行yuv轉(zhuǎn)rgb的時(shí)候用到了yuv轉(zhuǎn)RGB的轉(zhuǎn)換公式,可以參考另外一篇記錄color space2中YUV families的介紹,或者直接看一個(gè)綜合的整理的bt601 & bt709 color matrix,比如bt601 tv range的YUV轉(zhuǎn)RGB的公式為:

bt601 tv range YUV2RGB

bt601 tv range RGB2YUV

看一下這里的YUV2RGB的轉(zhuǎn)換公式,得到的RGB是可能有負(fù)值的,比如0, 255, 255得到的RGB就是負(fù)值,這里可能有人會(huì)說(shuō)這個(gè)公式是針對(duì)tv range(也有叫studio range的,就是Y 16-235,UV 16-240),我說(shuō)一下原因:

  • 1,很多情況下尤其是國(guó)內(nèi)的很多廠商錄制出來(lái)的視頻根本不帶著color range信息,即使帶著,經(jīng)過(guò)各種渠道的轉(zhuǎn)存流轉(zhuǎn),基本什么信息也都沒(méi)有了
  • 2,實(shí)際上硬解中是有KEY_COLOR_RANGE參數(shù)的,能設(shè)置兩種值COLOR_RANGE_FULL和COLOR_RANGE_LIMITIED,就是對(duì)應(yīng)著full range和tv range,但是更坑爹的是很多國(guó)內(nèi)廠商根本沒(méi)有做實(shí)現(xiàn)。這里表?yè)P(yáng)一下良心華為,錄制出來(lái)的視頻都有著完整的color range、color space、color transfer信息,華為錄制出來(lái)的基本都是tv range視頻,在<=480p的時(shí)候使用bt601,否則使用HDTV標(biāo)準(zhǔn)bt709,蘋果錄制出來(lái)的m4v文件也是比較良心的。測(cè)試了vivo x7錄制出來(lái)的視頻這幾個(gè)信息都是空著的,難道公司的主要精力都放在了“2000W柔光自拍”上?
  • 3,即使我們使用tv range內(nèi)的YUV值,比如(16,240,240)也會(huì)算出來(lái)的Green是負(fù)值。其實(shí)tv range中的很多YUV值都會(huì)算出來(lái)RGB值是負(fù)的

回歸正題,我們顯示任何東西,最終都是以RGB的形式顯示的,也就是說(shuō)我們?cè)赟urface中的顯示也是RGBA的color space,但是實(shí)際上上RGBA的值都必須是正值,負(fù)值是無(wú)法顯示的,所以我們自己寫shader的時(shí)候或者直接交給Surface處理的時(shí)候,需要對(duì)RGBA的值做clamp處理,裁剪到0-255范圍內(nèi),也就是負(fù)值變成0,超過(guò)255的變成255。然后我們對(duì)這個(gè)clamp以后的RGB值如果再轉(zhuǎn)回YUV值,就跟原始的YUV值相差比較大了。有人會(huì)覺(jué)得這樣不會(huì)變色了嗎?其實(shí)并不會(huì)!舉個(gè)例子:

以yuv(0,0,0)為例(也可以拿16,240,240試試)
1. 先減128 。 (0,-128,-128)
2. 轉(zhuǎn)換為RGB并作clamp  RGB (-179.456,135.424,-226.816)->(0,135,0)
3. 轉(zhuǎn)YUV (79.245,-44.685,-56.565)
4. 色度加128 YUV(79.245,83.315,71.435)
5. 取整,YUV(79,83,71)  轉(zhuǎn)換完畢的值
再轉(zhuǎn)回去:
6. 先減128  YUV (79,-45,-57)
7. 轉(zhuǎn)換為RGB并作clamp  RGB (-0.914,135.178,-0.74)->(0,135,0)
我們發(fā)現(xiàn)顏色是一樣的,再轉(zhuǎn)一下,看看YUV還會(huì)不會(huì)變化
8. 轉(zhuǎn)YUV (79.245,-44.685,-56.565)
9. 色度加128 YUV(79.245,83.315,71.435)
10. 得到Y(jié)UV(79,83,71)  轉(zhuǎn)換完畢的值

上面這個(gè)例子我們發(fā)現(xiàn)(0,0,0) (79,83,71)實(shí)際對(duì)應(yīng)的RGB是一樣的,也就是人眼看起來(lái)是一樣的。但是這樣的處理過(guò)程對(duì)我們比較PSNR造成了很大的問(wèn)題,計(jì)算出來(lái)的PSNR很低。x264進(jìn)行轉(zhuǎn)碼卻不會(huì)有這個(gè)問(wèn)題,還沒(méi)有自習(xí)看ff和x264轉(zhuǎn)碼的源碼,有待確認(rèn)具體是怎么個(gè)實(shí)現(xiàn),猜測(cè)是沒(méi)有對(duì)RGB做clamp,或者根本沒(méi)有中轉(zhuǎn)RGB。

其他方式做轉(zhuǎn)碼

在api 21后,android提供了Image類來(lái)做硬解的輸出和硬編的輸入,Image類基本類似于ffmpeg的AVFrame,里面包含幀圖像的各種信息和各個(gè)plane,以及stride、width、height、crop x、crop y等信息,也就是說(shuō)我們可以從Image中得到decode以后的YUV raw data,我們可以這樣的到decode 出來(lái)的Image:

int result = mDecoder.dequeueOutputBuffer(mBufferInfo, timeout);
Image image = mDecoder.getOutputImage(result);

對(duì)于decode以后直接存儲(chǔ)為YUV raw data file可以參考VideoToFrames github code(對(duì)應(yīng)的博客是android高效解碼得到Y(jié)UV file)

未完待續(xù)


References

  1. Image class & YUV_420_888
  2. YUV_420_888 convert to NV21 & I420
  3. Anroid MediaCodec stuffs
  4. VideoEncoderDecoderTest
  5. Camera and MediaCodec colorspace not match, with images, stack over flow issue
  6. color format of camera and mediacodec, google disscuss
  7. CTS samples EncodeDecodeTest
  8. How to get stride of encoder
  9. ffmpeg command: how to convert to YUV file and how to display it
  10. VideoToYUVFrames github sample code
  11. Android MediaCodec transcoder sample demo, with surface
  12. NV21 NV12 I420 YV12
  13. CTS codecUtils
  14. google CTS
  15. YUV RGB convert
  16. android mediacodec color formats
  17. CTS code: DecodeEditEncodeTest
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,687評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評(píng)論 2 374

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

  • 原文地址 Android MediaCodec stuff 這篇文章是關(guān)于 MediaCodec 這一系列類,它主...
    sheepm閱讀 68,661評(píng)論 17 102
  • MediaCodec的官方文檔 一、Android MediaCodec簡(jiǎn)單介紹 Android中可以使用Medi...
    黃海佳閱讀 6,192評(píng)論 1 16
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,661評(píng)論 25 708
  • 一、文章說(shuō)明 最近工作實(shí)在太忙,很久沒(méi)有更新文章了,收到很多小伙伴催更的消息,心中實(shí)在慚愧,趁著今天有空趕緊更新。...
    風(fēng)從影閱讀 18,915評(píng)論 33 118
  • 昨天是陶藝培訓(xùn)第一天,本想昨晚睡覺(jué)前總結(jié)的,可惜累癱了,躺在床上動(dòng)都不想動(dòng)~昨天的課程內(nèi)容安排的不算多,三大塊——...
    美禾hm閱讀 395評(píng)論 0 1