#include <vlc/decoder.h>\r
#include <vlc/vout.h>\r
\r
-#include <objbase.h>\r
-#include "codecs.h"\r
+#define LOADER\r
+#ifdef LOADER\r
+/* Need the w32dll loader from mplayer */\r
+# include <wine/winerror.h>\r
+# include <dmo/dmo.h>\r
+# include <dmo/dmo_interfaces.h>\r
+# include <dmo/dmo_guids.h>\r
+# include <ldt_keeper.h>\r
+\r
+/* Avoid codecs.h to redefine a few symbols */\r
+# define _RECT32_\r
+# define _GUID_DEFINED\r
+# define _REFERENCE_TIME_\r
+# define _VIDEOINFOHEADER_\r
+\r
+/* Ugly, wine loader and vlc doesn't use the same field name for GUID */\r
+#define Data1 f1\r
+#define Data2 f2\r
+#define Data3 f3\r
+#define Data4 f4\r
+\r
+/* Not Needed */\r
+HRESULT CoInitialize( LPVOID pvReserved ) { return (HRESULT)-1; }\r
+void CoUninitialize(void) { }\r
+\r
+/* */\r
+HMODULE WINAPI LoadLibraryA(LPCSTR);\r
+FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);\r
+int WINAPI FreeLibrary(HMODULE);\r
+\r
+typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);\r
+\r
+#else\r
+# include <objbase.h>\r
+#endif\r
+\r
#include "dmo.h"\r
+#include "codecs.h"\r
\r
static int pi_channels_maps[7] =\r
{\r
/*****************************************************************************\r
* Module descriptor\r
*****************************************************************************/\r
+static int Open ( vlc_object_t * );\r
static int DecoderOpen ( vlc_object_t * );\r
static void DecoderClose ( vlc_object_t * );\r
static void *DecodeBlock ( decoder_t *, block_t ** );\r
set_description( _("DirectMedia Object decoder") );\r
add_shortcut( "dmo" );\r
set_capability( "decoder", 1 );\r
- set_callbacks( DecoderOpen, DecoderClose );\r
+ set_callbacks( Open, DecoderClose );\r
vlc_module_end();\r
\r
/*****************************************************************************\r
uint8_t *p_buffer;\r
\r
audio_date_t end_date;\r
+\r
+#ifdef LOADER\r
+ ldt_fs_t *ldt_fs;\r
+#endif\r
+};\r
+\r
+#ifdef LOADER\r
+static const GUID guid_wmv9 = { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };\r
+static const GUID guid_wma9 = { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };\r
+\r
+static const GUID guid_wmv = { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };\r
+static const GUID guid_wma = { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };\r
+\r
+static const struct\r
+{\r
+ vlc_fourcc_t i_fourcc;\r
+ const char *psz_dll;\r
+ const GUID *p_guid;\r
+} codecs_table[] =\r
+{\r
+ /* WM3 */\r
+ { VLC_FOURCC('W','M','V','3'), "wmv9dmod.dll", &guid_wmv9 },\r
+ { VLC_FOURCC('w','m','v','3'), "wmv9dmod.dll", &guid_wmv9 },\r
+ /* WMV2 */\r
+ { VLC_FOURCC('W','M','V','2'), "wmvdmod.dll", &guid_wmv },\r
+ { VLC_FOURCC('w','m','v','2'), "wmvdmod.dll", &guid_wmv },\r
+ /* WMV1 */\r
+ { VLC_FOURCC('W','M','V','1'), "wmvdmod.dll", &guid_wmv },\r
+ { VLC_FOURCC('w','m','v','1'), "wmvdmod.dll", &guid_wmv },\r
+\r
+ /* WMA 3*/\r
+ { VLC_FOURCC('W','M','A','3'), "wma9dmod.dll", &guid_wma9 },\r
+ { VLC_FOURCC('w','m','a','3'), "wma9dmod.dll", &guid_wma9 },\r
+\r
+ /* */\r
+ { 0, NULL, NULL }\r
};\r
\r
+#endif\r
+\r
+/*****************************************************************************\r
+ * Open: open dmo codec\r
+ *****************************************************************************/\r
+static int Open( vlc_object_t *p_this )\r
+{\r
+#ifndef LOADER\r
+ return DecoderOpen( p_this );\r
+#else\r
+ decoder_t *p_dec = (decoder_t*)p_this;\r
+ int i;\r
+ /* We can't open it now, because of ldt_keeper or something\r
+ * Open/Decode/Close has to be done in the same thread */\r
+\r
+ p_dec->p_sys = NULL;\r
+\r
+\r
+ /* Probe if we support it */\r
+ for( i = 0; codecs_table[i].i_fourcc != 0; i++ )\r
+ {\r
+ if( codecs_table[i].i_fourcc == p_dec->fmt_in.i_codec )\r
+ {\r
+ msg_Dbg( p_dec, "DMO codec for %4.4s may work with dll=%s",\r
+ (char*)&p_dec->fmt_in.i_codec,\r
+ codecs_table[i].psz_dll );\r
+\r
+ /* Set callbacks */\r
+ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeBlock;\r
+ p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))DecodeBlock;\r
+ return VLC_SUCCESS;\r
+ }\r
+ }\r
+ return VLC_EGENERIC;\r
+#endif\r
+}\r
+\r
/*****************************************************************************\r
* DecoderOpen: open dmo codec\r
*****************************************************************************/\r
\r
DMO_PARTIAL_MEDIATYPE dmo_partial_type;\r
DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;\r
- IEnumDMO *p_enum_dmo = NULL; \r
IMediaObject *p_dmo = NULL;\r
- WCHAR *psz_dmo_name;\r
- GUID clsid_dmo;\r
\r
VIDEOINFOHEADER *p_vih = NULL;\r
WAVEFORMATEX *p_wf = NULL;\r
\r
+#ifdef LOADER\r
+ ldt_fs_t *ldt_fs = Setup_LDT_Keeper();\r
+#endif /* LOADER */\r
+\r
+ HINSTANCE hmsdmo_dll = NULL;\r
+\r
+ /* Look for a DMO which can handle the requested codec */\r
+ if( p_dec->fmt_in.i_cat == AUDIO_ES )\r
+ {\r
+ uint16_t i_tag;\r
+ dmo_partial_type.type = MEDIATYPE_Audio;\r
+ dmo_partial_type.subtype = dmo_partial_type.type;\r
+ dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;\r
+ fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );\r
+ if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;\r
+ }\r
+ else\r
+ {\r
+ dmo_partial_type.type = MEDIATYPE_Video;\r
+ dmo_partial_type.subtype = dmo_partial_type.type;\r
+ dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;\r
+ }\r
+\r
+#ifndef LOADER\r
+ { /* <- ugly ? yes */\r
+ IEnumDMO *p_enum_dmo = NULL;\r
+ WCHAR *psz_dmo_name;\r
+ GUID clsid_dmo;\r
HRESULT (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,\r
const DMO_PARTIAL_MEDIATYPE *,\r
uint32_t, const DMO_PARTIAL_MEDIATYPE *,\r
IEnumDMO ** );\r
\r
+\r
/* Load msdmo DLL */\r
- HINSTANCE hmsdmo_dll = LoadLibrary( "msdmo.dll" );\r
+ hmsdmo_dll = LoadLibrary( "msdmo.dll" );\r
if( hmsdmo_dll == NULL )\r
{\r
msg_Dbg( p_dec, "failed loading msdmo.dll" );\r
return VLC_EGENERIC;\r
}\r
\r
- /* Look for a DMO which can handle the requested codec */\r
- if( p_dec->fmt_in.i_cat == AUDIO_ES )\r
- {\r
- uint16_t i_tag;\r
- dmo_partial_type.type = MEDIATYPE_Audio;\r
- dmo_partial_type.subtype = dmo_partial_type.type;\r
- dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;\r
- fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );\r
- if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;\r
- }\r
- else\r
- {\r
- dmo_partial_type.type = MEDIATYPE_Video;\r
- dmo_partial_type.subtype = dmo_partial_type.type;\r
- dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;\r
- }\r
\r
/* Initialize OLE/COM */\r
CoInitialize( 0 );\r
msg_Err( p_dec, "can't create DMO" );\r
goto error;\r
}\r
+ }\r
+#else /* LOADER */\r
+ {\r
+ GETCLASS GetClass;\r
+ struct IClassFactory* cFactory = NULL;\r
+ struct IUnknown* cObject = NULL;\r
+\r
+ int i_err;\r
+ int i_codec;\r
+ for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ )\r
+ {\r
+ if( codecs_table[i_codec].i_fourcc == p_dec->fmt_in.i_codec )\r
+ break;\r
+ }\r
+ if( codecs_table[i_codec].i_fourcc == 0 )\r
+ return VLC_EGENERIC; /* Can't happen */\r
+\r
+ hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll );\r
+ if( hmsdmo_dll == NULL )\r
+ {\r
+ msg_Dbg( p_dec, "failed loading '%s'", codecs_table[i_codec].psz_dll );\r
+ return VLC_EGENERIC;\r
+ }\r
+\r
+ GetClass = (GETCLASS)GetProcAddress( hmsdmo_dll, "DllGetClassObject");\r
+ if (!GetClass)\r
+ {\r
+ msg_Dbg( p_dec, "GetProcAddress failed to find DllGetClassObject()" );\r
+ FreeLibrary( hmsdmo_dll );\r
+ return VLC_EGENERIC;\r
+ }\r
+\r
+ i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory, (void**)&cFactory );\r
+ if( i_err || cFactory == NULL )\r
+ {\r
+ msg_Dbg( p_dec, "no such class object" );\r
+ FreeLibrary( hmsdmo_dll );\r
+ return VLC_EGENERIC;\r
+ }\r
+\r
+ i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown, (void**)&cObject );\r
+ cFactory->vt->Release((IUnknown*)cFactory );\r
+ if( i_err || !cObject )\r
+ {\r
+ msg_Dbg( p_dec, "class factory failure" );\r
+ FreeLibrary( hmsdmo_dll );\r
+ return VLC_EGENERIC;\r
+ }\r
+ i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject, (void**)&p_dmo );\r
+#if 0\r
+ if (hr == 0)\r
+ {\r
+ /* query for some extra available interface */\r
+ HRESULT r = object->vt->QueryInterface(object, &IID_IMediaObjectInPlace, (void**)&This->m_pInPlace);\r
+ if (r == 0 && This->m_pInPlace)\r
+ printf("DMO dll supports InPlace - PLEASE REPORT to developer\n");\r
+ r = object->vt->QueryInterface(object, &IID_IDMOVideoOutputOptimizations, (void**)&This->m_pOptim);\r
+ if (r == 0 && This->m_pOptim)\r
+ {\r
+ unsigned long flags;\r
+ r = This->m_pOptim->vt->QueryOperationModePreferences(This->m_pOptim, 0, &flags);\r
+ printf("DMO dll supports VO Optimizations %ld %lx\n", r, flags);\r
+ if (flags & DMO_VOSF_NEEDS_PREVIOUS_SAMPLE)\r
+ printf("DMO dll might use previous sample when requested\n");\r
+ }\r
+ }\r
+#endif\r
+ cObject->vt->Release((IUnknown*)cObject );\r
+ }\r
+#endif /* LOADER */\r
\r
/* Setup input format */\r
memset( &dmo_input_type, 0, sizeof(dmo_input_type) );\r
p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;\r
p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;\r
p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;\r
- p_wf->cbSize = i_size;\r
+ p_wf->cbSize = p_dec->fmt_in.i_extra;\r
\r
dmo_input_type.formattype = FORMAT_WaveFormatEx;\r
dmo_input_type.cbFormat = i_size;\r
p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;\r
p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;\r
p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;\r
- p_dec->fmt_out.audio.i_bitspersample =\r
- p_dec->fmt_in.audio.i_bitspersample;\r
+ p_dec->fmt_out.audio.i_bitspersample = 16;//p_dec->fmt_in.audio.i_bitspersample; We request 16\r
p_dec->fmt_out.audio.i_physical_channels =\r
p_dec->fmt_out.audio.i_original_channels =\r
pi_channels_maps[p_dec->fmt_out.audio.i_channels];\r
p_wf->wBitsPerSample / 8 * p_wf->nChannels;\r
p_wf->nAvgBytesPerSec =\r
p_wf->nSamplesPerSec * p_wf->nBlockAlign;\r
- p_wf->cbSize = sizeof(WAVEFORMATEX);\r
+ p_wf->cbSize = 0;\r
\r
dmo_output_type.formattype = FORMAT_WaveFormatEx;\r
dmo_output_type.subtype = MEDIASUBTYPE_PCM;\r
\r
p_sys->hmsdmo_dll = hmsdmo_dll;\r
p_sys->p_dmo = p_dmo;\r
+#ifdef LOADER\r
+ p_sys->ldt_fs = ldt_fs;\r
+#endif\r
\r
/* Find out some properties of the output */\r
{\r
\r
FreeLibrary( p_sys->hmsdmo_dll );\r
\r
+#if 0\r
+#ifdef LOADER\r
+ Restore_LDT_Keeper( p_sys->ldt_fs );\r
+#endif\r
+#endif\r
+\r
if( p_sys->p_buffer ) free( p_sys->p_buffer );\r
free( p_sys );\r
}\r
uint32_t i_status, i_buffer_out;\r
uint8_t *p_buffer_out;\r
\r
+ if( p_sys == NULL )\r
+ {\r
+ if( DecoderOpen( VLC_OBJECT(p_dec) ) )\r
+ {\r
+ msg_Err( p_dec, "DecoderOpen failed" );\r
+ return NULL;\r
+ }\r
+ p_sys = p_dec->p_sys;\r
+ }\r
+\r
if( !pp_block ) return NULL;\r
\r
p_block = *pp_block;\r
{\r
aout_buffer_t *p_aout_buffer;\r
int i_samples = i_buffer_out /\r
- ( p_dec->fmt_in.audio.i_bitspersample *\r
- p_dec->fmt_in.audio.i_channels / 8 );\r
+ ( p_dec->fmt_out.audio.i_bitspersample *\r
+ p_dec->fmt_out.audio.i_channels / 8 );\r
\r
p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );\r
memcpy( p_aout_buffer->p_buffer, p_buffer_out, i_buffer_out );\r