我使用VFW采集视频用LRESULT CALLBACK capVideoStreamCallback( HWND hWnd, LPVIDEOHDR lpVHdr );
得到了视频缓冲数据,但是该如何从lpVHdr->lpData中取出数据显示在窗口上呢?这个数据是什么格式?如果是bmp格式的,我该怎么构造bmp,最终用StretchBlt显示呢?

解决方案 »

  1.   

    capSetVideoFormat指定的格式即为lpVHdr的格式,不过我一般是指定YUYV,然后Overlap上屏显示。
      

  2.   

    谢谢 DentistryDoctor!
    我现在用StretchBlt来写屏,所以是不是应该在capDriverConnect之后,capSetVideoFormat?我的目的是分包这一帧数据,然后发送到网络上,最后再组包显示。
    目前我已经取出来了这一帧,可以分包租包。所以我想知道该如何显示这个数据?麻烦你详细指点一下吧!
    不论是RGB数据,还是YUV数据,都可以。谢谢!
      

  3.   

    Yes,不过还是建议你将数据压后再传!
      

  4.   

    用双缓存直接绘制到窗口上就是了,不过用DrawDibDraw效率会高一些:
    在网络上传输就一定要编码和解码,不然带宽会受不了。///////////////////////////////////////////////////////////////
    HDC hDC = GetDC(m_hWnd);
    HDC hMemDC = CreateCompatibleDC(hDC);
    // 该位图大小,可以调整到同你采集视频时传递的位图大小一致。
    // 这里采用的是默认大小:176*144
    HBitmap m_hBitmap = CreateCompatibleBitmap(hDC, 176, 144);RECT rect;
    GetClientRect(m_hWnd, &rect);
          
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap);
            
    HDRAWDIB hDib = DrawDibOpen();// 参数m_bmpInfo是通过视频采集函数capGetVideoFormat得到的位图格式.
    DrawDibDraw(hDib, hMemDC, 
            0, 0, rect.right, rect.bottom, 
            &m_bmpInfo.bmiHeader, (LPVOID)lpData, 
            0, 0, m_bmpInfo.bmiHeader.biWidth, m_bmpInfo.bmiHeader.biHeight, 
            DDF_NOTKEYFRAME);DrawDibClose(hDib);
        
    BitBlt(hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);SelectObject(hMemDC, hOldBitmap);DeleteDC(hMemDC);ReleaseDC(m_hWnd, hDC);
      

  5.   

    非常感谢楼上的两位,正在试验你们说的方法!我正在做的是上层应用,本来只负责视频的播放和音频的采集、播放,视频的采集以及音视频的编解码,同步问题,都由另外一个小组用DSP板来完成,目前因为需要测试,所以,我临时模拟了DSP的部分功能,在局域网上测试。DrawDibDraw的效率比StretchBlt会高很多吗?主要原理有什么不同?
    因为我目前已经用剪贴板共享数据的方法,实现了单帧播放,但是这种方法,无法得知显示的数据Size(我也是初学VC,着了很久,没有找到这个方法),这样无法分包,所以采用回调函数capVideoStreamCallback来取单帧。capGrabFrameNoStop(hWndCap);
    capEditCopy(hWndCap);
    //***********************
    ::OpenClipboard(NULL);
    hBitmap = (HBITMAP)::GetClipboardData(CF_BITMAP);
    ......
    ::CloseClipboard();
      

  6.   

    为什么显示不出来呢?黑屏幕。
    我改造后的函数:
    //*************************************************************
    //因为我的视频采集单独用了一个线程,所以用了一个共享缓冲区pVBuffer,
    //由FrameCallbackProc来写入,然后发消息给显示窗。
    //CopyMemory(pVBufRemote,pVideoHdr->lpData,pVideoHdr->dwBytesUsed);
    //::PostMessage(hAVMainWnd, WM_VDSPTOAPPREMOTE, (WPARAM)0, (LPARAM)dwSize);
    //Debug中看到共享缓冲区中的数据都传递正常,函数执行正常,为何没反应呢? //pAVCtrl->PlayRemoteVideo();
    HDC hDC = ::GetDC(m_hFrameWnd);
    HDC hMemDC = CreateCompatibleDC(hDC);
    // 该位图大小,可以调整到同你采集视频时传递的位图大小一致。
    // 这里采用的是默认大小:176*144
    HBITMAP m_hBitmap = ::CreateCompatibleBitmap(hDC, 240, 180);

    RECT rect;
    ::GetClientRect(m_hFrameWnd, &rect);

    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

    HDRAWDIB hDib = DrawDibOpen();

    // 参数m_bmpInfo是通过视频采集函数capGetVideoFormat得到的位图格式.
    DrawDibDraw(hDib, hMemDC, 
            0, 0, rect.right, rect.bottom, 
            &m_BitmapInfo.bmiHeader, (LPVOID)pVBufRemote, 
            0, 0, m_BitmapInfo.bmiHeader.biWidth, m_BitmapInfo.bmiHeader.biHeight, 
            DDF_NOTKEYFRAME);

    DrawDibClose(hDib);

    BitBlt(hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);
    SelectObject(hMemDC, hOldBitmap);

    DeleteDC(hMemDC);

    ::ReleaseDC(m_hFrameWnd, hDC);
    //****************************************************************************
      

  7.   

    DrawDibDraw具有直接读写显存的能力。我就是将capVideoStreamCallback回调出来的数据,
    COPY到共享内存后作为参数(LPVOID)pVBufRemote来显示的,一切OK。是不是参数m_bmpInfo的问题?
      

  8.   

    不是m_bmpInfo的问题,我查看了内存,所有的参数都正确,&m_BitmapInfo.bmiHeader得内容都可以看到,我的那个pVBuffer里的数据也都有,DrawDibDraw()、BitBlt()两个函数返回值都是TRUE.但是就是没有效果,不知道为什么啊?我还调整了位置参数,也不行。折腾了一下午了郁闷不过还是谢谢你!我再看看!
      

  9.   

    你在capVideoStreamCallback取到了缓冲数据后,是否调整了共享缓冲pVBuffer的大小呢?我预先分配了一个较大的内存空间,在得到数据后,根据pVideoHdr->dwBytesUsed,realloc了pVBuffer的大小。应该不是这个问题吧?
      

  10.   

    非常感谢2位的指点,尤其是 freeshoot(巴蒂刘),按照你的方法已经试验成功。因为我不想用VFW的DrawDibDraw函数,所以我还想请教一下,如果单独用CreateBMP系列的函数,该怎么创建一个hBitmap?然后装入memDC,用StretchBlt显示?
      

  11.   

    如果你不想用DrawDibDraw, 可以用Win32 GDI函数StretchDIBits实现你想要得功能:
    int StretchDIBits(
      HDC hdc,                // handle to device context
      int XDest,              // x-coordinate of upper-left corner of dest. rectangle
      int YDest,              // y-coordinate of upper-left corner of dest. rectangle
      int nDestWidth,         // width of destination rectangle
      int nDestHeight,        // height of destination rectangle
      int XSrc,               // x-coordinate of upper-left corner of source rectangle
      int YSrc,               // y-coordinate of upper-left corner of source rectangle
      int nSrcWidth,          // width of source rectangle
      int nSrcHeight,         // height of source rectangle
      CONST VOID *lpBits,            // address of bitmap bits
      CONST BITMAPINFO *lpBitsInfo,  // address of bitmap data
      UINT iUsage,                   // usage flags
      DWORD dwRop                    // raster operation code
    );
      

  12.   

    已经全部搞定。
    非常感谢freeshoot(巴蒂刘) !