Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177218
  • 博文数量: 22
  • 博客积分: 1586
  • 博客等级: 上尉
  • 技术积分: 230
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-06 10:32
文章分类

全部博文(22)

文章存档

2015年(2)

2014年(1)

2013年(2)

2012年(5)

2011年(1)

2010年(11)

我的朋友

分类: LINUX

2013-11-18 16:23:58




饮水思

    使用ffmpeg解码h.264得到的图片都是YUV格式(准确来说是YV12格式),不是RGB格式。如果直接使用GTK提供的库函数,效率将比较低,不能充分发挥显卡的性能。在LINUX下,为了充分发挥显卡的性能,降低CPU的负载,可以使用vx接口来播放图片。

    xv又叫X-Video,是X-Window的一个扩展,为视频播放提供高速的接口。由于xv依赖显卡驱动,某些显卡可能不能提供播放YUV的接口,但大部分显卡应该没有这个问题。

    为了减少麻烦,可以选用ubuntu作为开发平台,选择“新立得软件包管理器”来安装开发需要的软件包。需要安装的开发包有:libgtk-3-dev、libX11-dev和libxv-dev。


    如何现实YUV图片呢?需要先从XvCreateImage这函数说起。

XvImage * XvCreateImage (Display *dpy,XvPortID port,int id, char *data,int width, int height);

需要包含的头文件有:

#include 
#include 

#include  // 里面包含一些宏
#include 

需要使用到的参数以及获取方法:

static GtkWidget *drawing_area1; //GTK3的用来画图的一个控件

//以下参数应该在gtk_widget_show (pTopWindow);后获取

static Display *display; //通过GDK_WINDOW_XDISPLAY(gtk_widget_get_window(drawing_area1));获取;这个值对于每个进程来说是唯一的。
static int      screen;  //通过GDK_SCREEN_XNUMBER(gtk_widget_get_screen(drawing_area1));获取
static Window   window;  //通过GDK_WINDOW_XID(gtk_widget_get_window(drawing_area1));获取
static Drawable d;       //通过GDK_WINDOW_XID(gtk_widget_get_window(drawing_area1));获取
static XvPortID xv_port; //比较麻烦,稍后详解
static GC gc=NULL;       //通过XCreateGC (display, d, 0, NULL);获取
static int iWidth; //drawing_area1的宽度,通过config_event signal中的iWidth = event->configure.width;获取
static int iHeight;//drawing_area1的高度,通过config_event signal中的iHeight = event->configure.height;获取

xv_port的获取比较麻烦,也不好解析,下面贴上源码:
    static int open_yv12_port (XvPortID port)
    {
        XvImageFormatValues *formatValues;
        int                  formats;
        int                  i;
        int ret;
        formatValues = XvListImageFormats (display, port, &formats);
        for (i = 0; i < formats; i++)
        {
            if(formatValues[i].type==XvYUV && (strcmp (formatValues[i].guid, "YV12")==0))
            {
                if(XvGrabPort(display, port, 0)==Success)
                {
                    ret = 0; // OK
                    goto OnExit;
                }
            }
        }
        ret = -1; // Fail
OnExit:
        XFree (formatValues);
        return ret;
    }
    static int xv_autodetect_port(XvPortID* pOut)
    {
        int ret;
        int i;
        unsigned int          ver,rel,req,ev,err;
        XvAdaptorInfo        *adaptor_info=NULL;
        unsigned int          adaptor_num;
        ret = XvQueryExtension(display, &ver,&rel, &req, &ev,&err);
        if(ret!=Success)
        {
            g_print("XvQueryExtension failed,xv is not present.\n");
            goto OnError;
        }
        g_print("xv version %u,release %u,request_base %u,event_base %u,error_base=%u\n",
                ver,rel,req,ev,err);
        ret = XvQueryAdaptors(display,window,&adaptor_num,&adaptor_info);
        if(ret!=Success)
        {
            g_print("XvQueryAdaptors failed.\n");
            goto OnError;
        }
        for(i=0; i         {
            int j;
            for(j=0; j             {
                ret = open_yv12_port(adaptor_info[i].base_id+j);
                if(ret==0)
                {
                    * pOut = adaptor_info[i].base_id+j;
                    goto OnError; // OK
                }
            }
        }
        ret = -1; // Fail
OnError:
        if(adaptor_info) XvFreeAdaptorInfo(adaptor_info);
        return ret;
    }

通过xv_autodetect_port函数就可以获取到xv_port的值,返回0表示成功。这里只取YV12的port。取到的值和xvinfo命令显示的一致,否则可能有误。

在图文界面的命令行终端输入:xvinfo ,(ssh或者telnet的会提示“xvinfo:  Unable to open display”)

得到如下结果:
X-Video Extension version 2.2
screen #0
  Adaptor #0: "Intel(R) Textured Video"
    number of ports: 16 // 这是可以使用的xv_port的总共个数
    port base: 163 // 这是xv_port的基值
    operations supported: PutImage 
    supported visuals:
      depth 24, visualID 0x69
    no port attributes defined
    maximum XvImage size: 2048 x 2048
    Number of image formats: 5
      id: 0x32595559 (YUY2)
        guid: 59555932-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x32315659 (YV12)
        guid: 59563132-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
      id: 0x30323449 (I420)
        guid: 49343230-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
      id: 0x59565955 (UYVY)
        guid: 55595659-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x434d5658 (XVMC)
        guid: 58564d43-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)


ffmpeg的图片现实:

把解压到的frame的数据拷贝到一个unsigned char sBuf[LARGE_ENOUGH]里面,然后创建一个image,然后显示:

// 数据拷贝

                dst = sBuf;
                i=0;
                do
                {
                    int width,height;
                    unsigned char* src;
                    if (i==0)
                    {
                        height = picture->height;
                        width = picture->width;
                    }
                    else
                    {
                        height = picture->height/2;
                        width = picture->width/2;
                    }
                    src = picture->data[i];
                    for (j=0; j                     {
                        memcpy(dst,src,width);
                        dst+=width;
                        src+=picture->linesize[i];
                    }
                    if(i==0) i=2;
                    else if(i==2) i=1;
                    else break;
                } while(1);

//创建image

xv_image=XvCreateImage(display,xv_port,0x32315659/*"YV12"*/,sBuf,codeccontext->width,codeccontext->height);

//显示image
XvPutImage(display,xv_port,window, gc, xv_image,
                           0, 0, codeccontext->width, codeccontext->height,
                           0, 0, iWidth, iHeight);
XFree(xv_image);


最后,有些资源是需要自己释放,别忘记了。

阅读(3123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~