📄 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_win32.c 622 2006-01-31 19:02:53Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#if defined(TARGET_WIN32) || defined(TARGET_WINCE)
#ifndef STRICT
#define STRICT
#endif
#define _WIN32_WINNT 0x0400
#define INITGUID
#include <objbase.h>
#define DMO_CLASS FOURCC('A','D','M','O')
// string table
#define DMO_MODULE 0x200
#define DMO_MODULEPPC 0x201
#define DMO_CLASSID 0x202
// registry
#define DMO_FOUND 0x400
#define WMV_ID FOURCC('W','M','V','_')
#define WMS_ID FOURCC('W','M','S','_')
#define WMVA_ID FOURCC('W','M','V','A')
#define WMA_ID FOURCC('W','M','A','_')
#define WMAV_ID FOURCC('W','M','A','V')
#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
const guid ID_IMEDIABUFFER = {0x59eff8b9,0x938c,0x4a26,{0x82,0xf2,0x95,0xcb,0x84,0xcd,0xc8,0x37}};
const guid ID_IUNKNOWN = {0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
const guid ID_ICLASSFACTORY = {00000001,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
const guid ID_IDMOQUALITYCONTROL = {0x65abea96,0xcf36,0x453f,{0xaf,0x8a,0x70,0x5e,0x98,0xf1,0x62,0x60}};
const guid WMCMEDIATYPE_Video = {0x73646976, 0x0000, 0x0010,{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const guid WMCMEDIATYPE_Audio = {0x73647561, 0x0000, 0x0010,{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const guid WMCFORMAT_VideoInfo = {0x05589f80, 0xc356, 0x11ce,{0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
const guid WMCFORMAT_WaveFormatEx = {0x05589f81, 0xc356, 0x11ce,{0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
const guid WMCMEDIASUBTYPE = {0x00000000,0x0000, 0x0010,{0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}};
const guid WMCMEDIASUBTYPE_RGB565 = {0xe436eb7b, 0x524f, 0x11ce,{0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
const guid 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, const guid* 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, const guid* 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, const guid* 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;
#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
{
codec Codec;
HMODULE Module;
guid ClassId;
int (STDCALL *CreateCodecDMO)(IMediaObject**);
int (STDCALL *CreateCodecDMOEx)(int Code,IMediaObject**);
int (STDCALL *QueryUnloadCodecDMO)();
int (STDCALL *DllGetClassObject)(const guid*,const guid*,IClassFactory**);
int (STDCALL *DllCanUnloadNow)();
IMediaObject* Media;
IOwnMediaBuffer* InputBuffers;
DMO_OUTPUT_DATA_BUFFER OutputBuffer[2];
int OutputNoMask;
int OutputNext;
int OutputPrev;
DMO_MEDIA_TYPE InType;
DMO_MEDIA_TYPE OutType;
int ConstSize;
BITMAPINFOHEADER* Const;
int WMPVersion;
bool_t First;
bool_t UseDropping;
} dmo;
static HRESULT STDCALL MoInitMediaType(DMO_MEDIA_TYPE* p, DWORD Size)
{
p->pUnk = NULL;
p->pbFormat = NULL;
p->cbFormat = Size;
if (Size)
{
p->pbFormat = CoTaskMemAlloc(Size);
if (!p->pbFormat)
{
p->cbFormat = 0;
return E_OUTOFMEMORY;
}
}
return S_OK;
}
static HRESULT STDCALL MoFreeMediaType(DMO_MEDIA_TYPE* p)
{
if (p->pUnk)
{
p->pUnk->lpVtbl->Release(p->pUnk);
p->pUnk = NULL;
}
if (p->pbFormat)
{
CoTaskMemFree(p->pbFormat);
p->pbFormat = NULL;
}
p->cbFormat = 0;
return S_OK;
}
static HRESULT STDCALL MBQueryInterface(IOwnMediaBuffer * p, const guid* 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;
}
static ULONG STDCALL MBAddRef(IOwnMediaBuffer * p)
{
p->RefCount++;
return 0;
}
static HRESULT STDCALL MBSetMaxLength(IOwnMediaBuffer * p, DWORD cbLength)
{
if (cbLength > 0)
{
if ((int)cbLength > p->Allocated)
{
void* Data = realloc(p->Data,cbLength);
if (!Data && cbLength)
return E_OUTOFMEMORY;
p->Data = Data;
p->Allocated = cbLength;
}
}
else
{
free(p->Data);
p->Data = NULL;
p->Allocated = 0;
}
if (p->Length > p->Allocated)
p->Length = p->Allocated;
return 0;
}
static 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;
}
static 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;
}
static HRESULT STDCALL MBGetMaxLength(IOwnMediaBuffer * p, DWORD *pcbMaxLength)
{
DEBUG_MSG1(DEBUG_VIDEO,T("MediaBuffer_GetMaxLength %d"),p->Allocated);
if (pcbMaxLength)
*pcbMaxLength = p->Allocated;
return 0;
}
static 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,
};
static 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, const void* Data)
{
memcpy((char*)p->Data + p->Length, Data, Length);
p->Length += Length;
}
static IOwnMediaBuffer* AllocBuffer(int MaxLength,IOwnMediaBuffer** Chain)
{
IOwnMediaBuffer* p = Chain ? *Chain : NULL;
if (MaxLength <= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -