OSDN Git Service

Merge the 0.8.0_mpeg4ip branch into the trunk
[handbrake-jp/handbrake-jp-git.git] / libmediafork / demuxmpeg.c
1 /* $Id: demuxmpeg.c,v 1.4 2004/10/19 23:11:36 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "mediafork.h"
8
9 /* Basic MPEG demuxer, only works with DVDs (2048 bytes packets) */
10
11 int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es )
12 {
13     hb_buffer_t * buf_es;
14     int           pos;
15
16     pos = 0;
17
18 #define d (buf_ps->data)
19
20     /* pack_header */
21     if( d[pos] != 0 || d[pos+1] != 0 ||
22         d[pos+2] != 0x1 || d[pos+3] != 0xBA )
23     {
24         hb_log( "hb_demux_ps: not a PS packet (%02x%02x%02x%02x)",
25                 d[pos], d[pos+1], d[pos+2], d[pos+3] );
26         return 0;
27     }
28     pos += 4;                    /* pack_start_code */
29     pos += 9;                    /* pack_header */
30     pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
31
32     /* system_header */
33     if( d[pos] == 0 && d[pos+1] == 0 &&
34         d[pos+2] == 0x1 && d[pos+3] == 0xBB )
35     {
36         int header_length;
37
38         pos           += 4; /* system_header_start_code */
39         header_length  = ( d[pos] << 8 ) + d[pos+1];
40         pos           += 2 + header_length;
41     }
42
43     /* pes */
44     while( pos + 6 < buf_ps->size &&
45            d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 )
46     {
47         int      id;
48         int      pes_packet_length;
49         int      pes_packet_end;
50         int      pes_header_d_length;
51         int      pes_header_end;
52         int      has_pts;
53         int64_t  pts = -1;
54
55         pos               += 3;               /* packet_start_code_prefix */
56         id           = d[pos];
57         pos               += 1;
58
59         pes_packet_length  = ( d[pos] << 8 ) + d[pos+1];
60         pos               += 2;               /* pes_packet_length */
61         pes_packet_end     = pos + pes_packet_length;
62
63         if( id != 0xE0 && id != 0xBD &&
64             ( id & 0xC0 ) != 0xC0  )
65         {
66             /* Not interesting */
67             pos = pes_packet_end;
68             continue;
69         }
70
71         has_pts             = ( ( d[pos+1] >> 6 ) & 0x2 ) ? 1 : 0;
72         pos               += 2;               /* Required headers */
73
74         pes_header_d_length  = d[pos];
75         pos                    += 1;
76         pes_header_end          = pos + pes_header_d_length;
77
78         if( has_pts )
79         {
80             pts = ( ( ( (uint64_t) d[pos] >> 1 ) & 0x7 ) << 30 ) +
81                   ( d[pos+1] << 22 ) +
82                   ( ( d[pos+2] >> 1 ) << 15 ) +
83                   ( d[pos+3] << 7 ) +
84                   ( d[pos+4] >> 1 );
85         }
86
87         pos = pes_header_end;
88
89         if( id == 0xBD )
90         {
91             id |= ( d[pos] << 8 );
92             if( ( id & 0xF0FF ) == 0x80BD ) /* A52 */
93             {
94                 pos += 4;
95             }
96             else if( ( id & 0xE0FF ) == 0x20BD || /* SPU */
97                      ( id & 0xF0FF ) == 0xA0BD )  /* LPCM */
98             {
99                 pos += 1;
100             }
101         }
102
103         /* Sanity check */
104         if( pos >= pes_packet_end )
105         {
106             pos = pes_packet_end;
107             continue;
108         }
109
110         /* Here we hit we ES payload */
111         buf_es = hb_buffer_init( pes_packet_end - pos );
112
113         buf_es->id    = id;
114         buf_es->start = pts;
115         memcpy( buf_es->data, d + pos, pes_packet_end - pos );
116
117         hb_list_add( list_es, buf_es );
118
119         pos = pes_packet_end;
120     }
121
122 #undef d
123
124     return 1;
125 }