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

时间:2017-08-06 23:00:48

标签: android rgb framebuffer mediacodec yuv

鉴于两个编码流,我想并排加入它们。假设我有两个独立的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)

谢谢!

2 个答案:

答案 0 :(得分:1)

解码后的帧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框架宽度的一半和高度的一半。

答案 1 :(得分:0)

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

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

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