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