Commit 7bb574fd authored by Gildas Bazin's avatar Gildas Bazin

* ALL: Introduction of a new api for decoders.
   The final aim of this new api is to make it possible to use the decoders from other modules like the transcoder for instance.
   Only a few decoders have been ported to the new api (a52, libmpeg2, dts, vorbis, theora) so the old api is still supported.

   Don't hold your breath, there is still much work to do before we reach this goal.

* modules/codec/a52.c, libmpeg2., dts.c, vorbis.c, theora.c:
   Converted to the new api.
   Merged the a52 and vorbis packetizers in their respective decoders (removes a lot of code duplication).
   New dts and theora packetizers (merged in their respective decoders).
parent 8fd7c421
dnl Autoconf settings for vlc dnl Autoconf settings for vlc
dnl $Id: configure.ac,v 1.71 2003/08/31 15:55:56 titer Exp $ dnl $Id: configure.ac,v 1.72 2003/09/02 20:19:25 gbazin Exp $
AC_INIT(vlc,0.6.3-cvs) AC_INIT(vlc,0.6.3-cvs)
...@@ -1000,7 +1000,7 @@ if test "${enable_sout}" != "no" ...@@ -1000,7 +1000,7 @@ if test "${enable_sout}" != "no"
then then
AX_ADD_PLUGINS([access_output_dummy access_output_udp access_output_file access_output_http]) AX_ADD_PLUGINS([access_output_dummy access_output_udp access_output_file access_output_http])
AX_ADD_PLUGINS([mux_ts mux_ps mux_avi mux_mp4 mux_asf mux_dummy]) AX_ADD_PLUGINS([mux_ts mux_ps mux_avi mux_mp4 mux_asf mux_dummy])
AX_ADD_PLUGINS([packetizer_mpegaudio packetizer_mpegvideo packetizer_a52]) AX_ADD_PLUGINS([packetizer_mpegaudio packetizer_mpegvideo])
AX_ADD_PLUGINS([packetizer_mpeg4video packetizer_mpeg4audio]) AX_ADD_PLUGINS([packetizer_mpeg4video packetizer_mpeg4audio])
AX_ADD_PLUGINS([packetizer_copy]) AX_ADD_PLUGINS([packetizer_copy])
...@@ -1934,11 +1934,7 @@ if test "${enable_vorbis}" != "no" ...@@ -1934,11 +1934,7 @@ if test "${enable_vorbis}" != "no"
then then
AC_CHECK_HEADERS(vorbis/codec.h, [ AC_CHECK_HEADERS(vorbis/codec.h, [
AX_ADD_PLUGINS([vorbis]) AX_ADD_PLUGINS([vorbis])
AX_ADD_LDFLAGS([vorbis],[-lvorbis -logg]) AX_ADD_LDFLAGS([vorbis],[-lvorbis -logg]) ],[])
if test "${enable_sout}" != "no"; then
AX_ADD_PLUGINS([packetizer_vorbis])
AX_ADD_LDFLAGS([packetizer_vorbis],[-lvorbis -logg])
fi ],[])
fi fi
dnl dnl
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders * input_ext-dec.h: structures exported to the VideoLAN decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_ext-dec.h,v 1.79 2003/03/04 13:21:19 massiot Exp $ * $Id: input_ext-dec.h,v 1.80 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr> * Michel Kaempf <maxx@via.ecp.fr>
...@@ -110,8 +110,29 @@ struct decoder_fifo_t ...@@ -110,8 +110,29 @@ struct decoder_fifo_t
void * p_waveformatex; void * p_waveformatex;
void * p_bitmapinfoheader; void * p_bitmapinfoheader;
decoder_t * p_dec;
};
/*****************************************************************************
* decoder_t
*****************************************************************************
* The decoder descriptor.
*****************************************************************************/
struct decoder_t
{
VLC_COMMON_MEMBERS
/* Module properties */ /* Module properties */
module_t * p_module; module_t * p_module;
decoder_sys_t * p_sys;
int ( * pf_init ) ( decoder_t * );
int ( * pf_decode )( decoder_t *, block_t * );
int ( * pf_end ) ( decoder_t * );
/* Input properties */
decoder_fifo_t * p_fifo; /* stores the PES stream data */
/* Tmp field for old decoder api */
int ( * pf_run ) ( decoder_fifo_t * ); int ( * pf_run ) ( decoder_fifo_t * );
}; };
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* decoder.h: header for vlc decoders * decoder.h: header for vlc decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: decoder.h,v 1.1 2002/06/01 12:31:58 sam Exp $ * $Id: decoder.h,v 1.2 2003/09/02 20:19:25 gbazin Exp $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -34,6 +34,7 @@ extern "C" { ...@@ -34,6 +34,7 @@ extern "C" {
/***************************************************************************** /*****************************************************************************
* Required internal headers * Required internal headers
*****************************************************************************/ *****************************************************************************/
#include "vlc_block.h"
#include "stream_control.h" #include "stream_control.h"
#include "input_ext-dec.h" #include "input_ext-dec.h"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input.h: input modules header for vlc * input.h: input modules header for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: input.h,v 1.1 2002/06/01 12:31:58 sam Exp $ * $Id: input.h,v 1.2 2003/09/02 20:19:25 gbazin Exp $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -34,6 +34,7 @@ extern "C" { ...@@ -34,6 +34,7 @@ extern "C" {
/***************************************************************************** /*****************************************************************************
* Required internal headers * Required internal headers
*****************************************************************************/ *****************************************************************************/
#include "vlc_block.h"
#include "stream_control.h" #include "stream_control.h"
#include "input_ext-intf.h" /* input_thread_s */ #include "input_ext-intf.h" /* input_thread_s */
#include "input_ext-dec.h" /* data_packet_s */ #include "input_ext-dec.h" /* data_packet_s */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* sout.h: video output header for vlc * sout.h: video output header for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: sout.h,v 1.2 2003/05/20 16:20:33 zorglub Exp $ * $Id: sout.h,v 1.3 2003/09/02 20:19:25 gbazin Exp $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -34,6 +34,7 @@ extern "C" { ...@@ -34,6 +34,7 @@ extern "C" {
/***************************************************************************** /*****************************************************************************
* Required internal headers * Required internal headers
*****************************************************************************/ *****************************************************************************/
#include "vlc_block.h"
#include "stream_output.h" #include "stream_output.h"
# ifdef __cplusplus # ifdef __cplusplus
......
/***************************************************************************** /*****************************************************************************
* block.h * vlc_block.h: Data blocks management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: vlc_block.h,v 1.1 2003/08/23 22:49:50 fenrir Exp $ * $Id: vlc_block.h,v 1.2 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -21,9 +21,8 @@ ...@@ -21,9 +21,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef _BLOCK_H #ifndef _VLC_BLOCK_H
#define _BLOCK_H 1 #define _VLC_BLOCK_H 1
/* /*
* block * block
...@@ -108,4 +107,4 @@ VLC_EXPORT( block_t *, block_FifoGet, ( block_fifo_t * ) ); ...@@ -108,4 +107,4 @@ VLC_EXPORT( block_t *, block_FifoGet, ( block_fifo_t * ) );
VLC_EXPORT( block_t *, block_FifoGetFrame, ( block_fifo_t * ) ); VLC_EXPORT( block_t *, block_FifoGetFrame, ( block_fifo_t * ) );
VLC_EXPORT( block_t *, block_FifoShow, ( block_fifo_t * ) ); VLC_EXPORT( block_t *, block_FifoShow, ( block_fifo_t * ) );
#endif #endif /* VLC_BLOCK_H */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.75 2003/08/23 22:49:50 fenrir Exp $ * $Id: vlc_common.h,v 1.76 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -268,6 +268,8 @@ typedef struct slp_session_t slp_session_t;*/ ...@@ -268,6 +268,8 @@ typedef struct slp_session_t slp_session_t;*/
/* Decoders */ /* Decoders */
typedef struct decoder_fifo_t decoder_fifo_t; typedef struct decoder_fifo_t decoder_fifo_t;
typedef struct decoder_t decoder_t;
typedef struct decoder_sys_t decoder_sys_t;
/* Misc */ /* Misc */
typedef struct data_packet_t data_packet_t; typedef struct data_packet_t data_packet_t;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vlc_objects.h: vlc_object_t definition. * vlc_objects.h: vlc_object_t definition.
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: vlc_objects.h,v 1.16 2003/02/23 19:07:02 fenrir Exp $ * $Id: vlc_objects.h,v 1.17 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#define VLC_OBJECT_ITEM (-6) #define VLC_OBJECT_ITEM (-6)
#define VLC_OBJECT_INPUT (-7) #define VLC_OBJECT_INPUT (-7)
#define VLC_OBJECT_DECODER (-8) #define VLC_OBJECT_DECODER (-8)
/* tmp for backward compat */
#define VLC_OBJECT_DECODER_FIFO (-999)
#define VLC_OBJECT_VOUT (-9) #define VLC_OBJECT_VOUT (-9)
#define VLC_OBJECT_AOUT (-10) #define VLC_OBJECT_AOUT (-10)
#define VLC_OBJECT_SOUT (-11) #define VLC_OBJECT_SOUT (-11)
......
...@@ -2,12 +2,11 @@ ...@@ -2,12 +2,11 @@
* a52.c: A/52 basic parser * a52.c: A/52 basic parser
***************************************************************************** *****************************************************************************
* Copyright (C) 2001-2002 VideoLAN * Copyright (C) 2001-2002 VideoLAN
* $Id: a52.c,v 1.22 2003/03/31 22:39:27 massiot Exp $ * $Id: a52.c,v 1.23 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Stphane Borel <stef@via.ecp.fr> * Authors: Stphane Borel <stef@via.ecp.fr>
* Christophe Massiot <massiot@via.ecp.fr> * Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@zoy.org> * Gildas Bazin <gbazin@netcourrier.com>
* Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -34,45 +33,85 @@ ...@@ -34,45 +33,85 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/aout.h> #include <vlc/aout.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#define A52_HEADER_SIZE 7
/***************************************************************************** /*****************************************************************************
* dec_thread_t : decoder thread descriptor * decoder_sys_t : decoder descriptor
*****************************************************************************/ *****************************************************************************/
typedef struct dec_thread_t struct decoder_sys_t
{ {
/* Module mode */
vlc_bool_t b_packetizer;
/* /*
* Thread properties * Input properties
*/ */
vlc_thread_t thread_id; /* id for thread functions */ int i_state;
uint8_t p_header[A52_HEADER_SIZE];
int i_header;
mtime_t pts;
int i_frame_size;
/* /*
* Input properties * Decoder output properties
*/
aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t aout_format;
aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
/*
* Packetizer output properties
*/ */
decoder_fifo_t * p_fifo; /* stores the PES stream data */ sout_packetizer_input_t *p_sout_input;
bit_stream_t bit_stream; sout_format_t sout_format;
sout_buffer_t * p_sout_buffer; /* current sout buffer */
/* /*
* Output properties * Common properties
*/ */
aout_instance_t * p_aout; /* opaque */ uint8_t *p_out_buffer; /* output buffer */
aout_input_t * p_aout_input; /* opaque */ int i_out_buffer; /* position in output buffer */
audio_sample_format_t output_format; audio_date_t end_date;
} dec_thread_t; };
enum {
STATE_NOSYNC,
STATE_PARTIAL_SYNC,
STATE_SYNC,
STATE_HEADER,
STATE_DATA
};
/**************************************************************************** /****************************************************************************
* Local prototypes * Local prototypes
****************************************************************************/ ****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int OpenPacketizer( vlc_object_t * );
static int InitDecoder ( decoder_t * );
static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static void EndThread ( dec_thread_t * ); static int SyncInfo ( const byte_t *, int *, int *, int *,int * );
static int SyncInfo ( const byte_t *, int *, int *, int * ); static int GetOutBuffer ( decoder_t *, uint8_t ** );
static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
static int SendOutBuffer( decoder_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -81,6 +120,11 @@ vlc_module_begin(); ...@@ -81,6 +120,11 @@ vlc_module_begin();
set_description( _("A/52 parser") ); set_description( _("A/52 parser") );
set_capability( "decoder", 100 ); set_capability( "decoder", 100 );
set_callbacks( OpenDecoder, NULL ); set_callbacks( OpenDecoder, NULL );
add_submodule();
set_description( _("A/52 audio packetizer") );
set_capability( "packetizer", 10 );
set_callbacks( OpenPacketizer, NULL );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -88,15 +132,62 @@ vlc_module_end(); ...@@ -88,15 +132,62 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
&& p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
{
return VLC_EGENERIC;
}
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') p_dec->pf_init = InitDecoder;
&& p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') ) p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{ {
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_dec->p_sys->b_packetizer = VLC_FALSE;
return VLC_SUCCESS;
}
static int OpenPacketizer( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
int i_ret = OpenDecoder( p_this );
if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
return i_ret;
}
/*****************************************************************************
* InitDecoder: Initalize the decoder
*****************************************************************************/
static int InitDecoder( decoder_t *p_dec )
{
p_dec->p_sys->i_state = STATE_NOSYNC;
p_dec->p_sys->p_out_buffer = NULL;
p_dec->p_sys->i_out_buffer = 0;
aout_DateSet( &p_dec->p_sys->end_date, 0 );
p_dec->p_sys->p_aout = NULL;
p_dec->p_sys->p_aout_input = NULL;
p_dec->p_sys->p_aout_buffer = NULL;
p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
p_dec->p_sys->p_sout_input = NULL;
p_dec->p_sys->p_sout_buffer = NULL;
p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -105,167 +196,350 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -105,167 +196,350 @@ static int OpenDecoder( vlc_object_t *p_this )
**************************************************************************** ****************************************************************************
* This function is called just after the thread is launched. * This function is called just after the thread is launched.
****************************************************************************/ ****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo ) static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{ {
dec_thread_t * p_dec; decoder_sys_t *p_sys = p_dec->p_sys;
audio_date_t end_date; int i_block_pos = 0;
mtime_t i_pts = p_block->i_pts;
/* Allocate the memory needed to store the thread's structure */ while( i_block_pos < p_block->i_buffer )
p_dec = malloc( sizeof(dec_thread_t) );
if( p_dec == NULL )
{ {
msg_Err( p_fifo, "out of memory" ); switch( p_sys->i_state )
DecoderError( p_fifo ); {
return -1; case STATE_NOSYNC:
} /* Look for sync word - should be 0x0b77 */
while( i_block_pos < p_block->i_buffer &&
p_block->p_buffer[i_block_pos] != 0x0b )
{
i_block_pos++;
}
/* Initialize the thread properties */ if( i_block_pos < p_block->i_buffer )
p_dec->p_aout = NULL; {
p_dec->p_aout_input = NULL; p_sys->i_state = STATE_PARTIAL_SYNC;
p_dec->p_fifo = p_fifo; i_block_pos++;
p_dec->output_format.i_format = VLC_FOURCC('a','5','2',' '); p_sys->p_header[0] = 0x0b;
break;
}
break;
aout_DateSet( &end_date, 0 ); case STATE_PARTIAL_SYNC:
if( p_block->p_buffer[i_block_pos] == 0x77 )
{
p_sys->i_state = STATE_SYNC;
i_block_pos++;
p_sys->p_header[1] = 0x77;
p_sys->i_header = 2;
}
else
{
p_sys->i_state = STATE_NOSYNC;
}
break;
/* Init the bitstream */ case STATE_SYNC:
if( InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, /* New frame, set the Presentation Time Stamp */
NULL, NULL ) != VLC_SUCCESS ) p_sys->pts = i_pts; i_pts = 0;
{ if( p_sys->pts != 0 &&
msg_Err( p_fifo, "cannot initialize bitstream" ); p_sys->pts != aout_DateGet( &p_sys->end_date ) )
DecoderError( p_fifo ); {
free( p_dec ); aout_DateSet( &p_sys->end_date, p_sys->pts );
return -1; }
p_sys->i_state = STATE_HEADER;
break;
case STATE_HEADER:
/* Get A/52 frame header (A52_HEADER_SIZE bytes) */
if( p_sys->i_header < A52_HEADER_SIZE )
{
int i_size = __MIN( A52_HEADER_SIZE - p_sys->i_header,
p_block->i_buffer - i_block_pos );
memcpy( p_sys->p_header + p_sys->i_header,
p_block->p_buffer + i_block_pos, i_size );
i_block_pos += i_size;
p_sys->i_header += i_size;
}
if( p_sys->i_header < A52_HEADER_SIZE )
break;
if( GetOutBuffer( p_dec, &p_sys->p_out_buffer )
!= VLC_SUCCESS )
{
block_Release( p_block );
return VLC_EGENERIC;
}
if( !p_sys->p_out_buffer )
{
p_sys->i_state = STATE_NOSYNC;
break;
}
memcpy( p_sys->p_out_buffer, p_sys->p_header, A52_HEADER_SIZE );
p_sys->i_out_buffer = A52_HEADER_SIZE;
p_sys->i_state = STATE_DATA;
break;
case STATE_DATA:
/* Copy the whole A52 frame into the aout buffer */
if( p_sys->i_out_buffer < p_sys->i_frame_size )
{
int i_size = __MIN( p_sys->i_frame_size - p_sys->i_out_buffer,
p_block->i_buffer - i_block_pos );
memcpy( p_sys->p_out_buffer + p_sys->i_out_buffer,
p_block->p_buffer + i_block_pos, i_size );
i_block_pos += i_size;
p_sys->i_out_buffer += i_size;
}
if( p_sys->i_out_buffer < p_sys->i_frame_size )
break; /* Need more data */
SendOutBuffer( p_dec );
p_sys->i_state = STATE_NOSYNC;
break;
}
} }
/* Decoder thread's main loop */ block_Release( p_block );
while ( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) return VLC_SUCCESS;
}
/*****************************************************************************
* EndDecoder: clean up the decoder
*****************************************************************************/
static int EndDecoder( decoder_t *p_dec )
{
if( p_dec->p_sys->p_aout_input != NULL )
{ {
int i_bit_rate; if( p_dec->p_sys->p_aout_buffer )
unsigned int i_rate, i_original_channels, i_frame_size;
mtime_t pts;
byte_t p_header[7];
aout_buffer_t * p_buffer;
/* Look for sync word - should be 0x0b77 */
RealignBits( &p_dec->bit_stream );
while ( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 &&
(!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
{ {
RemoveBits( &p_dec->bit_stream, 8 ); aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
p_dec->p_sys->p_aout_input,
p_dec->p_sys->p_aout_buffer );
} }
if ( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) break;
/* Set the Presentation Time Stamp */ aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
NextPTS( &p_dec->bit_stream, &pts, NULL ); }
if ( pts != 0 && pts != aout_DateGet( &end_date ) )
if( p_dec->p_sys->p_sout_input != NULL )
{
if( p_dec->p_sys->p_sout_buffer )
{ {
aout_DateSet( &end_date, pts ); sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
p_dec->p_sys->p_sout_buffer );
} }
/* Get A/52 frame header */ sout_InputDelete( p_dec->p_sys->p_sout_input );
GetChunk( &p_dec->bit_stream, p_header, 7 ); }
if ( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) break;
/* Check if frame is valid and get frame info */ free( p_dec->p_sys );
i_frame_size = SyncInfo( p_header, &i_original_channels, &i_rate,
&i_bit_rate );
if( !i_frame_size ) return VLC_SUCCESS;
{ }
msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" );
continue;
}
if( (p_dec->p_aout_input != NULL) && /*****************************************************************************
( (p_dec->output_format.i_rate != i_rate) * GetOutBuffer:
|| (p_dec->output_format.i_original_channels *****************************************************************************/
!= i_original_channels) static int GetOutBuffer ( decoder_t *p_dec, uint8_t **pp_out_buffer )
|| (p_dec->output_format.i_bytes_per_frame != i_frame_size) ) ) {
{ decoder_sys_t *p_sys = p_dec->p_sys;
/* Parameters changed - this should not happen. */ int i_ret;
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
p_dec->p_aout_input = NULL;
}
/* Creating the audio input if not created yet. */ if( p_sys->b_packetizer )
if( p_dec->p_aout_input == NULL ) {
{ i_ret= GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
p_dec->output_format.i_rate = i_rate; *pp_out_buffer =
p_dec->output_format.i_original_channels = i_original_channels; p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
p_dec->output_format.i_physical_channels }
= i_original_channels & AOUT_CHAN_PHYSMASK; else
p_dec->output_format.i_bytes_per_frame = i_frame_size; {
p_dec->output_format.i_frame_length = A52_FRAME_NB; i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
aout_DateInit( &end_date, i_rate ); *pp_out_buffer =
aout_DateSet( &end_date, pts ); p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo, }
&p_dec->p_aout,
&p_dec->output_format );
if ( p_dec->p_aout_input == NULL )
{
p_dec->p_fifo->b_error = 1;
break;
}
}
if ( !aout_DateGet( &end_date ) ) return i_ret;
{ }
byte_t p_junk[3840];
/* We've just started the stream, wait for the first PTS. */ /*****************************************************************************
GetChunk( &p_dec->bit_stream, p_junk, i_frame_size - 7 ); * GetAoutBuffer:
continue; *****************************************************************************/
} static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
{
int i_bit_rate;
unsigned int i_rate, i_channels, i_channels_conf;
p_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input, decoder_sys_t *p_sys = p_dec->p_sys;
A52_FRAME_NB );
if ( p_buffer == NULL ) /* Check if frame is valid and get frame info */
p_sys->i_frame_size = SyncInfo( p_sys->p_header,
&i_channels, &i_channels_conf,
&i_rate, &i_bit_rate );
if( !p_sys->i_frame_size )
{
msg_Warn( p_dec, "a52 syncinfo failed" );
*pp_buffer = NULL;
return VLC_SUCCESS;
}
if( p_sys->p_aout_input != NULL && ( p_sys->aout_format.i_rate != i_rate
|| p_sys->aout_format.i_original_channels != i_channels_conf
|| (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
{
/* Parameters changed - this should not happen. */
aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
p_sys->p_aout_input = NULL;
}
/* Creating the audio input if not created yet. */
if( p_sys->p_aout_input == NULL )
{
p_sys->aout_format.i_rate = i_rate;
p_sys->aout_format.i_original_channels = i_channels_conf;
p_sys->aout_format.i_physical_channels
= i_channels_conf & AOUT_CHAN_PHYSMASK;
p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
p_sys->aout_format.i_frame_length = A52_FRAME_NB;
aout_DateInit( &p_sys->end_date, i_rate );
aout_DateSet( &p_sys->end_date, p_sys->pts );
p_sys->p_aout_input = aout_DecNew( p_dec,
&p_sys->p_aout,
&p_sys->aout_format );
if ( p_sys->p_aout_input == NULL )
{ {
p_dec->p_fifo->b_error = 1; *pp_buffer = NULL;
break; return VLC_SUCCESS;
} }
p_buffer->start_date = aout_DateGet( &end_date ); }
p_buffer->end_date = aout_DateIncrement( &end_date,
A52_FRAME_NB ); if( !aout_DateGet( &p_sys->end_date ) )
{
/* Get the whole frame. */ /* We've just started the stream, wait for the first PTS. */
memcpy( p_buffer->p_buffer, p_header, 7 ); *pp_buffer = NULL;
GetChunk( &p_dec->bit_stream, p_buffer->p_buffer + 7, return VLC_SUCCESS;
i_frame_size - 7 ); }
if( p_dec->p_fifo->b_die )
*pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
A52_FRAME_NB );
if( *pp_buffer == NULL )
{
return VLC_SUCCESS;
}
(*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
(*pp_buffer)->end_date =
aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
return VLC_SUCCESS;
}
/*****************************************************************************
* GetSoutBuffer:
*****************************************************************************/
static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
{
int i_bit_rate;
unsigned int i_rate, i_channels, i_channels_conf;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Check if frame is valid and get frame info */
p_sys->i_frame_size = SyncInfo( p_sys->p_header,
&i_channels, &i_channels_conf,
&i_rate, &i_bit_rate );
if( !p_sys->i_frame_size )
{
msg_Warn( p_dec, "a52 syncinfo failed" );
*pp_buffer = NULL;
return VLC_SUCCESS;
}
if( p_sys->p_sout_input != NULL &&
( p_sys->sout_format.i_sample_rate != (int)i_rate
|| p_sys->sout_format.i_channels != (int)i_channels ) )
{
/* Parameters changed - this should not happen. */
}
/* Creating the sout input if not created yet. */
if( p_sys->p_sout_input == NULL )
{
p_sys->sout_format.i_sample_rate = i_rate;
p_sys->sout_format.i_channels = i_channels;
p_sys->sout_format.i_block_align = 0;
p_sys->sout_format.i_bitrate = i_bit_rate;
p_sys->sout_format.i_extra_data = 0;
p_sys->sout_format.p_extra_data = NULL;
aout_DateInit( &p_sys->end_date, i_rate );
aout_DateSet( &p_sys->end_date, p_sys->pts );
p_sys->p_sout_input = sout_InputNew( p_dec,
&p_sys->sout_format );
if( p_sys->p_sout_input == NULL )
{ {
aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input, msg_Err( p_dec, "cannot add a new stream" );
p_buffer ); *pp_buffer = NULL;
break; return VLC_EGENERIC;
} }
msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
i_channels, i_rate, i_bit_rate );
}
/* Send the buffer to the aout core. */ if( !aout_DateGet( &p_sys->end_date ) )
aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ); {
/* We've just started the stream, wait for the first PTS. */
*pp_buffer = NULL;
return VLC_SUCCESS;
} }
if( p_dec->p_fifo->b_error ) *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
p_sys->i_frame_size );
if( *pp_buffer == NULL )
{ {
DecoderError( p_dec->p_fifo ); return VLC_SUCCESS;
} }
EndThread( p_dec ); (*pp_buffer)->i_pts =
(*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
(*pp_buffer)->i_length =
aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
- (*pp_buffer)->i_pts;
return 0; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* EndThread : thread destruction * SendOutBuffer:
*****************************************************************************/ *****************************************************************************/
static void EndThread( dec_thread_t * p_dec ) static int SendOutBuffer( decoder_t *p_dec )
{ {
if ( p_dec->p_aout_input != NULL ) decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->b_packetizer )
{
sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
p_sys->p_sout_buffer = NULL;
}
else
{ {
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input ); /* We have all we need, send the buffer to the aout core. */
aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
p_sys->p_aout_buffer );
p_sys->p_aout_buffer = NULL;
} }
CloseBitstream( &p_dec->bit_stream ); return VLC_SUCCESS;
free( p_dec );
} }
/***************************************************************************** /*****************************************************************************
...@@ -275,7 +549,8 @@ static void EndThread( dec_thread_t * p_dec ) ...@@ -275,7 +549,8 @@ static void EndThread( dec_thread_t * p_dec )
* since we don't want to oblige S/PDIF people to use liba52 just to get * since we don't want to oblige S/PDIF people to use liba52 just to get
* their SyncInfo... * their SyncInfo...
*****************************************************************************/ *****************************************************************************/
static int SyncInfo( const byte_t * p_buf, int * pi_channels, static int SyncInfo( const byte_t * p_buf,
int * pi_channels, int * pi_channels_conf,
int * pi_sample_rate, int * pi_bit_rate ) int * pi_sample_rate, int * pi_bit_rate )
{ {
static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 }; static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
...@@ -301,52 +576,67 @@ static int SyncInfo( const byte_t * p_buf, int * pi_channels, ...@@ -301,52 +576,67 @@ static int SyncInfo( const byte_t * p_buf, int * pi_channels,
if ( (p_buf[6] & 0xf8) == 0x50 ) if ( (p_buf[6] & 0xf8) == 0x50 )
{ {
/* Dolby surround = stereo + Dolby */ /* Dolby surround = stereo + Dolby */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT *pi_channels = 2;
| AOUT_CHAN_DOLBYSTEREO; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_DOLBYSTEREO;
} }
else switch ( acmod ) else switch ( acmod )
{ {
case 0x0: case 0x0:
/* Dual-mono = stereo + dual-mono */ /* Dual-mono = stereo + dual-mono */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT *pi_channels = 2;
| AOUT_CHAN_DUALMONO; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_DUALMONO;
break; break;
case 0x1: case 0x1:
/* Mono */ /* Mono */
*pi_channels = AOUT_CHAN_CENTER; *pi_channels = 1;
*pi_channels_conf = AOUT_CHAN_CENTER;
break; break;
case 0x2: case 0x2:
/* Stereo */ /* Stereo */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; *pi_channels = 2;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
break; break;
case 0x3: case 0x3:
/* 3F */ /* 3F */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER; *pi_channels = 3;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER;
break; break;
case 0x4: case 0x4:
/* 2F1R */ /* 2F1R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER; *pi_channels = 3;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARCENTER;
break; break;
case 0x5: case 0x5:
/* 3F1R */ /* 3F1R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER *pi_channels = 4;
| AOUT_CHAN_REARCENTER; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARCENTER;
break; break;
case 0x6: case 0x6:
/* 2F2R */ /* 2F2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT *pi_channels = 4;
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break; break;
case 0x7: case 0x7:
/* 3F2R */ /* 3F2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER *pi_channels = 5;
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break; break;
default: default:
return 0; return 0;
} }
if ( p_buf[6] & lfeon[acmod] ) *pi_channels |= AOUT_CHAN_LFE; if ( p_buf[6] & lfeon[acmod] )
{
(*pi_channels)++;
*pi_channels_conf |= AOUT_CHAN_LFE;
}
frmsizecod = p_buf[4] & 63; frmsizecod = p_buf[4] & 63;
if (frmsizecod >= 38) if (frmsizecod >= 38)
...@@ -368,4 +658,3 @@ static int SyncInfo( const byte_t * p_buf, int * pi_channels, ...@@ -368,4 +658,3 @@ static int SyncInfo( const byte_t * p_buf, int * pi_channels,
return 0; return 0;
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* adpcm.c : adpcm variant audio decoder * adpcm.c : adpcm variant audio decoder
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: adpcm.c,v 1.12 2003/08/17 23:02:51 fenrir Exp $ * $Id: adpcm.c,v 1.13 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -151,9 +151,9 @@ static int i_adaptation_coeff2[7] = ...@@ -151,9 +151,9 @@ static int i_adaptation_coeff2[7] =
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
...@@ -161,13 +161,12 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -161,13 +161,12 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
/***************************************************************************** /*****************************************************************************
...@@ -874,5 +873,3 @@ static void DecodeAdpcmDk3( adec_thread_t *p_adec, ...@@ -874,5 +873,3 @@ static void DecodeAdpcmDk3( adec_thread_t *p_adec,
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* araw.c: Pseudo audio decoder; for raw pcm data * araw.c: Pseudo audio decoder; for raw pcm data
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: araw.c,v 1.16 2003/08/17 23:02:51 fenrir Exp $ * $Id: araw.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -80,9 +80,9 @@ vlc_module_end(); ...@@ -80,9 +80,9 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
case VLC_FOURCC('a','r','a','w'): /* from wav/avi/asf file */ case VLC_FOURCC('a','r','a','w'): /* from wav/avi/asf file */
case VLC_FOURCC('t','w','o','s'): /* _signed_ big endian samples (mov)*/ case VLC_FOURCC('t','w','o','s'): /* _signed_ big endian samples (mov)*/
...@@ -90,13 +90,12 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -90,13 +90,12 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('a','l','a','w'): case VLC_FOURCC('a','l','a','w'):
case VLC_FOURCC('u','l','a','w'): case VLC_FOURCC('u','l','a','w'):
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
static int pi_channels_maps[6] = static int pi_channels_maps[6] =
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* cinepak.c: cinepak video decoder * cinepak.c: cinepak video decoder
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: cinepak.c,v 1.11 2003/08/17 23:02:51 fenrir Exp $ * $Id: cinepak.c,v 1.12 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -70,13 +70,13 @@ vlc_module_end(); ...@@ -70,13 +70,13 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
case VLC_FOURCC('c','v','i','d'): case VLC_FOURCC('c','v','i','d'):
case VLC_FOURCC('C','V','I','D'): case VLC_FOURCC('C','V','I','D'):
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -834,5 +834,3 @@ static void EndThread( videodec_thread_t *p_vdec ) ...@@ -834,5 +834,3 @@ static void EndThread( videodec_thread_t *p_vdec )
free( p_vdec ); free( p_vdec );
} }
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* dts.c: DTS basic parser * dts.c: DTS basic parser
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: dts.c,v 1.3 2003/03/18 00:25:27 jlj Exp $ * $Id: dts.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Jon Lech Johansen <jon-vl@nanocrew.net> * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
* Gildas Bazin <gbazin@netcourrier.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -31,47 +32,88 @@ ...@@ -31,47 +32,88 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/aout.h> #include <vlc/aout.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#define DTS_HEADER_SIZE 10
/***************************************************************************** /*****************************************************************************
* dec_thread_t : decoder thread descriptor * decoder_sys_t : decoder descriptor
*****************************************************************************/ *****************************************************************************/
typedef struct dec_thread_t struct decoder_sys_t
{ {
/* Module mode */
vlc_bool_t b_packetizer;
/* /*
* Thread properties * Input properties
*/ */
vlc_thread_t thread_id; /* id for thread functions */ int i_state;
uint8_t p_header[DTS_HEADER_SIZE];
int i_header;
mtime_t pts;
int i_frame_size;
/* /*
* Input properties * Decoder output properties
*/ */
decoder_fifo_t * p_fifo; /* stores the PES stream data */ aout_instance_t * p_aout; /* opaque */
bit_stream_t bit_stream; aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t aout_format;
aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
/* This is very hacky. For DTS over S/PDIF we apparently need to send
* 3 frames at a time. This should likely be moved to the output stage. */
int i_frames_in_buf;
/* /*
* Output properties * Packetizer output properties
*/ */
aout_instance_t * p_aout; /* opaque */ sout_packetizer_input_t *p_sout_input;
aout_input_t * p_aout_input; /* opaque */ sout_format_t sout_format;
audio_sample_format_t output_format; sout_buffer_t * p_sout_buffer; /* current sout buffer */
} dec_thread_t;
/*
* Common properties
*/
uint8_t *p_out_buffer; /* output buffer */
int i_out_buffer; /* position in output buffer */
audio_date_t end_date;
};
enum {
STATE_NOSYNC,
STATE_PARTIAL_SYNC,
STATE_SYNC,
STATE_HEADER,
STATE_DATA
};
/**************************************************************************** /****************************************************************************
* Local prototypes * Local prototypes
****************************************************************************/ ****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int OpenPacketizer( vlc_object_t * );
static int InitDecoder ( decoder_t * );
static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static void EndThread ( dec_thread_t * ); static int SyncInfo ( const byte_t *, unsigned int *, unsigned int *,
unsigned int *, unsigned int *, unsigned int * );
static int SyncInfo ( const byte_t *, unsigned int *, static int GetOutBuffer ( decoder_t *, uint8_t ** );
unsigned int *, unsigned int *, static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
unsigned int * ); static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
static int SendOutBuffer( decoder_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -80,6 +122,11 @@ vlc_module_begin(); ...@@ -80,6 +122,11 @@ vlc_module_begin();
set_description( _("DTS parser") ); set_description( _("DTS parser") );
set_capability( "decoder", 100 ); set_capability( "decoder", 100 );
set_callbacks( OpenDecoder, NULL ); set_callbacks( OpenDecoder, NULL );
add_submodule();
set_description( _("DTS audio packetizer") );
set_capability( "packetizer", 10 );
set_callbacks( OpenPacketizer, NULL );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -87,214 +134,463 @@ vlc_module_end(); ...@@ -87,214 +134,463 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s',' ')
&& p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s','b') )
{
return VLC_EGENERIC;
}
p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
if( p_fifo->i_fourcc != VLC_FOURCC('d','t','s',' ') /* Allocate the memory needed to store the decoder's structure */
&& p_fifo->i_fourcc != VLC_FOURCC('d','t','s','b') ) if( ( p_dec->p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{ {
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_dec->p_sys->b_packetizer = VLC_FALSE;
p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/**************************************************************************** static int OpenPacketizer( vlc_object_t *p_this )
* RunDecoder: the whole thing
****************************************************************************
* This function is called just after the thread is launched.
****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo )
{ {
dec_thread_t * p_dec; decoder_t *p_dec = (decoder_t*)p_this;
audio_date_t end_date;
/* Allocate the memory needed to store the thread's structure */ int i_ret = OpenDecoder( p_this );
p_dec = malloc( sizeof(dec_thread_t) );
if( p_dec == NULL )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return -1;
}
/* Initialize the thread properties */ if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
p_dec->p_aout = NULL;
p_dec->p_aout_input = NULL;
p_dec->p_fifo = p_fifo;
p_dec->output_format.i_format = VLC_FOURCC('d','t','s',' ');
aout_DateSet( &end_date, 0 ); return i_ret;
}
/* Init the bitstream */ /*****************************************************************************
if( InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, * InitDecoder: Initalize the decoder
NULL, NULL ) != VLC_SUCCESS ) *****************************************************************************/
{ static int InitDecoder( decoder_t *p_dec )
msg_Err( p_fifo, "cannot initialize bitstream" ); {
DecoderError( p_fifo ); p_dec->p_sys->i_state = STATE_NOSYNC;
free( p_dec );
return -1;
}
/* Decoder thread's main loop */ p_dec->p_sys->p_out_buffer = NULL;
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) p_dec->p_sys->i_out_buffer = 0;
{ aout_DateSet( &p_dec->p_sys->end_date, 0 );
int i;
mtime_t pts; p_dec->p_sys->p_aout = NULL;
byte_t p_header[10]; p_dec->p_sys->p_aout_input = NULL;
p_dec->p_sys->p_aout_buffer = NULL;
p_dec->p_sys->aout_format.i_format = VLC_FOURCC('d','t','s',' ');
unsigned int i_rate; p_dec->p_sys->p_sout_input = NULL;
unsigned int i_bit_rate; p_dec->p_sys->p_sout_buffer = NULL;
unsigned int i_frame_size; p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
unsigned int i_frame_length; p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('d','t','s',' ');
unsigned int i_original_channels;
return VLC_SUCCESS;
}
aout_buffer_t * p_buffer = NULL; /****************************************************************************
* RunDecoder: the whole thing
****************************************************************************
* This function is called just after the thread is launched.
****************************************************************************/
static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i, i_block_pos = 0;
mtime_t i_pts = p_block->i_pts;
for( i = 0; i < 3; i++ ) while( i_block_pos < p_block->i_buffer )
{
switch( p_sys->i_state )
{ {
RealignBits( &p_dec->bit_stream ); case STATE_NOSYNC:
while( (ShowBits( &p_dec->bit_stream, 32 ) ) != 0x7ffe8001 && /* Look for sync dword - should be 0x7ffe8001 */
(!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) ) while( i_block_pos < p_block->i_buffer &&
p_block->p_buffer[i_block_pos] != 0x7f )
{ {
RemoveBits( &p_dec->bit_stream, 8 ); i_block_pos++;
} }
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) break;
if( i == 0 ) if( i_block_pos < p_block->i_buffer )
{ {
/* Set the Presentation Time Stamp */ p_sys->i_state = STATE_PARTIAL_SYNC;
NextPTS( &p_dec->bit_stream, &pts, NULL ); i_block_pos++;
if( pts != 0 && pts != aout_DateGet( &end_date ) ) p_sys->p_header[0] = 0x7f;
{ p_sys->i_header = 1;
aout_DateSet( &end_date, pts ); break;
}
} }
break;
/* Get DTS frame header */ case STATE_PARTIAL_SYNC:
GetChunk( &p_dec->bit_stream, p_header, 10 ); /* Get the full 4 sync bytes */
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) break; if( p_sys->i_header < 4 )
i_frame_size = SyncInfo( p_header, &i_original_channels, &i_rate,
&i_bit_rate, &i_frame_length );
if( !i_frame_size )
{ {
msg_Warn( p_dec->p_fifo, "dts_syncinfo failed" ); int i_size = __MIN( 4 - p_sys->i_header,
i--; continue; p_block->i_buffer - i_block_pos );
memcpy( p_sys->p_header + p_sys->i_header,
p_block->p_buffer + i_block_pos, i_size );
i_block_pos += i_size;
p_sys->i_header += i_size;
} }
if( i == 0 ) if( p_sys->i_header < 4 )
break;
if( p_sys->p_header[0] == 0x7f && p_sys->p_header[1] == 0xfe &&
p_sys->p_header[2] == 0x80 && p_sys->p_header[3] == 0x01 )
{ {
if( (p_dec->p_aout_input != NULL) && p_sys->i_state = STATE_SYNC;
( (p_dec->output_format.i_rate != i_rate) }
|| (p_dec->output_format.i_original_channels else
!= i_original_channels) {
|| (p_dec->output_format.i_bytes_per_frame for( i = 1; i < 4; i++ )
!= i_frame_size * 3) ) )
{ {
/* Parameters changed - this should not happen. */ if( p_sys->p_header[i] == 0x7f ) break;
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
p_dec->p_aout_input = NULL;
} }
/* Creating the audio input if not created yet. */ if( p_sys->p_header[i] == 0x7f )
if( p_dec->p_aout_input == NULL )
{ {
p_dec->output_format.i_rate = i_rate; /* Potential new sync */
p_dec->output_format.i_original_channels p_sys->i_header -= i;
= i_original_channels; memmove( p_sys->p_header, &p_sys->p_header[i],
p_dec->output_format.i_physical_channels p_sys->i_header );
= i_original_channels & AOUT_CHAN_PHYSMASK; break;
p_dec->output_format.i_bytes_per_frame = i_frame_size * 3;
p_dec->output_format.i_frame_length = i_frame_length * 3;
aout_DateInit( &end_date, i_rate );
p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
&p_dec->p_aout,
&p_dec->output_format );
if( p_dec->p_aout_input == NULL )
{
p_dec->p_fifo->b_error = 1;
break;
}
} }
/* retry to sync*/
p_sys->i_state = STATE_NOSYNC;
}
break;
case STATE_SYNC:
/* New frame, set the Presentation Time Stamp */
p_sys->pts = i_pts; i_pts = 0;
if( p_sys->pts != 0 &&
p_sys->pts != aout_DateGet( &p_sys->end_date ) )
{
aout_DateSet( &p_sys->end_date, p_sys->pts );
} }
p_sys->i_state = STATE_HEADER;
break;
if( !aout_DateGet( &end_date ) ) case STATE_HEADER:
/* Get DTS frame header (DTS_HEADER_SIZE bytes) */
if( p_sys->i_header < DTS_HEADER_SIZE )
{ {
byte_t p_junk[ i_frame_size ]; int i_size = __MIN( DTS_HEADER_SIZE - p_sys->i_header,
p_block->i_buffer - i_block_pos );
/* We've just started the stream, wait for the first PTS. */ memcpy( p_sys->p_header + p_sys->i_header,
GetChunk( &p_dec->bit_stream, p_junk, i_frame_size - 10 ); p_block->p_buffer + i_block_pos, i_size );
i--; continue; i_block_pos += i_size;
p_sys->i_header += i_size;
} }
if( i == 0 ) if( p_sys->i_header < DTS_HEADER_SIZE )
break;
if( GetOutBuffer( p_dec, &p_sys->p_out_buffer )
!= VLC_SUCCESS )
{ {
p_buffer = aout_DecNewBuffer( p_dec->p_aout, block_Release( p_block );
p_dec->p_aout_input, return VLC_EGENERIC;
i_frame_length * 3 );
if( p_buffer == NULL )
{
p_dec->p_fifo->b_error = 1;
break;
}
p_buffer->start_date = aout_DateGet( &end_date );
p_buffer->end_date = aout_DateIncrement( &end_date,
i_frame_length * 3 );
} }
/* Get the whole frame. */ if( !p_sys->p_out_buffer )
memcpy( p_buffer->p_buffer + (i * i_frame_size), p_header, 10 ); {
GetChunk( &p_dec->bit_stream, p_sys->i_state = STATE_NOSYNC;
p_buffer->p_buffer + (i * i_frame_size) + 10, break;
i_frame_size - 10 ); }
if( p_dec->p_fifo->b_die ) break;
}
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) memcpy( p_sys->p_out_buffer, p_sys->p_header, DTS_HEADER_SIZE );
{ p_sys->i_out_buffer = DTS_HEADER_SIZE;
if( p_buffer != NULL ) p_sys->i_state = STATE_DATA;
break;
case STATE_DATA:
/* Copy the whole DTS frame into the aout buffer */
if( p_sys->i_out_buffer < p_sys->i_frame_size )
{ {
aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input, int i_size = __MIN( p_sys->i_frame_size - p_sys->i_out_buffer,
p_buffer ); p_block->i_buffer - i_block_pos );
memcpy( p_sys->p_out_buffer + p_sys->i_out_buffer,
p_block->p_buffer + i_block_pos, i_size );
i_block_pos += i_size;
p_sys->i_out_buffer += i_size;
} }
if( p_sys->i_out_buffer < p_sys->i_frame_size )
break; /* Need more data */
SendOutBuffer( p_dec );
p_sys->i_state = STATE_NOSYNC;
break; break;
} }
}
block_Release( p_block );
return VLC_SUCCESS;
}
/*****************************************************************************
* EndDecoder: clean up the decoder
*****************************************************************************/
static int EndDecoder( decoder_t *p_dec )
{
if( p_dec->p_sys->p_aout_input != NULL )
{
if( p_dec->p_sys->p_aout_buffer )
{
aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
p_dec->p_sys->p_aout_input,
p_dec->p_sys->p_aout_buffer );
}
aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
}
if( p_dec->p_sys->p_sout_input != NULL )
{
if( p_dec->p_sys->p_sout_buffer )
{
sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
p_dec->p_sys->p_sout_buffer );
}
sout_InputDelete( p_dec->p_sys->p_sout_input );
}
free( p_dec->p_sys );
return VLC_SUCCESS;
}
/*****************************************************************************
* GetOutBuffer:
*****************************************************************************/
static int GetOutBuffer ( decoder_t *p_dec, uint8_t **pp_out_buffer )
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i_ret;
if( p_sys->b_packetizer )
{
i_ret= GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
*pp_out_buffer =
p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
}
else
{
i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
if( p_sys->i_frames_in_buf == 1 )
*pp_out_buffer = p_sys->p_aout_buffer ?
p_sys->p_aout_buffer->p_buffer : NULL;
else
*pp_out_buffer = p_sys->p_aout_buffer ?
p_sys->p_aout_buffer->p_buffer + p_sys->i_frame_size *
(p_sys->i_frames_in_buf - 1) : NULL;
}
return i_ret;
}
/*****************************************************************************
* GetAoutBuffer:
*****************************************************************************/
static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
{
int i_bit_rate;
unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Check if frame is valid and get frame info */
p_sys->i_frame_size = SyncInfo( p_sys->p_header,
&i_channels, &i_channels_conf,
&i_rate, &i_bit_rate, &i_frame_length );
if( !p_sys->i_frame_size )
{
msg_Warn( p_dec, "dts syncinfo failed" );
*pp_buffer = NULL;
return VLC_SUCCESS;
}
if( p_sys->p_aout_input != NULL && ( p_sys->aout_format.i_rate != i_rate
|| p_sys->aout_format.i_original_channels != i_channels_conf
|| (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
{
/* Parameters changed - this should not happen. */
aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
p_sys->p_aout_input = NULL;
}
/* Creating the audio input if not created yet. */
if( p_sys->p_aout_input == NULL )
{
p_sys->aout_format.i_rate = i_rate;
p_sys->aout_format.i_original_channels = i_channels_conf;
p_sys->aout_format.i_physical_channels
= i_channels_conf & AOUT_CHAN_PHYSMASK;
p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
p_sys->aout_format.i_frame_length = i_frame_length;
aout_DateInit( &p_sys->end_date, i_rate );
aout_DateSet( &p_sys->end_date, p_sys->pts );
p_sys->i_frames_in_buf = 3;
p_sys->p_aout_input = aout_DecNew( p_dec,
&p_sys->p_aout,
&p_sys->aout_format );
if ( p_sys->p_aout_input == NULL )
{
*pp_buffer = NULL;
return VLC_SUCCESS;
}
}
/* Send the buffer to the aout core. */ if( !aout_DateGet( &p_sys->end_date ) )
aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ); {
/* We've just started the stream, wait for the first PTS. */
*pp_buffer = NULL;
return VLC_SUCCESS;
} }
if( p_dec->p_fifo->b_error ) if( p_sys->i_frames_in_buf == 3 )
{ {
DecoderError( p_dec->p_fifo ); p_sys->i_frames_in_buf = 0;
*pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
i_frame_length * 3 );
if( *pp_buffer == NULL )
{
return VLC_SUCCESS;
}
(*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
(*pp_buffer)->end_date =
aout_DateIncrement( &p_sys->end_date, i_frame_length * 3 );
} }
EndThread( p_dec ); p_sys->i_frames_in_buf++;
return 0; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* EndThread : thread destruction * GetSoutBuffer:
*****************************************************************************/ *****************************************************************************/
static void EndThread( dec_thread_t * p_dec ) static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
{ {
if ( p_dec->p_aout_input != NULL ) int i_bit_rate;
unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Check if frame is valid and get frame info */
p_sys->i_frame_size = SyncInfo( p_sys->p_header,
&i_channels, &i_channels_conf,
&i_rate, &i_bit_rate, &i_frame_length );
if( !p_sys->i_frame_size )
{ {
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input ); msg_Warn( p_dec, "dts syncinfo failed" );
*pp_buffer = NULL;
return VLC_SUCCESS;
} }
CloseBitstream( &p_dec->bit_stream ); if( p_sys->p_sout_input != NULL &&
free( p_dec ); ( p_sys->sout_format.i_sample_rate != (int)i_rate
|| p_sys->sout_format.i_channels != (int)i_channels ) )
{
/* Parameters changed - this should not happen. */
}
/* Creating the sout input if not created yet. */
if( p_sys->p_sout_input == NULL )
{
p_sys->sout_format.i_sample_rate = i_rate;
p_sys->sout_format.i_channels = i_channels;
p_sys->sout_format.i_block_align = 0;
p_sys->sout_format.i_bitrate = i_bit_rate;
p_sys->sout_format.i_extra_data = 0;
p_sys->sout_format.p_extra_data = NULL;
aout_DateInit( &p_sys->end_date, i_rate );
aout_DateSet( &p_sys->end_date, p_sys->pts );
p_sys->p_sout_input = sout_InputNew( p_dec,
&p_sys->sout_format );
if( p_sys->p_sout_input == NULL )
{
msg_Err( p_dec, "cannot add a new stream" );
*pp_buffer = NULL;
return VLC_EGENERIC;
}
msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
i_channels, i_rate, i_bit_rate );
}
if( !aout_DateGet( &p_sys->end_date ) )
{
/* We've just started the stream, wait for the first PTS. */
*pp_buffer = NULL;
return VLC_SUCCESS;
}
*pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
p_sys->i_frame_size );
if( *pp_buffer == NULL )
{
return VLC_SUCCESS;
}
(*pp_buffer)->i_pts =
(*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
(*pp_buffer)->i_length =
aout_DateIncrement( &p_sys->end_date, i_frame_length )
- (*pp_buffer)->i_pts;
return VLC_SUCCESS;
}
/*****************************************************************************
* SendOutBuffer:
*****************************************************************************/
static int SendOutBuffer( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->b_packetizer )
{
sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
p_sys->p_sout_buffer = NULL;
}
else if( p_sys->i_frames_in_buf == 3 )
{
/* We have all we need, send the buffer to the aout core. */
aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
p_sys->p_aout_buffer );
p_sys->p_aout_buffer = NULL;
}
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* SyncInfo: parse DTS sync info * SyncInfo: parse DTS sync info
*****************************************************************************/ *****************************************************************************/
static int SyncInfo( const byte_t * p_buf, unsigned int * pi_channels, static int SyncInfo( const byte_t * p_buf,
unsigned int * pi_channels,
unsigned int * pi_channels_conf,
unsigned int * pi_sample_rate, unsigned int * pi_sample_rate,
unsigned int * pi_bit_rate, unsigned int * pi_bit_rate,
unsigned int * pi_frame_length ) unsigned int * pi_frame_length )
...@@ -340,71 +636,83 @@ static int SyncInfo( const byte_t * p_buf, unsigned int * pi_channels, ...@@ -340,71 +636,83 @@ static int SyncInfo( const byte_t * p_buf, unsigned int * pi_channels,
{ {
case 0x0: case 0x0:
/* Mono */ /* Mono */
*pi_channels = AOUT_CHAN_CENTER; *pi_channels_conf = AOUT_CHAN_CENTER;
break; break;
case 0x1: case 0x1:
/* Dual-mono = stereo + dual-mono */ /* Dual-mono = stereo + dual-mono */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_DUALMONO; AOUT_CHAN_DUALMONO;
break; break;
case 0x2: case 0x2:
case 0x3: case 0x3:
case 0x4: case 0x4:
/* Stereo */ /* Stereo */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; *pi_channels = 2;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
break; break;
case 0x5: case 0x5:
/* 3F */ /* 3F */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER; *pi_channels = 3;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_CENTER;
break; break;
case 0x6: case 0x6:
/* 2F/LFE */ /* 2F/LFE */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE; *pi_channels = 3;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_LFE;
break; break;
case 0x7: case 0x7:
/* 3F/LFE */ /* 3F/LFE */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 4;
AOUT_CHAN_CENTER | AOUT_CHAN_LFE; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
break; break;
case 0x8: case 0x8:
/* 2F2R */ /* 2F2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 4;
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break; break;
case 0x9: case 0x9:
/* 3F2R */ /* 3F2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 5;
AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARRIGHT; AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
AOUT_CHAN_REARRIGHT;
break; break;
case 0xA: case 0xA:
case 0xB: case 0xB:
/* 2F2M2R */ /* 2F2M2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 6;
AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break; break;
case 0xC: case 0xC:
/* 3F2M2R */ /* 3F2M2R */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 7;
AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT | *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
AOUT_CHAN_REARRIGHT; AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
AOUT_CHAN_REARRIGHT;
break; break;
case 0xD: case 0xD:
case 0xE: case 0xE:
/* 3F2M2R/LFE */ /* 3F2M2R/LFE */
*pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | *pi_channels = 8;
AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT | *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
break; break;
default: default:
if( i_audio_mode <= 63 ) if( i_audio_mode <= 63 )
{ {
/* User defined */ /* User defined */
*pi_channels = 0; *pi_channels = 0;
*pi_channels_conf = 0;
} }
else else
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dv.c: a decoder for DV video * dv.c: a decoder for DV video
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: dv.c,v 1.4 2003/01/28 16:57:28 sam Exp $ * $Id: dv.c,v 1.5 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -57,14 +57,14 @@ vlc_module_end(); ...@@ -57,14 +57,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t *p_this ) static int OpenDecoder ( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('d','v','s','d') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','v','s','d') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* decoder.c: AAC decoder using libfaad2 * decoder.c: AAC decoder using libfaad2
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: decoder.c,v 1.29 2003/08/24 23:22:02 gbazin Exp $ * $Id: decoder.c,v 1.30 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -65,14 +65,14 @@ vlc_module_end(); ...@@ -65,14 +65,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('m','p','4','a') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','4','a') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -480,4 +480,3 @@ static void EndThread (adec_thread_t *p_adec) ...@@ -480,4 +480,3 @@ static void EndThread (adec_thread_t *p_adec)
free( p_adec ); free( p_adec );
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library * ffmpeg.c: video decoder using ffmpeg library
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.48 2003/08/15 13:16:38 fenrir Exp $ * $Id: ffmpeg.c,v 1.49 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -189,15 +189,16 @@ vlc_module_end(); ...@@ -189,15 +189,16 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*) p_this;
if( ffmpeg_GetFfmpegCodec( p_fifo->i_fourcc, NULL, NULL, NULL ) ) if( !ffmpeg_GetFfmpegCodec( p_dec->p_fifo->i_fourcc, NULL, NULL, NULL ) )
{ {
p_fifo->pf_run = RunDecoder; return VLC_EGENERIC;
return VLC_SUCCESS;
} }
return VLC_EGENERIC; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS;
} }
typedef union decoder_thread_u typedef union decoder_thread_u
...@@ -208,7 +209,6 @@ typedef union decoder_thread_u ...@@ -208,7 +209,6 @@ typedef union decoder_thread_u
} decoder_thread_t; } decoder_thread_t;
/***************************************************************************** /*****************************************************************************
* RunDecoder: this function is called just after the thread is created * RunDecoder: this function is called just after the thread is created
*****************************************************************************/ *****************************************************************************/
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* flac.c: flac decoder module making use of libflac * flac.c: flac decoder module making use of libflac
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: flacdec.c,v 1.3 2003/08/17 13:56:26 gbazin Exp $ * $Id: flacdec.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
* *
...@@ -114,14 +114,14 @@ vlc_module_end(); ...@@ -114,14 +114,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('f','l','a','c') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('f','l','a','c') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* libmpeg2.c: mpeg2 video decoder module making use of libmpeg2. * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: libmpeg2.c,v 1.25 2003/08/18 13:16:43 zorglub Exp $ * $Id: libmpeg2.c,v 1.26 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -43,9 +44,9 @@ ...@@ -43,9 +44,9 @@
#define AR_221_1_PICTURE 4 /* 2.21:1 picture (movie) */ #define AR_221_1_PICTURE 4 /* 2.21:1 picture (movie) */
/***************************************************************************** /*****************************************************************************
* dec_thread_t : libmpeg2 decoder thread descriptor * decoder_sys_t : libmpeg2 decoder descriptor
*****************************************************************************/ *****************************************************************************/
typedef struct dec_thread_t struct decoder_sys_t
{ {
/* /*
* libmpeg2 properties * libmpeg2 properties
...@@ -57,7 +58,6 @@ typedef struct dec_thread_t ...@@ -57,7 +58,6 @@ typedef struct dec_thread_t
/* /*
* Input properties * Input properties
*/ */
decoder_fifo_t *p_fifo; /* stores the PES stream data */
pes_packet_t *p_pes; /* current PES we are decoding */ pes_packet_t *p_pes; /* current PES we are decoding */
mtime_t i_pts; mtime_t i_pts;
mtime_t i_previous_pts; mtime_t i_previous_pts;
...@@ -76,16 +76,17 @@ typedef struct dec_thread_t ...@@ -76,16 +76,17 @@ typedef struct dec_thread_t
vout_thread_t *p_vout; vout_thread_t *p_vout;
vout_synchro_t *p_synchro; vout_synchro_t *p_synchro;
} dec_thread_t; };
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int InitDecoder ( decoder_t * );
static void CloseDecoder ( dec_thread_t * ); static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static picture_t *GetNewPicture( dec_thread_t *, uint8_t ** ); static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -102,93 +103,100 @@ vlc_module_end(); ...@@ -102,93 +103,100 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','v') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','v') &&
p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','1') &&
p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','2') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* RunDecoder: the libmpeg2 decoder * InitDecoder: Initalize the decoder
*****************************************************************************/ *****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo ) static int InitDecoder( decoder_t *p_dec )
{ {
dec_thread_t *p_dec; /* Allocate the memory needed to store the decoder's structure */
data_packet_t *p_data = NULL; if( ( p_dec->p_sys =
mpeg2_state_t state; (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
picture_t *p_pic;
int i_aspect;
int i_pic;
/* Allocate the memory needed to store the thread's structure */
if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )
== NULL)
{ {
msg_Err( p_fifo, "out of memory" ); msg_Err( p_dec, "out of memory" );
goto error; return VLC_EGENERIC;
} }
/* Initialize the thread properties */ /* Initialize the thread properties */
memset( p_dec, 0, sizeof(dec_thread_t) ); memset( p_dec->p_sys, 0, sizeof(decoder_sys_t) );
p_dec->p_fifo = p_fifo; p_dec->p_sys->p_pes = NULL;
p_dec->p_pes = NULL; p_dec->p_sys->p_vout = NULL;
p_dec->p_vout = NULL; p_dec->p_sys->p_mpeg2dec = NULL;
p_dec->p_mpeg2dec = NULL; p_dec->p_sys->p_synchro = NULL;
p_dec->p_synchro = NULL; p_dec->p_sys->p_info = NULL;
p_dec->p_info = NULL; p_dec->p_sys->i_pts = mdate() + DEFAULT_PTS_DELAY;
p_dec->i_pts = mdate() + DEFAULT_PTS_DELAY; p_dec->p_sys->i_current_pts = 0;
p_dec->i_current_pts = 0; p_dec->p_sys->i_previous_pts = 0;
p_dec->i_previous_pts = 0; p_dec->p_sys->i_period_remainder = 0;
p_dec->i_period_remainder = 0; p_dec->p_sys->p_picture_to_destroy = NULL;
p_dec->p_picture_to_destroy = NULL; p_dec->p_sys->b_garbage_pic = 0;
p_dec->b_garbage_pic = 0; p_dec->p_sys->b_slice_i = 0;
p_dec->b_slice_i = 0; p_dec->p_sys->b_skip = 0;
p_dec->b_skip = 0;
/* Initialize decoder */ /* Initialize decoder */
p_dec->p_mpeg2dec = mpeg2_init(); p_dec->p_sys->p_mpeg2dec = mpeg2_init();
if( p_dec->p_mpeg2dec == NULL) if( p_dec->p_sys->p_mpeg2dec == NULL)
goto error; {
msg_Err( p_dec, "mpeg2_init() failed" );
free( p_dec->p_sys );
return VLC_EGENERIC;
}
p_dec->p_info = mpeg2_info( p_dec->p_mpeg2dec ); p_dec->p_sys->p_info = mpeg2_info( p_dec->p_sys->p_mpeg2dec );
return VLC_SUCCESS;
}
/* libmpeg2 decoder thread's main loop */ /*****************************************************************************
while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) ) * RunDecoder: the libmpeg2 decoder
*****************************************************************************/
static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
mpeg2_state_t state;
picture_t *p_pic;
int i_aspect;
vlc_bool_t b_need_more_data = VLC_FALSE;
while( 1 )
{ {
state = mpeg2_parse( p_dec->p_mpeg2dec ); state = mpeg2_parse( p_sys->p_mpeg2dec );
switch( state ) switch( state )
{ {
case STATE_BUFFER: case STATE_BUFFER:
/* Feed libmpeg2 a data packet at a time */ if( !p_block->i_buffer || b_need_more_data )
if( p_data == NULL )
{
/* Get the next PES */
if( p_dec->p_pes )
input_DeletePES( p_dec->p_fifo->p_packets_mgt,
p_dec->p_pes );
input_ExtractPES( p_dec->p_fifo, &p_dec->p_pes );
if( !p_dec->p_pes )
{ {
p_dec->p_fifo->b_error = 1; block_Release( p_block );
break; return VLC_SUCCESS;
} }
if( p_dec->p_pes->b_discontinuity && p_dec->p_synchro #if 0
&& p_dec->p_info->sequence->width != (unsigned)-1 ) if( p_pes->b_discontinuity && p_sys->p_synchro
&& p_sys->p_info->sequence->width != (unsigned)-1 )
{ {
vout_SynchroReset( p_dec->p_synchro ); vout_SynchroReset( p_sys->p_synchro );
if ( p_dec->p_info->current_fbuf != NULL if ( p_sys->p_info->current_fbuf != NULL
&& p_dec->p_info->current_fbuf->id != NULL ) && p_sys->p_info->current_fbuf->id != NULL )
{ {
p_dec->b_garbage_pic = 1; p_sys->b_garbage_pic = 1;
p_pic = p_dec->p_info->current_fbuf->id; p_pic = p_sys->p_info->current_fbuf->id;
} }
else else
{ {
...@@ -196,49 +204,43 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -196,49 +204,43 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
buf[0] = buf[1] = buf[2] = NULL; buf[0] = buf[1] = buf[2] = NULL;
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
break; break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
} }
p_dec->p_picture_to_destroy = p_pic; p_sys->p_picture_to_destroy = p_pic;
memset( p_pic->p[0].p_pixels, 0, memset( p_pic->p[0].p_pixels, 0,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height ); * p_sys->p_info->sequence->height );
memset( p_pic->p[1].p_pixels, 0x80, memset( p_pic->p[1].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
memset( p_pic->p[2].p_pixels, 0x80, memset( p_pic->p[2].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
if ( p_dec->b_slice_i ) if ( p_sys->b_slice_i )
{ {
vout_SynchroNewPicture( p_dec->p_synchro, vout_SynchroNewPicture( p_sys->p_synchro,
I_CODING_TYPE, 2, 0, 0, p_dec->i_current_rate ); I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
vout_SynchroDecode( p_dec->p_synchro ); vout_SynchroDecode( p_sys->p_synchro );
vout_SynchroEnd( p_dec->p_synchro, I_CODING_TYPE, 0 ); vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
} }
} }
#endif
if( p_dec->p_pes->i_pts ) if( p_block->i_pts )
{ {
mpeg2_pts( p_dec->p_mpeg2dec, mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );
(uint32_t)p_dec->p_pes->i_pts ); p_sys->i_previous_pts = p_sys->i_current_pts;
p_dec->i_previous_pts = p_dec->i_current_pts; p_sys->i_current_pts = p_block->i_pts;
p_dec->i_current_pts = p_dec->p_pes->i_pts;
}
p_dec->i_current_rate = p_dec->p_pes->i_rate;
p_data = p_dec->p_pes->p_first;
} }
if( p_data != NULL ) p_sys->i_current_rate = DEFAULT_RATE;//p_pes->i_rate;
{
mpeg2_buffer( p_dec->p_mpeg2dec,
p_data->p_payload_start,
p_data->p_payload_end );
p_data = p_data->p_next; mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
} p_block->p_buffer + p_block->i_buffer );
b_need_more_data = VLC_TRUE;
break; break;
case STATE_SEQUENCE: case STATE_SEQUENCE:
...@@ -266,99 +268,105 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -266,99 +268,105 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
case AR_SQUARE_PICTURE: case AR_SQUARE_PICTURE:
default: default:
i_aspect = VOUT_ASPECT_FACTOR * i_aspect = VOUT_ASPECT_FACTOR *
p_dec->p_info->sequence->width / p_sys->p_info->sequence->width /
p_dec->p_info->sequence->height; p_sys->p_info->sequence->height;
break; break;
} }
} }
else else
{ {
/* Use the value provided in the MPEG sequence header */ /* Use the value provided in the MPEG sequence header */
i_aspect = ((uint64_t)p_dec->p_info->sequence->display_width) * i_aspect = ((uint64_t)p_sys->p_info->sequence->display_width) *
p_dec->p_info->sequence->pixel_width * VOUT_ASPECT_FACTOR / p_sys->p_info->sequence->pixel_width * VOUT_ASPECT_FACTOR /
p_dec->p_info->sequence->display_height / p_sys->p_info->sequence->display_height /
p_dec->p_info->sequence->pixel_height; p_sys->p_info->sequence->pixel_height;
} }
if ( p_dec->p_vout != NULL ) if ( p_dec->p_sys->p_vout != NULL )
{ {
int i_pic;
/* Temporary hack to free the pictures in use by libmpeg2 */ /* Temporary hack to free the pictures in use by libmpeg2 */
for ( i_pic = 0; i_pic < p_dec->p_vout->render.i_pictures; i_pic++ ) for ( i_pic = 0; i_pic < p_dec->p_sys->p_vout->render.i_pictures; i_pic++ )
{ {
if( p_dec->p_vout->render.pp_picture[i_pic]->i_status == if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_status ==
RESERVED_PICTURE ) RESERVED_PICTURE )
vout_DestroyPicture( p_dec->p_vout, vout_DestroyPicture( p_dec->p_sys->p_vout,
p_dec->p_vout->render.pp_picture[i_pic] ); p_dec->p_sys->p_vout->render.pp_picture[i_pic] );
if( p_dec->p_vout->render.pp_picture[i_pic]->i_refcount > 0 ) if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 )
vout_UnlinkPicture( p_dec->p_vout, vout_UnlinkPicture( p_dec->p_sys->p_vout,
p_dec->p_vout->render.pp_picture[i_pic] ); p_dec->p_sys->p_vout->render.pp_picture[i_pic] );
} }
} }
p_dec->p_vout = vout_Request( p_dec->p_fifo, p_dec->p_vout, p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
p_dec->p_info->sequence->width, p_sys->p_info->sequence->width,
p_dec->p_info->sequence->height, p_sys->p_info->sequence->height,
VLC_FOURCC('Y','V','1','2'), i_aspect ); VLC_FOURCC('Y','V','1','2'),
i_aspect );
if(p_dec->p_vout == NULL )
if(p_sys->p_vout == NULL )
{ {
msg_Err( p_dec->p_fifo , "cannot create vout" ); msg_Err( p_dec, "cannot create vout" );
block_Release( p_block );
return -1; return -1;
} }
msg_Dbg( p_dec->p_fifo, "%dx%d, aspect %d, %u.%03u fps",
p_dec->p_info->sequence->width,
p_dec->p_info->sequence->height, i_aspect,
(u32)((u64)1001000000 * 27 / p_dec->p_info->sequence->frame_period / 1001),
(u32)((u64)1001000000 * 27 / p_dec->p_info->sequence->frame_period % 1001) );
mpeg2_custom_fbuf( p_dec->p_mpeg2dec, 1 ); msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
p_sys->p_info->sequence->width,
p_sys->p_info->sequence->height, i_aspect,
(uint32_t)((u64)1001000000 * 27 /
p_sys->p_info->sequence->frame_period / 1001),
(uint32_t)((u64)1001000000 * 27 /
p_sys->p_info->sequence->frame_period % 1001) );
mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
/* Set the first 2 reference frames */ /* Set the first 2 reference frames */
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break; if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
memset( p_pic->p[0].p_pixels, 0, memset( p_pic->p[0].p_pixels, 0,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height ); * p_sys->p_info->sequence->height );
memset( p_pic->p[1].p_pixels, 0x80, memset( p_pic->p[1].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
memset( p_pic->p[2].p_pixels, 0x80, memset( p_pic->p[2].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
/* This picture will never go through display_picture. */ /* This picture will never go through display_picture. */
vout_DatePicture( p_dec->p_vout, p_pic, 0 ); vout_DatePicture( p_sys->p_vout, p_pic, 0 );
vout_DisplayPicture( p_dec->p_vout, p_pic ); vout_DisplayPicture( p_sys->p_vout, p_pic );
/* For some reason, libmpeg2 will put this pic twice in /* For some reason, libmpeg2 will put this pic twice in
* discard_picture. This can be considered a bug in libmpeg2. */ * discard_picture. This can be considered a bug in libmpeg2. */
vout_LinkPicture( p_dec->p_vout, p_pic ); vout_LinkPicture( p_sys->p_vout, p_pic );
if ( p_dec->p_synchro ) if ( p_sys->p_synchro )
{ {
vout_SynchroRelease( p_dec->p_synchro ); vout_SynchroRelease( p_sys->p_synchro );
} }
p_dec->p_synchro = vout_SynchroInit( p_dec->p_fifo, p_dec->p_vout, p_sys->p_synchro = vout_SynchroInit( p_dec, p_sys->p_vout,
(u32)((u64)1001000000 * 27 / p_dec->p_info->sequence->frame_period) ); (uint32_t)((uint64_t)1001000000 * 27 /
p_dec->b_after_sequence_header = 1; p_sys->p_info->sequence->frame_period) );
p_sys->b_after_sequence_header = 1;
} }
break; break;
case STATE_PICTURE_2ND: case STATE_PICTURE_2ND:
vout_SynchroNewPicture( p_dec->p_synchro, vout_SynchroNewPicture( p_sys->p_synchro,
p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE, p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
p_dec->p_info->current_picture->nb_fields, p_sys->p_info->current_picture->nb_fields,
0, 0, 0, 0,
p_dec->i_current_rate ); p_sys->i_current_rate );
if ( p_dec->b_skip ) if ( p_sys->b_skip )
{ {
vout_SynchroTrash( p_dec->p_synchro ); vout_SynchroTrash( p_sys->p_synchro );
} }
else else
{ {
vout_SynchroDecode( p_dec->p_synchro ); vout_SynchroDecode( p_sys->p_synchro );
} }
break; break;
...@@ -367,85 +375,84 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -367,85 +375,84 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
uint8_t *buf[3]; uint8_t *buf[3];
buf[0] = buf[1] = buf[2] = NULL; buf[0] = buf[1] = buf[2] = NULL;
if ( p_dec->b_after_sequence_header if ( p_sys->b_after_sequence_header
&& ((p_dec->p_info->current_picture->flags && ((p_sys->p_info->current_picture->flags
& PIC_MASK_CODING_TYPE) & PIC_MASK_CODING_TYPE)
== PIC_FLAG_CODING_TYPE_P) ) == PIC_FLAG_CODING_TYPE_P) )
{ {
/* Intra-slice refresh. Simulate a blank I picture. */ /* Intra-slice refresh. Simulate a blank I picture. */
msg_Dbg( p_dec->p_fifo, "intra-slice refresh stream" ); msg_Dbg( p_dec, "intra-slice refresh stream" );
vout_SynchroNewPicture( p_dec->p_synchro, vout_SynchroNewPicture( p_sys->p_synchro,
I_CODING_TYPE, 2, 0, 0, p_dec->i_current_rate ); I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
vout_SynchroDecode( p_dec->p_synchro ); vout_SynchroDecode( p_sys->p_synchro );
vout_SynchroEnd( p_dec->p_synchro, I_CODING_TYPE, 0 ); vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
p_dec->b_slice_i = 1; p_sys->b_slice_i = 1;
} }
p_dec->b_after_sequence_header = 0; p_sys->b_after_sequence_header = 0;
vout_SynchroNewPicture( p_dec->p_synchro, vout_SynchroNewPicture( p_sys->p_synchro,
p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE, p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
p_dec->p_info->current_picture->nb_fields, p_sys->p_info->current_picture->nb_fields,
(p_dec->p_info->current_picture->flags & PIC_FLAG_PTS) ? (p_sys->p_info->current_picture->flags & PIC_FLAG_PTS) ?
( (p_dec->p_info->current_picture->pts == ( ( p_sys->p_info->current_picture->pts ==
(uint32_t)p_dec->i_current_pts) ? (uint32_t)p_sys->i_current_pts ) ?
p_dec->i_current_pts : p_dec->i_previous_pts ) : 0, p_sys->i_current_pts : p_sys->i_previous_pts ) : 0,
0, 0, p_sys->i_current_rate );
p_dec->i_current_rate );
if ( !(p_sys->b_slice_i
if ( !(p_dec->b_slice_i && ((p_sys->p_info->current_picture->flags
&& ((p_dec->p_info->current_picture->flags
& PIC_MASK_CODING_TYPE) == P_CODING_TYPE)) & PIC_MASK_CODING_TYPE) == P_CODING_TYPE))
&& !vout_SynchroChoose( p_dec->p_synchro, && !vout_SynchroChoose( p_sys->p_synchro,
p_dec->p_info->current_picture->flags p_sys->p_info->current_picture->flags
& PIC_MASK_CODING_TYPE ) ) & PIC_MASK_CODING_TYPE ) )
{ {
mpeg2_skip( p_dec->p_mpeg2dec, 1 ); mpeg2_skip( p_sys->p_mpeg2dec, 1 );
p_dec->b_skip = 1; p_sys->b_skip = 1;
vout_SynchroTrash( p_dec->p_synchro ); vout_SynchroTrash( p_sys->p_synchro );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
} }
else else
{ {
mpeg2_skip( p_dec->p_mpeg2dec, 0 ); mpeg2_skip( p_sys->p_mpeg2dec, 0 );
p_dec->b_skip = 0; p_sys->b_skip = 0;
vout_SynchroDecode( p_dec->p_synchro ); vout_SynchroDecode( p_sys->p_synchro );
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break; if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
} }
} }
break; break;
case STATE_END: case STATE_END:
case STATE_SLICE: case STATE_SLICE:
if( p_dec->p_info->display_fbuf if( p_sys->p_info->display_fbuf
&& p_dec->p_info->display_fbuf->id ) && p_sys->p_info->display_fbuf->id )
{ {
p_pic = (picture_t *)p_dec->p_info->display_fbuf->id; p_pic = (picture_t *)p_sys->p_info->display_fbuf->id;
vout_SynchroEnd( p_dec->p_synchro, vout_SynchroEnd( p_sys->p_synchro,
p_dec->p_info->display_picture->flags p_sys->p_info->display_picture->flags
& PIC_MASK_CODING_TYPE, & PIC_MASK_CODING_TYPE,
p_dec->b_garbage_pic ); p_sys->b_garbage_pic );
p_dec->b_garbage_pic = 0; p_sys->b_garbage_pic = 0;
vout_DisplayPicture( p_dec->p_vout, p_pic ); vout_DisplayPicture( p_sys->p_vout, p_pic );
if ( p_dec->p_picture_to_destroy != p_pic ) if ( p_sys->p_picture_to_destroy != p_pic )
{ {
vout_DatePicture( p_dec->p_vout, p_pic, vout_DatePicture( p_sys->p_vout, p_pic,
vout_SynchroDate( p_dec->p_synchro ) ); vout_SynchroDate( p_sys->p_synchro ) );
} }
else else
{ {
p_dec->p_picture_to_destroy = NULL; p_sys->p_picture_to_destroy = NULL;
vout_DatePicture( p_dec->p_vout, p_pic, 0 ); vout_DatePicture( p_sys->p_vout, p_pic, 0 );
} }
} }
if( p_dec->p_info->discard_fbuf && if( p_sys->p_info->discard_fbuf &&
p_dec->p_info->discard_fbuf->id ) p_sys->p_info->discard_fbuf->id )
{ {
p_pic = (picture_t *)p_dec->p_info->discard_fbuf->id; p_pic = (picture_t *)p_sys->p_info->discard_fbuf->id;
vout_UnlinkPicture( p_dec->p_vout, p_pic ); vout_UnlinkPicture( p_sys->p_vout, p_pic );
} }
break; break;
...@@ -454,46 +461,46 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -454,46 +461,46 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
uint8_t *buf[3]; uint8_t *buf[3];
buf[0] = buf[1] = buf[2] = NULL; buf[0] = buf[1] = buf[2] = NULL;
msg_Warn( p_dec->p_fifo, "invalid picture encountered" ); msg_Warn( p_dec, "invalid picture encountered" );
if ( ( p_dec->p_info->current_picture == NULL ) || if ( ( p_sys->p_info->current_picture == NULL ) ||
( ( p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE) ( ( p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE)
!= B_CODING_TYPE ) ) != B_CODING_TYPE ) )
{ {
vout_SynchroReset( p_dec->p_synchro ); vout_SynchroReset( p_sys->p_synchro );
} }
mpeg2_skip( p_dec->p_mpeg2dec, 1 ); mpeg2_skip( p_sys->p_mpeg2dec, 1 );
p_dec->b_skip = 1; p_sys->b_skip = 1;
if( p_dec->p_info->current_fbuf && if( p_sys->p_info->current_fbuf &&
p_dec->p_info->current_fbuf->id ) p_sys->p_info->current_fbuf->id )
{ {
p_dec->b_garbage_pic = 1; p_sys->b_garbage_pic = 1;
p_pic = p_dec->p_info->current_fbuf->id; p_pic = p_sys->p_info->current_fbuf->id;
} }
else else
{ {
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
break; break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
} }
p_dec->p_picture_to_destroy = p_pic; p_sys->p_picture_to_destroy = p_pic;
memset( p_pic->p[0].p_pixels, 0, memset( p_pic->p[0].p_pixels, 0,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height ); * p_sys->p_info->sequence->height );
memset( p_pic->p[1].p_pixels, 0x80, memset( p_pic->p[1].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
memset( p_pic->p[2].p_pixels, 0x80, memset( p_pic->p[2].p_pixels, 0x80,
p_dec->p_info->sequence->width p_sys->p_info->sequence->width
* p_dec->p_info->sequence->height / 4 ); * p_sys->p_info->sequence->height / 4 );
if ( p_dec->b_slice_i ) if ( p_sys->b_slice_i )
{ {
vout_SynchroNewPicture( p_dec->p_synchro, vout_SynchroNewPicture( p_sys->p_synchro,
I_CODING_TYPE, 2, 0, 0, p_dec->i_current_rate ); I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
vout_SynchroDecode( p_dec->p_synchro ); vout_SynchroDecode( p_sys->p_synchro );
vout_SynchroEnd( p_dec->p_synchro, I_CODING_TYPE, 0 ); vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
} }
break; break;
} }
...@@ -503,86 +510,68 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -503,86 +510,68 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
} }
} }
/* If b_error is set, the libmpeg2 decoder thread enters the error loop */ block_Release( p_block );
if( p_dec->p_fifo->b_error ) return VLC_EGENERIC;
{
DecoderError( p_dec->p_fifo );
}
/* End of the libmpeg2 decoder thread */
CloseDecoder( p_dec );
return 0;
error:
DecoderError( p_fifo );
if( p_dec )
{
if( p_dec->p_fifo )
p_dec->p_fifo->b_error = 1;
/* End of the libmpeg2 decoder thread */
CloseDecoder( p_dec );
}
return -1;
} }
/***************************************************************************** /*****************************************************************************
* CloseDecoder: libmpeg2 decoder destruction * EndDecoder: libmpeg2 decoder destruction
*****************************************************************************/ *****************************************************************************/
static void CloseDecoder( dec_thread_t * p_dec ) static int EndDecoder( decoder_t * p_dec )
{ {
if( p_dec ) decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys )
{ {
int i_pic; int i_pic;
if( p_dec->p_pes ) if( p_sys->p_synchro )
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_dec->p_pes ); vout_SynchroRelease( p_sys->p_synchro );
if( p_dec->p_synchro )
vout_SynchroRelease( p_dec->p_synchro );
if( p_dec->p_vout ) if( p_sys->p_vout )
{ {
/* Temporary hack to free the pictures in use by libmpeg2 */ /* Temporary hack to free the pictures in use by libmpeg2 */
for( i_pic = 0; i_pic < p_dec->p_vout->render.i_pictures; i_pic++ ) for( i_pic = 0; i_pic < p_sys->p_vout->render.i_pictures; i_pic++ )
{ {
if( p_dec->p_vout->render.pp_picture[i_pic]->i_status == if( p_sys->p_vout->render.pp_picture[i_pic]->i_status ==
RESERVED_PICTURE ) RESERVED_PICTURE )
vout_DestroyPicture( p_dec->p_vout, vout_DestroyPicture( p_sys->p_vout,
p_dec->p_vout->render.pp_picture[i_pic] ); p_sys->p_vout->render.pp_picture[i_pic] );
if( p_dec->p_vout->render.pp_picture[i_pic]->i_refcount > 0 ) if( p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 )
vout_UnlinkPicture( p_dec->p_vout, vout_UnlinkPicture( p_sys->p_vout,
p_dec->p_vout->render.pp_picture[i_pic] ); p_sys->p_vout->render.pp_picture[i_pic] );
} }
vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 ); vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
} }
if( p_dec->p_mpeg2dec ) mpeg2_close( p_dec->p_mpeg2dec ); if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
free( p_dec ); free( p_sys );
} }
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* GetNewPicture: Get a new picture from the vout and set the buf struct * GetNewPicture: Get a new picture from the vout and set the buf struct
*****************************************************************************/ *****************************************************************************/
static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf ) static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
{ {
decoder_sys_t *p_sys = p_dec->p_sys;
picture_t *p_pic; picture_t *p_pic;
vlc_bool_t b_progressive = p_dec->p_info->current_picture != NULL ? vlc_bool_t b_progressive = p_sys->p_info->current_picture != NULL ?
p_dec->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME :
1; 1;
vlc_bool_t b_top_field_first = p_dec->p_info->current_picture != NULL ? vlc_bool_t b_top_field_first = p_sys->p_info->current_picture != NULL ?
p_dec->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST :
1; 1;
unsigned int i_nb_fields = p_dec->p_info->current_picture != NULL ? unsigned int i_nb_fields = p_sys->p_info->current_picture != NULL ?
p_dec->p_info->current_picture->nb_fields : 2; p_sys->p_info->current_picture->nb_fields : 2;
/* Get a new picture */ /* Get a new picture */
while( !(p_pic = vout_CreatePicture( p_dec->p_vout, while( !(p_pic = vout_CreatePicture( p_sys->p_vout,
b_progressive, b_top_field_first, i_nb_fields )) ) b_progressive, b_top_field_first, i_nb_fields )) )
{ {
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
...@@ -592,7 +581,7 @@ static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf ) ...@@ -592,7 +581,7 @@ static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf )
} }
if( p_pic == NULL ) if( p_pic == NULL )
return NULL; return NULL;
vout_LinkPicture( p_dec->p_vout, p_pic ); vout_LinkPicture( p_sys->p_vout, p_pic );
pp_buf[0] = p_pic->p[0].p_pixels; pp_buf[0] = p_pic->p[0].p_pixels;
pp_buf[1] = p_pic->p[1].p_pixels; pp_buf[1] = p_pic->p[1].p_pixels;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* lpcm.c: lpcm decoder module * lpcm.c: lpcm decoder module
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: lpcm.c,v 1.16 2003/06/10 23:01:40 massiot Exp $ * $Id: lpcm.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org> * Henri Fallon <henri@videolan.org>
...@@ -102,15 +102,15 @@ vlc_module_end(); ...@@ -102,15 +102,15 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m') if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m')
&& p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') ) && p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg_audio.c: parse MPEG audio sync info and packetize the stream * mpeg_audio.c: parse MPEG audio sync info and packetize the stream
***************************************************************************** *****************************************************************************
* Copyright (C) 2001-2003 VideoLAN * Copyright (C) 2001-2003 VideoLAN
* $Id: mpeg_audio.c,v 1.16 2003/06/25 00:40:41 fenrir Exp $ * $Id: mpeg_audio.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -94,14 +94,14 @@ vlc_module_end(); ...@@ -94,14 +94,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -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.11 2003/08/17 23:02:51 fenrir Exp $ * $Id: quicktime.c,v 1.12 2003/09/02 20:19:25 gbazin 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>
...@@ -273,9 +273,9 @@ static int GetPESData( uint8_t *p_buf, int i_max, pes_packet_t *p_pes ) ...@@ -273,9 +273,9 @@ static int GetPESData( uint8_t *p_buf, int i_max, pes_packet_t *p_pes )
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
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
...@@ -285,7 +285,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -285,7 +285,7 @@ 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_fifo->pf_run = RunDecoderVideo; p_dec->pf_run = RunDecoderVideo;
return VLC_SUCCESS; return VLC_SUCCESS;
case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */ case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */
...@@ -309,7 +309,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -309,7 +309,7 @@ static int OpenDecoder( vlc_object_t *p_this )
case 0x6D730002: /* Microsoft ADPCM-ACM */ case 0x6D730002: /* Microsoft ADPCM-ACM */
case 0x6D730011: /* DVI Intel IMAADPCM-ACM */ case 0x6D730011: /* DVI Intel IMAADPCM-ACM */
p_fifo->pf_run = RunDecoderAudio; p_dec->pf_run = RunDecoderAudio;
return VLC_SUCCESS; return VLC_SUCCESS;
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* rawvideo.c: Pseudo audio decoder; for raw video data * rawvideo.c: Pseudo audio decoder; for raw video data
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: rawvideo.c,v 1.5 2003/05/02 03:40:01 fenrir Exp $ * $Id: rawvideo.c,v 1.6 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -76,9 +76,9 @@ vlc_module_end(); ...@@ -76,9 +76,9 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
/* Planar YUV */ /* Planar YUV */
case VLC_FOURCC('I','4','4','4'): case VLC_FOURCC('I','4','4','4'):
...@@ -99,13 +99,12 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -99,13 +99,12 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('R','V','1','6'): case VLC_FOURCC('R','V','1','6'):
case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','5'):
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* spudec.c : SPU decoder thread * spudec.c : SPU decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: spudec.c,v 1.24 2003/07/22 20:49:10 hartman Exp $ * $Id: spudec.c,v 1.25 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -59,15 +59,15 @@ vlc_module_end(); ...@@ -59,15 +59,15 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ') if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ')
&& p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') ) && p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -230,4 +230,3 @@ static void EndThread( spudec_thread_t *p_spudec ) ...@@ -230,4 +230,3 @@ static void EndThread( spudec_thread_t *p_spudec )
CloseBitstream( &p_spudec->bit_stream ); CloseBitstream( &p_spudec->bit_stream );
free( p_spudec ); free( p_spudec );
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* subsdec.c : SPU decoder thread * subsdec.c : SPU decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: subsdec.c,v 1.8 2003/08/27 12:24:52 sigmunau Exp $ * $Id: subsdec.c,v 1.9 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -95,14 +95,14 @@ vlc_module_end(); ...@@ -95,14 +95,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
var_Create( p_this, "subsdec-align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_this, "subsdec-align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
#if defined(HAVE_ICONV) #if defined(HAVE_ICONV)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* tarkin.c: tarkin decoder module making use of libtarkin. * tarkin.c: tarkin decoder module making use of libtarkin.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: tarkin.c,v 1.4 2002/11/28 21:00:48 gbazin Exp $ * $Id: tarkin.c,v 1.5 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -103,14 +103,14 @@ vlc_module_end(); ...@@ -103,14 +103,14 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('t','a','r','k') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('t','a','r','k') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* theora.c: theora decoder module making use of libtheora. * theora.c: theora decoder module making use of libtheora.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: theora.c,v 1.5 2003/06/11 15:53:50 gbazin Exp $ * $Id: theora.c,v 1.6 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -24,27 +24,32 @@ ...@@ -24,27 +24,32 @@
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* memcpy(), memset() */
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/vout.h> #include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <vlc/input.h>
#include <stdlib.h> /* malloc(), free() */ #include <vlc/sout.h>
#include <string.h> /* memcpy(), memset() */ #include <input_ext-dec.h>
#include <ogg/ogg.h> #include <ogg/ogg.h>
#include <theora/theora.h> #include <theora/theora.h>
/***************************************************************************** /*****************************************************************************
* dec_thread_t : theora decoder thread descriptor * decoder_sys_t : theora decoder descriptor
*****************************************************************************/ *****************************************************************************/
typedef struct dec_thread_t struct decoder_sys_t
{ {
/* Module mode */
vlc_bool_t b_packetizer;
/* /*
* Thread properties * Input properties
*/ */
vlc_thread_t thread_id; /* id for thread functions */ int i_headers;
/* /*
* Theora properties * Theora properties
...@@ -54,29 +59,39 @@ typedef struct dec_thread_t ...@@ -54,29 +59,39 @@ typedef struct dec_thread_t
theora_state td; /* theora bitstream user comments */ theora_state td; /* theora bitstream user comments */
/* /*
* Input properties * Output properties
*/ */
decoder_fifo_t *p_fifo; /* stores the PES stream data */ vout_thread_t *p_vout;
pes_packet_t *p_pes; /* current PES we are decoding */
/* /*
* Output properties * Packetizer output properties
*/ */
vout_thread_t *p_vout; sout_packetizer_input_t *p_sout_input;
sout_format_t sout_format;
} dec_thread_t; /*
* Common properties
*/
mtime_t i_pts;
};
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int OpenPacketizer( vlc_object_t * );
static void CloseDecoder ( dec_thread_t * );
static int InitDecoder ( decoder_t * );
static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static void DecodePacket ( dec_thread_t * ); static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t );
static int GetOggPacket ( dec_thread_t *, ogg_packet *, mtime_t * ); static int DecodePacket ( decoder_t *, ogg_packet * );
static int SendPacket ( decoder_t *, ogg_packet * );
static void theora_CopyPicture( dec_thread_t *, picture_t *, yuv_buffer * ); static void ParseTheoraComments( decoder_t * );
static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -86,6 +101,12 @@ vlc_module_begin(); ...@@ -86,6 +101,12 @@ vlc_module_begin();
set_capability( "decoder", 100 ); set_capability( "decoder", 100 );
set_callbacks( OpenDecoder, NULL ); set_callbacks( OpenDecoder, NULL );
add_shortcut( "theora" ); add_shortcut( "theora" );
add_submodule();
set_description( _("Theora video packetizer") );
set_capability( "packetizer", 100 );
set_callbacks( OpenPacketizer, NULL );
add_shortcut( "theora" );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -93,224 +114,375 @@ vlc_module_end(); ...@@ -93,224 +114,375 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('t','h','e','o') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('t','h','e','o') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC;
}
p_dec->p_sys->b_packetizer = VLC_FALSE;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int OpenPacketizer( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
int i_ret = OpenDecoder( p_this );
if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
return i_ret;
}
/***************************************************************************** /*****************************************************************************
* RunDecoder: the theora decoder * InitDecoder: Initalize the decoder
*****************************************************************************/ *****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo ) static int InitDecoder( decoder_t *p_dec )
{ {
dec_thread_t *p_dec; decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
int i_chroma, i_aspect;
mtime_t i_pts;
/* Allocate the memory needed to store the thread's structure */ p_sys->i_pts = 0;
if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )
== NULL)
{
msg_Err( p_fifo, "out of memory" );
goto error;
}
/* Initialize the thread properties */ p_sys->p_sout_input = NULL;
memset( p_dec, 0, sizeof(dec_thread_t) ); p_sys->sout_format.i_cat = VIDEO_ES;
p_dec->p_fifo = p_fifo; p_sys->sout_format.i_fourcc = VLC_FOURCC( 't', 'h', 'e', 'o' );
p_dec->p_pes = NULL; p_sys->sout_format.i_width = 0;
p_dec->p_vout = NULL; p_sys->sout_format.i_height = 0;
p_sys->sout_format.i_bitrate = 0;
p_sys->sout_format.i_extra_data = 0;
p_sys->sout_format.p_extra_data = NULL;
/* Init supporting Theora structures needed in header parsing */ /* Init supporting Theora structures needed in header parsing */
theora_comment_init( &p_dec->tc ); theora_comment_init( &p_sys->tc );
theora_info_init( &p_dec->ti ); theora_info_init( &p_sys->ti );
/* Take care of the initial Theora header */
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ p_sys->i_headers = 0;
if( theora_decode_header( &p_dec->ti, &p_dec->tc, &oggpacket ) < 0 )
{
msg_Err( p_dec->p_fifo, "This bitstream does not contain Theora "
"video data" );
goto error;
}
/* The next two packets in order are the comment and codebook headers. return VLC_SUCCESS;
We need to watch out that these packets are not missing as a }
missing or corrupted header is fatal. */
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( theora_decode_header( &p_dec->ti, &p_dec->tc, &oggpacket ) < 0 ) /****************************************************************************
{ * RunDecoder: the whole thing
msg_Err( p_dec->p_fifo, "2nd Theora header is corrupted" ); ****************************************************************************
goto error; * This function must be fed with ogg packets.
} ****************************************************************************/
static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
int i_ret;
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS ) /* Block to Ogg packet */
goto error; oggpacket.packet = p_block->p_buffer;
oggpacket.bytes = p_block->i_buffer;
oggpacket.granulepos = p_block->i_dts;
oggpacket.b_o_s = 0;
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
if( theora_decode_header( &p_dec->ti, &p_dec->tc, &oggpacket ) < 0 ) if( p_sys->i_headers == 0 )
{ {
msg_Err( p_dec->p_fifo, "3rd Theora header is corrupted" ); /* Take care of the initial Theora header */
goto error;
}
/* We have all the headers, initialize decoder */ oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
theora_decode_init( &p_dec->td, &p_dec->ti ); if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
msg_Dbg( p_dec->p_fifo, "%dx%d %.02f fps video, frame content is %dx%d " {
"with offset (%d,%d)", msg_Err( p_dec->p_fifo, "This bitstream does not contain Theora "
p_dec->ti.width, p_dec->ti.height, "video data" );
(double)p_dec->ti.fps_numerator/p_dec->ti.fps_denominator, block_Release( p_block );
p_dec->ti.frame_width, p_dec->ti.frame_height, return VLC_EGENERIC;
p_dec->ti.offset_x, p_dec->ti.offset_y ); }
p_sys->i_headers++;
/* Initialize video output */
if( p_dec->ti.aspect_denominator )
i_aspect = VOUT_ASPECT_FACTOR * p_dec->ti.aspect_numerator /
p_dec->ti.aspect_denominator;
else
i_aspect = VOUT_ASPECT_FACTOR * p_dec->ti.width / p_dec->ti.height;
i_chroma = VLC_FOURCC('Y','V','1','2');
if( p_sys->b_packetizer )
{
/* add a input for the stream ouput */
p_sys->sout_format.i_width = p_sys->ti.width;
p_sys->sout_format.i_height = p_sys->ti.height;
p_sys->p_sout_input =
sout_InputNew( p_dec, &p_sys->sout_format );
if( !p_sys->p_sout_input )
{
msg_Err( p_dec, "cannot add a new stream" );
block_Release( p_block );
return VLC_EGENERIC;
}
}
else
{
/* Initialize video output */
int i_chroma, i_aspect;
if( p_sys->ti.aspect_denominator )
i_aspect = VOUT_ASPECT_FACTOR * p_sys->ti.aspect_numerator /
p_sys->ti.aspect_denominator;
else
i_aspect = VOUT_ASPECT_FACTOR *
p_sys->ti.frame_width / p_sys->ti.frame_height;
i_chroma = VLC_FOURCC('Y','V','1','2');
p_sys->p_vout =
vout_Request( p_dec, NULL,
p_sys->ti.frame_width, p_sys->ti.frame_height,
i_chroma, i_aspect );
if( p_sys->p_vout == NULL )
{
msg_Err( p_dec, "failed to create video output" );
block_Release( p_block );
return VLC_EGENERIC;
}
}
p_dec->p_vout = vout_Request( p_dec->p_fifo, p_dec->p_vout, msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content "
p_dec->ti.width, p_dec->ti.height, "is %dx%d with offset (%d,%d)",
i_chroma, i_aspect ); p_sys->ti.width, p_sys->ti.height,
(double)p_sys->ti.fps_numerator/p_sys->ti.fps_denominator,
p_sys->ti.frame_width, p_sys->ti.frame_height,
p_sys->ti.offset_x, p_sys->ti.offset_y );
/* theora decoder thread's main loop */ if( p_sys->b_packetizer )
while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) ) {
i_ret = SendPacket( p_dec, &oggpacket );
block_Release( p_block );
return i_ret;
}
else
{
block_Release( p_block );
return VLC_SUCCESS;
}
}
if( p_sys->i_headers == 1 )
{ {
DecodePacket( p_dec ); /* The next packet in order is the comments header */
if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
{
msg_Err( p_dec, "2nd Theora header is corrupted" );
return VLC_EGENERIC;
}
p_sys->i_headers++;
ParseTheoraComments( p_dec );
if( p_sys->b_packetizer )
{
i_ret = SendPacket( p_dec, &oggpacket );
block_Release( p_block );
return i_ret;
}
else
{
block_Release( p_block );
return VLC_SUCCESS;
}
} }
/* If b_error is set, the theora decoder thread enters the error loop */ if( p_sys->i_headers == 2 )
if( p_dec->p_fifo->b_error )
{ {
DecoderError( p_dec->p_fifo ); /* The next packet in order is the codebooks header
We need to watch out that this packet is not missing as a
missing or corrupted header is fatal. */
if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
{
msg_Err( p_dec, "3rd Theora header is corrupted" );
return VLC_EGENERIC;
}
p_sys->i_headers++;
if( !p_sys->b_packetizer )
{
/* We have all the headers, initialize decoder */
theora_decode_init( &p_sys->td, &p_sys->ti );
}
if( p_sys->b_packetizer )
{
i_ret = SendPacket( p_dec, &oggpacket );
block_Release( p_block );
return i_ret;
}
else
{
block_Release( p_block );
return VLC_SUCCESS;
}
} }
/* End of the theora decoder thread */ i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
CloseDecoder( p_dec ); block_Release( p_block );
return i_ret;
}
return 0; /*****************************************************************************
* ProcessPacket: processes a Vorbis packet.
*****************************************************************************/
static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
mtime_t i_pts )
{
decoder_sys_t *p_sys = p_dec->p_sys;
error: /* Date management */
DecoderError( p_fifo ); if( i_pts > 0 && i_pts != p_sys->i_pts )
if( p_dec )
{ {
if( p_dec->p_fifo ) p_sys->i_pts = i_pts;
p_dec->p_fifo->b_error = 1;
/* End of the theora decoder thread */
CloseDecoder( p_dec );
} }
return -1; if( p_sys->b_packetizer )
{
return SendPacket( p_dec, p_oggpacket );
}
else
{
return DecodePacket( p_dec, p_oggpacket );
}
} }
/***************************************************************************** /*****************************************************************************
* DecodePacket: decodes a Theora packet. * DecodePacket: decodes a Theora packet.
*****************************************************************************/ *****************************************************************************/
static void DecodePacket( dec_thread_t *p_dec ) static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
{ {
ogg_packet oggpacket;
picture_t *p_pic; picture_t *p_pic;
mtime_t i_pts;
yuv_buffer yuv; yuv_buffer yuv;
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS ) decoder_sys_t *p_sys = p_dec->p_sys;
{
/* This should mean an eos */
return;
}
theora_decode_packetin( &p_dec->td, &oggpacket ); theora_decode_packetin( &p_sys->td, p_oggpacket );
/* Decode */ /* Decode */
theora_decode_YUVout( &p_dec->td, &yuv ); theora_decode_YUVout( &p_sys->td, &yuv );
/* Get a new picture */ /* Get a new picture */
while( !(p_pic = vout_CreatePicture( p_dec->p_vout, 0, 0, 0 ) ) ) while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
{ {
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
{ {
return; return VLC_EGENERIC;
} }
msleep( VOUT_OUTMEM_SLEEP ); msleep( VOUT_OUTMEM_SLEEP );
} }
if( !p_pic ) if( !p_pic ) return VLC_EGENERIC;
return;
theora_CopyPicture( p_dec, p_pic, &yuv ); theora_CopyPicture( p_dec, p_pic, &yuv );
vout_DatePicture( p_dec->p_vout, p_pic, i_pts ); vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts );
vout_DisplayPicture( p_dec->p_vout, p_pic ); vout_DisplayPicture( p_sys->p_vout, p_pic );
/* Date management */
p_sys->i_pts += ( 1000000 * p_sys->ti.fps_numerator /
p_sys->ti.fps_denominator ); /* 1 frame per packet */
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* GetOggPacket: get the following theora packet from the stream and send back * SendPacket: send an ogg packet to the stream output.
* the result in an ogg packet (for easy decoding by libtheora).
*****************************************************************************
* Returns VLC_EGENERIC in case of eof.
*****************************************************************************/ *****************************************************************************/
static int GetOggPacket( dec_thread_t *p_dec, ogg_packet *p_oggpacket, static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
mtime_t *p_pts )
{ {
if( p_dec->p_pes ) input_DeletePES( p_dec->p_fifo->p_packets_mgt, decoder_sys_t *p_sys = p_dec->p_sys;
p_dec->p_pes );
sout_buffer_t *p_sout_buffer =
sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes );
input_ExtractPES( p_dec->p_fifo, &p_dec->p_pes ); if( !p_sout_buffer ) return VLC_EGENERIC;
if( !p_dec->p_pes ) return VLC_EGENERIC;
p_oggpacket->packet = p_dec->p_pes->p_first->p_payload_start; p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
p_oggpacket->bytes = p_dec->p_pes->i_pes_size; p_oggpacket->packet,
p_oggpacket->granulepos = p_dec->p_pes->i_dts; p_oggpacket->bytes );
p_oggpacket->b_o_s = 0;
p_oggpacket->e_o_s = 0;
p_oggpacket->packetno = 0;
*p_pts = p_dec->p_pes->i_pts; /* Date management */
p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts;
p_sys->i_pts += ( 1000000 * p_sys->ti.fps_numerator /
p_sys->ti.fps_denominator ); /* 1 frame per packet */
if( p_sys->i_headers >= 3 )
p_sout_buffer->i_length = p_sys->i_pts - p_sout_buffer->i_pts;
else
p_sout_buffer->i_length = 0;
sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* CloseDecoder: theora decoder destruction * ParseTheoraComments: FIXME should be done in demuxer
*****************************************************************************/ *****************************************************************************/
static void CloseDecoder( dec_thread_t * p_dec ) static void ParseTheoraComments( decoder_t *p_dec )
{ {
input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
if( p_dec ) input_info_category_t *p_cat =
input_InfoCategory( p_input, _("Theora Comment") );
int i = 0;
char *psz_name, *psz_value, *psz_comment;
while ( i < p_dec->p_sys->tc.comments )
{ {
if( p_dec->p_pes ) psz_comment = strdup( p_dec->p_sys->tc.user_comments[i] );
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_dec->p_pes ); if( !psz_comment )
{
msg_Warn( p_dec, "Out of memory" );
break;
}
psz_name = psz_comment;
psz_value = strchr( psz_comment, '=' );
if( psz_value )
{
*psz_value = '\0';
psz_value++;
input_AddInfo( p_cat, psz_name, psz_value );
}
free( psz_comment );
i++;
}
}
/*****************************************************************************
* EndDecoder: theora decoder destruction
*****************************************************************************/
static int EndDecoder( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 ); if( !p_sys->b_packetizer )
vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
theora_info_clear( &p_dec->ti ); theora_info_clear( &p_sys->ti );
theora_comment_clear( &p_dec->tc ); theora_comment_clear( &p_sys->tc );
free( p_dec ); free( p_sys );
}
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* theora_CopyPicture: copy a picture from theora internal buffers to a * theora_CopyPicture: copy a picture from theora internal buffers to a
* picture_t structure. * picture_t structure.
*****************************************************************************/ *****************************************************************************/
static void theora_CopyPicture( dec_thread_t *p_dec, picture_t *p_pic, static void theora_CopyPicture( decoder_t *p_dec, picture_t *p_pic,
yuv_buffer *yuv ) yuv_buffer *yuv )
{ {
int i_plane, i_line, i_width, i_dst_stride, i_src_stride; int i_plane, i_line, i_width, i_dst_stride, i_src_stride;
int i_src_xoffset, i_src_yoffset;
u8 *p_dst, *p_src; u8 *p_dst, *p_src;
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
...@@ -318,12 +490,21 @@ static void theora_CopyPicture( dec_thread_t *p_dec, picture_t *p_pic, ...@@ -318,12 +490,21 @@ static void theora_CopyPicture( dec_thread_t *p_dec, picture_t *p_pic,
p_dst = p_pic->p[i_plane].p_pixels; p_dst = p_pic->p[i_plane].p_pixels;
p_src = i_plane ? (i_plane - 1 ? yuv->v : yuv->u ) : yuv->y; p_src = i_plane ? (i_plane - 1 ? yuv->v : yuv->u ) : yuv->y;
i_width = p_pic->p[i_plane].i_visible_pitch; i_width = p_pic->p[i_plane].i_visible_pitch;
i_dst_stride = p_pic->p[i_plane].i_pitch; i_dst_stride = p_pic->p[i_plane].i_pitch;
i_src_stride = i_plane ? yuv->uv_stride : yuv->y_stride; i_src_stride = i_plane ? yuv->uv_stride : yuv->y_stride;
i_src_xoffset = p_dec->p_sys->ti.offset_x;
i_src_yoffset = p_dec->p_sys->ti.offset_y;
if( i_plane )
{
i_src_xoffset /= 2;
i_src_yoffset /= 2;
}
p_src += (i_src_yoffset * i_src_stride + i_src_yoffset);
for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ ) for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
{ {
p_dec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width ); p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
p_src += i_src_stride; p_src += i_src_stride;
p_dst += i_dst_stride; p_dst += i_dst_stride;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vorbis.c: vorbis decoder module making use of libvorbis. * vorbis.c: vorbis decoder module making use of libvorbis.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: vorbis.c,v 1.16 2003/03/30 18:14:36 gbazin Exp $ * $Id: vorbis.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/aout.h> #include <vlc/aout.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#include <input_ext-dec.h> #include <input_ext-dec.h>
#include <vlc/input.h> #include <vlc/input.h>
...@@ -42,14 +44,17 @@ ...@@ -42,14 +44,17 @@
#endif #endif
/***************************************************************************** /*****************************************************************************
* dec_thread_t : vorbis decoder thread descriptor * decoder_sys_t : vorbis decoder descriptor
*****************************************************************************/ *****************************************************************************/
typedef struct dec_thread_t struct decoder_sys_t
{ {
/* Module mode */
vlc_bool_t b_packetizer;
/* /*
* Thread properties * Input properties
*/ */
vlc_thread_t thread_id; /* id for thread functions */ int i_headers;
/* /*
* Vorbis properties * Vorbis properties
...@@ -62,21 +67,26 @@ typedef struct dec_thread_t ...@@ -62,21 +67,26 @@ typedef struct dec_thread_t
* decoder */ * decoder */
vorbis_block vb; /* local working space for packet->PCM decode */ vorbis_block vb; /* local working space for packet->PCM decode */
/*
* Input properties
*/
decoder_fifo_t *p_fifo; /* stores the PES stream data */
pes_packet_t *p_pes; /* current PES we are decoding */
/* /*
* Output properties * Output properties
*/ */
aout_instance_t *p_aout; aout_instance_t *p_aout;
aout_input_t *p_aout_input; aout_input_t *p_aout_input;
audio_sample_format_t output_format; audio_sample_format_t aout_format;
audio_date_t end_date;
} dec_thread_t; /*
* Packetizer output properties
*/
sout_packetizer_input_t *p_sout_input;
sout_format_t sout_format;
/*
* Common properties
*/
audio_date_t end_date;
int i_last_block_size;
};
static int pi_channels_maps[6] = static int pi_channels_maps[6] =
{ {
...@@ -89,15 +99,21 @@ static int pi_channels_maps[6] = ...@@ -89,15 +99,21 @@ static int pi_channels_maps[6] =
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
}; };
/***************************************************************************** /****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ ****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int OpenPacketizer( vlc_object_t * );
static void CloseDecoder ( dec_thread_t * );
static int InitDecoder ( decoder_t * );
static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static void DecodePacket ( dec_thread_t * ); static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t );
static int GetOggPacket ( dec_thread_t *, ogg_packet *, mtime_t * ); static int DecodePacket ( decoder_t *, ogg_packet * );
static int SendPacket ( decoder_t *, ogg_packet * );
static void ParseVorbisComments( decoder_t * );
#ifdef MODULE_NAME_IS_tremor #ifdef MODULE_NAME_IS_tremor
static void Interleave ( int32_t *, const int32_t **, int, int ); static void Interleave ( int32_t *, const int32_t **, int, int );
...@@ -116,6 +132,11 @@ vlc_module_begin(); ...@@ -116,6 +132,11 @@ vlc_module_begin();
set_capability( "decoder", 100 ); set_capability( "decoder", 100 );
#endif #endif
set_callbacks( OpenDecoder, NULL ); set_callbacks( OpenDecoder, NULL );
add_submodule();
set_description( _("Vorbis audio packetizer") );
set_capability( "packetizer", 100 );
set_callbacks( OpenPacketizer, NULL );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -123,256 +144,381 @@ vlc_module_end(); ...@@ -123,256 +144,381 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this ) static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('v','o','r','b') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('v','o','r','b') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC;
}
p_dec->p_sys->b_packetizer = VLC_FALSE;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int OpenPacketizer( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
int i_ret = OpenDecoder( p_this );
if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
return i_ret;
}
/***************************************************************************** /*****************************************************************************
* RunDecoder: the vorbis decoder * InitDecoder: Initalize the decoder
*****************************************************************************/ *****************************************************************************/
static int RunDecoder( decoder_fifo_t * p_fifo ) static int InitDecoder( decoder_t *p_dec )
{ {
dec_thread_t *p_dec; decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
mtime_t i_pts;
/* Allocate the memory needed to store the thread's structure */ aout_DateSet( &p_sys->end_date, 0 );
if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )
== NULL)
{
msg_Err( p_fifo, "out of memory" );
goto error;
}
/* Initialize the thread properties */ p_sys->p_aout = NULL;
memset( p_dec, 0, sizeof(dec_thread_t) ); p_sys->p_aout_input = NULL;
p_dec->p_fifo = p_fifo; p_sys->aout_format.i_format = VLC_FOURCC('v','o','r','b');
p_dec->p_pes = NULL;
/* Take care of the initial Vorbis header */ p_sys->p_sout_input = NULL;
vorbis_info_init( &p_dec->vi ); p_sys->sout_format.i_cat = AUDIO_ES;
vorbis_comment_init( &p_dec->vc ); p_sys->sout_format.i_fourcc = VLC_FOURCC( 'v', 'o', 'r', 'b' );
p_sys->sout_format.i_block_align = 0;
p_sys->sout_format.i_bitrate = 0;
p_sys->sout_format.i_extra_data = 0;
p_sys->sout_format.p_extra_data = NULL;
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS ) /* Take care of vorbis init */
goto error; vorbis_info_init( &p_sys->vi );
vorbis_comment_init( &p_sys->vc );
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ p_sys->i_headers = 0;
if( vorbis_synthesis_headerin( &p_dec->vi, &p_dec->vc, &oggpacket ) < 0 )
{
msg_Err( p_dec->p_fifo, "This bitstream does not contain Vorbis "
"audio data");
goto error;
}
/* The next two packets in order are the comment and codebook headers. return VLC_SUCCESS;
We need to watch out that these packets are not missing as a }
missing or corrupted header is fatal. */
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( vorbis_synthesis_headerin( &p_dec->vi, &p_dec->vc, &oggpacket ) < 0 ) /****************************************************************************
{ * RunDecoder: the whole thing
msg_Err( p_dec->p_fifo, "2nd Vorbis header is corrupted" ); ****************************************************************************
goto error; * This function must be fed with ogg packets.
} ****************************************************************************/
/* parse the vorbis comment. FIXME should be done in demuxer*/ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
int i_ret;
/* Block to Ogg packet */
oggpacket.packet = p_block->p_buffer;
oggpacket.bytes = p_block->i_buffer;
oggpacket.granulepos = p_block->i_dts;
oggpacket.b_o_s = 0;
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
if( p_sys->i_headers == 0 )
{ {
input_thread_t *p_input = (input_thread_t *)p_fifo->p_parent; /* Take care of the initial Vorbis header */
input_info_category_t *p_cat = input_InfoCategory( p_input,
_("Vorbis Comment") ); oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
int i = 0; if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc,
char *psz_name, *psz_value, *psz_comment; &oggpacket ) < 0 )
while ( i < p_dec->vc.comments ) {
msg_Err( p_dec->p_fifo, "This bitstream does not contain Vorbis "
"audio data");
block_Release( p_block );
return VLC_EGENERIC;
}
p_sys->i_headers++;
if( p_sys->b_packetizer )
{ {
psz_comment = strdup( p_dec->vc.user_comments[i] ); /* add a input for the stream ouput */
if ( !psz_comment ) p_sys->sout_format.i_sample_rate = p_sys->vi.rate;
p_sys->sout_format.i_channels = p_sys->vi.channels;
p_sys->sout_format.i_block_align = 1;
p_sys->sout_format.i_bitrate = p_sys->vi.bitrate_nominal;
p_sys->p_sout_input =
sout_InputNew( p_dec, &p_sys->sout_format );
if( !p_sys->p_sout_input )
{ {
msg_Warn( p_dec->p_fifo, "Out of memory" ); msg_Err( p_dec, "cannot add a new stream" );
break; block_Release( p_block );
return VLC_EGENERIC;
} }
psz_name = psz_comment; }
psz_value = strchr( psz_comment, '=' ); else
if( psz_value ) {
#ifdef MODULE_NAME_IS_tremor
p_sys->aout_format.i_format = VLC_FOURCC('f','i','3','2');
#else
p_sys->aout_format.i_format = VLC_FOURCC('f','l','3','2');
#endif
p_sys->aout_format.i_physical_channels =
p_sys->aout_format.i_original_channels =
pi_channels_maps[p_sys->vi.channels];
p_sys->aout_format.i_rate = p_sys->vi.rate;
p_sys->p_aout = NULL;
p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout,
&p_sys->aout_format );
if( p_sys->p_aout_input == NULL )
{ {
*psz_value = '\0'; msg_Err( p_dec, "failed to create aout fifo" );
psz_value++; block_Release( p_block );
input_AddInfo( p_cat, psz_name, psz_value ); return VLC_EGENERIC;
} }
free( psz_comment );
i++;
} }
}
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( vorbis_synthesis_headerin( &p_dec->vi, &p_dec->vc, &oggpacket ) < 0 ) aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
{
msg_Err( p_dec->p_fifo, "3rd Vorbis header is corrupted" );
goto error;
}
/* Initialize the Vorbis packet->PCM decoder */ msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
vorbis_synthesis_init( &p_dec->vd, &p_dec->vi ); p_sys->vi.channels, p_sys->vi.rate,
vorbis_block_init( &p_dec->vd, &p_dec->vb ); p_sys->vi.bitrate_nominal );
#ifdef MODULE_NAME_IS_tremor if( p_sys->b_packetizer )
p_dec->output_format.i_format = VLC_FOURCC('f','i','3','2'); {
#else i_ret = SendPacket( p_dec, &oggpacket );
p_dec->output_format.i_format = VLC_FOURCC('f','l','3','2'); block_Release( p_block );
#endif return i_ret;
p_dec->output_format.i_physical_channels = }
p_dec->output_format.i_original_channels = else
pi_channels_maps[p_dec->vi.channels]; {
p_dec->output_format.i_rate = p_dec->vi.rate; block_Release( p_block );
return VLC_SUCCESS;
aout_DateInit( &p_dec->end_date, p_dec->vi.rate ); }
p_dec->p_aout = NULL;
p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
&p_dec->p_aout,
&p_dec->output_format );
if( p_dec->p_aout_input == NULL )
{
msg_Err( p_dec->p_fifo, "failed to create aout fifo" );
goto error;
} }
/* vorbis decoder thread's main loop */ if( p_sys->i_headers == 1 )
while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
{ {
DecodePacket( p_dec ); /* The next packet in order is the comments header */
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
< 0 )
{
msg_Err( p_dec, "2nd Vorbis header is corrupted" );
return VLC_EGENERIC;
}
p_sys->i_headers++;
ParseVorbisComments( p_dec );
if( p_sys->b_packetizer )
{
i_ret = SendPacket( p_dec, &oggpacket );
block_Release( p_block );
return i_ret;
}
else
{
block_Release( p_block );
return VLC_SUCCESS;
}
} }
/* If b_error is set, the vorbis decoder thread enters the error loop */ if( p_sys->i_headers == 2 )
if( p_dec->p_fifo->b_error )
{ {
DecoderError( p_dec->p_fifo ); /* The next packet in order is the codebooks header
We need to watch out that this packet is not missing as a
missing or corrupted header is fatal. */
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
< 0 )
{
msg_Err( p_dec, "3rd Vorbis header is corrupted" );
return VLC_EGENERIC;
}
p_sys->i_headers++;
if( !p_sys->b_packetizer )
{
/* Initialize the Vorbis packet->PCM decoder */
vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
vorbis_block_init( &p_sys->vd, &p_sys->vb );
}
if( p_sys->b_packetizer )
{
i_ret = SendPacket( p_dec, &oggpacket );
block_Release( p_block );
return i_ret;
}
else
{
block_Release( p_block );
return VLC_SUCCESS;
}
} }
/* End of the vorbis decoder thread */ i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
CloseDecoder( p_dec ); block_Release( p_block );
return i_ret;
}
return 0; /*****************************************************************************
* ProcessPacket: processes a Vorbis packet.
*****************************************************************************/
static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
mtime_t i_pts )
{
decoder_sys_t *p_sys = p_dec->p_sys;
error: /* Date management */
DecoderError( p_fifo ); if( i_pts > 0 && i_pts != aout_DateGet( &p_sys->end_date ) )
if( p_dec )
{ {
if( p_dec->p_fifo ) aout_DateSet( &p_sys->end_date, i_pts );
p_dec->p_fifo->b_error = 1;
/* End of the vorbis decoder thread */
CloseDecoder( p_dec );
} }
return -1; if( p_sys->b_packetizer )
{
return SendPacket( p_dec, p_oggpacket );
}
else
{
return DecodePacket( p_dec, p_oggpacket );
}
} }
/***************************************************************************** /*****************************************************************************
* DecodePacket: decodes a Vorbis packet. * DecodePacket: decodes a Vorbis packet.
*****************************************************************************/ *****************************************************************************/
static void DecodePacket( dec_thread_t *p_dec ) static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
{ {
aout_buffer_t *p_aout_buffer; decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket; int i_samples;
#ifdef MODULE_NAME_IS_tremor #ifdef MODULE_NAME_IS_tremor
int32_t **pp_pcm; int32_t **pp_pcm;
#else #else
float **pp_pcm; float **pp_pcm;
#endif #endif
int i_samples;
mtime_t i_pts;
if( GetOggPacket( p_dec, &oggpacket, &i_pts ) != VLC_SUCCESS ) if( vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
{ vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );
/* This should mean an eos */
return;
}
/* Date management */
if( i_pts > 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
{
aout_DateSet( &p_dec->end_date, i_pts );
}
if( vorbis_synthesis( &p_dec->vb, &oggpacket ) == 0 )
vorbis_synthesis_blockin( &p_dec->vd, &p_dec->vb );
/* **pp_pcm is a multichannel float vector. In stereo, for /* **pp_pcm is a multichannel float vector. In stereo, for
* example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
* the size of each channel. Convert the float values * the size of each channel. Convert the float values
* (-1.<=range<=1.) to whatever PCM format and write it out */ * (-1.<=range<=1.) to whatever PCM format and write it out */
while( ( i_samples = vorbis_synthesis_pcmout( &p_dec->vd, &pp_pcm ) ) > 0 ) while( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
{ {
p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input, aout_buffer_t *p_aout_buffer;
p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
i_samples ); i_samples );
if( !p_aout_buffer ) if( !p_aout_buffer )
{ {
msg_Err( p_dec->p_fifo, "cannot get aout buffer" ); msg_Err( p_dec, "cannot get aout buffer" );
p_dec->p_fifo->b_error = 1; return VLC_SUCCESS;
return;
} }
/* Interleave the samples */ /* Interleave the samples */
#ifdef MODULE_NAME_IS_tremor #ifdef MODULE_NAME_IS_tremor
Interleave( (int32_t *)p_aout_buffer->p_buffer, Interleave( (int32_t *)p_aout_buffer->p_buffer,
(const int32_t **)pp_pcm, p_dec->vi.channels, i_samples ); (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples );
#else #else
Interleave( (float *)p_aout_buffer->p_buffer, Interleave( (float *)p_aout_buffer->p_buffer,
(const float **)pp_pcm, p_dec->vi.channels, i_samples ); (const float **)pp_pcm, p_sys->vi.channels, i_samples );
#endif #endif
/* Tell libvorbis how many samples we actually consumed */ /* Tell libvorbis how many samples we actually consumed */
vorbis_synthesis_read( &p_dec->vd, i_samples ); vorbis_synthesis_read( &p_sys->vd, i_samples );
/* Date management */ /* Date management */
p_aout_buffer->start_date = aout_DateGet( &p_dec->end_date ); p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date, p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
i_samples ); i_samples );
aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer ); aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer );
} }
} }
/***************************************************************************** /*****************************************************************************
* GetOggPacket: get the following vorbis packet from the stream and send back * SendPacket: send an ogg packet to the stream output.
* the result in an ogg packet (for easy decoding by libvorbis).
*****************************************************************************
* Returns VLC_EGENERIC in case of eof.
*****************************************************************************/ *****************************************************************************/
static int GetOggPacket( dec_thread_t *p_dec, ogg_packet *p_oggpacket, static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
mtime_t *p_pts )
{ {
if( p_dec->p_pes ) input_DeletePES( p_dec->p_fifo->p_packets_mgt, decoder_sys_t *p_sys = p_dec->p_sys;
p_dec->p_pes ); int i_block_size, i_samples;
sout_buffer_t *p_sout_buffer =
sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes );
input_ExtractPES( p_dec->p_fifo, &p_dec->p_pes ); if( !p_sout_buffer ) return VLC_EGENERIC;
if( !p_dec->p_pes ) return VLC_EGENERIC;
p_oggpacket->packet = p_dec->p_pes->p_first->p_payload_start; i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
p_oggpacket->bytes = p_dec->p_pes->i_pes_size; if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
p_oggpacket->granulepos = p_dec->p_pes->i_dts; i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
p_oggpacket->b_o_s = 0; p_sys->i_last_block_size = i_block_size;
p_oggpacket->e_o_s = 0;
p_oggpacket->packetno = 0;
*p_pts = p_dec->p_pes->i_pts; p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
p_oggpacket->packet,
p_oggpacket->bytes );
p_sout_buffer->i_bitrate = p_sys->vi.bitrate_nominal;
/* Date management */
p_sout_buffer->i_dts = p_sout_buffer->i_pts =
aout_DateGet( &p_sys->end_date );
if( p_sys->i_headers >= 3 )
p_sout_buffer->i_length =
aout_DateIncrement( &p_sys->end_date, i_samples ) -
p_sout_buffer->i_pts;
else
p_sout_buffer->i_length = 0;
sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/*****************************************************************************
* ParseVorbisComments: FIXME should be done in demuxer
*****************************************************************************/
static void ParseVorbisComments( decoder_t *p_dec )
{
input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
input_info_category_t *p_cat =
input_InfoCategory( p_input, _("Vorbis Comment") );
int i = 0;
char *psz_name, *psz_value, *psz_comment;
while ( i < p_dec->p_sys->vc.comments )
{
psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
if( !psz_comment )
{
msg_Warn( p_dec, "Out of memory" );
break;
}
psz_name = psz_comment;
psz_value = strchr( psz_comment, '=' );
if( psz_value )
{
*psz_value = '\0';
psz_value++;
input_AddInfo( p_cat, psz_name, psz_value );
}
free( psz_comment );
i++;
}
}
/***************************************************************************** /*****************************************************************************
* Interleave: helper function to interleave channels * Interleave: helper function to interleave channels
*****************************************************************************/ *****************************************************************************/
...@@ -395,23 +541,32 @@ static void Interleave( float *p_out, const float **pp_in, ...@@ -395,23 +541,32 @@ static void Interleave( float *p_out, const float **pp_in,
} }
/***************************************************************************** /*****************************************************************************
* CloseDecoder: vorbis decoder destruction * EndDecoder: vorbis decoder destruction
*****************************************************************************/ *****************************************************************************/
static void CloseDecoder( dec_thread_t * p_dec ) static int EndDecoder( decoder_t * p_dec )
{ {
if( p_dec->p_aout_input != NULL ) decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->p_aout_input != NULL )
{
aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
}
if( p_sys->p_sout_input != NULL )
{ {
aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input ); sout_InputDelete( p_sys->p_sout_input );
} }
if( p_dec ) if( !p_sys->b_packetizer && p_sys->i_headers >= 3 )
{ {
if( p_dec->p_pes ) vorbis_block_clear( &p_sys->vb );
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_dec->p_pes ); vorbis_dsp_clear( &p_sys->vd );
vorbis_block_clear( &p_dec->vb );
vorbis_dsp_clear( &p_dec->vd );
vorbis_comment_clear( &p_dec->vc );
vorbis_info_clear( &p_dec->vi ); /* must be called last */
free( p_dec );
} }
vorbis_comment_clear( &p_sys->vc );
vorbis_info_clear( &p_sys->vi ); /* must be called last */
free( p_sys );
return VLC_SUCCESS;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* xvid.c: a decoder for libxvidcore, the Xvid video codec * xvid.c: a decoder for libxvidcore, the Xvid video codec
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: xvid.c,v 1.5 2003/02/20 01:52:45 sigmunau Exp $ * $Id: xvid.c,v 1.6 2003/09/02 20:19:25 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -59,16 +59,16 @@ vlc_module_end(); ...@@ -59,16 +59,16 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t *p_this ) static int OpenDecoder ( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('x','v','i','d') if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('x','v','i','d')
&& p_fifo->i_fourcc != VLC_FOURCC('X','V','I','D') && p_dec->p_fifo->i_fourcc != VLC_FOURCC('X','V','I','D')
&& p_fifo->i_fourcc != VLC_FOURCC('D','I','V','X') ) && p_dec->p_fifo->i_fourcc != VLC_FOURCC('D','I','V','X') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = RunDecoder; p_dec->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -271,4 +271,3 @@ static int RunDecoder ( decoder_fifo_t *p_fifo ) ...@@ -271,4 +271,3 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ogg.c : ogg stream input module for vlc * ogg.c : ogg stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: ogg.c,v 1.31 2003/08/17 23:02:52 fenrir Exp $ * $Id: ogg.c,v 1.32 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -601,7 +601,7 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -601,7 +601,7 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
i_keyframe_frequency_force >>= 1; i_keyframe_frequency_force >>= 1;
} }
p_stream->f_rate = (float)i_fps_numerator / p_stream->f_rate = ((float)i_fps_numerator) /
i_fps_denominator; i_fps_denominator;
msg_Dbg( p_input, msg_Dbg( p_input,
"found theora header, bitrate: %i, rate: %f", "found theora header, bitrate: %i, rate: %f",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dec_dummy.c: dummy decoder plugin for vlc. * dec_dummy.c: dummy decoder plugin for vlc.
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: decoder.c,v 1.5 2003/03/03 16:49:14 gbazin Exp $ * $Id: decoder.c,v 1.6 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -56,7 +56,7 @@ static int Run ( decoder_fifo_t * ); ...@@ -56,7 +56,7 @@ static int Run ( decoder_fifo_t * );
*****************************************************************************/ *****************************************************************************/
int E_(OpenDecoder) ( vlc_object_t *p_this ) int E_(OpenDecoder) ( vlc_object_t *p_this )
{ {
((decoder_fifo_t*)p_this)->pf_run = Run; ((decoder_t*)p_this)->pf_run = Run;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
SOURCES_packetizer_copy = copy.c SOURCES_packetizer_copy = copy.c
SOURCES_packetizer_a52 = a52.c
SOURCES_packetizer_mpegaudio = mpegaudio.c SOURCES_packetizer_mpegaudio = mpegaudio.c
SOURCES_packetizer_mpegvideo = mpegvideo.c SOURCES_packetizer_mpegvideo = mpegvideo.c
SOURCES_packetizer_mpeg4video = mpeg4video.c SOURCES_packetizer_mpeg4video = mpeg4video.c
SOURCES_packetizer_mpeg4audio = mpeg4audio.c SOURCES_packetizer_mpeg4audio = mpeg4audio.c
SOURCES_packetizer_vorbis = vorbis.c
/*****************************************************************************
* a52.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: a52.c,v 1.5 2003/05/03 02:09:41 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strdup() */
#include "codecs.h" /* WAVEFORMATEX BITMAPINFOHEADER */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
typedef struct packetizer_s
{
/* Input properties */
decoder_fifo_t *p_fifo;
bit_stream_t bit_stream;
/* Output properties */
sout_packetizer_input_t *p_sout_input;
sout_format_t output_format;
uint64_t i_samplescount;
mtime_t i_last_pts;
} packetizer_t;
static int Open ( vlc_object_t * );
static int Run ( decoder_fifo_t * );
static int InitThread ( packetizer_t * );
static void PacketizeThread ( packetizer_t * );
static void EndThread ( packetizer_t * );
static int SyncInfo( const byte_t *, int *, int *, int * );
#define FREE( p ) if( p ) free( p ); p = NULL
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("A/52 audio packetizer") );
set_capability( "packetizer", 10 );
set_callbacks( Open, NULL );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the packetizer and return score
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to choose.
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
if( p_fifo->i_fourcc != VLC_FOURCC( 'a', '5', '2', ' ') &&
p_fifo->i_fourcc != VLC_FOURCC( 'a', '5', '2', 'b') )
{
return VLC_EGENERIC;
}
p_fifo->pf_run = Run;
return VLC_SUCCESS;
}
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
*****************************************************************************/
static int Run( decoder_fifo_t *p_fifo )
{
packetizer_t *p_pack;
int b_error;
msg_Info( p_fifo, "Running A/52 packetizer" );
if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return( -1 );
}
memset( p_pack, 0, sizeof( packetizer_t ) );
p_pack->p_fifo = p_fifo;
if( InitThread( p_pack ) != 0 )
{
DecoderError( p_fifo );
return( -1 );
}
while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
{
PacketizeThread( p_pack );
}
if( ( b_error = p_pack->p_fifo->b_error ) )
{
DecoderError( p_pack->p_fifo );
}
EndThread( p_pack );
if( b_error )
{
return( -1 );
}
return( 0 );
}
/*****************************************************************************
* InitThread: initialize data before entering main loop
*****************************************************************************/
static int InitThread( packetizer_t *p_pack )
{
p_pack->output_format.i_cat = AUDIO_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
p_pack->p_sout_input = NULL;
p_pack->i_samplescount = 0;
p_pack->i_last_pts = 0;
if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
NULL, NULL ) != VLC_SUCCESS )
{
msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
return -1;
}
return( 0 );
}
/*****************************************************************************
* PacketizeThread: packetize an unit (here copy a complete pes)
*****************************************************************************/
static void PacketizeThread( packetizer_t *p_pack )
{
sout_buffer_t *p_sout_buffer;
uint8_t p_header[7];
int i_channels, i_samplerate, i_bitrate;
int i_framelength;
mtime_t i_pts;
/* search a valid start code */
for( ;; )
{
int i_skip = 0;
RealignBits( &p_pack->bit_stream );
while( ShowBits( &p_pack->bit_stream, 16 ) != 0x0b77 &&
!p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
{
RemoveBits( &p_pack->bit_stream, 8 );
i_skip++;
}
if( i_skip )
{
msg_Warn( p_pack->p_fifo, "trashing %d bytes", i_skip );
}
if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
{
return;
}
/* Set the Presentation Time Stamp */
NextPTS( &p_pack->bit_stream, &i_pts, NULL );
GetChunk( &p_pack->bit_stream, p_header, 7 );
if( p_pack->p_fifo->b_die ) return;
/* Check if frame is valid and get frame info */
i_framelength = SyncInfo( p_header, &i_channels, &i_samplerate,
&i_bitrate );
if( !i_framelength )
{
msg_Warn( p_pack->p_fifo, "invalid header found" );
continue;
}
else
{
// msg_Dbg( p_pack->p_fifo, "frame length %d b", i_framelength );
break;
}
}
if( !p_pack->p_sout_input )
{
p_pack->output_format.i_sample_rate = i_samplerate;
p_pack->output_format.i_channels = i_channels;
p_pack->output_format.i_block_align = 0;
p_pack->output_format.i_bitrate = 0;
p_pack->output_format.i_extra_data = 0;
p_pack->output_format.p_extra_data = NULL;
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo,
&p_pack->output_format );
if( !p_pack->p_sout_input )
{
msg_Err( p_pack->p_fifo,
"cannot add a new stream" );
p_pack->p_fifo->b_error = 1;
return;
}
msg_Info( p_pack->p_fifo,
"A/52 channels:%d samplerate:%d bitrate:%d",
i_channels, i_samplerate, i_bitrate );
}
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
return;
}
/* fix pts */
if( i_pts <= 0 )
{
i_pts = p_pack->i_last_pts +
(uint64_t)1000000 *
(uint64_t)A52_FRAME_NB /
(uint64_t)i_samplerate;
}
p_pack->i_last_pts = i_pts;
p_sout_buffer =
sout_BufferNew( p_pack->p_sout_input->p_sout, i_framelength );
if( !p_sout_buffer )
{
p_pack->p_fifo->b_error = 1;
return;
}
memcpy( p_sout_buffer->p_buffer, p_header, 7 );
p_sout_buffer->i_bitrate = i_bitrate;
p_sout_buffer->i_pts =
p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_length =
(uint64_t)1000000 *
(uint64_t)A52_FRAME_NB /
(uint64_t)i_samplerate;
p_pack->i_samplescount += A52_FRAME_NB;
/* we are already aligned */
GetChunk( &p_pack->bit_stream,
p_sout_buffer->p_buffer + 7,
i_framelength - 7 );
sout_InputSendBuffer( p_pack->p_sout_input,
p_sout_buffer );
}
/*****************************************************************************
* EndThread : packetizer thread destruction
*****************************************************************************/
static void EndThread ( packetizer_t *p_pack)
{
if( p_pack->p_sout_input )
{
sout_InputDelete( p_pack->p_sout_input );
}
free( p_pack );
}
/*****************************************************************************
* SyncInfo: parse A52 sync info
*****************************************************************************
* This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
* since we don't want to oblige S/PDIF people to use liba52 just to get
* their SyncInfo...
* fenrir: I've change it to report channels count
*****************************************************************************/
static int SyncInfo( const byte_t * p_buf, int * pi_channels,
int * pi_sample_rate, int * pi_bit_rate )
{
static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
128, 160, 192, 224, 256, 320, 384, 448,
512, 576, 640 };
static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
0x04, 0x01, 0x04, 0x01 };
static const int acmod_to_channels[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
int frmsizecod;
int bitrate;
int half;
int acmod;
if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */
return 0;
if (p_buf[5] >= 0x60) /* bsid >= 12 */
return 0;
half = halfrate[p_buf[5] >> 3];
/* acmod, dsurmod and lfeon */
acmod = p_buf[6] >> 5;
if ( (p_buf[6] & 0xf8) == 0x50 )
{
/* Dolby surround = stereo + Dolby */
/* *pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_DOLBYSTEREO;*/
*pi_channels = 2; /* FIXME ??? */
}
else
{
*pi_channels = acmod_to_channels[acmod&0x07];
}
if ( p_buf[6] & lfeon[acmod] ) *pi_channels += 1;//|= AOUT_CHAN_LFEA;
frmsizecod = p_buf[4] & 63;
if (frmsizecod >= 38)
return 0;
bitrate = rate [frmsizecod >> 1];
*pi_bit_rate = (bitrate * 1000) >> half;
switch (p_buf[4] & 0xc0) {
case 0:
*pi_sample_rate = 48000 >> half;
return 4 * bitrate;
case 0x40:
*pi_sample_rate = 44100 >> half;
return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
case 0x80:
*pi_sample_rate = 32000 >> half;
return 6 * bitrate;
default:
return 0;
}
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* copy.c * copy.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: copy.c,v 1.15 2003/08/11 20:19:45 fenrir Exp $ * $Id: copy.c,v 1.16 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -80,9 +80,9 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ); ...@@ -80,9 +80,9 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes );
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
p_fifo->pf_run = Run; p_dec->pf_run = Run;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -672,4 +672,3 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ) ...@@ -672,4 +672,3 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
*pp_pes = p_fifo->p_first; *pp_pes = p_fifo->p_first;
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg4audio.c * mpeg4audio.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4audio.c,v 1.6 2003/05/03 02:09:41 fenrir Exp $ * $Id: mpeg4audio.c,v 1.7 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -100,11 +100,11 @@ vlc_module_end(); ...@@ -100,11 +100,11 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
p_fifo->pf_run = Run; p_dec->pf_run = Run;
if( p_fifo->i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'a') ) if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'a') )
{ {
return( VLC_SUCCESS ); return( VLC_SUCCESS );
} }
...@@ -363,4 +363,3 @@ static void EndThread ( packetizer_thread_t *p_pack) ...@@ -363,4 +363,3 @@ static void EndThread ( packetizer_thread_t *p_pack)
} }
free( p_pack ); free( p_pack );
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg4video.c * mpeg4video.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4video.c,v 1.12 2003/05/03 02:09:41 fenrir Exp $ * $Id: mpeg4video.c,v 1.13 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -104,11 +104,11 @@ vlc_module_end(); ...@@ -104,11 +104,11 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
p_fifo->pf_run = Run; p_dec->pf_run = Run;
switch( p_fifo->i_fourcc ) switch( p_dec->p_fifo->i_fourcc )
{ {
case VLC_FOURCC( 'm', '4', 's', '2'): case VLC_FOURCC( 'm', '4', 's', '2'):
case VLC_FOURCC( 'M', '4', 'S', '2'): case VLC_FOURCC( 'M', '4', 'S', '2'):
...@@ -485,4 +485,3 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ) ...@@ -485,4 +485,3 @@ static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
*pp_pes = p_pes; *pp_pes = p_pes;
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpegaudio.c * mpegaudio.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegaudio.c,v 1.7 2003/08/26 23:12:37 fenrir Exp $ * $Id: mpegaudio.c,v 1.8 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -110,14 +110,14 @@ static int mpegaudio_samplerate[2][4] = /* version 1 then 2 */ ...@@ -110,14 +110,14 @@ static int mpegaudio_samplerate[2][4] = /* version 1 then 2 */
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') ) if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = Run; p_dec->pf_run = Run;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpegvideo.c * mpegvideo.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegvideo.c,v 1.18 2003/08/11 18:52:41 gbazin Exp $ * $Id: mpegvideo.c,v 1.19 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -98,16 +98,16 @@ vlc_module_end(); ...@@ -98,16 +98,16 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; decoder_t *p_dec = (decoder_t*)p_this;
if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'v') && if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'v') &&
p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '1') && p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '1') &&
p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '2') ) p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '2') )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_fifo->pf_run = Run; p_dec->pf_run = Run;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
/*****************************************************************************
* vorbis.c Vorbis audio packetizer
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: vorbis.c,v 1.1 2003/06/23 23:51:31 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strdup() */
#include "codecs.h" /* WAVEFORMATEX BITMAPINFOHEADER */
#include <ogg/ogg.h>
#include <vorbis/codec.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
typedef struct packetizer_s
{
/*
* Input properties
*/
decoder_fifo_t *p_fifo; /* stores the PES stream data */
pes_packet_t *p_pes; /* current PES we are decoding */
/* Output properties */
sout_packetizer_input_t *p_sout_input;
sout_format_t output_format;
/*
* Vorbis properties
*/
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user
* comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM
* decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
uint64_t i_samplescount;
mtime_t i_interpolated_pts;
int i_last_block_size;
} packetizer_t;
static int Open ( vlc_object_t * );
static int Run ( decoder_fifo_t * );
static int InitThread ( packetizer_t * );
static void PacketizeThread ( packetizer_t * );
static void EndThread ( packetizer_t * );
static int GetOggPacket( packetizer_t *, ogg_packet *, mtime_t * );
static int SendOggPacket( packetizer_t *, ogg_packet *, mtime_t, int );
#define FREE( p ) if( p ) free( p ); p = NULL
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Vorbis audio packetizer") );
set_capability( "packetizer", 50 );
set_callbacks( Open, NULL );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the packetizer and return score
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
if( p_fifo->i_fourcc != VLC_FOURCC( 'v', 'o', 'r', 'b') )
{
return VLC_EGENERIC;
}
p_fifo->pf_run = Run;
return VLC_SUCCESS;
}
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
*****************************************************************************/
static int Run( decoder_fifo_t *p_fifo )
{
packetizer_t *p_pack;
int b_error;
msg_Info( p_fifo, "Running vorbis packetizer" );
if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return -1;
}
memset( p_pack, 0, sizeof( packetizer_t ) );
p_pack->p_fifo = p_fifo;
if( InitThread( p_pack ) != 0 )
{
DecoderError( p_fifo );
return -1;
}
while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
{
PacketizeThread( p_pack );
}
if( ( b_error = p_pack->p_fifo->b_error ) )
{
DecoderError( p_pack->p_fifo );
}
EndThread( p_pack );
FREE( p_pack );
if( b_error )
{
return -1;
}
return 0;
}
/*****************************************************************************
* InitThread: initialize data before entering main loop
*****************************************************************************/
static int InitThread( packetizer_t *p_pack )
{
mtime_t i_pts;
ogg_packet oggpacket;
p_pack->output_format.i_cat = AUDIO_ES;
p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
p_pack->output_format.i_sample_rate = 0;
p_pack->output_format.i_channels = 0;
p_pack->output_format.i_block_align = 0;
p_pack->output_format.i_bitrate = 0;
p_pack->output_format.i_extra_data = 0;
p_pack->output_format.p_extra_data = NULL;
p_pack->p_sout_input = NULL;
p_pack->i_samplescount = 0;
p_pack->i_interpolated_pts = 0;
p_pack->p_pes = NULL;
/* Take care of vorbis init */
vorbis_info_init( &p_pack->vi );
vorbis_comment_init( &p_pack->vc );
/* Take care of the initial Vorbis headers */
if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
{
msg_Err( p_pack->p_fifo, "This bitstream does not contain Vorbis "
"audio data");
goto error;
}
/* add a input for the stream ouput */
p_pack->output_format.i_sample_rate = p_pack->vi.rate;
p_pack->output_format.i_channels = p_pack->vi.channels;
p_pack->output_format.i_block_align = 1;
p_pack->output_format.i_bitrate = p_pack->vi.bitrate_nominal;
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo, &p_pack->output_format );
if( !p_pack->p_sout_input )
{
msg_Err( p_pack->p_fifo, "cannot add a new stream" );
p_pack->p_fifo->b_error = 1;
goto error;
}
msg_Dbg( p_pack->p_fifo, "channels:%d samplerate:%d bitrate:%d",
p_pack->vi.channels, p_pack->vi.rate, p_pack->vi.bitrate_nominal);
if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
goto error;
/* The next two packets in order are the comment and codebook headers.
We need to watch out that these packets are not missing as a
missing or corrupted header is fatal. */
if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
{
msg_Err( p_pack->p_fifo, "2nd Vorbis header is corrupted" );
goto error;
}
if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
goto error;
if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
{
msg_Err( p_pack->p_fifo, "3rd Vorbis header is corrupted" );
goto error;
}
if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
goto error;
/* Initialize the Vorbis packet->PCM decoder */
vorbis_synthesis_init( &p_pack->vd, &p_pack->vi );
vorbis_block_init( &p_pack->vd, &p_pack->vb );
return 0;
error:
EndThread( p_pack );
return -1;
}
/*****************************************************************************
* PacketizeThread: packetize an unit (here copy a complete ogg packet)
*****************************************************************************/
static void PacketizeThread( packetizer_t *p_pack )
{
mtime_t i_pts;
int i_samples, i_block_size;
ogg_packet oggpacket;
/* Timestamp all the packets */
if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
goto error;
if( i_pts <= 0 && p_pack->i_interpolated_pts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
return;
}
if( i_pts > 0 ) p_pack->i_interpolated_pts = i_pts;
i_block_size = vorbis_packet_blocksize( &p_pack->vi, &oggpacket );
if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
i_samples = ( p_pack->i_last_block_size + i_block_size ) >> 2;
p_pack->i_last_block_size = i_block_size;
if( SendOggPacket( p_pack, &oggpacket, p_pack->i_interpolated_pts,
i_samples ) != VLC_SUCCESS )
goto error;
p_pack->i_interpolated_pts += 1000000 * (uint64_t)i_samples
/ p_pack->vi.rate;
return;
error:
p_pack->p_fifo->b_error = 1;
}
/*****************************************************************************
* EndThread : packetizer thread destruction
*****************************************************************************/
static void EndThread ( packetizer_t *p_pack)
{
if( p_pack->p_pes )
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pack->p_pes );
vorbis_block_clear( &p_pack->vb );
vorbis_dsp_clear( &p_pack->vd );
vorbis_comment_clear( &p_pack->vc );
vorbis_info_clear( &p_pack->vi ); /* must be called last */
if( p_pack->p_sout_input )
{
sout_InputDelete( p_pack->p_sout_input );
}
}
/*****************************************************************************
* GetOggPacket: get the following vorbis packet from the stream and send back
* the result in an ogg packet (for easy decoding by libvorbis).
*****************************************************************************
* Returns VLC_EGENERIC in case of eof.
*****************************************************************************/
static int GetOggPacket( packetizer_t *p_pack, ogg_packet *p_oggpacket,
mtime_t *p_pts )
{
if( p_pack->p_pes ) input_DeletePES( p_pack->p_fifo->p_packets_mgt,
p_pack->p_pes );
input_ExtractPES( p_pack->p_fifo, &p_pack->p_pes );
if( !p_pack->p_pes ) return VLC_EGENERIC;
p_oggpacket->packet = p_pack->p_pes->p_first->p_payload_start;
p_oggpacket->bytes = p_pack->p_pes->i_pes_size;
p_oggpacket->granulepos = p_pack->p_pes->i_dts;
p_oggpacket->b_o_s = 0;
p_oggpacket->e_o_s = 0;
p_oggpacket->packetno = 0;
*p_pts = p_pack->p_pes->i_pts;
return VLC_SUCCESS;
}
/*****************************************************************************
* SendOggPacket: send an ogg packet to the stream output.
*****************************************************************************
* Returns VLC_EGENERIC in case of error.
*****************************************************************************/
static int SendOggPacket( packetizer_t *p_pack, ogg_packet *p_oggpacket,
mtime_t i_pts, int i_samples )
{
sout_buffer_t *p_sout_buffer =
sout_BufferNew( p_pack->p_sout_input->p_sout, p_oggpacket->bytes );
if( !p_sout_buffer )
{
p_pack->p_fifo->b_error = 1;
return VLC_EGENERIC;
}
p_pack->p_fifo->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
p_oggpacket->packet,
p_oggpacket->bytes );
p_sout_buffer->i_bitrate = p_pack->vi.bitrate_nominal;
p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_pts = i_pts;
p_sout_buffer->i_length = 1000000 * (uint64_t)i_samples / p_pack->vi.rate;
p_pack->i_samplescount += i_samples;
sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );
return VLC_SUCCESS;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders * input_dec.c: Functions for the management of decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_dec.c,v 1.61 2003/07/23 01:13:48 gbazin Exp $ * $Id: input_dec.c,v 1.62 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -29,14 +29,15 @@ ...@@ -29,14 +29,15 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include "vlc_block.h"
#include "stream_control.h" #include "stream_control.h"
#include "input_ext-dec.h" #include "input_ext-dec.h"
#include "input_ext-intf.h" #include "input_ext-intf.h"
#include "input_ext-plugins.h" #include "input_ext-plugins.h"
static decoder_fifo_t * CreateDecoderFifo( input_thread_t *, static decoder_t * CreateDecoder( input_thread_t *, es_descriptor_t * );
es_descriptor_t * ); static int DecoderThread( decoder_t * );
static void DeleteDecoderFifo( decoder_fifo_t * ); static void DeleteDecoder( decoder_t * );
/***************************************************************************** /*****************************************************************************
* input_RunDecoder: spawns a new decoder thread * input_RunDecoder: spawns a new decoder thread
...@@ -45,19 +46,18 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input, ...@@ -45,19 +46,18 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
es_descriptor_t * p_es ) es_descriptor_t * p_es )
{ {
vlc_value_t val; vlc_value_t val;
decoder_fifo_t *p_fifo; decoder_t *p_dec;
int i_priority; int i_priority;
/* Create the decoder configuration structure */ /* Create the decoder configuration structure */
p_fifo = CreateDecoderFifo( p_input, p_es ); p_dec = CreateDecoder( p_input, p_es );
if( p_dec == NULL )
if( p_fifo == NULL )
{ {
msg_Err( p_input, "could not create decoder fifo" ); msg_Err( p_input, "could not create decoder" );
return NULL; return NULL;
} }
p_fifo->p_module = NULL; p_dec->p_module = NULL;
/* If we are in sout mode, search for packetizer module */ /* If we are in sout mode, search for packetizer module */
var_Get( p_input, "sout", &val ); var_Get( p_input, "sout", &val );
...@@ -77,24 +77,26 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input, ...@@ -77,24 +77,26 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
if( val.b_bool ) if( val.b_bool )
{ {
p_fifo->p_module = p_dec->p_module =
module_Need( p_fifo, "packetizer", "$packetizer" ); module_Need( p_dec, "packetizer", "$packetizer" );
} }
} }
else else
{ {
/* default Get a suitable decoder module */ /* default Get a suitable decoder module */
p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" ); p_dec->p_module = module_Need( p_dec, "decoder", "$codec" );
if( val.psz_string ) free( val.psz_string ); if( val.psz_string ) free( val.psz_string );
} }
if( p_fifo->p_module == NULL ) if( p_dec->p_module == NULL )
{ {
msg_Err( p_fifo, "no suitable decoder module for fourcc `%4.4s'.\nVLC probably does not support this sound or video format.", msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
(char*)&p_fifo->i_fourcc ); "VLC probably does not support this sound or video format.",
DeleteDecoderFifo( p_fifo ); (char*)&p_dec->p_fifo->i_fourcc );
vlc_object_destroy( p_fifo );
DeleteDecoder( p_dec );
vlc_object_destroy( p_dec );
return NULL; return NULL;
} }
...@@ -108,27 +110,29 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input, ...@@ -108,27 +110,29 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
} }
/* Spawn the decoder thread */ /* Spawn the decoder thread */
if( vlc_thread_create( p_fifo, "decoder", p_fifo->pf_run, if( vlc_thread_create( p_dec, "decoder", DecoderThread,
i_priority, VLC_FALSE ) ) i_priority, VLC_FALSE ) )
{ {
msg_Err( p_fifo, "cannot spawn decoder thread \"%s\"", msg_Err( p_dec, "cannot spawn decoder thread \"%s\"",
p_fifo->p_module->psz_object_name ); p_dec->p_module->psz_object_name );
module_Unneed( p_fifo, p_fifo->p_module ); module_Unneed( p_dec, p_dec->p_module );
DeleteDecoder( p_dec );
vlc_object_destroy( p_dec );
return NULL; return NULL;
} }
p_input->stream.b_changed = 1; p_input->stream.b_changed = 1;
return p_fifo; return p_dec->p_fifo;
} }
/***************************************************************************** /*****************************************************************************
* input_EndDecoder: kills a decoder thread and waits until it's finished * input_EndDecoder: kills a decoder thread and waits until it's finished
*****************************************************************************/ *****************************************************************************/
void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es ) void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
{ {
int i_dummy; int i_dummy;
decoder_t *p_dec = p_es->p_decoder_fifo->p_dec;
p_es->p_decoder_fifo->b_die = 1; p_es->p_decoder_fifo->b_die = 1;
...@@ -148,17 +152,17 @@ void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -148,17 +152,17 @@ void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
/* I thought that unlocking was better since thread join can be long /* I thought that unlocking was better since thread join can be long
* but it actually creates late pictures and freezes --stef */ * but it actually creates late pictures and freezes --stef */
/* vlc_mutex_unlock( &p_input->stream.stream_lock ); */ /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
vlc_thread_join( p_es->p_decoder_fifo ); vlc_thread_join( p_dec );
/* vlc_mutex_lock( &p_input->stream.stream_lock ); */ /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
/* Delete decoder configuration */
DeleteDecoderFifo( p_es->p_decoder_fifo );
/* Unneed module */ /* Unneed module */
module_Unneed( p_es->p_decoder_fifo, p_es->p_decoder_fifo->p_module ); module_Unneed( p_dec, p_dec->p_module );
/* Delete the fifo */ /* Delete decoder configuration */
vlc_object_destroy( p_es->p_decoder_fifo ); DeleteDecoder( p_dec );
/* Delete the decoder */
vlc_object_destroy( p_dec );
/* Tell the input there is no more decoder */ /* Tell the input there is no more decoder */
p_es->p_decoder_fifo = NULL; p_es->p_decoder_fifo = NULL;
...@@ -275,65 +279,161 @@ void input_EscapeAudioDiscontinuity( input_thread_t * p_input ) ...@@ -275,65 +279,161 @@ void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
/***************************************************************************** /*****************************************************************************
* CreateDecoderFifo: create a decoder_fifo_t * CreateDecoderFifo: create a decoder_fifo_t
*****************************************************************************/ *****************************************************************************/
static decoder_fifo_t * CreateDecoderFifo( input_thread_t * p_input, static decoder_t * CreateDecoder( input_thread_t * p_input,
es_descriptor_t * p_es ) es_descriptor_t * p_es )
{ {
decoder_fifo_t * p_fifo; decoder_t * p_dec;
/* Decoder FIFO */ p_dec = vlc_object_create( p_input, VLC_OBJECT_DECODER );
p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER ); if( p_dec == NULL )
if( p_fifo == NULL )
{ {
msg_Err( p_input, "out of memory" ); msg_Err( p_input, "out of memory" );
return NULL; return NULL;
} }
p_dec->pf_init = 0;
p_dec->pf_decode = 0;
p_dec->pf_end = 0;
p_dec->pf_run = 0;
/* Select a new ES */ /* Select a new ES */
INSERT_ELEM( p_input->stream.pp_selected_es, INSERT_ELEM( p_input->stream.pp_selected_es,
p_input->stream.i_selected_es_number, p_input->stream.i_selected_es_number,
p_input->stream.i_selected_es_number, p_input->stream.i_selected_es_number,
p_es ); p_es );
/* Allocate the memory needed to store the decoder's fifo */
//p_dec->p_fifo = (decoder_fifo_t *)malloc(sizeof(decoder_fifo_t));
p_dec->p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER_FIFO );
if( p_dec->p_fifo == NULL )
{
msg_Err( p_input, "out of memory" );
return NULL;
}
/* Initialize the decoder fifo */
//memset( p_dec->p_fifo, 0, sizeof(decoder_fifo_t) );
p_dec->p_module = NULL;
/* Initialize the p_fifo structure */ /* Initialize the p_fifo structure */
vlc_mutex_init( p_input, &p_fifo->data_lock ); vlc_mutex_init( p_input, &p_dec->p_fifo->data_lock );
vlc_cond_init( p_input, &p_fifo->data_wait ); vlc_cond_init( p_input, &p_dec->p_fifo->data_wait );
p_es->p_decoder_fifo = p_fifo; p_es->p_decoder_fifo = p_dec->p_fifo;
p_fifo->i_id = p_es->i_id; p_dec->p_fifo->i_id = p_es->i_id;
p_fifo->i_fourcc = p_es->i_fourcc; p_dec->p_fifo->i_fourcc = p_es->i_fourcc;
p_fifo->p_demux_data = p_es->p_demux_data; p_dec->p_fifo->p_demux_data = p_es->p_demux_data;
p_fifo->p_waveformatex = p_es->p_waveformatex; p_dec->p_fifo->p_waveformatex = p_es->p_waveformatex;
p_fifo->p_bitmapinfoheader = p_es->p_bitmapinfoheader; p_dec->p_fifo->p_bitmapinfoheader = p_es->p_bitmapinfoheader;
p_fifo->p_stream_ctrl = &p_input->stream.control; p_dec->p_fifo->p_stream_ctrl = &p_input->stream.control;
p_fifo->p_sout = p_input->stream.p_sout; p_dec->p_fifo->p_sout = p_input->stream.p_sout;
p_fifo->p_first = NULL; p_dec->p_fifo->p_first = NULL;
p_fifo->pp_last = &p_fifo->p_first; p_dec->p_fifo->pp_last = &p_dec->p_fifo->p_first;
p_fifo->i_depth = 0; p_dec->p_fifo->i_depth = 0;
p_fifo->b_die = p_fifo->b_error = 0; p_dec->p_fifo->b_die = p_dec->p_fifo->b_error = 0;
p_fifo->p_packets_mgt = p_input->p_method_data; p_dec->p_fifo->p_packets_mgt = p_input->p_method_data;
vlc_object_attach( p_fifo, p_input ); p_dec->p_fifo->p_dec = p_dec;
return p_fifo; vlc_object_attach( p_dec->p_fifo, p_input );
vlc_object_attach( p_dec, p_input );
return p_dec;
}
/*****************************************************************************
* DecoderThread: the decoding main loop
*****************************************************************************/
static int DecoderThread( decoder_t * p_dec )
{
pes_packet_t *p_pes;
data_packet_t *p_data;
block_t *p_block;
/* Temporary wrapper to keep old decoder api functional */
if( p_dec->pf_run )
{
p_dec->pf_run( p_dec->p_fifo );
return 0;
}
/* Initialize the decoder */
p_dec->p_fifo->b_error = p_dec->pf_init( p_dec );
/* The decoder's main loop */
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
{
int i_size;
input_ExtractPES( p_dec->p_fifo, &p_pes );
if( !p_pes )
{
p_dec->p_fifo->b_error = 1;
break;
}
for( i_size = 0, p_data = p_pes->p_first;
p_data != NULL; p_data = p_data->p_next )
{
i_size += p_data->p_payload_end - p_data->p_payload_start;
}
p_block = block_New( p_dec, i_size );
for( i_size = 0, p_data = p_pes->p_first;
p_data != NULL; p_data = p_data->p_next )
{
memcpy( p_block->p_buffer + i_size, p_data->p_payload_start,
p_data->p_payload_end - p_data->p_payload_start );
i_size += p_data->p_payload_end - p_data->p_payload_start;
}
p_block->i_pts = p_pes->i_pts;
p_block->i_dts = p_pes->i_dts;
p_dec->p_fifo->b_error = p_dec->pf_decode( p_dec, p_block );
input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
}
/* If b_error is set, the decoder thread enters the error loop */
if( p_dec->p_fifo->b_error )
{
/* Wait until a `die' order is sent */
while( !p_dec->p_fifo->b_die )
{
/* Trash all received PES packets */
input_ExtractPES( p_dec->p_fifo, NULL );
}
}
/* End of the decoder */
p_dec->pf_end( p_dec );
return 0;
} }
/***************************************************************************** /*****************************************************************************
* DeleteDecoderFifo: destroy a decoder_fifo_t * DeleteDecoderFifo: destroy a decoder_fifo_t
*****************************************************************************/ *****************************************************************************/
static void DeleteDecoderFifo( decoder_fifo_t * p_fifo ) static void DeleteDecoder( decoder_t * p_dec )
{ {
vlc_object_detach( p_fifo ); vlc_object_detach( p_dec );
vlc_object_detach( p_dec->p_fifo );
msg_Dbg( p_fifo, "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO", msg_Dbg( p_dec,
p_fifo->i_id, (char*)&p_fifo->i_fourcc, p_fifo->i_depth ); "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
p_dec->p_fifo->i_id, (char*)&p_dec->p_fifo->i_fourcc,
p_dec->p_fifo->i_depth );
/* Free all packets still in the decoder fifo. */ /* Free all packets still in the decoder fifo. */
input_DeletePES( p_fifo->p_packets_mgt, input_DeletePES( p_dec->p_fifo->p_packets_mgt,
p_fifo->p_first ); p_dec->p_fifo->p_first );
/* Destroy the lock and cond */ /* Destroy the lock and cond */
vlc_cond_destroy( &p_fifo->data_wait ); vlc_cond_destroy( &p_dec->p_fifo->data_wait );
vlc_mutex_destroy( &p_fifo->data_lock ); vlc_mutex_destroy( &p_dec->p_fifo->data_lock );
}
/* Free fifo */
vlc_object_destroy( p_dec->p_fifo );
//free( p_dec->p_fifo );
}
/***************************************************************************** /*****************************************************************************
* block.c * block.c: Data blocks management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: block.c,v 1.1 2003/08/23 22:49:50 fenrir Exp $ * $Id: block.c,v 1.2 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@videolan.org> * Authors: Laurent Aimar <fenrir@videolan.org>
* *
...@@ -38,8 +38,9 @@ struct block_sys_t ...@@ -38,8 +38,9 @@ struct block_sys_t
uint8_t *p_allocated_buffer; uint8_t *p_allocated_buffer;
int i_allocated_buffer; int i_allocated_buffer;
vlc_bool_t b_modify; /* has it be put in modify state */ vlc_bool_t b_modify; /* has it been put in modified state */
int i_duplicated; /* how many times it has been duplicated (only content) */ int i_duplicated; /* how many times has the content been
* duplicated */
}; };
...@@ -104,6 +105,7 @@ static block_t *BlockModify( block_t *p_block, vlc_bool_t b_will_modify ) ...@@ -104,6 +105,7 @@ static block_t *BlockModify( block_t *p_block, vlc_bool_t b_will_modify )
return p_mod; return p_mod;
} }
static block_t *BlockDuplicate( block_t *p_block ) static block_t *BlockDuplicate( block_t *p_block )
{ {
block_t *p_dup; block_t *p_dup;
...@@ -128,15 +130,16 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body ) ...@@ -128,15 +130,16 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
{ {
vlc_mutex_lock( &p_block->p_sys->lock ); vlc_mutex_lock( &p_block->p_sys->lock );
if( i_prebody < 0 || if( i_prebody < 0 || p_block->p_buffer - i_prebody >
( p_block->p_buffer - i_prebody > p_block->p_sys->p_allocated_buffer ) ) p_block->p_sys->p_allocated_buffer )
{ {
p_block->p_buffer -= i_prebody; p_block->p_buffer -= i_prebody;
p_block->i_buffer += i_prebody; p_block->i_buffer += i_prebody;
i_prebody = 0; i_prebody = 0;
} }
if( i_body < 0 || if( i_body < 0 ||
( p_block->p_buffer + i_body < p_block->p_sys->p_allocated_buffer + p_block->p_sys->i_allocated_buffer ) ) p_block->p_buffer + i_body < p_block->p_sys->p_allocated_buffer +
p_block->p_sys->i_allocated_buffer )
{ {
p_block->i_buffer = i_body; p_block->i_buffer = i_body;
i_body = 0; i_body = 0;
...@@ -147,7 +150,8 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body ) ...@@ -147,7 +150,8 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
{ {
block_t *p_rea = block_New( p_block->p_manager, i_prebody + i_body ); block_t *p_rea = block_New( p_block->p_manager, i_prebody + i_body );
memcpy( &p_rea->p_buffer[i_prebody], p_block->p_buffer, p_block->i_buffer ); memcpy( &p_rea->p_buffer[i_prebody], p_block->p_buffer,
p_block->i_buffer );
return p_rea; return p_rea;
} }
...@@ -160,7 +164,9 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body ) ...@@ -160,7 +164,9 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
i_start = p_rea->p_buffer - p_rea->p_sys->p_allocated_buffer; i_start = p_rea->p_buffer - p_rea->p_sys->p_allocated_buffer;
p_rea->p_sys->i_allocated_buffer += i_body - p_rea->i_buffer; p_rea->p_sys->i_allocated_buffer += i_body - p_rea->i_buffer;
p_rea->p_sys->p_allocated_buffer = realloc( p_rea->p_sys->p_allocated_buffer, p_rea->p_sys->i_allocated_buffer ); p_rea->p_sys->p_allocated_buffer =
realloc( p_rea->p_sys->p_allocated_buffer,
p_rea->p_sys->i_allocated_buffer );
p_rea->p_buffer = &p_rea->p_sys->p_allocated_buffer[i_start]; p_rea->p_buffer = &p_rea->p_sys->p_allocated_buffer[i_start];
p_rea->i_buffer = i_body; p_rea->i_buffer = i_body;
...@@ -170,6 +176,7 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body ) ...@@ -170,6 +176,7 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
return p_block; return p_block;
} }
/***************************************************************************** /*****************************************************************************
* Standard block management * Standard block management
* *
...@@ -203,7 +210,6 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size ) ...@@ -203,7 +210,6 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size )
block_t *p_block; block_t *p_block;
block_sys_t *p_sys; block_sys_t *p_sys;
p_block = block_NewEmpty(); p_block = block_NewEmpty();
p_block->i_buffer = i_size; p_block->i_buffer = i_size;
...@@ -218,7 +224,7 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size ) ...@@ -218,7 +224,7 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size )
p_block->pf_realloc = BlockRealloc; p_block->pf_realloc = BlockRealloc;
/* that should be ok (no comunication between multiple p_vlc) */ /* that should be ok (no comunication between multiple p_vlc) */
p_block->p_manager = p_obj->p_vlc; p_block->p_manager = VLC_OBJECT( p_obj->p_vlc );
p_block->p_sys = p_sys = malloc( sizeof( block_sys_t ) ); p_block->p_sys = p_sys = malloc( sizeof( block_sys_t ) );
vlc_mutex_init( p_obj, &p_sys->lock ); vlc_mutex_init( p_obj, &p_sys->lock );
...@@ -230,7 +236,7 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size ) ...@@ -230,7 +236,7 @@ block_t *__block_New( vlc_object_t *p_obj, int i_size )
return p_block; return p_block;
} }
void block_ChainAppend( block_t **pp_list, block_t *p_block ) void block_ChainAppend( block_t **pp_list, block_t *p_block )
{ {
if( *pp_list == NULL ) if( *pp_list == NULL )
...@@ -249,7 +255,7 @@ void block_ChainAppend( block_t **pp_list, block_t *p_block ) ...@@ -249,7 +255,7 @@ void block_ChainAppend( block_t **pp_list, block_t *p_block )
} }
} }
void block_ChainRelease( block_t *p_block ) void block_ChainRelease( block_t *p_block )
{ {
while( p_block ) while( p_block )
{ {
...@@ -320,7 +326,7 @@ block_t *block_ChainGather( block_t *p_list ) ...@@ -320,7 +326,7 @@ block_t *block_ChainGather( block_t *p_list )
/***************************************************************************** /*****************************************************************************
* block_fifo_t managment * block_fifo_t managment
*****************************************************************************/ *****************************************************************************/
block_fifo_t * __block_FifoNew ( vlc_object_t *p_obj ) block_fifo_t *__block_FifoNew( vlc_object_t *p_obj )
{ {
block_fifo_t *p_fifo; block_fifo_t *p_fifo;
...@@ -334,7 +340,7 @@ block_fifo_t * __block_FifoNew ( vlc_object_t *p_obj ) ...@@ -334,7 +340,7 @@ block_fifo_t * __block_FifoNew ( vlc_object_t *p_obj )
return p_fifo; return p_fifo;
} }
void block_FifoRelease( block_fifo_t *p_fifo ) void block_FifoRelease( block_fifo_t *p_fifo )
{ {
block_FifoEmpty( p_fifo ); block_FifoEmpty( p_fifo );
vlc_cond_destroy( &p_fifo->wait ); vlc_cond_destroy( &p_fifo->wait );
...@@ -342,7 +348,7 @@ void block_FifoRelease( block_fifo_t *p_fifo ) ...@@ -342,7 +348,7 @@ void block_FifoRelease( block_fifo_t *p_fifo )
free( p_fifo ); free( p_fifo );
} }
void block_FifoEmpty( block_fifo_t *p_fifo ) void block_FifoEmpty( block_fifo_t *p_fifo )
{ {
block_t *b; block_t *b;
...@@ -362,7 +368,7 @@ void block_FifoEmpty( block_fifo_t *p_fifo ) ...@@ -362,7 +368,7 @@ void block_FifoEmpty( block_fifo_t *p_fifo )
vlc_mutex_unlock( &p_fifo->lock ); vlc_mutex_unlock( &p_fifo->lock );
} }
int block_FifoPut ( block_fifo_t *p_fifo, block_t *p_block ) int block_FifoPut( block_fifo_t *p_fifo, block_t *p_block )
{ {
int i_size = 0; int i_size = 0;
vlc_mutex_lock( &p_fifo->lock ); vlc_mutex_lock( &p_fifo->lock );
...@@ -379,14 +385,14 @@ int block_FifoPut ( block_fifo_t *p_fifo, block_t *p_block ) ...@@ -379,14 +385,14 @@ int block_FifoPut ( block_fifo_t *p_fifo, block_t *p_block )
} while( p_block ); } while( p_block );
/* warm there is data in this fifo */ /* warn there is data in this fifo */
vlc_cond_signal( &p_fifo->wait ); vlc_cond_signal( &p_fifo->wait );
vlc_mutex_unlock( &p_fifo->lock ); vlc_mutex_unlock( &p_fifo->lock );
return i_size; return i_size;
} }
block_t * block_FifoGet ( block_fifo_t *p_fifo ) block_t *block_FifoGet( block_fifo_t *p_fifo )
{ {
block_t *b; block_t *b;
...@@ -413,7 +419,7 @@ block_t * block_FifoGet ( block_fifo_t *p_fifo ) ...@@ -413,7 +419,7 @@ block_t * block_FifoGet ( block_fifo_t *p_fifo )
return( b ); return( b );
} }
block_t * block_FifoShow ( block_fifo_t *p_fifo ) block_t *block_FifoShow( block_fifo_t *p_fifo )
{ {
block_t *b; block_t *b;
...@@ -432,7 +438,7 @@ block_t * block_FifoShow ( block_fifo_t *p_fifo ) ...@@ -432,7 +438,7 @@ block_t * block_FifoShow ( block_fifo_t *p_fifo )
} }
block_t * block_FifoGetFrame( block_fifo_t *p_fifo ) block_t *block_FifoGetFrame( block_fifo_t *p_fifo )
{ {
block_t *b = NULL; block_t *b = NULL;
...@@ -449,5 +455,3 @@ block_t * block_FifoGetFrame( block_fifo_t *p_fifo ) ...@@ -449,5 +455,3 @@ block_t * block_FifoGetFrame( block_fifo_t *p_fifo )
return b; return b;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* objects.c: vlc_object_t handling * objects.c: vlc_object_t handling
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: objects.c,v 1.37 2003/06/26 12:19:59 sam Exp $ * $Id: objects.c,v 1.38 2003/09/02 20:19:26 gbazin Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -109,6 +109,10 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) ...@@ -109,6 +109,10 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type )
psz_type = "input"; psz_type = "input";
break; break;
case VLC_OBJECT_DECODER: case VLC_OBJECT_DECODER:
i_size = sizeof(decoder_t);
psz_type = "decoder";
break;
case VLC_OBJECT_DECODER_FIFO: /* tmp for backward compat */
i_size = sizeof(decoder_fifo_t); i_size = sizeof(decoder_fifo_t);
psz_type = "decoder"; psz_type = "decoder";
break; break;
......
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