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

// 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值