【问题标题】:How to Convert YV12 to COLOR_FormatYUV420SemiPlanar?如何将 YV12 转换为 COLOR_FormatYUV420SemiPlanar?
【发布时间】:2017-04-12 17:57:23
【问题描述】:

我正在尝试使用 MediaCodec 和相机 (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;
}

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

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

注意:我知道 COLOR_FormatSurface,但我需要在 API 16 上完成这项工作。

【问题讨论】:

    标签: android video-capture android-mediacodec color-space


    【解决方案1】:

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

    public static byte[] YV12toYUV420PackedSemiPlanar(final byte[] input, final  byte[] output, final int width, final int height) {
        final int frameSize = width * height;
        final int alignedFrameSize = (frameSize + 2047)/2048*2048;
        final int qFrameSize = frameSize / 4;
    
        System.arraycopy(input, 0, output, 0, frameSize); // Y
    
        for (int i = 0; i < qFrameSize; i++) {
            output[alignedFrameSize + i * 2] = input[frameSize + i + qFrameSize]; // Cb (U)
            output[alignedFrameSize + i * 2 + 1] = input[frameSize + i]; // Cr (V)
        }
        return output;
    }
    

    这是一个众所周知的问题;在 Android 4.3 之前,编码器的输入格式并没有真正经过严格测试,因此编码器基本上可以为所欲为。 (请注意,三星的编码器会表现得更糟。)请参阅 https://code.google.com/p/android/issues/detail?id=37769 了解其他已知问题的集合。

    【讨论】:

    • 感谢您的回复,但不幸的是,这并没有解决问题。我添加了一些关于设备和框架尺寸的规范(编辑 2)。结果看起来完全一样,我也读到这个对齐问题不影响 720p 视频。 stackoverflow.com/questions/20699009/…
    • 您显然遇到了某种问题,即您没有从 UV 平面上的正确位置开始。您为该帧接收了多少字节的数据?正好是1280*720*1.5吗?
    【解决方案2】:

    你可以试试这个

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-08-04
      • 2022-01-12
      • 2017-06-19
      • 2012-02-17
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多