加载中…
个人资料
南冠彤
南冠彤
  • 博客等级:
  • 博客积分:0
  • 博客访问:411,815
  • 关注人气:59
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

(转)TS Source Filter + MPEG-2 Demultiplexer Filter进行简单的TS流

(2013-01-10 12:49:04)
标签:

杂谈

分类: 音视频

// 所有原创文章转载请注明作者及链接
//
blackboycpp(AT)gmail.com
// QQ群: 135202158

这个Filter的主要作用是把TS文件分割成TS包并发送至下游的MPEG-2 Demultiplexer(Push模式)。
通过在GraphEdit里(当然也可以编码实现)对MPEG-2 Demultiplexer进行必要的设置,
再连接一些Decoder和Render filters, 可以播放此TS文件。

首先, MPEG-2 Demultiplexer是可以用于push模式的:(http://msdn.microsoft.com/en-us/library/dd390717(VS.85).aspx)

 


The MPEG-2 Demultiplexer ("demux") can operate in push mode or pull mode. In push mode, the data comes from a live source, such as a network broadcast. In pull mode, the data comes from a local file.

 

  • Pull mode is available in Windows XP and later, for program streams only. On down-level platforms, use the MPEG-2 Splitter filter.
  • Push mode is available on all platforms, for both program streams and transport streams.

 

 


 

 

1. 首先安装DirectX SDK 9.0c并配置好环境(包括BaseClasses的编译), 如果是在VC++2005下进行工作, 可以看我以前的转帖日志

2. 找一个TS文件, 如果机器上没有, 可以下载这个:http://www.dododge.net/roku/hd-test-streams/wjz-200309111230-clip.ts

   它是一个单节目TS流, 格式为:  视频(codec: MPEG4, PID:0x11), 音频(codec: AC3, PID:0x14)

2. 把位于“DirectX安装目录/Samples/C++/DirectShow/Filters”下的Ball例子复制一个, 我们就要改它了

3. 打开ball工程, 做以下改动:

 (1)修改输出pin媒体格式

  

  1. const AMOVIESETUP_MEDIATYPE sudOpPinTypes  
  2.  
  3.     &MEDIATYPE_Stream,  
  4.     &MEDIASUBTYPE_MPEG2_TRANSPORT  
  5. };  
 

 (2)注释掉不必要的函数, 主要是(如果编译时出错, 视情况再注释掉其他无用函数):

  1. //HRESULT SetMediaType(const CMediaType *pMediaType);  
  2. //HRESULT CheckMediaType(const CMediaType *pMediaType);  
  3. //HRESULT GetMediaType(int iPosition, CMediaType *pmt);  
  4. //STDMETHODIMP Notify(IBaseFilter pSender, Quality q);  
 

添加一个成员函数:

  1.           
  2. HRESULT  GetMediaType(CMediaType *pMediaType);  
  3. HRESULT CBallStream::GetMediaType(CMediaType *pmt)  
  4.  
  5.     CheckPointer(pmt,E_POINTER);  
  6.     CAutoLock cAutoLock(m_pFilter->pStateLock());  
  7.     pmt->SetType(&MEDIATYPE_Stream);  
  8.     pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_TRANSPORT);  
  9.     pmt->SetTemporalCompression(FALSE);  
  10.     return NOERROR;  
  11. // GetMediaType  
 

(3)添加一些成员, 用于操作我们的TS文件:

  1. private 
  2.     FILE m_file;    // TS文件指针  
  3.     int    m_flen;    // TS文件长度  
  4.     int    m_offset;  // TS文件读取偏移  
 

(4)在OnThreadCreate()成员函数中添加以下代码:

  1. // 打开你硬盘上的TS文件  
  2. m_file fopen("F://test.ts""rb");    
  3. // 获取文件长度  
  4. fseek(m_file, 0L, SEEK_END);  
  5. m_flen ftell(m_file);  
  6. // 我下载的这个文件,TS同步头0x47从第79字节开始  
  7. fseek(m_file, 79L, SEEK_SET);    
  8. m_offset 79;  
 

(5)在DecideBufferSize()成员函数中,将每个buffer大小改成188字节:

  1. pProperties->cbBuffer 188;  
 

(6)修改FillBuffer()成员函数:

  1. HRESULT CBallStream::FillBuffer(IMediaSample *pms)  
  2.  
  3.     CheckPointer(pms,E_POINTER);  
  4.     ASSERT(m_Ball);  
  5.     BYTE *pData;  
  6.     long lDataLen;  
  7.     pms->GetPointer(&pData);  
  8.     lDataLen pms->GetSize();  
  9.     ZeroMemory(pData, lDataLen);  
  10.      
  11.         CAutoLock cAutoLockShared(&m_cSharedState);  
  12.                 // 重复读文件  
  13.         if(m_offset >= m_flen)     
  14.          
  15.             m_offset 79;  
  16.             fseek(m_file, 79L, SEEK_SET);  
  17.          
  18.                 // 用188字节的TS包数据填充Buffer  
  19.         fread(pData, 1, 188, m_file);  
  20.         m_offset += 188;  
  21.      
  22.         // 实际数据长度为188字节  
  23.     pms->SetActualDataLength(188);  
  24.     pms->SetSyncPoint(FALSE);  
  25.     return NOERROR;  
  26. // FillBuffer  
 

(7)在CBallStream的构造和析构函数里添加一些初始化/反初始化代码, 主要是一些文件操作。

再检查一下还有哪些无关的代码没注释掉。

4. 编译工程, 如果出错, 依提示修改。 应该主要是一些以前例子的东西, 注释掉就可以了。

5. 使用regsvr32命令注释你生成的Filter,如:

 

  1. // 注册:  
  2. D:/Ball/Debug>regsvr32 ball.ax  
  3. // 反注册:  
  4. D:/Ball/Debug>regsvr32 /u ball.ax  
 

6. 打开Grapedit(在DirectX SDK的DirectX Utilities中), 插入Bouncing Ball Filter和Mpeg-2 Demultiplexer Filter,

再把它们对应的pin相连。 并配置Mpeg-2 Demultiplexer, 设置好各个pin对应的媒体类型,映射好PID,

并将Pin输出的数据结构设为Elementary Stream (A/V only), 如下所示:

然后再添加Audio Render, Video Render,这时MPEG-2 Demultiplexer上应该会出现相应的输出pins,

点右键选render pin即可。 Graph Edit会自动挑选解码器并完成连接。 连接好的Filter Graph如下图:

 

 

 

然后运行graph就可以了

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有