Commit c5bc2448 authored by Laurent Aimar's avatar Laurent Aimar

* quicktime: ported to the new API, fix compilation with w32dll loader.

    -> but untested under OS X and win32.
parent 7b8e8730
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* quicktime.c: a quicktime decoder that uses the QT library/dll * quicktime.c: a quicktime decoder that uses the QT library/dll
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: quicktime.c,v 1.15 2003/11/22 23:39:14 fenrir Exp $ * $Id: quicktime.c,v 1.16 2003/11/23 03:41:58 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir at via.ecp.fr> * Authors: Laurent Aimar <fenrir at via.ecp.fr>
* Derk-Jan Hartman <thedj at users.sf.net> * Derk-Jan Hartman <thedj at users.sf.net>
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#include <vlc/vout.h> #include <vlc/vout.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include "codecs.h"
#ifdef SYS_DARWIN #ifdef SYS_DARWIN
#include <QuickTime/QuickTimeComponents.h> #include <QuickTime/QuickTimeComponents.h>
#include <QuickTime/Movies.h> #include <QuickTime/Movies.h>
...@@ -40,7 +38,7 @@ ...@@ -40,7 +38,7 @@
#endif #endif
/* for windows do we require Quicktime compents header? */ /* for windows do we require Quicktime compents header? */
#define LOADER 1
#ifdef LOADER #ifdef LOADER
#include "w32dll/loader/qtx/qtxsdk/components.h" #include "w32dll/loader/qtx/qtxsdk/components.h"
#include "w32dll/loader/wine/windef.h" #include "w32dll/loader/wine/windef.h"
...@@ -52,34 +50,40 @@ int WINAPI FreeLibrary(HMODULE); ...@@ -52,34 +50,40 @@ int WINAPI FreeLibrary(HMODULE);
#endif #endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenDecoder ( vlc_object_t * );
static int RunDecoderAudio( decoder_fifo_t * );
static int RunDecoderVideo( decoder_fifo_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * );
static void Close( vlc_object_t * );
vlc_module_begin(); vlc_module_begin();
set_description( _("QuickTime library decoder") ); set_description( _("QuickTime library decoder") );
set_capability( "decoder", 10 ); set_capability( "decoder", 10 );
set_callbacks( OpenDecoder, NULL ); set_callbacks( Open, Close );
/* create a mutex */ /* create a mutex */
var_Create( p_module->p_libvlc, "qt_mutex", VLC_VAR_MUTEX ); var_Create( p_module->p_libvlc, "qt_mutex", VLC_VAR_MUTEX );
vlc_module_end(); vlc_module_end();
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenAudio( decoder_t * );
static int OpenVideo( decoder_t * );
static aout_buffer_t *DecodeAudio( decoder_t *, block_t ** );
static picture_t *DecodeVideo( decoder_t *, block_t ** );
#define FCC( a, b , c, d ) \ #define FCC( a, b , c, d ) \
((uint32_t)( ((a)<<24)|((b)<<16)|((c)<<8)|(d))) ((uint32_t)( ((a)<<24)|((b)<<16)|((c)<<8)|(d)))
#ifndef SYS_DARWIN #ifndef SYS_DARWIN
typedef struct OpaqueSoundConverter* SoundConverter; typedef struct OpaqueSoundConverter* SoundConverter;
#ifndef LOADER
typedef long OSType; typedef long OSType;
typedef int OSErr; typedef int OSErr;
#endif
typedef unsigned long UnsignedFixed; typedef unsigned long UnsignedFixed;
typedef uint8_t Byte; typedef uint8_t Byte;
...@@ -96,11 +100,8 @@ typedef struct SoundComponentData { ...@@ -96,11 +100,8 @@ typedef struct SoundComponentData {
#endif /* SYS_DARWIN */ #endif /* SYS_DARWIN */
typedef struct struct decoder_sys_t
{ {
/* Input properties */
decoder_fifo_t *p_fifo;
/* library */ /* library */
#ifndef SYS_DARWIN #ifndef SYS_DARWIN
#ifdef LOADER #ifdef LOADER
...@@ -112,6 +113,7 @@ typedef struct ...@@ -112,6 +113,7 @@ typedef struct
OSErr (*TerminateQTML) ( void ); OSErr (*TerminateQTML) ( void );
#endif /* SYS_DARWIN */ #endif /* SYS_DARWIN */
/* Audio */
int (*SoundConverterOpen) ( const SoundComponentData *, int (*SoundConverterOpen) ( const SoundComponentData *,
const SoundComponentData *, const SoundComponentData *,
SoundConverter* ); SoundConverter* );
...@@ -133,38 +135,7 @@ typedef struct ...@@ -133,38 +135,7 @@ typedef struct
unsigned int InFrameSize; unsigned int InFrameSize;
unsigned int OutFrameSize; unsigned int OutFrameSize;
/* Output properties */ /* Video */
aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t output_format;
audio_date_t date;
mtime_t pts;
/* buffer */
unsigned int i_buffer;
unsigned int i_buffer_size;
uint8_t *p_buffer;
uint8_t buffer_out[1000000]; /* FIXME */
} adec_thread_t;
#ifndef WIN32
typedef struct
{
/* Input properties */
decoder_fifo_t *p_fifo;
/* library */
#ifndef SYS_DARWIN
#ifdef LOADER
ldt_fs_t *ldt_fs;
#endif /* LOADER */
HMODULE qtml;
OSErr (*InitializeQTML) ( long flags );
#endif /* SYS_DARWIN */
Component (*FindNextComponent) Component (*FindNextComponent)
( Component prev, ComponentDescription* desc ); ( Component prev, ComponentDescription* desc );
...@@ -191,8 +162,7 @@ typedef struct ...@@ -191,8 +162,7 @@ typedef struct
CTabHandle cTable, /*GDHandle*/ void *aGDevice, /*unused*/ CTabHandle cTable, /*GDHandle*/ void *aGDevice, /*unused*/
GWorldFlags flags, void *baseAddr, long rowBytes ); GWorldFlags flags, void *baseAddr, long rowBytes );
OSErr (*NewHandleClear) OSErr (*NewHandleClear)( Size byteCount );
( Size byteCount );
ComponentInstance ci; ComponentInstance ci;
Rect OutBufferRect; /* the dimensions of our GWorld */ Rect OutBufferRect; /* the dimensions of our GWorld */
...@@ -206,16 +176,22 @@ typedef struct ...@@ -206,16 +176,22 @@ typedef struct
/* Output properties */ /* Output properties */
vout_thread_t * p_vout;
uint8_t * plane; uint8_t * plane;
mtime_t pts; mtime_t pts;
audio_date_t date;
int i_late; /* video */
/* buffer */ /* buffer */
unsigned int i_buffer; unsigned int i_buffer;
unsigned int i_buffer_size;
uint8_t *p_buffer; uint8_t *p_buffer;
} vdec_thread_t; /* Audio only */
#endif uint8_t out_buffer[1000000]; /* FIXME */
int i_out_frames;
int i_out;
};
static int pi_channels_maps[6] = static int pi_channels_maps[6] =
{ {
...@@ -228,52 +204,20 @@ static int pi_channels_maps[6] = ...@@ -228,52 +204,20 @@ static int pi_channels_maps[6] =
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
}; };
static int QTAudioInit( decoder_t * );
static int GetPESData( uint8_t *p_buf, int i_max, pes_packet_t *p_pes ) static int QTVideoInit( decoder_t * );
{
int i_copy;
int i_count;
data_packet_t *p_data;
i_count = 0;
p_data = p_pes->p_first;
while( p_data != NULL && i_count < i_max )
{
i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
i_max - i_count );
if( i_copy > 0 )
{
memcpy( p_buf,
p_data->p_payload_start,
i_copy );
}
p_data = p_data->p_next;
i_count += i_copy;
p_buf += i_copy;
}
if( i_count < i_max )
{
memset( p_buf, 0, i_max - i_count );
}
return( i_count );
}
/***************************************************************************** /*****************************************************************************
* OpenDecoder: probe the decoder and return score * Open: probe the decoder and return score
***************************************************************************** *****************************************************************************
* Tries to launch a decoder and return score so that the interface is able * Tries to launch a decoder and return score so that the interface is able
* to choose. * to choose.
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t*)p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_dec->p_fifo->i_fourcc ) switch( p_dec->fmt_in.i_codec )
{ {
case VLC_FOURCC('S','V','Q','3'): /* Sorenson v3 */ case VLC_FOURCC('S','V','Q','3'): /* Sorenson v3 */
/* case VLC_FOURCC('S','V','Q','1'): Sorenson v1 /* case VLC_FOURCC('S','V','Q','1'): Sorenson v1
...@@ -283,8 +227,13 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -283,8 +227,13 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('r','l','e',' '): /* QuickTime animation (RLE) */ case VLC_FOURCC('r','l','e',' '): /* QuickTime animation (RLE) */
case VLC_FOURCC('r','p','z','a'): /* QuickTime Apple Video */ case VLC_FOURCC('r','p','z','a'): /* QuickTime Apple Video */
case VLC_FOURCC('a','z','p','r'): /* QuickTime animation (RLE) */ case VLC_FOURCC('a','z','p','r'): /* QuickTime animation (RLE) */
p_dec->pf_run = RunDecoderVideo; #ifdef LOADER
p_dec->p_sys = NULL;
p_dec->pf_decode_video = DecodeVideo;
return VLC_SUCCESS; return VLC_SUCCESS;
#else
return OpenVideo( p_dec );
#endif
case VLC_FOURCC('s','a','m','r'): /* 3GPP AMR audio */ case VLC_FOURCC('s','a','m','r'): /* 3GPP AMR audio */
case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */ case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */
...@@ -307,68 +256,89 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -307,68 +256,89 @@ static int OpenDecoder( vlc_object_t *p_this )
case 0x0011: /* DVI IMA */ case 0x0011: /* DVI IMA */
case 0x6D730002: /* Microsoft ADPCM-ACM */ case 0x6D730002: /* Microsoft ADPCM-ACM */
case 0x6D730011: /* DVI Intel IMAADPCM-ACM */ case 0x6D730011: /* DVI Intel IMAADPCM-ACM */
#ifdef LOADER
p_dec->pf_run = RunDecoderAudio; p_dec->p_sys = NULL;
p_dec->pf_decode_audio = DecodeAudio;
return VLC_SUCCESS; return VLC_SUCCESS;
#else
return OpenAudio( p_dec );
#endif
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
/**************************************************************************** /*****************************************************************************
**************************************************************************** * Close:
** *****************************************************************************/
** audio part static void Close( vlc_object_t *p_this )
**
****************************************************************************
****************************************************************************/
static int InitThreadAudio ( adec_thread_t * );
static void DecodeThreadAudio ( adec_thread_t * );
static void EndThreadAudio ( adec_thread_t * );
static int QTAudioInit ( adec_thread_t * );
static int RunDecoderAudio( decoder_fifo_t *p_fifo )
{ {
adec_thread_t *p_dec; decoder_t *p_dec = (decoder_t*)p_this;
vlc_bool_t b_error; decoder_sys_t *p_sys = p_dec->p_sys;
vlc_value_t lockval;
p_dec = malloc( sizeof( adec_thread_t ) ); /* get lock, avoid segfault */
if( !p_dec ) var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
{ vlc_mutex_lock( lockval.p_address );
msg_Err( p_fifo, "out of memory" ); #ifdef SYS_DARWIN
DecoderError( p_fifo ); /* on OS X QT is not threadsafe */
return VLC_EGENERIC; vlc_mutex_lock( &p_dec->p_vlc->quicktime_lock );
} #endif
p_dec->p_fifo = p_fifo;
if( InitThreadAudio( p_dec ) != 0 ) if( p_dec->fmt_out.i_cat == AUDIO_ES )
{ {
DecoderError( p_fifo ); int i_error;
return VLC_EGENERIC; unsigned long ConvertedFrames=0;
} unsigned long ConvertedBytes=0;
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) i_error = p_sys->SoundConverterEndConversion( p_sys->myConverter, NULL,
{ &ConvertedFrames,
DecodeThreadAudio( p_dec ); &ConvertedBytes );
} msg_Dbg( p_dec, "SoundConverterEndConversion => %d", i_error );
i_error = p_sys->SoundConverterClose( p_sys->myConverter );
msg_Dbg( p_dec, "SoundConverterClose => %d", i_error );
if( ( b_error = p_dec->p_fifo->b_error ) ) free( p_sys->p_buffer );
{
DecoderError( p_dec->p_fifo );
} }
else if( p_dec->fmt_out.i_cat == VIDEO_ES )
EndThreadAudio( p_dec );
if( b_error )
{ {
return VLC_EGENERIC; free( p_sys->plane );
} }
return VLC_SUCCESS; #ifndef SYS_DARWIN
FreeLibrary( p_sys->qtml );
msg_Dbg( p_dec, "FreeLibrary ok." );
#endif
#ifdef SYS_DARWIN
ExitMovies();
#endif
#if 0
/* Segfault */
#ifdef LOADER
Restore_LDT_Keeper( p_sys->ldt_fs );
msg_Dbg( p_dec, "Restore_LDT_Keeper" );
#endif
#endif
#ifdef SYS_DARWIN
vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
#endif
vlc_mutex_unlock( lockval.p_address );
free( p_sys );
} }
static int InitThreadAudio( adec_thread_t *p_dec ) /*****************************************************************************
* OpenAudio:
*****************************************************************************/
static int OpenAudio( decoder_t *p_dec )
{ {
decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
vlc_value_t lockval; vlc_value_t lockval;
int i_error; int i_error;
char fcc[4]; char fcc[4];
...@@ -376,69 +346,66 @@ static int InitThreadAudio( adec_thread_t *p_dec ) ...@@ -376,69 +346,66 @@ static int InitThreadAudio( adec_thread_t *p_dec )
unsigned long InputBufferSize = 0; unsigned long InputBufferSize = 0;
unsigned long OutputBufferSize = 0; unsigned long OutputBufferSize = 0;
WAVEFORMATEX *p_wf; memset( p_sys, 0, sizeof( decoder_sys_t ) );
if( !( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) ) p_dec->p_sys = p_sys;
{ p_dec->pf_decode_audio = DecodeAudio;
msg_Err( p_dec->p_fifo, "missing WAVEFORMATEX");
return VLC_EGENERIC; memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
}
memcpy( fcc, &p_dec->p_fifo->i_fourcc, 4 );
/* get lock, avoid segfault */ /* get lock, avoid segfault */
var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval ); var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
vlc_mutex_lock( lockval.p_address ); vlc_mutex_lock( lockval.p_address );
#ifdef SYS_DARWIN
/* on OS X QT is not threadsafe */
vlc_mutex_lock( &p_dec->p_vlc->quicktime_lock );
#endif
#ifdef SYS_DARWIN #ifdef SYS_DARWIN
EnterMovies(); EnterMovies();
#endif #endif
if( QTAudioInit( p_dec ) != VLC_SUCCESS ) if( QTAudioInit( p_dec ) )
{ {
msg_Err( p_dec->p_fifo, "cannot initialize QT"); msg_Err( p_dec, "cannot initialize QT");
goto exit_error; goto exit_error;
} }
#ifndef SYS_DARWIN #ifndef SYS_DARWIN
if( ( i_error = p_dec->InitializeQTML( 6 + 16 ) ) ) if( ( i_error = p_sys->InitializeQTML( 6 + 16 ) ) )
{ {
msg_Dbg( p_dec->p_fifo, "error while InitializeQTML = %d", i_error ); msg_Dbg( p_dec, "error while InitializeQTML = %d", i_error );
goto exit_error; goto exit_error;
} }
#endif #endif
/* input format settings */ /* input format settings */
p_dec->InputFormatInfo.flags = 0; p_sys->InputFormatInfo.flags = 0;
p_dec->InputFormatInfo.sampleCount = 0; p_sys->InputFormatInfo.sampleCount = 0;
p_dec->InputFormatInfo.buffer = NULL; p_sys->InputFormatInfo.buffer = NULL;
p_dec->InputFormatInfo.reserved = 0; p_sys->InputFormatInfo.reserved = 0;
p_dec->InputFormatInfo.numChannels = p_wf->nChannels; p_sys->InputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
p_dec->InputFormatInfo.sampleSize = p_wf->wBitsPerSample; p_sys->InputFormatInfo.sampleSize = p_dec->fmt_in.audio.i_bitspersample;
p_dec->InputFormatInfo.sampleRate = p_wf->nSamplesPerSec; p_sys->InputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate;
p_dec->InputFormatInfo.format = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); p_sys->InputFormatInfo.format = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
/* output format settings */ /* output format settings */
p_dec->OutputFormatInfo.flags = 0; p_sys->OutputFormatInfo.flags = 0;
p_dec->OutputFormatInfo.sampleCount = 0; p_sys->OutputFormatInfo.sampleCount = 0;
p_dec->OutputFormatInfo.buffer = NULL; p_sys->OutputFormatInfo.buffer = NULL;
p_dec->OutputFormatInfo.reserved = 0; p_sys->OutputFormatInfo.reserved = 0;
p_dec->OutputFormatInfo.numChannels = p_wf->nChannels; p_sys->OutputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels;
p_dec->OutputFormatInfo.sampleSize = 16; p_sys->OutputFormatInfo.sampleSize = 16;
p_dec->OutputFormatInfo.sampleRate = p_wf->nSamplesPerSec; p_sys->OutputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate;
p_dec->OutputFormatInfo.format = FCC( 'N', 'O', 'N', 'E' ); p_sys->OutputFormatInfo.format = FCC( 'N', 'O', 'N', 'E' );
#ifdef SYS_DARWIN
/* on OS X QT is not threadsafe */ i_error = p_sys->SoundConverterOpen( &p_sys->InputFormatInfo,
vlc_mutex_lock( &p_dec->p_fifo->p_vlc->quicktime_lock ); &p_sys->OutputFormatInfo,
#endif &p_sys->myConverter );
i_error = p_dec->SoundConverterOpen( &p_dec->InputFormatInfo,
&p_dec->OutputFormatInfo,
&p_dec->myConverter );
if( i_error ) if( i_error )
{ {
msg_Err( p_dec->p_fifo, msg_Err( p_dec, "error while SoundConverterOpen = %d", i_error );
"error while SoundConverterOpen = %d", i_error );
goto exit_error; goto exit_error;
} }
...@@ -448,418 +415,222 @@ static int InitThreadAudio( adec_thread_t *p_dec ) ...@@ -448,418 +415,222 @@ static int InitThreadAudio( adec_thread_t *p_dec )
(void *)true ); (void *)true );
#endif #endif
if( p_wf->cbSize > 36 + 8 ) if( p_dec->fmt_in.i_extra > 36 + 8 )
{ {
i_error = i_error = p_sys->SoundConverterSetInfo( p_sys->myConverter,
p_dec->SoundConverterSetInfo( p_dec->myConverter,
FCC( 'w', 'a', 'v', 'e' ), FCC( 'w', 'a', 'v', 'e' ),
((uint8_t*)&p_wf[1]) + 36 + 8 ); ((uint8_t*)p_dec->fmt_in.p_extra) + 36 + 8 );
msg_Dbg( p_dec->p_fifo,
"error while SoundConverterSetInfo = %d", i_error ); msg_Dbg( p_dec, "error while SoundConverterSetInfo = %d", i_error );
} }
WantedBufferSize = p_dec->OutputFormatInfo.numChannels * WantedBufferSize = p_sys->OutputFormatInfo.numChannels *
p_dec->OutputFormatInfo.sampleRate * 2; p_sys->OutputFormatInfo.sampleRate * 2;
p_dec->FramesToGet = 0; p_sys->FramesToGet = 0;
i_error = p_dec->SoundConverterGetBufferSizes( p_dec->myConverter, i_error = p_sys->SoundConverterGetBufferSizes( p_sys->myConverter,
WantedBufferSize, &p_dec->FramesToGet, WantedBufferSize,
&InputBufferSize, &OutputBufferSize ); &p_sys->FramesToGet,
&InputBufferSize,
&OutputBufferSize );
msg_Dbg( p_dec->p_fifo, "WantedBufferSize=%li InputBufferSize=%li " msg_Dbg( p_dec, "WantedBufferSize=%li InputBufferSize=%li "
"OutputBufferSize=%li FramesToGet=%li", WantedBufferSize, "OutputBufferSize=%li FramesToGet=%li",
InputBufferSize, OutputBufferSize, p_dec->FramesToGet ); WantedBufferSize, InputBufferSize, OutputBufferSize,
p_sys->FramesToGet );
p_dec->InFrameSize = (InputBufferSize + p_dec->FramesToGet - 1 ) / p_sys->InFrameSize = (InputBufferSize + p_sys->FramesToGet - 1 ) /
p_dec->FramesToGet; p_sys->FramesToGet;
p_dec->OutFrameSize = OutputBufferSize / p_dec->FramesToGet; p_sys->OutFrameSize = OutputBufferSize / p_sys->FramesToGet;
msg_Dbg( p_dec->p_fifo, "frame size %d -> %d", msg_Dbg( p_dec, "frame size %d -> %d",
p_dec->InFrameSize, p_dec->OutFrameSize ); p_sys->InFrameSize, p_sys->OutFrameSize );
i_error = p_dec->SoundConverterBeginConversion( p_dec->myConverter ); if( (i_error = p_sys->SoundConverterBeginConversion(p_sys->myConverter)) )
if( i_error )
{ {
msg_Err( p_dec->p_fifo, msg_Err( p_dec,
"error while SoundConverterBeginConversion = %d", i_error ); "error while SoundConverterBeginConversion = %d", i_error );
goto exit_error; goto exit_error;
} }
#ifdef SYS_DARWIN
vlc_mutex_unlock( &p_dec->p_fifo->p_vlc->quicktime_lock );
#endif
p_dec->output_format.i_format = AOUT_FMT_S16_NE; es_format_Init( &p_dec->fmt_out, AUDIO_ES, AOUT_FMT_S16_NE );
p_dec->output_format.i_rate = p_dec->OutputFormatInfo.sampleRate; p_dec->fmt_out.audio.i_rate = p_sys->OutputFormatInfo.sampleRate;
p_dec->output_format.i_physical_channels = p_dec->fmt_out.audio.i_channels = p_sys->OutputFormatInfo.numChannels;
p_dec->output_format.i_original_channels = p_dec->fmt_out.audio.i_physical_channels =
pi_channels_maps[p_dec->OutputFormatInfo.numChannels]; p_dec->fmt_out.audio.i_original_channels =
aout_DateInit( &p_dec->date, p_dec->output_format.i_rate ); pi_channels_maps[p_sys->OutputFormatInfo.numChannels];
p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
&p_dec->p_aout, aout_DateInit( &p_sys->date, p_dec->fmt_out.audio.i_rate );
&p_dec->output_format );
if( !p_dec->p_aout_input ) p_sys->i_buffer = 0;
{ p_sys->i_buffer_size = 100*1000;
msg_Err( p_dec->p_fifo, "cannot create aout" ); p_sys->p_buffer = malloc( p_sys->i_buffer_size );
goto exit_error;
}
p_dec->i_buffer = 0; p_sys->i_out = 0;
p_dec->i_buffer_size = 100*1000; p_sys->i_out_frames = 0;
p_dec->p_buffer = malloc( p_dec->i_buffer_size );
#ifdef SYS_DARWIN
vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
#endif
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
return VLC_SUCCESS; return VLC_SUCCESS;
exit_error: exit_error:
#ifdef LOADER #ifdef LOADER
Restore_LDT_Keeper( p_dec->ldt_fs ); Restore_LDT_Keeper( p_sys->ldt_fs );
#endif
#ifdef SYS_DARWIN
vlc_mutex_unlock( &p_dec->p_vlc->quicktime_lock );
#endif #endif
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
static void DecodeThreadAudio( adec_thread_t *p_dec ) /*****************************************************************************
* DecodeAudio:
*****************************************************************************/
static aout_buffer_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
{ {
pes_packet_t *p_pes; decoder_sys_t *p_sys = p_dec->p_sys;
vlc_value_t lockval; vlc_value_t lockval;
block_t *p_block;
int i_error; int i_error;
var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval ); #ifdef LOADER
/* We must do open and close in the same thread (unless we do
input_ExtractPES( p_dec->p_fifo, &p_pes ); * Setup_LDT_Keeper in the main thread before all others */
if( !p_pes ) if( p_sys == NULL )
{
if( OpenAudio( p_dec ) )
{ {
msg_Err( p_dec->p_fifo, "cannot get PES" ); /* Fatal */
p_dec->p_fifo->b_error = 1; p_dec->b_error = VLC_TRUE;
return; return NULL;
} }
p_dec->pts = p_pes->i_pts; p_sys = p_dec->p_sys;
}
#endif
if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() ) if( pp_block == NULL || *pp_block == NULL )
{ {
return NULL;
}
p_block = *pp_block;
if( p_dec->i_buffer_size < p_dec->i_buffer + p_pes->i_pes_size ) if( p_sys->i_out_frames > 0 && p_sys->i_out >= p_sys->i_out_frames )
{ {
p_dec->i_buffer_size = p_dec->i_buffer + p_pes->i_pes_size + 1024; /* Ask new data */
p_dec->p_buffer = realloc( p_dec->p_buffer, p_sys->i_out = 0;
p_dec->i_buffer_size ); p_sys->i_out_frames = 0;
*pp_block = NULL;
return NULL;
} }
GetPESData( &p_dec->p_buffer[p_dec->i_buffer], if( p_sys->i_out_frames <= 0 )
p_dec->i_buffer_size - p_dec->i_buffer, p_pes ); {
p_dec->i_buffer += p_pes->i_pes_size; if( ( p_sys->pts = p_block->i_pts ) < mdate() )
{
block_Release( p_block );
*pp_block = NULL;
return NULL;
}
if( p_dec->i_buffer > p_dec->InFrameSize ) /* Append data */
if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
{ {
int i_frames = p_dec->i_buffer / p_dec->InFrameSize; p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer + 1024;
p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
}
memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer,
p_block->i_buffer );
p_sys->i_buffer += p_block->i_buffer;
if( p_sys->i_buffer > p_sys->InFrameSize )
{
int i_frames = p_sys->i_buffer / p_sys->InFrameSize;
long i_out_frames, i_out_bytes; long i_out_frames, i_out_bytes;
/* enough data */
var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
vlc_mutex_lock( lockval.p_address ); vlc_mutex_lock( lockval.p_address );
i_error = p_dec->SoundConverterConvertBuffer( p_dec->myConverter, i_error = p_sys->SoundConverterConvertBuffer( p_sys->myConverter,
p_dec->p_buffer, p_sys->p_buffer,
i_frames, i_frames,
p_dec->buffer_out, p_sys->out_buffer,
&i_out_frames, &i_out_frames,
&i_out_bytes ); &i_out_bytes );
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
/* /*
msg_Dbg( p_dec->p_fifo, msg_Dbg( p_dec, "decoded %d frames -> %ld frames (error=%d)",
"decoded %d frames -> %ld frames (error=%d)",
i_frames, i_out_frames, i_error ); i_frames, i_out_frames, i_error );
msg_Dbg( p_dec->p_fifo, "decoded %ld frames = %ld bytes", msg_Dbg( p_dec, "decoded %ld frames = %ld bytes",
i_out_frames, i_out_bytes ); i_out_frames, i_out_bytes );
*/ */
p_dec->i_buffer -= i_frames * p_dec->InFrameSize; p_sys->i_buffer -= i_frames * p_sys->InFrameSize;
if( p_dec->i_buffer > 0 ) if( p_sys->i_buffer > 0 )
{ {
memmove( &p_dec->p_buffer[0], memmove( &p_sys->p_buffer[0],
&p_dec->p_buffer[i_frames * p_dec->InFrameSize], &p_sys->p_buffer[i_frames * p_sys->InFrameSize],
p_dec->i_buffer ); p_sys->i_buffer );
} }
if( !i_error && i_out_frames > 0 ) if( p_sys->pts != 0 &&
{ p_sys->pts != aout_DateGet( &p_sys->date ) )
aout_buffer_t *p_aout_buffer;
uint8_t *p_buff = p_dec->buffer_out;
/*msg_Dbg( p_dec->p_fifo, "pts=%lld date=%lld dateget=%lld",
p_dec->pts, mdate(), aout_DateGet( &p_dec->date ) );*/
if( p_dec->pts != 0 &&
p_dec->pts != aout_DateGet( &p_dec->date ) )
{ {
aout_DateSet( &p_dec->date, p_dec->pts ); aout_DateSet( &p_sys->date, p_sys->pts );
} }
else if( !aout_DateGet( &p_dec->date ) ) else if( !aout_DateGet( &p_sys->date ) )
{ {
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes ); return NULL;
return;
} }
while( i_out_frames > 0 ) if( !i_error && i_out_frames > 0 )
{
int i_frames;
i_frames = __MIN( i_out_frames, 1000 );
p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
p_dec->p_aout_input,
i_frames );
if( !p_aout_buffer )
{
msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
p_dec->p_fifo->b_error = 1;
return;
}
p_aout_buffer->start_date = aout_DateGet( &p_dec->date );
p_aout_buffer->end_date = aout_DateIncrement( &p_dec->date,
i_frames );
memcpy( p_aout_buffer->p_buffer,
p_buff,
p_aout_buffer->i_nb_bytes );
/*
msg_Dbg( p_dec->p_fifo,
"==> start=%lld end=%lld date=%lld",
p_aout_buffer->start_date,
p_aout_buffer->end_date, mdate() );
*/
aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input,
p_aout_buffer );
/*
msg_Dbg( p_dec->p_fifo, "s1=%d s2=%d", i_framesperchannels,
p_aout_buffer->i_nb_samples );
msg_Dbg( p_dec->p_fifo, "i_nb_bytes=%d i_nb_samples*4=%d",
p_aout_buffer->i_nb_bytes,
p_aout_buffer->i_nb_samples * 4 );
*/
p_buff += i_frames * 4;
i_out_frames -= i_frames;
}
}
}
}
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
}
static void EndThreadAudio( adec_thread_t *p_dec )
{
vlc_value_t lockval;
int i_error;
unsigned long ConvertedFrames=0;
unsigned long ConvertedBytes=0;
/* get lock, avoid segfault */
var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval );
vlc_mutex_lock( lockval.p_address );
i_error = p_dec->SoundConverterEndConversion( p_dec->myConverter, NULL,
&ConvertedFrames,
&ConvertedBytes );
msg_Dbg( p_dec->p_fifo, "SoundConverterEndConversion => %d", i_error );
i_error = p_dec->SoundConverterClose( p_dec->myConverter );
msg_Dbg( p_dec->p_fifo, "SoundConverterClose => %d", i_error );
#ifndef SYS_DARWIN
FreeLibrary( p_dec->qtml );
msg_Dbg( p_dec->p_fifo, "FreeLibrary ok." );
#endif
vlc_mutex_unlock( lockval.p_address );
#ifdef LOADER
Restore_LDT_Keeper( p_dec->ldt_fs );
msg_Dbg( p_dec->p_fifo, "Restore_LDT_Keeper" );
#endif
#ifdef SYS_DARWIN
ExitMovies();
#endif
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
}
static int QTAudioInit( adec_thread_t *p_dec )
{
#ifdef SYS_DARWIN
p_dec->SoundConverterOpen = (void*)SoundConverterOpen;
p_dec->SoundConverterClose = (void*)SoundConverterClose;
p_dec->SoundConverterSetInfo = (void*)SoundConverterSetInfo;
p_dec->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes;
p_dec->SoundConverterConvertBuffer = (void*)SoundConverterConvertBuffer;
p_dec->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion;
p_dec->SoundConverterEndConversion = (void*)SoundConverterEndConversion;
#else
#ifdef LOADER
p_dec->ldt_fs = Setup_LDT_Keeper();
#endif /* LOADER */
p_dec->qtml = LoadLibraryA( "qtmlClient.dll" );
if( p_dec->qtml == NULL )
{
msg_Dbg( p_dec->p_fifo, "failed loading qtmlClient.dll" );
return VLC_EGENERIC;
}
p_dec->InitializeQTML =
(void *)GetProcAddress( p_dec->qtml, "InitializeQTML" );
if( p_dec->InitializeQTML == NULL )
{ {
msg_Dbg( p_dec->p_fifo, "failed geting proc address InitializeQTML" ); /* we have others samples */
return VLC_EGENERIC; p_sys->i_out_frames = i_out_frames;
p_sys->i_out = 0;
} }
p_dec->SoundConverterOpen =
(void *)GetProcAddress( p_dec->qtml, "SoundConverterOpen" );
if( p_dec->SoundConverterOpen == NULL )
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterOpen");
return VLC_EGENERIC;
} }
p_dec->SoundConverterClose =
(void *)GetProcAddress( p_dec->qtml, "SoundConverterClose" );
if( p_dec->SoundConverterClose == NULL )
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterClose");
return VLC_EGENERIC;
} }
p_dec->TerminateQTML = if( p_sys->i_out < p_sys->i_out_frames )
(void *)GetProcAddress( p_dec->qtml, "TerminateQTML" );
if( p_dec->TerminateQTML == NULL )
{ {
msg_Dbg( p_dec->p_fifo, "failed getting proc address TerminateQTML"); aout_buffer_t *p_out;
return VLC_EGENERIC; int i_frames = __MIN( p_sys->i_out_frames - p_sys->i_out, 1000 );
}
p_dec->SoundConverterSetInfo = p_out = p_dec->pf_aout_buffer_new( p_dec, i_frames );
(void *)GetProcAddress( p_dec->qtml, "SoundConverterSetInfo" );
if( p_dec->SoundConverterSetInfo == NULL )
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterSetInfo");
return VLC_EGENERIC;
}
p_dec->SoundConverterGetBufferSizes = if( p_out )
(void *)GetProcAddress( p_dec->qtml, "SoundConverterGetBufferSizes" );
if( p_dec->SoundConverterGetBufferSizes == NULL )
{ {
msg_Dbg( p_dec->p_fifo, p_out->start_date = aout_DateGet( &p_sys->date );
"failed getting proc address SoundConverterGetBufferSizes"); p_out->end_date = aout_DateIncrement( &p_sys->date, i_frames );
return VLC_EGENERIC;
}
p_dec->SoundConverterConvertBuffer = memcpy( p_out->p_buffer,
(void *)GetProcAddress( p_dec->qtml, "SoundConverterConvertBuffer" ); &p_sys->out_buffer[2 * p_sys->i_out * p_dec->fmt_out.audio.i_channels],
if( p_dec->SoundConverterConvertBuffer == NULL ) p_out->i_nb_bytes );
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterConvertBuffer" );
return VLC_EGENERIC;
}
p_dec->SoundConverterEndConversion = p_sys->i_out += i_frames;
(void *)GetProcAddress( p_dec->qtml, "SoundConverterEndConversion" );
if( p_dec->SoundConverterEndConversion == NULL )
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterEndConversion" );
return VLC_EGENERIC;
} }
return p_out;
p_dec->SoundConverterBeginConversion =
(void *)GetProcAddress( p_dec->qtml, "SoundConverterBeginConversion");
if( p_dec->SoundConverterBeginConversion == NULL )
{
msg_Dbg( p_dec->p_fifo,
"failed getting proc address SoundConverterBeginConversion" );
return VLC_EGENERIC;
} }
msg_Dbg( p_dec->p_fifo, return NULL;
"Standard init done you may now call supported functions" );
#endif /* else SYS_DARWIN */
return VLC_SUCCESS;
} }
/**************************************************************************** /*****************************************************************************
**************************************************************************** * OpenVideo:
** *****************************************************************************/
** video part static int OpenVideo( decoder_t *p_dec )
**
****************************************************************************
****************************************************************************/
#ifdef WIN32
static int RunDecoderVideo( decoder_fifo_t *p_fifo ){ return VLC_EGENERIC; }
#else
static int InitThreadVideo ( vdec_thread_t * );
static void DecodeThreadVideo ( vdec_thread_t * );
static void EndThreadVideo ( vdec_thread_t * );
static int RunDecoderVideo( decoder_fifo_t *p_fifo )
{ {
vdec_thread_t *p_dec; decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
vlc_bool_t b_error;
p_dec = malloc( sizeof( vdec_thread_t ) );
if( !p_dec )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return VLC_EGENERIC;
}
p_dec->p_fifo = p_fifo;
if( InitThreadVideo( p_dec ) != 0 )
{
DecoderError( p_fifo );
return VLC_EGENERIC;
}
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
{
DecodeThreadVideo( p_dec );
}
if( ( b_error = p_dec->p_fifo->b_error ) )
{
DecoderError( p_dec->p_fifo );
}
EndThreadVideo( p_dec );
if( b_error )
{
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
/*
* InitThreadVideo: load and init library
*
*/
static int InitThreadVideo( vdec_thread_t *p_dec )
{
vlc_value_t lockval; vlc_value_t lockval;
long i_result; long i_result;
ComponentDescription desc; ComponentDescription desc;
...@@ -869,72 +640,43 @@ static int InitThreadVideo( vdec_thread_t *p_dec ) ...@@ -869,72 +640,43 @@ static int InitThreadVideo( vdec_thread_t *p_dec )
CodecInfo cinfo; /* for ImageCodecGetCodecInfo() */ CodecInfo cinfo; /* for ImageCodecGetCodecInfo() */
ImageDescription *id; ImageDescription *id;
BITMAPINFOHEADER *p_bih;
int i_vide;
uint8_t *p_vide;
char fcc[4]; char fcc[4];
int i_vide = p_dec->fmt_in.i_extra;
uint8_t *p_vide = p_dec->fmt_in.p_extra;
if( !( p_bih = (BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader ) ) p_dec->p_sys = p_sys;
{ p_dec->pf_decode_video = DecodeVideo;
msg_Err( p_dec->p_fifo, "missing BITMAPINFOHEADER !!" ); p_sys->i_late = 0;
return VLC_EGENERIC;
} if( i_vide <= 0 )
i_vide = p_bih->biSize - sizeof( BITMAPINFOHEADER );
p_vide = (uint8_t*)&p_bih[1];
if( i_vide <= 0 || p_vide == NULL )
{ {
msg_Err( p_dec->p_fifo, "invalid BITMAPINFOHEADER !!" ); msg_Err( p_dec, "missing extra info" );
free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
memcpy( fcc, &p_dec->p_fifo->i_fourcc, 4 );
msg_Dbg( p_dec->p_fifo, "quicktime_video %4.4s %dx%d", fcc, memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );
p_bih->biWidth, p_bih->biHeight ); msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d",
fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
/* get lock, avoid segfault */ /* get lock, avoid segfault */
var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval ); var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
vlc_mutex_lock( lockval.p_address ); vlc_mutex_lock( lockval.p_address );
#ifdef SYS_DARWIN #ifdef SYS_DARWIN
EnterMovies(); EnterMovies();
#else #endif
#ifdef LOADER
p_dec->ldt_fs = Setup_LDT_Keeper();
#endif /* LOADER */
msg_Dbg( p_dec->p_fifo, "trying to load `qtmlClient.dll'" );
if( !( p_dec->qtml = LoadLibraryA("qtmlClient.dll") ) )
{
msg_Err( p_dec->p_fifo, "cannot load qtmlClient.dll");
goto exit_error;
}
msg_Dbg( p_dec->p_fifo, "qtmlClient.dll loaded" );
/* (void*) to shut up gcc */
p_dec->InitializeQTML = (void*)InitializeQTML;
#endif /* SYS_DARWIN */
p_dec->FindNextComponent = (void*)FindNextComponent;
p_dec->OpenComponent = (void*)OpenComponent;
p_dec->ImageCodecInitialize = (void*)ImageCodecInitialize;
p_dec->ImageCodecGetCodecInfo = (void*)ImageCodecGetCodecInfo;
p_dec->ImageCodecPreDecompress = (void*)ImageCodecPreDecompress;
p_dec->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress;
p_dec->GetGWorldPixMap = (void*)GetGWorldPixMap;
p_dec->QTNewGWorldFromPtr = (void*)QTNewGWorldFromPtr;
p_dec->NewHandleClear = (void*)NewHandleClear;
#ifndef SYS_DARWIN if( QTVideoInit( p_dec ) )
/* some sanity check */
if( !p_dec->InitializeQTML ||
!p_dec->FindNextComponent ||
!p_dec->OpenComponent ||
!p_dec->ImageCodecBandDecompress )
{ {
msg_Err( p_dec->p_fifo, "error getting qtmlClient.dll symbols"); msg_Err( p_dec, "cannot initialize QT");
goto exit_error; goto exit_error;
} }
if( ( i_result = p_dec->InitializeQTML( 6 + 16 ) ) ) #ifndef SYS_DARWIN
if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) )
{ {
msg_Dbg( p_dec->p_fifo, "error while InitializeQTML = %d", i_result ); msg_Dbg( p_dec, "error while InitializeQTML = %d", (int)i_result );
goto exit_error; goto exit_error;
} }
#endif #endif
...@@ -947,39 +689,38 @@ static int InitThreadVideo( vdec_thread_t *p_dec ) ...@@ -947,39 +689,38 @@ static int InitThreadVideo( vdec_thread_t *p_dec )
desc.componentFlags = 0; desc.componentFlags = 0;
desc.componentFlagsMask = 0; desc.componentFlagsMask = 0;
if( !( prev = p_dec->FindNextComponent( NULL, &desc ) ) ) if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) )
{ {
msg_Err( p_dec->p_fifo, "cannot find requested component" ); msg_Err( p_dec, "cannot find requested component" );
goto exit_error; goto exit_error;
} }
msg_Dbg( p_dec->p_fifo, "component id=0x%p", prev ); msg_Dbg( p_dec, "component id=0x%p", prev );
p_dec->ci = p_dec->OpenComponent( prev ); p_sys->ci = p_sys->OpenComponent( prev );
msg_Dbg( p_dec->p_fifo, "component instance p=0x%p", p_dec->ci ); msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci );
memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) ); memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) );
cres = p_dec->ImageCodecInitialize( p_dec->ci, &icap ); cres = p_sys->ImageCodecInitialize( p_sys->ci, &icap );
/* msg_Dbg( p_dec->p_fifo, "ImageCodecInitialize->%p size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize); */ /* msg_Dbg( p_dec->p_fifo, "ImageCodecInitialize->%p size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize); */
memset( &cinfo, 0, sizeof( CodecInfo ) ); memset( &cinfo, 0, sizeof( CodecInfo ) );
cres = p_dec->ImageCodecGetCodecInfo( p_dec->ci, &cinfo ); cres = p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo );
msg_Dbg( p_dec->p_fifo, msg_Dbg( p_dec,
"Flags: compr: 0x%lx decomp: 0x%lx format: 0x%lx\n", "Flags: compr: 0x%lx decomp: 0x%lx format: 0x%lx\n",
cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags ); cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags );
msg_Dbg( p_dec->p_fifo, "quicktime_video: Codec name: %.*s\n", msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s\n",
((unsigned char*)&cinfo.typeName)[0], ((unsigned char*)&cinfo.typeName)[0],
((unsigned char*)&cinfo.typeName)+1 ); ((unsigned char*)&cinfo.typeName)+1 );
/* make a yuy2 gworld */ /* make a yuy2 gworld */
p_dec->OutBufferRect.top = 0; p_sys->OutBufferRect.top = 0;
p_dec->OutBufferRect.left = 0; p_sys->OutBufferRect.left = 0;
p_dec->OutBufferRect.right = p_bih->biWidth; p_sys->OutBufferRect.right = p_dec->fmt_in.video.i_width;
p_dec->OutBufferRect.bottom = p_bih->biHeight; p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height;
/* codec data FIXME use codec not SVQ3 */ /* codec data FIXME use codec not SVQ3 */
msg_Dbg( p_dec->p_fifo, "vide = %d", i_vide ); msg_Dbg( p_dec, "vide = %d", i_vide );
id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) ); id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) );
id->idSize = sizeof( ImageDescription ) + ( i_vide - 70 ); id->idSize = sizeof( ImageDescription ) + ( i_vide - 70 );
id->cType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); id->cType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
...@@ -1002,7 +743,7 @@ static int InitThreadVideo( vdec_thread_t *p_dec ) ...@@ -1002,7 +743,7 @@ static int InitThreadVideo( vdec_thread_t *p_dec )
memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 ); memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 );
} }
msg_Dbg( p_dec->p_fifo, "idSize=%ld ver=%d rev=%d vendor=%ld tempQ=%d " msg_Dbg( p_dec, "idSize=%ld ver=%d rev=%d vendor=%ld tempQ=%d "
"spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d frameCount=%d clutID=%d", "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d frameCount=%d clutID=%d",
id->idSize, id->version, id->revisionLevel, id->vendor, id->idSize, id->version, id->revisionLevel, id->vendor,
(int)id->temporalQuality, (int)id->spatialQuality, (int)id->temporalQuality, (int)id->spatialQuality,
...@@ -1012,156 +753,266 @@ static int InitThreadVideo( vdec_thread_t *p_dec ) ...@@ -1012,156 +753,266 @@ static int InitThreadVideo( vdec_thread_t *p_dec )
id->frameCount, id->frameCount,
id->clutID ); id->clutID );
p_dec->framedescHandle = p_sys->framedescHandle =
(ImageDescriptionHandle) p_dec->NewHandleClear( id->idSize ); (ImageDescriptionHandle) p_sys->NewHandleClear( id->idSize );
memcpy( *p_dec->framedescHandle, id, id->idSize ); memcpy( *p_sys->framedescHandle, id, id->idSize );
p_dec->plane = malloc( p_bih->biWidth * p_bih->biHeight * 3 ); p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 );
i_result = p_dec->QTNewGWorldFromPtr( &p_dec->OutBufferGWorld, i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld,
/*pixel format of new GWorld==YUY2 */ /*pixel format of new GWorld==YUY2 */
kYUVSPixelFormat, kYUVSPixelFormat,
/* we should benchmark if yvu9 is /* we should benchmark if yvu9 is
* faster for svq3, too */ * faster for svq3, too */
&p_dec->OutBufferRect, &p_sys->OutBufferRect,
0, 0, 0, 0, 0, 0,
p_dec->plane, p_sys->plane,
p_bih->biWidth * 2 ); p_dec->fmt_in.video.i_width * 2 );
msg_Dbg( p_dec->p_fifo, "NewGWorldFromPtr returned:%ld\n", msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld\n",
65536 - ( i_result&0xffff ) ); 65536 - ( i_result&0xffff ) );
memset( &p_dec->decpar, 0, sizeof( CodecDecompressParams ) ); memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) );
p_dec->decpar.imageDescription = p_dec->framedescHandle; p_sys->decpar.imageDescription = p_sys->framedescHandle;
p_dec->decpar.startLine = 0; p_sys->decpar.startLine = 0;
p_dec->decpar.stopLine = ( **p_dec->framedescHandle ).height; p_sys->decpar.stopLine = ( **p_sys->framedescHandle ).height;
p_dec->decpar.frameNumber = 1; p_sys->decpar.frameNumber = 1;
p_dec->decpar.matrixFlags = 0; p_sys->decpar.matrixFlags = 0;
p_dec->decpar.matrixType = 0; p_sys->decpar.matrixType = 0;
p_dec->decpar.matrix = 0; p_sys->decpar.matrix = 0;
p_dec->decpar.capabilities = &p_dec->codeccap; p_sys->decpar.capabilities = &p_sys->codeccap;
p_dec->decpar.accuracy = codecNormalQuality; p_sys->decpar.accuracy = codecNormalQuality;
p_dec->decpar.srcRect = p_dec->OutBufferRect; p_sys->decpar.srcRect = p_sys->OutBufferRect;
p_dec->decpar.transferMode = srcCopy; p_sys->decpar.transferMode = srcCopy;
p_dec->decpar.dstPixMap = **p_dec->GetGWorldPixMap( p_dec->OutBufferGWorld );/*destPixmap; */ p_sys->decpar.dstPixMap = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap; */
cres = p_dec->ImageCodecPreDecompress( p_dec->ci, &p_dec->decpar ); cres = p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar );
msg_Dbg( p_dec->p_fifo, msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X\n",
"quicktime_video: ImageCodecPreDecompress cres=0x%X\n",
(int)cres ); (int)cres );
p_dec->p_vout = vout_Request( p_dec->p_fifo, NULL, p_dec->fmt_out.i_codec = VLC_FOURCC( 'Y', 'U', 'Y', '2' );
p_bih->biWidth, p_bih->biHeight, p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
VLC_FOURCC( 'Y', 'U', 'Y', '2' ), p_dec->fmt_out.video.i_height= p_dec->fmt_in.video.i_height;
VOUT_ASPECT_FACTOR * p_bih->biWidth / p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_in.video.i_width / p_dec->fmt_in.video.i_height;
p_bih->biHeight );
if( !p_dec->p_vout )
{
msg_Err( p_dec->p_fifo, "cannot get a vout" );
goto exit_error;
}
p_dec->i_buffer = 1000*1000;
p_dec->p_buffer = malloc( p_dec->i_buffer );
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
return VLC_SUCCESS; return VLC_SUCCESS;
exit_error: exit_error:
#ifdef LOADER #ifdef LOADER
Restore_LDT_Keeper( p_dec->ldt_fs ); Restore_LDT_Keeper( p_sys->ldt_fs );
#endif #endif
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
static void DecodeThreadVideo( vdec_thread_t *p_dec ) /*****************************************************************************
* DecodeVideo:
*****************************************************************************/
static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
{ {
BITMAPINFOHEADER *p_bih = decoder_sys_t *p_sys = p_dec->p_sys;
(BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader;
pes_packet_t *p_pes; block_t *p_block;
vlc_value_t lockval;
picture_t *p_pic; picture_t *p_pic;
ComponentResult cres; ComponentResult cres;
var_Get( p_dec->p_fifo->p_libvlc, "qt_mutex", &lockval ); #ifdef LOADER
/* We must do open and close in the same thread (unless we do
input_ExtractPES( p_dec->p_fifo, &p_pes ); * Setup_LDT_Keeper in the main thread before all others */
if( !p_pes ) if( p_sys == NULL )
{ {
msg_Err( p_dec->p_fifo, "cannot get PES" ); if( OpenVideo( p_dec ) )
p_dec->p_fifo->b_error = 1;
return;
}
if( p_pes->i_pes_size > p_dec->i_buffer )
{ {
p_dec->i_buffer = 3 * p_pes->i_pes_size / 2; /* Fatal */
free( p_dec->p_buffer ); p_dec->b_error = VLC_TRUE;
p_dec->p_buffer = malloc( p_dec->i_buffer ); return NULL;
}
p_sys = p_dec->p_sys;
} }
#endif
if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() ) if( pp_block == NULL || *pp_block == NULL )
{ {
GetPESData( p_dec->p_buffer, p_dec->i_buffer, p_pes ); return NULL;
}
p_block = *pp_block;
*pp_block = NULL;
while( !(p_pic = vout_CreatePicture( p_dec->p_vout, 0, 0, 0 ) ) ) if( p_block->i_pts < mdate() )
{ {
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) p_sys->i_late++;
}
else
{ {
break; p_sys->i_late = 0;
} }
msleep( VOUT_OUTMEM_SLEEP );
if( p_sys->i_late > 10 )
{
msg_Dbg( p_dec, "too late buffer -> dropped" );
block_Release( p_block );
return NULL;
} }
p_dec->decpar.data = p_dec->p_buffer; if( ( p_pic = p_dec->pf_vout_buffer_new( p_dec ) ) )
p_dec->decpar.bufferSize = p_pes->i_pes_size; {
(**p_dec->framedescHandle).dataSize = p_pes->i_pes_size; vlc_value_t lockval;
p_sys->decpar.data = p_block->p_buffer;
p_sys->decpar.bufferSize = p_block->i_buffer;
(**p_sys->framedescHandle).dataSize = p_block->i_buffer;
var_Get( p_dec->p_libvlc, "qt_mutex", &lockval );
vlc_mutex_lock( lockval.p_address ); vlc_mutex_lock( lockval.p_address );
cres = p_dec->ImageCodecBandDecompress( p_dec->ci, &p_dec->decpar ); cres = p_sys->ImageCodecBandDecompress( p_sys->ci, &p_sys->decpar );
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
++p_dec->decpar.frameNumber; ++p_sys->decpar.frameNumber;
if( cres &0xFFFF ) if( cres &0xFFFF )
{ {
msg_Dbg( p_dec->p_fifo, "quicktime_video: ImageCodecBandDecompress" msg_Dbg( p_dec, "quicktime_video: ImageCodecBandDecompress"
" cres=0x%X (-0x%X) %d :(\n", " cres=0x%X (-0x%X) %d :(\n",
(int)cres,(int)-cres, (int)cres ); (int)cres,(int)-cres, (int)cres );
} }
memcpy( p_pic->p[0].p_pixels, memcpy( p_pic->p[0].p_pixels,
p_dec->plane, p_sys->plane,
p_bih->biWidth * p_bih->biHeight * 2 ); p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 2 );
p_pic->date = p_block->i_pts;
vout_DatePicture( p_dec->p_vout, p_pic, p_pes->i_pts );
vout_DisplayPicture( p_dec->p_vout, p_pic );
} }
block_Release( p_block );
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes ); return p_pic;
} }
static void EndThreadVideo( vdec_thread_t *p_dec ) /*****************************************************************************
* QTAudioInit:
*****************************************************************************/
static int QTAudioInit( decoder_t *p_dec )
{ {
msg_Dbg( p_dec->p_fifo, "QuickTime library video decoder closing" ); decoder_sys_t *p_sys = p_dec->p_sys;
free( p_dec->plane );
vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 );
#ifndef SYS_DARWIN #ifdef SYS_DARWIN
FreeLibrary( p_dec->qtml ); p_sys->SoundConverterOpen = (void*)SoundConverterOpen;
msg_Dbg( p_dec->p_fifo, "FreeLibrary ok." ); p_sys->SoundConverterClose = (void*)SoundConverterClose;
#endif p_sys->SoundConverterSetInfo = (void*)SoundConverterSetInfo;
p_sys->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes;
p_sys->SoundConverterConvertBuffer = (void*)SoundConverterConvertBuffer;
p_sys->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion;
p_sys->SoundConverterEndConversion = (void*)SoundConverterEndConversion;
#else
#ifdef LOADER #ifdef LOADER
Restore_LDT_Keeper( p_dec->ldt_fs ); p_sys->ldt_fs = Setup_LDT_Keeper();
msg_Dbg( p_dec->p_fifo, "Restore_LDT_Keeper" ); #endif /* LOADER */
#endif
p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
if( p_sys->qtml == NULL )
{
msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
return VLC_EGENERIC;
}
p_sys->InitializeQTML = (void *)GetProcAddress( p_sys->qtml, "InitializeQTML" );
p_sys->TerminateQTML = (void *)GetProcAddress( p_sys->qtml, "TerminateQTML" );
p_sys->SoundConverterOpen = (void *)GetProcAddress( p_sys->qtml, "SoundConverterOpen" );
p_sys->SoundConverterClose = (void *)GetProcAddress( p_sys->qtml, "SoundConverterClose" );
p_sys->SoundConverterSetInfo = (void *)GetProcAddress( p_sys->qtml, "SoundConverterSetInfo" );
p_sys->SoundConverterGetBufferSizes = (void *)GetProcAddress( p_sys->qtml, "SoundConverterGetBufferSizes" );
p_sys->SoundConverterConvertBuffer = (void *)GetProcAddress( p_sys->qtml, "SoundConverterConvertBuffer" );
p_sys->SoundConverterEndConversion = (void *)GetProcAddress( p_sys->qtml, "SoundConverterEndConversion" );
p_sys->SoundConverterBeginConversion= (void *)GetProcAddress( p_sys->qtml, "SoundConverterBeginConversion");
if( p_sys->InitializeQTML == NULL )
{
msg_Err( p_dec, "failed geting proc address InitializeQTML" );
return VLC_EGENERIC;
}
if( p_sys->SoundConverterOpen == NULL ||
p_sys->SoundConverterClose == NULL ||
p_sys->SoundConverterSetInfo == NULL ||
p_sys->SoundConverterGetBufferSizes == NULL ||
p_sys->SoundConverterConvertBuffer == NULL ||
p_sys->SoundConverterEndConversion == NULL ||
p_sys->SoundConverterBeginConversion == NULL )
{
msg_Err( p_dec, "failed geting proc address" );
return VLC_EGENERIC;
}
msg_Dbg( p_dec, "Standard init done" );
#endif /* else SYS_DARWIN */
return VLC_SUCCESS;
}
/*****************************************************************************
* QTVideoInit:
*****************************************************************************/
static int QTVideoInit( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
#ifdef SYS_DARWIN #ifdef SYS_DARWIN
ExitMovies(); p_sys->FindNextComponent = (void*)FindNextComponent;
#endif p_sys->OpenComponent = (void*)OpenComponent;
p_sys->ImageCodecInitialize = (void*)ImageCodecInitialize;
p_sys->ImageCodecGetCodecInfo = (void*)ImageCodecGetCodecInfo;
p_sys->ImageCodecPreDecompress = (void*)ImageCodecPreDecompress;
p_sys->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress;
p_sys->GetGWorldPixMap = (void*)GetGWorldPixMap;
p_sys->QTNewGWorldFromPtr = (void*)QTNewGWorldFromPtr;
p_sys->NewHandleClear = (void*)NewHandleClear;
#else
#ifdef LOADER
p_sys->ldt_fs = Setup_LDT_Keeper();
#endif /* LOADER */
p_sys->qtml = LoadLibraryA( "qtmlClient.dll" );
if( p_sys->qtml == NULL )
{
msg_Dbg( p_dec, "failed loading qtmlClient.dll" );
return VLC_EGENERIC;
}
msg_Dbg( p_dec, "qtmlClient.dll loaded" );
/* (void*) to shut up gcc */
p_sys->InitializeQTML = (void*)GetProcAddress( p_sys->qtml, "InitializeQTML" );
p_sys->FindNextComponent = (void*)GetProcAddress( p_sys->qtml, "FindNextComponent" );
p_sys->OpenComponent = (void*)GetProcAddress( p_sys->qtml, "OpenComponent" );
p_sys->ImageCodecInitialize = (void*)GetProcAddress( p_sys->qtml, "ImageCodecInitialize" );
p_sys->ImageCodecGetCodecInfo = (void*)GetProcAddress( p_sys->qtml, "ImageCodecGetCodecInfo" );
p_sys->ImageCodecPreDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecPreDecompress" );
p_sys->ImageCodecBandDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecBandDecompress" );
p_sys->GetGWorldPixMap = (void*)GetProcAddress( p_sys->qtml, "GetGWorldPixMap" );
p_sys->QTNewGWorldFromPtr = (void*)GetProcAddress( p_sys->qtml, "QTNewGWorldFromPtr" );
p_sys->NewHandleClear = (void*)GetProcAddress( p_sys->qtml, "NewHandleClear" );
if( p_sys->InitializeQTML == NULL )
{
msg_Dbg( p_dec, "failed geting proc address InitializeQTML" );
return VLC_EGENERIC;
}
if( p_sys->FindNextComponent == NULL ||
p_sys->OpenComponent == NULL ||
p_sys->ImageCodecInitialize == NULL ||
p_sys->ImageCodecGetCodecInfo == NULL ||
p_sys->ImageCodecPreDecompress == NULL ||
p_sys->ImageCodecBandDecompress == NULL ||
p_sys->GetGWorldPixMap == NULL ||
p_sys->QTNewGWorldFromPtr == NULL ||
p_sys->NewHandleClear == NULL )
{
msg_Err( p_dec, "failed geting proc address" );
return VLC_EGENERIC;
}
#endif /* SYS_DARWIN */
return VLC_SUCCESS;
} }
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment