利用DirectShow實現對視頻檔案H264編碼與解碼基類

來源:互聯網
上載者:User

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.