DirectShow应用:用程序连接Filters实现媒体播放

本文介绍了如何在Windows下使用DirectShow通过编程连接Filters来实现媒体播放。首先枚举系统中的Filters并管理,接着创建Filter目录项列表和Filter列表,通过友好名称获取Filter。然后介绍如何通过IGraphBuilder接口连接Filters,最后展示了一个播放avi文件的示例,包括添加和连接各个Filter的过程。
摘要由CSDN通过智能技术生成

                 DirectShow应用:用程序连接Filters实现媒体播放

 

Windows平台下的音视频应用,多以DirectShow为开发工具,通过Graphedit选择合适的Filters并连接成实际的链路,就可以实现简单播放。但在程序中如何实现呢,笔者带着这个问题进行了探索,现将初步成果呈现出来,以期收抛砖引玉之效,共同提高。

一.       枚举Filters

Windows系统中的Filters都经过了注册,并按照Filter目录进行组织,故为方便应用程序设计,宜将系统中所有的Filter依照其目录结构枚举出来,统一存放和管理,为此,设计了一个类CFilterManager来进行统一的管理,其定义如下:

#pragma once

#include "strmif.h"

#include "CurrentDevice.h"

#include "Category.h"

#include "ReadyFilter.h"

#pragma comment(lib,"strmiids.lib")

#pragma comment(lib,"quartz.lib")

class CFilterManager

{

public:

         ~CFilterManager(void);

         HRESULT init(void);

         IBaseFilter *GetFilterByFriendlyName(CString friendlyName );

         IBaseFilter *GetFilterByClsid( CLSIDclsid );

         IBaseFilter *GetFilterByDisplayName(CString displayName );

         staticCFilterManager *GetInstance( void );

         voidPlayFiles( void );

public:

         HRESULT EnumFilters(IEnumMoniker*pEnumCat, CLSID category);

         CList<CCategory *, CCategory *>mCategoryList;

         CList<CReadyFilter *, CReadyFilter*> mReadyFilterList;

private:

         HRESULT ConnectFilters( IGraphBuilder*pGraph, IBaseFilter *pSource, IBaseFilter *pTarget );

         CFilterManager(void);

         voidCreateCategory( void );

         voidCreateFilters( void );

         CComPtr<ICreateDevEnum>pCreateDevEnum;

         staticCFilterManager *pManager;

};

成员变量pCreateDevEnum用于存放系统枚举指针,列表mCategoryList存放所有Filter目录项,列表mReadyFilterList用于存放所有枚举到的Filter

系统中只应有一个Filter管理者实例,故此类设计成单件Singlton模式,通过静态函数GetInstance获取其唯一实例,其实现代码如下:

CFilterManager *CFilterManager::GetInstance( void )

{

         if(NULL == pManager )

         {

                   pManager = new CFilterManager();

                   if(NULL != pManager )

                   {

                            HRESULT hr =pManager->init();

                            if( FAILED(hr) )

                            {

                                     pManager =NULL;

                                     return NULL;

                            }

                            pManager->CreateCategory();

                            pManager->CreateFilters();

                   }

         }

         returnpManager;

}

如上所示,在第一次创建实例成功后,即调用init函数进行COM组件库的初始化,如初始化失败则撤销新建的实例,返回NULL以阻止后续程序操作。初始化成功后,再调用函数CreateCategory枚举系统中所有的Filter目录项,并存于列表mCategoryList中,调用CreateFilters枚举所有的Filters存于列表mReadFilterList中,这样所有的Filter都在掌握之中,方便查取。由于这几个函数只需调用一次,故放在这里与创建唯一实例的代码连成一体。

HRESULTCFilterManager::init(void)

{

         // Initializethe COM library

         HRESULT hr = CoInitializeEx( NULL,COINIT_APARTMENTTHREADED );

         if(FAILED(hr) )

         {

                   AfxMessageBox( _T("COM initializing failed!") );

                   returnhr;

         }

    // Create thesystem device enumerator.

    hr =CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,

                          IID_ICreateDevEnum, (void**)&pCreateDevEnum);

         returnhr;

}

以上代码首先调用CoInitializeEx初始化COM库,然后取得系统设备枚举器指针pCreateDevEnum供后面的代码使用。

void CFilterManager::CreateCategory( void )

{

         ASSERT( NULL != pCreateDevEnum );

 

    HRESULT hr;

    CComPtr<IEnumMoniker> pEmCat;

         CComPtr<IPropertyBag> pPropBag;

         // Use themeta-category that contains a list of all categories.

         hr =pCreateDevEnum->CreateClassEnumerator( CLSID_ActiveMovieCategories,&pEmCat, NULL );

         // Enumerateover every category and get the category CLSID and description.

         if(FAILED(hr) )

         {

                   return;

         }

    CComPtr<IMoniker> pMoniker;

         ULONG wished = 1, fetched = 1;

    while( S_OK== pEmCat->Next( wished, &pMoniker, &fetched ) )

    {

                   VARIANT varCatName;

                   VariantInit(&varCatName);

                   VARIANT varCatClsid;

                   VariantInit(&varCatClsid);

                   CLSID clsidCat;

 

        // Associatemoniker

        hr = pMoniker->BindToStorage(0, 0,IID_IPropertyBag, (void **)&pPropBag);

                   //Read CLSID string from property bag

                   if(SUCCEEDED(hr))

                   {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值