2011-06-09 51 views
3

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

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

然而,V4L2设备具有的缓冲流一个单一的文件描述符,我需要到流分为三个mmap'ed变量秉承YUV420标准,像这样......

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旨在通过文件,有点像这个(pseudoish码):

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)

而且YUV420格式可以清楚地从该维基图示可以看出:http://en.wikipedia.org/wiki/File:Yuv420.svg(I基本上要拆分了的Y,U和V字节到每个映射的内存)

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

干杯! ^^

回答

3

没有必要为三个独立的mmap秒。只需要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; 
+0

那么,我将如何拥有三个基本指针,指向mmap中的特定大小的分区,而不需要对另一块内存进行memcpy? – 2011-06-09 14:36:15

+0

看我的编辑.... – 2011-06-09 16:16:40

+0

甜,我现在也试试。类型铸造我的mmap与具有特定的数组大小为Y,U和V的结构(如在zvrba的帖子的评论)。这似乎工作,虽然,黑客 - 哈哈,你的方式可能会更好。 – 2011-06-09 16:22:28

1

如果我明白你想要什么:你不能使mmap'不交错'顺序存储器分成单独的指针。您必须mmap单个内存块并手动计算缓冲区内的适当偏移量?

(但是:。但绝对没有理由不能够的mmap相同的FD几次你从来没有说过什么地方出了错)

+0

好了,你可以投的映射内存要说的结构:typedef结构{无效y_plane [250]; void u_plane [125]; void v_plane [125]} YuvFormat;那么你可以从单个mmap指向指定范围的内存? – 2011-06-09 15:51:12

+0

其实......那么工作!现在只需要计算YUV420流中Y,U和V的长度!干杯:P – 2011-06-09 16:17:50