]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
* Removed b_die and b_error from all decoders (obsoleted by decoder_fifo_t).
[vlc] / src / input / input_ext-dec.c
1 /*****************************************************************************
2  * input_ext-dec.c: services to the decoders
3  *****************************************************************************
4  * Copyright (C) 1998, 1999, 2000 VideoLAN
5  *
6  * Authors: 
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include "config.h"
29 #include "common.h"
30 #include "threads.h"
31 #include "mtime.h"
32
33 #include "intf_msg.h"
34
35 #include "stream_control.h"
36 #include "input_ext-dec.h"
37 #include "input.h"
38
39 /*****************************************************************************
40  * InitBitstream: initialize a bit_stream_t structure
41  *****************************************************************************/
42 void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo )
43 {
44     p_bit_stream->p_decoder_fifo = p_fifo;
45     p_bit_stream->pf_next_data_packet = NextDataPacket;
46
47     /* Get the first data packet. */
48     vlc_mutex_lock( &p_fifo->data_lock );
49     while ( DECODER_FIFO_ISEMPTY( *p_fifo ) )
50     {
51         if ( p_fifo->b_die )
52         {
53             vlc_mutex_unlock( &p_fifo->data_lock );
54             return;
55         }
56         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
57     }
58     p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
59     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
60     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
61     p_bit_stream->fifo.buffer = 0;
62     p_bit_stream->fifo.i_available = 0;
63     vlc_mutex_unlock( &p_fifo->data_lock );
64 }
65
66 /*****************************************************************************
67  * NextDataPacket: go to the next data packet
68  *****************************************************************************/
69 void NextDataPacket( bit_stream_t * p_bit_stream )
70 {
71     WORD_TYPE           buffer_left;
72     /* FIXME : not portable in a 64bit environment */
73     int                 i_bytes_left;
74     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
75
76     /* Buffer used at the end of a decoder thread, to give it zero
77      * values if needed. */
78     static byte_t       p_zero[64] = { 0, 0, 0, 0, 0, 0, 0,
79                                        0, 0, 0, 0, 0, 0, 0,
80                                        0, 0, 0, 0, 0, 0, 0,
81                                        0, 0, 0, 0, 0, 0, 0,
82                                        0, 0, 0, 0, 0, 0, 0,
83                                        0, 0, 0, 0, 0, 0, 0,
84                                        0, 0, 0, 0, 0, 0, 0,
85                                        0, 0, 0, 0, 0, 0, 0 };
86
87     /* Put the remaining bytes (not aligned on a word boundary) in a
88      * temporary buffer. */
89     i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
90     buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
91
92     /* We are looking for the next data packet that contains real data,
93      * and not just a PES header */
94     do
95     {
96         /* We were reading the last data packet of this PES packet... It's
97          * time to jump to the next PES packet */
98         if( p_bit_stream->p_data->p_next == NULL )
99         {
100             /* We are going to read/write the start and end indexes of the
101              * decoder fifo and to use the fifo's conditional variable,
102              * that's why we need to take the lock before. */
103             vlc_mutex_lock( &p_fifo->data_lock );
104
105             /* Is the input thread dying ? */
106             if( p_fifo->b_die )
107             {
108                 vlc_mutex_unlock( &p_fifo->data_lock );
109                 p_bit_stream->p_byte = p_zero;
110                 p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
111                 return;
112             }
113
114             /* We should increase the start index of the decoder fifo, but
115              * if we do this now, the input thread could overwrite the
116              * pointer to the current PES packet, and we weren't able to
117              * give it back to the netlist. That's why we free the PES
118              * packet first. */
119             p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
120                                    DECODER_FIFO_START( *p_fifo ) );
121             DECODER_FIFO_INCSTART( *p_fifo );
122
123             while( DECODER_FIFO_ISEMPTY( *p_fifo ) )
124             {
125                 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
126                 if( p_fifo->b_die )
127                 {
128                     vlc_mutex_unlock( &p_fifo->data_lock );
129                     p_bit_stream->p_byte = p_zero;
130                     p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
131                     return;
132                 }
133             }
134
135             /* The next byte could be found in the next PES packet */
136             p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
137
138             /* We can release the fifo's data lock */
139             vlc_mutex_unlock( &p_fifo->data_lock );
140         }
141         else
142         {
143             /* Perhaps the next data packet of the current PES packet contains
144              * real data (ie its payload's size is greater than 0). */
145             p_bit_stream->p_data = p_bit_stream->p_data->p_next;
146         }
147     } while ( p_bit_stream->p_data->p_payload_start
148                == p_bit_stream->p_data->p_payload_end );
149
150     /* We've found a data packet which contains interesting data... */
151     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
152     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
153
154     /* Copy remaining bits of the previous packet */
155     *((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
156     p_bit_stream->p_byte -= i_bytes_left;
157 }