LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1004|回复: 3

gtk显示rgb24的视频流问题

[复制链接]
发表于 2009-12-29 17:38:46 | 显示全部楼层 |阅读模式
我在自己的mini2440上弄了个gtk视频采集的程序, v4l采集来的yuv视频转换为rgb24在gtk上显示。在PC上运行显示正常。
     交叉编译后在板子上就只显示那几个控制按钮了,视频区一片空白。后来查阅资料显示不支持rgb24 :yun:



给出我现在用的转换函数

[php]
#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0(x)>>16)))

static inline void
v4l_copy_420_block (int yTL, int yTR, int yBL, int yBR, int u, int v,
    int rowPixels, unsigned char * rgb, int bits)
{
    const int rvScale = 91881;
    const int guScale = -22553;
    const int gvScale = -46801;
    const int buScale = 116129;
    const int yScale  = 65536;
    int r, g, b;

    g = guScale * u + gvScale * v;
    r = rvScale * v;
    b = buScale * u;

    yTL *= yScale; yTR *= yScale;
    yBL *= yScale; yBR *= yScale;

    if (bits == 24) {
        /* Write out top two pixels */
        rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
        rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);

        /* Skip down to next line to write out bottom two pixels */
        rgb += 3 * rowPixels;
        rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
        rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
    } else if (bits == 16) {
        /* Write out top two pixels */
        rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0);
        rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8);

        rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0);
        rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8);

        /* Skip down to next line to write out bottom two pixels */
        rgb += 2 * rowPixels;

        rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0);
        rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8);

        rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0);
        rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8);
    }
}

int
v4l_yuv420p2rgb (unsigned char *rgb_out, unsigned char *yuv_in,
                 int width, int height, int bits)
{
    const int numpix = width * height;
    const unsigned int bytes = bits >> 3;
    int h, w, y00, y01, y10, y11, u, v;
    unsigned char *pY = yuv_in;
    unsigned char *pU = pY + numpix;
    unsigned char *pV = pU + numpix / 4;
    unsigned char *pOut = rgb_out;

    if (!rgb_out || !yuv_in)
        return -1;

    for (h = 0; h <= height - 2; h += 2) {
        for (w = 0; w <= width - 2; w += 2) {
            y00 = *(pY);
            y01 = *(pY + 1);
            y10 = *(pY + width);
            y11 = *(pY + width + 1);
            u = (*pU++) - 128;
            v = (*pV++) - 128;

            v4l_copy_420_block (y00, y01, y10, y11, u, v, width, pOut, bits);

            pY += 2;
            pOut += bytes << 1;

        }
        pY += width;
        pOut += width * bytes;
    }
    return 0;
}
[/php]

我用它转换rgb24的很多绿色的点
请问,yuv怎么转成rgb16呢? 又怎么用gtk显示rgb16的视频?
发表于 2009-12-29 17:57:57 | 显示全部楼层
有两个函数可以研究一下gdk_pixmap_create_from_data还有gdk_draw_pixmap()。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-12-29 20:56:38 | 显示全部楼层
看到斑竹的签名 应该是directfb高手了 那请问下怎么用directfb显示yuv视频流啊?
回复 支持 反对

使用道具 举报

发表于 2009-12-29 21:58:27 | 显示全部楼层
如果支持直接用overlay输出效率比较高,用dfb或者sdl都可以,拿到gdk窗口handle就可以了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表