如何将YV12转换为COLOR_FormatYUV420SemiPlanar?

时间:2015-12-08 00:05:25

标签: android video-capture mediacodec color-space

我正在尝试使用MediaCodec和Camera(onPreviewFrame)对.h264视频进行编码。我无法将色彩空间从YV12(从相机)转换为COLOR_FormatYUV420SemiPlanar(编码器需要)。

编辑:我注意到这可能是MediaCodec上的一个错误,因为以下代码适用于其他设备:

public static byte[] YV12toYUV420PackedSemiPlanar(final byte[] input, final  byte[] output, final int width, final int height) {
    /*
     * COLOR_TI_FormatYUV420PackedSemiPlanar is NV12
     * We convert by putting the corresponding U and V bytes together (interleaved).
     */
    final int frameSize = width * height;
    final int qFrameSize = frameSize / 4;

    System.arraycopy(input, 0, output, 0, frameSize); // Y

    for (int i = 0; i < qFrameSize; i++) {
        output[frameSize + i * 2] = input[frameSize + i + qFrameSize]; // Cb (U)
        output[frameSize + i * 2 + 1] = input[frameSize + i]; // Cr (V)
    }
    return output;
}

这是我得到的结果(似乎颜色位有一些偏移):

enter image description here

编辑2:帧大小为1280x720,设备为三星s5(SM-G900V),OMX.qcom.video.encoder.avc运行Android Lollipop 5.0(API 21)。

注意:我了解COLOR_FormatSurface但我需要在API 16上完成这项工作。

2 个答案:

答案 0 :(得分:0)

如果在Android 4.3之前在Qualcomm设备上运行,则需要将U / V平面的起点与2048字节边界对齐。这样的事情可能有用:

$(document).ready(function() {
 $('a#staff_info').click(function(e){ //link to page-2.php
  e.preventDefault();
  var page = $(this).attr('href');
  $('#content').load(page);
  $('a#upd_staff').click(function(){ //link on page2.php 
     var page_info = $('a#upd_staff').attr('href');
     $('#content').load(page_info);
  });   
 }); 
});

这是一个非常着名的问题;在Android 4.3之前,编码器的输入格式并没有经过严格的测试,因此编码器基本上可以做任何他们想做的事情。 (请注意,三星的编码器会表现得更糟。)有关其他已知问题的集合,请参阅https://code.google.com/p/android/issues/detail?id=37769

答案 1 :(得分:0)

你可以试试这个

public byte[] YV12toYUV420PackedSemiPlanar(final byte[] input, final byte[] output, final int width, final int height)
{
    for (int i = 0; i < height; i++)
        System.arraycopy(input, yStride * i, output, yStride * i, yStride); // Y

    for (int i = 0; i < halfHeight; i++) {
        for (int j = 0; j < halfWidth; j++) {
            output[ySize + (i * halfWidth + j) * 2] = input[ySize + cSize + i * cStride + j]; // Cb (U)
            output[ySize + (i * halfWidth + j) * 2 + 1] = input[ySize + i * cStride + j]; // Cr (V)
        }
    }

    return output;
}