📄 dmo_win32.c
字号:
/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: dmo.c 11 2004-07-15 13:46:20Z picard $
*
* BetaPlayer Core
* Copyright (c) 2004 Gabor Kovacs
*
****************************************************************************/
#include "../stdafx.h"
#define _WIN32_WINNT 0x0400
#define INITGUID
#include <objbase.h>
//#define static
#if defined(_WIN32_WCE)
#define ACCESS_LOAD 0
#define ACCESS_SAVE 0
#else
#define ACCESS_LOAD KEY_READ
#define ACCESS_SAVE KEY_READ | KEY_WRITE | KEY_SET_VALUE
#endif
#if defined(_WIN32_WCE)
#define TWIN(a) L ## a
#else
#define TWIN(a) a
#endif
#define DMO_INPUT_STATUSF_ACCEPT_DATA 0x00000001
#define DMO_INPUT_DATA_BUFFERF_SYNCPOINT 0x00000001
#define DMO_INPUT_DATA_BUFFERF_TIME 0x00000002
#define DMO_INPUT_DATA_BUFFERF_TIMELENGTH 0x00000004
#define DMO_INPUT_STREAMF_WHOLE_SAMPLES 0x00000001
#define DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER 0x00000002
#define DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE 0x00000004
#define DMO_INPUT_STREAMF_HOLDS_BUFFERS 0x00000008
#define DMO_SET_TYPEF_TEST_ONLY 0x00000001
#define DMO_SET_TYPEF_CLEAR 0x00000002
#define DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER 0x00000001
#define DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT 0x00000001
#define DMO_OUTPUT_DATA_BUFFERF_TIME 0x00000002
#define DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH 0x00000004
#define DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE 0x01000000
DEFINE_GUID(ID_IMEDIABUFFER,0x59eff8b9,0x938c,0x4a26,0x82,0xf2,0x95,0xcb,0x84,0xcd,0xc8,0x37);
DEFINE_GUID(ID_IUNKNOWN,0x00000000,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
DEFINE_GUID(ID_ICLASSFACTORY,00000001,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
DEFINE_GUID(ID_IDMOQUALITYCONTROL,0x65abea96,0xcf36,0x453f,0xaf,0x8a,0x70,0x5e,0x98,0xf1,0x62,0x60);
EXTERN_GUID(WMCMEDIATYPE_Video,0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
EXTERN_GUID(WMCMEDIATYPE_Audio,0x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
EXTERN_GUID(WMCFORMAT_VideoInfo,0x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
EXTERN_GUID(WMCFORMAT_WaveFormatEx,0x05589f81, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
EXTERN_GUID(WMCMEDIASUBTYPE, 0, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
EXTERN_GUID(WMCMEDIASUBTYPE_RGB565, 0xe436eb7b, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
const IID IID_IMediaObject = { 0xd8ad0f58, 0x5494, 0x4102, 0x97, 0xc5, 0xec, 0x79, 0x8e, 0x59, 0xbc, 0xf4 };
typedef int64_t REFERENCE_TIME;
struct IMediaObject;
struct IMediaBuffer;
struct IDMOQualityControl;
typedef struct VIDEOINFOHEADER
{
RECT rcSource;
RECT rcTarget;
DWORD dwBitRate;
DWORD dwBitErrorRate;
REFERENCE_TIME AvgTimePerFrame;
BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
typedef struct DMO_MEDIA_TYPE
{
GUID majortype;
GUID subtype;
BOOL bFixedSizeSamples;
BOOL bTemporalCompression;
ULONG lSampleSize;
GUID formattype;
IUnknown* pUnk;
ULONG cbFormat;
BYTE* pbFormat;
} DMO_MEDIA_TYPE;
typedef struct DMO_OUTPUT_DATA_BUFFER
{
struct IMediaBuffer* pBuffer;
DWORD dwStatus;
REFERENCE_TIME rtTimestamp;
REFERENCE_TIME rtTimelength;
} DMO_OUTPUT_DATA_BUFFER;
typedef struct IMediaBufferVMT
{
HRESULT ( STDCALL *QueryInterface )( void* This, REFIID riid, void **ppvObject);
ULONG ( STDCALL *AddRef )( void* This);
ULONG ( STDCALL *Release )( void* This);
HRESULT ( STDCALL *SetLength )( void* This, DWORD cbLength);
HRESULT ( STDCALL *GetMaxLength )( void* This, DWORD *pcbMaxLength);
HRESULT ( STDCALL *GetBufferAndLength )( void* This, BYTE **ppBuffer, DWORD *pcbLength);
} IMediaBufferVMT;
typedef struct IMediaBuffer
{
struct IMediaBufferVMT *VMT;
} IMediaBuffer;
typedef struct IDMOQualityControlVMT
{
HRESULT ( STDCALL *QueryInterface )( struct IDMOQualityControl* This, REFIID riid, void** ppvObject);
ULONG ( STDCALL *AddRef )( struct IDMOQualityControl* This);
ULONG ( STDCALL *Release )( struct IDMOQualityControl* This);
HRESULT ( STDCALL *SetNow)( struct IDMOQualityControl* This, REFERENCE_TIME rtNow );
HRESULT ( STDCALL *SetStatus)( struct IDMOQualityControl* This, DWORD dwFlags );
HRESULT ( STDCALL *GetStatus)( struct IDMOQualityControl* This, DWORD *pdwFlags );
} IDMOQualityControlVMT;
typedef struct IDMOQualityControl
{
IDMOQualityControlVMT *VMT;
} IDMOQualityControl;
typedef struct IMediaObjectVMT
{
HRESULT ( STDCALL *QueryInterface )( struct IMediaObject * This, REFIID riid, void** ppvObject);
ULONG ( STDCALL *AddRef )( struct IMediaObject * This);
ULONG ( STDCALL *Release )( struct IMediaObject * This);
HRESULT ( STDCALL *GetStreamCount )( struct IMediaObject * This, DWORD *pcInputStreams, DWORD *pcOutputStreams);
HRESULT ( STDCALL *GetInputStreamInfo )( struct IMediaObject * This, DWORD dwInputStreamIndex, DWORD *pdwFlags);
HRESULT ( STDCALL *GetOutputStreamInfo )( struct IMediaObject * This, DWORD dwOutputStreamIndex, DWORD *pdwFlags);
HRESULT ( STDCALL *GetInputType )( struct IMediaObject * This, DWORD dwInputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt);
HRESULT ( STDCALL *GetOutputType )( struct IMediaObject * This, DWORD dwOutputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt);
HRESULT ( STDCALL *SetInputType )( struct IMediaObject * This, DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt, DWORD dwFlags);
HRESULT ( STDCALL *SetOutputType )( struct IMediaObject * This, DWORD dwOutputStreamIndex,const DMO_MEDIA_TYPE *pmt, DWORD dwFlags);
HRESULT ( STDCALL *GetInputCurrentType )( struct IMediaObject * This, DWORD dwInputStreamIndex, DMO_MEDIA_TYPE *pmt);
HRESULT ( STDCALL *GetOutputCurrentType )( struct IMediaObject * This, DWORD dwOutputStreamIndex, DMO_MEDIA_TYPE *pmt);
HRESULT ( STDCALL *GetInputSizeInfo )( struct IMediaObject * This, DWORD dwInputStreamIndex, DWORD *pcbSize, DWORD *pcbMaxLookahead, DWORD *pcbAlignment);
HRESULT ( STDCALL *GetOutputSizeInfo )( struct IMediaObject * This, DWORD dwOutputStreamIndex, DWORD *pcbSize, DWORD *pcbAlignment);
HRESULT ( STDCALL *GetInputMaxLatency )( struct IMediaObject * This, DWORD dwInputStreamIndex, REFERENCE_TIME *prtMaxLatency);
HRESULT ( STDCALL *SetInputMaxLatency )( struct IMediaObject * This, DWORD dwInputStreamIndex, REFERENCE_TIME rtMaxLatency);
HRESULT ( STDCALL *Flush )( struct IMediaObject * This);
HRESULT ( STDCALL *Discontinuity )( struct IMediaObject * This, DWORD dwInputStreamIndex);
HRESULT ( STDCALL *AllocateStreamingResources )( struct IMediaObject * This);
HRESULT ( STDCALL *FreeStreamingResources )( struct IMediaObject * This);
HRESULT ( STDCALL *GetInputStatus )( struct IMediaObject * This,DWORD dwInputStreamIndex,DWORD *dwFlags);
HRESULT ( STDCALL *ProcessInput )( struct IMediaObject * This, DWORD dwInputStreamIndex, IMediaBuffer *pBuffer, DWORD dwFlags, REFERENCE_TIME rtTimestamp, REFERENCE_TIME rtTimelength);
HRESULT ( STDCALL *ProcessOutput )( struct IMediaObject * This, DWORD dwFlags, DWORD cOutputBufferCount, DMO_OUTPUT_DATA_BUFFER *pOutputBuffers, DWORD *pdwStatus);
HRESULT ( STDCALL *Lock )( struct IMediaObject * This, LONG bLock);
} IMediaObjectVMT;
typedef struct IMediaObject
{
IMediaObjectVMT *VMT;
} IMediaObject;
static HRESULT (STDCALL* FuncMoInitMediaType)( DMO_MEDIA_TYPE*, DWORD Size );
static HRESULT (STDCALL* FuncMoFreeMediaType)( DMO_MEDIA_TYPE* );
#define DMO_INPUT 0x100
#define DMO_OUTPUT 0x101
typedef struct IOwnMediaBuffer
{
struct IMediaBufferVMT *VMT;
int RefCount;
int Length;
int Allocated; // -1 for external allocated buffer
void* Data;
struct IOwnMediaBuffer** Chain;
struct IOwnMediaBuffer* Next;
} IOwnMediaBuffer;
typedef struct dmo
{
node VMT;
int Id;
const CLSID *ClassId;
HMODULE Module;
int (STDCALL *CreateCodecDMO)(IMediaObject**);
int (STDCALL *QueryUnloadCodecDMO)();
int (STDCALL *DllGetClassObject)(REFCLSID,REFIID,IClassFactory**);
int (STDCALL *DllCanUnloadNow)();
int FourCCCount;
int FourCC[32];
IMediaObject* Media;
IOwnMediaBuffer* InputBuffers;
DMO_OUTPUT_DATA_BUFFER OutputBuffer[2];
int OutputNoMask;
int OutputNext;
int OutputPrev;
int WMPVersion;
int FormatType;
int FormatSize;
void* InputFormat;
void* OutputFormat;
pin Output;
DMO_MEDIA_TYPE InType;
DMO_MEDIA_TYPE OutType;
int ConstSize;
BITMAPINFOHEADER* Const;
int TotalBytes;
int TotalPackets;
int DroppedPackets;
bool_t Pending;
bool_t First;
bool_t UseDropping;
packet Packet;
struct dmo* Chain;
} dmo;
//****************************************************
HRESULT STDCALL MBQueryInterface( IOwnMediaBuffer * p, REFIID riid, void **ppvObject)
{
if (memcmp(&riid,&ID_IMEDIABUFFER,sizeof(GUID))==0 ||
memcmp(&riid,&ID_IUNKNOWN,sizeof(GUID))==0)
{
if (ppvObject)
{
++p->RefCount;
*ppvObject = p;
}
return 0;
}
return -1;
}
ULONG STDCALL MBAddRef( IOwnMediaBuffer * p)
{
p->RefCount++;
return 0;
}
HRESULT STDCALL MBSetMaxLength( IOwnMediaBuffer * p, DWORD cbLength)
{
if (cbLength > 0)
{
if ((int)cbLength > p->Allocated)
{
p->Data = ReAlloc(p->Data,cbLength);
p->Allocated = p->Data ? cbLength:0;
}
}
else
{
Free(p->Data);
p->Data = NULL;
p->Allocated = 0;
}
if (p->Length > p->Allocated)
p->Length = p->Allocated;
return 0;
}
ULONG STDCALL MBRelease( IOwnMediaBuffer * p)
{
if (--p->RefCount<=0)
{
p->Length = 0;
if (p->Chain)
{
p->Next = *p->Chain;
*p->Chain = p;
}
else
{
Free(p->Data);
Free(p);
return 0;
}
}
return p->RefCount;
}
HRESULT STDCALL MBSetLength( IOwnMediaBuffer * p, DWORD cbLength)
{
DEBUG_MSG2(DEBUG_VIDEO,T("MediaBuffer_SetLength %d (%d)"),cbLength,p->Allocated);
if ((int)cbLength > p->Allocated)
return -1;
p->Length = cbLength;
return 0;
}
HRESULT STDCALL MBGetMaxLength( IOwnMediaBuffer * p, DWORD *pcbMaxLength)
{
DEBUG_MSG1(DEBUG_VIDEO,T("MediaBuffer_GetMaxLength %d"),p->Allocated);
if (pcbMaxLength)
*pcbMaxLength = p->Allocated;
return 0;
}
HRESULT STDCALL MBGetBufferAndLength( IOwnMediaBuffer * p, BYTE **ppBuffer, DWORD *pcbLength)
{
DEBUG_MSG1(DEBUG_VIDEO,T("MediaBuffer_GetBufferAndLength %d"),p->Length);
if (ppBuffer)
*ppBuffer = (BYTE*)p->Data;
if (pcbLength)
*pcbLength = p->Length;
return 0;
}
static IMediaBufferVMT MediaBufferVMT =
{
MBQueryInterface,
MBAddRef,
MBRelease,
MBSetLength,
MBGetMaxLength,
MBGetBufferAndLength,
};
void FreeBuffers(IOwnMediaBuffer** Chain)
{
while (*Chain)
{
IOwnMediaBuffer* p = (*Chain)->Next;
MBSetMaxLength(*Chain,0);
Free(*Chain);
*Chain = p;
}
}
static INLINE void AppendBuffer(IOwnMediaBuffer* p, int Length, void* Data )
{
memcpy((char*)p->Data + p->Length, Data, Length );
p->Length += Length;
}
IMediaBuffer* AllocBuffer(int MaxLength,IOwnMediaBuffer** Chain)
{
IOwnMediaBuffer* p = Chain ? *Chain : NULL;
if (MaxLength <= 0)
return NULL;
if (p)
*Chain = p->Next;
else
{
p = (IOwnMediaBuffer*) CAlloc(sizeof(IOwnMediaBuffer),1);
if (!p)
return NULL;
p->VMT = &MediaBufferVMT;
}
p->Chain = Chain;
p->Length = 0;
MBSetMaxLength(p,MaxLength);
p->VMT->AddRef(p);
return (IMediaBuffer*)p;
}
//****************************************************
bool_t BuildI420( dmo* p )
{
// manual video format guessing (for wince4 non pocketpc)
VIDEOINFOHEADER* VideoInfo;
video* Video = (video*) p->OutputFormat;
memcpy(p->OutputFormat,p->InputFormat,sizeof(video));
Video->Pixel.Flags = PF_FOURCC;
Video->Pixel.FourCC = FOURCC_I420;
Video->Pixel.BitCount = 16;
Video->Pitch = Video->Width;
if (FuncMoInitMediaType(&p->OutType,sizeof(VIDEOINFOHEADER)) != S_OK)
return 0;
VideoInfo = (VIDEOINFOHEADER*)p->OutType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader);
VideoInfo->bmiHeader.biWidth = Video->Width;
VideoInfo->bmiHeader.biHeight = Video->Height;
VideoInfo->bmiHeader.biCompression = Video->Pixel.FourCC;
VideoInfo->bmiHeader.biBitCount = (WORD)Video->Pixel.BitCount;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (Video->Width * Video->Height * Video->Pixel.BitCount)/8;
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = Video->Width;
VideoInfo->rcSource.bottom = Video->Height;
VideoInfo->rcTarget = VideoInfo->rcSource;
p->OutType.majortype = WMCMEDIATYPE_Video;
p->OutType.formattype = WMCFORMAT_VideoInfo;
p->OutType.subtype = WMCMEDIASUBTYPE;
p->OutType.subtype.Data1 = FOURCC_YUY2; // tricky
p->OutType.bTemporalCompression = 0;
p->OutType.bFixedSizeSamples = 1;
p->OutType.lSampleSize = 0;
/*
if (FuncMoInitMediaType(&p->OutType,sizeof(VIDEOINFOHEADER)) != S_OK)
return 0;
VideoInfo = (VIDEOINFOHEADER*)p->OutType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -