Commit 7bb574fd authored by gbazin's avatar gbazin

* 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 $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)
......@@ -1000,7 +1000,7 @@ if test "${enable_sout}" != "no"
then
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([packetizer_mpegaudio packetizer_mpegvideo packetizer_a52])
AX_ADD_PLUGINS([packetizer_mpegaudio packetizer_mpegvideo])
AX_ADD_PLUGINS([packetizer_mpeg4video packetizer_mpeg4audio])
AX_ADD_PLUGINS([packetizer_copy])
......@@ -1934,11 +1934,7 @@ if test "${enable_vorbis}" != "no"
then
AC_CHECK_HEADERS(vorbis/codec.h, [
AX_ADD_PLUGINS([vorbis])
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 ],[])
AX_ADD_LDFLAGS([vorbis],[-lvorbis -logg]) ],[])
fi
dnl
......
......@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders
*****************************************************************************
* 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>
* Michel Kaempf <maxx@via.ecp.fr>
......@@ -110,8 +110,29 @@ struct decoder_fifo_t
void * p_waveformatex;
void * p_bitmapinfoheader;
decoder_t * p_dec;
};
/*****************************************************************************
* decoder_t
*****************************************************************************
* The decoder descriptor.
*****************************************************************************/
struct decoder_t
{
VLC_COMMON_MEMBERS
/* Module properties */
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 * );
};
......
......@@ -2,7 +2,7 @@
* decoder.h: header for vlc decoders
*****************************************************************************
* 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
* it under the terms of the GNU General Public License as published by
......@@ -34,6 +34,7 @@ extern "C" {
/*****************************************************************************
* Required internal headers
*****************************************************************************/
#include "vlc_block.h"
#include "stream_control.h"
#include "input_ext-dec.h"
......
......@@ -2,7 +2,7 @@
* input.h: input modules header for vlc
*****************************************************************************
* 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
* it under the terms of the GNU General Public License as published by
......@@ -34,6 +34,7 @@ extern "C" {
/*****************************************************************************
* Required internal headers
*****************************************************************************/
#include "vlc_block.h"
#include "stream_control.h"
#include "input_ext-intf.h" /* input_thread_s */
#include "input_ext-dec.h" /* data_packet_s */
......
......@@ -2,7 +2,7 @@
* sout.h: video output header for vlc
*****************************************************************************
* 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
* it under the terms of the GNU General Public License as published by
......@@ -34,6 +34,7 @@ extern "C" {
/*****************************************************************************
* Required internal headers
*****************************************************************************/
#include "vlc_block.h"
#include "stream_output.h"
# ifdef __cplusplus
......
/*****************************************************************************
* block.h
* vlc_block.h: Data blocks management functions
*****************************************************************************
* 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>
*
......@@ -21,9 +21,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef _BLOCK_H
#define _BLOCK_H 1
#ifndef _VLC_BLOCK_H
#define _VLC_BLOCK_H 1
/*
* block
......@@ -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_FifoShow, ( block_fifo_t * ) );
#endif
#endif /* VLC_BLOCK_H */
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* 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>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -268,6 +268,8 @@ typedef struct slp_session_t slp_session_t;*/
/* Decoders */
typedef struct decoder_fifo_t decoder_fifo_t;
typedef struct decoder_t decoder_t;
typedef struct decoder_sys_t decoder_sys_t;
/* Misc */
typedef struct data_packet_t data_packet_t;
......
......@@ -2,7 +2,7 @@
* vlc_objects.h: vlc_object_t definition.
*****************************************************************************
* 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>
*
......@@ -30,6 +30,8 @@
#define VLC_OBJECT_ITEM (-6)
#define VLC_OBJECT_INPUT (-7)
#define VLC_OBJECT_DECODER (-8)
/* tmp for backward compat */
#define VLC_OBJECT_DECODER_FIFO (-999)
#define VLC_OBJECT_VOUT (-9)
#define VLC_OBJECT_AOUT (-10)
#define VLC_OBJECT_SOUT (-11)
......
......@@ -2,12 +2,11 @@
* a52.c: A/52 basic parser
*****************************************************************************
* 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>
* Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@zoy.org>
* Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
* 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
......@@ -34,45 +33,85 @@
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/aout.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#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
{
/*
* Thread properties
*/
vlc_thread_t thread_id; /* id for thread functions */
/* Module mode */
vlc_bool_t b_packetizer;
/*
* Input properties
*/
decoder_fifo_t * p_fifo; /* stores the PES stream data */
bit_stream_t bit_stream;
int i_state;
uint8_t p_header[A52_HEADER_SIZE];
int i_header;
mtime_t pts;
int i_frame_size;
/*
* Output properties
* Decoder output properties
*/
aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t output_format;
} dec_thread_t;
audio_sample_format_t aout_format;
aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
/*
* Packetizer output properties
*/
sout_packetizer_input_t *p_sout_input;
sout_format_t sout_format;
sout_buffer_t * p_sout_buffer; /* current sout buffer */
/*
* 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
****************************************************************************/
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
......@@ -81,6 +120,11 @@ vlc_module_begin();
set_description( _("A/52 parser") );
set_capability( "decoder", 100 );
set_callbacks( OpenDecoder, NULL );
add_submodule();
set_description( _("A/52 audio packetizer") );
set_capability( "packetizer", 10 );
set_callbacks( OpenPacketizer, NULL );
vlc_module_end();
/*****************************************************************************
......@@ -88,15 +132,62 @@ vlc_module_end();
*****************************************************************************/
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;
}
p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
&& p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
/* 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;
}
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;
}
......@@ -105,167 +196,350 @@ static int OpenDecoder( vlc_object_t *p_this )
****************************************************************************
* 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;
audio_date_t end_date;
decoder_sys_t *p_sys = p_dec->p_sys;
int i_block_pos = 0;
mtime_t i_pts = p_block->i_pts;
/* Allocate the memory needed to store the thread's structure */
p_dec = malloc( sizeof(dec_thread_t) );
if( p_dec == NULL )
while( i_block_pos < p_block->i_buffer )
{
switch( p_sys->i_state )
{
msg_Err( p_fifo, "out of memory" );
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 */
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('a','5','2',' ');
if( i_block_pos < p_block->i_buffer )
{
p_sys->i_state = STATE_PARTIAL_SYNC;
i_block_pos++;
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 */
if( InitBitstream( &p_dec->bit_stream, p_dec->p_fifo,
NULL, NULL ) != VLC_SUCCESS )
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 ) )
{
msg_Err( p_fifo, "cannot initialize bitstream" );
DecoderError( p_fifo );
free( p_dec );
return -1;
aout_DateSet( &p_sys->end_date, p_sys->pts );
}
p_sys->i_state = STATE_HEADER;
break;
/* Decoder thread's main loop */
while ( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
case STATE_HEADER:
/* Get A/52 frame header (A52_HEADER_SIZE bytes) */
if( p_sys->i_header < A52_HEADER_SIZE )
{
int i_bit_rate;
unsigned int i_rate, i_original_channels, i_frame_size;
mtime_t pts;
byte_t p_header[7];
aout_buffer_t * p_buffer;
int i_size = __MIN( A52_HEADER_SIZE - p_sys->i_header,
p_block->i_buffer - i_block_pos );
/* 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) )
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 )
{
RemoveBits( &p_dec->bit_stream, 8 );
block_Release( p_block );
return VLC_EGENERIC;
}
if ( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) break;
/* Set the Presentation Time Stamp */
NextPTS( &p_dec->bit_stream, &pts, NULL );
if ( pts != 0 && pts != aout_DateGet( &end_date ) )
if( !p_sys->p_out_buffer )
{
aout_DateSet( &end_date, pts );
p_sys->i_state = STATE_NOSYNC;
break;
}
/* Get A/52 frame header */
GetChunk( &p_dec->bit_stream, p_header, 7 );
if ( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) 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;
}
}
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 );
*pp_out_buffer =
p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
}
return i_ret;
}
/*****************************************************************************
* GetAoutBuffer:
*****************************************************************************/
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;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Check if frame is valid and get frame info */
i_frame_size = SyncInfo( p_header, &i_original_channels, &i_rate,
&i_bit_rate );
p_sys->i_frame_size = SyncInfo( p_sys->p_header,
&i_channels, &i_channels_conf,
&i_rate, &i_bit_rate );
if( !i_frame_size )
if( !p_sys->i_frame_size )
{
msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" );
continue;
msg_Warn( p_dec, "a52 syncinfo failed" );
*pp_buffer = NULL;
return VLC_SUCCESS;