mpeg_system.c 53.1 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * mpeg_system.c: TS, PS and PES management
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
5
 * $Id: mpeg_system.c,v 1.49 2001/04/12 03:26:53 stef Exp $
6
 *
7
8
9
10
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
 *          Michel Lespinasse <walken@via.ecp.fr>
 *          Benot Steiner <benny@via.ecp.fr>
 *          Samuel Hocevar <sam@via.ecp.fr>
Henri Fallon's avatar
   
Henri Fallon committed
11
 *          Henri Fallon <henri@via.ecp.fr>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "defs.h"

#include <stdlib.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
34
#include <string.h>                                    /* memcpy(), memset() */
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"

#include "intf_msg.h"

#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"

#include "input.h"
#include "mpeg_system.h"

50
51
#include "main.h"                           /* AC3/MPEG channel, SPU channel */

52
53
54
55
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/

Henri Fallon's avatar
   
Henri Fallon committed
56
57
static void input_DecodePAT( input_thread_t *, es_descriptor_t *);
static void input_DecodePMT( input_thread_t *, es_descriptor_t *);
58
59
60
61
62

/*
 * PES Packet management
 */

63
64
65
66
67
/*****************************************************************************
 * MoveChunk
 *****************************************************************************
 * Small utility function used to parse discontinuous headers safely. Copies
 * i_buf_len bytes of data to a buffer and returns the size copied.
68
 * It also solves some alignment problems on non-IA-32, non-PPC processors.
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 * This is a variation on the theme of input_ext-dec.h:GetChunk().
 *****************************************************************************/
static __inline__ size_t MoveChunk( byte_t * p_dest,
                                    data_packet_t ** pp_data_src,
                                    byte_t ** pp_src,
                                    size_t i_buf_len )
{
    ptrdiff_t           i_available;

    if( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
            >= i_buf_len )
    {
        if( p_dest != NULL )
            memcpy( p_dest, *pp_src, i_buf_len );
        *pp_src += i_buf_len;
        return( i_buf_len );
    }
    else
    {
        size_t          i_init_len = i_buf_len;

        do
        {
            if( p_dest != NULL )
                memcpy( p_dest, *pp_src, i_available );
            *pp_data_src = (*pp_data_src)->p_next;
            i_buf_len -= i_available;
            p_dest += i_available;
            if( *pp_data_src == NULL )
            {
                *pp_src = NULL;
                return( i_init_len - i_buf_len );
            }
            *pp_src = (*pp_data_src)->p_payload_start;
        }
        while( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
                <= i_buf_len );

        if( i_buf_len )
        {
            if( p_dest != NULL )
                memcpy( p_dest, *pp_src, i_buf_len );
            *pp_src += i_buf_len;
        }
        return( i_init_len );
    }
}

117
118
119
120
121
/*****************************************************************************
 * input_ParsePES
 *****************************************************************************
 * Parse a finished PES packet and analyze its header.
 *****************************************************************************/
122
#define PES_HEADER_SIZE     7
123
124
void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
{
125
126
    data_packet_t * p_data;
    byte_t *        p_byte;
127
    byte_t          p_header[PES_HEADER_SIZE];
128
    int             i_done;
129
130
131

#define p_pes (p_es->p_pes)

Sam Hocevar's avatar
   
Sam Hocevar committed
132
    //intf_DbgMsg("End of PES packet %p", p_pes);
133
134
135
136

    /* Parse the header. The header has a variable length, but in order
     * to improve the algorithm, we will read the 14 bytes we may be
     * interested in */
137
138
    p_data = p_pes->p_first;
    p_byte = p_data->p_payload_start;
139
140
    i_done = 0;

141
142
    if( MoveChunk( p_header, &p_data, &p_byte, PES_HEADER_SIZE )
            != PES_HEADER_SIZE )
143
144
    {
        intf_WarnMsg( 3, "PES packet too short to have a header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
145
        p_input->pf_delete_pes( p_input->p_method_data, p_pes );
146
147
148
149
150
151
152
153
154
155
156
157
158
        p_pes = NULL;
        return;
    }

    /* Get the PES size if defined */
    p_es->i_pes_real_size = U16_AT(p_header + 4) + 6;

    /* First read the 6 header bytes common to all PES packets:
     * use them to test the PES validity */
    if( (p_header[0] || p_header[1] || (p_header[2] != 1)) )
    {
        /* packet_start_code_prefix != 0x000001 */
        intf_ErrMsg( "PES packet doesn't start with 0x000001 : data loss" );
Sam Hocevar's avatar
   
Sam Hocevar committed
159
        p_input->pf_delete_pes( p_input->p_method_data, p_pes );
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
        p_pes = NULL;
    }
    else
    {
        int i_pes_header_size, i_payload_size;

        if ( p_es->i_pes_real_size &&
             (p_es->i_pes_real_size != p_pes->i_pes_size) )
        {
            /* PES_packet_length is set and != total received payload */
            /* Warn the decoder that the data may be corrupt. */
            intf_WarnMsg( 3, "PES sizes do not match : packet corrupted" );
        }

        switch( p_es->i_stream_id )
        {
        case 0xBC:  /* Program stream map */
        case 0xBE:  /* Padding */
        case 0xBF:  /* Private stream 2 */
        case 0xB0:  /* ECM */
        case 0xB1:  /* EMM */
        case 0xFF:  /* Program stream directory */
        case 0xF2:  /* DSMCC stream */
        case 0xF8:  /* ITU-T H.222.1 type E stream */
            /* The payload begins immediately after the 6 bytes header, so
             * we have finished with the parsing */
            i_pes_header_size = 6;
            break;

        default:
190
191
192
            if( (p_header[6] & 0xC0) == 0x80 )
            {
                /* MPEG-2 : the PES header contains at least 3 more bytes. */
193
                size_t      i_max_len;
194
195
                boolean_t   b_has_pts, b_has_dts;
                byte_t      p_full_header[12];
196

197
198
                p_pes->b_data_alignment = p_header[6] & 0x04;

199
                i_max_len = MoveChunk( p_full_header, &p_data, &p_byte, 12 );
200
201
202
203
                if( i_max_len < 2 )
                {
                    intf_WarnMsg( 3,
                            "PES packet too short to have a MPEG-2 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
204
205
                    p_input->pf_delete_pes( p_input->p_method_data,
                                            p_pes );
206
207
208
209
                    p_pes = NULL;
                    return;
                }

210
211
212
                b_has_pts = p_full_header[0] & 0x80;
                b_has_dts = p_full_header[0] & 0x40;
                i_pes_header_size = p_full_header[1] + 9;
213
214

                /* Now parse the optional header extensions */
215
                if( b_has_pts )
216
                {
217
218
219
220
                    if( i_max_len < 7 )
                    {
                        intf_WarnMsg( 3,
                            "PES packet too short to have a MPEG-2 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
221
222
                        p_input->pf_delete_pes( p_input->p_method_data,
                                                p_pes );
223
224
225
                        p_pes = NULL;
                        return;
                    }
226
                    p_pes->i_pts = input_ClockGetTS( p_input, p_es->p_pgrm,
227
                    ( ((mtime_t)(p_full_header[2] & 0x0E) << 29) |
228
229
                      ((mtime_t)(p_full_header[3]) << 22) |
                      ((mtime_t)(p_full_header[4] & 0xFE) << 14) |
230
231
                      ((mtime_t)p_full_header[5] << 7) |
                      ((mtime_t)p_full_header[6] >> 1) ) );
232
233
234
235
236
237
238

                    if( b_has_dts )
                    {
                        if( i_max_len < 12 )
                        {
                            intf_WarnMsg( 3,
                              "PES packet too short to have a MPEG-2 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
239
240
                            p_input->pf_delete_pes( p_input->p_method_data,
                                                    p_pes );
241
242
243
                            p_pes = NULL;
                            return;
                        }
244
                        p_pes->i_dts = input_ClockGetTS( p_input, p_es->p_pgrm,
245
                        ( ((mtime_t)(p_full_header[7] & 0x0E) << 29) |
246
                          (((mtime_t)U16_AT(p_full_header + 8) << 14)
247
                                - (1 << 14)) |
248
                          ((mtime_t)U16_AT(p_full_header + 10) >> 1) ) );
249
                    }
250
251
252
253
254
                }
            }
            else
            {
                /* Probably MPEG-1 */
255
256
                boolean_t       b_has_pts, b_has_dts;

257
258
                i_pes_header_size = 6;
                p_data = p_pes->p_first;
259
260
261
262
                p_byte = p_data->p_payload_start;
                /* Cannot fail because the previous one succeeded. */
                MoveChunk( NULL, &p_data, &p_byte, 6 );

263
                while( *p_byte == 0xFF && i_pes_header_size < 23 )
264
265
                {
                    i_pes_header_size++;
266
                    if( MoveChunk( NULL, &p_data, &p_byte, 1 ) != 1 )
267
                    {
268
269
                        intf_WarnMsg( 3,
                            "PES packet too short to have a MPEG-1 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
270
                        p_input->pf_delete_pes( p_input->p_method_data, p_pes );
271
272
                        p_pes = NULL;
                        return;
273
274
                    }
                }
275
                if( i_pes_header_size == 23 )
276
277
                {
                    intf_ErrMsg( "Too much MPEG-1 stuffing" );
Sam Hocevar's avatar
   
Sam Hocevar committed
278
                    p_input->pf_delete_pes( p_input->p_method_data, p_pes );
279
280
281
282
283
284
285
                    p_pes = NULL;
                    return;
                }

                if( (*p_byte & 0xC0) == 0x40 )
                {
                    /* Don't ask why... --Meuuh */
Sam Hocevar's avatar
   
Sam Hocevar committed
286
                    /* Erm... why ? --Sam */
287
288
                    /* Well... According to the recommendation, it is for
                     * STD_buffer_scale and STD_buffer_size. --Meuuh */
289
                    i_pes_header_size += 2;
290
                    if( MoveChunk( NULL, &p_data, &p_byte, 2 ) != 2 )
291
                    {
292
293
                        intf_WarnMsg( 3,
                            "PES packet too short to have a MPEG-1 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
294
                        p_input->pf_delete_pes( p_input->p_method_data, p_pes );
295
296
                        p_pes = NULL;
                        return;
297
298
299
300
301
                    }
                }

                i_pes_header_size++;

302
303
304
305
                b_has_pts = *p_byte & 0x20;
                b_has_dts = *p_byte & 0x10;

                if( b_has_pts )
306
                {
307
                    byte_t      p_ts[5];
308
309

                    i_pes_header_size += 4;
310
                    if( MoveChunk( p_ts, &p_data, &p_byte, 5 ) != 5 )
311
                    {
312
313
                        intf_WarnMsg( 3,
                            "PES packet too short to have a MPEG-1 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
314
                        p_input->pf_delete_pes( p_input->p_method_data, p_pes );
315
316
                        p_pes = NULL;
                        return;
317
                    }
318

319
                    p_pes->i_pts = input_ClockGetTS( p_input, p_es->p_pgrm,
320
321
322
323
                       ( ((mtime_t)(p_ts[0] & 0x0E) << 29) |
                         (((mtime_t)U32_AT(p_ts) & 0xFFFE00) << 6) |
                         ((mtime_t)p_ts[3] << 7) |
                         ((mtime_t)p_ts[4] >> 1) ) );
324
325
326
327
328
329
330
331

                    if( b_has_dts )
                    {
                        i_pes_header_size += 5;
                        if( MoveChunk( p_ts, &p_data, &p_byte, 5 ) != 5 )
                        {
                            intf_WarnMsg( 3,
                              "PES packet too short to have a MPEG-1 header" );
Sam Hocevar's avatar
   
Sam Hocevar committed
332
333
                            p_input->pf_delete_pes( p_input->p_method_data,
                                                    p_pes );
334
335
336
337
                            p_pes = NULL;
                            return;
                        }

338
339
                        p_pes->i_dts = input_ClockGetTS( p_input,
                                                         p_es->p_pgrm,
340
                            ( ((mtime_t)(p_ts[0] & 0x0E) << 29) |
341
342
343
                              (((mtime_t)U32_AT(p_ts) & 0xFFFE00) << 6) |
                              ((mtime_t)p_ts[3] << 7) |
                              ((mtime_t)p_ts[4] >> 1) ) );
344
                    }
345
346
347
                }
            }

348
349
350
            break;
        }

Sam Hocevar's avatar
   
Sam Hocevar committed
351
        if( p_es->i_stream_id == 0xbd )
352
353
354
355
356
357
        {
            /* With private stream 1, the first byte of the payload
             * is a stream_private_id, so skip it. */
            i_pes_header_size++;
        }

358
359
360
361
        /* Now we've parsed the header, we just have to indicate in some
         * specific data packets where the PES payload begins (renumber
         * p_payload_start), so that the decoders can find the beginning
         * of their data right out of the box. */
362
363
364
        p_data = p_pes->p_first;
        i_payload_size = p_data->p_payload_end
                                 - p_data->p_payload_start;
365
366
367
368
        while( i_pes_header_size > i_payload_size )
        {
            /* These packets are entirely filled by the PES header. */
            i_pes_header_size -= i_payload_size;
369
            p_data->p_payload_start = p_data->p_payload_end;
370
            /* Go to the next data packet. */
371
            if( (p_data = p_data->p_next) == NULL )
372
373
            {
                intf_ErrMsg( "PES header bigger than payload" );
Sam Hocevar's avatar
   
Sam Hocevar committed
374
                p_input->pf_delete_pes( p_input->p_method_data, p_pes );
375
376
377
                p_pes = NULL;
                return;
            }
378
379
            i_payload_size = p_data->p_payload_end
                                 - p_data->p_payload_start;
380
381
382
383
384
        }
        /* This last packet is partly header, partly payload. */
        if( i_payload_size < i_pes_header_size )
        {
            intf_ErrMsg( "PES header bigger than payload" );
Sam Hocevar's avatar
   
Sam Hocevar committed
385
            p_input->pf_delete_pes( p_input->p_method_data, p_pes );
386
387
388
            p_pes = NULL;
            return;
        }
389
        p_data->p_payload_start += i_pes_header_size;
390
391
392

        /* Now we can eventually put the PES packet in the decoder's
         * PES fifo */
393
394
395
396
397
398
399
400
        if( p_es->p_decoder_fifo != NULL )
        {
            input_DecodePES( p_es->p_decoder_fifo, p_pes );
        }
        else
        {
            intf_ErrMsg("No fifo to receive PES %p (who wrote this damn code ?)",
                        p_pes);
Sam Hocevar's avatar
   
Sam Hocevar committed
401
            p_input->pf_delete_pes( p_input->p_method_data, p_pes );
402
403
        }
        p_pes = NULL;
404
405
    }
#undef p_pes
406

407
408
409
410
411
412
413
}

/*****************************************************************************
 * input_GatherPES:
 *****************************************************************************
 * Gather a PES packet.
 *****************************************************************************/
414
void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data,
415
416
417
418
419
                      es_descriptor_t * p_es,
                      boolean_t b_unit_start, boolean_t b_packet_lost )
{
#define p_pes (p_es->p_pes)

Sam Hocevar's avatar
   
Sam Hocevar committed
420
    //intf_DbgMsg("PES-demultiplexing %p (%p)", p_ts_packet, p_pes);
421

Sam Hocevar's avatar
   
Sam Hocevar committed
422
    /* If we lost data, insert a NULL data packet (philosophy : 0 is quite
423
424
     * often an escape sequence in decoders, so that should make them wait
     * for the next start code). */
425
    if( b_packet_lost )
426
    {
427
        input_NullPacket( p_input, p_es );
428
429
430
431
    }

    if( b_unit_start && p_pes != NULL )
    {
432
        /* If the data packet contains the begining of a new PES packet, and
433
434
435
436
437
438
439
440
         * if we were reassembling a PES packet, then the PES should be
         * complete now, so parse its header and give it to the decoders. */
        input_ParsePES( p_input, p_es );
    }

    if( !b_unit_start && p_pes == NULL )
    {
        /* Random access... */
Sam Hocevar's avatar
   
Sam Hocevar committed
441
        p_input->pf_delete_packet( p_input->p_method_data, p_data );
442
443
444
445
446
447
448
449
450
451
    }
    else
    {
        if( b_unit_start )
        {
            /* If we are at the beginning of a new PES packet, we must fetch
             * a new PES buffer to begin with the reassembly of this PES
             * packet. This is also here that we can synchronize with the
             * stream if we lost packets or if the decoder has just
             * started. */
Sam Hocevar's avatar
   
Sam Hocevar committed
452
            if( (p_pes = p_input->pf_new_pes( p_input->p_method_data ) ) == NULL )
453
454
455
456
457
            {
                intf_ErrMsg("Out of memory");
                p_input->b_error = 1;
                return;
            }
458
            p_pes->i_rate = p_input->stream.control.i_rate;
459
            p_pes->p_first = p_data;
Henri Fallon's avatar
   
Henri Fallon committed
460
            
461
462
463
464
465
466
467
            /* If the PES header fits in the first data packet, we can
             * already set p_gather->i_pes_real_size. */
            if( p_data->p_payload_end - p_data->p_payload_start
                    >= PES_HEADER_SIZE )
            {
                p_es->i_pes_real_size =
                                U16_AT(p_data->p_payload_start + 4) + 6;
Henri Fallon's avatar
   
Henri Fallon committed
468
                
469
470
            }
            else
Henri Fallon's avatar
   
Henri Fallon committed
471
            { 
472
                p_es->i_pes_real_size = 0;
Henri Fallon's avatar
   
Henri Fallon committed
473
            } 
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
        }
        else
        {
            /* Update the relations between the data packets */
            p_es->p_last->p_next = p_data;
        }

        p_es->p_last = p_data;

        /* Size of the payload carried in the data packet */
        p_pes->i_pes_size += (p_data->p_payload_end
                                 - p_data->p_payload_start);
    
        /* We can check if the packet is finished */
        if( p_pes->i_pes_size == p_es->i_pes_real_size )
        {
            /* The packet is finished, parse it */
            input_ParsePES( p_input, p_es );
        }
    }
#undef p_pes
}


/*
 * PS Demultiplexing
 */

502
503
504
505
506
507
508
/*****************************************************************************
 * GetID: Get the ID of a stream
 *****************************************************************************/
static u16 GetID( data_packet_t * p_data )
{
    u16         i_id;

509
    i_id = p_data->p_payload_start[3];                                 /* stream_id */
510
511
    if( i_id == 0xBD )
    {
512
513
        /* FIXME : this is not valid if the header is split in multiple
         * packets */
514
        /* stream_private_id */
515
        i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8;
516
517
518
519
    }
    return( i_id );
}

520
521
/*****************************************************************************
 * DecodePSM: Decode the Program Stream Map information
522
523
 *****************************************************************************
 * FIXME : loads are not aligned in this function
524
525
526
527
528
 *****************************************************************************/
static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
{
    stream_ps_data_t *  p_demux =
                 (stream_ps_data_t *)p_input->stream.p_demux_data;
529
530
531
532
    byte_t *            p_byte;
    byte_t *            p_end;
    int                 i;
    int                 i_new_es_number = 0;
533

534
    if( p_data->p_payload_start + 10 > p_data->p_payload_end )
535
    {
536
537
538
        intf_ErrMsg( "PSM too short : packet corrupt" );
        return;
    }
539

540
    if( p_demux->b_has_PSM
541
        && p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) )
542
543
544
545
    {
        /* Already got that one. */
        return;
    }
546

547
    intf_DbgMsg( "Building PSM" );
548
    p_demux->b_has_PSM = 1;
549
    p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F;
550
551
552
553
554
555
556
557
558
559
560
561

    /* Go to elementary_stream_map_length, jumping over
     * program_stream_info. */
    p_byte = p_data->p_payload_start + 10
              + U16_AT(&p_data->p_payload_start[8]);
    if( p_byte > p_data->p_payload_end )
    {
        intf_ErrMsg( "PSM too short : packet corrupt" );
        return;
    }
    /* This is the full size of the elementary_stream_map.
     * 2 == elementary_stream_map_length
562
563
     * Please note that CRC_32 is not included in the length. */
    p_end = p_byte + 2 + U16_AT(p_byte);
564
565
566
567
568
569
    p_byte += 2;
    if( p_end > p_data->p_payload_end )
    {
        intf_ErrMsg( "PSM too short : packet corrupt" );
        return;
    }
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
    vlc_mutex_lock( &p_input->stream.stream_lock );

    /* 4 == minimum useful size of a section */
    while( p_byte + 4 <= p_end )
    {
        es_descriptor_t *   p_es = NULL;
        u8                  i_stream_id = p_byte[1];
        /* FIXME: there will be a problem with private streams... (same
         * stream_id) */

        /* Look for the ES in the ES table */
        for( i = i_new_es_number;
             i < p_input->stream.pp_programs[0]->i_es_number;
             i++ )
585
        {
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
            if( p_input->stream.pp_programs[0]->pp_es[i]->i_stream_id
                    == i_stream_id )
            {
                p_es = p_input->stream.pp_programs[0]->pp_es[i];
                if( p_es->i_type != p_byte[0] )
                {
                    input_DelES( p_input, p_es );
                    p_es = NULL;
                }
                else
                {
                    /* Move the ES to the beginning. */
                    p_input->stream.pp_programs[0]->pp_es[i]
                        = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];
                    p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ]
                        = p_es;
602
                    i_new_es_number++;
603
604
605
606
                }
                break;
            }
        }
607

608
609
610
611
612
        /* The goal is to have all the ES we have just read in the
         * beginning of the pp_es table, and all the others at the end,
         * so that we can close them more easily at the end. */
        if( p_es == NULL )
        {
613
            p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
614
                                i_stream_id, 0 );
615
            p_es->i_type = p_byte[0];
616
617
618
619
620
            p_es->b_audio = ( p_es->i_type == MPEG1_AUDIO_ES
                              || p_es->i_type == MPEG2_AUDIO_ES
                              || p_es->i_type == AC3_AUDIO_ES
                              || p_es->i_type == LPCM_AUDIO_ES
                            );
621

622
623
624
625
626
            /* input_AddES has inserted the new element at the end. */
            p_input->stream.pp_programs[0]->pp_es[
                p_input->stream.pp_programs[0]->i_es_number ]
                = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];
            p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ] = p_es;
627
            i_new_es_number++;
628
629
        }
        p_byte += 4 + U16_AT(&p_byte[2]);
630
    }
631
632
633
634
635

    /* Un-select the streams that are no longer parts of the program. */
    for( i = i_new_es_number;
         i < p_input->stream.pp_programs[0]->i_es_number;
         i++ )
636
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
637
638
        /* We remove pp_es[i_new_es_member] and not pp_es[i] because the
         * list will be emptied starting from the end */
639
640
        input_DelES( p_input,
                     p_input->stream.pp_programs[0]->pp_es[i_new_es_number] );
641
    }
642
643
644
645
646
647

#ifdef STATS
    intf_Msg( "input info: The stream map after the PSM is now :" );
    input_DumpStream( p_input );
#endif

648
    vlc_mutex_unlock( &p_input->stream.stream_lock );
649
650
}

651
652
653
654
655
656
657
658
659
/*****************************************************************************
 * input_ParsePS: read the PS header
 *****************************************************************************/
es_descriptor_t * input_ParsePS( input_thread_t * p_input,
                                 data_packet_t * p_data )
{
    u32                 i_code;
    es_descriptor_t *   p_es = NULL;

660
    i_code = p_data->p_payload_start[3];
Cyril Deguet's avatar
   
Cyril Deguet committed
661

662
    if( i_code > 0xBC ) /* ES start code */
663
664
665
666
667
668
669
670
671
672
673
    {
        u16                 i_id;
        int                 i_dummy;

        /* This is a PES packet. Find out if we want it or not. */
        i_id = GetID( p_data );

        vlc_mutex_lock( &p_input->stream.stream_lock );
        if( p_input->stream.pp_programs[0]->b_is_ok )
        {
            /* Look only at the selected ES. */
674
            for( i_dummy = 0; i_dummy < p_input->stream.i_selected_es_number;
675
                 i_dummy++ )
676
            {
677
678
                if( p_input->stream.pp_selected_es[i_dummy] != NULL
                    && p_input->stream.pp_selected_es[i_dummy]->i_id == i_id )
679
                {
680
                    p_es = p_input->stream.pp_selected_es[i_dummy];
681
682
683
684
685
686
                    break;
                }
            }
        }
        else
        {
687
688
689
            stream_ps_data_t * p_demux =
              (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;

690
            /* Search all ES ; if not found -> AddES */
691
            p_es = input_FindES( p_input, i_id );
692

693
            if( p_es == NULL && !p_demux->b_has_PSM )
694
695
696
697
698
            {
                p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
                                    i_id, 0 );
                if( p_es != NULL )
                {
699
                    p_es->i_stream_id = p_data->p_payload_start[3];
700
701
702
703
704
705

                    /* Set stream type and auto-spawn. */
                    if( (i_id & 0xF0) == 0xE0 )
                    {
                        /* MPEG video */
                        p_es->i_type = MPEG2_VIDEO_ES;
Stéphane Borel's avatar
Stéphane Borel committed
706
                        p_es->i_cat = VIDEO_ES;
707
#ifdef AUTO_SPAWN
708
709
                        if( !p_input->stream.b_seekable )
                            input_SelectES( p_input, p_es );
710
711
712
713
714
715
#endif
                    }
                    else if( (i_id & 0xE0) == 0xC0 )
                    {
                        /* MPEG audio */
                        p_es->i_type = MPEG2_AUDIO_ES;
716
                        p_es->b_audio = 1;
Stéphane Borel's avatar
Stéphane Borel committed
717
                        p_es->i_cat = AUDIO_ES;
718
#ifdef AUTO_SPAWN
719
                        if( !p_input->stream.b_seekable )
Sam Hocevar's avatar
   
Sam Hocevar committed
720
                        if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
721
                                == (p_es->i_id & 0x1F) )
Sam Hocevar's avatar
   
Sam Hocevar committed
722
                        switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
723
                        {
724
                        case 0:
Sam Hocevar's avatar
   
Sam Hocevar committed
725
                            main_PutIntVariable( INPUT_CHANNEL_VAR,
726
727
728
                                                 REQUESTED_MPEG );
                        case REQUESTED_MPEG:
                            input_SelectES( p_input, p_es );
729
                        }
730
731
732
733
#endif
                    }
                    else if( (i_id & 0xF0FF) == 0x80BD )
                    {
734
                        /* AC3 audio (0x80->0x8F) */
735
                        p_es->i_type = AC3_AUDIO_ES;
736
                        p_es->b_audio = 1;
Stéphane Borel's avatar
Stéphane Borel committed
737
                        p_es->i_cat = AUDIO_ES;
738
#ifdef AUTO_SPAWN
739
                        if( !p_input->stream.b_seekable )
Sam Hocevar's avatar
   
Sam Hocevar committed
740
                        if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
741
                                == ((p_es->i_id & 0xF00) >> 8) )
Sam Hocevar's avatar
   
Sam Hocevar committed
742
                        switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
743
                        {
744
                        case 0:
Sam Hocevar's avatar
   
Sam Hocevar committed
745
                            main_PutIntVariable( INPUT_CHANNEL_VAR,
746
747
748
                                                 REQUESTED_AC3 );
                        case REQUESTED_AC3:
                            input_SelectES( p_input, p_es );
749
                        }
750
751
#endif
                    }
752
                    else if( (i_id & 0xE0FF) == 0x20BD )
753
                    {
754
                        /* Subtitles video (0x20->0x3F) */
755
                        p_es->i_type = DVD_SPU_ES;
Stéphane Borel's avatar
Stéphane Borel committed
756
                        p_es->i_cat = SPU_ES;
757
#ifdef AUTO_SPAWN
Sam Hocevar's avatar
   
Sam Hocevar committed
758
                        if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
759
                                == ((p_es->i_id & 0x1F00) >> 8) )
760
                        {
761
762
                            if( !p_input->stream.b_seekable )
                                input_SelectES( p_input, p_es );
763
                        }
764
765
#endif
                    }
766
767
768
769
                    else if( (i_id & 0xF0FF) == 0xA0BD )
                    {
                        /* LPCM audio (0xA0->0xAF) */
                        p_es->i_type = LPCM_AUDIO_ES;
770
                        p_es->b_audio = 1;
Stéphane Borel's avatar
Stéphane Borel committed
771
                        p_es->i_cat = AUDIO_ES;
772
773
                        /* FIXME : write the decoder */
                    }
774
775
776
777
778
779
780
781
782
783
784
785
786
                    else
                    {
                        p_es->i_type = UNKNOWN_ES;
                    }
                }
            }
        } /* stream.b_is_ok */
        vlc_mutex_unlock( &p_input->stream.stream_lock );
    } /* i_code > 0xBC */

    return( p_es );
}

787
788
789
790
791
792
793
794
795
/*****************************************************************************
 * input_DemuxPS: first step of demultiplexing: the PS header
 *****************************************************************************/
void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
{
    u32                 i_code;
    boolean_t           b_trash = 0;
    es_descriptor_t *   p_es = NULL;

796
    i_code = U32_AT( p_data->p_payload_start );
797
    if( i_code <= 0x1BC )
798
799
800
801
802
    {
        switch( i_code )
        {
        case 0x1BA: /* PACK_START_CODE */
            {
803
                /* Read the SCR. */
804
                mtime_t         scr_time;
Christophe Massiot's avatar
Christophe Massiot committed
805
                u32             i_mux_rate;
806

807
                if( (p_data->p_payload_start[4] & 0xC0) == 0x40 )
808
809
                {
                    /* MPEG-2 */
810
811
812
813
814
815
816
817
818
819
                    byte_t      p_header[14];
                    byte_t *    p_byte;
                    p_byte = p_data->p_payload_start;

                    if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 )
                    {
                        intf_WarnMsg( 3, "Packet too short to have a header" );
                        b_trash = 1;
                        break;
                    }
820
                    scr_time =
821
822
                         ((mtime_t)(p_header[4] & 0x38) << 27) |
                         ((mtime_t)(U32_AT(p_header + 4) & 0x03FFF800)
823
                                        << 4) |
824
825
                         ((( ((mtime_t)U16_AT(p_header + 6) << 16)
                            | (mtime_t)U16_AT(p_header + 8) ) & 0x03FFF800)
826
                                        >> 11);
Christophe Massiot's avatar
Christophe Massiot committed
827
828

                    /* mux_rate */
829
830
                    i_mux_rate = ((u32)U16_AT(p_header + 10) << 6)
                                   | (p_header[12] >> 2);
831
832
833
                }
                else
                {
834
                    /* MPEG-1 SCR is like PTS. */
835
836
837
838
839
840
841
842
843
844
                    byte_t      p_header[12];
                    byte_t *    p_byte;
                    p_byte = p_data->p_payload_start;

                    if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 )
                    {
                        intf_WarnMsg( 3, "Packet too short to have a header" );
                        b_trash = 1;
                        break;
                    }
845
                    scr_time =
846
847
848
849
                         ((mtime_t)(p_header[4] & 0x0E) << 29) |
                         (((mtime_t)U32_AT(p_header + 4) & 0xFFFE00) << 6) |
                         ((mtime_t)p_header[7] << 7) |
                         ((mtime_t)p_header[8] >> 1);
Christophe Massiot's avatar
Christophe Massiot committed
850
851

                    /* mux_rate */
852
                    i_mux_rate = (U32_AT(p_header + 8) & 0x7FFFFE) >> 1;
853
                }
854
                /* Call the pace control. */
855
856
                input_ClockManageRef( p_input, p_input->stream.pp_programs[0],
                                      scr_time );
Christophe Massiot's avatar
Christophe Massiot committed
857
858
859
860
861
862
863
864
865

                if( i_mux_rate != p_input->stream.i_mux_rate
                     && p_input->stream.i_mux_rate )
                {
                    intf_WarnMsg(2,
                                 "Mux_rate changed - expect cosmetic errors");
                }
                p_input->stream.i_mux_rate = i_mux_rate;

866
                b_trash = 1;
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
            }
            break;

        case 0x1BB: /* SYSTEM_START_CODE */
            b_trash = 1;                              /* Nothing interesting */
            break;

        case 0x1BC: /* PROGRAM_STREAM_MAP_CODE */
            DecodePSM( p_input, p_data );
            b_trash = 1;
            break;
    
        case 0x1B9: /* PROGRAM_END_CODE */
            b_trash = 1;
            break;
   
        default:
            /* This should not happen */
            b_trash = 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
886
            intf_WarnMsg( 1, "Unwanted packet received with start code 0x%.8x",
887
888
889
890
891
                          i_code );
        }
    }
    else
    {
892
        p_es = input_ParsePS( p_input, p_data );
893

894
895
896
        vlc_mutex_lock( &p_input->stream.control.control_lock );
        if( p_es != NULL && p_es->p_decoder_fifo != NULL
             && (!p_es->b_audio || !p_input->stream.control.b_mute) )
897
        {
898
            vlc_mutex_unlock( &p_input->stream.control.control_lock );
899
900
901
902
903
#ifdef STATS
            p_es->c_packets++;
#endif
            input_GatherPES( p_input, p_data, p_es, 1, 0 );
        }
904
905
        else
        {
906
            vlc_mutex_unlock( &p_input->stream.control.control_lock );
907
908
            b_trash = 1;
        }
909
910
911
912
913
    }

    /* Trash the packet if it has no payload or if it isn't selected */
    if( b_trash )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
914
        p_input->pf_delete_packet( p_input->p_method_data, p_data );
915
916
917
918
919
920
#ifdef STATS
        p_input->c_packets_trashed++;
#endif
    }
}

Henri Fallon's avatar
   
Henri Fallon committed
921
 
922
923
924
925
926
927
928
929
930
/*
 * TS Demultiplexing
 */

/*****************************************************************************
 * input_DemuxTS: first step of demultiplexing: the TS header
 *****************************************************************************/
void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
{
Henri Fallon's avatar
   
Henri Fallon committed
931
932
    u16                 i_pid;
    int                 i_dummy;
933
934
935
936
937
    boolean_t           b_adaptation;         /* Adaptation field is present */
    boolean_t           b_payload;                 /* Packet carries payload */
    boolean_t           b_unit_start;  /* A PSI or a PES start in the packet */
    boolean_t           b_trash = 0;             /* Is the packet unuseful ? */
    boolean_t           b_lost = 0;             /* Was there a packet loss ? */
Henri Fallon's avatar
   
Henri Fallon committed
938
    boolean_t           b_psi = 0;                        /* Is this a PSI ? */
939
940
941
942
    es_descriptor_t *   p_es = NULL;
    es_ts_data_t *      p_es_demux = NULL;
    pgrm_ts_data_t *    p_pgrm_demux = NULL;

Henri Fallon's avatar
   
Henri Fallon committed
943
    #define p (p_data->p_buffer)
944
945
946
947
948
949
950
951
    /* Extract flags values from TS common header. */
    i_pid = U16_AT(&p[1]) & 0x1fff;
    b_unit_start = (p[1] & 0x40);
    b_adaptation = (p[3] & 0x20);
    b_payload = (p[3] & 0x10);

    /* Find out the elementary stream. */
    vlc_mutex_lock( &p_input->stream.stream_lock );
Henri Fallon's avatar
   
Henri Fallon committed
952
953
        
    p_es= input_FindES( p_input, i_pid );
Henri Fallon's avatar
   
Henri Fallon committed
954
    
Henri Fallon's avatar
   
Henri Fallon committed
955
956
957
958
959
960
    if( (p_es != NULL) && (p_es->p_demux_data != NULL) )
    {
        p_es_demux = (es_ts_data_t *)p_es->p_demux_data;
        
        if( p_es_demux->b_psi )
            b_psi = 1;
Henri Fallon's avatar
   
Henri Fallon committed
961
962
        else
            p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data; 
Henri Fallon's avatar
   
Henri Fallon committed
963
964
    }

965
    vlc_mutex_lock( &p_input->stream.control.control_lock );
Henri Fallon's avatar
   
Henri Fallon committed
966
    if( ( p_es == NULL ) || (p_es->b_audio && p_input->stream.control.b_mute) )
967
968
969
970
    {
        /* Not selected. Just read the adaptation field for a PCR. */
        b_trash = 1;
    }
Henri Fallon's avatar
   
Henri Fallon committed
971
972
973
    else if( p_es->p_decoder_fifo == NULL  && !b_psi )
      b_trash =1; 

974
975
    vlc_mutex_unlock( &p_input->stream.control.control_lock );
    vlc_mutex_unlock( &p_input->stream.stream_lock );
976

Henri Fallon's avatar
   
Henri Fallon committed
977

Henri Fallon's avatar
   
Henri Fallon committed
978
979
    /* Don't change the order of the tests : if b_psi then p_pgrm_demux 
     * may still be null. Who said it was ugly ? */
Henri Fallon's avatar
   
Henri Fallon committed
980
981
982
    if( ( p_es != NULL ) && 
        ((p_es->p_decoder_fifo != NULL) || b_psi 
                                   || (p_pgrm_demux->i_pcr_pid == i_pid) ) )
983
    {
984
985
986
987
#ifdef STATS
        p_es->c_packets++;
#endif

988
        /* Extract adaptation field information if any */
Henri Fallon's avatar
   
Henri Fallon committed
989

990
991
992
993
994
995
996
997
998
999
1000
        if( !b_adaptation )
        {
            /* We don't have any adaptation_field, so payload starts
             * immediately after the 4 byte TS header */
            p_data->p_payload_start += 4;
        }
        else
        {
            /* p[4] is adaptation_field_length minus one */
            p_data->p_payload_start += 5 + p[4];