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