]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
* src/input/input_ext-dec.c: added a few sanity checks that avoid crashing
[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.44 2003/02/26 13:51:36 gbazin 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
29 #include <vlc/vlc.h>
30
31 #include "stream_control.h"
32 #include "input_ext-dec.h"
33 #include "input_ext-intf.h"
34 #include "input_ext-plugins.h"
35
36 /*****************************************************************************
37  * InitBitstream: initialize a bit_stream_t structure and returns VLC_SUCCESS
38  *                on success.
39  *****************************************************************************/
40 int InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
41                 void (* pf_bitstream_callback)( bit_stream_t *, vlc_bool_t ),
42                 void * p_callback_arg )
43 {
44     /* Get the first pes packet */
45     input_ExtractPES( p_fifo, &p_bit_stream->p_pes );
46     if( !p_bit_stream->p_pes )
47         return VLC_EGENERIC;
48
49     p_bit_stream->p_decoder_fifo = p_fifo;
50     p_bit_stream->pf_bitstream_callback = pf_bitstream_callback;
51     p_bit_stream->p_callback_arg = p_callback_arg;
52
53     p_bit_stream->p_data = p_bit_stream->p_pes->p_first;
54     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
55     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
56     p_bit_stream->fifo.buffer = 0;
57     p_bit_stream->fifo.i_available = 0;
58     p_bit_stream->i_pts = p_bit_stream->p_pes->i_pts;
59     p_bit_stream->i_dts = p_bit_stream->p_pes->i_dts;
60     p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
61
62     /* Call back the decoder. */
63     if( p_bit_stream->pf_bitstream_callback != NULL )
64     {
65         p_bit_stream->pf_bitstream_callback( p_bit_stream, 1 );
66     }
67
68     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
69     {
70         /* Get aligned on a word boundary.
71          * NB : we _will_ get aligned, because we have at most 
72          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
73          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
74         AlignWord( p_bit_stream );
75     }
76
77     return VLC_SUCCESS;
78 }
79
80 /*****************************************************************************
81  * CloseBitstream: free the bitstream structure.
82  *****************************************************************************/
83 void CloseBitstream( bit_stream_t * p_bit_stream )
84 {
85     if( p_bit_stream->p_pes )
86         input_DeletePES( p_bit_stream->p_decoder_fifo->p_packets_mgt,
87                          p_bit_stream->p_pes );
88 }
89
90 /*****************************************************************************
91  * DecoderError : an error occured, use this function to empty the fifo
92  *****************************************************************************/
93 void DecoderError( decoder_fifo_t * p_fifo )
94 {
95     /* No need to take the lock, because input_ExtractPES already takes it
96      * and also check for p_fifo->b_die */
97
98     /* Wait until a `die' order is sent */
99     while( !p_fifo->b_die )
100     {
101         /* Trash all received PES packets */
102         input_ExtractPES( p_fifo, NULL );
103     }
104 }
105
106 /*****************************************************************************
107  * NextDataPacket: go to the data packet after *pp_data, return 1 if we
108  * changed PES. This function can fail in case of end of stream, you can
109  * check p_bit_stream->p_data or p_bit_stream->p_pes to know wether we did get
110  * the next data packet.
111  *****************************************************************************/
112 static inline vlc_bool_t _NextDataPacket( decoder_fifo_t * p_fifo,
113                                           bit_stream_t * p_bit_stream )
114 {
115     vlc_bool_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         /* Sanity check. Yes, this can happen if the caller doesn't check
122          * for p_fifo->b_die beforehand. */
123         if( p_bit_stream->p_pes == NULL ) return 0;
124
125         /* We were reading the last data packet of this PES packet... It's
126          * time to jump to the next PES packet */
127         if( p_bit_stream->p_data->p_next == NULL )
128         {
129             /* The next packet could be found in the next PES packet */
130             input_DeletePES( p_fifo->p_packets_mgt, p_bit_stream->p_pes );
131             input_ExtractPES( p_fifo, &p_bit_stream->p_pes );
132             if( !p_bit_stream->p_pes )
133             {
134                 /* Couldn't get the next PES, might be an eos */
135                 p_bit_stream->p_data = NULL;
136                 return 0;
137             }
138             p_bit_stream->p_data = p_bit_stream->p_pes->p_first;
139             b_new_pes = 1;
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             b_new_pes = 0;
148         }
149     } while ( p_bit_stream->p_data->p_payload_start ==
150               p_bit_stream->p_data->p_payload_end );
151
152     return( b_new_pes );
153 }
154
155 vlc_bool_t NextDataPacket( decoder_fifo_t * p_fifo,
156                            bit_stream_t * p_bit_stream )
157 {
158     return( _NextDataPacket( p_fifo, p_bit_stream ) );
159 }
160
161 /*****************************************************************************
162  * BitstreamNextDataPacket: go to the next data packet, and update bitstream
163  * context. This function can fail in case of eos!
164  *****************************************************************************/
165 static inline void _BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
166 {
167     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
168     vlc_bool_t          b_new_pes;
169
170     b_new_pes = _NextDataPacket( p_fifo, p_bit_stream );
171     if( !p_bit_stream->p_pes ) return;
172
173     /* We've found a data packet which contains interesting data... */
174     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
175     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
176
177     /* Call back the decoder. */
178     if( p_bit_stream->pf_bitstream_callback != NULL )
179     {
180         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
181     }
182
183     /* Discontinuity management. */
184     if( p_bit_stream->p_data->b_discard_payload )
185     {
186         p_bit_stream->i_pts = p_bit_stream->i_dts = 0;
187     }
188
189     /* Retrieve the PTS. */
190     if( b_new_pes && p_bit_stream->p_pes->i_pts )
191     {
192         p_bit_stream->i_pts = p_bit_stream->p_pes->i_pts;
193         p_bit_stream->i_dts = p_bit_stream->p_pes->i_dts;
194         p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
195     }
196 }
197
198 void BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
199 {
200     _BitstreamNextDataPacket( p_bit_stream );
201 }
202
203 /*****************************************************************************
204  * UnalignedShowBits : places i_bits bits into the bit buffer, even when
205  * not aligned on a word boundary
206  *****************************************************************************/
207 u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
208 {
209     /* We just fill in the bit buffer. */
210     while( (unsigned int)p_bit_stream->fifo.i_available < i_bits )
211     {
212         if( p_bit_stream->p_byte < p_bit_stream->p_end )
213         {
214             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
215                                             << (8 * sizeof(WORD_TYPE) - 8
216                                             - p_bit_stream->fifo.i_available);
217             p_bit_stream->fifo.i_available += 8;
218         }
219         else
220         {
221             _BitstreamNextDataPacket( p_bit_stream );
222             if( p_bit_stream->p_decoder_fifo->b_die ) return 0;
223
224             if( (ptrdiff_t)p_bit_stream->p_byte & (sizeof(WORD_TYPE) - 1) )
225             {
226                 /* We are not aligned anymore. */
227                 if( ((ptrdiff_t)p_bit_stream->p_byte
228                                     & (sizeof(WORD_TYPE) - 1)) * 8
229                         < (unsigned int)p_bit_stream->fifo.i_available )
230                 {
231                     /* We are not aligned, and won't be. Copy the first word
232                      * of the packet in a temporary buffer, and we'll see
233                      * later. */
234                     int     i;
235
236                     /* sizeof(WORD_TYPE) - number of bytes to trash
237                      * from the last payload */
238                     int     j;
239
240                     p_bit_stream->i_showbits_buffer = 0;
241
242                     for( j = i = 0 ; i < (int)sizeof(WORD_TYPE) ; i++ )
243                     {
244                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
245                         {
246                             j = i;
247                             _BitstreamNextDataPacket( p_bit_stream );
248                             if( p_bit_stream->p_decoder_fifo->b_die ) return 0;
249                         }
250                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
251                             * p_bit_stream->p_byte;
252                         p_bit_stream->p_byte++;
253                     }
254
255                     /* This is kind of kludgy. */
256                     p_bit_stream->p_data->p_payload_start +=
257                                                          sizeof(WORD_TYPE) - j;
258                     p_bit_stream->p_byte =
259                         (byte_t *)&p_bit_stream->i_showbits_buffer;
260                     p_bit_stream->p_end =
261                         (byte_t *)&p_bit_stream->i_showbits_buffer
262                             + sizeof(WORD_TYPE);
263                     p_bit_stream->showbits_data.p_next = p_bit_stream->p_data;
264                     p_bit_stream->p_data = &p_bit_stream->showbits_data;
265                 }
266                 else
267                 {
268                     /* We are not aligned, but we can be. */
269                     AlignWord( p_bit_stream );
270                 }
271             }
272
273             /* We have 32 bits ready for reading, it will be enough. */
274             break;
275         }
276     }
277
278     /* It shouldn't loop :-)) */
279     return( ShowBits( p_bit_stream, i_bits ) );
280 }
281
282 /*****************************************************************************
283  * UnalignedGetBits : returns i_bits bits from the bit stream and removes
284  * them from the buffer, even when the bit stream is not aligned on a word
285  * boundary
286  *****************************************************************************/
287 u32 UnalignedGetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
288 {
289     u32         i_result;
290
291     i_result = p_bit_stream->fifo.buffer
292                     >> (8 * sizeof(WORD_TYPE) - i_bits);
293     i_bits = -p_bit_stream->fifo.i_available;
294
295     /* Gather missing bytes. */
296     while( i_bits >= 8 )
297     {
298         if( p_bit_stream->p_byte < p_bit_stream->p_end )
299         {
300             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
301             i_bits -= 8;
302         }
303         else
304         {
305             _BitstreamNextDataPacket( p_bit_stream );
306             if( p_bit_stream->p_decoder_fifo->b_die ) return 0;
307             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
308             i_bits -= 8;
309         }
310     }
311
312     /* Gather missing bits. */
313     if( i_bits > 0 )
314     {
315         unsigned int    i_tmp = 8 - i_bits;
316
317         if( p_bit_stream->p_byte < p_bit_stream->p_end )
318         {
319             i_result |= *p_bit_stream->p_byte >> i_tmp;
320             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
321                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
322             p_bit_stream->fifo.i_available = i_tmp;
323         }
324         else
325         {
326             _BitstreamNextDataPacket( p_bit_stream );
327             if( p_bit_stream->p_decoder_fifo->b_die ) return 0;
328             i_result |= *p_bit_stream->p_byte >> i_tmp;
329             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
330                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
331             p_bit_stream->fifo.i_available = i_tmp;
332         }
333     }
334     else
335     {
336         p_bit_stream->fifo.i_available = 0;
337         p_bit_stream->fifo.buffer = 0;
338     }
339
340     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
341     {
342         /* Get aligned on a word boundary. Otherwise it is safer
343          * to do it the next time.
344          * NB : we _will_ get aligned, because we have at most
345          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
346          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
347         AlignWord( p_bit_stream );
348     }
349
350     return( i_result );
351 }
352
353 /*****************************************************************************
354  * UnalignedRemoveBits : removes i_bits (== -i_available) from the bit
355  * buffer, even when the bit stream is not aligned on a word boundary
356  *****************************************************************************/
357 void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
358 {
359     /* First remove all unnecessary bytes. */
360     while( p_bit_stream->fifo.i_available <= -8 )
361     {
362         if( p_bit_stream->p_byte < p_bit_stream->p_end )
363         {
364             p_bit_stream->p_byte++;
365             p_bit_stream->fifo.i_available += 8;
366         }
367         else
368         {
369             _BitstreamNextDataPacket( p_bit_stream );
370             if( p_bit_stream->p_decoder_fifo->b_die ) return;
371             p_bit_stream->p_byte++;
372             p_bit_stream->fifo.i_available += 8;
373         }
374     }
375
376     /* Remove unnecessary bits. */
377     if( p_bit_stream->fifo.i_available < 0 )
378     {
379         if( p_bit_stream->p_byte < p_bit_stream->p_end )
380         {
381             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
382                  << ( sizeof(WORD_TYPE) * 8 - 8
383                          - p_bit_stream->fifo.i_available );
384             p_bit_stream->fifo.i_available += 8;
385         }
386         else
387         {
388             _BitstreamNextDataPacket( p_bit_stream );
389             if( p_bit_stream->p_decoder_fifo->b_die ) return;
390             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
391                  << ( sizeof(WORD_TYPE) * 8 - 8
392                          - p_bit_stream->fifo.i_available );
393             p_bit_stream->fifo.i_available += 8;
394         }
395     }
396     else
397     {
398         p_bit_stream->fifo.buffer = 0;
399     }
400
401     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
402     {
403         /* Get aligned on a word boundary. Otherwise it is safer
404          * to do it the next time.
405          * NB : we _will_ get aligned, because we have at most 
406          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
407          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
408         AlignWord( p_bit_stream );
409     }
410 }
411
412 /*****************************************************************************
413  * CurrentPTS: returns the current PTS and DTS
414  *****************************************************************************/
415 void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
416                  mtime_t * pi_dts )
417 {
418     /* Check if the current PTS is already valid (ie. if the first byte
419      * of the packet has already been used in the decoder). */
420     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte;
421     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
422          || (p_diff * 8) >= p_bit_stream->fifo.i_available
423             /* We have buffered less bytes than actually read */ )
424     {
425         *pi_pts = p_bit_stream->i_pts;
426         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
427         p_bit_stream->i_pts = 0;
428         p_bit_stream->i_dts = 0;
429     }
430     else
431     {
432         *pi_pts = 0;
433         if( pi_dts != NULL) *pi_dts = 0;
434     }
435 }
436
437 /*****************************************************************************
438  * NextPTS: returns the PTS and DTS for the next starting byte
439  *****************************************************************************/
440 void NextPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
441               mtime_t * pi_dts )
442 {
443     /* Check if the current PTS is already valid (ie. if the first byte
444      * of the packet has already been used in the decoder). */
445     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte - 1;
446     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
447          || (p_diff * 8) >= p_bit_stream->fifo.i_available
448             /* We have buffered less bytes than actually read */ )
449     {
450         *pi_pts = p_bit_stream->i_pts;
451         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
452         p_bit_stream->i_pts = 0;
453         p_bit_stream->i_dts = 0;
454     }
455     else
456     {
457         *pi_pts = 0;
458         if( pi_dts != NULL) *pi_dts = 0;
459     }
460 }