见到网络上好多朋友从事流媒体开发,而不得法,到处求助而又有很少人回复,本人也是深有感触,现在断断续续的从事了一年多
的directshow的开发,对directshow有了一点点了解,在此写出来给那些初学者一些帮助,当然,本人水平也很差,如果在说明的
过程中有错误或者不对的地方,请大家多提意见和指正。。
1、首先说下媒体格式
audio:我所了解的wav、mp3、wma三中格式,基本上我都是先把它们解码成pcm的基本音频格式进行处理的。至于如何转换成wav
(PCM)格式的我就不多说了,通过一些decode解码器,在用wavedest的filter写到文件就成wav文件了,在这里我说一下两个wav文
件的合成。基本的音频文件的合成可以使用每个数据的叠加,数据的/2叠加等方法来合成两个音频数据。至于声音文件的放大,可
以对每个数据按照比例放大,当然要注意越界的问题。这里所说的合成是采样率、位数都相同的情况下。还有就是pcm数据的组成
格式,比如,8位的wav歌曲,双声道,它数据的存放格式是左、右、左、右这种格式,对于声道的拆分也可以采用这种格式。
video:常见的压缩格式有h263 h263++,mpeg1(avi,vcd)等基本是参照mpeg1的和h263是不同的两中标准。mpeg2居于dvd品质的
压缩格式,和dvd有一小点区别,mpeg4是现在最流行的基于网络的流媒体压缩格式,用的开源的有xvid,vidx等编解码器。最后就
是h264,是mpeg和定义h263的两个组织共同定义的,同等品质下的压缩率是mpeg4的一半。本人水平有限,对编解码没有研究,基
本上都是用别人的,编解码我就不多说了。对音频的处理,我只限于对基本的bmp图的处理。下面说说如何将音频数据和无压缩的
原始bmp图合成为avi。通过capture拿到sample,然后扩充dump的fi个合成sample戳,然后用wmwriter把这两个sample写到文件里
面。
2、下面说说简单的流媒体传输
基于directshow的架构的流,基本上是以sample为核心的,就是说我们只要拿到一个sample,把它通过网络发送出去,接收端接收
到以后把它复原(可以自己实现Allocater来开发smaple pool,也可以直接从编解码的input pin来获得sample来填充),然后通
过output pin 把它deliver到后面的filter就可以了
先说一个不处理的音频、视频流的传输
audio capture-> audio sender ##### net ##### audio receiver -> audio render
vidio caputre-> video sender #### new ##### video receiver -> video render
先说sender:重载CBaseInputPin,然后在媒体格式设置的时候,如下
HRESULT GetMediaType (IN int iPos,OUT CMediaType * pmt)
{
if(iPos==0)
{
pmt-> InitMediaType();
pmt-> SetType(&MEDIATYPE_Video);
pmt-> SetType(&MEDIASUBTYPE_RGB24);
return S_OK;
}
return VFW_S_NO_MORE_ITEMS ;
}
HRESULT CheckMediaType (IN const CMediaType * pmt)
{
ASSERT(pmt);
//if(pmt-> majortype != MEDIATYPE_Video && pmt-> subtype != MEDIASUBTYPE_XVID_TRANSPORT) return
S_FALSE;
if(pmt-> majortype == MEDIATYPE_Video && pmt-> subtype == MEDIASUBTYPE_RGB24)
{
VIDEOINFO *pInfo = (VIDEOINFO *) pmt-> Format();
if(pInfo-> bmiHeader.biWidth == 160 &&
pInfo-> bmiHeader.biHeight==120 ) return S_OK;
}
return E_INVALIDARG;
}
然后在input 的receive事件里面 发送sample的数据就可以了。
至于receive端:有两种模式,一种是自己实现IMemAllocator,这时候就要破坏pin协商的时候的(DecideAllocator)的input端
的开辟的请求,可以参考dsnetwork的receiver,一种就是默认的从output pin,GetDeliveryBuffer得到sample接口,然后把接收
到的值的buf填充就可以了,然后调用output pin 的deliver 下发下去就可以了。
------解决方案--------------------------------------------------------
Hi:
At it happens I have a problem how to let WMP load our source streaming filter. You known WMP can play remote files on the Internet; I guess it must load the File Source (URL) that can parse the protocol of http; then it can download the media content and play them.
So I want to do like the File Source (URL) to load our source streaming filter and parse the protocol RTSP. And I do followings:
[HKEY_CLASSES_ROOT\rtsp]
@= "RTSP "
"Source Filter "= "{11D7C001-211E-4492-BEDA-B0AF7348B12D} "
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shell\URLProtocols\rtsp]