如何取出VIDEOHDR中的数据,显示出来呢?

jethao 2004-11-26 11:55:30
我使用VFW采集视频

用LRESULT CALLBACK capVideoStreamCallback( HWND hWnd, LPVIDEOHDR lpVHdr );
得到了视频缓冲数据,但是该如何从lpVHdr->lpData中取出数据显示在窗口上呢?

这个数据是什么格式?

如果是bmp格式的,我该怎么构造bmp,最终用StretchBlt显示呢?
...全文
450 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
jethao 2004-11-29
  • 打赏
  • 举报
回复
已经全部搞定。
非常感谢freeshoot(巴蒂刘) !
freeshoot 2004-11-28
  • 打赏
  • 举报
回复
如果你不想用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
);
jethao 2004-11-28
  • 打赏
  • 举报
回复
非常感谢2位的指点,尤其是 freeshoot(巴蒂刘),按照你的方法已经试验成功。

因为我不想用VFW的DrawDibDraw函数,所以我还想请教一下,如果单独用CreateBMP系列的函数,该怎么创建一个hBitmap?然后装入memDC,用StretchBlt显示?
jethao 2004-11-26
  • 打赏
  • 举报
回复
你在capVideoStreamCallback取到了缓冲数据后,是否调整了共享缓冲pVBuffer的大小呢?

我预先分配了一个较大的内存空间,在得到数据后,根据pVideoHdr->dwBytesUsed,realloc了pVBuffer的大小。应该不是这个问题吧?
jethao 2004-11-26
  • 打赏
  • 举报
回复
不是m_bmpInfo的问题,我查看了内存,所有的参数都正确,&m_BitmapInfo.bmiHeader得内容都可以看到,我的那个pVBuffer里的数据也都有,DrawDibDraw()、BitBlt()两个函数返回值都是TRUE.

但是就是没有效果,不知道为什么啊?我还调整了位置参数,也不行。

折腾了一下午了。。。。。。郁闷。。。。。。

不过还是谢谢你!我再看看!
freeshoot 2004-11-26
  • 打赏
  • 举报
回复
DrawDibDraw具有直接读写显存的能力。

我就是将capVideoStreamCallback回调出来的数据,
COPY到共享内存后作为参数(LPVOID)pVBufRemote来显示的,一切OK。

是不是参数m_bmpInfo的问题?
jethao 2004-11-26
  • 打赏
  • 举报
回复
为什么显示不出来呢?黑屏幕。
我改造后的函数:
//*************************************************************
//因为我的视频采集单独用了一个线程,所以用了一个共享缓冲区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);
//****************************************************************************
jethao 2004-11-26
  • 打赏
  • 举报
回复
非常感谢楼上的两位,正在试验你们说的方法!

我正在做的是上层应用,本来只负责视频的播放和音频的采集、播放,视频的采集以及音视频的编解码,同步问题,都由另外一个小组用DSP板来完成,目前因为需要测试,所以,我临时模拟了DSP的部分功能,在局域网上测试。

DrawDibDraw的效率比StretchBlt会高很多吗?主要原理有什么不同?
因为我目前已经用剪贴板共享数据的方法,实现了单帧播放,但是这种方法,无法得知显示的数据Size(我也是初学VC,着了很久,没有找到这个方法),这样无法分包,所以采用回调函数capVideoStreamCallback来取单帧。

capGrabFrameNoStop(hWndCap);
capEditCopy(hWndCap);
//***********************
::OpenClipboard(NULL);
hBitmap = (HBITMAP)::GetClipboardData(CF_BITMAP);
......
::CloseClipboard();

freeshoot 2004-11-26
  • 打赏
  • 举报
回复
用双缓存直接绘制到窗口上就是了,不过用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);
DentistryDoctor 2004-11-26
  • 打赏
  • 举报
回复
Yes,不过还是建议你将数据压后再传!
jethao 2004-11-26
  • 打赏
  • 举报
回复
谢谢 DentistryDoctor!
我现在用StretchBlt来写屏,所以是不是应该在capDriverConnect之后,capSetVideoFormat?

我的目的是分包这一帧数据,然后发送到网络上,最后再组包显示。
目前我已经取出来了这一帧,可以分包租包。

所以我想知道该如何显示这个数据?麻烦你详细指点一下吧!
不论是RGB数据,还是YUV数据,都可以。

谢谢!
DentistryDoctor 2004-11-26
  • 打赏
  • 举报
回复
capSetVideoFormat指定的格式即为lpVHdr的格式,不过我一般是指定YUYV,然后Overlap上屏显示。
jethao 2004-11-26
  • 打赏
  • 举报
回复

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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