[DirectShow问题]Windows Mobile平台,CameraCapture的Preview的问题

Eleven 2011-12-19 04:22:11
背景:WM平台Camera程序开发:Windows Mobile SDK 6.0 Professional 包中的CameraCapture例子程序,这个例子程序是SDK的,我将它修改成MFC对话框工程。但是该程序没有预览功能,所以我要在它的基础上加上预览,主要修改了CGraphManager类的CreateCaptureGraphInternal函数和RunCaptureGraphInternal函数,然后自己加个自定义函数PreviewCaptureGraph用来预览。PreviewCaptureGraph函数是在主对话框类中调用间接调用的,不是像例子程序中那样什么都放到工作线程中(因为我发现放到线程中,函数会卡在pMediaControl->Run()处,所有我就自定义了PreviewCaptureGraph函数,改写了原来的RunCaptureGraphInternal()函数)

问题:现在可以预览,但是预览的效果如下所示:

PreviewCaptureGraph()函数中的CHK(pVideoWindow->SetWindowPosition(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));这句调用没有作用,函数调用本身并没有失败,而且发现前面两个参数有效,即left和top有效,可以改变预览的left和top坐标位置。希望那个预览的窗口可以填充满那个CStatic控件区域(黑色边框那个)。

对DirectShow不了解,希望有做过或者开发过的兄弟指点一下~

HRESULT CGraphManager::CreateCaptureGraphInternal()
{
HRESULT hr = S_OK;
CComVariant varCamName;
CPropertyBag PropBag;
OAEVENT oaEvent;
WCHAR wzDeviceName[MAX_PATH + 1] = {0};

CComPtr<IMediaEvent> pMediaEvent;
CComPtr<IGraphBuilder> pFilterGraph;
CComPtr<IBaseFilter> pVideoEncoder;
CComPtr<IBaseFilter> pASFMultiplexer;
CComPtr<IFileSinkFilter> pFileSinkFilter;
CComPtr<IPersistPropertyBag> pPropertyBag;
CComPtr<IDMOWrapperFilter> pWrapperFilter;
CComPtr<IBaseFilter> pImageSinkFilter;

//
// Create the capture graph builder and register the filtergraph manager.
//
CHK(m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder));
CHK(pFilterGraph.CoCreateInstance(CLSID_FilterGraph));
CHK(m_pCaptureGraphBuilder->SetFiltergraph(pFilterGraph));


//
// Create and initialize the video capture filter
//
CHK(m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture));
CHK(m_pVideoCaptureFilter.QueryInterface(&pPropertyBag));

// We are loading the driver CAM1 in the video capture filter.
CHK(GetFirstCameraDriver(wzDeviceName, MAX_PATH));
varCamName = wzDeviceName;
if(varCamName.vt != VT_BSTR)
{
ERR(E_OUTOFMEMORY);
}

CHK(PropBag.Write(L"VCapName", &varCamName));
CHK(pPropertyBag->Load(&PropBag, NULL));

// Everything succeeded, the video capture filter is added to the filtergraph
CHK(pFilterGraph->AddFilter(m_pVideoCaptureFilter, L"Video Capture Filter Source" ));


//
// Third step: Create the video encoder DMO, load the WMV9 encoder, and
// add it to the graph
//

// Create the video encoder
CHK(pVideoEncoder.CoCreateInstance(CLSID_DMOWrapperFilter ));
CHK(pVideoEncoder.QueryInterface(&pWrapperFilter));

// Load the WMV9 DMO
CHK(pWrapperFilter->Init(CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER));

// Everything succeeded, let's add the encoder to the graph
CHK(pFilterGraph->AddFilter(pVideoEncoder, L"WMV9 DMO Encoder"));

//
// Create the ASF multiplexer and add it to the graph
//
CHK(m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Asf, L"\\video1.asf", &pASFMultiplexer, &pFileSinkFilter));

// Create preview
CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, NULL));
//
// Connect the video capture filter, the encoder and the multiplexer together
//
CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer));

//
// Create the still image filter, and connect it to the video capture filter
//
CHK(pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter));
CHK(pFilterGraph->AddFilter(pImageSinkFilter, L"Still image filter"));
CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, pImageSinkFilter));
CHK(pImageSinkFilter.QueryInterface(&m_pImageSinkFilter));

//
// Prevent the data from flowing into the capture stream
//
CHK(m_pCaptureGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0));

//
// Let's get the handle for DShow events. The main loop will listen to both notifications from
// the UI thread and for DShow notifications
//
CHK(pFilterGraph->QueryInterface(IID_IMediaEvent, (void**) &pMediaEvent));
CHK(pMediaEvent->GetEventHandle(&oaEvent));
m_handle[1] = (HANDLE) oaEvent;

m_bGraphBuilt = TRUE;

_CLEANUP:
if(FAILED(hr))
{
NotifyMessage(MESSAGE_ERROR, _T("Building the graph failed"));
}
return hr;
}

HRESULT CGraphManager::RunCaptureGraphInternal()
{
HRESULT hr = S_OK;

// CComPtr<IGraphBuilder> pGraphBuilder;
// CComPtr<IMediaControl> pMediaControl;

// Let's make sure that the graph has been initialized
if((NULL == m_pCaptureGraphBuilder) || (FALSE == m_bGraphBuilt))
{
ERR(E_FAIL);
}

// Retrieve the filtergraph off the capture graph builder
// CHK(m_pCaptureGraphBuilder->GetFiltergraph(&pGraphBuilder));


// Get the media control interface, and run the graph
// CHK(pGraphBuilder->QueryInterface(&pMediaControl));
// CHK(pMediaControl->Run());

CHK(NotifyMessage(MESSAGE_INFO, L"The Graph is Running ..."));

_CLEANUP:
if(FAILED(hr))
{
NotifyMessage(MESSAGE_ERROR, L"Running The Capture Graph Failed");
}

PostMessage(m_hWnd, MSG_EVENTNOTIFICATION, 0, 0); // 这里我发送一个自定义消息到主对话框,在主对话框类的消息响应函数中调用PreviewCaptureGraph()函数。
return hr;
}

HRESULT CGraphManager::PreviewCaptureGraph()
{
HRESULT hr = S_OK;

CComPtr<IGraphBuilder> pGraphBuilder;
CComPtr<IMediaControl> pMediaControl;
CComPtr<IVideoWindow> pVideoWindow;

// Let's make sure that the graph has been initialized
if((NULL == m_pCaptureGraphBuilder) || (FALSE == m_bGraphBuilt))
{
ERR(E_FAIL);
}

// Retrieve the filtergraph off the capture graph builder
CHK(m_pCaptureGraphBuilder->GetFiltergraph(&pGraphBuilder));

// Previewer
{
ASSERT(m_hWndPreviewer);
RECT rect = {0};
GetClientRect(m_hWndPreviewer, &rect);
CHK(pGraphBuilder->QueryInterface(&pVideoWindow));
CHK(pVideoWindow->put_Owner((OAHWND)m_hWndPreviewer));
CHK(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
CHK(pVideoWindow->SetWindowPosition(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
// 这里无效,SetWindowPosition()中的最后两个参数宽度和高度似乎没起作用
CHK(pVideoWindow->put_Visible(OATRUE));

//CHK(pMediaControl->Run());
}

// Get the media control interface, and run the graph
CHK(pGraphBuilder->QueryInterface(&pMediaControl));
//CHK(pMediaControl->Stop());
CHK(pMediaControl->Run());

CHK(NotifyMessage(MESSAGE_INFO, L"The Graph is Running ..."));

_CLEANUP:
if(FAILED(hr))
{
NotifyMessage(MESSAGE_ERROR, L"Running The Capture Graph Failed");
}
return hr;
}


...全文
777 32 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
再见理想~ 2011-12-24
  • 打赏
  • 举报
回复
看看前十楼都是兔子党组织部的啊
jerry_xst 2011-12-22
  • 打赏
  • 举报
回复
setWindowsPosition放到主线程里面。
Eleven 2011-12-21
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 liangxd09 的回复:]
pVideoWindow->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top),这样肯定是可以的
[/Quote]
是的,最后将SDK里的代码框架改了,没有用到多线程,就可以了
Frog1228 2011-12-21
  • 打赏
  • 举报
回复
谁能回答一下我的问题啊?是不是太弱了。。。
莫聆 2011-12-21
  • 打赏
  • 举报
回复
wm都比微软放弃了,还搞啊,还是看看windows phone 7吧。
yyhzpk 2011-12-20
  • 打赏
  • 举报
回复
put_WindowStyle(WS_CHILD)
我之前做的时候,这个参数是有用的
除非现在的video render filter已经修改了
yyhzpk 2011-12-20
  • 打赏
  • 举报
回复
CHK(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
把这个修改一下呢
hhygcy 2011-12-20
  • 打赏
  • 举报
回复
你看看是不是可以自己写个filter把图像拉伸
chen870201 2011-12-20
  • 打赏
  • 举报
回复
代码有些难懂
liangxd09 2011-12-20
  • 打赏
  • 举报
回复
pVideoWindow->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top),这样肯定是可以的
Eleven 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 dream238 的回复:]

引用 19 楼 visualeleven 的回复:

另外发现如果不使用线程的话,SetWindowPosition就没有问题(即主要修改SDK包里的CameraCapture例子中CGraphManager类,去掉线程相关的东西)


对了...既然是对UI窗口进行Resize,应该放到主UI线程来做。也就是不要在工作线程里进行任何UI的控件操作,如果需要更新UI控件,应该sendm……
[/Quote]
是的,现在打算都在主线程中做,因为之前的SDK包的例子CameraCapture程序它是在工作线程中做了,并没有做preview预览功能。
ArcRain 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 visualeleven 的回复:]

另外发现如果不使用线程的话,SetWindowPosition就没有问题(即主要修改SDK包里的CameraCapture例子中CGraphManager类,去掉线程相关的东西)
[/Quote]

对了...既然是对UI窗口进行Resize,应该放到主UI线程来做。也就是不要在工作线程里进行任何UI的控件操作,如果需要更新UI控件,应该sendmessage到主UI线程来进行。
Frog1228 2011-12-19
  • 打赏
  • 举报
回复
Windows上的DirectShow和开发其它图像采集板卡的CameraCapture有什么区别?
Eleven 2011-12-19
  • 打赏
  • 举报
回复
另外发现如果不使用线程的话,SetWindowPosition就没有问题(即主要修改SDK包里的CameraCapture例子中CGraphManager类,去掉线程相关的东西)
Eleven 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 yuucyf 的回复:]

没看出有什么问题,这个是WINCE编程实例中的代码.只是调整了一下代码的位置,
不过可以用pVideoWindow->SetWindowPosition()设置区域比较小看是否成功?
[/Quote]
我不调用SetWindowPosition()的话,直接用GetWindowPostition()看了一下默认设置的大小是160 * 120的。
yuucyf 2011-12-19
  • 打赏
  • 举报
回复
没看出有什么问题,这个是WINCE编程实例中的代码.只是调整了一下代码的位置,
不过可以用pVideoWindow->SetWindowPosition()设置区域比较小看是否成功?
Eleven 2011-12-19
  • 打赏
  • 举报
回复
对DirectShow也不熟,不知道是不是CreateCaptureGraphInternal函数中什么地方设置不对,或者忘记调用什么其它函数~
Eleven 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 visualeleven 的回复:]
引用 13 楼 dream238 的回复:
看了下MSDN,SetWindowPosition有这么句:
If resizing the window to the specified dimensions is impossible, this method modifies the window's size and location to make the window fit.
估计……
[/Quote]
现在很奇怪的是SetWindowPosition前面的left和top参数有效,但是后面两个参数Width和Height确实无效?
Eleven 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 dream238 的回复:]
看了下MSDN,SetWindowPosition有这么句:
If resizing the window to the specified dimensions is impossible, this method modifies the window's size and location to make the window fit.
估计是为了保持宽高比例,所以不能填满。
一般填……
[/Quote]
put_Width/put_Height()也是无效的,SetWindowPosition()应该会调用put_Width/put_Height()函数的。
ArcRain 2011-12-19
  • 打赏
  • 举报
回复
看了下MSDN,SetWindowPosition有这么句:
If resizing the window to the specified dimensions is impossible, this method modifies the window's size and location to make the window fit.
估计是为了保持宽高比例,所以不能填满。
一般填满目标区域保持比例显示的话,都是上下填黑边或者左右填黑边,这些应该都是VideoRender已经干了的活。
P.S:put_Width和put_Height也调用试试。
加载更多回复(12)

16,548

社区成员

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

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

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