X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fac3_decoder%2Fac3_decoder_thread.c;h=278942cb0a422930e32a272c9763d653b877ca5d;hb=a70f8bb371466209770c4c3bcdb7137b94acef66;hp=5d43aec35275e5681fdad49a476a93d89fa5fe1b;hpb=57e189eb5d1d387f2036c31720e1e9aa8cb3ea78;p=vlc diff --git a/src/ac3_decoder/ac3_decoder_thread.c b/src/ac3_decoder/ac3_decoder_thread.c index 5d43aec352..278942cb0a 100644 --- a/src/ac3_decoder/ac3_decoder_thread.c +++ b/src/ac3_decoder/ac3_decoder_thread.c @@ -2,8 +2,9 @@ * ac3_decoder_thread.c: ac3 decoder thread ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN + * $Id: ac3_decoder_thread.c,v 1.31 2001/05/01 04:18:18 sam Exp $ * - * Authors: + * Authors: Michel Lespinasse * * 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 @@ -38,21 +39,16 @@ #include /* "intf_msg.h" */ #include /* malloc(), free() */ -#include /* on BSD, uio.h needs types.h */ -#include /* "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 "stream_control.h" +#include "input_ext-dec.h" #include "audio_output.h" @@ -68,80 +64,52 @@ static int InitThread (ac3dec_thread_t * p_adec); static void RunThread (ac3dec_thread_t * p_adec); static void ErrorThread (ac3dec_thread_t * p_adec); static void EndThread (ac3dec_thread_t * p_adec); +static void BitstreamCallback ( bit_stream_t *p_bit_stream, + boolean_t b_new_pes ); + /***************************************************************************** * ac3dec_CreateThread: creates an ac3 decoder thread *****************************************************************************/ -ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input) +vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config ) { - ac3dec_thread_t * p_ac3dec; + ac3dec_thread_t * p_ac3dec_t; - intf_DbgMsg( "ac3dec debug: creating ac3 decoder thread\n" ); + intf_DbgMsg( "ac3dec debug: creating ac3 decoder thread" ); /* Allocate the memory needed to store the thread's structure */ - if ((p_ac3dec = (ac3dec_thread_t *)malloc (sizeof(ac3dec_thread_t))) == NULL) { + if((p_ac3dec_t = (ac3dec_thread_t *)malloc(sizeof(ac3dec_thread_t)))==NULL) + { intf_ErrMsg ( "ac3dec error: not enough memory " - "for ac3dec_CreateThread() to create the new thread\n"); - return NULL; + "for ac3dec_CreateThread() to create the new thread"); + return 0; } - + /* * Initialize the thread properties */ - p_ac3dec->b_die = 0; - p_ac3dec->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_ac3dec->fifo.data_lock); - vlc_cond_init (&p_ac3dec->fifo.data_wait); - p_ac3dec->fifo.i_start = 0; - p_ac3dec->fifo.i_end = 0; + p_ac3dec_t->p_config = p_config; + p_ac3dec_t->p_fifo = p_config->decoder_config.p_decoder_fifo; /* Initialize the ac3 decoder structures */ - ac3_init (&p_ac3dec->ac3_decoder); - - /* Initialize the bit stream structure */ - p_ac3dec->p_input = p_input; + ac3_init (&p_ac3dec_t->ac3_decoder); /* * Initialize the output properties */ - p_ac3dec->p_aout = p_input->p_aout; - p_ac3dec->p_aout_fifo = NULL; + p_ac3dec_t->p_aout_fifo = NULL; /* Spawn the ac3 decoder thread */ - if (vlc_thread_create(&p_ac3dec->thread_id, "ac3 decoder", (vlc_thread_func_t)RunThread, (void *)p_ac3dec)) { - intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread\n" ); - free (p_ac3dec); - return NULL; + if (vlc_thread_create(&p_ac3dec_t->thread_id, "ac3 decoder", + (vlc_thread_func_t)RunThread, (void *)p_ac3dec_t)) + { + intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread" ); + free (p_ac3dec_t); + return 0; } - intf_DbgMsg ("ac3dec debug: ac3 decoder thread (%p) created\n", p_ac3dec); - return p_ac3dec; -} - -/***************************************************************************** - * ac3dec_DestroyThread: destroys an ac3 decoder thread - *****************************************************************************/ -void ac3dec_DestroyThread (ac3dec_thread_t * p_ac3dec) -{ - intf_DbgMsg ("ac3dec debug: requesting termination of ac3 decoder thread %p\n", p_ac3dec); - - /* Ask thread to kill itself */ - p_ac3dec->b_die = 1; - - /* Make sure the decoder thread leaves the GetByte() function */ - vlc_mutex_lock (&(p_ac3dec->fifo.data_lock)); - vlc_cond_signal (&(p_ac3dec->fifo.data_wait)); - vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock)); - - /* Waiting for the decoder thread to exit */ - /* Remove this as soon as the "status" flag is implemented */ - vlc_thread_join (p_ac3dec->thread_id); + intf_DbgMsg ("ac3dec debug: ac3 decoder thread (%p) created", p_ac3dec_t); + return p_ac3dec_t->thread_id; } /* Following functions are local */ @@ -149,251 +117,192 @@ void ac3dec_DestroyThread (ac3dec_thread_t * p_ac3dec) /***************************************************************************** * InitThread : initialize an ac3 decoder thread *****************************************************************************/ -static int InitThread (ac3dec_thread_t * p_ac3dec) +static int InitThread (ac3dec_thread_t * p_ac3dec_t) { - aout_fifo_t aout_fifo; - ac3_byte_stream_t * byte_stream; - - intf_DbgMsg ("ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec); - - /* Our first job is to initialize the bit stream structure with the - * beginning of the input stream */ - vlc_mutex_lock (&p_ac3dec->fifo.data_lock); - while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo)) { - if (p_ac3dec->b_die) { - vlc_mutex_unlock (&p_ac3dec->fifo.data_lock); - return -1; - } - vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock); - } - p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts; - byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder); - byte_stream->p_byte = - p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start; - byte_stream->p_end = - p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end; - byte_stream->info = p_ac3dec; - vlc_mutex_unlock (&p_ac3dec->fifo.data_lock); - - aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO; - aout_fifo.i_channels = 2; - aout_fifo.b_stereo = 1; + intf_DbgMsg("ac3dec debug: initializing ac3 decoder thread %p",p_ac3dec_t); - aout_fifo.l_frame_size = AC3DEC_FRAME_SIZE; + p_ac3dec_t->p_config->decoder_config.pf_init_bit_stream( + &p_ac3dec_t->ac3_decoder.bit_stream, + p_ac3dec_t->p_config->decoder_config.p_decoder_fifo, + BitstreamCallback, (void *) p_ac3dec_t ); /* Creating the audio output fifo */ - if ((p_ac3dec->p_aout_fifo = aout_CreateFifo(p_ac3dec->p_aout, &aout_fifo)) == NULL) { + p_ac3dec_t->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 0, 0, + AC3DEC_FRAME_SIZE, NULL ); + if ( p_ac3dec_t->p_aout_fifo == NULL ) + { return -1; } - intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p initialized\n", p_ac3dec); + intf_DbgMsg("ac3dec debug: ac3 decoder thread %p initialized", p_ac3dec_t); return 0; } /***************************************************************************** * RunThread : ac3 decoder thread *****************************************************************************/ -static void RunThread (ac3dec_thread_t * p_ac3dec) +static void RunThread (ac3dec_thread_t * p_ac3dec_t) { int sync; - intf_DbgMsg ("ac3dec debug: running ac3 decoder thread (%p) (pid == %i)\n", p_ac3dec, getpid()); - - msleep (INPUT_PTS_DELAY); + intf_DbgMsg ("ac3dec debug: running ac3 decoder thread (%p) (pid == %i)", p_ac3dec_t, getpid()); /* Initializing the ac3 decoder thread */ - if (InitThread (p_ac3dec)) /* XXX?? */ { - p_ac3dec->b_error = 1; + if (InitThread (p_ac3dec_t)) /* XXX?? */ + { + p_ac3dec_t->p_fifo->b_error = 1; } sync = 0; - p_ac3dec->sync_ptr = 0; + p_ac3dec_t->sync_ptr = 0; /* ac3 decoder thread's main loop */ /* FIXME : do we have enough room to store the decoded frames ?? */ - while ((!p_ac3dec->b_die) && (!p_ac3dec->b_error)) { + while ((!p_ac3dec_t->p_fifo->b_die) && (!p_ac3dec_t->p_fifo->b_error)) + { s16 * buffer; ac3_sync_info_t sync_info; + int ptr; - if (!sync) { /* have to find a synchro point */ - int ptr; - ac3_byte_stream_t * p_byte_stream; - - intf_Msg ("ac3dec: sync\n"); - - p_byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder); - - /* first read till next ac3 magic header */ + if (!sync) { do { - ac3_byte_stream_next (p_byte_stream); - } while ((!p_ac3dec->sync_ptr) && - (!p_ac3dec->b_die) && - (!p_ac3dec->b_error)); - /* skip the specified number of bytes */ - - ptr = p_ac3dec->sync_ptr; - while (--ptr && (!p_ac3dec->b_die) && (!p_ac3dec->b_error)) { - if (p_byte_stream->p_byte >= p_byte_stream->p_end) { - ac3_byte_stream_next (p_byte_stream); - } - p_byte_stream->p_byte++; + GetBits(&p_ac3dec_t->ac3_decoder.bit_stream,8); + } while ((!p_ac3dec_t->sync_ptr) && (!p_ac3dec_t->p_fifo->b_die) + && (!p_ac3dec_t->p_fifo->b_error)); + + ptr = p_ac3dec_t->sync_ptr; + + while(ptr-- && (!p_ac3dec_t->p_fifo->b_die) + && (!p_ac3dec_t->p_fifo->b_error)) + { + p_ac3dec_t->ac3_decoder.bit_stream.p_byte++; } - + /* we are in sync now */ - sync = 1; - p_ac3dec->sync_ptr = 0; } - if (DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts) { - p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_ac3dec->fifo)->i_pts; - DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts = 0; + if (DECODER_FIFO_START(*p_ac3dec_t->p_fifo)->i_pts) + { + p_ac3dec_t->p_aout_fifo->date[p_ac3dec_t->p_aout_fifo->l_end_frame] = + DECODER_FIFO_START(*p_ac3dec_t->p_fifo)->i_pts; + DECODER_FIFO_START(*p_ac3dec_t->p_fifo)->i_pts = 0; } else { - p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = LAST_MDATE; + p_ac3dec_t->p_aout_fifo->date[p_ac3dec_t->p_aout_fifo->l_end_frame] = + LAST_MDATE; } - - if (ac3_sync_frame (&p_ac3dec->ac3_decoder, &sync_info)) { + + if (ac3_sync_frame (&p_ac3dec_t->ac3_decoder, &sync_info)) + { sync = 0; goto bad_frame; } - p_ac3dec->p_aout_fifo->l_rate = sync_info.sample_rate; + p_ac3dec_t->p_aout_fifo->l_rate = sync_info.sample_rate; - buffer = ((s16 *)p_ac3dec->p_aout_fifo->buffer) + (p_ac3dec->p_aout_fifo->l_end_frame * AC3DEC_FRAME_SIZE); + buffer = ((s16 *)p_ac3dec_t->p_aout_fifo->buffer) + + (p_ac3dec_t->p_aout_fifo->l_end_frame * AC3DEC_FRAME_SIZE); - if (ac3_decode_frame (&p_ac3dec->ac3_decoder, buffer)) { + if (ac3_decode_frame (&p_ac3dec_t->ac3_decoder, buffer)) + { sync = 0; goto bad_frame; } - - vlc_mutex_lock (&p_ac3dec->p_aout_fifo->data_lock); - p_ac3dec->p_aout_fifo->l_end_frame = (p_ac3dec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE; - vlc_cond_signal (&p_ac3dec->p_aout_fifo->data_wait); - vlc_mutex_unlock (&p_ac3dec->p_aout_fifo->data_lock); - - bad_frame: + + vlc_mutex_lock (&p_ac3dec_t->p_aout_fifo->data_lock); + p_ac3dec_t->p_aout_fifo->l_end_frame = + (p_ac3dec_t->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE; + vlc_cond_signal (&p_ac3dec_t->p_aout_fifo->data_wait); + vlc_mutex_unlock (&p_ac3dec_t->p_aout_fifo->data_lock); + + bad_frame: + RealignBits(&p_ac3dec_t->ac3_decoder.bit_stream); } /* If b_error is set, the ac3 decoder thread enters the error loop */ - if (p_ac3dec->b_error) { - ErrorThread (p_ac3dec); + if (p_ac3dec_t->p_fifo->b_error) + { + ErrorThread (p_ac3dec_t); } /* End of the ac3 decoder thread */ - EndThread (p_ac3dec); + EndThread (p_ac3dec_t); } /***************************************************************************** * ErrorThread : ac3 decoder's RunThread() error loop *****************************************************************************/ -static void ErrorThread (ac3dec_thread_t * p_ac3dec) +static void ErrorThread (ac3dec_thread_t * p_ac3dec_t) { /* We take the lock, because we are going to read/write the start/end * indexes of the decoder fifo */ - vlc_mutex_lock (&p_ac3dec->fifo.data_lock); + vlc_mutex_lock (&p_ac3dec_t->p_fifo->data_lock); /* Wait until a `die' order is sent */ - while (!p_ac3dec->b_die) { + while (!p_ac3dec_t->p_fifo->b_die) + { /* Trash all received PES packets */ - while (!DECODER_FIFO_ISEMPTY(p_ac3dec->fifo)) { - input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo)); - DECODER_FIFO_INCSTART (p_ac3dec->fifo); + while (!DECODER_FIFO_ISEMPTY(*p_ac3dec_t->p_fifo)) + { + p_ac3dec_t->p_fifo->pf_delete_pes(p_ac3dec_t->p_fifo->p_packets_mgt, + DECODER_FIFO_START(*p_ac3dec_t->p_fifo)); + DECODER_FIFO_INCSTART (*p_ac3dec_t->p_fifo); } /* Waiting for the input thread to put new PES packets in the fifo */ - vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock); + vlc_cond_wait (&p_ac3dec_t->p_fifo->data_wait, + &p_ac3dec_t->p_fifo->data_lock); } /* We can release the lock before leaving */ - vlc_mutex_unlock (&p_ac3dec->fifo.data_lock); + vlc_mutex_unlock (&p_ac3dec_t->p_fifo->data_lock); } /***************************************************************************** * EndThread : ac3 decoder thread destruction *****************************************************************************/ -static void EndThread (ac3dec_thread_t * p_ac3dec) +static void EndThread (ac3dec_thread_t * p_ac3dec_t) { - intf_DbgMsg ("ac3dec debug: destroying ac3 decoder thread %p\n", p_ac3dec); + intf_DbgMsg ("ac3dec debug: destroying ac3 decoder thread %p", p_ac3dec_t); /* If the audio output fifo was created, we destroy it */ - if (p_ac3dec->p_aout_fifo != NULL) { - aout_DestroyFifo (p_ac3dec->p_aout_fifo); + if (p_ac3dec_t->p_aout_fifo != NULL) + { + aout_DestroyFifo (p_ac3dec_t->p_aout_fifo); /* Make sure the output thread leaves the NextFrame() function */ - vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock)); - vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait)); - vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock)); + vlc_mutex_lock (&(p_ac3dec_t->p_aout_fifo->data_lock)); + vlc_cond_signal (&(p_ac3dec_t->p_aout_fifo->data_wait)); + vlc_mutex_unlock (&(p_ac3dec_t->p_aout_fifo->data_lock)); + } /* Destroy descriptor */ - free (p_ac3dec); + free( p_ac3dec_t->p_config ); + free( p_ac3dec_t ); - intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p destroyed\n", p_ac3dec); + intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p destroyed", p_ac3dec_t); } -void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream) +/***************************************************************************** +* BitstreamCallback: Import parameters from the new data/PES packet +***************************************************************************** +* This function is called by input's NextDataPacket. +*****************************************************************************/ +static void BitstreamCallback ( bit_stream_t * p_bit_stream, + boolean_t b_new_pes) { - ac3dec_thread_t * p_ac3dec = p_byte_stream->info; - - /* We are looking for the next TS packet that contains real data, - * and not just a PES header */ - do { - /* We were reading the last TS packet of this PES packet... It's - * time to jump to the next PES packet */ - if (p_ac3dec->p_ts->p_next_ts == NULL) { - int ptr; - - /* We are going to read/write the start and end indexes of the - * decoder fifo and to use the fifo's conditional variable, - * that's why we need to take the lock before */ - vlc_mutex_lock (&p_ac3dec->fifo.data_lock); - - /* Is the input thread dying ? */ - if (p_ac3dec->p_input->b_die) { - vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock)); - return; - } - - /* We should increase the start index of the decoder fifo, but - * if we do this now, the input thread could overwrite the - * pointer to the current PES packet, and we weren't able to - * give it back to the netlist. That's why we free the PES - * packet first. */ - input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo)); - - DECODER_FIFO_INCSTART (p_ac3dec->fifo); - while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo)) { - vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock); - - if (p_ac3dec->p_input->b_die) { - vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock)); - return; - } - } - - /* The next byte could be found in the next PES packet */ - p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts; - - /* parse ac3 magic header */ - ptr = p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+2]; - ptr <<= 8; - ptr |= p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+3]; - p_ac3dec->sync_ptr = ptr; - p_ac3dec->p_ts->i_payload_start += 4; - - /* We can release the fifo's data lock */ - vlc_mutex_unlock (&p_ac3dec->fifo.data_lock); - } - - /* Perhaps the next TS packet of the current PES packet contains - * real data (ie its payload's size is greater than 0) */ - else { - p_ac3dec->p_ts = p_ac3dec->p_ts->p_next_ts; - } - } while (p_ac3dec->p_ts->i_payload_start == p_ac3dec->p_ts->i_payload_end); - p_byte_stream->p_byte = - p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start; - p_byte_stream->p_end = - p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end; + ac3dec_thread_t *p_ac3dec_t=(ac3dec_thread_t *)p_bit_stream->p_callback_arg; + + if( b_new_pes ) + { + int ptr; + + ptr = *(p_bit_stream->p_byte + 1); + ptr <<= 8; + ptr |= *(p_bit_stream->p_byte + 2); + p_ac3dec_t->sync_ptr = ptr; + p_bit_stream->p_byte += 3; + } }