您的位置:首页 > 其它

利用DirectShow实现对视频文件H264编码与解码基类

2015-03-26 11:04 471 查看
原文地址:利用DirectShow实现对视频文件H264编码与解码基类 作者:pamire

// Encode.h: interface for the CEncode class.

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ENCODE_H__F6B1A672_0A17_4011_87DA_F97CA0B0E52E__INCLUDED_)

#define AFX_ENCODE_H__F6B1A672_0A17_4011_87DA_F97CA0B0E52E__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include "streams.h"

#include "afxpriv.h"

# define SafeRelease(s) {if(s) {(s)->Release(); (s) = NULL;}}

# define WM_ENCODE_NOTIFY (WM_USER + 1200)

# define WM_DECODE_NOTIFY (WM_USER + 1201)

class CEncode

{

public:

CEncode();

virtual ~CEncode();

private:

struct _CODE_GRAPH

{

IGraphBuilder * pGraph;

IMediaControl * pControl;

IMediaEventEx * pEvent;

IMediaSeeking * pSeek;

IMediaFilter * pMedia;

ICaptureGraphBuilder2 * pBuilder;

}m_nEncode, m_nDecode; //Filter Graph Manager变量

struct _ENCODE_FILTER

{

IBaseFilter * pSrc;

IBaseFilter * pAviDecode;

IBaseFilter * pFileWrite;

IBaseFilter * pAviMux;

IBaseFilter * H264Encode;

IFileSinkFilter2 * pSink;

}m_nEncodeFilter; //Encode Graph变量

struct _DECODE_FILTER

{

IBaseFilter * pSrc;

IBaseFilter * pEncode;

IBaseFilter * pFileWrite;

IBaseFilter * pAviMux;

IBaseFilter * H264Decode;

IFileSinkFilter2 * pSink;

}m_nDecodeFilter; //Decode Graph变量

struct _CONTROL_STATE

{

int iProgress; //进度值(0 - 100)

bool bStop; //ture - 终止编码 false - 不终止编码

bool bStopFlag; //终止标志

bool bCompleted; //数据传输完成标志

}m_nEncodeCtl, m_nDecodeCtl; //Graph控制变量

public:

/********************功能函数*******************/

int CompressFile( CString strSourcePathName, CString strDestPathName); //实现视频文件的H264编码

int UnCompressFile( CString strSourcePathName, CString strDestPathName, CString strCompressorName); //对H264编码的视频文件用其它的编码器重新编码

int GetProgress(bool bFlag=true); //获得视频编码完成的进度

bool TerminiateProgress(bool bFlag=true); //终止视频编码

bool SetNotifyWindow(HWND inWindow, bool bFlag); //设置消息处理窗口

void OnCodecNotify(WPARAM inWParam, LPARAM inLParam, bool bFlags); //编码/解码消息处理

private:

/****************编码条件的检测*****************/

bool _IsFileOpenedCorrectly(CString strFileName);

bool _IsSuitedFileType(CString strFileName);

bool _HasDecodeFilter(CString strFileName);

int _IsH264Encoded(CString strFileName); //返回值:1 - 成功, 0 - 失败, -1 - 其它情况

int _HasH264Filter(bool bFlag); //返回值:1 - 成功 ,0 - 失败, -1 - 其它情况



/**************Filter Graph的创建与销毁************/

HRESULT _CreateFilterGraph(IGraphBuilder ** inGraph, ICaptureGraphBuilder2** inBuilder);

void _DestroyFilterGraph(IGraphBuilder * inGraph, ICaptureGraphBuilder2* inBuilder);

void _DestroyEncodeGraph();

void _DestroyDecodeGraph();

/*******************辅助功能函数*******************/

bool _CreateCompressDevice( CString strDevice , IBaseFilter ** pCompressorFilter ) ; //创建设备

bool _FindPins(IBaseFilter * pInFilter, bool bFlag, IPin ** pOutPin); //true - 输入pin, false - 输出pin

void _NukeDownstream(IGraphBuilder* inGraph, IBaseFilter * inFilter); //删除下游链路

};

#endif // !defined(AFX_ENCODE_H__F6B1A672_0A17_4011_87DA_F97CA0B0E52E__INCLUDED_)

// Encode.cpp: implementation of the CEncode class.

//

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "EncodeDemo.h"

#include "Encode.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CEncode::CEncode()

{

/*********Encode Graph中变量***********/

m_nEncode.pGraph = NULL;

m_nEncode.pBuilder = NULL;

m_nEncode.pControl = NULL;

m_nEncode.pEvent = NULL;

m_nEncode.pSeek = NULL;

m_nEncode.pMedia = NULL;

m_nEncodeFilter.H264Encode = NULL;

m_nEncodeFilter.pAviDecode = NULL;

m_nEncodeFilter.pAviMux = NULL;

m_nEncodeFilter.pFileWrite = NULL;

m_nEncodeFilter.pSink = NULL;

m_nEncodeFilter.pSrc = NULL;

/*********Decode Graph中变量***********/

m_nDecode.pGraph = NULL;

m_nDecode.pBuilder = NULL;

m_nDecode.pControl = NULL;

m_nDecode.pEvent = NULL;

m_nDecode.pSeek = NULL;

m_nDecode.pMedia = NULL;

m_nDecodeFilter.H264Decode = NULL;

m_nDecodeFilter.pAviMux = NULL;

m_nDecodeFilter.pEncode = NULL;

m_nDecodeFilter.pFileWrite = NULL;

m_nDecodeFilter.pSink = NULL;

m_nDecodeFilter.pSrc = NULL;

/*****Graph控制变量及状态变量*****/

m_nEncodeCtl.iProgress = 0;

m_nDecodeCtl.iProgress = 0;

m_nEncodeCtl.bStop = false;

m_nDecodeCtl.bStop = false;

m_nEncodeCtl.bStopFlag = false;

m_nDecodeCtl.bStopFlag = false;

m_nEncodeCtl.bCompleted = false;

m_nDecodeCtl.bCompleted = false;

}

CEncode::~CEncode()

{

/********异常退出资源释放*******/

// _DestroyEncodeGraph();

// _DestroyDecodeGraph();

}

int CEncode::CompressFile( CString strSourcePathName, CString strDestPathName)

{

/****************编码条件的检测*****************/

if(!_IsFileOpenedCorrectly(strSourcePathName))

return -3;

if(1 == _IsH264Encoded(strSourcePathName))

return -5;

if(!_HasDecodeFilter(strSourcePathName))

return -1;

if(0==_HasH264Filter(true))

return -2;

/*******************编码Graph创建的检测**************/

if (m_nEncode.pGraph&&m_nEncodeFilter.pSrc) //Filter Graph Manager已经创建

{

if(m_nEncode.pControl)

m_nEncode.pControl->Stop();//停止压缩

_NukeDownstream(m_nEncode.pGraph, m_nEncodeFilter.pSrc); //销毁下游链路

m_nEncode.pGraph->RemoveFilter(m_nEncodeFilter.pSrc);

SafeRelease(m_nEncode.pSeek);

SafeRelease(m_nEncode.pControl);

SafeRelease(m_nEncode.pEvent);

SafeRelease(m_nEncodeFilter.pSink);

SafeRelease(m_nEncodeFilter.pSrc);

_DestroyFilterGraph(m_nEncode.pGraph, m_nEncode.pBuilder);

}

/**************编码Graph的创建*************/

HRESULT hr = E_FAIL;

hr = _CreateFilterGraph(&m_nEncode.pGraph, &m_nEncode.pBuilder);

if(FAILED(hr))

{

AfxMessageBox("Uninitialize COM Library!");

return 0;

}

int iResult = 0;

do

{

/***************************查询接口***************************/

hr = m_nEncode.pGraph->QueryInterface(IID_IMediaControl, (void**)&m_nEncode.pControl);

if (FAILED(hr))//查询失败

break ;

hr = m_nEncode.pGraph->QueryInterface(IID_IMediaEventEx, (void**)&m_nEncode.pEvent);

if (FAILED(hr))//查询失败

break ;

hr = m_nEncode.pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_nEncode.pSeek);

if (FAILED(hr))//查询失败

break ;

hr = m_nEncode.pGraph->QueryInterface(IID_IMediaFilter, (void**)&m_nEncode.pMedia);

if (FAILED(hr))//查询失败

break ;



/*************************辅助Filter的创建*********************/

hr = m_nEncode.pGraph->AddSourceFilter(strSourcePathName.AllocSysString(), L"Source Filter", &m_nEncodeFilter.pSrc);

if(FAILED(hr))//添加失败

break ;

hr = CoCreateInstance(CLSID_***IDec, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_nEncodeFilter.pAviDecode);

if (FAILED(hr))//创建失败

break ;

hr = CoCreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_nEncodeFilter.pAviMux);

if (FAILED(hr)) //创建失败

break;

hr = m_nEncodeFilter.pAviMux->QueryInterface(IID_IMediaSeeking, (void**)&m_nEncode.pSeek);

if (FAILED(hr))//查询失败

break ;

hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC, IID_IFileSinkFilter2, (void**)&m_nEncodeFilter.pSink);

if (FAILED(hr)) //创建失败

break ;

hr = m_nEncodeFilter.pSink->QueryInterface(IID_IBaseFilter, (void**)&m_nEncodeFilter.pFileWrite);

if(FAILED(hr)) //创建失败

break ;

/* if(!_CreateCompressDevice("DT264 Compress Filter", &m_nEncodeFilter.H264Encode)) //创建压缩设备失败

break ; */

if (!m_nEncodeFilter.H264Encode) //H264Encode Filter 未被创建

break;

hr = m_nEncode.pGraph->AddFilter(m_nEncodeFilter.pAviDecode, L"***I Decompressor");

hr = m_nEncode.pGraph->AddFilter(m_nEncodeFilter.H264Encode, L"H264 Compress Filter");

/*******************Filter Graph链路的创建*******************/

hr = m_nEncode.pBuilder->RenderStream(NULL, NULL, m_nEncodeFilter.pSrc, m_nEncodeFilter.pAviDecode, m_nEncodeFilter.H264Encode);

if (FAILED(hr)) //创建链路失败

{

AfxMessageBox("\r该编解码器不支持所选的媒体类型,请下载相应的插件。\rCreate pSrc->pAviDecompress->pCompressFilter Failed!");

break;

}

hr = m_nEncode.pGraph->AddFilter(m_nEncodeFilter.pAviMux, L"***I Dest Filter");

hr = m_nEncode.pGraph->AddFilter((IBaseFilter *)m_nEncodeFilter.pFileWrite, L"File Write Filter");

hr = m_nEncodeFilter.pSink->SetMode(AM_FILE_OVERWRITE);

hr = m_nEncodeFilter.pSink->SetFileName(strDestPathName.AllocSysString() , NULL);

if(FAILED(hr))

{

iResult = -4;

break;

}

hr = m_nEncode.pBuilder->RenderStream(NULL, NULL, m_nEncodeFilter.H264Encode, m_nEncodeFilter.pAviMux, m_nEncodeFilter.pFileWrite);

if (FAILED(hr))

{

AfxMessageBox("\r该编解码器不支持所选的媒体类型,请下载相应的插件。\rCreate H264 Compress Filter->---->File Write Filter Failed!");

break;

}

hr=m_nEncode.pMedia->SetSyncSource(NULL);

hr = m_nEncode.pControl->Run(); //运行filter graph

if(SUCCEEDED(hr))

{

iResult = 1;

m_nEncodeCtl.bStopFlag = true;

}

}while(false);

return iResult;

}

int CEncode::UnCompressFile( CString strSourcePathName, CString strDestPathName, CString strCompressorName)

{

/****************编码条件的检测*****************/

if(!_IsFileOpenedCorrectly(strSourcePathName))

return -4;

if(!_IsSuitedFileType(strSourcePathName))

return -2;

if(0 == _IsH264Encoded(strSourcePathName))

return -1;

if(0==_HasH264Filter(false))

return -6;

/*******************编码Graph创建的检测**************/

if (m_nDecode.pGraph&&m_nDecodeFilter.pSrc) //Filter Graph Manager已经创建

{

if(m_nDecode.pControl)

m_nDecode.pControl->Stop();//停止压缩

_NukeDownstream(m_nDecode.pGraph, m_nDecodeFilter.pSrc); //销毁下游链路

m_nDecode.pGraph->RemoveFilter(m_nDecodeFilter.pSrc);

SafeRelease(m_nDecode.pSeek);

SafeRelease(m_nDecode.pControl);

SafeRelease(m_nDecode.pEvent);

SafeRelease(m_nDecodeFilter.pSink);

SafeRelease(m_nDecodeFilter.pSrc);

_DestroyFilterGraph(m_nDecode.pGraph, m_nDecode.pBuilder);

}

/**************编码Graph的创建*************/

HRESULT hr = E_FAIL;

hr = _CreateFilterGraph(&m_nDecode.pGraph, &m_nDecode.pBuilder);

if(FAILED(hr))

{

AfxMessageBox("Uninitialize COM Library!");

return -7;

}

int iResult = -7;

do

{

/***************************查询接口***************************/

hr = m_nDecode.pGraph->QueryInterface(IID_IMediaControl, (void**)&m_nDecode.pControl);

if (FAILED(hr))//查询失败

break ;

hr = m_nDecode.pGraph->QueryInterface(IID_IMediaEventEx, (void**)&m_nDecode.pEvent);

if (FAILED(hr))//查询失败

break ;

hr = m_nDecode.pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_nDecode.pSeek);

if (FAILED(hr))//查询失败

break ;

hr = m_nDecode.pGraph->QueryInterface(IID_IMediaFilter, (void**)&m_nDecode.pMedia);

if (FAILED(hr))//查询失败

break ;



/*************************辅助Filter的创建*********************/

hr = m_nDecode.pGraph->AddSourceFilter(strSourcePathName.AllocSysString(), L"Source Filter", &m_nDecodeFilter.pSrc);

if(FAILED(hr))//添加失败

break ;

hr = CoCreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_nDecodeFilter.pAviMux);

if (FAILED(hr)) //创建失败

break;

hr = m_nDecodeFilter.pAviMux->QueryInterface(IID_IMediaSeeking, (void**)&m_nDecode.pSeek);

if (FAILED(hr))//查询失败

break ;

hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC, IID_IFileSinkFilter2, (void**)&m_nDecodeFilter.pSink);

if (FAILED(hr)) //创建失败

break ;

hr = m_nDecodeFilter.pSink->QueryInterface(IID_IBaseFilter, (void**)&m_nDecodeFilter.pFileWrite);

if(FAILED(hr)) //创建失败

break ;

if (!m_nDecodeFilter.H264Decode) //H264Encode Filter 未被创建

break;

hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.H264Decode, L"H264 UnCompress Filter");

/*********************创建Graph中的上游链路(H264Decode)*****************/

hr = m_nDecode.pBuilder->RenderStream(NULL, NULL, m_nDecodeFilter.pSrc, NULL, m_nDecodeFilter.H264Decode);

if (FAILED(hr)) //创建链路失败

{

AfxMessageBox("\r该编解码器不支持所选的媒体类型,请下载相应的插件。\rCreate pSrc->pAviSplitter->H264UnCompressFilter Failed!");

break;

}

/**********************第三方编码器的检测********************/

if(strCompressorName.IsEmpty()) //压缩设备名为空

m_nDecodeFilter.pEncode = NULL;

else

if(!_CreateCompressDevice(strCompressorName, &m_nDecodeFilter.pEncode)) //创建压缩设备失败

{

iResult = -3;

break ;

}

/************************添加Filter到Graph中********************/

if(m_nDecodeFilter.pEncode)

{

hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.pEncode, L"Compress Filter");

if(FAILED(hr))

break;

}

hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.pAviMux, L"***I Dest Filter");

if(FAILED(hr))

break;

hr = m_nDecode.pGraph->AddFilter((IBaseFilter *)m_nDecodeFilter.pFileWrite, L"File Write Filter");

if(FAILED(hr))

break;

hr = m_nDecodeFilter.pSink->SetMode(AM_FILE_OVERWRITE);

if(FAILED(hr))

break;

hr = m_nDecodeFilter.pSink->SetFileName(strDestPathName.AllocSysString() , NULL);

if(FAILED(hr))

{

iResult = -5;

break;

}

/*********************创建Graph中的下游链路(H264Decode)*****************/

hr = m_nDecode.pBuilder->RenderStream(NULL, NULL, m_nDecodeFilter.H264Decode, m_nDecodeFilter.pEncode, m_nDecodeFilter.pFileWrite);

if (FAILED(hr))

{

AfxMessageBox("\r该编解码器不支持所选的媒体类型,请下载相应的插件。\rCreate H264 Filter->---->File Write Filter Failed!");

break;

}

hr=m_nDecode.pMedia->SetSyncSource(NULL);

hr = m_nDecode.pControl->Run(); //运行filter graph

if(SUCCEEDED(hr))

{

iResult = 1;

m_nDecodeCtl.bStopFlag = true;

}

}while(false);

return iResult;

}

int CEncode::GetProgress(bool bFlag)

{

HRESULT hr = E_FAIL;

if(bFlag) //压缩状态

{

if(m_nEncodeCtl.bCompleted) //数据传输完成

{

m_nEncodeCtl.bCompleted = false;

return 100;

}



}

else //解压状态

{

if(m_nDecodeCtl.bCompleted) //数据传输完成

{

m_nDecodeCtl.bCompleted = false;

return 100;

}

}

/********************获得数据传输的当前状态*********************/

IMediaSeeking * pSeek = bFlag? m_nEncode.pSeek : m_nDecode.pSeek;

LONGLONG lDuration = 1;

if(pSeek == NULL)

return -1;

hr = pSeek->GetDuration(&lDuration);

if(SUCCEEDED(hr)) //得到总的持续时间成功

{

LONGLONG Start = 0;

hr = pSeek->GetCurrentPosition(&Start); //得到当前的位置

if(SUCCEEDED(hr)) //获得当前的位置成功

{

int iProgress = (int)(100*(Start/((double)lDuration)));

if (bFlag) //压缩状态

{

m_nEncodeCtl.iProgress = iProgress;

return m_nEncodeCtl.iProgress;

}

else //解缩状态

{

m_nDecodeCtl.iProgress = iProgress;

return m_nDecodeCtl.iProgress;

}

}

return -1;

}

else

return -1;

}

bool CEncode::TerminiateProgress(bool bFlag)

{

HRESULT hr = E_FAIL;

if(bFlag)

{

/*********************终止编码*******************/

if(m_nEncode.pControl!=NULL&&m_nEncodeCtl.bStopFlag)

{

OAFilterState state = State_Stopped;

if (SUCCEEDED(m_nEncode.pControl->GetState(15, &state)/*得到当前状态*/))

{

if(state != State_Stopped)

hr = m_nEncode.pControl->Stop(); //停止filter graph

}

_DestroyEncodeGraph();

}

return SUCCEEDED(hr);

}

else

{

/*********************终止解码*******************/

if(m_nDecode.pControl!=NULL&&m_nDecodeCtl.bStopFlag)

{

OAFilterState state = State_Stopped;

if (SUCCEEDED(m_nDecode.pControl->GetState(15, &state)/*得到当前状态*/))

{

if(state != State_Stopped)

hr = m_nDecode.pControl->Stop(); //停止filter graph

}

_DestroyDecodeGraph();

}

return SUCCEEDED(hr);

}

}

bool CEncode::SetNotifyWindow(HWND inWindow, bool bFlag)

{

HRESULT hr = E_FAIL;

if (bFlag) //压缩过程

{

if(m_nEncode.pEvent)

{

hr = m_nEncode.pEvent->SetNotifyWindow((OAHWND)inWindow, WM_ENCODE_NOTIFY, 0);

return SUCCEEDED(hr);

}

}

else //解压过程

if(m_nDecode.pEvent)

{

hr = m_nDecode.pEvent->SetNotifyWindow((OAHWND)inWindow, WM_DECODE_NOTIFY, 0);

return SUCCEEDED(hr);

}

return false;

}

void CEncode::OnCodecNotify(WPARAM inWParam, LPARAM inLParam, bool bFlags)

{

IMediaEventEx * pEvent = bFlags? m_nEncode.pEvent:m_nDecode.pEvent;

if (pEvent)

{

LONG eventCode = 0, eventParam1 = 0, eventParam2 = 0;

while (SUCCEEDED(pEvent->GetEvent(&eventCode, &eventParam1, &eventParam2, 0)))

{

switch (eventCode)

{

case EC_COMPLETE: //数据传输完毕

TerminiateProgress(bFlags);

bFlags? (m_nEncodeCtl.bCompleted = true) : (m_nDecodeCtl.bCompleted = true);

break;

case EC_USERABORT: //运行出错

case EC_ERRORABORT:

TerminiateProgress(bFlags);

bFlags? (m_nEncodeCtl.bCompleted = true) : (m_nDecodeCtl.bCompleted = true);

break;

default:

break;

}

pEvent->FreeEventParams(eventCode, eventParam1, eventParam2);

}

}

}

int CEncode::_IsH264Encoded(CString strFileName)

{

IGraphBuilder * pGraph = NULL;

IBaseFilter * pSrc = NULL;

IBaseFilter * pAviSplitter = NULL;

HRESULT hr = E_FAIL;

int nResult = -1;

do

{

/******************创建Filter Graph Manager******************/

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);

if(FAILED(hr)) //创建Filter Graph Manager失败

{

AfxMessageBox("Create Filter Graph Manager Failed!");

return nResult;

}

int nlen = MultiByteToWideChar(CP_ACP, 0, strFileName, -1, NULL, NULL);

LPWSTR pstrFile = new WCHAR[nlen];

MultiByteToWideChar(CP_ACP, 0, strFileName, -1, pstrFile, nlen);



/***************创建Source Filter与***I Splitter Filter***************/

hr = pGraph->AddSourceFilter(pstrFile, L"Source Filter", &pSrc);

if(pstrFile)

delete pstrFile; //释放资源

if(FAILED(hr))//添加Source Filter失败

{

AfxMessageBox("Create Source Filter Failed!");

return nResult;

}

hr = CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviSplitter);

if(FAILED(hr))//创建Avi Splitter Filter 失败

{

AfxMessageBox("Add Avi Splitter Filer Failed!");

return nResult;

}

pGraph->AddFilter(pAviSplitter, L"***I Splitter");

/****************链接Source Filter 与***I Splitter Filter**************/

IPin * pSrcOutPin = NULL;

IPin * pAviInPin = NULL;

IPin * pAviOutPin = NULL;

if(_FindPins(pSrc, false, &pSrcOutPin)&&_FindPins(pAviSplitter, true, &pAviInPin))

{

hr = pGraph->Connect(pSrcOutPin, pAviInPin);

if(FAILED(hr)) //连接失败

{

pSrcOutPin->Release();

pAviInPin->Release();

AfxMessageBox("Connect Source Filter to Avi Splitter Failed!");

break;

}

else //连接成功

{

if(_FindPins(pAviSplitter, false, &pAviOutPin))

{

IEnumMediaTypes * pEnumType = NULL;

hr = pAviOutPin->EnumMediaTypes(&pEnumType);

if(FAILED(hr))//枚举pin的媒体类型失败

{

pAviOutPin->Release();

AfxMessageBox("Enum MediaTypes Failed!");

break;

}

else //枚举pin的媒体类型成功

{

AM_MEDIA_TYPE * mediaType;

ULONG nfeched = 0;

pEnumType->Reset();

while(SUCCEEDED(pEnumType->Next(1, &mediaType, &nfeched))&&nfeched)//枚举媒体类型

{

static const GUID MEDIASUBTYPE_DT264=

{0x52445444, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}};

if(mediaType->subtype == MEDIASUBTYPE_DT264) //为H264编码文件

{

nResult = 1;

DeleteMediaType(mediaType);

break;

}

else ////不为H264编码文件

nResult = 0;

DeleteMediaType(mediaType);

}

pEnumType->Release();

}

pAviOutPin->Release();

}

pGraph->Disconnect(pSrcOutPin);

pGraph->Disconnect(pAviInPin);

pSrcOutPin->Release();

pAviInPin->Release();

}

}

else //查找Source Filter的输出pin或Avi Splitter Filter的输入pin失败

return nResult;

}while(false);

/********************释放资源*********************/

if(pAviSplitter)

{

pGraph->RemoveFilter(pAviSplitter);

SafeRelease(pAviSplitter);

}

if(pSrc)

{

pGraph->RemoveFilter(pSrc);

SafeRelease(pSrc);

}

SafeRelease(pGraph);

return nResult;

}

bool CEncode::_IsFileOpenedCorrectly(CString strFileName)

{

bool bOpened = false;

char * pFileName = (LPSTR)(LPCTSTR)strFileName;

try

{

CFile f(pFileName, CFile::modeRead|CFile::shareDenyNone);

bOpened = true;

f.Close();

}

catch(CFileException e)

{

bOpened = false;

throw;

}

return bOpened;

}

bool CEncode::_IsSuitedFileType(CString strFileName)

{

if(strFileName.IsEmpty())

return false;

if (strFileName.GetLength()<5) //文件名长度小于5

return false;

else //文件名长度大于5

{

if ((strFileName.Right(4)).Compare(".avi")!=0) //文件名后四位不为.avi

return false;

}

return true;

}

bool CEncode::_HasDecodeFilter(CString strFileName)

{

IGraphBuilder * pGraph = NULL;

IBaseFilter * pSrc = NULL;

HRESULT hr = E_FAIL;

bool bHas = false;

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);

if(SUCCEEDED(hr))

{

int nlen = MultiByteToWideChar(CP_ACP, 0, strFileName, -1, NULL, NULL);

LPWSTR pstrFile = new WCHAR[nlen];

MultiByteToWideChar(CP_ACP, 0, strFileName, -1, pstrFile, nlen);

hr = pGraph->RenderFile(pstrFile, NULL);

delete pstrFile;

if(SUCCEEDED(hr))

{

bHas = true;

hr = pGraph->FindFilterByName(pstrFile, &pSrc);

if(pSrc)

{

_NukeDownstream(pGraph, pSrc);

pGraph->RemoveFilter(pSrc);

pSrc->Release();

}

}

else

bHas = false;

pGraph->Release();

}

return bHas;

}

int CEncode::_HasH264Filter(bool bFlag )

{

HRESULT hr=E_FAIL;

int iResult = -1;

/**************创建系统枚举器并获得ICreateDevEnum接口*****************/

ICreateDevEnum * pEnumHardware=NULL;//定义一个指向ICreateDevEnum接口的指针

hr=CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_ALL, IID_ICreateDevEnum, (void**)&pEnumHardware);

if(FAILED(hr))//创建失败返回

return iResult;

/**************创建类型目录枚举器并获得IEnumMoniker接口*****************/

CString strTempName = bFlag? "DT264 Compress Filter":"DT264 Decompress Filter";

REFCLSID CLSID_TempCategory = bFlag? CLSID_VideoCompressorCategory : CLSID_LegacyAmFilterCategory;

IBaseFilter * pTempFilter = NULL;

IEnumMoniker * pEnumMoniker=NULL;//定义一个指向IEnumMoniker接口的指针

hr=pEnumHardware->CreateClassEnumerator(CLSID_TempCategory, &pEnumMoniker ,0);

if(pEnumMoniker)//创建类型目录枚举器成功且IEnumMoniker接口不为空

{

pEnumMoniker->Reset();//重置枚举序列到初始状态

ULONG fetched=0;

IMoniker * pMoniker=NULL;

//当查询IMoniker接口成功且未成功创建设备filter时,做for循环

while(SUCCEEDED(pEnumMoniker->Next(1, &pMoniker, &fetched))&&fetched)

{

if(pMoniker)//查询IMoniker接口成功

{

IPropertyBag * pPropertyBag=NULL;

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

if(FAILED(hr))

{

iResult = -1;

continue;

}

VARIANT name;

name.vt=VT_BSTR;

hr=pPropertyBag->Read(L"FriendlyName", &name , NULL);//获得设备的友好名

if (SUCCEEDED(hr))//获取设备的友好名成功

{

char friendlyName[256];

friendlyName[0]=0;

WideCharToMultiByte(CP_ACP, 0, name.bstrVal, -1, friendlyName, 256, NULL, NULL);

if(strcmp(friendlyName, (LPSTR)(LPCTSTR)strTempName)==0)

{

iResult = 1;

hr=pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pTempFilter);//创建设备filter

if(FAILED(hr))//创建设备filter成功

AfxMessageBox("\r对该文件进行编解码,需要H264编解码器,请下载并安装相应的插件。\rCreate H264 Filter Failed!");

else

bFlag? (m_nEncodeFilter.H264Encode = pTempFilter):(m_nDecodeFilter.H264Decode = pTempFilter);

break;

}

else

iResult = 0;

}

pPropertyBag->Release();//propertyBag不为空时,释放其内存空间

pMoniker->Release();

}

}

pEnumMoniker->Release();

}

pEnumHardware->Release();

return iResult;

}

bool CEncode::_FindPins(IBaseFilter * pInFilter, bool bFlag, IPin ** pOutPin)

{

ASSERT(pInFilter);

HRESULT hr = E_FAIL;

bool bReturned = false;

IEnumPins * pEnumPins;

hr = pInFilter->EnumPins(&pEnumPins);

if(FAILED(hr))

return bReturned;

IPin * pPin = NULL;

ULONG nfetched = 0;

pEnumPins->Reset();

while(SUCCEEDED(pEnumPins->Next(1, &pPin, &nfetched))&&nfetched)

{

if(pPin)//查询pin成功

{

PIN_DIRECTION pinDir;

PIN_DIRECTION pinDirection = bFlag? PINDIR_INPUT : PINDIR_OUTPUT;

hr = pPin->QueryDirection(&pinDir);

if(FAILED(hr)) //查询pin的方向失败

{

pPin->Release();

continue;

}

else //查询pin的方向成功

{

if(pinDir == pinDirection)

{

IPin * pConnectedPin = NULL;

hr = pPin->ConnectedTo(&pConnectedPin);

if(FAILED(hr))//该pin已被连接

{

* pOutPin = pPin;

bReturned = true;

}

else//该pin未被连接

{

pPin->Release();

pConnectedPin->Release();

continue;

}

}

}

}

}

pEnumPins->Release();

return bReturned;

}

void CEncode::_NukeDownstream(IGraphBuilder* inGraph, IBaseFilter * inFilter)

{

if (!inGraph || !inFilter)

return ;

IEnumPins * pinEnum = NULL;

if (SUCCEEDED(inFilter->EnumPins(&pinEnum))) //枚举所有的pin成功

{

pinEnum->Reset();

IPin * pin = NULL;

ULONG fetched = 0;

while (SUCCEEDED(pinEnum->Next(1, &pin, &fetched)) && fetched)//查询pin成功

{

if (pin)

{

IPin * connectedPin = NULL;

pin->ConnectedTo(&connectedPin);//得到与该pin相连的pin

if (connectedPin) //与查询pin相连的pin不为空

{

PIN_INFO pininfo;

if (SUCCEEDED(connectedPin->QueryPinInfo(&pininfo)))//查询pin的方向成功

{

if (pininfo.dir == PINDIR_INPUT) //连接的pin为输入pin

{

_NukeDownstream(inGraph, pininfo.pFilter);//递归调用

inGraph->Disconnect(connectedPin);

inGraph->Disconnect(pin);

inGraph->RemoveFilter(pininfo.pFilter);//从Filter Graph中移除

}

pininfo.pFilter->Release();

}

connectedPin->Release();

}

pin->Release();

pin = NULL;

}

}

pinEnum->Release();

}

}

bool CEncode::_CreateCompressDevice( CString strDevice , IBaseFilter ** pCompressorFilter)

{

HRESULT hr=S_OK;

bool bCreated = false;

IBaseFilter * pTempFilter = NULL;

ICreateDevEnum * enumHardware=NULL;//定义一个指向ICreateDevEnum接口的指针

hr=CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_ALL, IID_ICreateDevEnum, (void**)&enumHardware);//创建一个系统设备枚举器并获得ICreateDevEnum接口

if(FAILED(hr))//创建失败返回

return false;

IEnumMoniker * enumMoniker=NULL;//定义一个指向IEnumMoniker接口的指针

hr=enumHardware->CreateClassEnumerator(CLSID_VideoCompressorCategory, &enumMoniker ,0);//创建一个类型目录枚举器并获得IEnumMoniker接口

if(enumMoniker)//创建类型目录枚举器成功且IEnumMoniker接口不为空

{

enumMoniker->Reset();//重置枚举序列到初始状态

ULONG fetched=0;

IMoniker * moniker=NULL;

char friendlyName[256];

//当查询IMoniker接口成功且未成功创建设备filter时,做for循环

while(SUCCEEDED(enumMoniker->Next(1, &moniker, &fetched))&&fetched)

{

if(moniker)//查询IMoniker接口成功

{

IPropertyBag * propertyBag=NULL;

VARIANT name;

friendlyName[0]=0;

hr=moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&propertyBag);

if(SUCCEEDED(hr))

{

name.vt=VT_BSTR;

hr=propertyBag->Read(L"FriendlyName", &name , NULL);//获得设备的友好名

}

if (SUCCEEDED(hr))//获取设备的友好名成功

{

WideCharToMultiByte(CP_ACP, 0, name.bstrVal, -1, friendlyName, 256, NULL, NULL);

if(strcmp(friendlyName, (LPSTR)(LPCTSTR)strDevice)==0)

{

hr=moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pTempFilter);//创建设备filter

if(SUCCEEDED(hr))//创建设备filter成功

{

*pCompressorFilter = pTempFilter;

bCreated = true;

}

}

}

if(propertyBag)//propertyBag不为空时,释放其内存空间

{

propertyBag->Release();

propertyBag=NULL;

}

moniker->Release();

}

}

enumMoniker->Release();

}

enumHardware->Release();

return bCreated;

}

HRESULT CEncode::_CreateFilterGraph(IGraphBuilder ** inGraph, ICaptureGraphBuilder2 ** inBuilder)

{

HRESULT hr = E_FAIL;

IGraphBuilder * pGraph = NULL;

ICaptureGraphBuilder2 * pBuilder = NULL;

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);

if(SUCCEEDED(hr))//创建Filter Graph Manager成功

{

*inGraph = pGraph;

hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuilder);

if(SUCCEEDED(hr)) //创建辅助组件成功

{

hr = pBuilder->SetFiltergraph(pGraph);

*inBuilder = pBuilder;

}

else //创建辅助组件失败

AfxMessageBox("Create Capture Graph Builder object Failed!");

}

else //创建Filter Graph Manager失败

AfxMessageBox("Create Filter Graph Manager Failed!");

return hr;

}

void CEncode::_DestroyEncodeGraph()

{

/*************释放资源***************/

SafeRelease(m_nEncode.pSeek);

SafeRelease(m_nEncode.pControl);

SafeRelease(m_nEncode.pEvent);

SafeRelease(m_nEncodeFilter.pSink);

if (m_nEncode.pGraph&&m_nEncodeFilter.pSrc)

{

_NukeDownstream(m_nEncode.pGraph, m_nEncodeFilter.pSrc); //销毁下游链路

m_nEncode.pGraph->RemoveFilter(m_nEncodeFilter.pSrc);

SafeRelease(m_nEncodeFilter.pSrc);

}

_DestroyFilterGraph(m_nEncode.pGraph, m_nEncode.pBuilder);

}

void CEncode::_DestroyDecodeGraph()

{

/*************释放资源***************/

SafeRelease(m_nDecode.pSeek);

SafeRelease(m_nDecode.pControl);

SafeRelease(m_nDecode.pEvent);

SafeRelease(m_nDecodeFilter.pSink);

if (m_nDecode.pGraph&&m_nDecodeFilter.pSrc)

{

_NukeDownstream(m_nDecode.pGraph, m_nDecodeFilter.pSrc); //销毁下游链路

m_nDecode.pGraph->RemoveFilter(m_nDecodeFilter.pSrc);

SafeRelease(m_nDecodeFilter.pSrc);

}

_DestroyFilterGraph(m_nDecode.pGraph, m_nDecode.pBuilder);

}

void CEncode::_DestroyFilterGraph(IGraphBuilder * inGraph, ICaptureGraphBuilder2 * inBuilder)

{

SafeRelease(inBuilder);

SafeRelease(inGraph);

}

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=571400
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: