音频转码 via Media Foundation
音频转码 via Media Foundation
- Media Foundation 简介
- Media Foundation 转码音频
- Transcoding 流程图
- Transcoding 代码
- setTranscodeProfile 函数
- CTranscodeTopoBuilder::_setAudioAttributes 函数
- CTranscodeTopoBuilder::_setContainerAttributes 函数
- CTranscodeTopoBuilder::createTranscodeTopology 函数
- IMFAsyncCallback::Invoke 函数
- 其他框架的转码
转码(transcoding)其实就是把音频从一种编码转换成另一种编码的过程,如 MP3 → WMA。基本流程如下图:
Media Foundation 简介
Media Foundation (简称 MF)是微软在 Windows Vista上 推出的新一代多媒体应用库,目的是提供 Windows 平台一个统一的多媒体影音解决方案,开发者可以通过 MF 播放视频或声音文件、进行多媒体文件格式转码,或者将一连串图片编码为视频等等。
MF 是 DirectShow 为主的旧式多媒体应用程序接口的替代者与继承者,在微软的计划下将逐步汰换 DirectShow 技术。MF 要求 Windows Vista 或更高版本,不支持较早期的 Windows 版本,特别是 Windows XP。
MF 长于高质量的音频和视频播放,高清内容(如 HDTV,高清电视)和数字版权管理(DRM)访问控制。MF 在不同的 Windows 版本上能力不同,如 Windows 7 上就添加了 h.264 编码支持。Windows 8 上则提供数种更高质量的设置。
MF 提供了两种编程模型,第一种是以 Media Session 为主的 Media pipeline 模型,但是该模型太过复杂,且曝露过多底层细节,故微软于 Windows 7 上推出第二种编程模型,内含 SourceReader、Transcode API 、SinkWriter 及 MFPlay 等高度封装模块,大大简化了 MF 的使用难度。
# 本文使用了第二种(简单的)编程模型。
Media Foundation 转码音频
Transcoding 流程图
Transcoding 代码
以下是整个 MF 转码过程的概要代码,略去 TopoBuilder 类的实现:
HRESULT CTranscodeApi::transcodeFile(PCWSTR pszInput, PCWSTR pszOutput)
{HRESULT hr = S_OK;CComPtr<IMFTopology> pTopology; hr = MFCreateMediaSession(NULL, &m_pSession);RETURN_IF_FAILED(hr);hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);RETURN_IF_FAILED(hr);hr = _setTranscodeProfile(pszOutput);RETURN_IF_FAILED(hr);hr = m_topoBuilder.createTranscodeTopology(pszInput, pszOutput);RETURN_IF_FAILED(hr);pTopology = m_topoBuilder.getTopology();hr = m_pSession->SetTopology(0, pTopology);if (SUCCEEDED(hr)) {PROPVARIANT varStart;PropVariantClear(&varStart);hr = m_pSession->Start(&GUID_NULL, &varStart);}return hr;
}
setTranscodeProfile 函数
Windows7以上系统默认支持 AAC 和 WMA encoder。
HRESULT CTranscodeApi::_setTranscodeProfile(LPCTSTR pszOutputFile)
{HRESULT hr = E_NOTIMPL;LPCTSTR ext = pszOutputFile + _tcslen(pszOutputFile) - 3;if (_tcsicmp(ext, _T("aac")) == 0) {hr = m_topoBuilder.SetTranscodeProfile(MFAudioFormat_AAC, GUID_NULL, MFTranscodeContainerType_MPEG4); }else if (_tcsicmp(ext, _T("wma")) == 0) {hr = m_topoBuilder.SetTranscodeProfile(MFAudioFormat_WMAudioV9, GUID_NULL, MFTranscodeContainerType_ASF); }return hr;
}HRESULT CTranscodeTopoBuilder::setTranscodeProfile(const GUID& audioFormat, // target audio formatconst GUID& videoFormat, // target video formatconst GUID& containerType) // target file container
{HRESULT hr = S_OK;hr = MFCreateTranscodeProfile(&m_pTranscodeProfile);RETURN_IF_FAILED(hr);hr = _setAudioAttributes(audioFormat);RETURN_IF_FAILED(hr);hr = _setVideoAttributes(videoFormat);RETURN_IF_FAILED(hr);hr = _setContainerAttributes(containerType);RETURN_IF_FAILED(hr);return hr;
}
CTranscodeTopoBuilder::_setAudioAttributes 函数
枚举所有支持的输出媒体类型并选择第一个。
HRESULT CTranscodeTopoBuilder::_setAudioAttributes(const GUID& audioFormat)
{HRESULT hr = S_OK;CComPtr<IMFCollection> pAudioTypeCollection;CComPtr<IMFAttributes> pAudioAttrs;// enumerate all of the audio encoders that match the specified// parameters and find all audio types that can be generated. DWORD dwFlags = (MFT_ENUM_FLAG_ALL & (~MFT_ENUM_FLAG_FIELDOFUSE)) | MFT_ENUM_FLAG_SORTANDFILTER; hr = MFTranscodeGetAudioOutputAvailableTypes(audioFormat, // specify the requested audio formatdwFlags, // get all MFTs except for the FOU, and sortNULL, // no custom attributes&pAudioTypeCollection); // store result in specified collectionRETURN_IF_FAILED(hr);// get the first element from the collection of media types, // copy all the information of the first type into a new attribute// collection, and return the attribute collectionhr = getTypeAttributesFromTypeCollection(pAudioTypeCollection, 0, pAudioAttrs);RETURN_IF_FAILED(hr);hr = m_pTranscodeProfile->SetAudioAttributes(pAudioAttrs);RETURN_IF_FAILED(hr);return hr;
}
CTranscodeTopoBuilder::_setContainerAttributes 函数
设置媒体容器的类型,如 MP3,AVI 等。
HRESULT CTranscodeTopoBuilder::_setContainerAttributes(const GUID& containerType)
{HRESULT hr = S_OK;CComPtr<IMFAttributes> pContainerAttributes;RETURN_IF_NULL(m_pTranscodeProfile);hr = MFCreateAttributes(&pContainerAttributes, 1);RETURN_IF_FAILED(hr);// store an attribute that indicates that we want to write to an ASF filehr = pContainerAttributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, // attribute ID GUID - container typecontainerType); // generate the specified containerRETURN_IF_FAILED(hr);// store the container attributes in the transcode profilehr = m_pTranscodeProfile->SetContainerAttributes(pContainerAttributes);RETURN_IF_FAILED(hr);return hr;
}
CTranscodeTopoBuilder::createTranscodeTopology 函数
MF 提供了 transcoding 专用的 topology。
HRESULT CTranscodeTopoBuilder::createTranscodeTopology(PCWSTR pszInput, PCWSTR pszOutput)
{HRESULT hr = S_OK;// standard media source creationhr = createMediaSource(pszInput, m_pSource);RETURN_IF_FAILED(hr);// create the actual transcode topology based on the transcode profilehr = MFCreateTranscodeTopology(m_pSource, // the source of the content to transcodepszOutput, // output filenamem_pTranscodeProfile, // transcode profile to use&m_pTopology); // resulting topologyRETURN_IF_FAILED(hr);return hr;
}
IMFAsyncCallback::Invoke 函数
Media Session 的 所有事件 都会回调这里。当收到 MESessionEnded 事件时就说明转码结束了。
注意:转码未完时要重新 BeginGetEvent,不然就傻傻等不到下一个事件了。
HRESULT CTranscodeApi::Invoke(IMFAsyncResult* pAsyncResult)
{CComPtr<IMFMediaEvent> pEvent;HRESULT hr = S_OK;MediaEventType eventType;// Get the event from the event queue.hr = m_pSession->EndGetEvent(pAsyncResult, &pEvent);RETURN_IF_FAILED(hr);// Get the event type.hr = pEvent->GetType(&eventType);RETURN_IF_FAILED(hr);if (eventType == MESessionEnded) {hr = m_pSession->Close();}else if (eventType == MESessionClosed) {SetEvent(m_closeCompleteEvent);}else {hr = m_pSession->BeginGetEvent(this, NULL);}RETURN_IF_FAILED(hr);return S_OK;
}
其他框架的转码
- 关于 FFmpeg 的音频转码请参考 这里。
- 关于 DirectShow 的音频转码请参考 这里。
– EOF –
音频转码 via Media Foundation相关推荐
- 音频特效滤镜 via Media Foundation Transform (MFT)
音频特效滤镜 via Media Foundation Transform 音频特效定义 Media Foundation Transform IMFTransform::GetInputStream ...
- Media Foundation
1简介 Media Foundation是微软在Windows Vista上推出的新一代多媒体应用库,目的是提供Windows平台一个统一的多媒体影音解决方案,开发者可以通过Media Foundat ...
- 音视频播放 via Media Foundation II
音视频播放 via Media Foundation II Media Foundation 简介 Media Foundation 播放音视频 播放流程图 播放代码 MFPlayer 类 MFPla ...
- 音频转码 via FFmpeg
音频转码 via FFmpeg FFmpeg 简介 FFmpeg 命令行转码 FFmpeg API 转码 Transcoding 流程图 Transcoding 代码 open_input_file ...
- 音频转码 via DirectShow
音频转码 via DirectShow DirectShow 简介 DirectShow 转码 Transcoding 流程图 Transcoding 代码 _initGraph 函数 _addEnc ...
- Android 音频源码分析——AndroidRecord录音(一)
Android 音频源码分析--AndroidRecord录音(一) Android 音频源码分析--AndroidRecord录音(二) Android 音频源码分析--AndroidRecord音 ...
- Media Foundation——媒体类型(1)
Media Foundaton对象的属性和特性 每一个对象上的数据,都可通过"属性(Attributes)"和"特性(Properties)"来设置.描述.属性 ...
- Microsoft Media Foundation官方文档翻译(20)《Stream Subtype GUIDs》《...
官方英文文档链接:https://docs.microsoft.com/en-us/windows/desktop/medfound/stream-subtype-guids 基于05/31/2018 ...
- Media Foundation与DirectShow的具体差别有哪些
DirectShow是微软公司在ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,与Dire ...
最新文章
- C# 实现Oracle中的数据与Excel之间的转换
- 这68个Python内置函数,建议你吃透!
- SPCAMLEditor–灵活实用的CAML编辑工具(上)
- 结构体指针struct stu *p;和结构体变量struct stu p;结构体为什么要用指针引用而不用变量引用
- vsftp虚拟用户权限问题
- mariadb用户群体mysql_mysql(mariadb)新建用户及用户授权管理
- cuda和cudnn各版本下载地址
- 中国象棋,源码,开发,毕业设计,go,qt,c++,gin,游戏,残局,悔棋,人机,网络对战,双人
- python幂次_python n次幂
- 工厂生产管理流程有哪些环节?
- bmp,jpg,png,tif,wmf,emf与eps图片格式转换
- 求100到1000内水仙花数及个数
- 计算机操作员考试模拟在线考试,计算机操作员高级问答集考试卷模拟考_试题...
- 【独立按键鼠标式的单击与双击】
- 拼多多蓝海词数据分析:如何优化拼多多关键词?拼多多标题关键词优化方法。
- android socket 推送服务版本
- SqlServer Tigger
- Array,String 方法
- 联想台式机 ubuntu 16.04 安装 Nvidia GTX 1060 3g 驱动
- 求职与面试(一):Android必备
热门文章
- PHP与正则表达式 | 黄乔国PHP
- html video标签播放直播视频,HTML5 Video 标签播放及控制视频
- Qt 实现系统托盘,托盘菜单,托盘消息
- mysql 主备和双主模式_MySQL双主模式
- java out of memory_java中OutOfMemory种类和解决方法
- 对称与魔术初步(一)——美丽的对称
- vm虚拟机中的虚拟网络编辑器出现 不能更改网络为桥接:已经没有桥接的主机网络适配器的 解决方案
- python保存灰度图像_如何使用matplotlib/numpy将数组保存为灰度图像?
- 关于keil常见问题解决方法记录error: #268: declaration may not appear after executable statement in block
- 张勇:阿里巴巴所有产品未来将接入大模型全面改造