1 /*****************************************************************************
\r
2 * dmo.c : DirectMedia Object decoder module for vlc
\r
3 *****************************************************************************
\r
4 * Copyright (C) 2002, 2003 VideoLAN
\r
7 * Author: Gildas Bazin <gbazin@videolan.org>
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License as published by
\r
11 * the Free Software Foundation; either version 2 of the License, or
\r
12 * (at your option) any later version.
\r
14 * This program is distributed in the hope that it will be useful,
\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 * GNU General Public License for more details.
\r
19 * You should have received a copy of the GNU General Public License
\r
20 * along with this program; if not, write to the Free Software
\r
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
\r
22 *****************************************************************************/
\r
24 /*****************************************************************************
\r
26 *****************************************************************************/
\r
31 #include <vlc/vlc.h>
\r
32 #include <vlc/decoder.h>
\r
33 #include <vlc/vout.h>
\r
37 /* Need the w32dll loader from mplayer */
\r
38 # include <wine/winerror.h>
\r
39 # include <dmo/dmo.h>
\r
40 # include <dmo/dmo_interfaces.h>
\r
41 # include <dmo/dmo_guids.h>
\r
42 # include <ldt_keeper.h>
\r
44 /* Avoid codecs.h to redefine a few symbols */
\r
46 # define _GUID_DEFINED
\r
47 # define _REFERENCE_TIME_
\r
48 # define _VIDEOINFOHEADER_
\r
50 /* Ugly, wine loader and vlc doesn't use the same field name for GUID */
\r
57 HRESULT CoInitialize( LPVOID pvReserved ) { return (HRESULT)-1; }
\r
58 void CoUninitialize(void) { }
\r
61 HMODULE WINAPI LoadLibraryA(LPCSTR);
\r
62 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
\r
63 int WINAPI FreeLibrary(HMODULE);
\r
65 typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);
\r
68 # include <objbase.h>
\r
74 static int pi_channels_maps[7] =
\r
78 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
79 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
80 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
\r
81 | AOUT_CHAN_REARRIGHT,
\r
82 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
83 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
\r
84 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
85 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
\r
88 /*****************************************************************************
\r
90 *****************************************************************************/
\r
91 static int Open ( vlc_object_t * );
\r
92 static int DecoderOpen ( vlc_object_t * );
\r
93 static void DecoderClose ( vlc_object_t * );
\r
94 static void *DecodeBlock ( decoder_t *, block_t ** );
\r
96 static void CopyPicture( decoder_t *, picture_t *, uint8_t * );
\r
99 set_description( _("DirectMedia Object decoder") );
\r
100 add_shortcut( "dmo" );
\r
101 set_capability( "decoder", 1 );
\r
102 set_callbacks( Open, DecoderClose );
\r
105 /*****************************************************************************
\r
107 *****************************************************************************/
\r
109 /****************************************************************************
\r
110 * Decoder descriptor declaration
\r
111 ****************************************************************************/
\r
112 struct decoder_sys_t
\r
114 HINSTANCE hmsdmo_dll;
\r
115 IMediaObject *p_dmo;
\r
120 audio_date_t end_date;
\r
128 static const GUID guid_wmv9 = { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };
\r
129 static const GUID guid_wma9 = { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };
\r
131 static const GUID guid_wmv = { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };
\r
132 static const GUID guid_wma = { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };
\r
134 static const struct
\r
136 vlc_fourcc_t i_fourcc;
\r
137 const char *psz_dll;
\r
138 const GUID *p_guid;
\r
142 { VLC_FOURCC('W','M','V','3'), "wmv9dmod.dll", &guid_wmv9 },
\r
143 { VLC_FOURCC('w','m','v','3'), "wmv9dmod.dll", &guid_wmv9 },
\r
145 { VLC_FOURCC('W','M','V','2'), "wmvdmod.dll", &guid_wmv },
\r
146 { VLC_FOURCC('w','m','v','2'), "wmvdmod.dll", &guid_wmv },
\r
148 { VLC_FOURCC('W','M','V','1'), "wmvdmod.dll", &guid_wmv },
\r
149 { VLC_FOURCC('w','m','v','1'), "wmvdmod.dll", &guid_wmv },
\r
152 { VLC_FOURCC('W','M','A','3'), "wma9dmod.dll", &guid_wma9 },
\r
153 { VLC_FOURCC('w','m','a','3'), "wma9dmod.dll", &guid_wma9 },
\r
161 /*****************************************************************************
\r
162 * Open: open dmo codec
\r
163 *****************************************************************************/
\r
164 static int Open( vlc_object_t *p_this )
\r
167 return DecoderOpen( p_this );
\r
169 decoder_t *p_dec = (decoder_t*)p_this;
\r
171 /* We can't open it now, because of ldt_keeper or something
\r
172 * Open/Decode/Close has to be done in the same thread */
\r
174 p_dec->p_sys = NULL;
\r
177 /* Probe if we support it */
\r
178 for( i = 0; codecs_table[i].i_fourcc != 0; i++ )
\r
180 if( codecs_table[i].i_fourcc == p_dec->fmt_in.i_codec )
\r
182 msg_Dbg( p_dec, "DMO codec for %4.4s may work with dll=%s",
\r
183 (char*)&p_dec->fmt_in.i_codec,
\r
184 codecs_table[i].psz_dll );
\r
186 /* Set callbacks */
\r
187 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeBlock;
\r
188 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))DecodeBlock;
\r
189 return VLC_SUCCESS;
\r
192 return VLC_EGENERIC;
\r
196 /*****************************************************************************
\r
197 * DecoderOpen: open dmo codec
\r
198 *****************************************************************************/
\r
199 static int DecoderOpen( vlc_object_t *p_this )
\r
201 decoder_t *p_dec = (decoder_t*)p_this;
\r
202 decoder_sys_t *p_sys = NULL;
\r
204 DMO_PARTIAL_MEDIATYPE dmo_partial_type;
\r
205 DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;
\r
206 IMediaObject *p_dmo = NULL;
\r
208 VIDEOINFOHEADER *p_vih = NULL;
\r
209 WAVEFORMATEX *p_wf = NULL;
\r
212 ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
\r
213 #endif /* LOADER */
\r
215 HINSTANCE hmsdmo_dll = NULL;
\r
217 /* Look for a DMO which can handle the requested codec */
\r
218 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
221 dmo_partial_type.type = MEDIATYPE_Audio;
\r
222 dmo_partial_type.subtype = dmo_partial_type.type;
\r
223 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
224 fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );
\r
225 if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;
\r
229 dmo_partial_type.type = MEDIATYPE_Video;
\r
230 dmo_partial_type.subtype = dmo_partial_type.type;
\r
231 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
235 { /* <- ugly ? yes */
\r
236 IEnumDMO *p_enum_dmo = NULL;
\r
237 WCHAR *psz_dmo_name;
\r
239 HRESULT (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,
\r
240 const DMO_PARTIAL_MEDIATYPE *,
\r
241 uint32_t, const DMO_PARTIAL_MEDIATYPE *,
\r
245 /* Load msdmo DLL */
\r
246 hmsdmo_dll = LoadLibrary( "msdmo.dll" );
\r
247 if( hmsdmo_dll == NULL )
\r
249 msg_Dbg( p_dec, "failed loading msdmo.dll" );
\r
250 return VLC_EGENERIC;
\r
252 OurDMOEnum = (void *)GetProcAddress( hmsdmo_dll, "DMOEnum" );
\r
253 if( OurDMOEnum == NULL )
\r
255 msg_Dbg( p_dec, "GetProcAddress failed to find DMOEnum()" );
\r
256 FreeLibrary( hmsdmo_dll );
\r
257 return VLC_EGENERIC;
\r
261 /* Initialize OLE/COM */
\r
264 if( OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
\r
265 1, &dmo_partial_type, 0, NULL, &p_enum_dmo ) )
\r
270 /* Pickup the first available codec */
\r
271 if( p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo,
\r
272 &psz_dmo_name, NULL ) )
\r
276 p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo );
\r
280 char psz_temp[MAX_PATH];
\r
281 wcstombs( psz_temp, psz_dmo_name, MAX_PATH );
\r
282 msg_Dbg( p_dec, "found DMO: %s", psz_temp );
\r
286 CoTaskMemFree( psz_dmo_name );
\r
289 if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC,
\r
290 &IID_IMediaObject, (void **)&p_dmo ) )
\r
292 msg_Err( p_dec, "can't create DMO" );
\r
299 struct IClassFactory* cFactory = NULL;
\r
300 struct IUnknown* cObject = NULL;
\r
304 for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ )
\r
306 if( codecs_table[i_codec].i_fourcc == p_dec->fmt_in.i_codec )
\r
309 if( codecs_table[i_codec].i_fourcc == 0 )
\r
310 return VLC_EGENERIC; /* Can't happen */
\r
312 hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll );
\r
313 if( hmsdmo_dll == NULL )
\r
315 msg_Dbg( p_dec, "failed loading '%s'", codecs_table[i_codec].psz_dll );
\r
316 return VLC_EGENERIC;
\r
319 GetClass = (GETCLASS)GetProcAddress( hmsdmo_dll, "DllGetClassObject");
\r
322 msg_Dbg( p_dec, "GetProcAddress failed to find DllGetClassObject()" );
\r
323 FreeLibrary( hmsdmo_dll );
\r
324 return VLC_EGENERIC;
\r
327 i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory, (void**)&cFactory );
\r
328 if( i_err || cFactory == NULL )
\r
330 msg_Dbg( p_dec, "no such class object" );
\r
331 FreeLibrary( hmsdmo_dll );
\r
332 return VLC_EGENERIC;
\r
335 i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown, (void**)&cObject );
\r
336 cFactory->vt->Release((IUnknown*)cFactory );
\r
337 if( i_err || !cObject )
\r
339 msg_Dbg( p_dec, "class factory failure" );
\r
340 FreeLibrary( hmsdmo_dll );
\r
341 return VLC_EGENERIC;
\r
343 i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject, (void**)&p_dmo );
\r
347 /* query for some extra available interface */
\r
348 HRESULT r = object->vt->QueryInterface(object, &IID_IMediaObjectInPlace, (void**)&This->m_pInPlace);
\r
349 if (r == 0 && This->m_pInPlace)
\r
350 printf("DMO dll supports InPlace - PLEASE REPORT to developer\n");
\r
351 r = object->vt->QueryInterface(object, &IID_IDMOVideoOutputOptimizations, (void**)&This->m_pOptim);
\r
352 if (r == 0 && This->m_pOptim)
\r
354 unsigned long flags;
\r
355 r = This->m_pOptim->vt->QueryOperationModePreferences(This->m_pOptim, 0, &flags);
\r
356 printf("DMO dll supports VO Optimizations %ld %lx\n", r, flags);
\r
357 if (flags & DMO_VOSF_NEEDS_PREVIOUS_SAMPLE)
\r
358 printf("DMO dll might use previous sample when requested\n");
\r
362 cObject->vt->Release((IUnknown*)cObject );
\r
364 #endif /* LOADER */
\r
366 /* Setup input format */
\r
367 memset( &dmo_input_type, 0, sizeof(dmo_input_type) );
\r
368 dmo_input_type.majortype = dmo_partial_type.type;
\r
369 dmo_input_type.subtype = dmo_partial_type.subtype;
\r
370 dmo_input_type.pUnk = 0;
\r
372 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
374 int i_size = sizeof(WAVEFORMATEX) + p_dec->fmt_in.i_extra;
\r
375 p_wf = malloc( i_size );
\r
377 memset( p_wf, 0, sizeof(WAVEFORMATEX) );
\r
378 if( p_dec->fmt_in.i_extra )
\r
379 memcpy( &p_wf[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
381 p_wf->wFormatTag = dmo_partial_type.subtype.Data1;
\r
382 p_wf->nSamplesPerSec = p_dec->fmt_in.audio.i_rate;
\r
383 p_wf->nChannels = p_dec->fmt_in.audio.i_channels;
\r
384 p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;
\r
385 p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;
\r
386 p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;
\r
387 p_wf->cbSize = p_dec->fmt_in.i_extra;
\r
389 dmo_input_type.formattype = FORMAT_WaveFormatEx;
\r
390 dmo_input_type.cbFormat = i_size;
\r
391 dmo_input_type.pbFormat = (char *)p_wf;
\r
392 dmo_input_type.pUnk = NULL;
\r
393 dmo_input_type.bFixedSizeSamples = 1;
\r
394 dmo_input_type.bTemporalCompression = 0;
\r
395 dmo_input_type.lSampleSize = p_wf->nBlockAlign;
\r
399 BITMAPINFOHEADER *p_bih;
\r
401 int i_size = sizeof(VIDEOINFOHEADER) + p_dec->fmt_in.i_extra;
\r
402 p_vih = malloc( i_size );
\r
404 memset( p_vih, 0, sizeof(VIDEOINFOHEADER) );
\r
405 if( p_dec->fmt_in.i_extra )
\r
406 memcpy( &p_vih[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
408 p_bih = &p_vih->bmiHeader;
\r
409 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
410 p_bih->biWidth = p_dec->fmt_in.video.i_width;
\r
411 p_bih->biHeight = p_dec->fmt_in.video.i_height;
\r
412 p_bih->biBitCount = p_dec->fmt_in.video.i_bits_per_pixel;
\r
413 p_bih->biPlanes = 1;
\r
414 p_bih->biSize = i_size - sizeof(VIDEOINFOHEADER) +
\r
415 sizeof(BITMAPINFOHEADER);
\r
417 p_vih->rcSource.left = p_vih->rcSource.top = 0;
\r
418 p_vih->rcSource.right = p_dec->fmt_in.video.i_width;
\r
419 p_vih->rcSource.bottom = p_dec->fmt_in.video.i_height;
\r
420 p_vih->rcTarget = p_vih->rcSource;
\r
422 dmo_input_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
423 dmo_input_type.bFixedSizeSamples = 0;
\r
424 dmo_input_type.bTemporalCompression = 1;
\r
425 dmo_input_type.cbFormat = i_size;
\r
426 dmo_input_type.pbFormat = (char *)p_vih;
\r
429 if( p_dmo->vt->SetInputType( p_dmo, 0, &dmo_input_type, 0 ) )
\r
431 msg_Err( p_dec, "can't set DMO input type" );
\r
434 msg_Dbg( p_dec, "DMO input type set" );
\r
436 /* Setup output format */
\r
437 memset( &dmo_output_type, 0, sizeof(dmo_output_type) );
\r
438 dmo_output_type.majortype = dmo_partial_type.type;
\r
439 dmo_output_type.pUnk = 0;
\r
441 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
443 /* Setup the format */
\r
444 p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
\r
445 p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
\r
446 p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
\r
447 p_dec->fmt_out.audio.i_bitspersample = 16;//p_dec->fmt_in.audio.i_bitspersample; We request 16
\r
448 p_dec->fmt_out.audio.i_physical_channels =
\r
449 p_dec->fmt_out.audio.i_original_channels =
\r
450 pi_channels_maps[p_dec->fmt_out.audio.i_channels];
\r
452 p_wf->wFormatTag = WAVE_FORMAT_PCM;
\r
453 p_wf->nSamplesPerSec = p_dec->fmt_out.audio.i_rate;
\r
454 p_wf->nChannels = p_dec->fmt_out.audio.i_channels;
\r
455 p_wf->wBitsPerSample = p_dec->fmt_out.audio.i_bitspersample;
\r
456 p_wf->nBlockAlign =
\r
457 p_wf->wBitsPerSample / 8 * p_wf->nChannels;
\r
458 p_wf->nAvgBytesPerSec =
\r
459 p_wf->nSamplesPerSec * p_wf->nBlockAlign;
\r
462 dmo_output_type.formattype = FORMAT_WaveFormatEx;
\r
463 dmo_output_type.subtype = MEDIASUBTYPE_PCM;
\r
464 dmo_output_type.cbFormat = sizeof(WAVEFORMATEX);
\r
465 dmo_output_type.pbFormat = (char *)p_wf;
\r
466 dmo_output_type.bFixedSizeSamples = 1;
\r
467 dmo_output_type.bTemporalCompression = 0;
\r
468 dmo_output_type.lSampleSize = p_wf->nBlockAlign;
\r
469 dmo_output_type.pUnk = NULL;
\r
473 BITMAPINFOHEADER *p_bih;
\r
475 p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
\r
476 p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
\r
477 p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
\r
478 p_dec->fmt_out.video.i_bits_per_pixel = 12;
\r
479 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
\r
480 p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
\r
482 dmo_output_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
483 dmo_output_type.subtype = MEDIASUBTYPE_YV12;
\r
485 p_bih = &p_vih->bmiHeader;
\r
486 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
487 p_bih->biHeight *= -1;
\r
488 p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel;
\r
489 p_bih->biSizeImage = p_dec->fmt_in.video.i_width *
\r
490 p_dec->fmt_in.video.i_height *
\r
491 (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8;
\r
493 //p_bih->biPlanes = 1;
\r
494 p_bih->biSize = sizeof(BITMAPINFOHEADER);
\r
496 dmo_output_type.bFixedSizeSamples = VLC_TRUE;
\r
497 dmo_output_type.bTemporalCompression = 0;
\r
498 dmo_output_type.lSampleSize = p_bih->biSizeImage;
\r
499 dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER);
\r
500 dmo_output_type.pbFormat = (char *)p_vih;
\r
503 /* Enumerate output types */
\r
504 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
509 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
511 msg_Dbg( p_dec, "available output chroma: %4.4s",
\r
512 (char *)&mt.subtype.Data1 );
\r
516 /* Choose an output type.
\r
517 * FIXME, get rid of the dmo_output_type code above. */
\r
518 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
523 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
525 if( dmo_output_type.subtype.Data1 == mt.subtype.Data1 )
\r
527 *p_vih = *(VIDEOINFOHEADER *)mt.pbFormat;
\r
533 if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) )
\r
535 msg_Err( p_dec, "can't set DMO output type" );
\r
538 msg_Dbg( p_dec, "DMO output type set" );
\r
540 /* Allocate the memory needed to store the decoder's structure */
\r
541 if( ( p_dec->p_sys = p_sys =
\r
542 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
\r
544 msg_Err( p_dec, "out of memory" );
\r
548 p_sys->hmsdmo_dll = hmsdmo_dll;
\r
549 p_sys->p_dmo = p_dmo;
\r
551 p_sys->ldt_fs = ldt_fs;
\r
554 /* Find out some properties of the output */
\r
556 uint32_t i_size, i_align;
\r
558 p_sys->i_min_output = 0;
\r
559 if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
\r
561 msg_Err( p_dec, "GetOutputSizeInfo() failed" );
\r
566 msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i",
\r
568 p_sys->i_min_output = i_size;
\r
569 p_sys->p_buffer = malloc( i_size );
\r
570 if( !p_sys->p_buffer ) goto error;
\r
574 /* Set output properties */
\r
575 p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
\r
576 if( p_dec->fmt_out.i_cat == AUDIO_ES )
\r
577 aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
\r
579 aout_DateInit( &p_sys->end_date, 25 /* FIXME */ );
\r
580 aout_DateSet( &p_sys->end_date, 0 );
\r
582 /* Set callbacks */
\r
583 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
\r
585 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
\r
588 if( p_vih ) free( p_vih );
\r
589 if( p_wf ) free( p_wf );
\r
591 return VLC_SUCCESS;
\r
594 /* Uninitialize OLE/COM */
\r
596 FreeLibrary( hmsdmo_dll );
\r
598 if( p_vih ) free( p_vih );
\r
599 if( p_wf ) free( p_wf );
\r
600 if( p_sys ) free( p_sys );
\r
602 return VLC_EGENERIC;
\r
605 /*****************************************************************************
\r
606 * DecoderClose: close codec
\r
607 *****************************************************************************/
\r
608 void DecoderClose( vlc_object_t *p_this )
\r
610 decoder_t *p_dec = (decoder_t*)p_this;
\r
611 decoder_sys_t *p_sys = p_dec->p_sys;
\r
613 /* Uninitialize OLE/COM */
\r
616 FreeLibrary( p_sys->hmsdmo_dll );
\r
620 Restore_LDT_Keeper( p_sys->ldt_fs );
\r
624 if( p_sys->p_buffer ) free( p_sys->p_buffer );
\r
628 /****************************************************************************
\r
629 * DecodeBlock: the whole thing
\r
630 ****************************************************************************
\r
631 * This function must be fed with ogg packets.
\r
632 ****************************************************************************/
\r
633 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
\r
635 decoder_sys_t *p_sys = p_dec->p_sys;
\r
639 DMO_OUTPUT_DATA_BUFFER db;
\r
640 CMediaBuffer *p_out;
\r
642 uint32_t i_status, i_buffer_out;
\r
643 uint8_t *p_buffer_out;
\r
645 if( p_sys == NULL )
\r
647 if( DecoderOpen( VLC_OBJECT(p_dec) ) )
\r
649 msg_Err( p_dec, "DecoderOpen failed" );
\r
652 p_sys = p_dec->p_sys;
\r
655 if( !pp_block ) return NULL;
\r
657 p_block = *pp_block;
\r
659 /* Won't work with streams with B-frames, but do we have any ? */
\r
660 if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts;
\r
662 /* Date management */
\r
663 if( p_block && p_block->i_pts > 0 &&
\r
664 p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
\r
666 aout_DateSet( &p_sys->end_date, p_block->i_pts );
\r
669 #if 0 /* Breaks the video decoding */
\r
670 if( !aout_DateGet( &p_sys->end_date ) )
\r
672 /* We've just started the stream, wait for the first PTS. */
\r
673 if( p_block ) block_Release( p_block );
\r
678 /* Feed input to the DMO */
\r
679 if( p_block && p_block->i_buffer )
\r
681 CMediaBuffer *p_in;
\r
683 p_in = CMediaBufferCreate( p_block, p_block->i_buffer, VLC_TRUE );
\r
685 i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
\r
686 (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFER_SYNCPOINT,
\r
689 p_in->vt->Release( (IUnknown *)p_in );
\r
691 if( i_result == S_FALSE )
\r
693 /* No output generated */
\r
695 msg_Dbg( p_dec, "ProcessInput(): no output generated" );
\r
699 else if( i_result == DMO_E_NOTACCEPTING )
\r
701 /* Need to call ProcessOutput */
\r
702 msg_Dbg( p_dec, "ProcessInput(): not accepting" );
\r
704 else if( i_result != S_OK )
\r
706 msg_Dbg( p_dec, "ProcessInput(): failed" );
\r
711 //msg_Dbg( p_dec, "ProcessInput(): successful" );
\r
715 else if( p_block && !p_block->i_buffer )
\r
717 block_Release( p_block );
\r
721 /* Get output from the DMO */
\r
722 block_out.p_buffer = p_sys->p_buffer;;
\r
723 block_out.i_buffer = 0;
\r
725 p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, VLC_FALSE );
\r
726 db.rtTimestamp = 0;
\r
727 db.rtTimelength = 0;
\r
729 db.pBuffer = (IMediaBuffer *)p_out;
\r
731 i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
\r
732 DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER,
\r
733 1, &db, &i_status );
\r
735 if( i_result != S_OK )
\r
737 if( i_result != S_FALSE )
\r
738 msg_Dbg( p_dec, "ProcessOutput(): failed" );
\r
741 msg_Dbg( p_dec, "ProcessOutput(): no output" );
\r
744 p_out->vt->Release( (IUnknown *)p_out );
\r
749 msg_Dbg( p_dec, "ProcessOutput(): success" );
\r
752 i_result = p_out->vt->GetBufferAndLength( (IMediaBuffer *)p_out,
\r
753 &p_buffer_out, &i_buffer_out );
\r
754 if( i_result != S_OK )
\r
756 msg_Dbg( p_dec, "GetBufferAndLength(): failed" );
\r
757 p_out->vt->Release( (IUnknown *)p_out );
\r
761 if( !i_buffer_out )
\r
764 msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );
\r
766 p_out->vt->Release( (IUnknown *)p_out );
\r
770 if( p_dec->fmt_out.i_cat == VIDEO_ES )
\r
772 /* Get a new picture */
\r
773 picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec );
\r
774 if( !p_pic ) return NULL;
\r
776 CopyPicture( p_dec, p_pic, block_out.p_buffer );
\r
778 /* Date management */
\r
779 p_pic->date = aout_DateGet( &p_sys->end_date );
\r
780 aout_DateIncrement( &p_sys->end_date, 1 );
\r
782 p_out->vt->Release( (IUnknown *)p_out );
\r
788 aout_buffer_t *p_aout_buffer;
\r
789 int i_samples = i_buffer_out /
\r
790 ( p_dec->fmt_out.audio.i_bitspersample *
\r
791 p_dec->fmt_out.audio.i_channels / 8 );
\r
793 p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
\r
794 memcpy( p_aout_buffer->p_buffer, p_buffer_out, i_buffer_out );
\r
796 /* Date management */
\r
797 p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
\r
798 p_aout_buffer->end_date =
\r
799 aout_DateIncrement( &p_sys->end_date, i_samples );
\r
801 p_out->vt->Release( (IUnknown *)p_out );
\r
803 return p_aout_buffer;
\r
809 static void CopyPicture( decoder_t *p_dec, picture_t *p_pic, uint8_t *p_in )
\r
811 int i_plane, i_line, i_width, i_dst_stride;
\r
812 uint8_t *p_dst, *p_src = p_in;
\r
814 p_dst = p_pic->p[1].p_pixels;
\r
815 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
816 p_pic->p[2].p_pixels = p_dst;
\r
818 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
\r
820 p_dst = p_pic->p[i_plane].p_pixels;
\r
821 i_width = p_pic->p[i_plane].i_visible_pitch;
\r
822 i_dst_stride = p_pic->p[i_plane].i_pitch;
\r
824 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
\r
826 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
\r
828 p_dst += i_dst_stride;
\r
832 p_dst = p_pic->p[1].p_pixels;
\r
833 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
834 p_pic->p[2].p_pixels = p_dst;
\r