科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件DirectShow开发快速入门之慨述

DirectShow开发快速入门之慨述

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本篇文档概括性的介绍了DirectShow的主要组成部分,以及一些Directshow的基本概念。熟悉这些基本的知识对于Directshow的应用开发或者过滤器的开发者都会有所帮助。

作者:李强 来源:天极网 2007年10月17日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
3、媒体类型

  因为Directshow是基于com组件的,就需要有一种方式来描述filter graph每一个点的数据格式,例如,我们还以播放AVI文件为例,数据以RIFF块的形式进入graph中,然后被分割成视频和音频流,视频流有一系列的压缩的视频桢组成,解压后,视频流由一系列的无压缩的位图组成,音频流也要走同样的步骤。

Media Types: How DirectShow Represents Formats

  媒体类型是一种很普遍的,可以扩展的用来描述数字媒体格式的方法,当两个filter连接的时候,他们会就采用某一种媒体类型达成一致的协议。媒体类型定义了处于源头的filter将要给下游的filter发送什么样的数据,以及数据的physical layout。如果两个filter不能够支持同一种的媒体类型,那么他们就没法连接起来。

  对于大多数的应用来说,也许你不用考虑媒体类型,但是,有些应用程序中,你会直接应用到媒体类型的。

  媒体类型是通过AM_MEDIA_TYPE结构定义的,看看原始定义吧

typedef struct _MediaType {
 GUID majortype;
 GUID subtype;
 BOOL bFixedSizeSamples;
 BOOL bTemporalCompression;
 ULONG lSampleSize;
 GUID formattype;
 IUnknown *pUnk;
 ULONG cbFormat;
 [size_is(cbFormat)] BYTE *pbFormat;
} AM_MEDIA_TYPE;

  Major type:是一个GUID,用来定义数据的主类型,包括,音频,视频,unparsed字节流,MIDI数据,等等,具体可以参考msdn。

  Subtype:子类型,也是一个GUID,用来进一步的细化数据格式,例如,在视频主类型中,还包括RGB-24, RGB-32, UYVY等等一些子类型,在音频主类型中还包括PCM audio, MPEG-1 payload等类型,子类型提供了比主类型更详细的信息,但是并没有定义所有的格式,例如,视频的子类型并没有定义图像大小,桢率。这些由下面的字段定义。

  bFixedSizeSamples当这个值为TRUE时,表示sample大小固定。

  bTemporalCompression当这个值为TRUE时,表示sample采用了临时压缩格式,表明不是所有的桢都是关键桢,如果为FALSE,表明所有的都是关键桢。

  lSampleSize 表示sample的大小。对于压缩的数据,这个值可能为零。
  
  Formattype一个GUID值,用来表明内存块的格式。包括如下:FORMAT_None,FORMAT_DvInfo,FORMAT_MPEGVideo,FORMAT_MPEG2Video,FORMAT_VideoInfo,FORMAT_VideoInfo2,FORMAT_WaveFormatEx,GUID_NULL。

  pUnk该参数没有用到。

  cbFormat内存块的大小。

  pbFormat指向内存块的指针。

  下面我们看一段代码,看看filter如何检测媒体类型的。

HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt)
{
 if (pmt == NULL) return E_POINTER;
 // Check the major type. We’re looking for video.
 if (pmt->majortype != MEDIATYPE_Video)
 {
  return VFW_E_INVALIDMEDIATYPE;
 }
 // Check the subtype. We’re looking for 24-bit RGB.
 if (pmt->subtype != MEDIASUBTYPE_RGB24)
 {
  return VFW_E_INVALIDMEDIATYPE;
 }
 // Check the format type and the size of the format block.
 if ((pmt->formattype == FORMAT_VideoInfo) && (pmt->cbFormat >= sizeof(VIDEOINFOHEADER) &&
(pmt->pbFormat != NULL))
 {
  // Now it’s safe to coerce the format block pointer to the
  // correct structure, as defined by the formattype GUID.
  VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
  // Examine pVIH (not shown). If it looks OK, return S_OK.
  return S_OK;
 }
 return VFW_E_INVALIDMEDIATYPE;
}

  下面简单介绍几个和 Media Type相关的函数:

  AM_MEDIA_TYPE结构包含一个指向数据块的指针,因此,当你使用这个结构的时候,一定要小心内存分配,以防内存泄漏。

  分配函数

  1) AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc );

  这个函数分配一个新的AM_MEDIA_TYPE结构,包含特定格式的数据块。释放由这个函数分配的内存,可以调用DeleteMediaType函数

  2) STDAPI CreateAudioMediaType(const WAVEFORMATEX *pwfx,AM_MEDIA_TYPE *pmt,BOOL bSetFormat);

  该函数利用一个给定的WAVEFORMATIEX结构来初始化媒体类型,如果bsetFormat参数为TRUE,该函数就分配一块新的内存,如果原来的pmt已经包含内存,就有可能发生内存泄漏。为了避免内存泄漏,在调用这个函数前要调用FreeMediaType(),在这个函数返回之后,再次调用FreeMediaType(),释放format block。

  3) HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget,const AM_MEDIA_TYPE *pmtSource);

  这个函数复制了一个结构到另一个结构中去。这个函数也要重新分配内存给目的结构,如果pmtTarget,已经包含一个内存块,就要内存泄漏,因此,在调用该函数前后都要调用FreeMediaType函数。

  释放函数

  4) void WINAPI DeleteMediaType( AM_MEDIA_TYPE *pmt);

  无论是采用CoTaskMemAlloc函数还是用CreateMediaType函数分配的内存都可以用这个函数来释放,如果你没有连接基类的动态库,你可以用下面的代码

void MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
{
 if (pmt != NULL)
 {
  MyFreeMediaType(*pmt); // 见下面的 FreeMediaType 函数
  CoTaskMemFree(pmt);
 }
}

  5) void WINAPI FreeMediaType( AM_MEDIA_TYPE& mt);

  这个函数用来释放数据块的内存,如果要删除AM_MEDIA_TYPE结构,可以使用DeleteMediaType函数。

void MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
 if (mt.cbFormat != 0)
 {
  CoTaskMemFree((PVOID)mt.pbFormat);
  mt.cbFormat = 0;
  mt.pbFormat = NULL;
 }
 if (mt.pUnk != NULL)
 {
  // Unecessary because pUnk should not be used, but safest.
  mt.pUnk->Release();
  mt.pUnk = NULL;
 }
}
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章