📄 hantrodecoderdmo.cpp
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2005 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Description : Hantro MPEG-4/H.263 Video Decoder DirectX Media Object
--
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "HantroDecoderDMO.h" // Class declaration
#include "HantroDecoderGuids.h"
#pragma warning(disable:4100) // Disable C4100: unreferenced formal parameter
/*------------------------------------------------------------------------------
2. Module defines
------------------------------------------------------------------------------*/
#define HDDMO_LOG
#define HDDMO_TRACE /*printf*/
#ifdef HDDMO_LOG
#include <stdio.h>
static FILE* slog = NULL;
static int csum( void* buffer, int len ) {
unsigned short* ptr = (unsigned short*)buffer;
unsigned short cs = 0;
len /= sizeof(unsigned short);
while( len-- ) cs += *ptr++;
return cs;
}
#endif
/*------------------------------------------------------------------------------
3. TypesMatch function
------------------------------------------------------------------------------*/
// Helper - compares media types - ignoring the advisory fields
static bool TypesMatch(const DMO_MEDIA_TYPE *pmt1, const DMO_MEDIA_TYPE *pmt2)
{
if(pmt1->majortype == pmt2->majortype &&
pmt1->subtype == pmt2->subtype &&
pmt1->lSampleSize == pmt2->lSampleSize &&
pmt1->formattype == pmt2->formattype &&
pmt1->cbFormat == pmt2->cbFormat &&
0 == memcmp(pmt1->pbFormat, pmt2->pbFormat, pmt1->cbFormat)
)
{
return true;
}
else
{
return false;
}
}
/*------------------------------------------------------------------------------
4. CHantroDecoderDMO class
------------------------------------------------------------------------------*/
// Private method that returns a new instance.
CUnknown* WINAPI CHantroDecoderDMO::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
{
CHantroDecoderDMO *pNewObject = new CHantroDecoderDMO(pUnk);
if( pNewObject == NULL )
{
*pHr = E_OUTOFMEMORY;
return NULL;
}
*pHr = S_OK;
return pNewObject;
}
// This method retrieves information about an input stream, such as any restrictions on
// the number of samples per buffer, and whether the stream performs a lookahead on the
// input data. This information never changes.
//
// Parameters
//
// dwInputStreamIndex
// Zero-based index of an input stream on the DMO.
// pdwFlags
// [out] Pointer to a variable that receives a bitwise combination of zero or more
// DMO_INPUT_STREAM_INFO_FLAGS flags.
//
// Return Values
//
// Returns an HRESULT value. Possible values include the following.
// Value Description
// S_OK Success
// DMO_E_INVALIDSTREAMINDEX Invalid stream index
// E_POINTER NULL pointer argument
HRESULT CHantroDecoderDMO::InternalGetInputStreamInfo(DWORD dwInputStreamIndex, DWORD *pdwFlags)
{
// We can process data on any boundary
*pdwFlags = 0;
return S_OK;
}
// This method retrieves information about an output stream; for example, whether the stream is
// discardable and whether it uses a fixed sample size. This information never changes.
//
// Parameters
//
// dwOutputStreamIndex
// Zero-based index of an output stream on the DMO.
// pdwFlags
// [out] Pointer to a variable that receives a bitwise combination of zero or more
// DMO_OUTPUT_STREAM_INFO_FLAGS flags.
//
// Return Values
//
// Returns an HRESULT value. Possible values include the following.
// Value Description
// S_OK Success
// DMO_E_INVALIDSTREAMINDEX Invalid stream index
// E_POINTER NULL pointer argument
HRESULT CHantroDecoderDMO::InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex, DWORD *pdwFlags)
{
// We output single frames
*pdwFlags = DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE;
return S_OK;
}
// This method queries whether an input stream can accept a given media type.
// The derived class must declare and implement this method.
//
// Parameters
//
// dwInputStreamIndex
// Index of an input stream.
// pmt
// Pointer to a DMO_MEDIA_TYPE structure that describes the media type.
//
// Return Values
// Returns S_OK if the media type is valid or otherwise returns DMO_E_INVALIDTYPE.
HRESULT CHantroDecoderDMO::InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt)
{
// Check if the type is already set and if so reject any type that's not identical
if (InputTypeSet(dwInputStreamIndex)) {
if (!TypesMatch(pmt, InputType(dwInputStreamIndex))) {
return DMO_E_INVALIDTYPE;
} else {
return S_OK;
}
}
// We accept only major type video
if( MEDIATYPE_Video != pmt->majortype )
return DMO_E_INVALIDTYPE;
// Check for supported subtypes
for( int i=0; i<4; i++ )
{
if( pmt->subtype == INPUTTYPE_MP4V ||
pmt->subtype == INPUTTYPE_mp4v ||
pmt->subtype == INPUTTYPE_H263 ||
pmt->subtype == INPUTTYPE_h263 )
break;
if( i == 3 )
return DMO_E_INVALIDTYPE;
}
// Check that format is defined
if( !(pmt->formattype == FORMAT_VideoInfo ||
pmt->formattype == FORMAT_VideoInfo2) )
{
return DMO_E_INVALIDTYPE;
}
if( pmt->pbFormat == NULL )
{
return DMO_E_INVALIDTYPE;
}
// If we got here, everything is ok
return S_OK;
}
// This method queries whether an output stream can accept a given media type. The
// derived class must declare and implement this method.
//
// Parameters
//
// dwOutputStreamIndex
// Index of an output stream.
// pmt
// Pointer to a DMO_MEDIA_TYPE structure that describes the media type.
//
// Return Values
// Returns S_OK if the media type is valid or otherwise returns DMO_E_INVALIDTYPE.
HRESULT CHantroDecoderDMO::InternalCheckOutputType(DWORD dwOutputStreamIndex, const DMO_MEDIA_TYPE *pmt)
{
// Check if the type is already set and if so reject any type that's not identical
if (OutputTypeSet(dwOutputStreamIndex)) {
if (!TypesMatch(pmt, OutputType(dwOutputStreamIndex))) {
return DMO_E_INVALIDTYPE;
} else {
return S_OK;
}
}
// If input type is not set, output information can't be delivered
if (!InputTypeSet(0)) {
return DMO_E_TYPE_NOT_SET;
}
// Check the major type
if( pmt->majortype != MEDIATYPE_Video )
{
return DMO_E_INVALIDTYPE;
}
// Check for supported subtypes
for( int i=0; i<3; i++ )
{
if( pmt->subtype == OUTPUTTYPE_IYUV ||
pmt->subtype == OUTPUTTYPE_iyuv ||
pmt->subtype == MEDIASUBTYPE_RGB565 )
break;
if( i == 1 )
return DMO_E_INVALIDTYPE;
}
if (pmt->formattype == FORMAT_VideoInfo &&
pmt->pbFormat != NULL) {
// get input and output formats
const VIDEOINFOHEADER* pvihInput = (const VIDEOINFOHEADER*)InputType(0)->pbFormat;
const VIDEOINFOHEADER* pvihOutput = (const VIDEOINFOHEADER*)pmt->pbFormat;
const BITMAPINFOHEADER pbihInput = (const BITMAPINFOHEADER)pvihInput->bmiHeader;
if (pmt->subtype == OUTPUTTYPE_IYUV ||
pmt->subtype == OUTPUTTYPE_iyuv )
{
// Check that we are supporting compression
for( i=0; i<sizeof(supportedInputFourCCs)/sizeof(supportedInputFourCCs[0]); i++ )
{
if( pbihInput.biCompression == supportedInputFourCCs[i] )
break;
if( i == sizeof(supportedInputFourCCs)/sizeof(supportedInputFourCCs[0]) - 1 )
return DMO_E_INVALIDTYPE;
}
}
else if (pmt->subtype == MEDIASUBTYPE_RGB565 )
{
if( pbihInput.biCompression == BI_BITFIELDS) // Unpacked RGB data )
return S_OK;
}
return S_OK;
}
// no video information available
return DMO_E_INVALIDTYPE;
}
// This method retrieves a preferred media type for a specified input stream.
//
// Parameters
//
// dwInputStreamIndex
// Zero-based index of an input stream on the DMO.
// dwTypeIndex
// Zero-based index on the set of acceptable media types.
// pmt
// [out] Pointer to a DMO_MEDIA_TYPE structure allocated by the caller. The
// method fills the structure with the media type. The format block might be NULL,
// in which case the format type GUID is GUID_NULL.
//
// Return Values
//
// Returns an HRESULT value. Possible values include the following.
// Value Description
// S_OK Success
// DMO_E_INVALIDSTREAMINDEX Invalid stream index
// DMO_E_NO_MORE_ITEMS Type index is out of range
// E_OUTOFMEMORY Insufficient memory
// E_POINTER NULL pointer argument
HRESULT CHantroDecoderDMO::InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex,
DMO_MEDIA_TYPE *pmt)
{
if( dwTypeIndex >= 4 )
return DMO_E_NO_MORE_ITEMS;
memset(pmt, 0, sizeof(DMO_MEDIA_TYPE));
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
pmt->lSampleSize = 0;
pmt->majortype = MEDIATYPE_Video;
switch( dwTypeIndex )
{
case 0:
pmt->subtype = INPUTTYPE_MP4V;
break;
case 1:
pmt->subtype = INPUTTYPE_mp4v;
break;
case 2:
pmt->subtype = INPUTTYPE_H263;
break;
case 3:
pmt->subtype = INPUTTYPE_h263;
break;
}
return S_OK;
}
// This method retrieves a preferred media type for a specified output stream.
//
// Parameters
//
// dwOutputStreamIndex
// Zero-based index of an output stream on the DMO.
// dwTypeIndex
// Zero-based index on the set of acceptable media types.
// pmt
// [out] Pointer to a DMO_MEDIA_TYPE structure allocated by the caller. The
// method fills the structure with the media type. The format block might be NULL,
// in which case the format type GUID is GUID_NULL.
//
// Return Values
//
// Returns an HRESULT value. Possible values include the following.
// Value Description
// S_OK Success
// DMO_E_INVALIDSTREAMINDEX Invalid stream index
// DMO_E_NO_MORE_ITEMS Type index is out of range
// E_OUTOFMEMORY Insufficient memory
// E_POINTER NULL pointer argument
HRESULT CHantroDecoderDMO::InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex,
DMO_MEDIA_TYPE *pmt)
{
// If input type is not set, output information can't be delivered
if (!InputTypeSet(0))
return DMO_E_TYPE_NOT_SET;
if( dwTypeIndex >= 3 )
return DMO_E_NO_MORE_ITEMS;
// If GetOutputType()'s pmt parameter is NULL, return S_OK if the type exists.
// Return DMO_E_NO_MORE_ITEMS if the type does not exists. See the
// documentation for IMediaObject::GetOutputType() for more information.
if (NULL != pmt) {
if (dwOutputStreamIndex == 0) {
// Create our media type
HRESULT hr = MoInitMediaType(pmt, FIELD_OFFSET(VIDEOINFO, dwBitMasks[3]));
if (FAILED(hr)) {
return hr;
}
const VIDEOINFOHEADER *pvihInput = (const VIDEOINFOHEADER *)InputType(0)->pbFormat;
LONG lWidth = pvihInput->bmiHeader.biWidth;
LONG lHeight = pvihInput->bmiHeader.biHeight;
// Initialize the media type structure (MoInitMediaType initalized cbFormat
// and pbFormat)
pmt->majortype = MEDIATYPE_Video;
switch( dwTypeIndex )
{
case 0:
pmt->subtype = OUTPUTTYPE_IYUV;
break;
case 1:
pmt->subtype = OUTPUTTYPE_iyuv;
break;
case 2:
pmt->subtype = MEDIASUBTYPE_RGB565;
break;
}
pmt->bFixedSizeSamples = TRUE;
pmt->bTemporalCompression = FALSE;
if( pmt->subtype == MEDIASUBTYPE_RGB565 )
{
pmt->lSampleSize = lWidth * lHeight * 2;
}
else
{
pmt->lSampleSize = ( lWidth * lHeight * 3 ) / 2;
}
pmt->formattype = FORMAT_VideoInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -