quicktime.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:36k
源码类别:

多媒体

开发平台:

MultiPlatform

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