分类: WINDOWS
2007-01-31 11:58:15
// 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_AVIDec, 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"AVI 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"AVI 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"AVI 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与AVI 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"AVI Splitter");
/****************链接Source Filter 与AVI 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