/* $Id: demuxmpeg.c,v 1.4 2004/10/19 23:11:36 titer Exp $
This file is part of the HandBrake source code.
- Homepage: <http://handbrake.m0k.org/>.
+ Homepage: <http://handbrake.fr/>.
It may be used under the terms of the GNU General Public License. */
#include "hb.h"
/* Basic MPEG demuxer, only works with DVDs (2048 bytes packets) */
-int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es )
+int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state )
{
hb_buffer_t * buf_es;
- int pos;
-
- pos = 0;
+ int pos = 0;
#define d (buf_ps->data)
return 0;
}
pos += 4; /* pack_start_code */
+
+ if ( state )
+ {
+ /*
+ * This section of code implements the timing model of
+ * the "Standard Target Decoder" (STD) of the MPEG2 standard
+ * (specified in ISO 13818-1 sections 2.4.2, 2.5.2 & Annex D).
+ * The STD removes and corrects for clock discontinuities so
+ * that the time stamps on the video, audio & other media
+ * streams can be used for cross-media synchronization. To do
+ * this the STD has its own timestamp value, the System Clock
+ * Reference or SCR, in the PACK header. Clock discontinuities
+ * are detected using the SCR & and the adjustment needed
+ * to correct post-discontinuity timestamps to be contiguous
+ * with pre-discontinuity timestamps is computed from pre- and
+ * post-discontinuity values of the SCR. Then this adjustment
+ * is applied to every media timestamp (PTS).
+ *
+ * ISO 13818-1 says there must be an SCR at least every 700ms
+ * (100ms for Transport Streams) so if the difference between
+ * this SCR & the previous is >700ms it's a discontinuity.
+ * If the difference is negative it's non-physical (time doesn't
+ * go backward) and must also be a discontinuity. When we find a
+ * discontinuity we adjust the scr_offset so that the SCR of the
+ * new packet lines up with that of the previous packet.
+ */
+ /* extract the system clock reference (scr) */
+ int64_t scr = ((uint64_t)(d[pos] & 0x38) << 27) |
+ ((uint64_t)(d[pos] & 0x03) << 28) |
+ ((uint64_t)(d[pos+1]) << 20) |
+ ((uint64_t)(d[pos+2] >> 3) << 15) |
+ ((uint64_t)(d[pos+2] & 3) << 13) |
+ ((uint64_t)(d[pos+3]) << 5) |
+ (d[pos+4] >> 3);
+ int64_t scr_delta = scr - state->last_scr;
+ if ( scr_delta > (90*700) || scr_delta < 0 )
+ {
+ ++state->scr_changes;
+ state->scr_offset += scr_delta - 1;
+ }
+ state->last_scr = scr;
+ }
+
pos += 9; /* pack_header */
pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
buf_es->id = id;
buf_es->start = pts;
- buf_es->new_chap = buf_ps->new_chap; // Consume a chapter break, and apply it to the ES.
- buf_ps->new_chap = 0;
+ buf_es->stop = -1;
+ if (id == 0xE0) {
+ // Consume a chapter break, and apply it to the ES.
+ buf_es->new_chap = buf_ps->new_chap;
+ buf_ps->new_chap = 0;
+ }
memcpy( buf_es->data, d + pos, pes_packet_end - pos );
hb_list_add( list_es, buf_es );