1 /* $Id: demuxmpeg.c,v 1.4 2004/10/19 23:11:36 titer Exp $
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. */
9 static inline void check_mpeg_scr( hb_psdemux_t *state, int64_t scr, int tol )
12 * This section of code implements the timing model of
13 * the "Standard Target Decoder" (STD) of the MPEG2 standard
14 * (specified in ISO 13818-1 sections 2.4.2, 2.5.2 & Annex D).
15 * The STD removes and corrects for clock discontinuities so
16 * that the time stamps on the video, audio & other media
17 * streams can be used for cross-media synchronization. To do
18 * this the STD has its own timestamp value, the System Clock
19 * Reference or SCR, in the PACK header. Clock discontinuities
20 * are detected using the SCR & and the adjustment needed
21 * to correct post-discontinuity timestamps to be contiguous
22 * with pre-discontinuity timestamps is computed from pre- and
23 * post-discontinuity values of the SCR. Then this adjustment
24 * is applied to every media timestamp (PTS).
26 * ISO 13818-1 says there must be an SCR at least every 700ms
27 * (100ms for Transport Streams) so if the difference between
28 * this SCR & the previous is >700ms it's a discontinuity.
29 * If the difference is negative it's non-physical (time doesn't
30 * go backward) and must also be a discontinuity. When we find a
31 * discontinuity we adjust the scr_offset so that the SCR of the
32 * new packet lines up with that of the previous packet.
35 // we declare a discontinuity if there's a gap of more than
36 // 'tol'ms between the last scr & this or if this scr goes back
37 // by more than half a frame time.
38 int64_t scr_delta = scr - state->last_scr;
39 if ( scr_delta > 90*tol || scr_delta < -90*10 )
43 state->last_scr = scr;
46 /* Basic MPEG demuxer */
48 int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state )
53 #define d (buf_ps->data)
56 if( d[pos] != 0 || d[pos+1] != 0 ||
57 d[pos+2] != 0x1 || d[pos+3] != 0xBA )
59 hb_log( "hb_demux_ps: not a PS packet (%02x%02x%02x%02x)",
60 d[pos], d[pos+1], d[pos+2], d[pos+3] );
63 pos += 4; /* pack_start_code */
67 /* extract the system clock reference (scr) */
68 int64_t scr = ((uint64_t)(d[pos] & 0x38) << 27) |
69 ((uint64_t)(d[pos] & 0x03) << 28) |
70 ((uint64_t)(d[pos+1]) << 20) |
71 ((uint64_t)(d[pos+2] >> 3) << 15) |
72 ((uint64_t)(d[pos+2] & 3) << 13) |
73 ((uint64_t)(d[pos+3]) << 5) |
75 check_mpeg_scr( state, scr, 100 );
78 pos += 9; /* pack_header */
79 pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
82 if( d[pos] == 0 && d[pos+1] == 0 &&
83 d[pos+2] == 0x1 && d[pos+3] == 0xBB )
87 pos += 4; /* system_header_start_code */
88 header_length = ( d[pos] << 8 ) + d[pos+1];
89 pos += 2 + header_length;
93 while( pos + 6 < buf_ps->size &&
94 d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 )
97 int pes_packet_length;
99 int pes_header_d_length;
102 int64_t pts = -1, dts = -1;
104 pos += 3; /* packet_start_code_prefix */
108 pes_packet_length = ( d[pos] << 8 ) + d[pos+1];
109 pos += 2; /* pes_packet_length */
110 pes_packet_end = pos + pes_packet_length;
112 if( id != 0xE0 && id != 0xBD &&
113 ( id & 0xC0 ) != 0xC0 )
115 /* Not interesting */
116 pos = pes_packet_end;
120 has_pts = d[pos+1] >> 6;
121 pos += 2; /* Required headers */
123 pes_header_d_length = d[pos];
125 pes_header_end = pos + pes_header_d_length;
129 pts = ( (uint64_t)(d[pos] & 0xe ) << 29 ) +
131 ( ( d[pos+2] >> 1 ) << 15 ) +
136 dts = ( (uint64_t)(d[pos+5] & 0xe ) << 29 ) +
138 ( ( d[pos+7] >> 1 ) << 15 ) +
146 if ( state && state->flaky_clock )
148 // Program streams have an SCR in every PACK header so they
149 // can't lose their clock reference. But the PCR in Transport
150 // streams is typically on <.1% of the packets. If a PCR
151 // packet gets lost and it marks a clock discontinuity then
152 // the data following it will be referenced to the wrong
153 // clock & introduce huge gaps or throw our A/V sync off.
154 // We try to protect against that here by sanity checking
155 // timestamps against the current reference clock and discarding
156 // packets where the DTS is "too far" from its clock.
157 int64_t fdelta = dts - state->last_scr;
158 if ( fdelta < -300 * 90000LL || fdelta > 300 * 90000LL )
160 // packet too far behind or ahead of its clock reference
162 pos = pes_packet_end;
168 pos = pes_header_end;
172 id |= ( d[pos] << 8 );
173 if( ( id & 0xF0FF ) == 0x80BD ) /* A52 */
177 else if( ( id & 0xE0FF ) == 0x20BD || /* SPU */
178 ( id & 0xF0FF ) == 0xA0BD ) /* LPCM */
185 if( pos >= pes_packet_end )
187 pos = pes_packet_end;
191 /* Here we hit we ES payload */
192 buf_es = hb_buffer_init( pes_packet_end - pos );
196 buf_es->renderOffset = dts;
199 // Consume a chapter break, and apply it to the ES.
200 buf_es->new_chap = buf_ps->new_chap;
201 buf_ps->new_chap = 0;
203 memcpy( buf_es->data, d + pos, pes_packet_end - pos );
205 hb_list_add( list_es, buf_es );
207 pos = pes_packet_end;
215 // mpeg transport stream demuxer. the elementary stream headers have been
216 // stripped off and buf_ps has all the info gleaned from them: id is set,
217 // start contains the pts (if any), renderOffset contains the dts (if any)
218 // and stop contains the pcr (if it changed).
219 int hb_demux_ts( hb_buffer_t *buf_ps, hb_list_t *list_es, hb_psdemux_t *state )
223 // we're keeping track of timing (i.e., not in scan)
224 // check if there's a new pcr in this packet
225 if ( buf_ps->stop >= 0 )
228 check_mpeg_scr( state, buf_ps->stop, 300 );
231 if ( buf_ps->renderOffset >= 0 )
233 // Program streams have an SCR in every PACK header so they
234 // can't lose their clock reference. But the PCR in Transport
235 // streams is typically on <.1% of the packets. If a PCR
236 // packet gets lost and it marks a clock discontinuity then
237 // the data following it will be referenced to the wrong
238 // clock & introduce huge gaps or throw our A/V sync off.
239 // We try to protect against that here by sanity checking
240 // timestamps against the current reference clock and discarding
241 // packets where the DTS is "too far" from its clock.
242 int64_t fdelta = buf_ps->renderOffset - state->last_scr;
243 if ( fdelta < -300 * 90000LL || fdelta > 300 * 90000LL )
245 // packet too far behind or ahead of its clock reference
252 hb_buffer_t *buf = hb_buffer_init( buf_ps->alloc );
253 hb_buffer_swap_copy( buf_ps, buf );
254 hb_list_add( list_es, buf );
259 // "null" demuxer (makes a copy of input buf & returns it in list)
260 // used when the reader for some format includes its own demuxer.
261 // for example, ffmpeg.
262 int hb_demux_null( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state )
264 // if we don't have a time offset yet, use this timestamp as the offset.
265 if ( state && state->scr_changes == 0 &&
266 ( buf_ps->start >= 0 || buf_ps->renderOffset >= 0 ) )
268 ++state->scr_changes;
269 state->last_scr = buf_ps->start >= 0 ? buf_ps->start : buf_ps->renderOffset;
272 hb_buffer_t *buf = hb_buffer_init( buf_ps->alloc );
273 hb_buffer_swap_copy( buf_ps, buf );
274 hb_list_add( list_es, buf );
279 const hb_muxer_t hb_demux[] = { hb_demux_ps, hb_demux_ts, hb_demux_null };