Commit ba9eb158 authored by Damien Lucas's avatar Damien Lucas

Ajout des fichiers pour la gestion du lpcm.

Il reste � impl�menter le lpcm au niveau de l'input et �crire le d�codage.
parent ed8a78d7
......@@ -240,6 +240,9 @@ ac3_decoder_obj = ac3_decoder/ac3_decoder_thread.o \
ac3_decoder/ac3_rematrix.o \
ac3_decoder/ac3_imdct.o \
ac3_decoder/ac3_downmix.o
lpcm_decoder_obj = lpcm_decoder/lpcm_decoder_thread.o \
lpcm_decoder/lpcm_decoder.o
audio_decoder_obj = audio_decoder/audio_decoder_thread.o \
audio_decoder/audio_decoder.o \
......@@ -288,6 +291,7 @@ C_OBJ = $(interface_obj) \
$(audio_output_obj) \
$(video_output_obj) \
$(ac3_decoder_obj) \
$(lpcm_decoder_obj) \
$(audio_decoder_obj) \
$(spu_decoder_obj) \
$(generic_decoder_obj) \
......
......@@ -170,7 +170,7 @@ typedef struct es_descriptor_t
#define MPEG2_AUDIO_ES 0x04
#define AC3_AUDIO_ES 0x81
#define DVD_SPU_ES 0x82 /* 0x82 might violate the norm */
#define LPCM_AUDIO_ES 0x83
/*****************************************************************************
* program_descriptor_t
*****************************************************************************
......
/*****************************************************************************
* lpcm_decoder.h : lpcm decoder interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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-1307, USA.
*****************************************************************************/
typedef struct lpcmdec_s lpcmdec_t;
typedef struct lpcm_sync_info_s {
int sample_rate; /* sample rate in Hz */
int frame_size; /* frame size in bytes */
int bit_rate; /* nominal bit rate in kbps */
} lpcm_sync_info_t;
typedef struct lpcm_byte_stream_s {
u8 * p_byte;
u8 * p_end;
void * info;
} lpcm_byte_stream_t;
int lpcm_init (lpcmdec_t * p_lpcmdec);
int lpcm_sync_frame (lpcmdec_t * p_lpcmdec, lpcm_sync_info_t * p_sync_info);
int lpcm_decode_frame (lpcmdec_t * p_lcpmdec, s16 * buffer);
//static lpcm_byte_stream_t * lpcm_byte_stream (lcpmdec_t * p_lpcmdec);
void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream);
typedef struct lpcm_bit_stream_s {
u32 buffer;
int i_available;
lpcm_byte_stream_t byte_stream;
} lpcm_bit_stream_t;
struct lpcmdec_s {
/*
* Input properties
*/
/* The bit stream structure handles the PES stream at the bit level */
lpcm_bit_stream_t bit_stream;
};
static lpcm_byte_stream_t * lpcm_byte_stream (lpcmdec_t * p_lpcmdec)
{
return &(p_lpcmdec->bit_stream.byte_stream);
}
/*****************************************************************************
* lpcm_decoder_thread.h : lpcm decoder thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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-1307, USA.
*****************************************************************************/
/*****************************************************************************
* lpcmdec_thread_t : lpcm decoder thread descriptor
*****************************************************************************/
typedef struct lpcmdec_thread_s
{
/*
* Thread properties
*/
vlc_thread_t thread_id; /* id for thread functions */
boolean_t b_die; /* `die' flag */
boolean_t b_error; /* `error' flag */
/*
* Input properties
*/
decoder_fifo_t fifo; /* stores the PES stream data */
input_thread_t * p_input;
ts_packet_t * p_ts;
int sync_ptr; /* sync ptr from lpcm magic header */
/*
* Decoder properties
*/
lpcmdec_t lpcm_decoder;
/*
* Output properties
*/
aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
aout_thread_t * p_aout; /* needed to create the audio fifo */
} lpcmdec_thread_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
lpcmdec_thread_t * lpcmdec_CreateThread( input_thread_t * p_input );
void lpcmdec_DestroyThread( lpcmdec_thread_t * p_lcpmdec );
......@@ -60,6 +60,9 @@
#include "ac3_decoder.h" /* ac3dec_t (for ac3_decoder_thread.h) */
#include "ac3_decoder_thread.h" /* ac3dec_thread_t */
#include "lpcm_decoder.h"
#include "lpcm_decoder_thread.h"
#include "video.h" /* picture_t (for video_output.h) */
#include "video_output.h" /* vout_thread_t */
......@@ -444,6 +447,9 @@ static void EndThread( input_thread_t * p_input )
case AC3_AUDIO_ES:
ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
case LPCM_AUDIO_ES:
lpcmdec_DestroyThread((lpcmdec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
case DVD_SPU_ES:
spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
......@@ -1225,6 +1231,10 @@ static __inline__ void input_ParsePES( input_thread_t *p_input,
p_fifo = &(((ac3dec_thread_t *)(p_es_descriptor->p_dec))->fifo);
break;
case LPCM_AUDIO_ES:
p_fifo = &(((lpcmdec_thread_t *)(p_es_descriptor->p_dec))->fifo);
break;
case DVD_SPU_ES:
/* we skip the first byte at the beginning of the
* subpicture payload, it only contains the SPU ID. */
......
......@@ -30,7 +30,7 @@
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include <stdio.h>
#include <netinet/in.h> /* ntohs */
#include "config.h"
......@@ -53,6 +53,9 @@
#include "ac3_decoder.h" /* ac3dec_t (for ac3_decoder_thread.h) */
#include "ac3_decoder_thread.h" /* ac3dec_thread_t */
#include "lpcm_decoder.h"
#include "lpcm_decoder_thread.h"
#include "video.h" /* picture_t (for video_output.h) */
#include "video_output.h" /* vout_thread_t */
......@@ -122,7 +125,9 @@ int input_AddPgrmElem( input_thread_t *p_input, int i_current_id )
/* Spawn the decoder. */
switch( p_input->p_es[i_es_loop].i_type )
{
case AC3_AUDIO_ES:
fprintf (stderr, "Start an AC3 decoder\n");
/* Spawn ac3 thread */
if ( ((ac3dec_thread_t *)(p_input->p_es[i_es_loop].p_dec) =
ac3dec_CreateThread(p_input)) == NULL )
......@@ -133,6 +138,19 @@ int input_AddPgrmElem( input_thread_t *p_input, int i_current_id )
}
break;
case LPCM_AUDIO_ES:
/* Spawn lpcm thread */
fprintf (stderr, "Start a LPCM decoder\n");
if ( ((lpcmdec_thread_t *)(p_input->p_es[i_es_loop].p_dec) =
lpcmdec_CreateThread(p_input)) == NULL )
{
intf_ErrMsg( "LPCM Debug: Could not start lpcm decoder\n" );
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
case DVD_SPU_ES:
/* Spawn spu thread */
if ( ((spudec_thread_t *)(p_input->p_es[i_es_loop].p_dec) =
......@@ -248,6 +266,10 @@ int input_DelPgrmElem( input_thread_t *p_input, int i_current_id )
case AC3_AUDIO_ES:
ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case LPCM_AUDIO_ES:
lpcmdec_DestroyThread( (lpcmdec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case DVD_SPU_ES:
spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
......
......@@ -654,7 +654,16 @@ static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
}
break;
case DVD_SPU_ES:
case LPCM_AUDIO_ES:
if ( p_main->b_audio )
{
/* Spawn an lpcm thread */
input_AddPgrmElem( p_input,
p_input->p_es[i_es_loop].i_id );
}
break;
case DVD_SPU_ES:
if ( p_main->b_video )
{
/* Spawn a spu decoder thread */
......
/*****************************************************************************
* lpcm_decoder.c: core lpcm decoder
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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-1307, USA.
*****************************************************************************/
#include <stdio.h>
#include "defs.h"
#include "int_types.h"
#include "lpcm_decoder.h"
int lpcm_init (lpcmdec_t * p_lpcmdec)
{
fprintf (stderr, "LPCM Debug: lpmcm init called\n");
return 0;
}
int lpcm_decode_frame (lpcmdec_t * p_lpcmdec, s16 * buffer)
{
/*
* XXX was part of ac3dec, is to change
int i;
if (parse_bsi (p_ac3dec))
return 1;
for (i = 0; i < 6; i++) {
if (parse_audblk (p_ac3dec, i))
return 1;
if (exponent_unpack (p_ac3dec))
return 1;
bit_allocate (p_ac3dec);
mantissa_unpack (p_ac3dec);
if (p_ac3dec->bsi.acmod == 0x2)
rematrix (p_ac3dec);
imdct (p_ac3dec);
downmix (p_ac3dec, buffer);
buffer += 2*256;
}
parse_auxdata (p_ac3dec);
*/
return 0;
}
/*****************************************************************************
* lpcm_decoder_thread.c: lpcm decoder thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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-1307, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <unistd.h> /* getpid() */
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* malloc(), free() */
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "debug.h" /* "input_netlist.h" */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "input.h" /* pes_packet_t */
#include "input_netlist.h" /* input_NetlistFreePES() */
#include "decoder_fifo.h" /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
#include "audio_output.h"
#include "lpcm_decoder.h"
#include "lpcm_decoder_thread.h"
#define LPCMDEC_FRAME_SIZE (2*1536) /* May not be usefull */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int InitThread (lpcmdec_thread_t * p_adec);
static void RunThread (lpcmdec_thread_t * p_adec);
static void ErrorThread (lpcmdec_thread_t * p_adec);
static void EndThread (lpcmdec_thread_t * p_adec);
/*****************************************************************************
* lpcmdec_CreateThread: creates an lpcm decoder thread
*****************************************************************************/
lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
{
lpcmdec_thread_t * p_lpcmdec;
fprintf (stderr, "LPCM Debug: creating lpcm decoder thread\n");
/* Allocate the memory needed to store the thread's structure */
if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
fprintf (stderr, "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread\n");
return NULL;
}
/*
* Initialize the thread properties
*/
p_lpcmdec->b_die = 0;
p_lpcmdec->b_error = 0;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set
* its buffer as empty */
vlc_mutex_init (&p_lpcmdec->fifo.data_lock);
vlc_cond_init (&p_lpcmdec->fifo.data_wait);
p_lpcmdec->fifo.i_start = 0;
p_lpcmdec->fifo.i_end = 0;
/* Initialize the lpcm decoder structures */
lpcm_init (&p_lpcmdec->lpcm_decoder);
/* Initialize the bit stream structure */
p_lpcmdec->p_input = p_input;
/*
* Initialize the output properties
*/
p_lpcmdec->p_aout = p_input->p_aout;
p_lpcmdec->p_aout_fifo = NULL;
/* Spawn the lpcm decoder thread */
if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
fprintf (stderr, "LPCM Error: can't spawn lpcm decoder thread\n");
free (p_lpcmdec);
return NULL;
}
fprintf (stderr, "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec);
return p_lpcmdec;
}
/*****************************************************************************
* lpcmdec_DestroyThread: destroys an lpcm decoder thread
*****************************************************************************/
void lpcmdec_DestroyThread (lpcmdec_thread_t * p_lpcmdec)
{
fprintf (stderr, "LPCM Debug: requesting termination of lpcm decoder thread %p\n", p_lpcmdec);
/* Ask thread to kill itself */
p_lpcmdec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock (&(p_lpcmdec->fifo.data_lock));
vlc_cond_signal (&(p_lpcmdec->fifo.data_wait));
vlc_mutex_unlock (&(p_lpcmdec->fifo.data_lock));
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join (p_lpcmdec->thread_id);
}
/* Following functions are local */
/*****************************************************************************
* InitThread : initialize an lpcm decoder thread
*****************************************************************************/
static int InitThread (lpcmdec_thread_t * p_lpcmdec)
{
aout_fifo_t aout_fifo;
lpcm_byte_stream_t * byte_stream;
fprintf (stderr, "LPCM Debug: initializing lpcm decoder thread %p\n", p_lpcmdec);
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
while (DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
if (p_lpcmdec->b_die) {
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
return -1;
}
vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
}
p_lpcmdec->p_ts = DECODER_FIFO_START (p_lpcmdec->fifo)->p_first_ts;
byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
byte_stream->p_byte =
p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_start;
byte_stream->p_end =
p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_end;
byte_stream->info = p_lpcmdec;
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
aout_fifo.i_channels = 2;
aout_fifo.b_stereo = 1;
aout_fifo.l_frame_size = LPCMDEC_FRAME_SIZE;
/* Creating the audio output fifo */
if ((p_lpcmdec->p_aout_fifo = aout_CreateFifo(p_lpcmdec->p_aout, &aout_fifo)) == NULL) {
return -1;
}
fprintf (stderr,"LPCM Debug: lpcm decoder thread %p initialized\n", p_lpcmdec);
return 0;
}
/*****************************************************************************
* RunThread : lpcm decoder thread
*****************************************************************************/
static void RunThread (lpcmdec_thread_t * p_lpcmdec)
{
int sync;
fprintf (stderr,"LPCM Debug: running lpcm decoder thread (%p) (pid== %i)\n", p_lpcmdec, getpid());
msleep (INPUT_PTS_DELAY);
/* Initializing the lpcm decoder thread */
if (InitThread (p_lpcmdec))
{
p_lpcmdec->b_error = 1;
}
sync = 0;
p_lpcmdec->sync_ptr = 0;
/* lpcm decoder thread's main loop */
/* FIXME : do we have enough room to store the decoded frames ?? */
while ((!p_lpcmdec->b_die) && (!p_lpcmdec->b_error))
{
s16 * buffer;
lpcm_sync_info_t sync_info;
if (!sync)
{
/* have to find a synchro point */
}
if (DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts)
{
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_lpcmdec->fifo)->i_pts;
DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts = 0;
}
else
{
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
}
p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
{
sync = 0;
goto bad_frame;
}
vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
fprintf(stderr, "LPCM Debug: %x\n", *buffer);
bad_frame:
}
/* If b_error is set, the lpcm decoder thread enters the error loop */
if (p_lpcmdec->b_error)
{
ErrorThread (p_lpcmdec);
}
/* End of the lpcm decoder thread */
EndThread (p_lpcmdec);
}
/*****************************************************************************
* ErrorThread : lpcm decoder's RunThread() error loop
*****************************************************************************/
static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
/* Wait until a `die' order is sent */
while (!p_lpcmdec->b_die) {
/* Trash all received PES packets */
while (!DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
input_NetlistFreePES (p_lpcmdec->p_input, DECODER_FIFO_START(p_lpcmdec->fifo));
DECODER_FIFO_INCSTART (p_lpcmdec->fifo);
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
}
/* We can release the lock before leaving */
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
}
/*****************************************************************************
* EndThread : lpcm decoder thread destruction
*****************************************************************************/
static void EndThread (lpcmdec_thread_t * p_lpcmdec)
{
fprintf (stderr, "LPCM Debug: destroying lpcm decoder thread %p\n", p_lpcmdec);
/* If the audio output fifo was created, we destroy it */
if (p_lpcmdec->p_aout_fifo != NULL) {
aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
/* Make sure the output thread leaves the NextFrame() function */
vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
}
/* Destroy descriptor */
free (p_lpcmdec);
fprintf (stderr, "LPCM Debug: lpcm decoder thread %p destroyed\n", p_lpcmdec);
}
void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
{
// lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
/* We are looking for the next TS packet that contains real data,
* and not just a PES header */
}
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