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
38 # include <objbase.h>
\r
42 /* Need the w32dll loader from mplayer */
\r
43 # include <wine/winerror.h>
\r
44 # include <ldt_keeper.h>
\r
45 # include <wine/windef.h>
\r
53 long CoInitialize( void *pvReserved ) { return -1; }
\r
54 void CoUninitialize( void ) { }
\r
56 /* A few prototypes */
\r
57 HMODULE WINAPI LoadLibraryA(LPCSTR);
\r
58 #define LoadLibrary LoadLibraryA
\r
59 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
\r
60 int WINAPI FreeLibrary(HMODULE);
\r
61 typedef long STDCALL (*GETCLASS) ( const GUID*, const GUID*, void** );
\r
64 static int pi_channels_maps[7] =
\r
68 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
69 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
70 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
\r
71 | AOUT_CHAN_REARRIGHT,
\r
72 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
73 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
\r
74 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
75 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
\r
78 /*****************************************************************************
\r
80 *****************************************************************************/
\r
81 static int Open ( vlc_object_t * );
\r
82 static int DecoderOpen ( vlc_object_t * );
\r
83 static void DecoderClose ( vlc_object_t * );
\r
84 static void *DecodeBlock ( decoder_t *, block_t ** );
\r
86 static void CopyPicture( decoder_t *, picture_t *, uint8_t * );
\r
89 set_description( _("DirectMedia Object decoder") );
\r
90 add_shortcut( "dmo" );
\r
91 set_capability( "decoder", 1 );
\r
92 set_callbacks( Open, DecoderClose );
\r
95 /*****************************************************************************
\r
97 *****************************************************************************/
\r
99 /****************************************************************************
\r
100 * Decoder descriptor declaration
\r
101 ****************************************************************************/
\r
102 struct decoder_sys_t
\r
104 HINSTANCE hmsdmo_dll;
\r
105 IMediaObject *p_dmo;
\r
110 audio_date_t end_date;
\r
118 static const GUID guid_wmv9 = { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };
\r
119 static const GUID guid_wma9 = { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };
\r
121 static const GUID guid_wmv = { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };
\r
122 static const GUID guid_wma = { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };
\r
124 static const struct
\r
126 vlc_fourcc_t i_fourcc;
\r
127 const char *psz_dll;
\r
128 const GUID *p_guid;
\r
132 { VLC_FOURCC('W','M','V','3'), "wmv9dmod.dll", &guid_wmv9 },
\r
133 { VLC_FOURCC('w','m','v','3'), "wmv9dmod.dll", &guid_wmv9 },
\r
135 { VLC_FOURCC('W','M','V','2'), "wmvdmod.dll", &guid_wmv },
\r
136 { VLC_FOURCC('w','m','v','2'), "wmvdmod.dll", &guid_wmv },
\r
138 { VLC_FOURCC('W','M','V','1'), "wmvdmod.dll", &guid_wmv },
\r
139 { VLC_FOURCC('w','m','v','1'), "wmvdmod.dll", &guid_wmv },
\r
142 { VLC_FOURCC('W','M','A','3'), "wma9dmod.dll", &guid_wma9 },
\r
143 { VLC_FOURCC('w','m','a','3'), "wma9dmod.dll", &guid_wma9 },
\r
148 #endif /* LOADER */
\r
150 /*****************************************************************************
\r
151 * Open: open dmo codec
\r
152 *****************************************************************************/
\r
153 static int Open( vlc_object_t *p_this )
\r
156 return DecoderOpen( p_this );
\r
159 decoder_t *p_dec = (decoder_t*)p_this;
\r
161 /* We can't open it now, because of ldt_keeper or something
\r
162 * Open/Decode/Close has to be done in the same thread */
\r
164 p_dec->p_sys = NULL;
\r
166 /* Probe if we support it */
\r
167 for( i = 0; codecs_table[i].i_fourcc != 0; i++ )
\r
169 if( codecs_table[i].i_fourcc == p_dec->fmt_in.i_codec )
\r
171 msg_Dbg( p_dec, "DMO codec for %4.4s may work with dll=%s",
\r
172 (char*)&p_dec->fmt_in.i_codec, codecs_table[i].psz_dll );
\r
174 /* Set callbacks */
\r
175 p_dec->pf_decode_video =
\r
176 (picture_t *(*)(decoder_t *, block_t **))DecodeBlock;
\r
177 p_dec->pf_decode_audio =
\r
178 (aout_buffer_t *(*)(decoder_t *, block_t **))DecodeBlock;
\r
179 return VLC_SUCCESS;
\r
183 return VLC_EGENERIC;
\r
184 #endif /* LOADER */
\r
187 /*****************************************************************************
\r
188 * DecoderOpen: open dmo codec
\r
189 *****************************************************************************/
\r
190 static int DecoderOpen( vlc_object_t *p_this )
\r
192 decoder_t *p_dec = (decoder_t*)p_this;
\r
193 decoder_sys_t *p_sys = NULL;
\r
195 DMO_PARTIAL_MEDIATYPE dmo_partial_type;
\r
196 DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;
\r
197 IMediaObject *p_dmo = NULL;
\r
199 VIDEOINFOHEADER *p_vih = NULL;
\r
200 WAVEFORMATEX *p_wf = NULL;
\r
203 ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
\r
204 #endif /* LOADER */
\r
206 HINSTANCE hmsdmo_dll = NULL;
\r
208 /* Look for a DMO which can handle the requested codec */
\r
209 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
212 dmo_partial_type.type = MEDIATYPE_Audio;
\r
213 dmo_partial_type.subtype = dmo_partial_type.type;
\r
214 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
215 fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );
\r
216 if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;
\r
220 dmo_partial_type.type = MEDIATYPE_Video;
\r
221 dmo_partial_type.subtype = dmo_partial_type.type;
\r
222 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
227 IEnumDMO *p_enum_dmo = NULL;
\r
228 WCHAR *psz_dmo_name;
\r
230 long (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,
\r
231 const DMO_PARTIAL_MEDIATYPE *,
\r
232 uint32_t, const DMO_PARTIAL_MEDIATYPE *,
\r
235 /* Load msdmo DLL */
\r
236 hmsdmo_dll = LoadLibrary( "msdmo.dll" );
\r
237 if( hmsdmo_dll == NULL )
\r
239 msg_Dbg( p_dec, "failed loading msdmo.dll" );
\r
240 return VLC_EGENERIC;
\r
242 OurDMOEnum = (void *)GetProcAddress( hmsdmo_dll, "DMOEnum" );
\r
243 if( OurDMOEnum == NULL )
\r
245 msg_Dbg( p_dec, "GetProcAddress failed to find DMOEnum()" );
\r
246 FreeLibrary( hmsdmo_dll );
\r
247 return VLC_EGENERIC;
\r
251 /* Initialize OLE/COM */
\r
254 if( OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
\r
255 1, &dmo_partial_type, 0, NULL, &p_enum_dmo ) )
\r
260 /* Pickup the first available codec */
\r
261 if( p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo,
\r
262 &psz_dmo_name, NULL ) )
\r
266 p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo );
\r
270 char psz_temp[MAX_PATH];
\r
271 wcstombs( psz_temp, psz_dmo_name, MAX_PATH );
\r
272 msg_Dbg( p_dec, "found DMO: %s", psz_temp );
\r
276 CoTaskMemFree( psz_dmo_name );
\r
279 if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC,
\r
280 &IID_IMediaObject, (void **)&p_dmo ) )
\r
282 msg_Err( p_dec, "can't create DMO" );
\r
290 IClassFactory *cFactory = NULL;
\r
291 IUnknown *cObject = NULL;
\r
295 for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ )
\r
297 if( codecs_table[i_codec].i_fourcc == p_dec->fmt_in.i_codec )
\r
300 if( codecs_table[i_codec].i_fourcc == 0 )
\r
301 return VLC_EGENERIC; /* Can't happen */
\r
303 hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll );
\r
304 if( hmsdmo_dll == NULL )
\r
306 msg_Dbg( p_dec, "failed loading '%s'", codecs_table[i_codec].psz_dll );
\r
307 return VLC_EGENERIC;
\r
310 GetClass = (GETCLASS)GetProcAddress( hmsdmo_dll, "DllGetClassObject" );
\r
313 msg_Dbg( p_dec, "GetProcAddress failed to find DllGetClassObject()" );
\r
314 FreeLibrary( hmsdmo_dll );
\r
315 return VLC_EGENERIC;
\r
318 i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory,
\r
319 (void**)&cFactory );
\r
320 if( i_err || cFactory == NULL )
\r
322 msg_Dbg( p_dec, "no such class object" );
\r
323 FreeLibrary( hmsdmo_dll );
\r
324 return VLC_EGENERIC;
\r
327 i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown,
\r
328 (void**)&cObject );
\r
329 cFactory->vt->Release((IUnknown*)cFactory );
\r
330 if( i_err || !cObject )
\r
332 msg_Dbg( p_dec, "class factory failure" );
\r
333 FreeLibrary( hmsdmo_dll );
\r
334 return VLC_EGENERIC;
\r
336 i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject,
\r
338 cObject->vt->Release((IUnknown*)cObject );
\r
340 #endif /* LOADER */
\r
342 /* Setup input format */
\r
343 memset( &dmo_input_type, 0, sizeof(dmo_input_type) );
\r
344 dmo_input_type.majortype = dmo_partial_type.type;
\r
345 dmo_input_type.subtype = dmo_partial_type.subtype;
\r
346 dmo_input_type.pUnk = 0;
\r
348 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
350 int i_size = sizeof(WAVEFORMATEX) + p_dec->fmt_in.i_extra;
\r
351 p_wf = malloc( i_size );
\r
353 memset( p_wf, 0, sizeof(WAVEFORMATEX) );
\r
354 if( p_dec->fmt_in.i_extra )
\r
355 memcpy( &p_wf[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
357 p_wf->wFormatTag = dmo_partial_type.subtype.Data1;
\r
358 p_wf->nSamplesPerSec = p_dec->fmt_in.audio.i_rate;
\r
359 p_wf->nChannels = p_dec->fmt_in.audio.i_channels;
\r
360 p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;
\r
361 p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;
\r
362 p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;
\r
363 p_wf->cbSize = p_dec->fmt_in.i_extra;
\r
365 dmo_input_type.formattype = FORMAT_WaveFormatEx;
\r
366 dmo_input_type.cbFormat = i_size;
\r
367 dmo_input_type.pbFormat = (char *)p_wf;
\r
368 dmo_input_type.pUnk = NULL;
\r
369 dmo_input_type.bFixedSizeSamples = 1;
\r
370 dmo_input_type.bTemporalCompression = 0;
\r
371 dmo_input_type.lSampleSize = p_wf->nBlockAlign;
\r
375 BITMAPINFOHEADER *p_bih;
\r
377 int i_size = sizeof(VIDEOINFOHEADER) + p_dec->fmt_in.i_extra;
\r
378 p_vih = malloc( i_size );
\r
380 memset( p_vih, 0, sizeof(VIDEOINFOHEADER) );
\r
381 if( p_dec->fmt_in.i_extra )
\r
382 memcpy( &p_vih[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
384 p_bih = &p_vih->bmiHeader;
\r
385 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
386 p_bih->biWidth = p_dec->fmt_in.video.i_width;
\r
387 p_bih->biHeight = p_dec->fmt_in.video.i_height;
\r
388 p_bih->biBitCount = p_dec->fmt_in.video.i_bits_per_pixel;
\r
389 p_bih->biPlanes = 1;
\r
390 p_bih->biSize = i_size - sizeof(VIDEOINFOHEADER) +
\r
391 sizeof(BITMAPINFOHEADER);
\r
393 p_vih->rcSource.left = p_vih->rcSource.top = 0;
\r
394 p_vih->rcSource.right = p_dec->fmt_in.video.i_width;
\r
395 p_vih->rcSource.bottom = p_dec->fmt_in.video.i_height;
\r
396 p_vih->rcTarget = p_vih->rcSource;
\r
398 dmo_input_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
399 dmo_input_type.bFixedSizeSamples = 0;
\r
400 dmo_input_type.bTemporalCompression = 1;
\r
401 dmo_input_type.cbFormat = i_size;
\r
402 dmo_input_type.pbFormat = (char *)p_vih;
\r
405 if( p_dmo->vt->SetInputType( p_dmo, 0, &dmo_input_type, 0 ) )
\r
407 msg_Err( p_dec, "can't set DMO input type" );
\r
410 msg_Dbg( p_dec, "DMO input type set" );
\r
412 /* Setup output format */
\r
413 memset( &dmo_output_type, 0, sizeof(dmo_output_type) );
\r
414 dmo_output_type.majortype = dmo_partial_type.type;
\r
415 dmo_output_type.pUnk = 0;
\r
417 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
419 /* Setup the format */
\r
420 p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
\r
421 p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
\r
422 p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
\r
423 p_dec->fmt_out.audio.i_bitspersample = 16;//p_dec->fmt_in.audio.i_bitspersample; We request 16
\r
424 p_dec->fmt_out.audio.i_physical_channels =
\r
425 p_dec->fmt_out.audio.i_original_channels =
\r
426 pi_channels_maps[p_dec->fmt_out.audio.i_channels];
\r
428 p_wf->wFormatTag = WAVE_FORMAT_PCM;
\r
429 p_wf->nSamplesPerSec = p_dec->fmt_out.audio.i_rate;
\r
430 p_wf->nChannels = p_dec->fmt_out.audio.i_channels;
\r
431 p_wf->wBitsPerSample = p_dec->fmt_out.audio.i_bitspersample;
\r
432 p_wf->nBlockAlign =
\r
433 p_wf->wBitsPerSample / 8 * p_wf->nChannels;
\r
434 p_wf->nAvgBytesPerSec =
\r
435 p_wf->nSamplesPerSec * p_wf->nBlockAlign;
\r
438 dmo_output_type.formattype = FORMAT_WaveFormatEx;
\r
439 dmo_output_type.subtype = MEDIASUBTYPE_PCM;
\r
440 dmo_output_type.cbFormat = sizeof(WAVEFORMATEX);
\r
441 dmo_output_type.pbFormat = (char *)p_wf;
\r
442 dmo_output_type.bFixedSizeSamples = 1;
\r
443 dmo_output_type.bTemporalCompression = 0;
\r
444 dmo_output_type.lSampleSize = p_wf->nBlockAlign;
\r
445 dmo_output_type.pUnk = NULL;
\r
449 BITMAPINFOHEADER *p_bih;
\r
451 p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
\r
452 p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
\r
453 p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
\r
454 p_dec->fmt_out.video.i_bits_per_pixel = 12;
\r
455 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
\r
456 p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
\r
458 dmo_output_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
459 dmo_output_type.subtype = MEDIASUBTYPE_YV12;
\r
461 p_bih = &p_vih->bmiHeader;
\r
462 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
463 p_bih->biHeight *= -1;
\r
464 p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel;
\r
465 p_bih->biSizeImage = p_dec->fmt_in.video.i_width *
\r
466 p_dec->fmt_in.video.i_height *
\r
467 (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8;
\r
469 //p_bih->biPlanes = 1;
\r
470 p_bih->biSize = sizeof(BITMAPINFOHEADER);
\r
472 dmo_output_type.bFixedSizeSamples = VLC_TRUE;
\r
473 dmo_output_type.bTemporalCompression = 0;
\r
474 dmo_output_type.lSampleSize = p_bih->biSizeImage;
\r
475 dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER);
\r
476 dmo_output_type.pbFormat = (char *)p_vih;
\r
479 /* Enumerate output types */
\r
480 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
485 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
487 msg_Dbg( p_dec, "available output chroma: %4.4s",
\r
488 (char *)&mt.subtype.Data1 );
\r
492 /* Choose an output type.
\r
493 * FIXME, get rid of the dmo_output_type code above. */
\r
494 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
499 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
501 if( dmo_output_type.subtype.Data1 == mt.subtype.Data1 )
\r
503 *p_vih = *(VIDEOINFOHEADER *)mt.pbFormat;
\r
509 if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) )
\r
511 msg_Err( p_dec, "can't set DMO output type" );
\r
514 msg_Dbg( p_dec, "DMO output type set" );
\r
516 /* Allocate the memory needed to store the decoder's structure */
\r
517 if( ( p_dec->p_sys = p_sys =
\r
518 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
\r
520 msg_Err( p_dec, "out of memory" );
\r
524 p_sys->hmsdmo_dll = hmsdmo_dll;
\r
525 p_sys->p_dmo = p_dmo;
\r
527 p_sys->ldt_fs = ldt_fs;
\r
530 /* Find out some properties of the output */
\r
532 uint32_t i_size, i_align;
\r
534 p_sys->i_min_output = 0;
\r
535 if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
\r
537 msg_Err( p_dec, "GetOutputSizeInfo() failed" );
\r
542 msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i",
\r
544 p_sys->i_min_output = i_size;
\r
545 p_sys->p_buffer = malloc( i_size );
\r
546 if( !p_sys->p_buffer ) goto error;
\r
550 /* Set output properties */
\r
551 p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
\r
552 if( p_dec->fmt_out.i_cat == AUDIO_ES )
\r
553 aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
\r
555 aout_DateInit( &p_sys->end_date, 25 /* FIXME */ );
\r
556 aout_DateSet( &p_sys->end_date, 0 );
\r
558 /* Set callbacks */
\r
559 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
\r
561 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
\r
564 if( p_vih ) free( p_vih );
\r
565 if( p_wf ) free( p_wf );
\r
567 return VLC_SUCCESS;
\r
570 /* Uninitialize OLE/COM */
\r
572 FreeLibrary( hmsdmo_dll );
\r
574 if( p_vih ) free( p_vih );
\r
575 if( p_wf ) free( p_wf );
\r
576 if( p_sys ) free( p_sys );
\r
578 return VLC_EGENERIC;
\r
581 /*****************************************************************************
\r
582 * DecoderClose: close codec
\r
583 *****************************************************************************/
\r
584 void DecoderClose( vlc_object_t *p_this )
\r
586 decoder_t *p_dec = (decoder_t*)p_this;
\r
587 decoder_sys_t *p_sys = p_dec->p_sys;
\r
589 /* Uninitialize OLE/COM */
\r
592 FreeLibrary( p_sys->hmsdmo_dll );
\r
596 Restore_LDT_Keeper( p_sys->ldt_fs );
\r
600 if( p_sys->p_buffer ) free( p_sys->p_buffer );
\r
604 /****************************************************************************
\r
605 * DecodeBlock: the whole thing
\r
606 ****************************************************************************
\r
607 * This function must be fed with ogg packets.
\r
608 ****************************************************************************/
\r
609 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
\r
611 decoder_sys_t *p_sys = p_dec->p_sys;
\r
615 DMO_OUTPUT_DATA_BUFFER db;
\r
616 CMediaBuffer *p_out;
\r
618 uint32_t i_status, i_buffer_out;
\r
619 uint8_t *p_buffer_out;
\r
621 if( p_sys == NULL )
\r
623 if( DecoderOpen( VLC_OBJECT(p_dec) ) )
\r
625 msg_Err( p_dec, "DecoderOpen failed" );
\r
628 p_sys = p_dec->p_sys;
\r
631 if( !pp_block ) return NULL;
\r
633 p_block = *pp_block;
\r
635 /* Won't work with streams with B-frames, but do we have any ? */
\r
636 if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts;
\r
638 /* Date management */
\r
639 if( p_block && p_block->i_pts > 0 &&
\r
640 p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
\r
642 aout_DateSet( &p_sys->end_date, p_block->i_pts );
\r
645 #if 0 /* Breaks the video decoding */
\r
646 if( !aout_DateGet( &p_sys->end_date ) )
\r
648 /* We've just started the stream, wait for the first PTS. */
\r
649 if( p_block ) block_Release( p_block );
\r
654 /* Feed input to the DMO */
\r
655 if( p_block && p_block->i_buffer )
\r
657 CMediaBuffer *p_in;
\r
659 p_in = CMediaBufferCreate( p_block, p_block->i_buffer, VLC_TRUE );
\r
661 i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
\r
662 (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFER_SYNCPOINT,
\r
665 p_in->vt->Release( (IUnknown *)p_in );
\r
667 if( i_result == S_FALSE )
\r
669 /* No output generated */
\r
671 msg_Dbg( p_dec, "ProcessInput(): no output generated" );
\r
675 else if( i_result == DMO_E_NOTACCEPTING )
\r
677 /* Need to call ProcessOutput */
\r
678 msg_Dbg( p_dec, "ProcessInput(): not accepting" );
\r
680 else if( i_result != S_OK )
\r
682 msg_Dbg( p_dec, "ProcessInput(): failed" );
\r
687 //msg_Dbg( p_dec, "ProcessInput(): successful" );
\r
691 else if( p_block && !p_block->i_buffer )
\r
693 block_Release( p_block );
\r
697 /* Get output from the DMO */
\r
698 block_out.p_buffer = p_sys->p_buffer;;
\r
699 block_out.i_buffer = 0;
\r
701 p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, VLC_FALSE );
\r
702 db.rtTimestamp = 0;
\r
703 db.rtTimelength = 0;
\r
705 db.pBuffer = (IMediaBuffer *)p_out;
\r
707 i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
\r
708 DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER,
\r
709 1, &db, &i_status );
\r
711 if( i_result != S_OK )
\r
713 if( i_result != S_FALSE )
\r
714 msg_Dbg( p_dec, "ProcessOutput(): failed" );
\r
717 msg_Dbg( p_dec, "ProcessOutput(): no output" );
\r
720 p_out->vt->Release( (IUnknown *)p_out );
\r
725 msg_Dbg( p_dec, "ProcessOutput(): success" );
\r
728 i_result = p_out->vt->GetBufferAndLength( (IMediaBuffer *)p_out,
\r
729 &p_buffer_out, &i_buffer_out );
\r
730 if( i_result != S_OK )
\r
732 msg_Dbg( p_dec, "GetBufferAndLength(): failed" );
\r
733 p_out->vt->Release( (IUnknown *)p_out );
\r
737 if( !i_buffer_out )
\r
740 msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );
\r
742 p_out->vt->Release( (IUnknown *)p_out );
\r
746 if( p_dec->fmt_out.i_cat == VIDEO_ES )
\r
748 /* Get a new picture */
\r
749 picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec );
\r
750 if( !p_pic ) return NULL;
\r
752 CopyPicture( p_dec, p_pic, block_out.p_buffer );
\r
754 /* Date management */
\r
755 p_pic->date = aout_DateGet( &p_sys->end_date );
\r
756 aout_DateIncrement( &p_sys->end_date, 1 );
\r
758 p_out->vt->Release( (IUnknown *)p_out );
\r
764 aout_buffer_t *p_aout_buffer;
\r
765 int i_samples = i_buffer_out /
\r
766 ( p_dec->fmt_out.audio.i_bitspersample *
\r
767 p_dec->fmt_out.audio.i_channels / 8 );
\r
769 p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
\r
770 memcpy( p_aout_buffer->p_buffer, p_buffer_out, i_buffer_out );
\r
772 /* Date management */
\r
773 p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
\r
774 p_aout_buffer->end_date =
\r
775 aout_DateIncrement( &p_sys->end_date, i_samples );
\r
777 p_out->vt->Release( (IUnknown *)p_out );
\r
779 return p_aout_buffer;
\r
785 static void CopyPicture( decoder_t *p_dec, picture_t *p_pic, uint8_t *p_in )
\r
787 int i_plane, i_line, i_width, i_dst_stride;
\r
788 uint8_t *p_dst, *p_src = p_in;
\r
790 p_dst = p_pic->p[1].p_pixels;
\r
791 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
792 p_pic->p[2].p_pixels = p_dst;
\r
794 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
\r
796 p_dst = p_pic->p[i_plane].p_pixels;
\r
797 i_width = p_pic->p[i_plane].i_visible_pitch;
\r
798 i_dst_stride = p_pic->p[i_plane].i_pitch;
\r
800 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
\r
802 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
\r
804 p_dst += i_dst_stride;
\r
808 p_dst = p_pic->p[1].p_pixels;
\r
809 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
810 p_pic->p[2].p_pixels = p_dst;
\r