]> git.sesse.net Git - vlc/blob - include/decoder_fifo.h
. removed the sdlvlc alias
[vlc] / include / decoder_fifo.h
1 /*****************************************************************************
2  * decoder_fifo.h: interface for decoders PES fifo
3  *****************************************************************************
4  * Copyright (C) 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  * Required headers:
25  * - "config.h"
26  * - "common.h"
27  * - "threads.h"
28  * - "input.h"
29  *****************************************************************************/
30
31 #define WORD_TYPE           u32
32 #define WORD_BYTE_LENGTH    4
33 #define WORD_LENGTH         32
34
35 /*****************************************************************************
36  * Macros
37  *****************************************************************************/
38
39 /* FIXME: move to inline functions ??*/
40 #define DECODER_FIFO_ISEMPTY( fifo )  ( (fifo).i_start == (fifo).i_end )
41 #define DECODER_FIFO_ISFULL( fifo )   ( ( ((fifo).i_end + 1 - (fifo).i_start)\
42                                           & FIFO_SIZE ) == 0 )
43 #define DECODER_FIFO_START( fifo )    ( (fifo).buffer[ (fifo).i_start ] )
44 #define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
45                                                          & FIFO_SIZE )
46 #define DECODER_FIFO_END( fifo )      ( (fifo).buffer[ (fifo).i_end ] )
47 #define DECODER_FIFO_INCEND( fifo )   ( (fifo).i_end = ((fifo).i_end + 1) \
48                                                        & FIFO_SIZE )
49
50 /*****************************************************************************
51  * decoder_fifo_t
52  *****************************************************************************
53  * This rotative FIFO contains PES packets that are to be decoded...
54  *****************************************************************************/
55 typedef struct
56 {
57     vlc_mutex_t         data_lock;                         /* fifo data lock */
58     vlc_cond_t          data_wait;         /* fifo data conditional variable */
59
60     /* buffer is an array of PES packets pointers */
61     pes_packet_t *      buffer[FIFO_SIZE + 1];
62     int                 i_start;
63     int                 i_end;
64
65 } decoder_fifo_t;
66
67 /*****************************************************************************
68  * bit_fifo_t : bit fifo descriptor
69  *****************************************************************************
70  * This type describes a bit fifo used to store bits while working with the
71  * input stream at the bit level.
72  *****************************************************************************/
73 typedef struct bit_fifo_s
74 {
75     /* This unsigned integer allows us to work at the bit level. This buffer
76      * can contain 32 bits, and the used space can be found on the MSb's side
77      * and the available space on the LSb's side. */
78     WORD_TYPE           buffer;
79
80     /* Number of bits available in the bit buffer */
81     int                 i_available;
82
83 } bit_fifo_t;
84
85 /*****************************************************************************
86  * bit_stream_t : bit stream descriptor
87  *****************************************************************************
88  * This type, based on a PES stream, includes all the structures needed to
89  * handle the input stream like a bit stream.
90  *****************************************************************************/
91 typedef struct bit_stream_s
92 {
93     /*
94      * Input structures
95      */
96     /* The input thread feeds the stream with fresh PES packets */
97     input_thread_t *    p_input;
98     /* The decoder fifo contains the data of the PES stream */
99     decoder_fifo_t *    p_decoder_fifo;
100
101     /*
102      * Byte structures
103      */
104     /* Current TS packet (in the current PES packet of the PES stream) */
105     ts_packet_t *       p_ts;
106    /* Pointer to the next byte that is to be read (in the current TS packet) */
107     byte_t *            p_byte;
108     /* Pointer to the last byte that is to be read (in the current TS packet */
109     byte_t *            p_end;
110
111     /*
112      * Bit structures
113      */
114     bit_fifo_t          fifo;
115
116 } bit_stream_t;
117
118
119 void decoder_fifo_next( bit_stream_t * p_bit_stream );
120 /*****************************************************************************
121  * GetByte : reads the next byte in the input stream
122  *****************************************************************************/
123 static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
124 {
125     /* Are there some bytes left in the current TS packet ? */
126     /* could change this test to have a if (! (bytes--)) instead */
127     if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
128     {
129         /* no, switch to next TS packet */
130         decoder_fifo_next( p_bit_stream );
131     }
132
133     return( *(p_bit_stream->p_byte++));
134 }
135
136 /*****************************************************************************
137  * NeedBits : reads i_bits new bits in the bit stream and stores them in the
138  *            bit buffer
139  *****************************************************************************
140  * - i_bits must be less or equal 32 !
141  * - There is something important to notice with that function : if the number
142  * of bits available in the bit buffer when calling NeedBits() is greater than
143  * 24 (i_available > 24) but less than the number of needed bits
144  * (i_available < i_bits), the byte returned by GetByte() will be shifted with
145  * a negative value and the number of bits available in the bit buffer will be
146  * set to more than 32 !
147  *****************************************************************************/
148 static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
149 {
150     while ( p_bit_stream->fifo.i_available < i_bits )
151     {
152         p_bit_stream->fifo.buffer |= ((u32)GetByte( p_bit_stream )) << (24 - p_bit_stream->fifo.i_available);
153         p_bit_stream->fifo.i_available += 8;
154     }
155 }
156
157 /*****************************************************************************
158  * DumpBits : removes i_bits bits from the bit buffer
159  *****************************************************************************
160  * - i_bits <= i_available
161  * - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
162  *****************************************************************************/
163 static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
164 {
165     p_bit_stream->fifo.buffer <<= i_bits;
166     p_bit_stream->fifo.i_available -= i_bits;
167 }
168
169 /*****************************************************************************
170  * DumpBits32 : removes 32 bits from the bit buffer
171  *****************************************************************************
172  * This function actually believes that you have already put 32 bits in the
173  * bit buffer, so you can't use it anytime.
174  *****************************************************************************/
175 static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
176 {
177     p_bit_stream->fifo.buffer = 0;
178     p_bit_stream->fifo.i_available = 0;
179 }
180
181 /*
182  * For the following functions, please read VERY CAREFULLY the warning in
183  * NeedBits(). If i_bits > 24, the stream parser must be already aligned
184  * on an 8-bit boundary, or you will get curious results (that is, you
185  * need to call RealignBits() before).
186  */
187
188 void PeekNextPacket( bit_stream_t * p_bit_stream );
189
190 //(stolen from the kernel)
191 // XXX: The macro swab32 for little endian machine does
192 //      not seem to work correctly
193
194 #if defined(SYS_BEOS)
195 #       define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
196 #else
197 #    if __BYTE_ORDER == __BIG_ENDIAN
198 #        define swab32(x) (x)
199 #    else
200 #        if defined (__i386__)
201 #           define swab32(x) __i386_swab32(x)
202 static inline const u32 __i386_swab32(u32 x)
203 {
204     __asm__("bswap %0" : "=r" (x) : "0" (x));
205     return x;
206 }
207 #        else
208 #           define swab32(x)\
209             ( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) |  \
210               ( (u32)(((u8*)&x)[2]) << 8 )  | ( (u32)(((u8*)&x)[3])) )
211 #        endif
212 #    endif
213 #endif
214
215
216 static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
217 {
218     if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
219     {
220         return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
221     }
222     else
223     {
224         PeekNextPacket( p_bit_stream );
225         return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
226     }
227 }
228
229 /*****************************************************************************
230  * RemoveBits : removes i_bits bits from the bit buffer
231  *****************************************************************************/
232 static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
233 {
234     p_bit_stream->fifo.i_available -= i_bits;
235
236     if( p_bit_stream->fifo.i_available >= 0 )
237     {
238         p_bit_stream->fifo.buffer <<= i_bits;
239         return;
240     }
241     p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
242                             << ( -p_bit_stream->fifo.i_available );
243     p_bit_stream->fifo.i_available += WORD_LENGTH;
244 }
245
246 /*****************************************************************************
247  * RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
248  * refill it)
249  *****************************************************************************/
250 static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
251 {
252     p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
253                         << (32 - p_bit_stream->fifo.i_available);
254 }
255
256 /*****************************************************************************
257  * ShowBits : return i_bits bits from the bit stream
258  *****************************************************************************/
259 static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
260 {
261     if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
262     {
263         return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
264     }
265
266     PeekNextPacket( p_bit_stream );
267     return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
268 }
269
270 static __inline__ u32 ShowBits( bit_stream_t * p_bit_stream, int i_bits )
271 {
272     if( p_bit_stream->fifo.i_available >= i_bits )
273     {
274         return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
275     }
276
277     return( (p_bit_stream->fifo.buffer |
278             (ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
279                     >> (32 - i_bits) );
280 }
281
282 /*****************************************************************************
283  * GetBits : returns i_bits bits from the bit stream and removes them
284  *****************************************************************************/
285 static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
286 {
287     u32             i_result;
288
289     p_bit_stream->fifo.i_available -= i_bits;
290     if( p_bit_stream->fifo.i_available >= 0 )
291     {
292         i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
293         p_bit_stream->fifo.buffer <<= i_bits;
294         return( i_result );
295     }
296
297     i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
298     p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
299     i_result |= p_bit_stream->fifo.buffer
300                              >> (32 + p_bit_stream->fifo.i_available);
301     p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
302     p_bit_stream->fifo.i_available += WORD_LENGTH;
303
304     return( i_result );
305 }
306
307 /*****************************************************************************
308  * GetBits32 : returns 32 bits from the bit stream and removes them
309  *****************************************************************************/
310 static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
311 {
312     u32             i_result;
313
314     i_result = p_bit_stream->fifo.buffer;
315     p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
316     i_result |= p_bit_stream->fifo.buffer
317                              >> (p_bit_stream->fifo.i_available);
318     p_bit_stream->fifo.buffer <<= (32 - p_bit_stream->fifo.i_available);
319     
320     return( i_result );
321 }
322
323 /*****************************************************************************
324  * RealignBits : realigns the bit buffer on an 8-bit boundary
325  *****************************************************************************/
326 static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
327 {
328     p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
329     p_bit_stream->fifo.i_available &= ~0x7;
330 }
331