Mediacodec and camera, color space incorrect

前端 未结 2 1667
春和景丽
春和景丽 2021-02-03 14:59

By referring Aegonis\'s work 1 and work 2, I also got the H.264 stream , but the color is not correct. I am using HTC Butterfly for development. Here is part of my code:

相关标签:
2条回答
  • 2021-02-03 15:26

    Got it, now the color looks good, the test is based on HTC Butterfly. When set the resolution to 320x240, your color transform should looks like:

        System.arraycopy(input, 0, output, 0, frameSize);
        for (int i = 0; i < (qFrameSize); i++) {  
            output[frameSize + i*2] = (input[frameSize + qFrameSize + i - 32 - 320]);  
            output[frameSize + i*2 + 1] = (input[frameSize + i - 32 - 320]);            
        }
    

    for resolution 640x480 and above,

    System.arraycopy(input, 0, output, 0, frameSize);    
        for (int i = 0; i < (qFrameSize); i++) {  
            output[frameSize + i*2] = (input[frameSize + qFrameSize + i]);  
            output[frameSize + i*2 + 1] = (input[frameSize + i]);   
        } 
    

    For the frame rate issue, we can use the getSupportedPreviewFpsRange() to check the supported frame rate range of our device as:

    List<int[]> fpsRange = parameters.getSupportedPreviewFpsRange();
    for (int[] temp3 : fpsRange) {
    System.out.println(Arrays.toString(temp3));}
    

    And the following setting works correct when play the encoded H.264 ES,

    parameters.setPreviewFpsRange(29000, 30000);    
    //parameters.setPreviewFpsRange(4000,60000);//this one results fast playback when I use the FRONT CAMERA 
    
    0 讨论(0)
  • 2021-02-03 15:31

    After reading this discussion it turns out that more generalised way for encoding frames of various resolutions is to align chroma plane by 2048 bytes before sending frame to the MediaCodec. This is actual for QualComm (OMX.qcom.video.encoder.avc) encoder which I believe HTC Butterfly has, but still does not works well for all resolutions. 720x480 and 176x144 are still have chroma plane misaligned according to the output video. Also, avoid resolutions which sizes can't be divided by 16.

    The transformation is pretty simple:

    int padding = 0;
    if (mediaCodecInfo.getName().contains("OMX.qcom")) {
      padding = (width * height) % 2048;
    }
    byte[] inputFrameBuffer = new byte[frame.length];
    byte[] inputFrameBufferWithPadding = new byte[padding + frame.length];
    
    ColorHelper.NV21toNV12(frame, inputFrameBuffer, width, height);
    # copy Y plane
    System.arraycopy(inputFrameBuffer, 0, inputFrameBufferWithPadding, 0, inputFrameBuffer.length);
    int offset = width * height;
    # copy U and V planes aligned by <padding> boundary
    System.arraycopy(inputFrameBuffer, offset, inputFrameBufferWithPadding, offset + padding, inputFrameBuffer.length - offset);
    
    0 讨论(0)
提交回复
热议问题