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