/**************編碼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;
}