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

    技术2022-05-11  69

    // 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_FILEstatic 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);}


    最新回复(0)