]> git.sesse.net Git - vlc/blob - src/input/input_ext-dec.c
bd40554f813dd043c5993a8cf928c98c600831b2
[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.35 2002/10/21 10:46:34 fenrir 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 <vlc/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)( bit_stream_t *, vlc_bool_t ),
42                 void * p_callback_arg )
43 {
44     p_bit_stream->p_decoder_fifo = p_fifo;
45     p_bit_stream->pf_bitstream_callback = pf_bitstream_callback;
46     p_bit_stream->p_callback_arg = p_callback_arg;
47
48     /* Get the first data packet. */
49     vlc_mutex_lock( &p_fifo->data_lock );
50     while ( p_fifo->p_first == NULL )
51     {
52         if ( p_fifo->b_die )
53         {
54             vlc_mutex_unlock( &p_fifo->data_lock );
55             return;
56         }
57         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
58     }
59     p_bit_stream->p_data = p_fifo->p_first->p_first;
60     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
61     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
62     p_bit_stream->fifo.buffer = 0;
63     p_bit_stream->fifo.i_available = 0;
64     p_bit_stream->i_pts = p_fifo->p_first->i_pts;
65     p_bit_stream->i_dts = p_fifo->p_first->i_dts;
66     p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
67     vlc_mutex_unlock( &p_fifo->data_lock );
68
69     /* Call back the decoder. */
70     if( p_bit_stream->pf_bitstream_callback != NULL )
71     {
72         p_bit_stream->pf_bitstream_callback( p_bit_stream, 1 );
73     }
74
75     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
76     {
77         /* Get aligned on a word boundary.
78          * NB : we _will_ get aligned, because we have at most 
79          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
80          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
81         AlignWord( p_bit_stream );
82     }
83 }
84
85 /*****************************************************************************
86  * DecoderError : an error occured, use this function to empty the fifo
87  *****************************************************************************/
88 void DecoderError( decoder_fifo_t * p_fifo )
89 {
90     /* We take the lock, because we are going to read/write the start/end
91      * indexes of the decoder fifo */
92     vlc_mutex_lock (&p_fifo->data_lock);
93
94     /* Wait until a `die' order is sent */
95     while (!p_fifo->b_die)
96     {
97         /* Trash all received PES packets */
98         input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
99         p_fifo->p_first = NULL;
100         p_fifo->pp_last = &p_fifo->p_first;
101
102         /* If the input is waiting for us, tell him to stop */
103         vlc_cond_signal( &p_fifo->data_wait );
104
105         /* Waiting for the input thread to put new PES packets in the fifo */
106         vlc_cond_wait (&p_fifo->data_wait, &p_fifo->data_lock);
107     }
108
109     /* We can release the lock before leaving */
110     vlc_mutex_unlock (&p_fifo->data_lock);
111 }
112
113 /*****************************************************************************
114  * NextDataPacket: go to the data packet after *pp_data, return 1 if we
115  * changed PES
116  *****************************************************************************/
117 static inline vlc_bool_t _NextDataPacket( decoder_fifo_t * p_fifo,
118                                           data_packet_t ** pp_data )
119 {
120     vlc_bool_t b_new_pes;
121
122     /* We are looking for the next data packet that contains real data,
123      * and not just a PES header */
124     do
125     {
126         /* We were reading the last data packet of this PES packet... It's
127          * time to jump to the next PES packet */
128         if( (*pp_data)->p_next == NULL )
129         {
130             pes_packet_t * p_next;
131
132             vlc_mutex_lock( &p_fifo->data_lock );
133
134             /* Free the previous PES packet. */
135             p_next = p_fifo->p_first->p_next;
136             p_fifo->p_first->p_next = NULL;
137             input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
138             p_fifo->p_first = p_next;
139             p_fifo->i_depth--;
140
141             if( p_fifo->p_first == NULL )
142             {
143                 /* No PES in the FIFO. p_last is no longer valid. */
144                 p_fifo->pp_last = &p_fifo->p_first;
145
146                 /* Signal the input thread we're waiting. This is only
147                  * needed in case of slave clock (ES plug-in)  but it won't
148                  * harm. */
149                 vlc_cond_signal( &p_fifo->data_wait );
150
151                 /* Wait for the input to tell us when we receive a packet. */
152                 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
153             }
154
155             /* The next packet could be found in the next PES packet */
156             *pp_data = p_fifo->p_first->p_first;
157
158             vlc_mutex_unlock( &p_fifo->data_lock );
159
160             b_new_pes = 1;
161         }
162         else
163         {
164             /* Perhaps the next data packet of the current PES packet contains
165              * real data (ie its payload's size is greater than 0). */
166             *pp_data = (*pp_data)->p_next;
167
168             b_new_pes = 0;
169         }
170     } while ( (*pp_data)->p_payload_start == (*pp_data)->p_payload_end );
171
172     return( b_new_pes );
173 }
174
175 vlc_bool_t NextDataPacket( decoder_fifo_t * p_fifo, data_packet_t ** pp_data )
176 {
177     return( _NextDataPacket( p_fifo, pp_data ) );
178 }
179
180 /*****************************************************************************
181  * BitstreamNextDataPacket: go to the next data packet, and update bitstream
182  * context
183  *****************************************************************************/
184 static inline void _BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
185 {
186     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
187     vlc_bool_t          b_new_pes;
188
189     b_new_pes = _NextDataPacket( p_fifo, &p_bit_stream->p_data );
190
191     /* We've found a data packet which contains interesting data... */
192     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
193     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
194
195     /* Call back the decoder. */
196     if( p_bit_stream->pf_bitstream_callback != NULL )
197     {
198         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
199     }
200
201     /* Discontinuity management. */
202     if( p_bit_stream->p_data->b_discard_payload )
203     {
204         p_bit_stream->i_pts = p_bit_stream->i_dts = 0;
205     }
206
207     /* Retrieve the PTS. */
208     if( b_new_pes && p_fifo->p_first->i_pts )
209     {
210         p_bit_stream->i_pts = p_fifo->p_first->i_pts;
211         p_bit_stream->i_dts = p_fifo->p_first->i_dts;
212         p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
213     }
214 }
215
216 void BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
217 {
218     _BitstreamNextDataPacket( p_bit_stream );
219 }
220
221 /*****************************************************************************
222  * UnalignedShowBits : places i_bits bits into the bit buffer, even when
223  * not aligned on a word boundary
224  *****************************************************************************/
225 u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
226 {
227     /* We just fill in the bit buffer. */
228     while( p_bit_stream->fifo.i_available < i_bits )
229     {
230         if( p_bit_stream->p_byte < p_bit_stream->p_end )
231         {
232             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
233                                             << (8 * sizeof(WORD_TYPE) - 8
234                                             - p_bit_stream->fifo.i_available);
235             p_bit_stream->fifo.i_available += 8;
236         }
237         else
238         {
239             _BitstreamNextDataPacket( p_bit_stream );
240
241             if( (ptrdiff_t)p_bit_stream->p_byte & (sizeof(WORD_TYPE) - 1) )
242             {
243                 /* We are not aligned anymore. */
244                 if( ((ptrdiff_t)p_bit_stream->p_byte
245                                     & (sizeof(WORD_TYPE) - 1)) * 8
246                         < p_bit_stream->fifo.i_available )
247                 {
248                     /* We are not aligned, and won't be. Copy the first word
249                      * of the packet in a temporary buffer, and we'll see
250                      * later. */
251                     int     i;
252
253                     /* sizeof(WORD_TYPE) - number of bytes to trash
254                      * from the last payload */
255                     int     j;
256
257                     p_bit_stream->i_showbits_buffer = 0;
258
259                     for( j = i = 0 ; i < sizeof(WORD_TYPE) ; i++ )
260                     {
261                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
262                         {
263                             j = i;
264                             _BitstreamNextDataPacket( p_bit_stream );
265                         }
266                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
267                             * p_bit_stream->p_byte;
268                         p_bit_stream->p_byte++;
269                     }
270
271                     /* This is kind of kludgy. */
272                     p_bit_stream->p_data->p_payload_start +=
273                                                          sizeof(WORD_TYPE) - j;
274                     p_bit_stream->p_byte =
275                         (byte_t *)&p_bit_stream->i_showbits_buffer;
276                     p_bit_stream->p_end =
277                         (byte_t *)&p_bit_stream->i_showbits_buffer
278                             + sizeof(WORD_TYPE);
279                     p_bit_stream->showbits_data.p_next = p_bit_stream->p_data;
280                     p_bit_stream->p_data = &p_bit_stream->showbits_data;
281                 }
282                 else
283                 {
284                     /* We are not aligned, but we can be. */
285                     AlignWord( p_bit_stream );
286                 }
287             }
288
289             /* We have 32 bits ready for reading, it will be enough. */
290             break;
291         }
292     }
293
294     /* It shouldn't loop :-)) */
295     return( ShowBits( p_bit_stream, i_bits ) );
296 }
297
298 /*****************************************************************************
299  * UnalignedGetBits : returns i_bits bits from the bit stream and removes
300  * them from the buffer, even when the bit stream is not aligned on a word
301  * boundary
302  *****************************************************************************/
303 u32 UnalignedGetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
304 {
305     u32         i_result;
306
307     i_result = p_bit_stream->fifo.buffer
308                     >> (8 * sizeof(WORD_TYPE) - i_bits);
309     i_bits = -p_bit_stream->fifo.i_available;
310
311     /* Gather missing bytes. */
312     while( i_bits >= 8 )
313     {
314         if( p_bit_stream->p_byte < p_bit_stream->p_end )
315         {
316             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
317             i_bits -= 8;
318         }
319         else
320         {
321             _BitstreamNextDataPacket( p_bit_stream );
322             i_result |= *(p_bit_stream->p_byte++) << (i_bits - 8);
323             i_bits -= 8;
324         }
325     }
326
327     /* Gather missing bits. */
328     if( i_bits > 0 )
329     {
330         unsigned int    i_tmp = 8 - i_bits;
331
332         if( p_bit_stream->p_byte < p_bit_stream->p_end )
333         {
334             i_result |= *p_bit_stream->p_byte >> i_tmp;
335             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
336                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
337             p_bit_stream->fifo.i_available = i_tmp;
338         }
339         else
340         {
341             _BitstreamNextDataPacket( p_bit_stream );
342             i_result |= *p_bit_stream->p_byte >> i_tmp;
343             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
344                  << ( sizeof(WORD_TYPE) * 8 - i_tmp );
345             p_bit_stream->fifo.i_available = i_tmp;
346         }
347     }
348     else
349     {
350         p_bit_stream->fifo.i_available = 0;
351         p_bit_stream->fifo.buffer = 0;
352     }
353
354     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
355     {
356         /* Get aligned on a word boundary. Otherwise it is safer
357          * to do it the next time.
358          * NB : we _will_ get aligned, because we have at most
359          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
360          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
361         AlignWord( p_bit_stream );
362     }
363
364     return( i_result );
365 }
366
367 /*****************************************************************************
368  * UnalignedRemoveBits : removes i_bits (== -i_available) from the bit
369  * buffer, even when the bit stream is not aligned on a word boundary
370  *****************************************************************************/
371 void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
372 {
373     /* First remove all unnecessary bytes. */
374     while( p_bit_stream->fifo.i_available <= -8 )
375     {
376         if( p_bit_stream->p_byte < p_bit_stream->p_end )
377         {
378             p_bit_stream->p_byte++;
379             p_bit_stream->fifo.i_available += 8;
380         }
381         else
382         {
383             _BitstreamNextDataPacket( p_bit_stream );
384             p_bit_stream->p_byte++;
385             p_bit_stream->fifo.i_available += 8;
386         }
387     }
388
389     /* Remove unnecessary bits. */
390     if( p_bit_stream->fifo.i_available < 0 )
391     {
392         if( p_bit_stream->p_byte < p_bit_stream->p_end )
393         {
394             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
395                  << ( sizeof(WORD_TYPE) * 8 - 8
396                          - p_bit_stream->fifo.i_available );
397             p_bit_stream->fifo.i_available += 8;
398         }
399         else
400         {
401             _BitstreamNextDataPacket( p_bit_stream );
402             p_bit_stream->fifo.buffer = *(p_bit_stream->p_byte++)
403                  << ( sizeof(WORD_TYPE) * 8 - 8
404                          - p_bit_stream->fifo.i_available );
405             p_bit_stream->fifo.i_available += 8;
406         }
407     }
408     else
409     {
410         p_bit_stream->fifo.buffer = 0;
411     }
412
413     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
414     {
415         /* Get aligned on a word boundary. Otherwise it is safer
416          * to do it the next time.
417          * NB : we _will_ get aligned, because we have at most 
418          * sizeof(WORD_TYPE) - 1 bytes to store, and at least
419          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
420         AlignWord( p_bit_stream );
421     }
422 }
423
424 /*****************************************************************************
425  * CurrentPTS: returns the current PTS and DTS
426  *****************************************************************************/
427 void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
428                  mtime_t * pi_dts )
429 {
430     /* Check if the current PTS is already valid (ie. if the first byte
431      * of the packet has already been used in the decoder). */
432     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte;
433     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
434          || (p_diff * 8) >= p_bit_stream->fifo.i_available
435             /* We have buffered less bytes than actually read */ )
436     {
437         *pi_pts = p_bit_stream->i_pts;
438         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
439         p_bit_stream->i_pts = 0;
440         p_bit_stream->i_dts = 0;
441     }
442     else
443     {
444         *pi_pts = 0;
445         if( pi_dts != NULL) *pi_dts = 0;
446     }
447 }
448
449 /*****************************************************************************
450  * NextPTS: returns the PTS and DTS for the next starting byte
451  *****************************************************************************/
452 void NextPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
453               mtime_t * pi_dts )
454 {
455     /* Check if the current PTS is already valid (ie. if the first byte
456      * of the packet has already been used in the decoder). */
457     ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte - 1;
458     if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
459          || (p_diff * 8) >= p_bit_stream->fifo.i_available
460             /* We have buffered less bytes than actually read */ )
461     {
462         *pi_pts = p_bit_stream->i_pts;
463         if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
464         p_bit_stream->i_pts = 0;
465         p_bit_stream->i_dts = 0;
466     }
467     else
468     {
469         *pi_pts = 0;
470         if( pi_dts != NULL) *pi_dts = 0;
471     }
472 }
473
474 /****************************************************************************
475  * input_NextPES : extract a PES from the fifo. If pp_pes is NULL then this 
476  * PES is deleted, else pp_pes will be set to this PES
477  ****************************************************************************/
478 int input_NextPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
479 {
480     pes_packet_t *p_pes, *p_next;
481
482     vlc_mutex_lock( &p_fifo->data_lock );
483
484     /* if fifo is emty wait */
485     while( !p_fifo->p_first )
486     {
487         if( p_fifo->b_die )
488         {
489             vlc_mutex_unlock( &p_fifo->data_lock );
490             if( pp_pes )
491             {
492                 *pp_pes = NULL;
493             }
494             return( -1 );
495         }
496         vlc_cond_signal( &p_fifo->data_wait );
497         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
498     }
499     p_pes = p_fifo->p_first;
500
501     p_next = p_pes->p_next;
502     p_pes->p_next = NULL;
503
504
505     p_fifo->p_first = p_next;
506     p_fifo->i_depth--;
507
508     if( !p_fifo->p_first )
509     {
510         /* No PES in the fifo */
511         /* pp_last no longer valid */
512         p_fifo->pp_last = &p_fifo->p_first;
513     }
514     vlc_mutex_unlock( &p_fifo->data_lock );
515
516     if( pp_pes )
517     {
518         *pp_pes = p_pes;
519     }
520     else
521     {
522         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
523     }
524     return( 0 );
525 }
526