視訊轉碼後有色差要如何處理呢?丨有問有答

語言: CN / TW / HK

今天我們要討論的是 關鍵幀的音視訊開發圈 的一位朋友在社群裡提的問題,如下:

遇到了視訊轉碼後有色差,這種一般如何處理呢?

以下是回答,歡迎大家留言討論補充:

1、色差是如何產生的?

1)有失真壓縮產生的質量損失。

  • 解決方法為儘可能的提高位元速率。

  • 可以使用 FFmpeg 指令檢視原位元速率與輸出位元速率對比,如果使用硬體編碼位元速率要高於原位元速率一些,因為原檔案可能使用了更高階的編碼方式(軟體編碼)或編碼引數(HEVC)。

2)顏色空間轉換產生的損失。

  • 解決方法為儘量避免顏色空間的轉換,如果必須轉換需要找到正確的顏色轉換矩陣。

  • 可以使用 FFmpeg 指令對比色差檔案與原檔案 color_rangecolor_space
$ ffprobe -show_streams -i test.mp4

2、如何做顏色空間轉換?

顏色空間轉換每個模組都會有所涉及,播放器、轉碼、獲取縮圖等,但按照底層模組劃分如下:

1)解碼模組:需要獲取出正確的 ColorSpaceColorRange ,然後傳遞給後面的模組。

  • CVPixelBuffer
    CVImageBufferYCbCrMatrix
    FullRange
    CVPixelBufferGetPixelFormatType(buffer) == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
    
  • MediaFormat
    KEY_COLOR_STANDARD
    KEY_COLOR_RANGE
    
  • FFmpeg 模組需要根據解碼後資料 AVFrame 獲取,ColorSpace 為 colorspace ,ColorRange 為 color_range

2)編碼模組:根據外層輸入的 ColorSpaceColorRange ,設定給編碼器即可。

  • iOS VideoToolBox 編碼設定與解碼相對應 kVTCompressionPropertyKey_YCbCrMatrix
  • Android 編碼設定與解碼相對應 KEY_COLOR_STANDARDKEY_COLOR_RANGE
  • FFmpeg X264 編碼設定 x264_param_t 內 vui.b_fullrangevui.i_colmatrix

3)YUV 資料轉換 RGBA 紋理模組。

  • 資料轉紋理主要涉及 GL 矩陣操作,根據解碼後的 ColorSpace 與 ColorRange 生成合適的矩陣。

  • GPUImage 矩陣生成,參考: GPUImage [1]

  • libyuv 矩陣生成(搜尋 『bt.』),參考: libyuv [2]

4)RGBA 紋理轉換 YUV 資料模組。

  • 紋理轉資料與資料轉紋理相反的流程,但具體轉換為哪種 ColorSpace 與 ColorRange 都可以的。

  • 參考 RGBA 轉 YUV 即可: RGB2YUV [3]

5)RGB 資料與 YUV 資料轉換模組。

  • libyuv
    I420ToARGBMatrix
    YuvConstants
    

3、其他建議

1)儘量減少自定義處理顏色空間轉換。

Android 平臺儘量使用 Surface 解碼與編碼,好處就是不需要手動處理。

2)ByteBuffer 編碼必須設定 ColorSpaceColorRange

如果不設定底層不清楚輸入進來的資料顏色格式,只能根據預設值隨意發揮了。

3) ColorSpaceColorRange 預設值。

  • 本地檔案 ColorSpace 為空,則直接預設為 601 即可。
  • 本地檔案 ColorRange 為空,則直接預設為非 FullRange

如果你也對音視訊技術感興趣,比如,符合下面的情況:

  • 在校大學生 → 學習音視訊開發

  • iOS/Android 客戶端開發 → 轉入音視訊領域

  • 直播/短視訊業務開發 → 深入音視訊底層 SDK 開發

  • 音視訊 SDK 開發 → 提升技能,解決優化瓶頸

可以長按識別或掃描下面二維碼,瞭解一下這個社群,根據自己的情況按需加入:

識別二維碼加入我們

參考資料

[1]

CPUImage: http://github.com/BradLarson/GPUImage/blob/master/framework/Source/GPUImageColorConversion.m

[2]

libyuv: http://github.com/lemenkov/libyuv/blob/master/source/row_common.cc

[3]

RGB2YUV: http://en.wikipedia.org/wiki/YUV#Y%E2%80%B2UV444_to_RGB888_conversion