]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
* Fixed a bug in DecoderError.
[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.27 2001/12/31 03:26:27 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 <string.h>                                    /* memcpy(), memset() */
28 #include <sys/types.h>                                              /* off_t */
29
30 #include <videolan/vlc.h>
31
32 #include "stream_control.h"
33 #include "input_ext-dec.h"
34 #include "input_ext-intf.h"
35 #include "input_ext-plugins.h"
36
37 /*****************************************************************************
38  * InitBitstream: initialize a bit_stream_t structure
39  *****************************************************************************/
40 void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
41                     void (* pf_bitstream_callback)( struct bit_stream_s *,
42                                                     boolean_t ),
43                     void * p_callback_arg )
44 {
45     p_bit_stream->p_decoder_fifo = p_fifo;
46     p_bit_stream->pf_next_data_packet = NextDataPacket;
47     p_bit_stream->pf_bitstream_callback = pf_bitstream_callback;
48     p_bit_stream->p_callback_arg = p_callback_arg;
49
50     /* Get the first data packet. */
51     vlc_mutex_lock( &p_fifo->data_lock );
52     while ( p_fifo->p_first == NULL )
53     {
54         if ( p_fifo->b_die )
55         {
56             vlc_mutex_unlock( &p_fifo->data_lock );
57             return;
58         }
59         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
60     }
61     p_bit_stream->p_data = p_fifo->p_first->p_first;
62     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
63     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
64     p_bit_stream->fifo.buffer = 0;
65     p_bit_stream->fifo.i_available = 0;
66     vlc_mutex_unlock( &p_fifo->data_lock );
67
68     /* Call back the decoder. */
69     if( p_bit_stream->pf_bitstream_callback != NULL )
70     {
71         p_bit_stream->pf_bitstream_callback( p_bit_stream, 1 );
72     }
73
74     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
75     {
76         /* Get aligned on a word boundary.
77          * NB : we _will_ get aligned, because we have at most 
78          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
79          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
80         AlignWord( p_bit_stream );
81     }
82 }
83
84 /*****************************************************************************
85  * DecoderError : an error occured, use this function to empty the fifo
86  *****************************************************************************/
87 void DecoderError( decoder_fifo_t * p_fifo )
88 {
89     /* We take the lock, because we are going to read/write the start/end
90      * indexes of the decoder fifo */
91     vlc_mutex_lock (&p_fifo->data_lock);
92
93     /* Wait until a `die' order is sent */
94     while (!p_fifo->b_die)
95     {
96         /* Trash all received PES packets */
97         p_fifo->pf_delete_pes( p_fifo->p_packets_mgt, p_fifo->p_first );
98         p_fifo->p_first = NULL;
99         p_fifo->pp_last = &p_fifo->p_first;
100
101         /* Waiting for the input thread to put new PES packets in the fifo */
102         vlc_cond_wait (&p_fifo->data_wait, &p_fifo->data_lock);
103     }
104
105     /* We can release the lock before leaving */
106     vlc_mutex_unlock (&p_fifo->data_lock);
107 }
108
109 /*****************************************************************************
110  * NextDataPacket: go to the next data packet
111  *****************************************************************************/
112 void NextDataPacket( bit_stream_t * p_bit_stream )
113 {
114     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
115     boolean_t           b_new_pes;
116
117     /* We are looking for the next data packet that contains real data,
118      * and not just a PES header */
119     do
120     {
121         /* We were reading the last data packet of this PES packet... It's
122          * time to jump to the next PES packet */
123         if( p_bit_stream->p_data->p_next == NULL )
124         {
125             pes_packet_t * p_next;
126
127             vlc_mutex_lock( &p_fifo->data_lock );
128
129             /* Free the previous PES packet. */
130             p_next = p_fifo->p_first->p_next;
131             p_fifo->p_first->p_next = NULL;
132             p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
133                                    p_fifo->p_first );
134             p_fifo->p_first = p_next;
135             p_fifo->i_depth--;
136
137             if( p_fifo->p_first == NULL )
138             {
139                 /* No PES in the FIFO. p_last is no longer valid. */
140                 p_fifo->pp_last = &p_fifo->p_first;
141
142                 /* Wait for the input to tell us when we receive a packet. */
143                 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
144             }
145
146             /* The next byte could be found in the next PES packet */
147             p_bit_stream->p_data = p_fifo->p_first->p_first;
148
149             vlc_mutex_unlock( &p_fifo->data_lock );
150
151             b_new_pes = 1;
152         }
153         else
154         {
155             /* Perhaps the next data packet of the current PES packet contains
156              * real data (ie its payload's size is greater than 0). */
157             p_bit_stream->p_data = p_bit_stream->p_data->p_next;
158
159             b_new_pes = 0;
160         }
161     } while ( p_bit_stream->p_data->p_payload_start
162                == p_bit_stream->p_data->p_payload_end );
163
164     /* We've found a data packet which contains interesting data... */
165     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
166     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
167
168     /* Call back the decoder. */
169     if( p_bit_stream->pf_bitstream_callback != NULL )
170     {
171         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
172     }
173 }
174
175 /*****************************************************************************
176  * UnalignedShowBits : places i_bits bits into the bit buffer, even when
177  * not aligned on a word boundary
178  *****************************************************************************/
179 u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
180 {
181     /* We just fill in the bit buffer. */
182     while( p_bit_stream->fifo.i_available < i_bits )
183     {
184         if( p_bit_stream->p_byte < p_bit_stream->p_end )
185         {
186             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
187                                             << (8 * sizeof(WORD_TYPE) - 8
188                                             - p_bit_stream->fifo.i_available);
189             p_bit_stream->fifo.i_available += 8;
190         }
191         else
192         {
193             p_bit_stream->pf_next_data_packet( p_bit_stream );
194
195             if( (ptrdiff_t)p_bit_stream->p_byte & (sizeof(WORD_TYPE) - 1) )
196             {
197                 /* We are not aligned anymore. */
198                 if( ((ptrdiff_t)p_bit_stream->p_byte
199                                     & (sizeof(WORD_TYPE) - 1)) * 8
200                         < p_bit_stream->fifo.i_available )
201                 {
202                     /* We are not aligned, and won't be. Copy the first word
203                      * of the packet in a temporary buffer, and we'll see
204                      * later. */
205                     int     i;
206
207                     /* sizeof(WORD_TYPE) - number of bytes to trash
208                      * from the last payload */
209                     int     j;
210
211                     p_bit_stream->i_showbits_buffer = 0;
212
213                     for( j = i = 0 ; i < sizeof(WORD_TYPE) ; i++ )
214                     {
215                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
216                         {
217                             j = i;
218                             p_bit_stream->pf_next_data_packet( p_bit_stream );
219                         }
220                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
221                             * p_bit_stream->p_byte;
222                         p_bit_stream->p_byte++;
223                     }
224
225                     /* This is kind of kludgy. */
226                     p_bit_stream->p_data->p_payload_start +=
227                                                          sizeof(WORD_TYPE) - j;
228                     p_bit_stream->p_byte =
229                         (byte_t *)&p_bit_stream->i_showbits_buffer;
230                     p_bit_stream->p_end =
231                         (byte_t *)&p_bit_stream->i_showbits_buffer
232                             + sizeof(WORD_TYPE);
233                     p_bit_stream->showbits_data.p_next = p_bit_stream->p_data;
234                     p_bit_stream->p_data = &p_bit_stream->showbits_data;
235                 }
236                 else
237                 {
238                     /* We are not aligned, but we can be. */
239                     AlignWord( p_bit_stream );
240                 }
241             }
242
243             /* We have 32 bits ready for reading, it will be enough. */
244             break;
245         }
246     }
247
248     /* It shouldn't loop :-)) */
249     return( ShowBits( p_bit_stream, i_bits ) );
250 }
251
252 /*****************************************************************************
253  * UnalignedGetBits : returns i_bits bits from the bit stream and removes
254  * them from the buffer, even when the bit stream is not aligned on a word
255  * boundary
256  *****************************************************************************/
257 u32 UnalignedGetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
258 {
259     u32         i_result;
260
261     i_result = p_bit_stream->fifo.buffer
262                     >> (8 * sizeof(WORD_TYPE) - i_bits);
263     i_bits = -p_bit_stream->fifo.i_available;
264
265     /* Gather missing bytes. */
266     while( i_bits >= 8 )
267     {
268         if( p_bit_stream->p_byte < p_bit_stream->p_end )
269         {
270             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
271             i_bits -= 8;
272         }
273         else
274         {
275             p_bit_stream->pf_next_data_packet( p_bit_stream );
276             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
277             i_bits -= 8;
278         }
279     }
280
281     /* Gather missing bits. */
282     if( i_bits > 0 )
283     {
284         unsigned int    i_tmp = 8 - i_bits;
285
286         if( p_bit_stream->p_byte < p_bit_stream->p_end )
287         {
288             i_result |= *p_bit_stream->p_byte >> i_tmp;
289             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
290                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
291             p_bit_stream->fifo.i_available = i_tmp;
292         }
293         else
294         {
295             p_bit_stream->pf_next_data_packet( p_bit_stream );
296             i_result |= *p_bit_stream->p_byte >> i_tmp;
297             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
298                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
299             p_bit_stream->fifo.i_available = i_tmp;
300         }
301     }
302     else
303     {
304         p_bit_stream->fifo.i_available = 0;
305         p_bit_stream->fifo.buffer = 0;
306     }
307
308     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
309     {
310         /* Get aligned on a word boundary. Otherwise it is safer
311          * to do it the next time.
312          * NB : we _will_ get aligned, because we have at most
313          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
314          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
315         AlignWord( p_bit_stream );
316     }
317
318     return( i_result );
319 }
320
321 /*****************************************************************************
322  * UnalignedRemoveBits : removes i_bits (== -i_available) from the bit
323  * buffer, even when the bit stream is not aligned on a word boundary
324  *****************************************************************************/
325 void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
326 {
327     /* First remove all unnecessary bytes. */
328     while( p_bit_stream->fifo.i_available <= -8 )
329     {
330         if( p_bit_stream->p_byte < p_bit_stream->p_end )
331         {
332             p_bit_stream->p_byte++;
333             p_bit_stream->fifo.i_available += 8;
334         }
335         else
336         {
337             p_bit_stream->pf_next_data_packet( p_bit_stream );
338             p_bit_stream->p_byte++;
339             p_bit_stream->fifo.i_available += 8;
340         }
341     }
342
343     /* Remove unnecessary bits. */
344     if( p_bit_stream->fifo.i_available < 0 )
345     {
346         if( p_bit_stream->p_byte < p_bit_stream->p_end )
347         {
348             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
349                  << ( sizeof(WORD_TYPE) * 8 - 8
350                          - p_bit_stream->fifo.i_available );
351             p_bit_stream->fifo.i_available += 8;
352         }
353         else
354         {
355             p_bit_stream->pf_next_data_packet( p_bit_stream );
356             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
357                  << ( sizeof(WORD_TYPE) * 8 - 8
358                          - p_bit_stream->fifo.i_available );
359             p_bit_stream->fifo.i_available += 8;
360         }
361     }
362     else
363     {
364         p_bit_stream->fifo.buffer = 0;
365     }
366
367     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
368     {
369         /* Get aligned on a word boundary. Otherwise it is safer
370          * to do it the next time.
371          * NB : we _will_ get aligned, because we have at most 
372          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
373          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
374         AlignWord( p_bit_stream );
375     }
376 }
377