Android視頻錄製 花屏、綠屏的分析及解決方案

      人生苦短,不說廢話,不作無用功      java

      當咱們在用android 開發視頻錄製時候,會遇到錄製出來的視頻 花屏、綠屏等現象,不用懷疑,90%是由於視頻編碼時候的顏色格式和編碼器配置的編碼格式不匹配。android

相機預覽的數據通常是兩種 NV21和YV12,如下代碼能夠查出手機支持的預覽格式:編碼

List<Integer> previewFormats = mCamera.getParameters().getSupportedPreviewFormats();

手機MediaCodec編解碼顏色格式通常爲:spa

一、COLOR_FormatYUV420Planar
二、COLOR_FormatYUV420SemiPlanar

YUV420Planar支持的顏色格式通常也有兩種:NV2一、NV12orm

YUV420SemiPlanne支持的顏色格式通常也有兩種:I420、YV12視頻

對應關係以下:blog

I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP開發

 

用Camera攝像頭預覽的時候:get

這裏第一個參數data的數據格式,若是沒有特殊配置,android默認返回的是NV21格式,查看源碼能夠看到:源碼

因此若是相機支持YUV420SemiPlanne編碼格式,那麼NV21數據時沒問題的,若是不支持那麼須要將NV21的數據格式轉爲YUV420Planar所支持的

例如:

 public final static int NV21_TO_yuv420P(byte[] dst, byte[] src, int w, int h){
        int ysize = w * h;
        int usize = w * h * 1 / 4;

        byte[] dsttmp = dst;

        // y
        System.arraycopy(src, 0, dst, 0, ysize);

        // u, 1/4
        int srcPointer = ysize;
        int dstPointer = ysize;
        int count = usize;
        while (count > 0)
        {
            srcPointer++;
            dst[dstPointer] = src[srcPointer];
            dstPointer++;
            srcPointer++;
            count--;
        }

        // v, 1/4
        srcPointer = ysize;

        count = usize;
        while (count > 0)
        {
            dst[dstPointer] = src[srcPointer];
            dstPointer++;
            srcPointer += 2;
            count--;
        }

        dst = dsttmp;

        // _EF_TIME_DEBUG_END(0x000414141);

        return 0;
    }

  同時設置mediaCodec的顏色編碼格式:

 

mediaFormat_camera.setInteger(MediaFormat.KEY_COLOR_FORMAT,mColorFormat);
//mColorFormat能夠是 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar 或者 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar

 

  

 

    若是相機支持YUV420SemiPlanne編碼格式,那麼NV21須要轉爲NV12 不然會報錯

public static void NV21ToNV12(byte[] nv21,byte[] nv12,int width,int height) {
if (nv21 ==null || nv12 ==null)return;

int framesize = width * height;
int i =0, j =0;

System.arraycopy(nv21,0, nv12,0, framesize);

for (i =0; i < framesize; i++) {
nv12[i] = nv21[i];
}

for (j =0; j < framesize /2; j +=2) {
nv12[framesize + j -1] = nv21[j + framesize];
}

for (j =0; j < framesize /2; j +=2) {
nv12[framesize + j] = nv21[j + framesize -1];
    }
}
相關文章
相關標籤/搜索