解码后并排显示视频帧 (Android)

Showing video frames side by side after decoding (Android)

给定两个编码流,我想并排加入它们。假设我有两个具有相同帧速率的独立 H.264 编码的 1024x768 视频。我想将这两个组合起来,使视频 1 和视频 2 并排形成一个双倍宽度 (1024*2)x768 或 2048x768 的流。我的第一个想法是解码流并组合各个帧,然后重新编码单个流。解码和重新编码都很好,但它工作得非常慢(就像 ffmpeg 一样)。问题似乎在于将帧从 YUV 转换为 RGB 或将它们组合成 YUV 形式的计算时间。 Android 解码器产生 YUV,并且用于并排组合帧的数学对于该形式来说是密集的。所以我的问题是;

1) 如果帧是 YUV 格式,有没有更快或更有效的方法来合并帧?

2a) 如果不是,如果它们是 RGB 形式,那么合并它们在计算上是否更快?

2b) 如果是这样,我如何将 H.264 流解码为 Android 中的 RGB 帧?

P.S。尝试过的 ffmpeg 和 openCV 都需要 YUV 到 RGB 的转换,这使得它非常慢(~5fps)

谢谢!

组合这些图像需要什么复杂的数学运算?

您需要做的就是将 frameOfVideo1 中的每一行复制到索引 0 到 1023,并将 frameOfVideo2 中的每一行复制到索引 1024 到 2047。 (组合图像的线)

(这些是y平面的索引。u,v平面或uv平面(例如nv12)数字不同。但概念相同)

解码帧AVFrame在结构中有uint_t *data[]int linesize[]。一个 YUV 帧有三个数据指针和三个线宽。线条尺寸通常大于宽度,因此请注意考虑到这一点。

下面是一些可能有用的伪代码。希望没有太多错别字。

// No proper checks in here, it's just for reference
// You could just as easily pass the data pointers for the outframe as uint8_t *data[]

void mergeFrames(AVFrame *frame1, AVFrame *frame2, AVFrame *outframe)
{
    // do Y frame
    uint32_t *out = outframe->data[0]; // 1 and 2 are for the U and V frames

    uint8_t *in1 = frame1->data[0];
    uint8_t *in2 = frame2->data[0];

    int height = outframe->height;
    int inwidth = frame1->width;
    int stride = frame1->linesize[0];
    int pos = 0;

    while (pos++ < height) {
        // left side

        uint32_t *in = (uint32_t*)(in1 + pos * stride); // <- stride, not width

        int c = frame1->width >> 2; // assume 4 bytes
        while (c--) *out++ = *in++;

        // right side

        in = (uint32_t*)(in2 + pos * stride);

        c = width >> 2;
        while (c--) *out++ = *in++;
    }

    // And the same for the U and V frames
}

编译器应该会很好地优化它。

另请注意,在使用 U 和 V 框架时,它们是 Y 框架宽度和高度的一半。