]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
* Changed the way decoder_fifo_t works ;
[vlc] / src / input / input_ext-dec.c
1 /*****************************************************************************
2  * input_ext-dec.c: services to the decoders
3  *****************************************************************************
4  * Copyright (C) 1998-2001 VideoLAN
5  * $Id: input_ext-dec.c,v 1.23 2001/12/27 01:49:34 massiot Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <string.h>                                    /* memcpy(), memset() */
30 #include <sys/types.h>                                              /* off_t */
31
32 #include "common.h"
33 #include "intf_msg.h"
34 #include "threads.h"
35 #include "mtime.h"
36
37 #include "stream_control.h"
38 #include "input_ext-dec.h"
39 #include "input_ext-intf.h"
40 #include "input_ext-plugins.h"
41
42 /*****************************************************************************
43  * InitBitstream: initialize a bit_stream_t structure
44  *****************************************************************************/
45 void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
46                     void (* pf_bitstream_callback)( struct bit_stream_s *,
47                                                     boolean_t ),
48                     void * p_callback_arg )
49 {
50     p_bit_stream->p_decoder_fifo = p_fifo;
51     p_bit_stream->pf_next_data_packet = NextDataPacket;
52     p_bit_stream->pf_bitstream_callback = pf_bitstream_callback;
53     p_bit_stream->p_callback_arg = p_callback_arg;
54
55     /* Get the first data packet. */
56     vlc_mutex_lock( &p_fifo->data_lock );
57     while ( p_fifo->p_first == NULL )
58     {
59         if ( p_fifo->b_die )
60         {
61             vlc_mutex_unlock( &p_fifo->data_lock );
62             return;
63         }
64         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
65     }
66     p_bit_stream->p_data = p_fifo->p_first->p_first;
67     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
68     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
69     p_bit_stream->fifo.buffer = 0;
70     p_bit_stream->fifo.i_available = 0;
71     vlc_mutex_unlock( &p_fifo->data_lock );
72
73     /* Call back the decoder. */
74     if( p_bit_stream->pf_bitstream_callback != NULL )
75     {
76         p_bit_stream->pf_bitstream_callback( p_bit_stream, 1 );
77     }
78
79     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
80     {
81         /* Get aligned on a word boundary.
82          * NB : we _will_ get aligned, because we have at most 
83          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
84          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
85         AlignWord( p_bit_stream );
86     }
87 }
88
89 /*****************************************************************************
90  * NextDataPacket: go to the next data packet
91  *****************************************************************************/
92 void NextDataPacket( bit_stream_t * p_bit_stream )
93 {
94     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
95     boolean_t           b_new_pes;
96
97     /* We are looking for the next data packet that contains real data,
98      * and not just a PES header */
99     do
100     {
101         /* We were reading the last data packet of this PES packet... It's
102          * time to jump to the next PES packet */
103         if( p_bit_stream->p_data->p_next == NULL )
104         {
105             pes_packet_t * p_next;
106
107             vlc_mutex_lock( &p_fifo->data_lock );
108
109             /* Free the previous PES packet. */
110             p_next = p_fifo->p_first->p_next;
111             p_fifo->p_first->p_next = NULL;
112             p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
113                                    p_fifo->p_first );
114             p_fifo->p_first = p_next;
115             p_fifo->i_depth--;
116
117             if( p_fifo->p_first == NULL )
118             {
119                 /* No PES in the FIFO. p_last is no longer valid. */
120                 p_fifo->pp_last = &p_fifo->p_first;
121
122                 /* Wait for the input to tell us when we receive a packet. */
123                 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
124             }
125
126             /* The next byte could be found in the next PES packet */
127             p_bit_stream->p_data = p_fifo->p_first->p_first;
128
129             vlc_mutex_unlock( &p_fifo->data_lock );
130
131             b_new_pes = 1;
132         }
133         else
134         {
135             /* Perhaps the next data packet of the current PES packet contains
136              * real data (ie its payload's size is greater than 0). */
137             p_bit_stream->p_data = p_bit_stream->p_data->p_next;
138
139             b_new_pes = 0;
140         }
141     } while ( p_bit_stream->p_data->p_payload_start
142                == p_bit_stream->p_data->p_payload_end );
143
144     /* We've found a data packet which contains interesting data... */
145     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
146     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
147
148     /* Call back the decoder. */
149     if( p_bit_stream->pf_bitstream_callback != NULL )
150     {
151         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
152     }
153 }
154
155 /*****************************************************************************
156  * UnalignedShowBits : places i_bits bits into the bit buffer, even when
157  * not aligned on a word boundary
158  *****************************************************************************/
159 u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
160 {
161     /* We just fill in the bit buffer. */
162     while( p_bit_stream->fifo.i_available < i_bits )
163     {
164         if( p_bit_stream->p_byte < p_bit_stream->p_end )
165         {
166             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
167                                             << (8 * sizeof(WORD_TYPE) - 8
168                                             - p_bit_stream->fifo.i_available);
169             p_bit_stream->fifo.i_available += 8;
170         }
171         else
172         {
173             p_bit_stream->pf_next_data_packet( p_bit_stream );
174
175             if( (ptrdiff_t)p_bit_stream->p_byte & (sizeof(WORD_TYPE) - 1) )
176             {
177                 /* We are not aligned anymore. */
178                 if( ((ptrdiff_t)p_bit_stream->p_byte
179                                     & (sizeof(WORD_TYPE) - 1)) * 8
180                         < p_bit_stream->fifo.i_available )
181                 {
182                     /* We are not aligned, and won't be. Copy the first word
183                      * of the packet in a temporary buffer, and we'll see
184                      * later. */
185                     int     i;
186
187                     /* sizeof(WORD_TYPE) - number of bytes to trash
188                      * from the last payload */
189                     int     j;
190
191                     p_bit_stream->i_showbits_buffer = 0;
192
193                     for( j = i = 0 ; i < sizeof(WORD_TYPE) ; i++ )
194                     {
195                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
196                         {
197                             j = i;
198                             p_bit_stream->pf_next_data_packet( p_bit_stream );
199                         }
200                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
201                             * p_bit_stream->p_byte;
202                         p_bit_stream->p_byte++;
203                     }
204
205                     /* This is kind of kludgy. */
206                     p_bit_stream->p_data->p_payload_start +=
207                                                          sizeof(WORD_TYPE) - j;
208                     p_bit_stream->p_byte =
209                         (byte_t *)&p_bit_stream->i_showbits_buffer;
210                     p_bit_stream->p_end =
211                         (byte_t *)&p_bit_stream->i_showbits_buffer
212                             + sizeof(WORD_TYPE);
213                     p_bit_stream->showbits_data.p_next = p_bit_stream->p_data;
214                     p_bit_stream->p_data = &p_bit_stream->showbits_data;
215                 }
216                 else
217                 {
218                     /* We are not aligned, but we can be. */
219                     AlignWord( p_bit_stream );
220                 }
221             }
222
223             /* We have 32 bits ready for reading, it will be enough. */
224             break;
225         }
226     }
227
228     /* It shouldn't loop :-)) */
229     return( ShowBits( p_bit_stream, i_bits ) );
230 }
231
232 /*****************************************************************************
233  * UnalignedGetBits : returns i_bits bits from the bit stream and removes
234  * them from the buffer, even when the bit stream is not aligned on a word
235  * boundary
236  *****************************************************************************/
237 u32 UnalignedGetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
238 {
239     u32         i_result;
240
241     i_result = p_bit_stream->fifo.buffer
242                     >> (8 * sizeof(WORD_TYPE) - i_bits);
243     i_bits = -p_bit_stream->fifo.i_available;
244
245     /* Gather missing bytes. */
246     while( i_bits >= 8 )
247     {
248         if( p_bit_stream->p_byte < p_bit_stream->p_end )
249         {
250             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
251             i_bits -= 8;
252         }
253         else
254         {
255             p_bit_stream->pf_next_data_packet( p_bit_stream );
256             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
257             i_bits -= 8;
258         }
259     }
260
261     /* Gather missing bits. */
262     if( i_bits > 0 )
263     {
264         unsigned int    i_tmp = 8 - i_bits;
265
266         if( p_bit_stream->p_byte < p_bit_stream->p_end )
267         {
268             i_result |= *p_bit_stream->p_byte >> i_tmp;
269             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
270                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
271             p_bit_stream->fifo.i_available = i_tmp;
272         }
273         else
274         {
275             p_bit_stream->pf_next_data_packet( p_bit_stream );
276             i_result |= *p_bit_stream->p_byte >> i_tmp;
277             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
278                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
279             p_bit_stream->fifo.i_available = i_tmp;
280         }
281     }
282     else
283     {
284         p_bit_stream->fifo.i_available = 0;
285         p_bit_stream->fifo.buffer = 0;
286     }
287
288     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
289     {
290         /* Get aligned on a word boundary. Otherwise it is safer
291          * to do it the next time.
292          * NB : we _will_ get aligned, because we have at most
293          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
294          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
295         AlignWord( p_bit_stream );
296     }
297
298     return( i_result );
299 }
300
301 /*****************************************************************************
302  * UnalignedRemoveBits : removes i_bits (== -i_available) from the bit
303  * buffer, even when the bit stream is not aligned on a word boundary
304  *****************************************************************************/
305 void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
306 {
307     /* First remove all unnecessary bytes. */
308     while( p_bit_stream->fifo.i_available <= -8 )
309     {
310         if( p_bit_stream->p_byte < p_bit_stream->p_end )
311         {
312             p_bit_stream->p_byte++;
313             p_bit_stream->fifo.i_available += 8;
314         }
315         else
316         {
317             p_bit_stream->pf_next_data_packet( p_bit_stream );
318             p_bit_stream->p_byte++;
319             p_bit_stream->fifo.i_available += 8;
320         }
321     }
322
323     /* Remove unnecessary bits. */
324     if( p_bit_stream->fifo.i_available < 0 )
325     {
326         if( p_bit_stream->p_byte < p_bit_stream->p_end )
327         {
328             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
329                  << ( sizeof(WORD_TYPE) * 8 - 8
330                          - p_bit_stream->fifo.i_available );
331             p_bit_stream->fifo.i_available += 8;
332         }
333         else
334         {
335             p_bit_stream->pf_next_data_packet( p_bit_stream );
336             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
337                  << ( sizeof(WORD_TYPE) * 8 - 8
338                          - p_bit_stream->fifo.i_available );
339             p_bit_stream->fifo.i_available += 8;
340         }
341     }
342     else
343     {
344         p_bit_stream->fifo.buffer = 0;
345     }
346
347     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
348     {
349         /* Get aligned on a word boundary. Otherwise it is safer
350          * to do it the next time.
351          * NB : we _will_ get aligned, because we have at most 
352          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
353          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
354         AlignWord( p_bit_stream );
355     }
356 }
357