skins2: reuse graphics from generic bitmap cache (radialslider)
[vlc.git] / modules / codec / quicktime.c
blobd4834d7208ff4a8b0b5470f98a1a9dbd51ee516d
1 /*****************************************************************************
2 * quicktime.c: a quicktime decoder that uses the QT library/dll
3 *****************************************************************************
4 * Copyright (C) 2003, 2008 - 2009 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Laurent Aimar <fenrir at via.ecp.fr>
8 * Derk-Jan Hartman <hartman at videolan.org>>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
37 #if !defined (__APPLE__) && !defined(WIN32)
38 # define LOADER 1
39 #endif
41 #ifdef __APPLE__
42 #include <QuickTime/QuickTimeComponents.h>
43 #include <QuickTime/Movies.h>
44 #include <QuickTime/ImageCodec.h>
45 #endif
47 /* for windows do we require Quicktime compents header? */
48 #ifdef LOADER
49 #include "qtx/qtxsdk/components.h"
50 #include "wine/windef.h"
51 #include "ldt_keeper.h"
53 HMODULE WINAPI LoadLibraryA(LPCSTR);
54 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
55 int WINAPI FreeLibrary(HMODULE);
57 #endif
59 /*****************************************************************************
60 * Module descriptor
61 *****************************************************************************/
62 static int Open ( vlc_object_t * );
63 static void Close( vlc_object_t * );
65 vlc_module_begin ()
66 set_description( N_("QuickTime library decoder") )
67 set_capability( "decoder", 0 )
68 set_category( CAT_INPUT )
69 set_subcategory( SUBCAT_INPUT_VCODEC )
70 set_callbacks( Open, Close )
72 vlc_module_end ()
75 /*****************************************************************************
76 * Local prototypes
77 *****************************************************************************/
78 static int OpenAudio( decoder_t * );
79 static int OpenVideo( decoder_t * );
81 static block_t *DecodeAudio( decoder_t *, block_t ** );
82 #ifndef WIN32
83 static picture_t *DecodeVideo( decoder_t *, block_t ** );
84 #endif
86 #define FCC( a, b , c, d ) \
87 ((uint32_t)( ((a)<<24)|((b)<<16)|((c)<<8)|(d)))
89 #ifndef __APPLE__
90 typedef struct OpaqueSoundConverter* SoundConverter;
91 #ifndef LOADER
92 typedef long OSType;
93 typedef int OSErr;
94 #endif
95 typedef unsigned long UnsignedFixed;
96 typedef uint8_t Byte;
98 typedef struct SoundComponentData {
99 long flags;
100 OSType format;
101 short numChannels;
102 short sampleSize;
103 UnsignedFixed sampleRate;
104 long sampleCount;
105 Byte * buffer;
106 long reserved;
107 } SoundComponentData;
109 #endif /* __APPLE__ */
111 struct decoder_sys_t
113 /* library */
114 #ifndef __APPLE__
115 #ifdef LOADER
116 ldt_fs_t *ldt_fs;
117 #endif /* LOADER */
119 HMODULE qtml;
120 HINSTANCE qts;
121 OSErr (*InitializeQTML) ( long flags );
122 OSErr (*TerminateQTML) ( void );
123 #endif /* __APPLE__ */
125 /* Audio */
126 int (*SoundConverterOpen) ( const SoundComponentData *,
127 const SoundComponentData *,
128 SoundConverter* );
129 int (*SoundConverterClose) ( SoundConverter );
130 int (*SoundConverterSetInfo) ( SoundConverter , OSType, void * );
131 int (*SoundConverterGetBufferSizes) ( SoundConverter, unsigned long,
132 unsigned long*, unsigned long*,
133 unsigned long* );
134 int (*SoundConverterBeginConversion)( SoundConverter );
135 int (*SoundConverterEndConversion) ( SoundConverter, void *,
136 unsigned long *, unsigned long *);
137 int (*SoundConverterConvertBuffer) ( SoundConverter, const void *,
138 unsigned long, void *,
139 unsigned long *, unsigned long * );
140 SoundConverter myConverter;
141 SoundComponentData InputFormatInfo, OutputFormatInfo;
143 unsigned long FramesToGet;
144 unsigned int InFrameSize;
145 unsigned int OutFrameSize;
147 #ifndef WIN32
148 /* Video */
149 Component (*FindNextComponent)
150 ( Component prev, ComponentDescription* desc );
152 ComponentInstance (*OpenComponent)
153 ( Component c );
155 ComponentResult (*ImageCodecInitialize)
156 ( ComponentInstance ci, ImageSubCodecDecompressCapabilities * cap);
158 ComponentResult (*ImageCodecGetCodecInfo)
159 ( ComponentInstance ci, CodecInfo *info );
161 ComponentResult (*ImageCodecPreDecompress)
162 ( ComponentInstance ci, CodecDecompressParams * params );
164 ComponentResult (*ImageCodecBandDecompress)
165 ( ComponentInstance ci, CodecDecompressParams * params );
167 PixMapHandle (*GetGWorldPixMap)
168 ( GWorldPtr offscreenGWorld );
170 OSErr (*QTNewGWorldFromPtr)
171 ( GWorldPtr *gw, OSType pixelFormat, const Rect *boundsRect,
172 CTabHandle cTable, /*GDHandle*/ void *aGDevice, /*unused*/
173 GWorldFlags flags, void *baseAddr, long rowBytes );
175 OSErr (*NewHandleClear)( Size byteCount );
177 ComponentInstance ci;
178 Rect OutBufferRect; /* the dimensions of our GWorld */
179 GWorldPtr OutBufferGWorld; /* a GWorld is some kind of
180 description for a drawing
181 environment */
182 ImageDescriptionHandle framedescHandle;
184 CodecDecompressParams decpar; /* for ImageCodecPreDecompress()*/
185 CodecCapabilities codeccap; /* for decpar */
186 #endif
188 /* Output properties */
189 uint8_t * plane;
190 mtime_t pts;
191 date_t date;
193 int i_late; /* video */
195 /* buffer */
196 unsigned int i_buffer;
197 unsigned int i_buffer_size;
198 uint8_t *p_buffer;
200 /* Audio only */
201 uint8_t out_buffer[1000000]; /* FIXME */
202 int i_out_frames;
203 int i_out;
206 static const int pi_channels_maps[6] =
209 AOUT_CHAN_CENTER,
210 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
211 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
212 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
213 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
214 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
217 static int QTAudioInit( decoder_t * );
218 #ifndef WIN32
219 static int QTVideoInit( decoder_t * );
220 #endif
222 /*****************************************************************************
223 * Open: probe the decoder and return score
224 *****************************************************************************
225 * Tries to launch a decoder and return score so that the interface is able
226 * to choose.
227 *****************************************************************************/
228 static int Open( vlc_object_t *p_this )
230 decoder_t *p_dec = (decoder_t*)p_this;
232 #ifdef __APPLE__
233 OSErr err;
234 SInt32 qtVersion, macosversion;
236 err = Gestalt(gestaltQuickTimeVersion, &qtVersion);
237 err = Gestalt(gestaltSystemVersion, &macosversion);
238 #ifndef NDEBUG
239 msg_Dbg( p_this, "Mac OS version is %#lx", macosversion );
240 msg_Dbg( p_this, "Quicktime version is %#lx", qtVersion );
241 #endif
243 /* bail out. This plugin is soo Carbon, that it can't be used on 10.5 at all */
244 msg_Info( p_dec, "Your Mac OS version is to new to use this plugin for anything." );
245 return VLC_EGENERIC;
246 #endif
248 switch( p_dec->fmt_in.i_codec )
250 case VLC_CODEC_H264:
251 case VLC_CODEC_CINEPAK:
252 case VLC_FOURCC('I','V','4','1'): /* Indeo Video IV */
253 case VLC_FOURCC('i','v','4','1'): /* dto. */
254 #ifdef __APPLE__
255 case VLC_FOURCC('p','x','l','t'): /* Pixlet */
256 #endif
257 case VLC_CODEC_DV:
258 case VLC_CODEC_SVQ3: /* Sorenson v3 */
259 /* case VLC_CODEC_SVQ1: Sorenson v1
260 case VLC_FOURCC('Z','y','G','o'):
261 case VLC_FOURCC('V','P','3','1'):
262 case VLC_FOURCC('3','I','V','1'): */
263 case VLC_CODEC_QTRLE:
264 case VLC_CODEC_RPZA:
265 #ifdef LOADER
266 p_dec->p_sys = NULL;
267 p_dec->pf_decode_video = DecodeVideo;
268 p_dec->fmt_out.i_cat = VIDEO_ES;
269 return VLC_SUCCESS;
270 #else
271 return OpenVideo( p_dec );
272 #endif
274 #ifdef __APPLE__
275 case VLC_FOURCC('I','L','B','C'): /* iLBC */
276 if ((err != noErr) || (qtVersion < 0x07500000))
277 return VLC_EGENERIC;
278 case VLC_FOURCC('i','l','b','c'): /* iLBC */
279 if ((err != noErr) || (qtVersion < 0x07500000))
280 return VLC_EGENERIC;
281 #endif
282 case VLC_CODEC_AMR_NB: /* 3GPP AMR audio */
283 case VLC_FOURCC('s','a','m','b'): /* 3GPP AMR-WB audio */
284 case VLC_CODEC_MP4A: /* MPEG-4 audio */
285 case VLC_FOURCC('Q','D','M','C'): /* QDesign */
286 case VLC_CODEC_QDM2: /* QDesign* 2 */
287 case VLC_CODEC_QCELP: /* Qualcomm Purevoice Codec */
288 case VLC_FOURCC('Q','C','L','P'): /* Qualcomm Purevoice Codec */
289 case VLC_CODEC_MACE3: /* MACE3 audio decoder */
290 case VLC_CODEC_MACE6: /* MACE6 audio decoder */
291 case VLC_FOURCC('d','v','c','a'): /* DV Audio */
292 case VLC_FOURCC('s','o','w','t'): /* 16-bit Little Endian */
293 case VLC_FOURCC('t','w','o','s'): /* 16-bit Big Endian */
294 case VLC_CODEC_ALAW: /* ALaw 2:1 */
295 case VLC_FOURCC('u','l','a','w'): /* mu-Law 2:1 */
296 case VLC_FOURCC('r','a','w',' '): /* 8-bit offset binaries */
297 case VLC_CODEC_FL32: /* 32-bit Floating Point */
298 case VLC_CODEC_FL64: /* 64-bit Floating Point */
299 case VLC_FOURCC('i','n','2','4'): /* 24-bit Interger */
300 case VLC_FOURCC('i','n','3','2'): /* 32-bit Integer */
301 case 0x0011: /* DVI IMA */
302 case 0x6D730002: /* Microsoft ADPCM-ACM */
303 case 0x6D730011: /* DVI Intel IMAADPCM-ACM */
304 #ifdef LOADER
305 p_dec->p_sys = NULL;
306 p_dec->pf_decode_audio = DecodeAudio;
307 p_dec->fmt_out.i_cat = AUDIO_ES;
308 return VLC_SUCCESS;
309 #else
310 return OpenAudio( p_dec );
311 #endif
313 default:
314 return VLC_EGENERIC;
318 static vlc_mutex_t qt_mutex = VLC_STATIC_MUTEX;
320 /*****************************************************************************
321 * Close:
322 *****************************************************************************/
323 static void Close( vlc_object_t *p_this )
325 decoder_t *p_dec = (decoder_t*)p_this;
326 decoder_sys_t *p_sys = p_dec->p_sys;
328 /* get lock, avoid segfault */
329 vlc_mutex_lock( &qt_mutex );
331 if( p_dec->fmt_out.i_cat == AUDIO_ES )
333 int i_error;
334 unsigned long ConvertedFrames=0;
335 unsigned long ConvertedBytes=0;
337 i_error = p_sys->SoundConverterEndConversion( p_sys->myConverter, NULL,
338 &ConvertedFrames,
339 &ConvertedBytes );
340 msg_Dbg( p_dec, "SoundConverterEndConversion => %d", i_error );
342 i_error = p_sys->SoundConverterClose( p_sys->myConverter );
343 msg_Dbg( p_dec, "SoundConverterClose => %d", i_error );
345 free( p_sys->p_buffer );
347 else if( p_dec->fmt_out.i_cat == VIDEO_ES )
349 free( p_sys->plane );
352 #ifndef __APPLE__
353 FreeLibrary( p_sys->qtml );
354 FreeLibrary( p_sys->qts );
355 msg_Dbg( p_dec, "FreeLibrary ok." );
356 #else
357 ExitMovies();
358 #endif
360 #if 0
361 /* Segfault */
362 #ifdef LOADER
363 Restore_LDT_Keeper( p_sys->ldt_fs );
364 msg_Dbg( p_dec, "Restore_LDT_Keeper" );
365 #endif
366 #endif
368 vlc_mutex_unlock( &qt_mutex );
370 free( p_sys );
373 /*****************************************************************************
374 * OpenAudio:
375 *****************************************************************************/
376 static int OpenAudio( decoder_t *p_dec )
378 decoder_sys_t *p_sys;
380 int i_error;
381 char fcc[4];
382 unsigned long WantedBufferSize;
383 unsigned long InputBufferSize = 0;
384 unsigned long OutputBufferSize = 0;
386 /* get lock, avoid segfault */
387 vlc_mutex_lock( &qt_mutex );
389 p_sys = calloc( 1, sizeof( decoder_sys_t ) );
390 p_dec->p_sys = p_sys;
391 p_dec->pf_decode_audio = DecodeAudio;
393 if( p_dec->fmt_in.i_original_fourcc )
394 memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 );
395 else
396 memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
398 #ifdef __APPLE__
399 EnterMovies();
400 #endif
402 if( QTAudioInit( p_dec ) )
404 msg_Err( p_dec, "cannot initialize QT");
405 goto exit_error;
408 #ifndef __APPLE__
409 if( ( i_error = p_sys->InitializeQTML( 6 + 16 ) ) )
411 msg_Dbg( p_dec, "error on InitializeQTML = %d", i_error );
412 goto exit_error;
414 #endif
416 /* input format settings */
417 p_sys->InputFormatInfo.flags = 0;
418 p_sys->InputFormatInfo.sampleCount = 0;
419 p_sys->InputFormatInfo.buffer = NULL;
420 p_sys->InputFormatInfo.reserved = 0;
421 p_sys->InputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
422 p_sys->InputFormatInfo.sampleSize = p_dec->fmt_in.audio.i_bitspersample;
423 p_sys->InputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate;
424 p_sys->InputFormatInfo.format = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
426 /* output format settings */
427 p_sys->OutputFormatInfo.flags = 0;
428 p_sys->OutputFormatInfo.sampleCount = 0;
429 p_sys->OutputFormatInfo.buffer = NULL;
430 p_sys->OutputFormatInfo.reserved = 0;
431 p_sys->OutputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
432 p_sys->OutputFormatInfo.sampleSize = 16;
433 p_sys->OutputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate;
434 p_sys->OutputFormatInfo.format = FCC( 'N', 'O', 'N', 'E' );
437 i_error = p_sys->SoundConverterOpen( &p_sys->InputFormatInfo,
438 &p_sys->OutputFormatInfo,
439 &p_sys->myConverter );
440 if( i_error )
442 msg_Err( p_dec, "error on SoundConverterOpen = %d", i_error );
443 goto exit_error;
446 #if 0
447 /* tell the sound converter we accept VBR formats */
448 i_error = SoundConverterSetInfo( p_dec->myConverter, siClientAcceptsVBR,
449 (void *)true );
450 #endif
452 if( p_dec->fmt_in.i_extra > 36 + 8 )
454 i_error = p_sys->SoundConverterSetInfo( p_sys->myConverter,
455 FCC( 'w', 'a', 'v', 'e' ),
456 ((uint8_t*)p_dec->fmt_in.p_extra) + 36 + 8 );
458 msg_Dbg( p_dec, "error on SoundConverterSetInfo = %d", i_error );
461 WantedBufferSize = p_sys->OutputFormatInfo.numChannels *
462 p_sys->OutputFormatInfo.sampleRate * 2;
463 p_sys->FramesToGet = 0;
465 i_error = p_sys->SoundConverterGetBufferSizes( p_sys->myConverter,
466 WantedBufferSize,
467 &p_sys->FramesToGet,
468 &InputBufferSize,
469 &OutputBufferSize );
471 msg_Dbg( p_dec, "WantedBufferSize=%li InputBufferSize=%li "
472 "OutputBufferSize=%li FramesToGet=%li",
473 WantedBufferSize, InputBufferSize, OutputBufferSize,
474 p_sys->FramesToGet );
476 p_sys->InFrameSize = (InputBufferSize + p_sys->FramesToGet - 1 ) /
477 p_sys->FramesToGet;
478 p_sys->OutFrameSize = OutputBufferSize / p_sys->FramesToGet;
480 msg_Dbg( p_dec, "frame size %d -> %d",
481 p_sys->InFrameSize, p_sys->OutFrameSize );
483 if( (i_error = p_sys->SoundConverterBeginConversion(p_sys->myConverter)) )
485 msg_Err( p_dec,
486 "error on SoundConverterBeginConversion = %d", i_error );
487 goto exit_error;
491 es_format_Init( &p_dec->fmt_out, AUDIO_ES, VLC_CODEC_S16N );
492 p_dec->fmt_out.audio.i_rate = p_sys->OutputFormatInfo.sampleRate;
493 p_dec->fmt_out.audio.i_channels = p_sys->OutputFormatInfo.numChannels;
494 p_dec->fmt_out.audio.i_physical_channels =
495 p_dec->fmt_out.audio.i_original_channels =
496 pi_channels_maps[p_sys->OutputFormatInfo.numChannels];
498 date_Init( &p_sys->date, p_dec->fmt_out.audio.i_rate, 1 );
500 p_sys->i_buffer = 0;
501 p_sys->i_buffer_size = 100*1000;
502 p_sys->p_buffer = malloc( p_sys->i_buffer_size );
503 if( !p_sys->p_buffer )
504 goto exit_error;
506 p_sys->i_out = 0;
507 p_sys->i_out_frames = 0;
509 vlc_mutex_unlock( &qt_mutex );
510 return VLC_SUCCESS;
512 exit_error:
514 #ifdef LOADER
515 Restore_LDT_Keeper( p_sys->ldt_fs );
516 #endif
517 vlc_mutex_unlock( &qt_mutex );
519 free( p_sys );
520 return VLC_EGENERIC;
523 /*****************************************************************************
524 * DecodeAudio:
525 *****************************************************************************/
526 static block_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
528 decoder_sys_t *p_sys = p_dec->p_sys;
530 block_t *p_block;
531 int i_error;
533 #ifdef LOADER
534 /* We must do open and close in the same thread (unless we do
535 * Setup_LDT_Keeper in the main thread before all others */
536 if( p_sys == NULL )
538 if( OpenAudio( p_dec ) )
540 /* Fatal */
541 p_dec->b_error = true;
542 return NULL;
545 p_sys = p_dec->p_sys;
547 #endif
549 if( pp_block == NULL || *pp_block == NULL )
551 return NULL;
553 p_block = *pp_block;
555 if( p_sys->i_out_frames > 0 && p_sys->i_out >= p_sys->i_out_frames )
557 /* Ask new data */
558 p_sys->i_out = 0;
559 p_sys->i_out_frames = 0;
561 *pp_block = NULL;
562 return NULL;
565 if( p_sys->i_out_frames <= 0 )
567 p_sys->pts = p_block->i_pts;
569 mtime_t i_display_date = 0;
570 if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
571 i_display_date = decoder_GetDisplayDate( p_dec, p_block->i_pts );
573 if( i_display_date > 0 && i_display_date < mdate() )
575 block_Release( p_block );
576 *pp_block = NULL;
577 return NULL;
580 /* Append data */
581 if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
583 p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer + 1024;
584 p_sys->p_buffer = xrealloc( p_sys->p_buffer, p_sys->i_buffer_size );
586 memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer,
587 p_block->i_buffer );
588 p_sys->i_buffer += p_block->i_buffer;
590 if( p_sys->i_buffer > p_sys->InFrameSize )
592 int i_frames = p_sys->i_buffer / p_sys->InFrameSize;
593 unsigned long i_out_frames, i_out_bytes;
594 vlc_mutex_lock( &qt_mutex );
596 i_error = p_sys->SoundConverterConvertBuffer( p_sys->myConverter,
597 p_sys->p_buffer,
598 i_frames,
599 p_sys->out_buffer,
600 &i_out_frames,
601 &i_out_bytes );
602 vlc_mutex_unlock( &qt_mutex );
605 msg_Dbg( p_dec, "decoded %d frames -> %ld frames (error=%d)",
606 i_frames, i_out_frames, i_error );
608 msg_Dbg( p_dec, "decoded %ld frames = %ld bytes",
609 i_out_frames, i_out_bytes );
612 p_sys->i_buffer -= i_frames * p_sys->InFrameSize;
613 if( p_sys->i_buffer > 0 )
615 memmove( &p_sys->p_buffer[0],
616 &p_sys->p_buffer[i_frames * p_sys->InFrameSize],
617 p_sys->i_buffer );
620 if( p_sys->pts > VLC_TS_INVALID &&
621 p_sys->pts != date_Get( &p_sys->date ) )
623 date_Set( &p_sys->date, p_sys->pts );
625 else if( !date_Get( &p_sys->date ) )
627 return NULL;
630 if( !i_error && i_out_frames > 0 )
632 /* we have others samples */
633 p_sys->i_out_frames = i_out_frames;
634 p_sys->i_out = 0;
639 if( p_sys->i_out < p_sys->i_out_frames )
641 block_t *p_out;
642 int i_frames = __MIN( p_sys->i_out_frames - p_sys->i_out, 1000 );
644 p_out = decoder_NewAudioBuffer( p_dec, i_frames );
646 if( p_out )
648 p_out->i_pts = date_Get( &p_sys->date );
649 p_out->i_length = date_Increment( &p_sys->date, i_frames )
650 - p_out->i_pts;
652 memcpy( p_out->p_buffer,
653 &p_sys->out_buffer[2 * p_sys->i_out * p_dec->fmt_out.audio.i_channels],
654 p_out->i_buffer );
656 p_sys->i_out += i_frames;
658 return p_out;
661 return NULL;
664 /*****************************************************************************
665 * OpenVideo:
666 *****************************************************************************/
667 static int OpenVideo( decoder_t *p_dec )
669 #ifndef WIN32
670 decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
671 if( !p_sys )
672 return VLC_ENOMEM;
674 long i_result;
675 ComponentDescription desc;
676 Component prev;
677 ComponentResult cres;
678 ImageSubCodecDecompressCapabilities icap; /* for ImageCodecInitialize() */
679 CodecInfo cinfo; /* for ImageCodecGetCodecInfo() */
680 ImageDescription *id;
682 char fcc[4];
683 int i_vide = p_dec->fmt_in.i_extra;
684 uint8_t *p_vide = p_dec->fmt_in.p_extra;
686 p_dec->p_sys = p_sys;
687 p_dec->pf_decode_video = DecodeVideo;
688 p_sys->i_late = 0;
690 if( i_vide <= 0 )
692 msg_Err( p_dec, "missing extra info" );
693 free( p_sys );
694 return VLC_EGENERIC;
697 if( p_dec->fmt_in.i_original_fourcc )
698 memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 );
699 else
700 memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
702 msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d",
703 fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
705 /* get lock, avoid segfault */
706 vlc_mutex_lock( &qt_mutex );
708 #ifdef __APPLE__
709 EnterMovies();
710 #endif
712 if( QTVideoInit( p_dec ) )
714 msg_Err( p_dec, "cannot initialize QT");
715 goto exit_error;
718 #ifndef __APPLE__
719 if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) )
721 msg_Dbg( p_dec, "error on InitializeQTML = %d", (int)i_result );
722 goto exit_error;
724 #endif
726 /* init ComponentDescription */
727 memset( &desc, 0, sizeof( ComponentDescription ) );
728 desc.componentType = FCC( 'i', 'm', 'd', 'c' );
729 desc.componentSubType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
730 desc.componentManufacturer = 0;
731 desc.componentFlags = 0;
732 desc.componentFlagsMask = 0;
734 if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) )
736 msg_Err( p_dec, "cannot find requested component" );
737 goto exit_error;
739 msg_Dbg( p_dec, "component id=0x%p", prev );
741 p_sys->ci = p_sys->OpenComponent( prev );
742 msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci );
744 memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) );
745 cres = p_sys->ImageCodecInitialize( p_sys->ci, &icap );
746 msg_Dbg( p_dec, "ImageCodecInitialize->0x%X size=%d (%d)",
747 (int)cres, (int)icap.recordSize, (int)icap.decompressRecordSize);
749 memset( &cinfo, 0, sizeof( CodecInfo ) );
750 cres = p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo );
751 msg_Dbg( p_dec,
752 "Flags: compr: 0x%x decomp: 0x%x format: 0x%x",
753 (unsigned int)cinfo.compressFlags,
754 (unsigned int)cinfo.decompressFlags,
755 (unsigned int)cinfo.formatFlags );
756 msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s",
757 ((unsigned char*)&cinfo.typeName)[0],
758 ((unsigned char*)&cinfo.typeName)+1 );
760 /* make a yuy2 gworld */
761 p_sys->OutBufferRect.top = 0;
762 p_sys->OutBufferRect.left = 0;
763 p_sys->OutBufferRect.right = p_dec->fmt_in.video.i_width;
764 p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height;
767 /* codec data FIXME use codec not SVQ3 */
768 msg_Dbg( p_dec, "vide = %d", i_vide );
769 id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) );
770 if( !id )
771 goto exit_error;
772 id->idSize = sizeof( ImageDescription ) + ( i_vide - 70 );
773 id->cType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
774 id->version = GetWBE ( p_vide + 0 );
775 id->revisionLevel = GetWBE ( p_vide + 2 );
776 id->vendor = GetDWBE( p_vide + 4 );
777 id->temporalQuality = GetDWBE( p_vide + 8 );
778 id->spatialQuality = GetDWBE( p_vide + 12 );
779 id->width = GetWBE ( p_vide + 16 );
780 id->height = GetWBE ( p_vide + 18 );
781 id->hRes = GetDWBE( p_vide + 20 );
782 id->vRes = GetDWBE( p_vide + 24 );
783 id->dataSize = GetDWBE( p_vide + 28 );
784 id->frameCount = GetWBE ( p_vide + 32 );
785 memcpy( &id->name, p_vide + 34, 32 );
786 id->depth = GetWBE ( p_vide + 66 );
787 id->clutID = GetWBE ( p_vide + 68 );
788 if( i_vide > 70 )
790 memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 );
793 msg_Dbg( p_dec, "idSize=%d ver=%d rev=%d vendor=%d tempQ=%d "
794 "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d depth=%d frameCount=%d clutID=%d",
795 (int)id->idSize, id->version, id->revisionLevel, (int)id->vendor,
796 (int)id->temporalQuality, (int)id->spatialQuality,
797 (int)id->width, (int)id->height,
798 (int)id->hRes, (int)id->vRes,
799 (int)id->dataSize,
800 id->depth,
801 id->frameCount,
802 id->clutID );
804 p_sys->framedescHandle = (ImageDescriptionHandle) NewHandleClear( id->idSize );
805 memcpy( *p_sys->framedescHandle, id, id->idSize );
807 if( p_dec->fmt_in.video.i_width != 0 && p_dec->fmt_in.video.i_height != 0)
808 p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 );
809 if( !p_sys->plane )
810 goto exit_error;
812 i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld,
813 /*pixel format of new GWorld==YUY2 */
814 kYUVSPixelFormat,
815 /* we should benchmark if yvu9 is
816 * faster for svq3, too */
817 &p_sys->OutBufferRect,
818 0, 0, 0,
819 p_sys->plane,
820 p_dec->fmt_in.video.i_width * 2 );
822 msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld",
823 65536 - ( i_result&0xffff ) );
825 memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) );
826 p_sys->decpar.imageDescription = p_sys->framedescHandle;
827 p_sys->decpar.startLine = 0;
828 p_sys->decpar.stopLine = ( **p_sys->framedescHandle ).height;
829 p_sys->decpar.frameNumber = 1;
830 p_sys->decpar.matrixFlags = 0;
831 p_sys->decpar.matrixType = 0;
832 p_sys->decpar.matrix = 0;
833 p_sys->decpar.capabilities = &p_sys->codeccap;
834 p_sys->decpar.accuracy = codecNormalQuality;
835 p_sys->decpar.srcRect = p_sys->OutBufferRect;
836 p_sys->decpar.transferMode = srcCopy;
837 p_sys->decpar.dstPixMap = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap; */
839 cres = p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar );
840 msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X",
841 (int)cres );
843 es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_CODEC_YUYV);
844 p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
845 p_dec->fmt_out.video.i_height= p_dec->fmt_in.video.i_height;
846 p_dec->fmt_out.video.i_sar_num = 1;
847 p_dec->fmt_out.video.i_sar_den = 1;
849 vlc_mutex_unlock( &qt_mutex );
850 return VLC_SUCCESS;
852 exit_error:
853 #ifdef LOADER
854 Restore_LDT_Keeper( p_sys->ldt_fs );
855 #endif
856 vlc_mutex_unlock( &qt_mutex );
858 #else
859 VLC_UNUSED( p_dec );
860 #endif /* !WIN32 */
862 return VLC_EGENERIC;
865 #ifndef WIN32
866 /*****************************************************************************
867 * DecodeVideo:
868 *****************************************************************************/
869 static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
871 decoder_sys_t *p_sys = p_dec->p_sys;
872 block_t *p_block;
873 picture_t *p_pic;
874 mtime_t i_pts;
876 ComponentResult cres;
878 #ifdef LOADER
879 /* We must do open and close in the same thread (unless we do
880 * Setup_LDT_Keeper in the main thread before all others */
881 if( p_sys == NULL )
883 if( OpenVideo( p_dec ) )
885 /* Fatal */
886 p_dec->b_error = true;
887 return NULL;
889 p_sys = p_dec->p_sys;
891 #endif
893 if( pp_block == NULL || *pp_block == NULL )
895 return NULL;
897 p_block = *pp_block;
898 *pp_block = NULL;
900 i_pts = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;
902 mtime_t i_display_date = 0;
903 if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
904 i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
906 if( i_display_date > 0 && i_display_date < mdate() )
908 p_sys->i_late++;
910 else
912 p_sys->i_late = 0;
914 #ifndef NDEBUG
915 msg_Dbg( p_dec, "bufsize: %zu", p_block->i_buffer);
916 #endif
918 if( p_sys->i_late > 10 )
920 msg_Dbg( p_dec, "late buffer dropped (%"PRId64")", i_pts );
921 block_Release( p_block );
922 return NULL;
925 vlc_mutex_lock( &qt_mutex );
927 if( ( p_pic = decoder_NewPicture( p_dec ) ) )
929 p_sys->decpar.data = (Ptr)p_block->p_buffer;
930 p_sys->decpar.bufferSize = p_block->i_buffer;
931 (**p_sys->framedescHandle).dataSize = p_block->i_buffer;
933 cres = p_sys->ImageCodecBandDecompress( p_sys->ci, &p_sys->decpar );
935 ++p_sys->decpar.frameNumber;
937 if( cres &0xFFFF )
939 msg_Dbg( p_dec, "quicktime_video: ImageCodecBandDecompress"
940 " cres=0x%X (-0x%X) %d :(",
941 (int)cres,(int)-cres, (int)cres );
944 memcpy( p_pic->p[0].p_pixels, p_sys->plane,
945 p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 2 );
946 p_pic->date = i_pts;
949 vlc_mutex_unlock( &qt_mutex );
951 block_Release( p_block );
952 return p_pic;
954 #endif /* !WIN32 */
956 /*****************************************************************************
957 * QTAudioInit:
958 *****************************************************************************/
959 static int QTAudioInit( decoder_t *p_dec )
961 decoder_sys_t *p_sys = p_dec->p_sys;
963 #ifdef __APPLE__
964 p_sys->SoundConverterOpen = (void*)SoundConverterOpen;
965 p_sys->SoundConverterClose = (void*)SoundConverterClose;
966 p_sys->SoundConverterSetInfo = (void*)SoundConverterSetInfo;
967 p_sys->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes;
968 p_sys->SoundConverterConvertBuffer = (void*)SoundConverterConvertBuffer;
969 p_sys->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion;
970 p_sys->SoundConverterEndConversion = (void*)SoundConverterEndConversion;
971 #else
973 #ifdef LOADER
974 p_sys->ldt_fs = Setup_LDT_Keeper();
975 #endif /* LOADER */
977 p_sys->qts = LoadLibraryA( "QuickTime.qts" );
978 if( p_sys->qts == NULL )
980 msg_Dbg( p_dec, "failed loading QuickTime.qts" );
981 return VLC_EGENERIC;
983 p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
984 if( p_sys->qtml == NULL )
986 msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
987 return VLC_EGENERIC;
990 p_sys->InitializeQTML = (void *)GetProcAddress( p_sys->qtml, "InitializeQTML" );
991 p_sys->TerminateQTML = (void *)GetProcAddress( p_sys->qtml, "TerminateQTML" );
992 p_sys->SoundConverterOpen = (void *)GetProcAddress( p_sys->qtml, "SoundConverterOpen" );
993 p_sys->SoundConverterClose = (void *)GetProcAddress( p_sys->qtml, "SoundConverterClose" );
994 p_sys->SoundConverterSetInfo = (void *)GetProcAddress( p_sys->qtml, "SoundConverterSetInfo" );
995 p_sys->SoundConverterGetBufferSizes = (void *)GetProcAddress( p_sys->qtml, "SoundConverterGetBufferSizes" );
996 p_sys->SoundConverterConvertBuffer = (void *)GetProcAddress( p_sys->qtml, "SoundConverterConvertBuffer" );
997 p_sys->SoundConverterEndConversion = (void *)GetProcAddress( p_sys->qtml, "SoundConverterEndConversion" );
998 p_sys->SoundConverterBeginConversion= (void *)GetProcAddress( p_sys->qtml, "SoundConverterBeginConversion");
1000 if( p_sys->InitializeQTML == NULL )
1002 msg_Err( p_dec, "failed getting proc address InitializeQTML" );
1003 return VLC_EGENERIC;
1005 if( p_sys->SoundConverterOpen == NULL ||
1006 p_sys->SoundConverterClose == NULL ||
1007 p_sys->SoundConverterSetInfo == NULL ||
1008 p_sys->SoundConverterGetBufferSizes == NULL ||
1009 p_sys->SoundConverterConvertBuffer == NULL ||
1010 p_sys->SoundConverterEndConversion == NULL ||
1011 p_sys->SoundConverterBeginConversion == NULL )
1013 msg_Err( p_dec, "failed getting proc address" );
1014 return VLC_EGENERIC;
1017 msg_Dbg( p_dec, "standard init done" );
1018 #endif /* else __APPLE__ */
1020 return VLC_SUCCESS;
1023 #ifndef WIN32
1024 /*****************************************************************************
1025 * QTVideoInit:
1026 *****************************************************************************/
1027 static int QTVideoInit( decoder_t *p_dec )
1029 decoder_sys_t *p_sys = p_dec->p_sys;
1031 #ifdef __APPLE__
1032 p_sys->FindNextComponent = (void*)FindNextComponent;
1033 p_sys->OpenComponent = (void*)OpenComponent;
1034 p_sys->ImageCodecInitialize = (void*)ImageCodecInitialize;
1035 p_sys->ImageCodecGetCodecInfo = (void*)ImageCodecGetCodecInfo;
1036 p_sys->ImageCodecPreDecompress = (void*)ImageCodecPreDecompress;
1037 p_sys->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress;
1038 p_sys->GetGWorldPixMap = (void*)GetGWorldPixMap;
1039 p_sys->QTNewGWorldFromPtr = (void*)QTNewGWorldFromPtr;
1040 p_sys->NewHandleClear = (void*)NewHandleClear;
1041 #else
1043 #ifdef LOADER
1044 p_sys->ldt_fs = Setup_LDT_Keeper();
1045 #endif /* LOADER */
1046 p_sys->qts = LoadLibraryA( "QuickTime.qts" );
1047 if( p_sys->qts == NULL )
1049 msg_Dbg( p_dec, "failed loading QuickTime.qts" );
1050 return VLC_EGENERIC;
1052 msg_Dbg( p_dec, "QuickTime.qts loaded" );
1053 p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
1054 if( p_sys->qtml == NULL )
1056 msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
1057 return VLC_EGENERIC;
1059 msg_Dbg( p_dec, "qtmlClient.dll loaded" );
1061 /* (void*) to shut up gcc */
1062 p_sys->InitializeQTML = (void*)GetProcAddress( p_sys->qtml, "InitializeQTML" );
1063 p_sys->FindNextComponent = (void*)GetProcAddress( p_sys->qtml, "FindNextComponent" );
1064 p_sys->OpenComponent = (void*)GetProcAddress( p_sys->qtml, "OpenComponent" );
1065 p_sys->ImageCodecInitialize = (void*)GetProcAddress( p_sys->qtml, "ImageCodecInitialize" );
1066 p_sys->ImageCodecGetCodecInfo = (void*)GetProcAddress( p_sys->qtml, "ImageCodecGetCodecInfo" );
1067 p_sys->ImageCodecPreDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecPreDecompress" );
1068 p_sys->ImageCodecBandDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecBandDecompress" );
1069 p_sys->GetGWorldPixMap = (void*)GetProcAddress( p_sys->qtml, "GetGWorldPixMap" );
1070 p_sys->QTNewGWorldFromPtr = (void*)GetProcAddress( p_sys->qtml, "QTNewGWorldFromPtr" );
1071 p_sys->NewHandleClear = (void*)GetProcAddress( p_sys->qtml, "NewHandleClear" );
1073 if( p_sys->InitializeQTML == NULL )
1075 msg_Dbg( p_dec, "failed getting proc address InitializeQTML" );
1076 return VLC_EGENERIC;
1078 if( p_sys->FindNextComponent == NULL ||
1079 p_sys->OpenComponent == NULL ||
1080 p_sys->ImageCodecInitialize == NULL ||
1081 p_sys->ImageCodecGetCodecInfo == NULL ||
1082 p_sys->ImageCodecPreDecompress == NULL ||
1083 p_sys->ImageCodecBandDecompress == NULL ||
1084 p_sys->GetGWorldPixMap == NULL ||
1085 p_sys->QTNewGWorldFromPtr == NULL ||
1086 p_sys->NewHandleClear == NULL )
1088 msg_Err( p_dec, "failed getting proc address" );
1089 return VLC_EGENERIC;
1091 #endif /* __APPLE__ */
1093 return VLC_SUCCESS;
1095 #endif /* !WIN32 */