📄 h264.cpp
字号:
//------------------------------------------------------------------------------
// File: H264.cpp
//------------------------------------------------------------------------------
#include "stdafx.h"
#define FIX_LOCK_NAME
#include <dmo.h>
#include <limits.h> // _I64_MAX
#ifndef UNDER_CE
#include <crtdbg.h>
#endif
#include <dmoimpl.h>
#include <uuids.h> // DirectShow media type guids
#include <amvideo.h> // VIDEOINFOHEADER definition
#include "resource.h"
#include "H264.h"
#include "debug.h"
#include "MAECommon.h"
#define DMO_QC_PROCESS /* enable quality control (frame skipping) */
#pragma warning(disable:4100) // Disable C4100: unreferenced formal parameter
//#define DUMP_FILE //dumps input and output of the dmo for verification
//#define DUMP_STANDALONE_FILE //Creates a video elementary file for standalone testdecoder.exe application
#if defined DUMP_FILE || defined DUMP_STANDALONE_FILE
#include "stdio.h"
#endif
#ifdef DUMP_FILE
static FILE *s_InDataFile = NULL;
static FILE *s_OutDataFile = NULL;
TCHAR g_szInDataFile[100];
TCHAR g_szOutDataFile[100];
#endif
#ifdef DUMP_STANDALONE_FILE
#undef DMO_QC_PROCESS //disable frame skipping when creating standalone files
#include "sadecoder.h"
#define TEST_FILENAME TEXT("\\Hard Disk2\\H264VideoOnly.vid")
static FILE *s_TestFile = NULL;
TCHAR g_szTestFile[100];
#endif
#define FOURCC_H264 0x34363248
// {0x34363248-0000-0010-8000-00AA00389B71}
DEFINE_GUID(MEDIASUBTYPE_H264,
0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
#define FOURCC_h264 0x34363268
// {0x34363268-0000-0010-8000-00AA00389B71}
DEFINE_GUID(MEDIASUBTYPE_h264,
0x34363268, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
// {05589f91-c356-11ce-bf01-00aa0055595a}
DEFINE_GUID(FORMAT_H264VideoInfo,
0x05589f91, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
typedef struct tagH264VIDEOINFOHEADER
{
RECT rcSource; // The bit we really want to use
RECT rcTarget; // Where the video should go
DWORD dwBitRate; // Approximate bit data rate
DWORD dwBitErrorRate; // Bit error rate for this stream
REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units)
BITMAPINFOHEADER bmiHeader;
DWORD vihSize; // amount of extra decoder config info at end of stucture
} H264VIDEOINFOHEADER;
#define FOURCC_YV12 0x32315659
CH264Dmo::CH264Dmo()
{
DP_FUNC((TEXT("CH264Dmo::CH264Dmo")));
m_pUnkMarshaler = NULL;
m_hDecoder = M_HANDLE_INVALID;
#ifdef DUMP_FILE
#ifdef UNDER_CE
DP_ERROR((TEXT("Creating input/output dump files!")));
_tcscpy(g_szInDataFile, TEXT("\\Hard Disk\\h264InputCE.dmp"));
_tcscpy(g_szOutDataFile, TEXT("\\Hard Disk\\h264OutputCE.dmp"));
#else
_tcscpy(g_szInDataFile, TEXT("c:\\h264Input.dmp"));
_tcscpy(g_szOutDataFile, TEXT("c:\\h264Output.dmp"));
#endif
s_InDataFile = _tfopen(g_szInDataFile, TEXT("wb"));
s_OutDataFile = _tfopen(g_szOutDataFile, TEXT("wb"));
#endif
#ifdef DUMP_STANDALONE_FILE
DP_ERROR((TEXT("Creating Standalone test file %s!"), TEST_FILENAME));
_tcscpy(g_szTestFile, TEST_FILENAME);
s_TestFile = _tfopen(g_szTestFile, TEXT("wb"));
#endif
DecoderOpen(&m_hDecoder);
m_rtNow = m_rtOld = 0;
DP_INFO((TEXT("Loaded H264 Video Decoder (%08X)"), m_hDecoder));
//initialize everything
m_pBuffer = NULL;
m_bFrame = false;
m_bSentHeader = false;
m_bDiscontinuity = false;
Init(); //initialize quality control specifics
// Open a handle to the mae driver
open_mae_driver_handle(TEXT("H264DMO"));
}
CH264Dmo::~CH264Dmo()
{
DP_FUNC((TEXT("~CH264Dmo")));
if (m_hDecoder != M_HANDLE_INVALID)
{
DIUComp_End(m_hDecoder);
DecoderClose(m_hDecoder);
m_hDecoder = M_HANDLE_INVALID;
}
#ifdef DUMP_FILE
if (s_InDataFile)
{
fclose(s_InDataFile);
s_InDataFile = NULL;
}
if (s_OutDataFile)
{
fclose(s_OutDataFile);
s_OutDataFile = NULL;
}
#endif
#ifdef DUMP_STANDALONE_FILE
if (s_TestFile)
{
DP_ERROR((TEXT("Standalone test file %s complete!"), TEST_FILENAME));
fclose(s_TestFile);
s_TestFile = NULL;
}
#endif
// Close a handle to the mae driver
close_mae_driver_handle();
}
HRESULT CH264Dmo::InternalGetInputStreamInfo(DWORD dwInputStreamIndex, DWORD *pdwFlags)
{
// We can process data on any boundary
DP_FUNC((TEXT("InternalGetInputStreamInfo")));
*pdwFlags = 0;
return S_OK;
}
HRESULT CH264Dmo::InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex, DWORD *pdwFlags)
{
// We output single frames
DP_FUNC((TEXT("InternalGetOutputStreamInfo")));
*pdwFlags = 0;
return S_OK;
}
HRESULT CH264Dmo::InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt)
{
uint32 iMaxMAESize, iClipSize;
VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)pmt->pbFormat;
DP_FUNC((TEXT("InternalCheckInputType")));
//Verfiy that we loaded the decoder properly
if (m_hDecoder == M_HANDLE_INVALID)
{
DP_ERROR((TEXT("InternalCheckInputType FAILED No Decoder")));
return E_FAIL;
}
// Get the drivers capabilities for YUV input (ioctl call AU1XXXMAE_GETYUVCONFIG)
MAE_DISP_STRUCT disp_struct;
get_mae_yuv_config(&disp_struct);
// Update the memory sizes
iMaxMAESize = (disp_struct.display_linesize * disp_struct.display_height);
iClipSize = ((uint32)pvih->bmiHeader.biWidth * (uint32)pvih->bmiHeader.biHeight);
// Check to see that the spatial size is within the driver's capabilities
if (iClipSize > iMaxMAESize)
{
DP_ERROR((TEXT("ClipSize %d is too big for MAE (%d)!!"), iClipSize, iMaxMAESize));
return DMO_E_INVALIDTYPE;
}
// Check if the type is already set and if so reject any type that's not identical
if (InputTypeSet(dwInputStreamIndex))
{
if(pmt->majortype == InputType(dwInputStreamIndex)->majortype &&
pmt->subtype == InputType(dwInputStreamIndex)->subtype &&
pmt->lSampleSize == InputType(dwInputStreamIndex)->lSampleSize &&
pmt->formattype == InputType(dwInputStreamIndex)->formattype &&
pmt->cbFormat == InputType(dwInputStreamIndex)->cbFormat &&
0 == memcmp(pmt->pbFormat, InputType(dwInputStreamIndex)->pbFormat, pmt->cbFormat))
{
return S_OK;
} else
{
DP_ERROR((TEXT("InternalCheckInputType InputType is already set and different")));
return DMO_E_INVALIDTYPE;
}
}
if ((pmt->majortype == MEDIATYPE_Video) &&
(pmt->subtype == MEDIASUBTYPE_H264 ||
pmt->subtype == MEDIASUBTYPE_h264))
{
return S_OK;
} else
{
DP_INFO((TEXT("InternalCheckInputType InputType not valid")));
return DMO_E_INVALIDTYPE;
}
}
HRESULT CH264Dmo::InternalCheckOutputType(DWORD dwOutputStreamIndex, const DMO_MEDIA_TYPE *pmt)
{
DP_FUNC((TEXT("InternalCheckOutputType")));
//Verfiy that we loaded the decoder properly
if (m_hDecoder == M_HANDLE_INVALID)
{
DP_ERROR((TEXT("InternalCheckOutputType FAILED No Decoder")));
return E_FAIL;
}
// Check if the type is already set and if so reject any type that's not identical
if (OutputTypeSet(dwOutputStreamIndex))
{
if(pmt->majortype == OutputType(dwOutputStreamIndex)->majortype &&
pmt->subtype == OutputType(dwOutputStreamIndex)->subtype &&
pmt->lSampleSize == OutputType(dwOutputStreamIndex)->lSampleSize &&
pmt->formattype == OutputType(dwOutputStreamIndex)->formattype &&
pmt->cbFormat == OutputType(dwOutputStreamIndex)->cbFormat &&
0 == memcmp(pmt->pbFormat, OutputType(dwOutputStreamIndex)->pbFormat, pmt->cbFormat))
{
return S_OK;
}
else
{
DP_ERROR((TEXT("InternalCheckOutputType OutputType is set but different")));
return DMO_E_INVALIDTYPE;
}
}
if (!InputTypeSet(0))
{
DP_ERROR((TEXT("InternalCheckOutputType InputType not set")));
return DMO_E_INVALIDTYPE;
}
if (pmt->majortype == MEDIATYPE_Video &&
pmt->subtype == MEDIASUBTYPE_Overlay)
{
return S_OK;
}
DP_INFO((TEXT("InternalCheckOutputType returning DMO_E_INVALIDTYPE")));
return DMO_E_INVALIDTYPE;
}
HRESULT CH264Dmo::InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex,
DMO_MEDIA_TYPE *pmt)
{
DP_FUNC((TEXT("InternalGetInputType")));
//Verfiy that we loaded the decoder properly
if (m_hDecoder == M_HANDLE_INVALID)
{
DP_ERROR((TEXT("InternalGetInputType FAILED No Decoder")));
return E_FAIL;
}
if (pmt && dwTypeIndex == 0)
{
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_H264;
pmt->formattype = FORMAT_None;
return S_OK;
}
return DMO_E_NO_MORE_ITEMS;
}
HRESULT CH264Dmo::InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex,
DMO_MEDIA_TYPE *pmt)
{
DP_FUNC((TEXT("InternalGetOutputType")));
HRESULT hr = S_OK;
//Verfiy that we loaded the decoder properly
if (m_hDecoder == M_HANDLE_INVALID)
{
DP_ERROR((TEXT("InternalGetOutputType FAILED No Decoder")));
return E_FAIL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -