linux中如何将缓存内的YUV流输出至屏幕??

qazws110 2010-08-27 10:48:33
大家好!!

初步接触linux的程序开发!!

目前在研究使用v4l2将camera capture到的资料流(YUV422)显示至屏幕!

相关资料都是参考tvtime的源码,大略已知可用
VIDIOC_REQBUFS=申请缓存
VIDIOC_QUERYBUF=得到缓存资料
mmap =得到缓存映像位址
VIDIOC_DBUF=取得缓存资料
VIDIOC_QBUF=把缓存重新放置FIFO对列
得到缓存内的位址,但不知如何将缓存内的资料流(YUV422),显示至屏幕

在windows,曾经使用DirectDraw实现过,不知在linux上该如何实做???使用GTK GDK能否?

小弟实在对linux认识初浅,烦情大家不吝赐教!提供些资料参考!!

多谢!!
...全文
1243 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
smilestone322 2011-05-07
  • 打赏
  • 举报
回复
windows下有directshow,linux可以用opengl吧
qazws110 2010-09-03
  • 打赏
  • 举报
回复
目前会已朝gtk+directFB的方向

可是在库的编译关联上遇到了一些问题!!

等调试好会将步骤贴出!!到时候再散分

楼上的各位前辈 请稍等^^
wwwunix 2010-08-30
  • 打赏
  • 举报
回复
1、如果camera的分辨率小于屏幕的分辨率,YUV资料流不会自动显示到整个屏幕。要自己写放大/缩小函数或使用硬件放大/缩小。
2、如果想显示到屏幕中的一个区块,要注意换行的问题。例如:你的camera的分辨率是320*240,而你的屏幕的分辨率是640*480。那么你不能直接用memcpy整个资料区域。你需要一行一行的memcpy,共拷贝240行数据。
qazws110 2010-08-30
  • 打赏
  • 举报
回复
to wwwunix:

直接copy YUV缓存资料给framebuffer,是否YUV资料流会显示到整个萤幕?

如果我只想把camera的到资料显示到萤幕中的其中一个区块(不占满整个画面),该如何着手呢?

麻烦指教!!谢谢
wwwunix 2010-08-30
  • 打赏
  • 举报
回复
你可以用QT试试。
qazws110 2010-08-30
  • 打赏
  • 举报
回复
to wwwunix:
多谢您的回应,我也是大概想到需要做到您提到这两个步骤,可是这样在就必须花很大的功夫在判断及显示camera 及屏幕的分辨率(如两个装置的分辨率及显示的位置)。
另再请教:
有无类似如Directx Draw可以操控底层buffer的接口函式呢?还是LINUX要做类似工程,都只有此一途径?
wwwunix 2010-08-27
  • 打赏
  • 举报
回复
关于你的显示是否支持YUV,要看你的相关Framebuffer的驱动是否支持(大多数不支持)。
YUV转RGB的算法如下:
R= 1.0Y + 0 +1.402(V-128)
G= 1.0Y - 0.34413 (U-128)-0.71414(V-128)
B= 1.0Y + 1.772 (U-128)+0
wwwunix 2010-08-27
  • 打赏
  • 举报
回复
直接写屏:
1、打开一个FrameBuffer设备
2、通过mmap调用把显卡的物理内存空间映射到用户空间
3、直接写内存。

好象很简单哦~
fbtools.h

代码:

#ifndef _FBTOOLS_H_
#define _FBTOOLS_H_

#include <linux/fb.h>

/a framebuffer device structure;
typedef struct fbdev{
int fb;
unsigned long fb_mem_offset;
unsigned long fb_mem;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char dev[20];
} FBDEV, *PFBDEV;

/open & init a frame buffer
/to use this function,
/you must set FBDEV.dev=\"/dev/fb0\"
/or \"/dev/fbX\"
/it\'s your frame buffer.
int fb_open(PFBDEV pFbdev);

/close a frame buffer
int fb_close(PFBDEV pFbdev);

/get display depth
int get_display_depth(PFBDEV pFbdev);


/full screen clear
void fb_memset(void *addr, int c, size_t len);

#endif



fbtools.c

代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>

#include \"fbtools.h\"

#define TRUE 1
#define FALSE 0
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))

/open & init a frame buffer
int fb_open(PFBDEV pFbdev)
{
pFbdev->fb = open(pFbdev->dev, O_RDWR);
if(pFbdev->fb < 0)
{
printf(\"Error opening %s: %m. Check kernel config\\n\", pFbdev->dev);
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
{
printf(\"ioctl FBIOGET_VSCREENINFO\\n\");
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
{
printf(\"ioctl FBIOGET_FSCREENINFO\\n\");
return FALSE;
}

/map physics address to virtual address
pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
pFbdev->fb_mem_offset,
PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
if (-1L == (long) pFbdev->fb_mem)
{
printf(\"mmap error! mem:%d offset:%d\\n\", pFbdev->fb_mem,
pFbdev->fb_mem_offset);
return FALSE;
}

return TRUE;
}

/close frame buffer
int fb_close(PFBDEV pFbdev)
{
close(pFbdev->fb);
pFbdev->fb=-1;
}

/get display depth
int get_display_depth(PFBDEV pFbdev);
{
if(pFbdev->fb<=0)
{
printf(\"fb device not open, open it first\\n\");
return FALSE;
}
return pFbdev->fb_var.bits_per_pixel;
}

/full screen clear
void fb_memset (void *addr, int c, size_t len)
{
memset(addr, c, len);
}

/use by test
#define DEBUG
#ifdef DEBUG
main()
{
FBDEV fbdev;
memset(&fbdev, 0, sizeof(FBDEV));
strcpy(fbdev.dev, \"/dev/fb0\");
if(fb_open(&fbdev)==FALSE)
{
printf(\"open frame buffer error\\n\");
return;
}

fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);

fb_close(&fbdev);
}



qazws110 2010-08-27
  • 打赏
  • 举报
回复
pottichu大:

有点理解您的说法!但...不知道该如何着手

能否提供点代码?感谢
pottichu 2010-08-27
  • 打赏
  • 举报
回复

->pottichu:不太能理解您的意思!mmap不是映像memory位址让我们可以直接存取吗?还是我理解错误,麻烦提点
==============
你的理解是正确的 , 这里 的 mmap 就是 映射 framebuffer 的地址到 应用程序空间, 你直接操作这个映射得到的地址,就可以在屏幕上显示信息。
qazws110 2010-08-27
  • 打赏
  • 举报
回复
感谢两位的回覆!

不过还是有些疑问!!
->wwwunix:看似有必要自行转换成RGB,能否提供些ioctl framebuffer相关的代码及资料呢?

->pottichu:不太能理解您的意思!mmap不是映像memory位址让我们可以直接存取吗?还是我理解错误,麻烦提点

再次感谢两位的协助!!谢谢
pottichu 2010-08-27
  • 打赏
  • 举报
回复
得到缓存内的位址,但不知如何将缓存内的资料流(YUV422),显示至屏幕
===================================================
直接把数据 memcpy 到 mmap 得到的地址即可在屏幕上显示。
wwwunix 2010-08-27
  • 打赏
  • 举报
回复
可以这样做:
如果你的显示芯片支持YUV的格式,并且提供了对应的驱动。则可以使用ioctl设置framebuffer的显示格式为YUV,然后将资料直接拷贝到framebuffer的显示缓存中。
如果你的显示芯片不支持YUV,那么就需要将YUV转换成RGB,然后在拷贝到framebuffer的显存中。

23,114

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧