]> git.sesse.net Git - vlc/blob - modules/codec/quicktime.c
* vlc.ebuild: fixed the ebuild. Now i know it should work with a test2 ;)
[vlc] / modules / codec / quicktime.c
1 /*****************************************************************************
2  * quicktime.c: a quicktime decoder that uses the QT library/dll
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: quicktime.c,v 1.4 2003/05/23 00:00:48 hartman Exp $
6  *
7  * Authors: Laurent Aimar <fenrir at via.ecp.fr>
8  *          Derk-Jan Hartman <thedj at users.sf.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc/aout.h>
30 #include <vlc/vout.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36 #include "codecs.h"
37
38 #ifdef SYS_DARWIN
39 #include <QuickTime/QuickTimeComponents.h>
40 #include <QuickTime/Movies.h>
41 #include <QuickTime/ImageCodec.h>
42 #endif
43
44 /* for windows do we require Quicktime compents header? */
45
46 #ifdef LOADER
47 #include "w32dll/loader/qtx/qtxsdk/components.h"
48 #include "w32dll/loader/wine/windef.h"
49 #include "w32dll/loader/ldt_keeper.h"
50 #endif
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static int  OpenDecoder    ( vlc_object_t * );
56
57 static int  RunDecoderAudio( decoder_fifo_t * );
58 static int  RunDecoderVideo( decoder_fifo_t * );
59
60 /*****************************************************************************
61  * Module descriptor
62  *****************************************************************************/
63
64 vlc_module_begin();
65     set_description( _("QuickTime library decoder") );
66     set_capability( "decoder", 10 );
67     set_callbacks( OpenDecoder, NULL );
68
69     /* create a mutex */
70     var_Create( p_module->p_libvlc, "qt_mutex", VLC_VAR_MUTEX );
71 vlc_module_end();
72
73
74
75 #define FCC( a, b , c, d ) \
76     ((uint32_t)( ((a)<<24)|((b)<<16)|((c)<<8)|(d)))
77
78 #ifndef SYS_DARWIN
79 typedef struct OpaqueSoundConverter*    SoundConverter;
80 typedef unsigned long                   UnsignedFixed;
81 typedef uint8_t                          Byte;
82 typedef struct SoundComponentData {
83     long                            flags;
84     OSType                          format;
85     short                           numChannels;
86     short                           sampleSize;
87     UnsignedFixed                   sampleRate;
88     long                            sampleCount;
89     Byte *                          buffer;
90     long                            reserved;
91 } SoundComponentData;
92 #endif /* SYS_DARWIN */
93
94 typedef struct
95 {
96     /* Input properties */
97     decoder_fifo_t *p_fifo;
98
99     /* library */
100 #ifndef SYS_DARWIN
101 #ifdef LOADER
102     ldt_fs_t    *ldt_fs;
103 #endif /* LOADER */
104     HMODULE     qtml;
105     OSErr       (*InitializeQTML)               ( long flags );
106 #endif /* SYS_DARWIN */
107     int         (*SoundConverterOpen)           ( const SoundComponentData *, const SoundComponentData *, SoundConverter* );
108     int         (*SoundConverterClose)          ( SoundConverter );
109     int         (*SoundConverterSetInfo)        ( SoundConverter , OSType ,void * );
110     int         (*SoundConverterGetBufferSizes) ( SoundConverter, unsigned long,
111                                                   unsigned long*, unsigned long*, unsigned long* );
112     int         (*SoundConverterBeginConversion)( SoundConverter );
113     int         (*SoundConverterEndConversion)  ( SoundConverter, void *, unsigned long *, unsigned long *);
114     int         (*SoundConverterConvertBuffer)  ( SoundConverter, const void *, unsigned long, void *,
115                                                   unsigned long *,unsigned long * );
116     SoundConverter      myConverter;
117     SoundComponentData  InputFormatInfo, OutputFormatInfo;
118
119     long            FramesToGet;
120     unsigned int    InFrameSize;
121     unsigned int    OutFrameSize;
122
123     /* Output properties */
124     aout_instance_t *   p_aout;       /* opaque */
125     aout_input_t *      p_aout_input; /* opaque */
126     audio_sample_format_t output_format;
127
128     audio_date_t        date;
129     mtime_t             pts;
130
131     /* buffer */
132     unsigned int        i_buffer;
133     unsigned int        i_buffer_size;
134     uint8_t             *p_buffer;
135
136     uint8_t             buffer_out[1000000];    /* FIXME */
137 } adec_thread_t;
138
139 typedef struct
140 {
141     /* Input properties */
142     decoder_fifo_t *p_fifo;
143
144     /* library */
145 #ifndef SYS_DARWIN
146 #ifdef LOADER
147     ldt_fs_t          *ldt_fs;
148 #endif /* LOADER */
149     HMODULE           qtml;
150     OSErr             (*InitializeQTML)         ( long flags );
151 #endif /* SYS_DARWIN */
152     Component         (*FindNextComponent)      ( Component prev, ComponentDescription* desc );
153     ComponentInstance (*OpenComponent)          ( Component c );
154     ComponentResult   (*ImageCodecInitialize)   ( ComponentInstance ci, ImageSubCodecDecompressCapabilities * cap);
155     ComponentResult   (*ImageCodecGetCodecInfo) ( ComponentInstance ci,
156                                                     CodecInfo *info );
157     ComponentResult   (*ImageCodecPreDecompress)( ComponentInstance ci,
158                                                     CodecDecompressParams * params );
159     ComponentResult   (*ImageCodecBandDecompress)( ComponentInstance ci,
160                                                     CodecDecompressParams * params );
161     PixMapHandle      (*GetGWorldPixMap)        ( GWorldPtr offscreenGWorld );
162     OSErr             (*QTNewGWorldFromPtr)     ( GWorldPtr *gw,
163                                                     OSType pixelFormat,
164                                                     const Rect *boundsRect,
165                                                     CTabHandle cTable,
166                                                     /*GDHandle*/ void *aGDevice, /*unused*/
167                                                     GWorldFlags flags,
168                                                     void *baseAddr,
169                                                     long rowBytes );
170     OSErr             (*NewHandleClear)         ( Size byteCount );
171
172     ComponentInstance       ci;
173     Rect                    OutBufferRect;   /* the dimensions of our GWorld */
174     GWorldPtr               OutBufferGWorld; /* a GWorld is some kind of
175                                                 description for a drawing
176                                                 environment */
177     ImageDescriptionHandle  framedescHandle;
178
179     CodecDecompressParams   decpar;          /* for ImageCodecPreDecompress() */
180     CodecCapabilities       codeccap;        /* for decpar */
181
182
183     /* Output properties */
184     vout_thread_t *     p_vout;
185     uint8_t *           plane;
186     mtime_t             pts;
187
188     /* buffer */
189     unsigned int        i_buffer;
190     uint8_t             *p_buffer;
191
192 } vdec_thread_t;
193
194 static int pi_channels_maps[6] =
195 {
196     0,
197     AOUT_CHAN_CENTER,
198     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
199     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
200     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
201     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
202      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
203 };
204
205
206 static uint16_t GetWBE( uint8_t *p_buff )
207 {
208     return( (p_buff[0]<<8) + p_buff[1] );
209 }
210
211 static uint32_t GetDWBE( uint8_t *p_buff )
212 {
213     return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
214             ( p_buff[2] <<8 ) + p_buff[3] );
215 }
216
217
218 static int GetPESData( uint8_t *p_buf, int i_max, pes_packet_t *p_pes )
219 {
220     int i_copy;
221     int i_count;
222
223     data_packet_t   *p_data;
224
225     i_count = 0;
226     p_data = p_pes->p_first;
227     while( p_data != NULL && i_count < i_max )
228     {
229
230         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
231                         i_max - i_count );
232
233         if( i_copy > 0 )
234         {
235             memcpy( p_buf,
236                     p_data->p_payload_start,
237                     i_copy );
238         }
239
240         p_data = p_data->p_next;
241         i_count += i_copy;
242         p_buf   += i_copy;
243     }
244
245     if( i_count < i_max )
246     {
247         memset( p_buf, 0, i_max - i_count );
248     }
249     return( i_count );
250 }
251
252 /*****************************************************************************
253  * OpenDecoder: probe the decoder and return score
254  *****************************************************************************
255  * Tries to launch a decoder and return score so that the interface is able
256  * to choose.
257  *****************************************************************************/
258 static int OpenDecoder( vlc_object_t *p_this )
259 {
260     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
261
262     switch( p_fifo->i_fourcc )
263     {
264         case VLC_FOURCC('S','V','Q','3'): /* Sorenson v3 */
265         case VLC_FOURCC('S','V','Q','1'): /* Sorenson v1 */
266         case VLC_FOURCC('Z','y','G','o'):
267         case VLC_FOURCC('V','P','3','1'):
268         case VLC_FOURCC('3','I','V','1'):
269         case VLC_FOURCC('r','l','e',' '): /* QuickTime animation (RLE) */
270         case VLC_FOURCC('r','p','z','a'): /* QuickTime Apple Video */
271         case VLC_FOURCC('a','z','p','r'): /* QuickTime animation (RLE) */
272             p_fifo->pf_run = RunDecoderVideo;
273             return VLC_SUCCESS;
274
275         case VLC_FOURCC('Q','D','M','C'): /* QDesign */
276         case VLC_FOURCC('Q','D','M','2'): /* QDesign* 2 */
277         case VLC_FOURCC('Q','c','l','p'): /* Qualcomm Purevoice Codec */
278         case VLC_FOURCC('Q','C','L','P'): /* Qualcomm Purevoice Codec */
279         case VLC_FOURCC('M','A','C','3'): /* MACE3 audio decoder */
280         case VLC_FOURCC('M','A','C','6'): /* MACE6 audio decoder */
281         case VLC_FOURCC('d','v','c','a'): /* DV Audio */
282         case VLC_FOURCC('s','o','w','t'): /* 16-bit Little Endian */
283         case VLC_FOURCC('t','w','o','s'): /* 16-bit Big Endian */
284         case VLC_FOURCC('a','l','a','w'): /* ALaw 2:1 */
285         case VLC_FOURCC('u','l','a','w'): /* mu-Law 2:1 */
286         case VLC_FOURCC('r','a','w',' '): /* 8-bit offset binaries */
287         case VLC_FOURCC('f','l','3','2'): /* 32-bit Floating Point */
288         case VLC_FOURCC('f','l','6','4'): /* 64-bit Floating Point */
289         case VLC_FOURCC('i','n','2','4'): /* 24-bit Interger */
290         case VLC_FOURCC('i','n','3','2'): /* 32-bit Integer */
291         case 0x31:                              /* MS GSM */
292         case 0x32:                              /* MSN Audio */
293         case 0x0011:                            /* DVI IMA */
294         case 0x6D730002:                        /* Microsoft ADPCM-ACM */
295         case 0x6D730011:                        /* DVI Intel IMAADPCM-ACM */
296
297             p_fifo->pf_run = RunDecoderAudio;
298             return VLC_SUCCESS;
299         default:
300             return VLC_EGENERIC;
301     }
302 }
303
304 #ifdef LOADER
305 HMODULE   WINAPI LoadLibraryA(LPCSTR);
306 FARPROC   WINAPI GetProcAddress(HMODULE,LPCSTR);
307 int       WINAPI FreeLibrary(HMODULE);
308 #endif
309
310 /****************************************************************************
311  ****************************************************************************
312  **
313  **     audio part
314  **
315  **************************************************************************** 
316  ****************************************************************************/
317
318 static int  InitThreadAudio     ( adec_thread_t * );
319 static void DecodeThreadAudio   ( adec_thread_t * );
320 static void EndThreadAudio      ( adec_thread_t * );
321
322 static int RunDecoderAudio( decoder_fifo_t *p_fifo )
323 {
324     adec_thread_t *p_dec;
325     vlc_bool_t    b_error;
326
327     p_dec = malloc( sizeof( adec_thread_t ) );
328     if( !p_dec )
329     {
330         msg_Err( p_fifo, "out of memory" );
331         DecoderError( p_fifo );
332         return VLC_EGENERIC;
333     }
334     p_dec->p_fifo = p_fifo;
335
336     if( InitThreadAudio( p_dec ) != 0 )
337     {
338         DecoderError( p_fifo );
339         return VLC_EGENERIC;
340     }
341
342     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
343     {
344         DecodeThreadAudio( p_dec );
345     }
346
347
348     if( ( b_error = p_dec->p_fifo->b_error ) )
349     {
350         DecoderError( p_dec->p_fifo );
351     }
352
353     EndThreadAudio( p_dec );
354     if( b_error )
355     {
356         return VLC_EGENERIC;
357     }
358
359     return VLC_SUCCESS;
360 }
361
362 static int InitThreadAudio( adec_thread_t *p_dec )
363 {
364     vlc_value_t     lockval;
365     int             i_error;
366     char            fcc[4];
367     unsigned long   WantedBufferSize;
368     unsigned long   InputBufferSize = 0;
369     unsigned long   OutputBufferSize = 0;
370
371     WAVEFORMATEX    *p_wf;
372
373     if( !( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) )
374     {
375         msg_Err( p_dec->p_fifo, "missing WAVEFORMATEX");
376         return VLC_EGENERIC;
377     }
378     memcpy( fcc, &p_dec->p_fifo->i_fourcc, 4 );
379
380     /* get lock, avoid segfault */
381     var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
382     vlc_mutex_lock( lockval.p_address );
383 #ifdef SYS_DARWIN
384     EnterMovies();
385 #else
386 #ifdef LOADER
387     p_dec->ldt_fs = Setup_LDT_Keeper();
388 #endif /* LOADER */
389     msg_Dbg( p_dec->p_fifo, "trying to load `qtmlClient.dll'" );
390     if( !( p_dec->qtml = LoadLibraryA("qtmlClient.dll") ) )
391     {
392         msg_Err( p_dec->p_fifo, "cannot load qtmlClient.dll");
393         goto exit_error;
394     }
395
396     msg_Dbg( p_dec->p_fifo, "qtmlClient.dll loaded" );
397
398     /* (void*) to shut up gcc */
399     p_dec->InitializeQTML           = (void*)InitializeQTML;
400 #endif /* SYS_DARWIN */
401     p_dec->SoundConverterOpen       = (void*)SoundConverterOpen;
402     p_dec->SoundConverterClose      = (void*)SoundConverterClose;
403     p_dec->SoundConverterSetInfo    = (void*)SoundConverterSetInfo;
404     p_dec->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes;
405     p_dec->SoundConverterConvertBuffer  = (void*)SoundConverterConvertBuffer;
406     p_dec->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion;
407     p_dec->SoundConverterEndConversion  = (void*)SoundConverterEndConversion;
408
409 #ifndef SYS_DARWIN
410     if( !p_dec->InitializeQTML ||
411         !p_dec->SoundConverterOpen || !p_dec->SoundConverterClose ||
412         !p_dec->SoundConverterSetInfo || !p_dec->SoundConverterGetBufferSizes ||
413         !p_dec->SoundConverterConvertBuffer ||
414         !p_dec->SoundConverterBeginConversion || !p_dec->SoundConverterEndConversion )
415     {
416         msg_Err( p_dec->p_fifo, "error getting qtmlClient.dll symbols");
417         goto exit_error;
418     }
419
420     if( ( i_error = p_dec->InitializeQTML( 6 + 16 ) ) )
421     {
422         msg_Dbg( p_dec->p_fifo, "error while InitializeQTML = %d", i_error );
423         goto exit_error;
424     }
425 #endif
426
427     /* input format settings */
428     p_dec->InputFormatInfo.flags       = 0;
429     p_dec->InputFormatInfo.sampleCount = 0;
430     p_dec->InputFormatInfo.buffer      = NULL;
431     p_dec->InputFormatInfo.reserved    = 0;
432     p_dec->InputFormatInfo.numChannels = p_wf->nChannels;
433     p_dec->InputFormatInfo.sampleSize  = p_wf->wBitsPerSample;
434     p_dec->InputFormatInfo.sampleRate  = p_wf->nSamplesPerSec;
435     p_dec->InputFormatInfo.format      = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
436
437     /* output format settings */
438     p_dec->OutputFormatInfo.flags       = 0;
439     p_dec->OutputFormatInfo.sampleCount = 0;
440     p_dec->OutputFormatInfo.buffer      = NULL;
441     p_dec->OutputFormatInfo.reserved    = 0;
442     p_dec->OutputFormatInfo.numChannels = p_wf->nChannels;
443     p_dec->OutputFormatInfo.sampleSize  = 16;
444     p_dec->OutputFormatInfo.sampleRate  = p_wf->nSamplesPerSec;
445     p_dec->OutputFormatInfo.format      = FCC( 'N', 'O', 'N', 'E' );
446
447 #ifdef SYS_DARWIN
448 /* on OS X QT is not threadsafe */
449     vlc_mutex_lock( &p_dec->p_fifo->p_vlc->quicktime_lock );
450 #endif
451
452     i_error = p_dec->SoundConverterOpen( &p_dec->InputFormatInfo,
453                                          &p_dec->OutputFormatInfo,
454                                          &p_dec->myConverter );
455     if( i_error )
456     {
457         msg_Dbg( p_dec->p_fifo, "error while SoundConverterOpen = %d", i_error );
458         goto exit_error;
459     }
460
461     if( p_wf->cbSize > 36 + 8 )
462     {
463         i_error = p_dec->SoundConverterSetInfo( p_dec->myConverter,
464                                                 FCC( 'w', 'a', 'v', 'e' ),
465                                                 ((uint8_t*)&p_wf[1]) + 36 + 8 );
466         msg_Dbg( p_dec->p_fifo, "error while SoundConverterSetInfo = %d", i_error );
467     }
468
469     WantedBufferSize   = p_dec->OutputFormatInfo.numChannels * p_dec->OutputFormatInfo.sampleRate * 2;
470     p_dec->FramesToGet = 0;
471     i_error = p_dec->SoundConverterGetBufferSizes( p_dec->myConverter,
472                                                    WantedBufferSize, &p_dec->FramesToGet,
473                                                    &InputBufferSize, &OutputBufferSize );
474
475     msg_Dbg( p_dec->p_fifo, "WantedBufferSize=%li InputBufferSize=%li OutputBufferSize=%li FramesToGet=%li",
476              WantedBufferSize, InputBufferSize, OutputBufferSize, p_dec->FramesToGet );
477
478     p_dec->InFrameSize  = (InputBufferSize + p_dec->FramesToGet - 1 ) / p_dec->FramesToGet;
479     p_dec->OutFrameSize = OutputBufferSize / p_dec->FramesToGet;
480
481     msg_Dbg( p_dec->p_fifo, "frame size %d -> %d", p_dec->InFrameSize, p_dec->OutFrameSize );
482
483     i_error = p_dec->SoundConverterBeginConversion( p_dec->myConverter );
484     if( i_error )
485     {
486         msg_Err( p_dec->p_fifo, "error while SoundConverterBeginConversion = %d", i_error );
487         goto exit_error;
488     }
489
490 #ifdef SYS_DARWIN
491     vlc_mutex_unlock( &p_dec->p_fifo->p_vlc->quicktime_lock );
492 #endif
493
494     p_dec->output_format.i_format   = AOUT_FMT_S16_NE;
495     p_dec->output_format.i_rate     = p_wf->nSamplesPerSec;
496     p_dec->output_format.i_physical_channels =
497         p_dec->output_format.i_original_channels =
498             pi_channels_maps[p_wf->nChannels];
499     aout_DateInit( &p_dec->date, p_dec->output_format.i_rate );
500     p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
501                                        &p_dec->p_aout,
502                                        &p_dec->output_format );
503     if( !p_dec->p_aout_input )
504     {
505         msg_Err( p_dec->p_fifo, "cannot create aout" );
506         goto exit_error;
507     }
508
509     p_dec->i_buffer      = 0;
510     p_dec->i_buffer_size = 100*1000;
511     p_dec->p_buffer      = malloc( p_dec->i_buffer_size );
512
513     p_dec->pts = -1;
514
515     vlc_mutex_unlock( lockval.p_address );
516     return VLC_SUCCESS;
517
518 exit_error:
519 #ifdef LOADER
520     Restore_LDT_Keeper( p_dec->ldt_fs );
521 #endif
522     vlc_mutex_unlock( lockval.p_address );
523     return VLC_EGENERIC;
524
525 }
526 static void DecodeThreadAudio   ( adec_thread_t *p_dec )
527 {
528     pes_packet_t    *p_pes;
529     vlc_value_t     lockval;
530     int             i_error;
531
532     var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
533
534     input_ExtractPES( p_dec->p_fifo, &p_pes );
535     if( !p_pes )
536     {
537         msg_Err( p_dec->p_fifo, "cannot get PES" );
538         p_dec->p_fifo->b_error = 1;
539         return;
540     }
541     /*if( p_dec->pts <= 0 )*/
542     {
543         p_dec->pts = p_pes->i_pts;
544     }
545
546     if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() )
547     {
548
549         if( p_dec->i_buffer_size < p_dec->i_buffer + p_pes->i_pes_size )
550         {
551             p_dec->i_buffer_size = p_dec->i_buffer + p_pes->i_pes_size + 1024;
552             p_dec->p_buffer = realloc( p_dec->p_buffer,
553                                        p_dec->i_buffer_size );
554         }
555
556         GetPESData( &p_dec->p_buffer[p_dec->i_buffer],
557                     p_dec->i_buffer_size - p_dec->i_buffer, p_pes );
558         p_dec->i_buffer += p_pes->i_pes_size;
559
560         if( p_dec->i_buffer > p_dec->InFrameSize )
561         {
562             int i_frames = p_dec->i_buffer / p_dec->InFrameSize;
563             long i_out_frames, i_out_bytes;
564             /* enough data */
565
566             vlc_mutex_lock( lockval.p_address );
567             i_error = p_dec->SoundConverterConvertBuffer( p_dec->myConverter,
568                                                           p_dec->p_buffer,
569                                                           i_frames,
570                                                           p_dec->buffer_out,
571                                                           &i_out_frames, &i_out_bytes );
572             vlc_mutex_unlock( lockval.p_address );
573
574             /*msg_Dbg( p_dec->p_fifo, "decoded %d frames -> %ld frames (error=%d)",
575                      i_frames, i_out_frames, i_error );
576
577             msg_Dbg( p_dec->p_fifo, "decoded %ld frames = %ld bytes", i_out_frames, i_out_bytes );*/
578             p_dec->i_buffer -= i_frames * p_dec->InFrameSize;
579             if( p_dec->i_buffer > 0 )
580             {
581                 memmove( &p_dec->p_buffer[0],
582                          &p_dec->p_buffer[i_frames * p_dec->InFrameSize],
583                          p_dec->i_buffer );
584             }
585
586             if( i_out_frames > 0 )
587             {
588                 aout_buffer_t   *p_aout_buffer;
589                 uint8_t         *p_buff = p_dec->buffer_out;
590
591                 /*msg_Dbg( p_dec->p_fifo, "pts=%lld date=%lld dateget=%lld",
592                          p_dec->pts, mdate(), aout_DateGet( &p_dec->date ) );*/
593
594                 if( p_dec->pts != 0 && p_dec->pts != aout_DateGet( &p_dec->date ) )
595                 {
596                     aout_DateSet( &p_dec->date, p_dec->pts );
597                 }
598                 else if( !aout_DateGet( &p_dec->date ) )
599                 {
600                     input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
601                     return;
602                 }
603
604                 while( i_out_frames > 0 )
605                 {
606                     int i_frames;
607
608                     i_frames = __MIN( i_out_frames, 1000 );
609                     p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
610                                                        p_dec->p_aout_input,
611                                                        i_frames );
612                     if( !p_aout_buffer )
613                     {
614                         msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
615                         p_dec->p_fifo->b_error = 1;
616                         return;
617                     }
618                     p_aout_buffer->start_date = aout_DateGet( &p_dec->date );
619                     p_aout_buffer->end_date = aout_DateIncrement( &p_dec->date,
620                                                                   i_frames );
621
622                     memcpy( p_aout_buffer->p_buffer,
623                             p_buff,
624                             p_aout_buffer->i_nb_bytes );
625
626                     /*msg_Dbg( p_dec->p_fifo, "==> start=%lld end=%lld date=%lld",
627                              p_aout_buffer->start_date, p_aout_buffer->end_date, mdate() );*/
628                     aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
629                     /*msg_Dbg( p_dec->p_fifo, "s1=%d s2=%d", i_framesperchannels, p_aout_buffer->i_nb_samples );
630
631                     msg_Dbg( p_dec->p_fifo, "i_nb_bytes=%d i_nb_samples*4=%d", p_aout_buffer->i_nb_bytes, p_aout_buffer->i_nb_samples * 4 );*/
632                     p_buff += i_frames * 4;
633                     i_out_frames -= i_frames;
634                 }
635
636                 p_dec->pts = -1;
637             }
638         }
639     }
640
641     input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
642 }
643
644 static void EndThreadAudio( adec_thread_t *p_dec )
645 {
646     vlc_value_t             lockval;
647     int i_error;
648     unsigned long ConvertedFrames=0;
649     unsigned long ConvertedBytes=0;
650
651     /* get lock, avoid segfault */
652     var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
653     vlc_mutex_lock( lockval.p_address );
654
655     i_error = p_dec->SoundConverterEndConversion( p_dec->myConverter, NULL, &ConvertedFrames, &ConvertedBytes );
656     msg_Dbg( p_dec->p_fifo, "SoundConverterEndConversion => %d", i_error );
657
658     i_error = p_dec->SoundConverterClose( p_dec->myConverter );
659     msg_Dbg( p_dec->p_fifo, "SoundConverterClose => %d", i_error );
660
661 #ifndef SYS_DARWIN
662     FreeLibrary( p_dec->qtml );
663     msg_Dbg( p_dec->p_fifo, "FreeLibrary ok." ); */
664 #endif
665     vlc_mutex_unlock( lockval.p_address );
666
667 #ifdef LOADER
668     Restore_LDT_Keeper( p_dec->ldt_fs );
669     msg_Dbg( p_dec->p_fifo, "Restore_LDT_Keeper" ); */
670 #endif
671 #ifdef SYS_DARWIN
672     ExitMovies();
673 #endif
674     aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
675 }
676
677
678 /****************************************************************************
679  ****************************************************************************
680  **
681  **     video part
682  **
683  **************************************************************************** 
684  ****************************************************************************/
685
686 static int  InitThreadVideo     ( vdec_thread_t * );
687 static void DecodeThreadVideo   ( vdec_thread_t * );
688 static void EndThreadVideo      ( vdec_thread_t * );
689
690 static int  RunDecoderVideo( decoder_fifo_t *p_fifo )
691 {
692     vdec_thread_t *p_dec;
693     vlc_bool_t    b_error;
694
695     p_dec = malloc( sizeof( vdec_thread_t ) );
696     if( !p_dec )
697     {
698         msg_Err( p_fifo, "out of memory" );
699         DecoderError( p_fifo );
700         return VLC_EGENERIC;
701     }
702     p_dec->p_fifo = p_fifo;
703
704     if( InitThreadVideo( p_dec ) != 0 )
705     {
706         DecoderError( p_fifo );
707         return VLC_EGENERIC;
708     }
709
710     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
711     {
712         DecodeThreadVideo( p_dec );
713     }
714
715
716     if( ( b_error = p_dec->p_fifo->b_error ) )
717     {
718         DecoderError( p_dec->p_fifo );
719     }
720
721     EndThreadVideo( p_dec );
722     if( b_error )
723     {
724         return VLC_EGENERIC;
725     }
726
727     return VLC_SUCCESS;
728 }
729
730 /*
731  * InitThreadVideo: load and init library
732  *
733  */
734 static int InitThreadVideo( vdec_thread_t *p_dec )
735 {
736     vlc_value_t                         lockval;
737     long                                i_result;
738     ComponentDescription                desc;
739     Component                           prev;
740     ComponentResult                     cres;
741     ImageSubCodecDecompressCapabilities icap;   /* for ImageCodecInitialize() */
742     CodecInfo                           cinfo;  /* for ImageCodecGetCodecInfo() */
743     ImageDescription                    *id;
744
745     BITMAPINFOHEADER    *p_bih;
746     int                 i_vide;
747     uint8_t             *p_vide;
748     char                fcc[4];
749
750     if( !( p_bih  = (BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader ) )
751     {
752         msg_Err( p_dec->p_fifo, "missing BITMAPINFOHEADER !!" );
753         return VLC_EGENERIC;
754     }
755     i_vide = p_bih->biSize - sizeof( BITMAPINFOHEADER );
756     p_vide = (uint8_t*)&p_bih[1];
757     if( i_vide <= 0 || p_vide == NULL )
758     {
759         msg_Err( p_dec->p_fifo, "invalid BITMAPINFOHEADER !!" );
760         return VLC_EGENERIC;
761     }
762     memcpy( fcc, &p_dec->p_fifo->i_fourcc, 4 );
763     msg_Dbg( p_dec->p_fifo, "quicktime_video %4.4s %dx%d", fcc, p_bih->biWidth, p_bih->biHeight );
764
765     /* get lock, avoid segfault */
766     var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
767     vlc_mutex_lock( lockval.p_address );
768 #ifdef SYS_DARWIN
769     EnterMovies();
770 #else
771 #ifdef LOADER
772     p_dec->ldt_fs = Setup_LDT_Keeper();
773 #endif /* LOADER */
774     msg_Dbg( p_dec->p_fifo, "trying to load `qtmlClient.dll'" );
775     if( !( p_dec->qtml = LoadLibraryA("qtmlClient.dll") ) )
776     {
777         msg_Err( p_dec->p_fifo, "cannot load qtmlClient.dll");
778         goto exit_error;
779     }
780
781     msg_Dbg( p_dec->p_fifo, "qtmlClient.dll loaded" );
782
783     /* (void*) to shut up gcc */
784     p_dec->InitializeQTML           = (void*)InitializeQTML;
785 #endif /* SYS_DARWIN */
786     p_dec->FindNextComponent        = (void*)FindNextComponent;
787     p_dec->OpenComponent            = (void*)OpenComponent;
788     p_dec->ImageCodecInitialize     = (void*)ImageCodecInitialize;
789     p_dec->ImageCodecGetCodecInfo   = (void*)ImageCodecGetCodecInfo;
790     p_dec->ImageCodecPreDecompress  = (void*)ImageCodecPreDecompress;
791     p_dec->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress;
792     p_dec->GetGWorldPixMap          = (void*)GetGWorldPixMap;
793     p_dec->QTNewGWorldFromPtr       = (void*)QTNewGWorldFromPtr;
794     p_dec->NewHandleClear           = (void*)NewHandleClear;
795
796 #ifndef SYS_DARWIN
797     /* some sanity check */
798     if( !p_dec->InitializeQTML ||
799         !p_dec->FindNextComponent ||
800         !p_dec->OpenComponent ||
801         !p_dec->ImageCodecBandDecompress )
802     {
803         msg_Err( p_dec->p_fifo, "error getting qtmlClient.dll symbols");
804         goto exit_error;
805     }
806
807     if( ( i_result = p_dec->InitializeQTML( 6 + 16 ) ) )
808     {
809         msg_Dbg( p_dec->p_fifo, "error while InitializeQTML = %d", i_result );
810         goto exit_error;
811     }
812 #endif
813
814     /* init ComponentDescription */
815     memset( &desc, 0, sizeof( ComponentDescription ) );
816     desc.componentType      = FCC( 'i', 'm', 'd', 'c' );
817     desc.componentSubType   = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
818     desc.componentManufacturer = 0;
819     desc.componentFlags        = 0;
820     desc.componentFlagsMask    = 0;
821
822     if( !( prev = p_dec->FindNextComponent( NULL, &desc ) ) )
823     {
824         msg_Err( p_dec->p_fifo, "cannot find requested component" );
825         goto exit_error;
826     }
827     msg_Dbg( p_dec->p_fifo, "component id=0x%p", prev );
828
829     p_dec->ci =  p_dec->OpenComponent( prev );
830     msg_Dbg( p_dec->p_fifo, "component instance p=0x%p", p_dec->ci );
831
832     memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) );
833     cres =  p_dec->ImageCodecInitialize( p_dec->ci, &icap );
834 /*    msg_Dbg( p_dec->p_fifo, "ImageCodecInitialize->%p  size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize); */
835
836
837     memset( &cinfo, 0, sizeof( CodecInfo ) );
838     cres =  p_dec->ImageCodecGetCodecInfo( p_dec->ci,&cinfo);
839     msg_Dbg( p_dec->p_fifo, "Flags: compr: 0x%lx  decomp: 0x%lx format: 0x%lx\n",
840                 cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags);
841     msg_Dbg( p_dec->p_fifo, "quicktime_video: Codec name: %.*s\n", ((unsigned char*)&cinfo.typeName)[0],
842                   ((unsigned char*)&cinfo.typeName)+1);
843
844     /* make a yuy2 gworld */
845     p_dec->OutBufferRect.top    = 0;
846     p_dec->OutBufferRect.left   = 0;
847     p_dec->OutBufferRect.right  = p_bih->biWidth;
848     p_dec->OutBufferRect.bottom = p_bih->biHeight;
849
850
851     /* codec data FIXME use codec not SVQ3 */
852     msg_Dbg( p_dec->p_fifo, "vide = %d", i_vide );
853     id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) );
854     id->idSize          = sizeof( ImageDescription ) + ( i_vide - 70 );
855     id->cType           = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
856     id->version         = GetWBE ( p_vide +  0 );
857     id->revisionLevel   = GetWBE ( p_vide +  2 );
858     id->vendor          = GetDWBE( p_vide +  4 );
859     id->temporalQuality = GetDWBE( p_vide +  8 );
860     id->spatialQuality  = GetDWBE( p_vide + 12 );
861     id->width           = GetWBE ( p_vide + 16 );
862     id->height          = GetWBE ( p_vide + 18 );
863     id->hRes            = GetDWBE( p_vide + 20 );
864     id->vRes            = GetDWBE( p_vide + 24 );
865     id->dataSize        = GetDWBE( p_vide + 28 );
866     id->frameCount      = GetWBE ( p_vide + 32 );
867     memcpy( &id->name, p_vide + 34, 32 );
868     id->depth           = GetWBE ( p_vide + 66 );
869     id->clutID          = GetWBE ( p_vide + 68 );
870     if( i_vide > 70 )
871     {
872         memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 );
873     }
874
875     msg_Dbg( p_dec->p_fifo, "idSize=%ld ver=%d rev=%d vendor=%ld tempQ=%d spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d frameCount=%d clutID=%d",
876              id->idSize, id->version, id->revisionLevel, id->vendor,
877              (int)id->temporalQuality, (int)id->spatialQuality,
878              id->width, id->height,
879              (int)id->hRes, (int)id->vRes,
880              (int)id->dataSize,
881              id->frameCount,
882              id->clutID );
883
884     p_dec->framedescHandle = (ImageDescriptionHandle) p_dec->NewHandleClear (id->idSize);
885     memcpy (*p_dec->framedescHandle, id, id->idSize);
886
887     p_dec->plane = malloc( p_bih->biWidth * p_bih->biHeight * 3 );
888
889     i_result =  p_dec->QTNewGWorldFromPtr(&p_dec->OutBufferGWorld,
890                                          kYUVSPixelFormat, /*pixel format of new GWorld==YUY2 */
891                                          &p_dec->OutBufferRect,   /*we should benchmark if yvu9 is faster for svq3, too */
892                                          0,
893                                          0,
894                                          0,
895                                          p_dec->plane,
896                                          p_bih->biWidth * 2 );
897
898     msg_Dbg( p_dec->p_fifo, "NewGWorldFromPtr returned:%ld\n",65536-(i_result&0xffff));
899
900     memset( &p_dec->decpar, 0, sizeof( CodecDecompressParams ) );
901     p_dec->decpar.imageDescription = p_dec->framedescHandle;
902     p_dec->decpar.startLine        = 0;
903     p_dec->decpar.stopLine         = (**p_dec->framedescHandle).height;
904     p_dec->decpar.frameNumber      = 1;
905     p_dec->decpar.matrixFlags      = 0;
906     p_dec->decpar.matrixType       = 0;
907     p_dec->decpar.matrix           = 0;
908     p_dec->decpar.capabilities     = &p_dec->codeccap;
909     p_dec->decpar.accuracy         = codecNormalQuality;
910     p_dec->decpar.srcRect          = p_dec->OutBufferRect;
911     p_dec->decpar.transferMode     = srcCopy;
912     p_dec->decpar.dstPixMap        = ** p_dec->GetGWorldPixMap (p_dec->OutBufferGWorld);/*destPixmap;  */
913
914     msg_Dbg( p_dec->p_fifo, "will call: ImageCodecPreDecompress");
915     cres =  p_dec->ImageCodecPreDecompress (p_dec->ci, &p_dec->decpar);
916     msg_Dbg( p_dec->p_fifo, "quicktime_video: ImageCodecPreDecompress cres=0x%X\n", (int)cres);
917
918     p_dec->p_vout = vout_Request( p_dec->p_fifo, NULL,
919                                   p_bih->biWidth, p_bih->biHeight,
920                                   VLC_FOURCC( 'Y', 'U', 'Y', '2' ),
921                                   VOUT_ASPECT_FACTOR * p_bih->biWidth / p_bih->biHeight );
922
923     if( !p_dec->p_vout )
924     {
925         msg_Err( p_dec->p_fifo, "cannot get a vout" );
926         goto exit_error;
927     }
928
929     p_dec->i_buffer = 1000*1000;
930     p_dec->p_buffer = malloc( p_dec->i_buffer );
931
932     vlc_mutex_unlock( lockval.p_address );
933     return VLC_SUCCESS;
934
935 exit_error:
936 #ifdef LOADER
937     Restore_LDT_Keeper( p_dec->ldt_fs );
938 #endif
939     vlc_mutex_unlock( lockval.p_address );
940     return VLC_EGENERIC;
941
942 }
943
944 static void DecodeThreadVideo   ( vdec_thread_t *p_dec )
945 {
946     BITMAPINFOHEADER    *p_bih = (BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader;
947     pes_packet_t    *p_pes;
948     vlc_value_t     lockval;
949     picture_t       *p_pic;
950     ComponentResult     cres;
951
952     var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
953
954     input_ExtractPES( p_dec->p_fifo, &p_pes );
955     if( !p_pes )
956     {
957         msg_Err( p_dec->p_fifo, "cannot get PES" );
958         p_dec->p_fifo->b_error = 1;
959         return;
960     }
961
962     if( p_pes->i_pes_size > p_dec->i_buffer )
963     {
964         p_dec->i_buffer = 3 * p_pes->i_pes_size / 2;
965         free( p_dec->p_buffer );
966         p_dec->p_buffer = malloc( p_dec->i_buffer );
967     }
968
969     if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() )
970     {
971         GetPESData( p_dec->p_buffer, p_dec->i_buffer, p_pes );
972
973         while( !(p_pic = vout_CreatePicture( p_dec->p_vout, 0, 0, 0 ) ) )
974         {
975             if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
976             {
977                 break;
978             }
979             msleep( VOUT_OUTMEM_SLEEP );
980         }
981
982         p_dec->decpar.data                  = p_dec->p_buffer;
983         p_dec->decpar.bufferSize            = p_pes->i_pes_size;
984         (**p_dec->framedescHandle).dataSize = p_pes->i_pes_size;
985
986         vlc_mutex_lock( lockval.p_address );
987         cres = p_dec->ImageCodecBandDecompress( p_dec->ci, &p_dec->decpar );
988         vlc_mutex_unlock( lockval.p_address );
989
990         ++p_dec->decpar.frameNumber;
991
992         if( cres &0xFFFF )
993         {
994             msg_Dbg( p_dec->p_fifo,
995                      "quicktime_video: ImageCodecBandDecompress cres=0x%X (-0x%X) %d :(\n",
996                      (int)cres,(int)-cres, (int)cres );
997         }
998
999         memcpy( p_pic->p[0].p_pixels,
1000                 p_dec->plane,
1001                 p_bih->biWidth * p_bih->biHeight * 2 );
1002
1003         vout_DatePicture( p_dec->p_vout, p_pic, p_pes->i_pts );
1004         vout_DisplayPicture( p_dec->p_vout, p_pic );
1005     }
1006
1007     input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
1008 }
1009
1010 static void EndThreadVideo      ( vdec_thread_t *p_dec )
1011 {
1012     msg_Dbg( p_dec->p_fifo, "QuickTime library video decoder closing" );
1013     free( p_dec->plane );
1014     vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 );
1015
1016 #ifndef SYS_DARWIN
1017     FreeLibrary( p_dec->qtml );
1018     msg_Dbg( p_dec->p_fifo, "FreeLibrary ok." );
1019 #endif
1020
1021 #ifdef LOADER
1022     Restore_LDT_Keeper( p_dec->ldt_fs );
1023     msg_Dbg( p_dec->p_fifo, "Restore_LDT_Keeper" );
1024 #endif
1025 #ifdef SYS_DARWIN
1026     ExitMovies();
1027 #endif
1028 }