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

Eleven Eleven 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
背景: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;
}


...全文

相关推荐

高校技术转移办公室人员如何利用平台提升技术成果的市场转化率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

人工智能基于Spring AI的流程编排技术:Java开发者实现RAG、工具调用与多Agent协作的系统化方法论

「AI大模型」Spring-AI-流程编排主流做法-保姆级教程 内容概要:本文是一份关于 Spring AI 1.0 GA 版本中流程编排的系统性教程,重点讲解如何利用 Spring AI 的核心机制实现 AI 应用中的标准化、可复用的流程控制。文章从环境搭建入手,深入介绍 ChatClient 作为编排入口的使用方式,并详细阐述 Advisors 拦截链在实现安全过滤、记忆管理、检索增强生成(RAG)、工具调用等功能中的核心作用。进一步覆盖结构化输出、跨进程通信协议 MCP 及基于状态图的复杂工作流引擎 Spring AI Alibaba Graph 等高级编排能力,最后通过一个集成 RAG、工具调用与对话记忆的生产级 Agent 实战案例,展示了全流程自动化的能力。整套体系借鉴了 Servlet Filter 和 LangGraph 思想,强调“约定优于配置”的工程化设计。; 适合人群:具备 Spring Boot 基础,希望系统掌握 AI 应用流程编排的 Java 开发者,尤其是从事企业级 AI 功能开发、Agent 构建及相关平台建设的技术人员。; 使用场景及目标:① 构建具备记忆、RAG、工具调用等复合能力的智能助手;② 实现可插拔、高复用、易测试的 AI 流程组件;③ 设计支持循环、分支和并行的复杂 Agent 工作流;④ 推动跨服务、跨语言的 AI 工具标准化集成(通过 MCP)。; 阅读建议:此资源以 Spring 官方及 Alibaba 生态权威资料为基础,内容紧跟 1.0 GA 最新演进,建议结合官方文档同步实践代码,特别注意版本迁移要点(如 artifactId 更名、Advisor 替换等),并在实际项目中遵循最佳实践规避常见陷阱。

资源创作小能手

产业园区如何精准识别并引进符合本地产业特色的优质科技成果转化项目?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

阿里云云原生架构白皮书文档

阿里云云原生架构白皮书,由阿里云内部技术团队合著,对整个阿里云云原生产品和架构理念进行了全面深入介绍

元界MetaLite

NexIoT AI物联网平台 是一款基于Java 25 AI+创新的"真·零代码侵入"企业级物联网平台

基于Java 25 AI+创新的"真·零代码侵入"企业级物联网平台 | 开箱即用 | 设备驱动完全外置,一键导出即用 | 支持TCP、MQTT、Modbus、天翼物联等多协议多平台接入 | 基于浏览器的调试IDE、插件化和热部署 | 驱动生态共享,你对接的设备我可直接导入

Java程序员-张凯
评论 32
收藏 已收藏
分享
返回顶部
Eleven
VC/MFC 16,550 成员 421,606 内容