]> git.sesse.net Git - vlc/blob - include/decoder_fifo.h
Je vous avais pr�venu. Le demoronifier a frapp�.
[vlc] / include / decoder_fifo.h
1 /*****************************************************************************
2  * decoder_fifo.h: interface for decoders PES fifo
3  * (c)1999 VideoLAN
4  *****************************************************************************
5  * Required headers:
6  * - "config.h"
7  * - "common.h"
8  * - "vlc_thread.h"
9  * - "input.h"
10  *****************************************************************************/
11
12 /*****************************************************************************
13  * Macros
14  *****************************************************************************/
15
16 /* ?? move to inline functions */
17 #define DECODER_FIFO_ISEMPTY( fifo )    ( (fifo).i_start == (fifo).i_end )
18 #define DECODER_FIFO_ISFULL( fifo )     ( ( ( (fifo).i_end + 1 - (fifo).i_start ) \
19                                           & FIFO_SIZE ) == 0 )
20 #define DECODER_FIFO_START( fifo )      ( (fifo).buffer[ (fifo).i_start ] )
21 #define DECODER_FIFO_INCSTART( fifo )   ( (fifo).i_start = ((fifo).i_start + 1)\
22                                                            & FIFO_SIZE )
23 #define DECODER_FIFO_END( fifo )        ( (fifo).buffer[ (fifo).i_end ] )
24 #define DECODER_FIFO_INCEND( fifo )     ( (fifo).i_end = ((fifo).i_end + 1) \
25                                                          & FIFO_SIZE )
26
27 /*****************************************************************************
28  * decoder_fifo_t
29  *****************************************************************************
30  * This rotative FIFO contains PES packets that are to be decoded...
31  *****************************************************************************/
32 typedef struct
33 {
34     vlc_mutex_t         data_lock;                         /* fifo data lock */
35     vlc_cond_t          data_wait;         /* fifo data conditional variable */
36
37     /* buffer is an array of PES packets pointers */
38     pes_packet_t *      buffer[FIFO_SIZE + 1];
39     int                 i_start;
40     int                 i_end;
41
42 } decoder_fifo_t;
43
44 /*****************************************************************************
45  * bit_fifo_t : bit fifo descriptor
46  *****************************************************************************
47  * This type describes a bit fifo used to store bits while working with the
48  * input stream at the bit level.
49  *****************************************************************************/
50 typedef struct bit_fifo_s
51 {
52     /* This unsigned integer allows us to work at the bit level. This buffer
53      * can contain 32 bits, and the used space can be found on the MSb's side
54      * and the available space on the LSb's side. */
55     u32                 buffer;
56
57     /* Number of bits available in the bit buffer */
58     int                 i_available;
59
60 } bit_fifo_t;
61
62 /*****************************************************************************
63  * bit_stream_t : bit stream descriptor
64  *****************************************************************************
65  * This type, based on a PES stream, includes all the structures needed to
66  * handle the input stream like a bit stream.
67  *****************************************************************************/
68 typedef struct bit_stream_s
69 {
70     /*
71      * Input structures
72      */
73     /* The input thread feeds the stream with fresh PES packets */
74     input_thread_t *    p_input;
75     /* The decoder fifo contains the data of the PES stream */
76     decoder_fifo_t *    p_decoder_fifo;
77
78     /*
79      * Byte structures
80      */
81     /* Current TS packet (in the current PES packet of the PES stream) */
82     ts_packet_t *       p_ts;
83     /* Index of the next byte that is to be read (in the current TS packet) */
84     unsigned int        i_byte;
85
86     /*
87      * Bit structures
88      */
89     bit_fifo_t          fifo;
90
91 } bit_stream_t;
92
93
94 /*****************************************************************************
95  * GetByte : reads the next byte in the input stream
96  *****************************************************************************/
97 static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
98 {
99     /* Are there some bytes left in the current TS packet ? */
100     if ( p_bit_stream->i_byte < p_bit_stream->p_ts->i_payload_end )
101     {
102         return( p_bit_stream->p_ts->buffer[ p_bit_stream->i_byte++ ] );
103     }
104     else
105     {
106         /* We are looking for the next TS packet that contains real data,
107          * and not just a PES header */
108         do
109         {
110             /* We were reading the last TS packet of this PES packet... It's
111              * time to jump to the next PES packet */
112             if ( p_bit_stream->p_ts->p_next_ts == NULL )
113             {
114                 /* We are going to read/write the start and end indexes of the
115                  * decoder fifo and to use the fifo's conditional variable,
116                  * that's why we need to take the lock before */
117                 vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
118
119                 /* Is the input thread dying ? */
120                 if ( p_bit_stream->p_input->b_die )
121                 {
122                     vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
123                     return( 0 );
124                 }
125
126                 /* We should increase the start index of the decoder fifo, but
127                  * if we do this now, the input thread could overwrite the
128                  * pointer to the current PES packet, and we weren't able to
129                  * give it back to the netlist. That's why we free the PES
130                  * packet first. */
131                 input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
132                 DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
133
134                 while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
135                 {
136                     vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
137                     if ( p_bit_stream->p_input->b_die )
138                     {
139                         vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
140                         return( 0 );
141                     }
142                 }
143
144                 /* The next byte could be found in the next PES packet */
145                 p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
146
147                 /* We can release the fifo's data lock */
148                 vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
149             }
150             /* Perhaps the next TS packet of the current PES packet contains
151              * real data (ie its payload's size is greater than 0) */
152             else
153             {
154                 p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
155             }
156         } while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
157
158         /* We've found a TS packet which contains interesting data... As we
159          * return the payload's first byte, we set i_byte to the following
160          * one */
161         p_bit_stream->i_byte = p_bit_stream->p_ts->i_payload_start;
162         return( p_bit_stream->p_ts->buffer[ p_bit_stream->i_byte++ ] );
163     }
164 }
165
166 /*****************************************************************************
167  * NeedBits : reads i_bits new bits in the bit stream and stores them in the
168  *            bit buffer
169  *****************************************************************************
170  * - i_bits must be less or equal 32 !
171  * - There is something important to notice with that function : if the number
172  * of bits available in the bit buffer when calling NeedBits() is greater than
173  * 24 (i_available > 24) but less than the number of needed bits
174  * (i_available < i_bits), the byte returned by GetByte() will be shifted with
175  * a negative value and the number of bits available in the bit buffer will be
176  * set to more than 32 !
177  *****************************************************************************/
178 static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
179 {
180     while ( p_bit_stream->fifo.i_available < i_bits )
181     {
182         p_bit_stream->fifo.buffer |= ((u32)GetByte( p_bit_stream )) << (24 - p_bit_stream->fifo.i_available);
183         p_bit_stream->fifo.i_available += 8;
184     }
185 }
186
187 /*****************************************************************************
188  * DumpBits : removes i_bits bits from the bit buffer
189  *****************************************************************************
190  * - i_bits <= i_available
191  * - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
192  *****************************************************************************/
193 static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
194 {
195     p_bit_stream->fifo.buffer <<= i_bits;
196     p_bit_stream->fifo.i_available -= i_bits;
197 }
198
199 /*****************************************************************************
200  * DumpBits32 : removes 32 bits from the bit buffer
201  *****************************************************************************
202  * This function actually believes that you have already put 32 bits in the
203  * bit buffer, so you can't you use it anytime.
204  *****************************************************************************/
205 static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
206 {
207     p_bit_stream->fifo.buffer = 0;
208     p_bit_stream->fifo.i_available = 0;
209 }
210
211 /*
212  * For the following functions, please read VERY CAREFULLY the warning in
213  * NeedBits(). If i_bits > 24, the stream parser must be already aligned
214  * on an 8-bit boundary, or you will get curious results (that is, you
215  * need to call RealignBits() before).
216  */
217
218 /*****************************************************************************
219  * RemoveBits : removes i_bits bits from the bit buffer
220  *****************************************************************************/
221 static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
222 {
223     NeedBits( p_bit_stream, i_bits );
224     DumpBits( p_bit_stream, i_bits );
225 }
226
227 /*****************************************************************************
228  * RemoveBits32 : removes 32 bits from the bit buffer
229  *****************************************************************************/
230 static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
231 {
232     NeedBits( p_bit_stream, 32 );
233     DumpBits32( p_bit_stream );
234 }
235
236 /*****************************************************************************
237  * ShowBits : return i_bits bits from the bit stream
238  *****************************************************************************/
239 static __inline__ u32 ShowBits( bit_stream_t * p_bit_stream, int i_bits )
240 {
241     NeedBits( p_bit_stream, i_bits );
242     return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
243 }
244
245 /*****************************************************************************
246  * GetBits : returns i_bits bits from the bit stream and removes them
247  *****************************************************************************/
248 static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
249 {
250     u32 i_buffer;
251
252     NeedBits( p_bit_stream, i_bits );
253     i_buffer = p_bit_stream->fifo.buffer >> (32 - i_bits);
254     DumpBits( p_bit_stream, i_bits );
255     return( i_buffer );
256 }
257
258 /*****************************************************************************
259  * GetBits32 : returns 32 bits from the bit stream and removes them
260  *****************************************************************************/
261 static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
262 {
263     u32 i_buffer;
264
265     NeedBits( p_bit_stream, 32 );
266     i_buffer = p_bit_stream->fifo.buffer;
267     DumpBits32( p_bit_stream );
268     return( i_buffer );
269 }
270
271 /*****************************************************************************
272  * RealignBits : realigns the bit buffer on an 8-bit boundary
273  *****************************************************************************/
274 static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
275 {
276     DumpBits( p_bit_stream, p_bit_stream->fifo.i_available & 7 );
277 }