本文主要是介绍【MediaFoundation】读取音视频,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原文链接: 官方文档
Microsoft Media Foundation支持音频和视频捕获。视频捕获设备通过UVC类驱动程序支持,并必须与UVC 1.1兼容。音频捕获设备通过Windows音频会话API(WASAPI)支持。
在Media Foundation中,捕获设备通过媒体源对象来表示,该对象公开了IMFMediaSource接口。在大多数情况下,应用程序不会直接使用这个接口,而是会使用一个更高级的API,如Source Reader,来控制捕获设备。
枚举音视频捕获设备
要枚举系统上的捕获设备,请执行以下步骤:
- 调用
MFCreateAttributes
函数来创建一个属性存储。 - 将
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE
属性设置为以下值之一:
值 | 描述 |
---|---|
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID | 列举音频设别 |
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID | 列举视频设别 |
- 调用
MFEnumDeviceSources
函数。该函数分配了一个IMFActivate
指针的数组。每个指针表示系统上一个设备的激活对象。 - 调用
IMFActivate::ActivateObject
方法从一个激活的对象中创建一个媒体源的实例。 - 可以访问被激活的对象的属性,包括:
MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME
包含设备展示的名字。这个展示的名字是给用户看的,并不一定是唯一的。- 对于视频设备,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK
属性包含了设备的符号链接。符号链接在系统上唯一标识设备,但不是可读的字符串。 - 对于音频设备,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID
效果同上。
下面是一个完整的Demo用于输出视频设备的名称。
#include <iostream>
#include <Windows.h>
#include <mferror.h>
#include <comdef.h>
#include <mfidl.h>
#include <mfapi.h>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")void DebugShowDeviceNames(IMFActivate** ppDevices, UINT count)
{for (DWORD i = 0; i < count; i++){HRESULT hr = S_OK;WCHAR* szFriendlyName = NULL;// Try to get the display name.UINT32 cchName;hr = ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,&szFriendlyName, &cchName);if (SUCCEEDED(hr)){// 调试的时候输出到调试窗口/*OutputDebugString(szFriendlyName);OutputDebugString(L"\n");*/// 直接输出到终端std::wcout << szFriendlyName << std::endl;}CoTaskMemFree(szFriendlyName);}
}HRESULT CreateVideoCaptureDevice(IMFMediaSource** ppSource)
{*ppSource = NULL;UINT32 count = 0;IMFAttributes* pConfig = NULL;IMFActivate** ppDevices = NULL;// Create an attribute store to hold the search criteria.HRESULT hr = MFCreateAttributes(&pConfig, 1);// Request video capture devices.if (SUCCEEDED(hr)){hr = pConfig->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);}// Enumerate the devices,if (SUCCEEDED(hr)){hr = MFEnumDeviceSources(pConfig, &ppDevices, &count);DebugShowDeviceNames(ppDevices, count);}// Create a media source for the first device in the list.if (SUCCEEDED(hr)){if (count > 0){hr = ppDevices[0]->ActivateObject(IID_PPV_ARGS(ppSource));}else{hr = MF_E_NOT_FOUND;}}for (DWORD i = 0; i < count; i++){ppDevices[i]->Release();}CoTaskMemFree(ppDevices);return hr;
}int main()
{IMFMediaSource* ppSource = nullptr;auto ret = CreateVideoCaptureDevice(&ppSource);
}
使用捕获设备
在为捕获设备创建媒体源后,使用 Source Reader 从设备获取数据。Source Reader 提供包含捕获音频数据或视频帧的媒体样本。下一步取决于你的应用场景:
- 视频预览:使用 Microsoft Direct3D 或 Direct2D 来显示视频
- 文件捕获:使用
Sink Writer
对文件进行编码 - 音频预览: Use WASAPI.
如果你想将音频捕获与视频捕获结合起来,可以使用聚合媒体源。聚合媒体源包含一组媒体源,并将所有的流合并到一个单一的媒体源对象中。要创建聚合媒体源的实例,调用 MFCreateAggregateSource 函数。
关闭设备
当不再需要捕获设备时,你必须通过调用 MFCreateDeviceSource 或 IMFActivate::ActivateObject 获取的 IMFMediaSource 对象上调用 Shutdown 来关闭设备。如果不调用 Shutdown,可能会导致内存链接,因为系统可能会保持对 IMFMediaSource 资源的引用,直到调用 Shutdown 为止。
if (g_pSource)
{g_pSource->Shutdown();g_pSource->Release();g_pSource = NULL;
}
如果申请了字符容器或者符号链接设别,你应该释放这些对象
CoTaskMemFree(g_pwszSymbolicLink);g_pwszSymbolicLink = NULL;g_cchSymbolicLink = 0;
这篇关于【MediaFoundation】读取音视频的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!