3

因此,对于我最后一年的项目,我使用 Video4Linux2 从相机中提取 YUV420 图像,将它们解析为 x264(本机使用这些图像),然后通过 Live555 将编码流发送到兼容 RTP/RTCP 的视频播放器通过无线网络在客户端上。所有这些我都试图实时完成,所以会有一个控制算法,但这不是这个问题的范围。所有这些——除了 Live555——都是用 C 语言编写的。目前,我的视频编码接近尾声,但想要提高性能。

至少可以说,我遇到了一个障碍……我试图避免 V4L2 的用户空间指针并使用 mmap()。我正在编码视频,但由于它是 YUV420,我一直在分配新内存以将 Y'、U 和 V 平面保存在三个不同的变量中,以供 x264 读取。我想将这些变量保留为指向 mmap'ed 内存的指针。

但是,V4L2 设备有一个用于缓冲流的文件描述符,我需要将流拆分为三个符合 YUV420 标准的 mmap 变量,就像这样......

buffers[n_buffers].y_plane = mmap(NULL, (2 * width * height) / 3,
                                    PROT_READ | PROT_WRITE, MAP_SHARED,
                                    fd, buf.m.offset);
buffers[n_buffers].u_plane = mmap(NULL, width * height / 6,
                                    PROT_READ | PROT_WRITE, MAP_SHARED,
                                    fd, buf.m.offset +
                                    ((2 * width * height) / 3 + 1) /
                                    sysconf(_SC_PAGE_SIZE));
buffers[n_buffers].v_plane = mmap(NULL, width * height / 6,
                                    PROT_READ | PROT_WRITE, MAP_SHARED,
                                    fd, buf.m.offset +
                                    ((2 * width * height) / 3 + 
                                    width * height / 6 + 1) / 
                                    sysconf(_SC_PAGE_SIZE));

其中“宽度”和“高度”是视频的分辨率(例如 640x480)。

据我了解... MMAP 寻找一个文件,有点像这样(伪代码):

fd = v4l2_open(...);
lseek(fd, buf.m.offset + (2 * width * height) / 3);
read(fd, buffers[n_buffers].u_plane, width * height / 6);

我的代码位于此处的 Launchpad 存储库中(更多背景信息): http ://bazaar.launchpad.net/~alex-stevens/+junk/spyPanda/files (修订版 11)

从这个 Wiki 插图中可以清楚地看到 YUV420 格式:http://en.wikipedia.org/wiki/File: Yuv420.svg(我基本上想将 Y、U 和 V 字节分成每个 mmap 的记忆)

任何人都愿意解释一种将三个变量从一个文件描述符映射到内存的方法,或者为什么我出错了?或者甚至暗示将 YUV420 缓冲区解析为 x264 的更好主意?:P

干杯! ^^

4

2 回答 2

3

不需要三个单独mmap的 s。只需mmap一次,然后计算每个平面相对于整个地图的基指针的基指针。

编辑:你需要这样的东西:

unsigned char *y = mmap(...); /* map total size of all 3 planes */
unsigned char *u = y + y_height*y_bytes_per_line;
unsigned char *v = u + u_height*u_bytes_per_line;
于 2011-06-09T13:42:33.753 回答
1

如果我明白你想要什么:你不能将 mmap 'uninterleave' 顺序内存变成单独的指针。您必须映射单个内存块并手动计算缓冲区内的适当偏移量吗?

(但是:绝对没有理由不能多次映射同一个 fd。你从来没有说过出了什么问题。)

于 2011-06-09T13:09:54.320 回答