]> git.sesse.net Git - vlc/blob - include/input_ext-dec.h
a75a224319989999e1a2053bcd967ef22ea117cf
[vlc] / include / input_ext-dec.h
1 /*****************************************************************************
2  * input_ext-dec.h: structures exported to the VideoLAN decoders
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: input_ext-dec.h,v 1.64 2002/07/23 00:39:16 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Michel Kaempf <maxx@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #ifndef _VLC_INPUT_EXT_DEC_H
26 #define _VLC_INPUT_EXT_DEC_H 1
27
28 /* ES streams types - see ISO/IEC 13818-1 table 2-29 numbers.
29  * these values are used in src/input/mpeg_system.c, and in
30  * the following plugins: mpeg_ts, mpeg_ts_dvbpsi, input_satellite. */
31 #define MPEG1_VIDEO_ES      0x01
32 #define MPEG2_VIDEO_ES      0x02
33 #define MPEG1_AUDIO_ES      0x03
34 #define MPEG2_AUDIO_ES      0x04
35 #define AC3_AUDIO_ES        0x81
36 /* These ones might violate the norm : */
37 #define DVD_SPU_ES          0x82
38 #define LPCM_AUDIO_ES       0x83
39
40 /* Structures exported to the decoders */
41
42 /*****************************************************************************
43  * data_packet_t
44  *****************************************************************************
45  * Describe a data packet.
46  *****************************************************************************/
47 struct data_packet_t
48 {
49     /* Used to chain the packets that carry data for a same PES or PSI */
50     data_packet_t *  p_next;
51
52     /* start of the PS or TS packet */
53     byte_t *         p_demux_start;
54     /* start of the PES payload in this packet */
55     byte_t *         p_payload_start;
56     byte_t *         p_payload_end; /* guess ? :-) */
57     /* is the packet messed up ? */
58     vlc_bool_t       b_discard_payload;
59
60     /* pointer to the real data */
61     data_buffer_t *  p_buffer;
62 };
63
64 /*****************************************************************************
65  * pes_packet_t
66  *****************************************************************************
67  * Describes an PES packet, with its properties, and pointers to the TS packets
68  * containing it.
69  *****************************************************************************/
70 struct pes_packet_t
71 {
72     /* Chained list to the next PES packet (depending on the context) */
73     pes_packet_t *  p_next;
74
75     /* PES properties */
76     vlc_bool_t      b_data_alignment;          /* used to find the beginning of
77                                                 * a video or audio unit */
78     vlc_bool_t      b_discontinuity;          /* This packet doesn't follow the
79                                                * previous one */
80
81     mtime_t         i_pts;            /* PTS for this packet (zero if unset) */
82     mtime_t         i_dts;            /* DTS for this packet (zero if unset) */
83     int             i_rate;   /* current reading pace (see stream_control.h) */
84
85     unsigned int    i_pes_size;            /* size of the current PES packet */
86
87     /* Chained list to packets */
88     data_packet_t * p_first;              /* The first packet contained by this
89                                            * PES (used by decoders). */
90     data_packet_t * p_last;            /* The last packet contained by this
91                                         * PES (used by the buffer allocator) */
92     unsigned int    i_nb_data; /* Number of data packets in the chained list */
93 };
94
95 /*****************************************************************************
96  * decoder_fifo_t
97  *****************************************************************************
98  * This rotative FIFO contains PES packets that are to be decoded.
99  *****************************************************************************/
100 struct decoder_fifo_t
101 {
102     VLC_COMMON_MEMBERS
103
104     /* Thread structures */
105     vlc_mutex_t         data_lock;                         /* fifo data lock */
106     vlc_cond_t          data_wait;         /* fifo data conditional variable */
107
108     /* Data */
109     pes_packet_t *      p_first;
110     pes_packet_t **     pp_last;
111     int                 i_depth;       /* number of PES packets in the stack */
112
113     /* Communication interface between input and decoders */
114     input_buffers_t    *p_packets_mgt;   /* packets management services data */
115
116     /* Standard pointers given to the decoders as a toolbox. */
117     u16                 i_id;
118     vlc_fourcc_t        i_fourcc;
119     void *              p_demux_data;
120     stream_ctrl_t *     p_stream_ctrl;
121 };
122
123 /*****************************************************************************
124  * bit_fifo_t : bit fifo descriptor
125  *****************************************************************************
126  * This type describes a bit fifo used to store bits while working with the
127  * input stream at the bit level.
128  *****************************************************************************/
129 typedef u32         WORD_TYPE;
130
131 typedef struct bit_fifo_t
132 {
133     /* This unsigned integer allows us to work at the bit level. This buffer
134      * can contain 32 bits, and the used space can be found on the MSb's side
135      * and the available space on the LSb's side. */
136     WORD_TYPE           buffer;
137
138     /* Number of bits available in the bit buffer */
139     int                 i_available;
140
141 } bit_fifo_t;
142
143 /*****************************************************************************
144  * bit_stream_t : bit stream descriptor
145  *****************************************************************************
146  * This type, based on a PES stream, includes all the structures needed to
147  * handle the input stream like a bit stream.
148  *****************************************************************************/
149 struct bit_stream_t
150 {
151     /*
152      * Bit structures
153      */
154     bit_fifo_t       fifo;
155
156     /*
157      * Input structures
158      */
159     /* The decoder fifo contains the data of the PES stream */
160     decoder_fifo_t * p_decoder_fifo;
161
162     /* Callback to the decoder used when changing data packets ; set
163      * to NULL if your decoder doesn't need it. */
164     void          (* pf_bitstream_callback)( bit_stream_t *, vlc_bool_t );
165     /* Optional argument to the callback */
166     void *           p_callback_arg;
167
168     /*
169      * PTS retrieval
170      */
171     mtime_t          i_pts, i_dts;
172     byte_t *         p_pts_validity;
173
174     /*
175      * Byte structures
176      */
177     /* Current data packet (in the current PES packet of the PES stream) */
178     data_packet_t *         p_data;
179     /* Pointer to the next byte that is to be read (in the current packet) */
180     byte_t *                p_byte;
181     /* Pointer to the last byte that is to be read (in the current packet */
182     byte_t *                p_end;
183     /* Temporary buffer in case we're not aligned when changing data packets */
184     WORD_TYPE               i_showbits_buffer;
185     data_packet_t           showbits_data;
186 };
187
188 /*****************************************************************************
189  * Inline functions used by the decoders to read bit_stream_t
190  *****************************************************************************/
191
192 /*
193  * DISCUSSION : How to use the bit_stream structures
194  *
195  * sizeof(WORD_TYPE) (usually 32) bits are read at the same time, thus
196  * minimizing the number of p_byte changes.
197  * Bits are read via GetBits() or ShowBits.
198  *
199  * XXX : Be aware that if, in the forthcoming functions, i_bits > 24,
200  * the data have to be already aligned on an 8-bit boundary, or wrong
201  * results will be returned. Use RealignBits() if unsure.
202  */
203
204 #if (WORD_TYPE == u32)
205 #   define WORD_AT      U32_AT
206 #   define WORD_SIGNED  s32
207 #elif (WORD_TYPE == u64)
208 #   define WORD_AT      U64_AT
209 #   define WORD_SIGNED  s64
210 #else
211 #   error Unsupported WORD_TYPE
212 #endif
213
214 /*****************************************************************************
215  * Prototypes from input_ext-dec.c
216  *****************************************************************************/
217 VLC_EXPORT( void, InitBitstream,  ( bit_stream_t *, decoder_fifo_t *, void ( * )( bit_stream_t *, vlc_bool_t ), void * p_callback_arg ) );
218 VLC_EXPORT( vlc_bool_t, NextDataPacket,    ( decoder_fifo_t *, data_packet_t ** ) );
219 VLC_EXPORT( void, BitstreamNextDataPacket, ( bit_stream_t * ) );
220 VLC_EXPORT( u32,  UnalignedShowBits,       ( bit_stream_t *, unsigned int ) );
221 VLC_EXPORT( void, UnalignedRemoveBits,     ( bit_stream_t * ) );
222 VLC_EXPORT( u32,  UnalignedGetBits,        ( bit_stream_t *, unsigned int ) );
223 VLC_EXPORT( void, CurrentPTS,              ( bit_stream_t *, mtime_t *, mtime_t * ) );
224
225 /*****************************************************************************
226  * AlignWord : fill in the bit buffer so that the byte pointer be aligned
227  * on a word boundary (XXX: there must be at least sizeof(WORD_TYPE) - 1
228  * empty bytes in the bit buffer)
229  *****************************************************************************/
230 static inline void AlignWord( bit_stream_t * p_bit_stream )
231 {
232     while( (ptrdiff_t)p_bit_stream->p_byte
233              & (sizeof(WORD_TYPE) - 1) )
234     {
235         if( p_bit_stream->p_byte < p_bit_stream->p_end )
236         {
237             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
238                 << (8 * sizeof(WORD_TYPE) - 8
239                      - p_bit_stream->fifo.i_available);
240             p_bit_stream->fifo.i_available += 8;
241         }
242         else
243         {
244             BitstreamNextDataPacket( p_bit_stream );
245             p_bit_stream->fifo.buffer |= *(p_bit_stream->p_byte++)
246                 << (8 * sizeof(WORD_TYPE) - 8
247                      - p_bit_stream->fifo.i_available);
248             p_bit_stream->fifo.i_available += 8;
249         }
250     }
251 }
252
253 /*****************************************************************************
254  * ShowBits : return i_bits bits from the bit stream
255  *****************************************************************************/
256 static inline u32 ShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
257 {
258     if( p_bit_stream->fifo.i_available >= i_bits )
259     {
260         return( p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits) );
261     }
262
263     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
264     {
265         return( (p_bit_stream->fifo.buffer |
266                     (WORD_AT( p_bit_stream->p_byte )
267                         >> p_bit_stream->fifo.i_available))
268                     >> (8 * sizeof(WORD_TYPE) - i_bits) );
269     }
270
271     return( UnalignedShowBits( p_bit_stream, i_bits ) );
272 }
273
274 /*****************************************************************************
275  * ShowSignedBits : return i_bits bits from the bit stream, using signed
276  *                  arithmetic
277  *****************************************************************************/
278 static inline s32 ShowSignedBits( bit_stream_t * p_bit_stream,
279                                   unsigned int i_bits )
280 {
281     if( p_bit_stream->fifo.i_available >= i_bits )
282     {
283         return( (WORD_SIGNED)p_bit_stream->fifo.buffer
284                     >> (8 * sizeof(WORD_TYPE) - i_bits) );
285     }
286
287     /* You can probably do something a little faster, but now I'm tired. */
288     return( (WORD_SIGNED)(ShowBits( p_bit_stream, i_bits ) << (32 - i_bits))
289              >> (32 - i_bits) );
290 }
291
292 /*****************************************************************************
293  * RemoveBits : removes i_bits bits from the bit buffer
294  *              XXX: do not use for 32 bits, see RemoveBits32
295  *****************************************************************************/
296 static inline void RemoveBits( bit_stream_t * p_bit_stream,
297                                unsigned int i_bits )
298 {
299     p_bit_stream->fifo.i_available -= i_bits;
300
301     if( p_bit_stream->fifo.i_available >= 0 )
302     {
303         p_bit_stream->fifo.buffer <<= i_bits;
304         return;
305     }
306
307     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
308     {
309         p_bit_stream->fifo.buffer = WORD_AT( p_bit_stream->p_byte )
310                                         << ( -p_bit_stream->fifo.i_available );
311         ((WORD_TYPE *)p_bit_stream->p_byte)++;
312         p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
313         return;
314     }
315
316     UnalignedRemoveBits( p_bit_stream );
317 }
318
319 /*****************************************************************************
320  * RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
321  *                refill it)
322  *****************************************************************************/
323 #if (WORD_TYPE == u32)
324 static inline void RemoveBits32( bit_stream_t * p_bit_stream )
325 {
326     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
327     {
328         if( p_bit_stream->fifo.i_available )
329         {
330             p_bit_stream->fifo.buffer = WORD_AT( p_bit_stream->p_byte )
331                             << (32 - p_bit_stream->fifo.i_available);
332             ((WORD_TYPE *)p_bit_stream->p_byte)++;
333             return;
334         }
335
336         ((WORD_TYPE *)p_bit_stream->p_byte)++;
337         return;
338     }
339
340     p_bit_stream->fifo.i_available -= 32;
341     UnalignedRemoveBits( p_bit_stream );
342 }
343 #else
344 #   define RemoveBits32( p_bit_stream )     RemoveBits( p_bit_stream, 32 )
345 #endif
346
347 /*****************************************************************************
348  * GetBits : returns i_bits bits from the bit stream and removes them
349  *           XXX: do not use for 32 bits, see GetBits32
350  *****************************************************************************/
351 static inline u32 GetBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
352 {
353     u32             i_result;
354
355     p_bit_stream->fifo.i_available -= i_bits;
356
357     if( p_bit_stream->fifo.i_available >= 0 )
358     {
359         i_result = p_bit_stream->fifo.buffer
360                         >> (8 * sizeof(WORD_TYPE) - i_bits);
361         p_bit_stream->fifo.buffer <<= i_bits;
362         return( i_result );
363     }
364
365     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
366     {
367         i_result = p_bit_stream->fifo.buffer
368                         >> (8 * sizeof(WORD_TYPE) - i_bits);
369         p_bit_stream->fifo.buffer = WORD_AT( p_bit_stream->p_byte );
370         ((WORD_TYPE *)p_bit_stream->p_byte)++;
371         i_result |= p_bit_stream->fifo.buffer
372                         >> (8 * sizeof(WORD_TYPE)
373                                      + p_bit_stream->fifo.i_available);
374         p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
375         p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
376         return( i_result );
377     }
378
379     return UnalignedGetBits( p_bit_stream, i_bits );
380 }
381
382 /*****************************************************************************
383  * GetSignedBits : returns i_bits bits from the bit stream and removes them,
384  *                 using signed arithmetic
385  *                 XXX: do not use for 32 bits
386  *****************************************************************************/
387 static inline s32 GetSignedBits( bit_stream_t * p_bit_stream,
388                                  unsigned int i_bits )
389 {
390     if( p_bit_stream->fifo.i_available >= i_bits )
391     {
392         s32             i_result;
393
394         p_bit_stream->fifo.i_available -= i_bits;
395         i_result = (WORD_SIGNED)p_bit_stream->fifo.buffer
396                         >> (8 * sizeof(WORD_TYPE) - i_bits);
397         p_bit_stream->fifo.buffer <<= i_bits;
398         return( i_result );
399     }
400
401     /* You can probably do something a little faster, but now I'm tired. */
402     return( (WORD_SIGNED)(GetBits( p_bit_stream, i_bits ) << (32 - i_bits))
403              >> (32 - i_bits) );
404 }
405
406 /*****************************************************************************
407  * GetBits32 : returns 32 bits from the bit stream and removes them
408  *****************************************************************************/
409 #if (WORD_TYPE == u32)
410 static inline u32 GetBits32( bit_stream_t * p_bit_stream )
411 {
412     u32             i_result;
413
414     if( p_bit_stream->fifo.i_available == 32 )
415     {
416         p_bit_stream->fifo.i_available = 0;
417         i_result = p_bit_stream->fifo.buffer;
418         p_bit_stream->fifo.buffer = 0;
419         return( i_result );
420     }
421
422     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
423     {
424         if( p_bit_stream->fifo.i_available )
425         {
426             i_result = p_bit_stream->fifo.buffer;
427             p_bit_stream->fifo.buffer = WORD_AT( p_bit_stream->p_byte );
428             ((WORD_TYPE *)p_bit_stream->p_byte)++;
429             i_result |= p_bit_stream->fifo.buffer
430                              >> (p_bit_stream->fifo.i_available);
431             p_bit_stream->fifo.buffer <<= (32 - p_bit_stream->fifo.i_available);
432             return( i_result );
433         }
434
435         i_result = WORD_AT( p_bit_stream->p_byte );
436         ((WORD_TYPE *)p_bit_stream->p_byte)++;
437         return( i_result );
438     }
439
440     p_bit_stream->fifo.i_available -= 32;
441     return UnalignedGetBits( p_bit_stream, 32 );
442 }
443 #else
444 #   define GetBits32( p_bit_stream )    GetBits( p_bit_stream, 32 )
445 #endif
446
447 /*****************************************************************************
448  * RealignBits : realigns the bit buffer on an 8-bit boundary
449  *****************************************************************************/
450 static inline void RealignBits( bit_stream_t * p_bit_stream )
451 {
452     p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
453     p_bit_stream->fifo.i_available &= ~0x7;
454 }
455
456
457 /*****************************************************************************
458  * GetChunk : reads a large chunk of data
459  *****************************************************************************
460  * The position in the stream must be byte-aligned, if unsure call
461  * RealignBits(). p_buffer must point to a buffer at least as big as i_buf_len
462  * otherwise your code will crash.
463  *****************************************************************************/
464 static inline void GetChunk( bit_stream_t * p_bit_stream,
465                              byte_t * p_buffer, size_t i_buf_len )
466 {
467     ptrdiff_t           i_available;
468
469     /* We need to take care because i_buf_len may be < 4. */
470     while( p_bit_stream->fifo.i_available > 0 && i_buf_len )
471     {
472         *p_buffer = p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - 8);
473         p_buffer++;
474         i_buf_len--;
475         p_bit_stream->fifo.buffer <<= 8;
476         p_bit_stream->fifo.i_available -= 8;
477     }
478
479     if( (i_available = p_bit_stream->p_end - p_bit_stream->p_byte)
480             >= i_buf_len )
481     {
482         p_bit_stream->p_decoder_fifo->p_vlc->pf_memcpy( p_buffer,
483                                            p_bit_stream->p_byte, i_buf_len );
484         p_bit_stream->p_byte += i_buf_len;
485     }
486     else
487     {
488         do
489         {
490             p_bit_stream->p_decoder_fifo->p_vlc->pf_memcpy( p_buffer,
491                                            p_bit_stream->p_byte, i_available );
492             p_bit_stream->p_byte = p_bit_stream->p_end;
493             p_buffer += i_available;
494             i_buf_len -= i_available;
495             BitstreamNextDataPacket( p_bit_stream );
496             if( p_bit_stream->p_decoder_fifo->b_die )
497                 return;
498         }
499         while( (i_available = p_bit_stream->p_end - p_bit_stream->p_byte)
500                 <= i_buf_len );
501
502         if( i_buf_len )
503         {
504             p_bit_stream->p_decoder_fifo->p_vlc->pf_memcpy( p_buffer,
505                                            p_bit_stream->p_byte, i_buf_len );
506             p_bit_stream->p_byte += i_buf_len;
507         }
508     }
509
510     if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
511     {
512         AlignWord( p_bit_stream );
513     }
514 }
515
516
517 /*
518  * Communication interface between input and decoders
519  */
520
521 /*****************************************************************************
522  * Prototypes from input_dec.c
523  *****************************************************************************/
524 VLC_EXPORT( void, DecoderError, ( decoder_fifo_t * p_fifo ) );
525
526 #endif /* "input_ext-dec.h" */