个位高手您好:
     能否用DirectX显示YUV格式的图像

解决方案 »

  1.   

    yuv和RGB是呈线性关系的,用个Matrix转化一下不就行了?
      

  2.   

    DirectX(准确的说是大部分显卡)是支持YUV格式直接显示的,并且有硬件加速(硬件色彩空间转换),最好是用Overlay表面来显示,DirectX不支持软件模拟Overlay。所以要么先作RGB转换然后用普通DirectDraw表面显示,要么用Overlay直接显示。我的想法是如果显卡连Overlay都不支持,那也太老了,普通DirectDraw表面显示也不会有好的效果,所以直接用Overlay显示就可以了。
      

  3.   

    初学DX,请问楼上朋友,YUV文件中的每一帧在转化为RGB之后,怎样用DirectDraw来显示?
    RGB的点阵在内存中,创建位图,创建表面,然后将位图绘到表面上。
    我试了一下,屏幕上什么也没有,怎么回事?
    DX9搞得更复杂了,不知道到哪里去找接口了。
    希望得到你的指教!
      

  4.   

    "...\DXVcSDK8\samples\Multimedia\DirectDraw\OverlayAnimate" 就是用显示的例子,曾对我有所帮助,希望对你也有所启发。
      

  5.   

    我试了一下,该程序
    Failed to create surfaces.
    The directdraw device may not support overlays.
    与我的显卡有关系?
      

  6.   

    #include <stdio.h>
    #include <conio.h>
    #include <sys/stat.h>
    #include <ddraw.h>unsigned char *y;
    unsigned char *u;
    unsigned char *v;bool testsize(int w, int h, int s, int *pw, int *ph);int main(int argc, char *argv[])
    {
    HRESULT hr;
    LPDIRECTDRAW lpDD;
    DDSURFACEDESC ddsd;
    LPDIRECTDRAWSURFACE lpPrimary;
    LPDIRECTDRAWSURFACE lpOverlay;
    RECT rcSrc;
    FILE *fd;
    int i, j, f;
    char name[256];
    unsigned char *py, *pu, *pv;
    unsigned int *dst;
    int ffirst, fcount, ms_per_frame;
    int width, height, size;
    int width2, height2, size2;
    int t1, t2;
    char c;
    bool done, wait; if (argc != 4 && argc != 6 && argc != 7)
    {
    fprintf(stderr, "vidplay template first count [width height [ms_per_frame]]");
    return -1;
    }
    sscanf(argv[2], "%d", &ffirst);
    sscanf(argv[3], "%d", &fcount);
    if (argc == 7)
    {
    sscanf(argv[6], "%d", &ms_per_frame);
    }
    else
    {
    ms_per_frame = 33;
    }
    if (argc >= 6)
    {
    sscanf(argv[4], "%d", &width);
    sscanf(argv[5], "%d", &height);
    }
    else
    {
    struct _stat st;
    sprintf(name, argv[1], ffirst);
    if (_stat(name, &st) != 0)
    return -1;
    size = st.st_size;
    if (!(testsize( 176, 144, size, &width, &height)
       || testsize( 352, 240, size, &width, &height)
       || testsize( 352, 480, size, &width, &height)
       || testsize( 704, 480, size, &width, &height)
       || testsize( 720, 480, size, &width, &height)
       || testsize( 352, 288, size, &width, &height)
       || testsize( 352, 576, size, &width, &height)
       || testsize( 704, 576, size, &width, &height)
       || testsize( 720, 576, size, &width, &height)
       || testsize(   8,   8, size, &width, &height)
       || testsize(  16,  16, size, &width, &height)
       || testsize(  32,  32, size, &width, &height)
       || testsize(  64,  64, size, &width, &height)
       || testsize( 128, 128, size, &width, &height)
       || testsize( 256, 256, size, &width, &height)
       || testsize( 512, 512, size, &width, &height)
       || testsize(1024,1024, size, &width, &height)))
    {
    fprintf(stderr, "Nonstandard picture size: specify width and height\n");
    return -1;
    }
    }
    width2 = width/2;
    height2 = height/2;
    size = width*height;
    size2 = width2*height2;
    y = (unsigned char *)malloc(size);
    u = (unsigned char *)malloc(size2);
    v = (unsigned char *)malloc(size2);
    if (y == NULL || u == NULL || v ==NULL)
    {
    fprintf(stderr, "Out of memory\n");
    return -1;
    }
    hr = DirectDrawCreate(NULL, &lpDD, NULL);
    if (FAILED(hr)) { fprintf(stderr, "DirectDrawCreate failed\n"); return -1; }
    hr = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
    if (FAILED(hr)) { fprintf(stderr, "SetCooperativeLevel failed\n"); return -1; }
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    hr = lpDD->CreateSurface(&ddsd, &lpPrimary, NULL);
    if (FAILED(hr)) { fprintf(stderr, "CreateSurface (primary) failed\n"); return -1; }
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
    ddsd.dwWidth = width;
    ddsd.dwHeight = height;
    ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
    ddsd.ddpfPixelFormat.dwFourCC = 0x32595559; // YUY2
    hr = lpDD->CreateSurface(&ddsd, &lpOverlay, NULL);
    if (FAILED(hr)) { fprintf(stderr, "CreateSurface (overlay) failed\n"); return -1; }
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    hr = lpOverlay->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
    if (FAILED(hr)) { fprintf(stderr, "Lock failed\n"); return -1; }
    for (i=0; i<height; i++)
    {
    dst = (unsigned int *)(((unsigned char *)ddsd.lpSurface) + i * ddsd.lPitch);
    for (j=0; j<width2; j++)
    {
    dst[j] = 0x00800080;
    }
    }
    hr = lpOverlay->Unlock(NULL);
    SetRect(&rcSrc, 0, 0, width, height);
    hr = lpOverlay->UpdateOverlay(NULL, lpPrimary, NULL, DDOVER_SHOW, NULL);
    if (FAILED(hr)) { fprintf(stderr, "UpdateOverlay failed\n"); return -1; }
    done = false;
    wait = false;
    while (!done)
    {
    t1 = timeGetTime();
    for (f=ffirst; f<ffirst+fcount; f++)
    {
    sprintf(name, argv[1], f);
    fd = fopen(name, "rb");
    if (fd != NULL)
    {
    fread(y, 1, size, fd);
    fread(u, 1, size2, fd);
    fread(v, 1, size2, fd);
    fclose(fd);
    }
    else
    {
    char name1[256];
    sprintf(name1, "%s.Y", name);
    fd = fopen(name1, "rb");
    if (fd != NULL)
    {
    fread(y, 1, size, fd);
    fclose(fd);
    sprintf(name1, "%s.U", name);
    fd = fopen(name1, "rb");
    fread(u, 1, size2, fd);
    fclose(fd);
    sprintf(name1, "%s.V", name);
    fd = fopen(name1, "rb");
    fread(v, 1, size2, fd);
    fclose(fd);
    }
    }
    if (fd != NULL)
    {
    t2 = t1 - timeGetTime();
    if (t2 > 0) Sleep(t2);
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    hr = lpOverlay->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
    if (SUCCEEDED(hr))
    {
    for (i=0; i<height; i++)
    {
    dst = (unsigned int *)(((unsigned char *)ddsd.lpSurface) + i * ddsd.lPitch);
    py = &y[width*i];
    pu = &u[width2*(i>>1)];
    pv = &v[width2*(i>>1)]; for (j=0; j<width2; j++)
    {
    dst[j] = py[j<<1] | (pu[j]<<8) | (py[(j<<1)+1]<<16) | (pv[j]<<24);
    }
    }
    hr = lpOverlay->Unlock(NULL);
    }
    if (wait || _kbhit())
    {
    c = _getch();
    if (c=='q')
    {
    done = true;
    break;
    }
    else if (c==' ')
    wait = true;
    else
    {
    wait = false;
    t1 = timeGetTime();
    }
    }
    }
    t1 += ms_per_frame;
    }
    t2 = t1 - timeGetTime();
    if (t2 > 0) Sleep(t2);
    }
    hr = lpOverlay->UpdateOverlay(NULL, lpPrimary, NULL, DDOVER_HIDE, NULL);
    lpOverlay->Release();
    lpPrimary->Release();
    lpDD->Release();
    return 0;
    }bool testsize(int w, int h, int s, int *pw, int *ph)
    {
    if (s == w*h || s == (w*h*3)/2)
    {
    *pw = w;
    *ph = h;
    return true;
    } return false;
    }