C++ 配置MPEG4MediaSink
我正在尝试构建一个简单的WMF演示应用程序,它使用媒体源、管道和媒体接收器来复制MP4文件。以下是基本程序C++ 配置MPEG4MediaSink,c++,windows,ms-media-foundation,C++,Windows,Ms Media Foundation,我正在尝试构建一个简单的WMF演示应用程序,它使用媒体源、管道和媒体接收器来复制MP4文件。以下是基本程序 创建媒体源,并从中获取表示描述符 从中获取第一个活动视频和音频流描述符 表示描述符 从每个流中获取当前视频和音频IMFMediaTypes 描述符。检查表明视频媒体子类型为H264 音频媒体子类型为AAC 使用两种介质MFCreateMPEG4MediaSink打开介质接收器 类型和输出文件名 使用流和流设置视频和音频源节点 表示描述符 使用媒体接收器设置视频和音频接收器节点 将所有节点添
我已经使用MFCreateMP3MediaSink成功地对MP3文件进行了类似的复制,但这种情况下的媒体类型是MP3。在Mediafoundation示例中,您有LogMediaType函数 你能给我们看一下AAC音频的MediaType日志吗 通常,以下是AAC所需的一些属性(某些值可能不同):
- MF\U MT\U主要类型:MFMediaType\U音频
- MF\U MT\U子类型:MFAudioFormat\U AAC或MEDIASUBTYPE\U RAW\U AAC1
- MF\u MT\u音频\u首选\u波形:正确
- MF\U MT\U AAC\U有效负载类型:0
- MF\U MT\U AAC\U音频配置文件\U电平\U指示:0
- 音频频道:6个
- 音频采样率:每秒48000
- 音频块对齐:24
- 音频平均字节/秒:1152000
- MF\u MT\u音频\u位\u每个样本:32
- 音频通道屏蔽:63
- MF_MT_USER_DATA:byte array==AudioSpecificConfig(取决于MFAudioFormat_AAC或MEDIASUBTYPE_RAW_AAC1)
- MF\u MT\u MPEG4\u示例\u说明:字节数组
- MF\U MT\U MPEG4\u当前\u样本\u条目:0
- MF\u MT\u平均比特率:x
- MF\U MT\U AM\U格式\U类型:clsid
- MF\u MT\u所有样本\u独立:1
- MF\U MT\U固定尺寸\U样品:1
- MF\U MT\U样本大小:1
是否将音频源节点连接到右侧IMFStreamLink。您是否使用了IMFMediaSink中的正确索引?谢谢大家的帮助!!本例中的问题是在创建输出节点时使用了硬编码流索引0。在我的辩护中,各种WMF样本似乎只演示了每个接收器一个流,因此使用硬编码流索引0。我的代码基于这些示例,并将该部分分解到实用程序库中,但很快就忘记了它是一个特例。当然,MP4接收器使用两个流,在解析拓扑时,流索引0用于音频中断 这里是我的音频媒体类型的设置。一旦我对streamsink问题进行了分类,这种媒体类型配置就可以正常工作。这些问题被分解为与上述示例音频媒体类型内容相同、不同、额外和缺失的项目 相同
MF_MT_MAJOR_TYPE=MFMediaType_Audio (73647561-0000-0010-8000-00aa00389b71)
MF_MT_SUBTYPE=AAC (00001610-0000-0010-8000-00aa00389b71)
MF_MT_AUDIO_PREFER_WAVEFORMATEX=1
MF_MT_AAC_PAYLOAD_TYPE=0
MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION=0
MF_MT_AUDIO_NUM_CHANNELS=6
MF_MT_AUDIO_SAMPLES_PER_SECOND=48000
不同
MF_MT_AUDIO_BLOCK_ALIGNMENT=1
MF_MT_AUDIO_AVG_BYTES_PER_SECOND=47995
MF_MT_AUDIO_BITS_PER_SAMPLE=16
未知
MF_MT_USER_DATA=00,00,00,00,00,00,00,00,00,00,00,00,11,b0
额外的
MF_MT_AVG_BITRATE=383960
MF_MT_MPEG4_SAMPLE_DESCRIPTION=00,00,00,67,73,74,73,64,00,00,00,00,00,00,00,01...
MF_MT_AM_FORMAT_TYPE=Unknown (05589f81-c356-11ce-bf01-00aa0055595a)
MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY=0
MF_MT_FIXED_SIZE_SAMPLES=1
MF_MT_ALL_SAMPLES_INDEPENDENT=1
MF_MT_SAMPLE_SIZE=1
缺失
MF_MT_AUDIO_CHANNEL_MASK : 63
只是为了好玩,我以一种快速的方式重写了您的程序:
//----------------------------------------------------------------------------------------------
// Main.cpp
//----------------------------------------------------------------------------------------------
#pragma once
#define WIN32_LEAN_AND_MEAN
#define STRICT
#pragma comment(lib, "mf")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")
#include <WinSDKVer.h>
#include <new>
#include <windows.h>
#include <mfapi.h>
#include <mfidl.h>
#include <wchar.h>
#define MP4_SOURCE_VIDEO_MEDIA_FILE L"big_buck_bunny_720p_50mb.mp4"
#define MP4_FINAL_VIDEO_MEDIA_FILE L"final.mp4"
HRESULT ProcessConverter(LPCWSTR);
HRESULT ConfigureSource(LPCWSTR, IMFMediaSource**, IMFMediaType**, IMFMediaType**, IMFTopologyNode**, IMFTopologyNode**);
HRESULT CreateMediaSource(LPCWSTR, IMFMediaSource**);
HRESULT ConfigureMediaTypeSource(IMFMediaSource*, IMFPresentationDescriptor*, IMFStreamDescriptor*, IMFMediaType**, IMFMediaType**, IMFTopologyNode**, IMFTopologyNode**);
HRESULT CreateTopologyNodeSink(IMFMediaSink*, IMFTopologyNode**, IMFTopologyNode**, IMFMediaType*, IMFMediaType*);
HRESULT CreateSourceStreamNode(IMFMediaSource*, IMFPresentationDescriptor*, IMFStreamDescriptor*, IMFTopologyNode**);
HRESULT ConfigureSinkNode(IMFMediaTypeHandler*, IMFStreamSink*, IMFTopologyNode**, IMFMediaType*);
HRESULT ConfigureTopologyNode(IMFTopology*, IMFTopologyNode*, IMFTopologyNode*, IMFTopologyNode*, IMFTopologyNode*);
HRESULT RunMediaSession(IMFMediaSession*);
template <class T> inline void SAFE_RELEASE(T*& p){
if(p){
p->Release();
p = NULL;
}
}
void main() {
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if(SUCCEEDED(hr)) {
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
if(SUCCEEDED(hr)) {
hr = ProcessConverter(MP4_SOURCE_VIDEO_MEDIA_FILE);
hr = MFShutdown();
}
CoUninitialize();
}
}
HRESULT ProcessConverter(LPCWSTR wszVideoFile){
HRESULT hr = S_OK;
IMFMediaSource* pSource = NULL;
IMFMediaType* pVideoMediaType = NULL;
IMFMediaType* pAudioMediaType = NULL;
IMFByteStream* pByteStream = NULL;
IMFMediaSink* pMediaSink = NULL;
IMFTopology* pTopology = NULL;
IMFTopologyNode* pVideoSourceNode = NULL;
IMFTopologyNode* pAudioSourceNode = NULL;
IMFTopologyNode* pVideoSinkNode = NULL;
IMFTopologyNode* pAudioSinkNode = NULL;
IMFMediaSession* pSession = NULL;
hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, MP4_FINAL_VIDEO_MEDIA_FILE, &pByteStream);
if(FAILED(hr)){ goto done; }
hr = ConfigureSource(wszVideoFile, &pSource, &pVideoMediaType, &pAudioMediaType, &pVideoSourceNode, &pAudioSourceNode);
if(FAILED(hr)){ goto done; }
hr = MFCreateMPEG4MediaSink(pByteStream, pVideoMediaType, pAudioMediaType, &pMediaSink);
if(FAILED(hr)){ goto done; }
hr = CreateTopologyNodeSink(pMediaSink, &pVideoSinkNode, &pAudioSinkNode, pVideoMediaType, pAudioMediaType);
if(FAILED(hr)){ goto done; }
hr = MFCreateTopology(&pTopology);
if(FAILED(hr)){ goto done; }
hr = ConfigureTopologyNode(pTopology, pVideoSourceNode, pAudioSourceNode, pVideoSinkNode, pAudioSinkNode);
if(FAILED(hr)){ goto done; }
hr = MFCreateMediaSession(NULL, &pSession);
if(FAILED(hr)){ goto done; }
hr = pSession->SetTopology(0, pTopology);
if(FAILED(hr)){ goto done; }
hr = RunMediaSession(pSession);
done:
if(pSession){
hr = pSession->Close();
// todo : normally wait for close event, here just Sleep
Sleep(1000);
}
if(pMediaSink){
hr = pMediaSink->Shutdown();
SAFE_RELEASE(pMediaSink);
}
if(pSource){
hr = pSource->Shutdown();
SAFE_RELEASE(pSource);
}
if(pSession){
hr = pSession->Shutdown();
SAFE_RELEASE(pSession);
}
SAFE_RELEASE(pByteStream);
SAFE_RELEASE(pAudioMediaType);
SAFE_RELEASE(pVideoMediaType);
SAFE_RELEASE(pAudioSinkNode);
SAFE_RELEASE(pVideoSinkNode);
SAFE_RELEASE(pAudioSourceNode);
SAFE_RELEASE(pVideoSourceNode);
SAFE_RELEASE(pTopology);
return hr;
}
HRESULT ConfigureSource(LPCWSTR wszVideoFile, IMFMediaSource** ppSource, IMFMediaType** ppVideoMediaType, IMFMediaType** ppAudioMediaType, IMFTopologyNode** ppVideoSourceNode, IMFTopologyNode** ppVAudioSourceNode){
HRESULT hr = S_OK;
IMFPresentationDescriptor* pPresentationDescriptor = NULL;
IMFStreamDescriptor* pStreamDescriptor = NULL;
DWORD dwStreamCount = 0;
BOOL bSelected = FALSE;
hr = CreateMediaSource(wszVideoFile, ppSource);
if(FAILED(hr)){ goto done; }
hr = (*ppSource)->CreatePresentationDescriptor(&pPresentationDescriptor);
if(FAILED(hr)){ goto done; }
hr = pPresentationDescriptor->GetStreamDescriptorCount(&dwStreamCount);
if(FAILED(hr)){ goto done; }
for(DWORD dwStream = 0; dwStream < dwStreamCount; dwStream++){
hr = pPresentationDescriptor->GetStreamDescriptorByIndex(dwStream, &bSelected, &pStreamDescriptor);
if(FAILED(hr)){
break;
}
if(bSelected){
hr = ConfigureMediaTypeSource(*ppSource, pPresentationDescriptor, pStreamDescriptor, ppVideoMediaType, ppAudioMediaType, ppVideoSourceNode, ppVAudioSourceNode);
}
SAFE_RELEASE(pStreamDescriptor);
if(FAILED(hr) || ((*ppVideoMediaType) && (*ppAudioMediaType))){
break;
}
}
done:
SAFE_RELEASE(pStreamDescriptor);
SAFE_RELEASE(pPresentationDescriptor);
// We just only if video and audio stream are presents
if((*ppVideoMediaType) == NULL && (*ppAudioMediaType) == NULL)
hr = E_FAIL;
return hr;
}
HRESULT CreateMediaSource(LPCWSTR wszVideoFile, IMFMediaSource** ppSource){
MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
IMFSourceResolver* pSourceResolver = NULL;
IUnknown* pSource = NULL;
HRESULT hr = MFCreateSourceResolver(&pSourceResolver);
if(FAILED(hr)){ goto done; }
hr = pSourceResolver->CreateObjectFromURL(wszVideoFile, MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &pSource);
if(FAILED(hr)){ goto done; }
hr = pSource->QueryInterface(IID_PPV_ARGS(ppSource));
done:
SAFE_RELEASE(pSourceResolver);
SAFE_RELEASE(pSource);
return hr;
}
HRESULT ConfigureMediaTypeSource(IMFMediaSource* pSource, IMFPresentationDescriptor* pPresentationDescriptor, IMFStreamDescriptor* pStreamDescriptor, IMFMediaType** ppVideoMediaType,
IMFMediaType** ppAudioMediaType, IMFTopologyNode** ppVideoSourceNode, IMFTopologyNode** ppAudioSourceNode){
HRESULT hr = S_OK;
IMFMediaTypeHandler* pHandler = NULL;
IMFMediaType* pMediaType = NULL;
DWORD dwTypeCount = 0;
GUID MajorType = GUID_NULL;
hr = pStreamDescriptor->GetMediaTypeHandler(&pHandler);
if(FAILED(hr)){ goto done; }
hr = pHandler->GetMediaTypeCount(&dwTypeCount);
if(FAILED(hr)){ goto done; }
for(DWORD dwType = 0; dwType < dwTypeCount; dwType++){
hr = pHandler->GetMediaTypeByIndex(dwType, &pMediaType);
if(hr == S_OK){
hr = pMediaType->GetMajorType(&MajorType);
if(hr == S_OK){
if(MajorType == MFMediaType_Video && (*ppVideoMediaType) == NULL){
hr = pHandler->SetCurrentMediaType(pMediaType);
if(hr == S_OK){
//LogMediaType(pMediaType);
hr = CreateSourceStreamNode(pSource, pPresentationDescriptor, pStreamDescriptor, ppVideoSourceNode);
if(hr == S_OK){
*ppVideoMediaType = pMediaType;
(*ppVideoMediaType)->AddRef();
break;
}
}
}
else if(MajorType == MFMediaType_Audio && (*ppAudioMediaType) == NULL){
hr = pHandler->SetCurrentMediaType(pMediaType);
if(hr == S_OK){
//LogMediaType(pMediaType);
hr = CreateSourceStreamNode(pSource, pPresentationDescriptor, pStreamDescriptor, ppAudioSourceNode);
if(hr == S_OK){
*ppAudioMediaType = pMediaType;
(*ppAudioMediaType)->AddRef();
break;
}
}
}
}
}
SAFE_RELEASE(pMediaType);
}
done:
SAFE_RELEASE(pMediaType);
SAFE_RELEASE(pHandler);
return hr;
}
HRESULT CreateSourceStreamNode(IMFMediaSource* pSource, IMFPresentationDescriptor* pPresentationDescriptor, IMFStreamDescriptor* pStreamDescriptor, IMFTopologyNode** ppNode){
HRESULT hr = S_OK;
IMFTopologyNode* pNode = NULL;
hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode);
if(FAILED(hr)){ goto done; }
hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);
if(FAILED(hr)){ goto done; }
hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPresentationDescriptor);
if(FAILED(hr)){ goto done; }
hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pStreamDescriptor);
if(FAILED(hr)){ goto done; }
*ppNode = pNode;
(*ppNode)->AddRef();
done:
SAFE_RELEASE(pNode);
return hr;
}
HRESULT CreateTopologyNodeSink(IMFMediaSink* pMediaSink, IMFTopologyNode** ppVideoSinkNode, IMFTopologyNode** ppAudioSinkNode, IMFMediaType* pVideoMediaType, IMFMediaType* pAudioMediaType){
HRESULT hr = S_OK;
DWORD dwCount = 0;
IMFStreamSink* pStreamSink = NULL;
IMFMediaTypeHandler* pHandler = NULL;
GUID MajorType = GUID_NULL;
hr = pMediaSink->GetStreamSinkCount(&dwCount);
if(FAILED(hr)){ goto done; }
for(DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++){
hr = pMediaSink->GetStreamSinkByIndex(dwIndex, &pStreamSink);
if(hr == S_OK){
hr = pStreamSink->GetMediaTypeHandler(&pHandler);
if(hr == S_OK){
hr = pHandler->GetMajorType(&MajorType);
if(hr == S_OK){
if(MajorType == MFMediaType_Video)
hr = ConfigureSinkNode(pHandler, pStreamSink, ppVideoSinkNode, pVideoMediaType);
else if(MajorType == MFMediaType_Audio)
hr = ConfigureSinkNode(pHandler, pStreamSink, ppAudioSinkNode, pAudioMediaType);
}
if(hr == S_OK && (*ppVideoSinkNode) != NULL && (*ppAudioSinkNode) != NULL){
break;
}
}
SAFE_RELEASE(pHandler);
}
SAFE_RELEASE(pStreamSink);
}
done:
SAFE_RELEASE(pHandler);
SAFE_RELEASE(pStreamSink);
if((*ppVideoSinkNode) == NULL || (*ppAudioSinkNode) == NULL)
hr = E_FAIL;
return hr;
}
HRESULT ConfigureSinkNode(IMFMediaTypeHandler* pHandler, IMFStreamSink* pStreamSink, IMFTopologyNode** ppSinkNode, IMFMediaType* pMediaType){
HRESULT hr = S_OK;
IMFTopologyNode* pNode = NULL;
hr = pHandler->SetCurrentMediaType(pMediaType);
if(FAILED(hr)){ goto done; }
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
if(FAILED(hr)){ goto done; }
hr = pNode->SetObject(pStreamSink);
if(FAILED(hr)){ goto done; }
*ppSinkNode = pNode;
(*ppSinkNode)->AddRef();
done:
SAFE_RELEASE(pNode);
return hr;
}
HRESULT ConfigureTopologyNode(IMFTopology* pTopology, IMFTopologyNode* pVideoSourceNode, IMFTopologyNode* pAudioSourceNode, IMFTopologyNode* pVideoSinkNode, IMFTopologyNode* pAudioSinkNode){
HRESULT hr = S_OK;
hr = pTopology->AddNode(pVideoSourceNode);
if(FAILED(hr)){ goto done; }
hr = pTopology->AddNode(pAudioSourceNode);
if(FAILED(hr)){ goto done; }
hr = pTopology->AddNode(pVideoSinkNode);
if(FAILED(hr)){ goto done; }
hr = pTopology->AddNode(pAudioSinkNode);
if(FAILED(hr)){ goto done; }
hr = pVideoSourceNode->ConnectOutput(0, pVideoSinkNode, 0);
if(FAILED(hr)){ goto done; }
hr = pAudioSourceNode->ConnectOutput(0, pAudioSinkNode, 0);
done:
return hr;
}
HRESULT RunMediaSession(IMFMediaSession* pSession){
HRESULT hr = S_OK;
BOOL bSessionEvent = TRUE;
while(bSessionEvent){
HRESULT hrStatus = S_OK;
IMFMediaEvent* pEvent = NULL;
MediaEventType meType = MEUnknown;
MF_TOPOSTATUS TopoStatus = MF_TOPOSTATUS_INVALID;
hr = pSession->GetEvent(0, &pEvent);
if(SUCCEEDED(hr)){
hr = pEvent->GetStatus(&hrStatus);
}
if(SUCCEEDED(hr)){
hr = pEvent->GetType(&meType);
}
if(SUCCEEDED(hr) && SUCCEEDED(hrStatus)){
switch(meType){
case MESessionTopologySet:
wprintf(L"MESessionTopologySet\n");
break;
case MESessionTopologyStatus:
hr = pEvent->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, (UINT32*)&TopoStatus);
if(SUCCEEDED(hr)){
switch(TopoStatus){
case MF_TOPOSTATUS_READY:
{
wprintf(L"MESessionTopologyStatus: MF_TOPOSTATUS_READY\n");
PROPVARIANT varStartPosition;
PropVariantInit(&varStartPosition);
hr = pSession->Start(&GUID_NULL, &varStartPosition);
PropVariantClear(&varStartPosition);
}
break;
case MF_TOPOSTATUS_STARTED_SOURCE:
wprintf(L"MESessionTopologyStatus: MF_TOPOSTATUS_STARTED_SOURCE\n");
break;
case MF_TOPOSTATUS_ENDED:
wprintf(L"MESessionTopologyStatus: MF_TOPOSTATUS_ENDED\n");
break;
default:
wprintf(L"MESessionTopologyStatus: %d\n", TopoStatus);
break;
}
}
break;
case MESessionStarted:
wprintf(L"MESessionStarted\n");
break;
case MESessionEnded:
wprintf(L"MESessionEnded\n");
hr = pSession->Stop();
break;
case MESessionStopped:
wprintf(L"MESessionStopped\n");
hr = pSession->Close();
break;
case MESessionClosed:
wprintf(L"MESessionClosed\n");
bSessionEvent = FALSE;
break;
case MESessionNotifyPresentationTime:
wprintf(L"MESessionNotifyPresentationTime\n");
break;
case MESessionCapabilitiesChanged:
wprintf(L"MESessionCapabilitiesChanged\n");
break;
case MEEndOfPresentation:
wprintf(L"MEEndOfPresentation\n");
break;
default:
wprintf(L"Media session event: %d\n", meType);
break;
}
SAFE_RELEASE(pEvent);
if(FAILED(hr) || FAILED(hrStatus)){
bSessionEvent = FALSE;
}
}
}
return hr;
}
//----------------------------------------------------------------------------------------------
//Main.cpp
//----------------------------------------------------------------------------------------------
#布拉格语一次
#定义WIN32_精益_和_平均值
#定义严格
#pragma注释(lib,“mf”)
#pragma注释(lib,“mfplat”)
#pragma注释(lib,“mfuuid”)
#包括
#包括
#包括
#包括
#包括
#包括
#定义MP4\u源\u视频\u媒体\u文件L“big\u buck\u bunny\u 720p\u 50mb.MP4”
#定义MP4\u FINAL\u VIDEO\u MEDIA\u文件L“FINAL.MP4”
HRESULT进程转换器(LPCWSTR);
HRESULT配置源(LPCWSTR、IMFMediaSource**、IMFMediaType**、IMFMediaType**、IMFTopologyNode**、IMFTopologyNode**);
HRESULT CreateMediaSource(LPCWSTR、IMFMediaSource**);
HRESULT配置MediaTypeSource(IMFMediaSource*、IMFPresentationDescriptor*、IMFStreamDescriptor*、IMFMediaType**、IMFMediaType**、IMFTopologyNode**、IMFTopologyNode**);
HRESULT CreateTopologyNodeLink(IMFMediaSink*、IMFTopologyNode**、IMFTopologyNode**、IMFMediaType*、IMFMediaType*);
HRESULT CreateSourceStreamNode(IMFMediaSource*、IMFPresentationDescriptor*、IMFStreamDescriptor*、IMFTopologyNode**);
HRESULT ConfigureSinkNode(IMFMediaTypeHandler*、IMFStreamSink*、IMFTopologyNode**、IMFMediaType*);
HRESULT配置拓扑节点(IMFTopology*、IMFTopologyNode*、IMFTopologyNode*、IMFTopologyNode*、IMFTopologyNode*);
HRESULT RunMediaSession(IMFMediaSession*);
模板内联作废安全发布(T*&p){
如果(p){
p->Release();
p=零;
}
}
void main(){
HRESULT hr=coinitializex(NULL,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
如果(成功(hr)){
hr=MFS