OSDN Git Service

CLI: Add support for naming audio tracks to the HandBrakeCLI, thanks to LePetomane...
[handbrake-jp/handbrake-jp-git.git] / libhb / 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.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8
9 /* Basic MPEG demuxer */
10
11 int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state )
12 {
13     hb_buffer_t * buf_es;
14     int           pos = 0;
15
16 #define d (buf_ps->data)
17
18     /* pack_header */
19     if( d[pos] != 0 || d[pos+1] != 0 ||
20         d[pos+2] != 0x1 || d[pos+3] != 0xBA )
21     {
22         hb_log( "hb_demux_ps: not a PS packet (%02x%02x%02x%02x)",
23                 d[pos], d[pos+1], d[pos+2], d[pos+3] );
24         return 0;
25     }
26     pos += 4;                    /* pack_start_code */
27
28     if ( state )
29     {
30         /*
31          * This section of code implements the timing model of
32          * the "Standard Target Decoder" (STD) of the MPEG2 standard
33          * (specified in ISO 13818-1 sections 2.4.2, 2.5.2 & Annex D).
34          * The STD removes and corrects for clock discontinuities so
35          * that the time stamps on the video, audio & other media
36          * streams can be used for cross-media synchronization. To do
37          * this the STD has its own timestamp value, the System Clock
38          * Reference or SCR, in the PACK header. Clock discontinuities
39          * are detected using the SCR & and the adjustment needed
40          * to correct post-discontinuity timestamps to be contiguous
41          * with pre-discontinuity timestamps is computed from pre- and
42          * post-discontinuity values of the SCR. Then this adjustment
43          * is applied to every media timestamp (PTS).
44          *
45          * ISO 13818-1 says there must be an SCR at least every 700ms
46          * (100ms for Transport Streams) so if the difference between
47          * this SCR & the previous is >700ms it's a discontinuity.
48          * If the difference is negative it's non-physical (time doesn't
49          * go backward) and must also be a discontinuity. When we find a
50          * discontinuity we adjust the scr_offset so that the SCR of the
51          * new packet lines up with that of the previous packet.
52          */
53         /* extract the system clock reference (scr) */
54         int64_t scr = ((uint64_t)(d[pos] & 0x38) << 27) |
55                       ((uint64_t)(d[pos] & 0x03) << 28) |
56                       ((uint64_t)(d[pos+1]) << 20) |
57                       ((uint64_t)(d[pos+2] >> 3) << 15) |
58                       ((uint64_t)(d[pos+2] & 3) << 13) |
59                       ((uint64_t)(d[pos+3]) << 5) |
60                       (d[pos+4] >> 3);
61         // we declare a discontinuity if there's a gap of more than
62         // 100ms between the last scr & this or if this scr goes back
63         // by more than half a frame time.
64         int64_t scr_delta = scr - state->last_scr;
65         if ( scr_delta > 90*100 || scr_delta < -90*10 )
66         {
67             ++state->scr_changes;
68         }
69         state->last_scr = scr;
70     }
71
72     pos += 9;                    /* pack_header */
73     pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
74
75     /* system_header */
76     if( d[pos] == 0 && d[pos+1] == 0 &&
77         d[pos+2] == 0x1 && d[pos+3] == 0xBB )
78     {
79         int header_length;
80
81         pos           += 4; /* system_header_start_code */
82         header_length  = ( d[pos] << 8 ) + d[pos+1];
83         pos           += 2 + header_length;
84     }
85
86     /* pes */
87     while( pos + 6 < buf_ps->size &&
88            d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 )
89     {
90         int      id;
91         int      pes_packet_length;
92         int      pes_packet_end;
93         int      pes_header_d_length;
94         int      pes_header_end;
95         int      has_pts;
96         int64_t  pts = -1, dts = -1;
97
98         pos               += 3;               /* packet_start_code_prefix */
99         id           = d[pos];
100         pos               += 1;
101
102         pes_packet_length  = ( d[pos] << 8 ) + d[pos+1];
103         pos               += 2;               /* pes_packet_length */
104         pes_packet_end     = pos + pes_packet_length;
105
106         if( id != 0xE0 && id != 0xBD &&
107             ( id & 0xC0 ) != 0xC0  )
108         {
109             /* Not interesting */
110             pos = pes_packet_end;
111             continue;
112         }
113
114         has_pts            = d[pos+1] >> 6;
115         pos               += 2;               /* Required headers */
116
117         pes_header_d_length  = d[pos];
118         pos                    += 1;
119         pes_header_end          = pos + pes_header_d_length;
120
121         if( has_pts )
122         {
123             pts = ( (uint64_t)(d[pos] & 0xe ) << 29 ) +
124                   ( d[pos+1] << 22 ) +
125                   ( ( d[pos+2] >> 1 ) << 15 ) +
126                   ( d[pos+3] << 7 ) +
127                   ( d[pos+4] >> 1 );
128             if ( has_pts & 1 )
129             {
130                 dts = ( (uint64_t)(d[pos+5] & 0xe ) << 29 ) +
131                       ( d[pos+6] << 22 ) +
132                       ( ( d[pos+7] >> 1 ) << 15 ) +
133                       ( d[pos+8] << 7 ) +
134                       ( d[pos+9] >> 1 );
135             }
136             else
137             {
138                 dts = pts;
139             }
140             if ( state && state->flaky_clock )
141             {
142                 // Program streams have an SCR in every PACK header so they
143                 // can't lose their clock reference. But the PCR in Transport
144                 // streams is typically on <.1% of the packets. If a PCR
145                 // packet gets lost and it marks a clock discontinuity then
146                 // the data following it will be referenced to the wrong
147                 // clock & introduce huge gaps or throw our A/V sync off.
148                 // We try to protect against that here by sanity checking
149                 // timestamps against the current reference clock and discarding
150                 // packets where the DTS is "too far" from its clock.
151                 int64_t fdelta = dts - state->last_scr;
152                 if ( fdelta < -300 * 90000LL || fdelta > 300 * 90000LL )
153                 {
154                     // packet too far behind or ahead of its clock reference
155                     ++state->dts_drops;
156                     pos = pes_packet_end;
157                     continue;
158                 }
159             }
160         }
161
162         pos = pes_header_end;
163
164         if( id == 0xBD )
165         {
166             id |= ( d[pos] << 8 );
167             if( ( id & 0xF0FF ) == 0x80BD ) /* A52 */
168             {
169                 pos += 4;
170             }
171             else if( ( id & 0xE0FF ) == 0x20BD || /* SPU */
172                      ( id & 0xF0FF ) == 0xA0BD )  /* LPCM */
173             {
174                 pos += 1;
175             }
176         }
177
178         /* Sanity check */
179         if( pos >= pes_packet_end )
180         {
181             pos = pes_packet_end;
182             continue;
183         }
184
185         /* Here we hit we ES payload */
186         buf_es = hb_buffer_init( pes_packet_end - pos );
187
188         buf_es->id       = id;
189         buf_es->start    = pts;
190         buf_es->renderOffset = dts;
191         buf_es->stop     = -1;
192         if (id == 0xE0) {
193             // Consume a chapter break, and apply it to the ES.
194             buf_es->new_chap = buf_ps->new_chap;
195             buf_ps->new_chap = 0;
196         }
197         memcpy( buf_es->data, d + pos, pes_packet_end - pos );
198
199         hb_list_add( list_es, buf_es );
200
201         pos = pes_packet_end;
202     }
203
204 #undef d
205
206     return 1;
207 }
208
209 // "null" demuxer (makes a copy of input buf & returns it in list)
210 // used when the reader for some format includes its own demuxer.
211 // for example, ffmpeg.
212 int hb_demux_null( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state )
213 {
214     hb_buffer_t *buf = hb_buffer_init( buf_ps->size );
215
216     // copy everything from the old to the new except the data ptr & alloc
217     uint8_t *data = buf->data;
218     int alloc = buf->alloc;
219     *buf = *buf_ps;
220     buf->data = data;
221     buf->alloc = alloc;
222
223     // now copy the data
224     memcpy( buf->data, buf_ps->data, buf_ps->size );
225     hb_list_add( list_es, buf );
226     return 1;
227 }