]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
* ./include/*, ./src/*: separated WIN32 #tests and UNDER_CE #tests, because
[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.41 2002/11/11 14:39:12 sam 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         /* 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             /* The next packet could be found in the next PES packet */
126             input_DeletePES( p_fifo->p_packets_mgt, p_bit_stream->p_pes );
127             input_ExtractPES( p_fifo, &p_bit_stream->p_pes );
128             if( !p_bit_stream->p_pes )
129             {
130                 /* Couldn't get the next PES, might be an eos */
131                 p_bit_stream->p_data = NULL;
132                 return 0;
133             }
134             p_bit_stream->p_data = p_bit_stream->p_pes->p_first;
135             b_new_pes = 1;
136         }
137         else
138         {
139             /* Perhaps the next data packet of the current PES packet contains
140              * real data (ie its payload's size is greater than 0). */
141             p_bit_stream->p_data = p_bit_stream->p_data->p_next;
142
143             b_new_pes = 0;
144         }
145     } while ( p_bit_stream->p_data->p_payload_start ==
146               p_bit_stream->p_data->p_payload_end );
147
148     return( b_new_pes );
149 }
150
151 vlc_bool_t NextDataPacket( decoder_fifo_t * p_fifo,
152                            bit_stream_t * p_bit_stream )
153 {
154     return( _NextDataPacket( p_fifo, p_bit_stream ) );
155 }
156
157 /*****************************************************************************
158  * BitstreamNextDataPacket: go to the next data packet, and update bitstream
159  * context. This function can fail in case of eos!
160  *****************************************************************************/
161 static inline void _BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
162 {
163     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
164     vlc_bool_t          b_new_pes;
165
166     b_new_pes = _NextDataPacket( p_fifo, p_bit_stream );
167     if( !p_bit_stream->p_pes ) return;
168
169     /* We've found a data packet which contains interesting data... */
170     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
171     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
172
173     /* Call back the decoder. */
174     if( p_bit_stream->pf_bitstream_callback != NULL )
175     {
176         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
177     }
178
179     /* Discontinuity management. */
180     if( p_bit_stream->p_data->b_discard_payload )
181     {
182         p_bit_stream->i_pts = p_bit_stream->i_dts = 0;
183     }
184
185     /* Retrieve the PTS. */
186     if( b_new_pes && p_bit_stream->p_pes->i_pts )
187     {
188         p_bit_stream->i_pts = p_bit_stream->p_pes->i_pts;
189         p_bit_stream->i_dts = p_bit_stream->p_pes->i_dts;
190         p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
191     }
192 }
193
194 void BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
195 {
196     _BitstreamNextDataPacket( p_bit_stream );
197 }
198
199 /*****************************************************************************
200  * UnalignedShowBits : places i_bits bits into the bit buffer, even when
201  * not aligned on a word boundary
202  *****************************************************************************/
203 u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
204 {
205     /* We just fill in the bit buffer. */
206     while( p_bit_stream->fifo.i_available < i_bits )
207     {
208         if( p_bit_stream->p_byte < p_bit_stream->p_end )
209         {
210             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
211                                             << (8 * sizeof(WORD_TYPE) - 8
212                                             - p_bit_stream->fifo.i_available);
213             p_bit_stream->fifo.i_available += 8;
214         }
215         else
216         {
217             _BitstreamNextDataPacket( p_bit_stream );
218
219             if( (ptrdiff_t)p_bit_stream->p_byte & (sizeof(WORD_TYPE) - 1) )
220             {
221                 /* We are not aligned anymore. */
222                 if( ((ptrdiff_t)p_bit_stream->p_byte
223                                     & (sizeof(WORD_TYPE) - 1)) * 8
224                         < p_bit_stream->fifo.i_available )
225                 {
226                     /* We are not aligned, and won't be. Copy the first word
227                      * of the packet in a temporary buffer, and we'll see
228                      * later. */
229                     int     i;
230
231                     /* sizeof(WORD_TYPE) - number of bytes to trash
232                      * from the last payload */
233                     int     j;
234
235                     p_bit_stream->i_showbits_buffer = 0;
236
237                     for( j = i = 0 ; i < sizeof(WORD_TYPE) ; i++ )
238                     {
239                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
240                         {
241                             j = i;
242                             _BitstreamNextDataPacket( p_bit_stream );
243                         }
244                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
245                             * p_bit_stream->p_byte;
246                         p_bit_stream->p_byte++;
247                     }
248
249                     /* This is kind of kludgy. */
250                     p_bit_stream->p_data->p_payload_start +=
251                                                          sizeof(WORD_TYPE) - j;
252                     p_bit_stream->p_byte =
253                         (byte_t *)&p_bit_stream->i_showbits_buffer;
254                     p_bit_stream->p_end =
255                         (byte_t *)&p_bit_stream->i_showbits_buffer
256                             + sizeof(WORD_TYPE);
257                     p_bit_stream->showbits_data.p_next = p_bit_stream->p_data;
258                     p_bit_stream->p_data = &p_bit_stream->showbits_data;
259                 }
260                 else
261                 {
262                     /* We are not aligned, but we can be. */
263                     AlignWord( p_bit_stream );
264                 }
265             }
266
267             /* We have 32 bits ready for reading, it will be enough. */
268             break;
269         }
270     }
271
272     /* It shouldn't loop :-)) */
273     return( ShowBits( p_bit_stream, i_bits ) );
274 }
275
276 /*****************************************************************************
277  * UnalignedGetBits : returns i_bits bits from the bit stream and removes
278  * them from the buffer, even when the bit stream is not aligned on a word
279  * boundary
280  *****************************************************************************/
281 u32 UnalignedGetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
282 {
283     u32         i_result;
284
285     i_result = p_bit_stream->fifo.buffer
286                     >> (8 * sizeof(WORD_TYPE) - i_bits);
287     i_bits = -p_bit_stream->fifo.i_available;
288
289     /* Gather missing bytes. */
290     while( i_bits >= 8 )
291     {
292         if( p_bit_stream->p_byte < p_bit_stream->p_end )
293         {
294             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
295             i_bits -= 8;
296         }
297         else
298         {
299             _BitstreamNextDataPacket( p_bit_stream );
300             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
301             i_bits -= 8;
302         }
303     }
304
305     /* Gather missing bits. */
306     if( i_bits > 0 )
307     {
308         unsigned int    i_tmp = 8 - i_bits;
309
310         if( p_bit_stream->p_byte < p_bit_stream->p_end )
311         {
312             i_result |= *p_bit_stream->p_byte >> i_tmp;
313             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
314                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
315             p_bit_stream->fifo.i_available = i_tmp;
316         }
317         else
318         {
319             _BitstreamNextDataPacket( p_bit_stream );
320             i_result |= *p_bit_stream->p_byte >> i_tmp;
321             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
322                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
323             p_bit_stream->fifo.i_available = i_tmp;
324         }
325     }
326     else
327     {
328         p_bit_stream->fifo.i_available = 0;
329         p_bit_stream->fifo.buffer = 0;
330     }
331
332     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
333     {
334         /* Get aligned on a word boundary. Otherwise it is safer
335          * to do it the next time.
336          * NB : we _will_ get aligned, because we have at most
337          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
338          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
339         AlignWord( p_bit_stream );
340     }
341
342     return( i_result );
343 }
344
345 /*****************************************************************************
346  * UnalignedRemoveBits : removes i_bits (== -i_available) from the bit
347  * buffer, even when the bit stream is not aligned on a word boundary
348  *****************************************************************************/
349 void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
350 {
351     /* First remove all unnecessary bytes. */
352     while( p_bit_stream->fifo.i_available <= -8 )
353     {
354         if( p_bit_stream->p_byte < p_bit_stream->p_end )
355         {
356             p_bit_stream->p_byte++;
357             p_bit_stream->fifo.i_available += 8;
358         }
359         else
360         {
361             _BitstreamNextDataPacket( p_bit_stream );
362             p_bit_stream->p_byte++;
363             p_bit_stream->fifo.i_available += 8;
364         }
365     }
366
367     /* Remove unnecessary bits. */
368     if( p_bit_stream->fifo.i_available < 0 )
369     {
370         if( p_bit_stream->p_byte < p_bit_stream->p_end )
371         {
372             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
373                  << ( sizeof(WORD_TYPE) * 8 - 8
374                          - p_bit_stream->fifo.i_available );
375             p_bit_stream->fifo.i_available += 8;
376         }
377         else
378         {
379             _BitstreamNextDataPacket( p_bit_stream );
380             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
381                  << ( sizeof(WORD_TYPE) * 8 - 8
382                          - p_bit_stream->fifo.i_available );
383             p_bit_stream->fifo.i_available += 8;
384         }
385     }
386     else
387     {
388         p_bit_stream->fifo.buffer = 0;
389     }
390
391     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
392     {
393         /* Get aligned on a word boundary. Otherwise it is safer
394          * to do it the next time.
395          * NB : we _will_ get aligned, because we have at most 
396          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
397          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
398         AlignWord( p_bit_stream );
399     }
400 }
401
402 /*****************************************************************************
403  * CurrentPTS: returns the current PTS and DTS
404  *****************************************************************************/
405 void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
406                  mtime_t * pi_dts )
407 {
408     /* Check if the current PTS is already valid (ie. if the first byte
409      * of the packet has already been used in the decoder). */
410     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte;
411     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
412          || (p_diff * 8) >= p_bit_stream->fifo.i_available
413             /* We have buffered less bytes than actually read */ )
414     {
415         *pi_pts = p_bit_stream->i_pts;
416         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
417         p_bit_stream->i_pts = 0;
418         p_bit_stream->i_dts = 0;
419     }
420     else
421     {
422         *pi_pts = 0;
423         if( pi_dts != NULL) *pi_dts = 0;
424     }
425 }
426
427 /*****************************************************************************
428  * NextPTS: returns the PTS and DTS for the next starting byte
429  *****************************************************************************/
430 void NextPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
431               mtime_t * pi_dts )
432 {
433     /* Check if the current PTS is already valid (ie. if the first byte
434      * of the packet has already been used in the decoder). */
435     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte - 1;
436     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
437          || (p_diff * 8) >= p_bit_stream->fifo.i_available
438             /* We have buffered less bytes than actually read */ )
439     {
440         *pi_pts = p_bit_stream->i_pts;
441         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
442         p_bit_stream->i_pts = 0;
443         p_bit_stream->i_dts = 0;
444     }
445     else
446     {
447         *pi_pts = 0;
448         if( pi_dts != NULL) *pi_dts = 0;
449     }
450 }