Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

quicktime.c

00001 /*****************************************************************************
00002  * quicktime.c: a quicktime decoder that uses the QT library/dll
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: quicktime.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Laurent Aimar <fenrir at via.ecp.fr>
00008  *          Derk-Jan Hartman <thedj at users.sf.net>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 
00029 #include <vlc/vlc.h>
00030 #include <vlc/aout.h>
00031 #include <vlc/vout.h>
00032 #include <vlc/decoder.h>
00033 
00034 #if !defined (SYS_DARWIN) && !defined(WIN32)
00035 # define LOADER 1
00036 #endif
00037 
00038 #ifdef SYS_DARWIN
00039 #include <QuickTime/QuickTimeComponents.h>
00040 #include <QuickTime/Movies.h>
00041 #include <QuickTime/ImageCodec.h>
00042 #endif
00043 
00044 /* for windows do we require Quicktime compents header? */
00045 #ifdef LOADER
00046 #include "qtx/qtxsdk/components.h"
00047 #include "wine/windef.h"
00048 #include "ldt_keeper.h"
00049 
00050 HMODULE   WINAPI LoadLibraryA(LPCSTR);
00051 FARPROC   WINAPI GetProcAddress(HMODULE,LPCSTR);
00052 int       WINAPI FreeLibrary(HMODULE);
00053 
00054 #endif
00055 
00056 /*****************************************************************************
00057  * Module descriptor
00058  *****************************************************************************/
00059 static int  Open ( vlc_object_t * );
00060 static void Close( vlc_object_t * );
00061 
00062 vlc_module_begin();
00063     set_description( _("QuickTime library decoder") );
00064     set_capability( "decoder", 10 );
00065     set_category( CAT_INPUT );
00066     set_subcategory( SUBCAT_INPUT_VCODEC );
00067     set_callbacks( Open, Close );
00068 
00069     /* create a mutex */
00070     var_Create( p_module->p_libvlc, "qt_mutex", VLC_VAR_MUTEX );
00071 vlc_module_end();
00072 
00073 
00074 /*****************************************************************************
00075  * Local prototypes
00076  *****************************************************************************/
00077 static int           OpenAudio( decoder_t * );
00078 static int           OpenVideo( decoder_t * );
00079 
00080 static aout_buffer_t *DecodeAudio( decoder_t *, block_t ** );
00081 static picture_t     *DecodeVideo( decoder_t *, block_t ** );
00082 
00083 #define FCC( a, b , c, d ) \
00084     ((uint32_t)( ((a)<<24)|((b)<<16)|((c)<<8)|(d)))
00085 
00086 #ifndef SYS_DARWIN
00087 typedef struct OpaqueSoundConverter*    SoundConverter;
00088 #ifndef LOADER
00089 typedef long                            OSType;
00090 typedef int                             OSErr;
00091 #endif
00092 typedef unsigned long                   UnsignedFixed;
00093 typedef uint8_t                         Byte;
00094 
00095 typedef struct SoundComponentData {
00096     long                            flags;
00097     OSType                          format;
00098     short                           numChannels;
00099     short                           sampleSize;
00100     UnsignedFixed                   sampleRate;
00101     long                            sampleCount;
00102     Byte *                          buffer;
00103     long                            reserved;
00104 } SoundComponentData;
00105 
00106 #endif /* SYS_DARWIN */
00107 
00108 struct decoder_sys_t
00109 {
00110     /* library */
00111 #ifndef SYS_DARWIN
00112 #ifdef LOADER
00113     ldt_fs_t    *ldt_fs;
00114 
00115 #endif /* LOADER */
00116     HMODULE qtml;
00117     OSErr (*InitializeQTML)             ( long flags );
00118     OSErr (*TerminateQTML)              ( void );
00119 #endif /* SYS_DARWIN */
00120 
00121     /* Audio */
00122     int (*SoundConverterOpen)           ( const SoundComponentData *,
00123                                           const SoundComponentData *,
00124                                           SoundConverter* );
00125     int (*SoundConverterClose)          ( SoundConverter );
00126     int (*SoundConverterSetInfo)        ( SoundConverter , OSType, void * );
00127     int (*SoundConverterGetBufferSizes) ( SoundConverter, unsigned long,
00128                                           unsigned long*, unsigned long*,
00129                                           unsigned long* );
00130     int (*SoundConverterBeginConversion)( SoundConverter );
00131     int (*SoundConverterEndConversion)  ( SoundConverter, void *,
00132                                           unsigned long *, unsigned long *);
00133     int (*SoundConverterConvertBuffer)  ( SoundConverter, const void *,
00134                                           unsigned long, void *,
00135                                           unsigned long *, unsigned long * );
00136     SoundConverter      myConverter;
00137     SoundComponentData  InputFormatInfo, OutputFormatInfo;
00138 
00139     long            FramesToGet;
00140     unsigned int    InFrameSize;
00141     unsigned int    OutFrameSize;
00142 
00143 #ifndef WIN32
00144     /* Video */
00145     Component         (*FindNextComponent)
00146         ( Component prev, ComponentDescription* desc );
00147 
00148     ComponentInstance (*OpenComponent)
00149         ( Component c );
00150 
00151     ComponentResult   (*ImageCodecInitialize)
00152         ( ComponentInstance ci, ImageSubCodecDecompressCapabilities * cap);
00153 
00154     ComponentResult   (*ImageCodecGetCodecInfo)
00155         ( ComponentInstance ci, CodecInfo *info );
00156 
00157     ComponentResult   (*ImageCodecPreDecompress)
00158         ( ComponentInstance ci, CodecDecompressParams * params );
00159 
00160     ComponentResult   (*ImageCodecBandDecompress)
00161         ( ComponentInstance ci, CodecDecompressParams * params );
00162 
00163     PixMapHandle      (*GetGWorldPixMap)
00164         ( GWorldPtr offscreenGWorld );
00165 
00166     OSErr             (*QTNewGWorldFromPtr)
00167         ( GWorldPtr *gw, OSType pixelFormat, const Rect *boundsRect,
00168           CTabHandle cTable, /*GDHandle*/ void *aGDevice, /*unused*/
00169           GWorldFlags flags, void *baseAddr, long rowBytes );
00170 
00171     OSErr             (*NewHandleClear)( Size byteCount );
00172 
00173     ComponentInstance       ci;
00174     Rect                    OutBufferRect;   /* the dimensions of our GWorld */
00175     GWorldPtr               OutBufferGWorld; /* a GWorld is some kind of
00176                                                 description for a drawing
00177                                                 environment */
00178     ImageDescriptionHandle  framedescHandle;
00179 
00180     CodecDecompressParams   decpar;          /* for ImageCodecPreDecompress()*/
00181     CodecCapabilities       codeccap;        /* for decpar */
00182 #endif
00183 
00184     /* Output properties */
00185     uint8_t *           plane;
00186     mtime_t             pts;
00187     audio_date_t        date;
00188 
00189     int                 i_late; /* video */
00190 
00191     /* buffer */
00192     unsigned int        i_buffer;
00193     unsigned int        i_buffer_size;
00194     uint8_t             *p_buffer;
00195 
00196     /* Audio only */
00197     uint8_t             out_buffer[1000000];    /* FIXME */
00198     int                 i_out_frames;
00199     int                 i_out;
00200 };
00201 
00202 static int pi_channels_maps[6] =
00203 {
00204     0,
00205     AOUT_CHAN_CENTER,
00206     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00207     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
00208     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
00209     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00210      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
00211 };
00212 
00213 static int QTAudioInit( decoder_t * );
00214 static int QTVideoInit( decoder_t * );
00215 
00216 /*****************************************************************************
00217  * Open: probe the decoder and return score
00218  *****************************************************************************
00219  * Tries to launch a decoder and return score so that the interface is able
00220  * to choose.
00221  *****************************************************************************/
00222 static int Open( vlc_object_t *p_this )
00223 {
00224     decoder_t *p_dec = (decoder_t*)p_this;
00225 
00226     switch( p_dec->fmt_in.i_codec )
00227     {
00228         case VLC_FOURCC('S','V','Q','3'): /* Sorenson v3 */
00229     /*    case VLC_FOURCC('S','V','Q','1'):  Sorenson v1 
00230         case VLC_FOURCC('Z','y','G','o'):
00231         case VLC_FOURCC('V','P','3','1'):
00232         case VLC_FOURCC('3','I','V','1'): */
00233         case VLC_FOURCC('r','l','e',' '): /* QuickTime animation (RLE) */
00234         case VLC_FOURCC('r','p','z','a'): /* QuickTime Apple Video */
00235         case VLC_FOURCC('a','z','p','r'): /* QuickTime animation (RLE) */
00236 #ifdef LOADER
00237             p_dec->p_sys = NULL;
00238             p_dec->pf_decode_video = DecodeVideo;
00239             return VLC_SUCCESS;
00240 #else
00241             return OpenVideo( p_dec );
00242 #endif
00243 
00244         case VLC_FOURCC('s','a','m','r'): /* 3GPP AMR audio */
00245         case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */
00246         case VLC_FOURCC('Q','D','M','C'): /* QDesign */
00247         case VLC_FOURCC('Q','D','M','2'): /* QDesign* 2 */
00248         case VLC_FOURCC('Q','c','l','p'): /* Qualcomm Purevoice Codec */
00249         case VLC_FOURCC('Q','C','L','P'): /* Qualcomm Purevoice Codec */
00250         case VLC_FOURCC('M','A','C','3'): /* MACE3 audio decoder */
00251         case VLC_FOURCC('M','A','C','6'): /* MACE6 audio decoder */
00252         case VLC_FOURCC('d','v','c','a'): /* DV Audio */
00253         case VLC_FOURCC('s','o','w','t'): /* 16-bit Little Endian */
00254         case VLC_FOURCC('t','w','o','s'): /* 16-bit Big Endian */
00255         case VLC_FOURCC('a','l','a','w'): /* ALaw 2:1 */
00256         case VLC_FOURCC('u','l','a','w'): /* mu-Law 2:1 */
00257         case VLC_FOURCC('r','a','w',' '): /* 8-bit offset binaries */
00258         case VLC_FOURCC('f','l','3','2'): /* 32-bit Floating Point */
00259         case VLC_FOURCC('f','l','6','4'): /* 64-bit Floating Point */
00260         case VLC_FOURCC('i','n','2','4'): /* 24-bit Interger */
00261         case VLC_FOURCC('i','n','3','2'): /* 32-bit Integer */
00262         case 0x0011:                            /* DVI IMA */
00263         case 0x6D730002:                        /* Microsoft ADPCM-ACM */
00264         case 0x6D730011:                        /* DVI Intel IMAADPCM-ACM */
00265 #ifdef LOADER
00266             p_dec->p_sys = NULL;
00267             p_dec->pf_decode_audio = DecodeAudio;
00268             return VLC_SUCCESS;
00269 #else
00270             return OpenAudio( p_dec );
00271 #endif
00272 
00273         default:
00274             return VLC_EGENERIC;
00275     }
00276 }
00277 
00278 /*****************************************************************************
00279  * Close:
00280  *****************************************************************************/
00281 static void Close( vlc_object_t *p_this )
00282 {
00283     decoder_t     *p_dec = (decoder_t*)p_this;
00284     decoder_sys_t *p_sys = p_dec->p_sys;
00285     vlc_value_t   lockval;
00286 
00287     /* get lock, avoid segfault */
00288     var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
00289     vlc_mutex_lock( lockval.p_address );
00290 #ifdef SYS_DARWIN
00291     /* on OS X QT is not threadsafe */
00292     vlc_mutex_lock( &p_dec->p_vlc->quicktime_lock );
00293 #endif
00294 
00295     if( p_dec->fmt_out.i_cat == AUDIO_ES )
00296     {
00297         int i_error;
00298         unsigned long ConvertedFrames=0;
00299         unsigned long ConvertedBytes=0;
00300 
00301         i_error = p_sys->SoundConverterEndConversion( p_sys->myConverter, NULL,
00302                                                       &ConvertedFrames,
00303                                                       &ConvertedBytes );
00304         msg_Dbg( p_dec, "SoundConverterEndConversion => %d", i_error );
00305 
00306         i_error = p_sys->SoundConverterClose( p_sys->myConverter );
00307         msg_Dbg( p_dec, "SoundConverterClose => %d", i_error );
00308 
00309         free( p_sys->p_buffer );
00310     }
00311     else if( p_dec->fmt_out.i_cat == VIDEO_ES )
00312     {
00313         free( p_sys->plane );
00314     }
00315 
00316 #ifndef SYS_DARWIN
00317     FreeLibrary( p_sys->qtml );
00318     msg_Dbg( p_dec, "FreeLibrary ok." );
00319 #endif
00320 
00321 #ifdef SYS_DARWIN
00322     ExitMovies();
00323 #endif
00324 
00325 #if 0
00326     /* Segfault */
00327 #ifdef LOADER
00328     Restore_LDT_Keeper( p_sys->ldt_fs );
00329     msg_Dbg( p_dec, "Restore_LDT_Keeper" );
00330 #endif
00331 #endif
00332 
00333 #ifdef SYS_DARWIN
00334     vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
00335 #endif
00336     vlc_mutex_unlock( lockval.p_address );
00337 
00338     free( p_sys );
00339 }
00340 
00341 /*****************************************************************************
00342  * OpenAudio:
00343  *****************************************************************************/
00344 static int OpenAudio( decoder_t *p_dec )
00345 {
00346     decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
00347 
00348     vlc_value_t     lockval;
00349     int             i_error;
00350     char            fcc[4];
00351     unsigned long   WantedBufferSize;
00352     unsigned long   InputBufferSize = 0;
00353     unsigned long   OutputBufferSize = 0;
00354 
00355     memset( p_sys, 0, sizeof( decoder_sys_t ) );
00356 
00357     p_dec->p_sys = p_sys;
00358     p_dec->pf_decode_audio = DecodeAudio;
00359 
00360     memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
00361 
00362     /* get lock, avoid segfault */
00363     var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
00364     vlc_mutex_lock( lockval.p_address );
00365 #ifdef SYS_DARWIN
00366     /* on OS X QT is not threadsafe */
00367     vlc_mutex_lock( &p_dec->p_vlc->quicktime_lock );
00368 #endif
00369 
00370 #ifdef SYS_DARWIN
00371     EnterMovies();
00372 #endif
00373 
00374     if( QTAudioInit( p_dec ) )
00375     {
00376         msg_Err( p_dec, "cannot initialize QT");
00377         goto exit_error;
00378     }
00379 
00380 #ifndef SYS_DARWIN
00381     if( ( i_error = p_sys->InitializeQTML( 6 + 16 ) ) )
00382     {
00383         msg_Dbg( p_dec, "error on InitializeQTML = %d", i_error );
00384         goto exit_error;
00385     }
00386 #endif
00387 
00388     /* input format settings */
00389     p_sys->InputFormatInfo.flags       = 0;
00390     p_sys->InputFormatInfo.sampleCount = 0;
00391     p_sys->InputFormatInfo.buffer      = NULL;
00392     p_sys->InputFormatInfo.reserved    = 0;
00393     p_sys->InputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
00394     p_sys->InputFormatInfo.sampleSize  = p_dec->fmt_in.audio.i_bitspersample;
00395     p_sys->InputFormatInfo.sampleRate  = p_dec->fmt_in.audio.i_rate;
00396     p_sys->InputFormatInfo.format      = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00397 
00398     /* output format settings */
00399     p_sys->OutputFormatInfo.flags       = 0;
00400     p_sys->OutputFormatInfo.sampleCount = 0;
00401     p_sys->OutputFormatInfo.buffer      = NULL;
00402     p_sys->OutputFormatInfo.reserved    = 0;
00403     p_sys->OutputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
00404     p_sys->OutputFormatInfo.sampleSize  = 16;
00405     p_sys->OutputFormatInfo.sampleRate  = p_dec->fmt_in.audio.i_rate;
00406     p_sys->OutputFormatInfo.format      = FCC( 'N', 'O', 'N', 'E' );
00407 
00408 
00409     i_error = p_sys->SoundConverterOpen( &p_sys->InputFormatInfo,
00410                                          &p_sys->OutputFormatInfo,
00411                                          &p_sys->myConverter );
00412     if( i_error )
00413     {
00414         msg_Err( p_dec, "error on SoundConverterOpen = %d", i_error );
00415         goto exit_error;
00416     }
00417 
00418 #if 0
00419     /* tell the sound converter we accept VBR formats */
00420     i_error = SoundConverterSetInfo( p_dec->myConverter, siClientAcceptsVBR,
00421                                      (void *)true );
00422 #endif
00423 
00424     if( p_dec->fmt_in.i_extra > 36 + 8 )
00425     {
00426         i_error = p_sys->SoundConverterSetInfo( p_sys->myConverter,
00427                                                 FCC( 'w', 'a', 'v', 'e' ),
00428                                                 ((uint8_t*)p_dec->fmt_in.p_extra) + 36 + 8 );
00429 
00430         msg_Dbg( p_dec, "error on SoundConverterSetInfo = %d", i_error );
00431     }
00432 
00433     WantedBufferSize = p_sys->OutputFormatInfo.numChannels *
00434                        p_sys->OutputFormatInfo.sampleRate * 2;
00435     p_sys->FramesToGet = 0;
00436 
00437     i_error = p_sys->SoundConverterGetBufferSizes( p_sys->myConverter,
00438                                                    WantedBufferSize,
00439                                                    &p_sys->FramesToGet,
00440                                                    &InputBufferSize,
00441                                                    &OutputBufferSize );
00442 
00443     msg_Dbg( p_dec, "WantedBufferSize=%li InputBufferSize=%li "
00444              "OutputBufferSize=%li FramesToGet=%li",
00445              WantedBufferSize, InputBufferSize, OutputBufferSize,
00446              p_sys->FramesToGet );
00447 
00448     p_sys->InFrameSize  = (InputBufferSize + p_sys->FramesToGet - 1 ) /
00449                             p_sys->FramesToGet;
00450     p_sys->OutFrameSize = OutputBufferSize / p_sys->FramesToGet;
00451 
00452     msg_Dbg( p_dec, "frame size %d -> %d",
00453              p_sys->InFrameSize, p_sys->OutFrameSize );
00454 
00455     if( (i_error = p_sys->SoundConverterBeginConversion(p_sys->myConverter)) )
00456     {
00457         msg_Err( p_dec,
00458                  "error on SoundConverterBeginConversion = %d", i_error );
00459         goto exit_error;
00460     }
00461 
00462 
00463     es_format_Init( &p_dec->fmt_out, AUDIO_ES, AOUT_FMT_S16_NE );
00464     p_dec->fmt_out.audio.i_rate = p_sys->OutputFormatInfo.sampleRate;
00465     p_dec->fmt_out.audio.i_channels = p_sys->OutputFormatInfo.numChannels;
00466     p_dec->fmt_out.audio.i_physical_channels =
00467     p_dec->fmt_out.audio.i_original_channels =
00468         pi_channels_maps[p_sys->OutputFormatInfo.numChannels];
00469 
00470     aout_DateInit( &p_sys->date, p_dec->fmt_out.audio.i_rate );
00471 
00472     p_sys->i_buffer      = 0;
00473     p_sys->i_buffer_size = 100*1000;
00474     p_sys->p_buffer      = malloc( p_sys->i_buffer_size );
00475 
00476     p_sys->i_out = 0;
00477     p_sys->i_out_frames = 0;
00478 
00479 #ifdef SYS_DARWIN
00480     vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
00481 #endif
00482     vlc_mutex_unlock( lockval.p_address );
00483     return VLC_SUCCESS;
00484 
00485 exit_error:
00486 
00487 #ifdef LOADER
00488     Restore_LDT_Keeper( p_sys->ldt_fs );
00489 #endif
00490 #ifdef SYS_DARWIN
00491     vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
00492 #endif
00493     vlc_mutex_unlock( lockval.p_address );
00494 
00495     free( p_sys );
00496     return VLC_EGENERIC;
00497 }
00498 
00499 /*****************************************************************************
00500  * DecodeAudio:
00501  *****************************************************************************/
00502 static aout_buffer_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
00503 {
00504     decoder_sys_t *p_sys = p_dec->p_sys;
00505 
00506     vlc_value_t lockval;
00507     block_t     *p_block;
00508     int         i_error;
00509 
00510 #ifdef LOADER
00511     /* We must do open and close in the same thread (unless we do
00512      * Setup_LDT_Keeper in the main thread before all others */
00513     if( p_sys == NULL )
00514     {
00515         if( OpenAudio( p_dec ) )
00516         {
00517             /* Fatal */
00518             p_dec->b_error = VLC_TRUE;
00519             return NULL;
00520         }
00521 
00522         p_sys = p_dec->p_sys;
00523     }
00524 #endif
00525 
00526     if( pp_block == NULL || *pp_block == NULL )
00527     {
00528         return NULL;
00529     }
00530     p_block = *pp_block;
00531 
00532     if( p_sys->i_out_frames > 0 && p_sys->i_out >= p_sys->i_out_frames )
00533     {
00534         /* Ask new data */
00535         p_sys->i_out = 0;
00536         p_sys->i_out_frames = 0;
00537 
00538         *pp_block = NULL;
00539         return NULL;
00540     }
00541 
00542     if( p_sys->i_out_frames <= 0 )
00543     {
00544         if( ( p_sys->pts = p_block->i_pts ) < mdate() )
00545         {
00546             block_Release( p_block );
00547             *pp_block = NULL;
00548             return NULL;
00549         }
00550 
00551         /* Append data */
00552         if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
00553         {
00554             p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer + 1024;
00555             p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
00556         }
00557         memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer,
00558                 p_block->i_buffer );
00559         p_sys->i_buffer += p_block->i_buffer;
00560 
00561         if( p_sys->i_buffer > p_sys->InFrameSize )
00562         {
00563             int i_frames = p_sys->i_buffer / p_sys->InFrameSize;
00564             long i_out_frames, i_out_bytes;
00565 
00566             var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
00567             vlc_mutex_lock( lockval.p_address );
00568             i_error = p_sys->SoundConverterConvertBuffer( p_sys->myConverter,
00569                                                           p_sys->p_buffer,
00570                                                           i_frames,
00571                                                           p_sys->out_buffer,
00572                                                           &i_out_frames,
00573                                                           &i_out_bytes );
00574             vlc_mutex_unlock( lockval.p_address );
00575 
00576             /*
00577             msg_Dbg( p_dec, "decoded %d frames -> %ld frames (error=%d)",
00578                      i_frames, i_out_frames, i_error );
00579 
00580             msg_Dbg( p_dec, "decoded %ld frames = %ld bytes",
00581                      i_out_frames, i_out_bytes );
00582             */
00583 
00584             p_sys->i_buffer -= i_frames * p_sys->InFrameSize;
00585             if( p_sys->i_buffer > 0 )
00586             {
00587                 memmove( &p_sys->p_buffer[0],
00588                          &p_sys->p_buffer[i_frames * p_sys->InFrameSize],
00589                          p_sys->i_buffer );
00590             }
00591 
00592             if( p_sys->pts != 0 &&
00593                 p_sys->pts != aout_DateGet( &p_sys->date ) )
00594             {
00595                 aout_DateSet( &p_sys->date, p_sys->pts );
00596             }
00597             else if( !aout_DateGet( &p_sys->date ) )
00598             {
00599                 return NULL;
00600             }
00601 
00602             if( !i_error && i_out_frames > 0 )
00603             {
00604                 /* we have others samples */
00605                 p_sys->i_out_frames = i_out_frames;
00606                 p_sys->i_out = 0;
00607             }
00608         }
00609     }
00610 
00611     if( p_sys->i_out < p_sys->i_out_frames )
00612     {
00613         aout_buffer_t *p_out;
00614         int  i_frames = __MIN( p_sys->i_out_frames - p_sys->i_out, 1000 );
00615 
00616         p_out = p_dec->pf_aout_buffer_new( p_dec, i_frames );
00617 
00618         if( p_out )
00619         {
00620             p_out->start_date = aout_DateGet( &p_sys->date );
00621             p_out->end_date = aout_DateIncrement( &p_sys->date, i_frames );
00622 
00623             memcpy( p_out->p_buffer,
00624                     &p_sys->out_buffer[2 * p_sys->i_out * p_dec->fmt_out.audio.i_channels],
00625                     p_out->i_nb_bytes );
00626 
00627             p_sys->i_out += i_frames;
00628         }
00629         return p_out;
00630     }
00631 
00632     return NULL;
00633 }
00634 
00635 /*****************************************************************************
00636  * OpenVideo:
00637  *****************************************************************************/
00638 static int OpenVideo( decoder_t *p_dec )
00639 {
00640     decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
00641 
00642 #ifndef WIN32
00643     vlc_value_t                         lockval;
00644     long                                i_result;
00645     ComponentDescription                desc;
00646     Component                           prev;
00647     ComponentResult                     cres;
00648     ImageSubCodecDecompressCapabilities icap;   /* for ImageCodecInitialize() */
00649     CodecInfo                           cinfo;  /* for ImageCodecGetCodecInfo() */
00650     ImageDescription                    *id;
00651 
00652     char                fcc[4];
00653     int     i_vide = p_dec->fmt_in.i_extra;
00654     uint8_t *p_vide = p_dec->fmt_in.p_extra;
00655 
00656     p_dec->p_sys = p_sys;
00657     p_dec->pf_decode_video = DecodeVideo;
00658     p_sys->i_late = 0;
00659 
00660     if( i_vide <= 0 )
00661     {
00662         msg_Err( p_dec, "missing extra info" );
00663         free( p_sys );
00664         return VLC_EGENERIC;
00665     }
00666 
00667     memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
00668     msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d",
00669              fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
00670 
00671     /* get lock, avoid segfault */
00672     var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
00673     vlc_mutex_lock( lockval.p_address );
00674 
00675 #ifdef SYS_DARWIN
00676     EnterMovies();
00677 #endif
00678 
00679     if( QTVideoInit( p_dec ) )
00680     {
00681         msg_Err( p_dec, "cannot initialize QT");
00682         goto exit_error;
00683     }
00684 
00685 #ifndef SYS_DARWIN
00686     if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) )
00687     {
00688         msg_Dbg( p_dec, "error on InitializeQTML = %d", (int)i_result );
00689         goto exit_error;
00690     }
00691 #endif
00692 
00693     /* init ComponentDescription */
00694     memset( &desc, 0, sizeof( ComponentDescription ) );
00695     desc.componentType      = FCC( 'i', 'm', 'd', 'c' );
00696     desc.componentSubType   = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00697     desc.componentManufacturer = 0;
00698     desc.componentFlags        = 0;
00699     desc.componentFlagsMask    = 0;
00700 
00701     if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) )
00702     {
00703         msg_Err( p_dec, "cannot find requested component" );
00704         goto exit_error;
00705     }
00706     msg_Dbg( p_dec, "component id=0x%p", prev );
00707 
00708     p_sys->ci =  p_sys->OpenComponent( prev );
00709     msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci );
00710 
00711     memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) );
00712     cres =  p_sys->ImageCodecInitialize( p_sys->ci, &icap );
00713 /*    msg_Dbg( p_dec->p_fifo, "ImageCodecInitialize->%p  size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize); */
00714 
00715     memset( &cinfo, 0, sizeof( CodecInfo ) );
00716     cres =  p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo );
00717     msg_Dbg( p_dec,
00718              "Flags: compr: 0x%lx  decomp: 0x%lx format: 0x%lx\n",
00719              cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags );
00720     msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s\n",
00721              ((unsigned char*)&cinfo.typeName)[0],
00722              ((unsigned char*)&cinfo.typeName)+1 );
00723 
00724     /* make a yuy2 gworld */
00725     p_sys->OutBufferRect.top    = 0;
00726     p_sys->OutBufferRect.left   = 0;
00727     p_sys->OutBufferRect.right  = p_dec->fmt_in.video.i_width;
00728     p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height;
00729 
00730 
00731     /* codec data FIXME use codec not SVQ3 */
00732     msg_Dbg( p_dec, "vide = %d", i_vide  );
00733     id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) );
00734     id->idSize          = sizeof( ImageDescription ) + ( i_vide - 70 );
00735     id->cType           = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00736     id->version         = GetWBE ( p_vide +  0 );
00737     id->revisionLevel   = GetWBE ( p_vide +  2 );
00738     id->vendor          = GetDWBE( p_vide +  4 );
00739     id->temporalQuality = GetDWBE( p_vide +  8 );
00740     id->spatialQuality  = GetDWBE( p_vide + 12 );
00741     id->width           = GetWBE ( p_vide + 16 );
00742     id->height          = GetWBE ( p_vide + 18 );
00743     id->hRes            = GetDWBE( p_vide + 20 );
00744     id->vRes            = GetDWBE( p_vide + 24 );
00745     id->dataSize        = GetDWBE( p_vide + 28 );
00746     id->frameCount      = GetWBE ( p_vide + 32 );
00747     memcpy( &id->name, p_vide + 34, 32 );
00748     id->depth           = GetWBE ( p_vide + 66 );
00749     id->clutID          = GetWBE ( p_vide + 68 );
00750     if( i_vide > 70 )
00751     {
00752         memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 );
00753     }
00754 
00755     msg_Dbg( p_dec, "idSize=%ld ver=%d rev=%d vendor=%ld tempQ=%d "
00756              "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d frameCount=%d clutID=%d",
00757              id->idSize, id->version, id->revisionLevel, id->vendor,
00758              (int)id->temporalQuality, (int)id->spatialQuality,
00759              id->width, id->height,
00760              (int)id->hRes, (int)id->vRes,
00761              (int)id->dataSize,
00762              id->frameCount,
00763              id->clutID );
00764 
00765     p_sys->framedescHandle =
00766         (ImageDescriptionHandle) p_sys->NewHandleClear( id->idSize );
00767     memcpy( *p_sys->framedescHandle, id, id->idSize );
00768 
00769     p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 );
00770 
00771     i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld,
00772                                           /*pixel format of new GWorld==YUY2 */
00773                                           kYUVSPixelFormat,
00774                                           /* we should benchmark if yvu9 is
00775                                            * faster for svq3, too */
00776                                           &p_sys->OutBufferRect,
00777                                           0, 0, 0,
00778                                           p_sys->plane,
00779                                           p_dec->fmt_in.video.i_width * 2 );
00780 
00781     msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld\n",
00782              65536 - ( i_result&0xffff ) );
00783 
00784     memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) );
00785     p_sys->decpar.imageDescription = p_sys->framedescHandle;
00786     p_sys->decpar.startLine        = 0;
00787     p_sys->decpar.stopLine         = ( **p_sys->framedescHandle ).height;
00788     p_sys->decpar.frameNumber      = 1;
00789     p_sys->decpar.matrixFlags      = 0;
00790     p_sys->decpar.matrixType       = 0;
00791     p_sys->decpar.matrix           = 0;
00792     p_sys->decpar.capabilities     = &p_sys->codeccap;
00793     p_sys->decpar.accuracy         = codecNormalQuality;
00794     p_sys->decpar.srcRect          = p_sys->OutBufferRect;
00795     p_sys->decpar.transferMode     = srcCopy;
00796     p_sys->decpar.dstPixMap        = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap;  */
00797 
00798     cres =  p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar );
00799     msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X\n",
00800              (int)cres );
00801 
00802     p_dec->fmt_out.i_codec = VLC_FOURCC( 'Y', 'U', 'Y', '2' );
00803     p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
00804     p_dec->fmt_out.video.i_height= p_dec->fmt_in.video.i_height;
00805     p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_in.video.i_width / p_dec->fmt_in.video.i_height;
00806 
00807 
00808     vlc_mutex_unlock( lockval.p_address );
00809     return VLC_SUCCESS;
00810 
00811 exit_error:
00812 #ifdef LOADER
00813     Restore_LDT_Keeper( p_sys->ldt_fs );
00814 #endif
00815     vlc_mutex_unlock( lockval.p_address );
00816 
00817 #endif /* !WIN32 */
00818 
00819     return VLC_EGENERIC;
00820 }
00821 
00822 #ifndef WIN32
00823 /*****************************************************************************
00824  * DecodeVideo:
00825  *****************************************************************************/
00826 static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
00827 {
00828     decoder_sys_t *p_sys = p_dec->p_sys;
00829     block_t       *p_block;
00830     picture_t     *p_pic;
00831     mtime_t       i_pts;
00832 
00833     ComponentResult cres;
00834 
00835 #ifdef LOADER
00836     /* We must do open and close in the same thread (unless we do
00837      * Setup_LDT_Keeper in the main thread before all others */
00838     if( p_sys == NULL )
00839     {
00840         if( OpenVideo( p_dec ) )
00841         {
00842             /* Fatal */
00843             p_dec->b_error = VLC_TRUE;
00844             return NULL;
00845         }
00846         p_sys = p_dec->p_sys;
00847     }
00848 #endif
00849 
00850     if( pp_block == NULL || *pp_block == NULL )
00851     {
00852         return NULL;
00853     }
00854     p_block = *pp_block;
00855     *pp_block = NULL;
00856 
00857     i_pts = p_block->i_pts ? p_block->i_pts : p_block->i_dts;
00858 
00859     if( i_pts < mdate() )
00860     {
00861         p_sys->i_late++;
00862     }
00863     else
00864     {
00865         p_sys->i_late = 0;
00866     }
00867 
00868     if( p_sys->i_late > 10 )
00869     {
00870         msg_Dbg( p_dec, "too late buffer -> dropped" );
00871         block_Release( p_block );
00872         return NULL;
00873     }
00874 
00875     if( ( p_pic = p_dec->pf_vout_buffer_new( p_dec ) ) )
00876     {
00877         vlc_value_t     lockval;
00878 
00879         p_sys->decpar.data                  = p_block->p_buffer;
00880         p_sys->decpar.bufferSize            = p_block->i_buffer;
00881         (**p_sys->framedescHandle).dataSize = p_block->i_buffer;
00882 
00883         var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
00884         vlc_mutex_lock( lockval.p_address );
00885         cres = p_sys->ImageCodecBandDecompress( p_sys->ci, &p_sys->decpar );
00886         vlc_mutex_unlock( lockval.p_address );
00887 
00888         ++p_sys->decpar.frameNumber;
00889 
00890         if( cres &0xFFFF )
00891         {
00892             msg_Dbg( p_dec, "quicktime_video: ImageCodecBandDecompress"
00893                      " cres=0x%X (-0x%X) %d :(\n",
00894                      (int)cres,(int)-cres, (int)cres );
00895         }
00896 
00897         memcpy( p_pic->p[0].p_pixels, p_sys->plane,
00898                 p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 2 );
00899         p_pic->date = i_pts;
00900     }
00901     block_Release( p_block );
00902 
00903     return p_pic;
00904 }
00905 #endif /* !WIN32 */
00906 
00907 /*****************************************************************************
00908  * QTAudioInit:
00909  *****************************************************************************/
00910 static int QTAudioInit( decoder_t *p_dec )
00911 {
00912     decoder_sys_t *p_sys = p_dec->p_sys;
00913 
00914 #ifdef SYS_DARWIN
00915     p_sys->SoundConverterOpen       = (void*)SoundConverterOpen;
00916     p_sys->SoundConverterClose      = (void*)SoundConverterClose;
00917     p_sys->SoundConverterSetInfo    = (void*)SoundConverterSetInfo;
00918     p_sys->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes;
00919     p_sys->SoundConverterConvertBuffer  = (void*)SoundConverterConvertBuffer;
00920     p_sys->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion;
00921     p_sys->SoundConverterEndConversion  = (void*)SoundConverterEndConversion;
00922 #else
00923 
00924 #ifdef LOADER
00925     p_sys->ldt_fs = Setup_LDT_Keeper();
00926 #endif /* LOADER */
00927 
00928     p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
00929     if( p_sys->qtml == NULL )
00930     {
00931         msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
00932         return VLC_EGENERIC;
00933     }
00934 
00935     p_sys->InitializeQTML               = (void *)GetProcAddress( p_sys->qtml, "InitializeQTML" );
00936     p_sys->TerminateQTML                = (void *)GetProcAddress( p_sys->qtml, "TerminateQTML" );
00937     p_sys->SoundConverterOpen           = (void *)GetProcAddress( p_sys->qtml, "SoundConverterOpen" );
00938     p_sys->SoundConverterClose          = (void *)GetProcAddress( p_sys->qtml, "SoundConverterClose" );
00939     p_sys->SoundConverterSetInfo        = (void *)GetProcAddress( p_sys->qtml, "SoundConverterSetInfo" );
00940     p_sys->SoundConverterGetBufferSizes = (void *)GetProcAddress( p_sys->qtml, "SoundConverterGetBufferSizes" );
00941     p_sys->SoundConverterConvertBuffer  = (void *)GetProcAddress( p_sys->qtml, "SoundConverterConvertBuffer" );
00942     p_sys->SoundConverterEndConversion  = (void *)GetProcAddress( p_sys->qtml, "SoundConverterEndConversion" );
00943     p_sys->SoundConverterBeginConversion= (void *)GetProcAddress( p_sys->qtml, "SoundConverterBeginConversion");
00944 
00945     if( p_sys->InitializeQTML == NULL )
00946     {
00947         msg_Err( p_dec, "failed getting proc address InitializeQTML" );
00948         return VLC_EGENERIC;
00949     }
00950     if( p_sys->SoundConverterOpen == NULL ||
00951         p_sys->SoundConverterClose == NULL ||
00952         p_sys->SoundConverterSetInfo == NULL ||
00953         p_sys->SoundConverterGetBufferSizes == NULL ||
00954         p_sys->SoundConverterConvertBuffer == NULL ||
00955         p_sys->SoundConverterEndConversion == NULL ||
00956         p_sys->SoundConverterBeginConversion == NULL )
00957     {
00958         msg_Err( p_dec, "failed getting proc address" );
00959         return VLC_EGENERIC;
00960     }
00961 
00962     msg_Dbg( p_dec, "Standard init done" );
00963 #endif /* else SYS_DARWIN */
00964 
00965     return VLC_SUCCESS;
00966 }
00967 
00968 #ifndef WIN32
00969 /*****************************************************************************
00970  * QTVideoInit:
00971  *****************************************************************************/
00972 static int QTVideoInit( decoder_t *p_dec )
00973 {
00974     decoder_sys_t *p_sys = p_dec->p_sys;
00975 
00976 #ifdef SYS_DARWIN
00977     p_sys->FindNextComponent        = (void*)FindNextComponent;
00978     p_sys->OpenComponent            = (void*)OpenComponent;
00979     p_sys->ImageCodecInitialize     = (void*)ImageCodecInitialize;
00980     p_sys->ImageCodecGetCodecInfo   = (void*)ImageCodecGetCodecInfo;
00981     p_sys->ImageCodecPreDecompress  = (void*)ImageCodecPreDecompress;
00982     p_sys->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress;
00983     p_sys->GetGWorldPixMap          = (void*)GetGWorldPixMap;
00984     p_sys->QTNewGWorldFromPtr       = (void*)QTNewGWorldFromPtr;
00985     p_sys->NewHandleClear           = (void*)NewHandleClear;
00986 #else
00987 
00988 #ifdef LOADER
00989     p_sys->ldt_fs = Setup_LDT_Keeper();
00990 #endif /* LOADER */
00991     p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
00992     if( p_sys->qtml == NULL )
00993     {
00994         msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
00995         return VLC_EGENERIC;
00996     }
00997     msg_Dbg( p_dec, "qtmlClient.dll loaded" );
00998 
00999     /* (void*) to shut up gcc */
01000     p_sys->InitializeQTML           = (void*)GetProcAddress( p_sys->qtml, "InitializeQTML" );
01001     p_sys->FindNextComponent        = (void*)GetProcAddress( p_sys->qtml, "FindNextComponent" );
01002     p_sys->OpenComponent            = (void*)GetProcAddress( p_sys->qtml, "OpenComponent" );
01003     p_sys->ImageCodecInitialize     = (void*)GetProcAddress( p_sys->qtml, "ImageCodecInitialize" );
01004     p_sys->ImageCodecGetCodecInfo   = (void*)GetProcAddress( p_sys->qtml, "ImageCodecGetCodecInfo" );
01005     p_sys->ImageCodecPreDecompress  = (void*)GetProcAddress( p_sys->qtml, "ImageCodecPreDecompress" );
01006     p_sys->ImageCodecBandDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecBandDecompress" );
01007     p_sys->GetGWorldPixMap          = (void*)GetProcAddress( p_sys->qtml, "GetGWorldPixMap" );
01008     p_sys->QTNewGWorldFromPtr       = (void*)GetProcAddress( p_sys->qtml, "QTNewGWorldFromPtr" );
01009     p_sys->NewHandleClear           = (void*)GetProcAddress( p_sys->qtml, "NewHandleClear" );
01010 
01011     if( p_sys->InitializeQTML == NULL )
01012     {
01013         msg_Dbg( p_dec, "failed getting proc address InitializeQTML" );
01014         return VLC_EGENERIC;
01015     }
01016     if( p_sys->FindNextComponent == NULL ||
01017         p_sys->OpenComponent == NULL ||
01018         p_sys->ImageCodecInitialize == NULL ||
01019         p_sys->ImageCodecGetCodecInfo == NULL ||
01020         p_sys->ImageCodecPreDecompress == NULL ||
01021         p_sys->ImageCodecBandDecompress == NULL ||
01022         p_sys->GetGWorldPixMap == NULL ||
01023         p_sys->QTNewGWorldFromPtr == NULL ||
01024         p_sys->NewHandleClear == NULL )
01025     {
01026         msg_Err( p_dec, "failed getting proc address" );
01027         return VLC_EGENERIC;
01028     }
01029 #endif /* SYS_DARWIN */
01030 
01031     return VLC_SUCCESS;
01032 }
01033 #endif /* !WIN32 */

Generated on Tue Dec 20 10:14:29 2005 for vlc-0.8.4a by  doxygen 1.4.2