summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvan <[email protected]>2008-04-15 19:14:03 +0000
committervan <[email protected]>2008-04-15 19:14:03 +0000
commit56d9caaefb91abc763be3a1d17d14d0e7e2e9059 (patch)
treec693cf6b581410cc53b55772bf1d5a68ddc9456f
parentb856292606251eafc70286eac8c5dc6e6fd9dd02 (diff)
Move clock recovery code from reader to demuxmpeg so it sees all frames & not just the ones we happen to be encoding. This change gives a more accurate clock and allows us to once again ignore audio during pass 1 of a 2 pass encode.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1420 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--libhb/demuxmpeg.c56
-rw-r--r--libhb/hb.c6
-rw-r--r--libhb/internal.h8
-rw-r--r--libhb/reader.c61
-rw-r--r--libhb/scan.c2
-rwxr-xr-xlibhb/stream.c4
6 files changed, 65 insertions, 72 deletions
diff --git a/libhb/demuxmpeg.c b/libhb/demuxmpeg.c
index 424cce696..35d941ad0 100644
--- a/libhb/demuxmpeg.c
+++ b/libhb/demuxmpeg.c
@@ -8,11 +8,10 @@
/* 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 = 0;
- int64_t scr;
#define d (buf_ps->data)
@@ -25,14 +24,49 @@ int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es )
return 0;
}
pos += 4; /* pack_start_code */
- /* extract the system clock reference (scr) */
- 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);
+
+ 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 */
@@ -119,7 +153,7 @@ int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es )
buf_es->id = id;
buf_es->start = pts;
- buf_es->stop = scr;
+ 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;
diff --git a/libhb/hb.c b/libhb/hb.c
index a6fc87fca..5f176f1ae 100644
--- a/libhb/hb.c
+++ b/libhb/hb.c
@@ -857,11 +857,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
title_copy->list_audio = hb_list_init();
/* Do nothing about audio during first pass */
- // XXX for right now we need to see the audio in libhb/reader.c to track
- // clock changes otherwise we'll discard more video frames in pass 1 than
- // pass 2 & screw up the encoding. Once the clock tracking is moved from
- // reader to the mpeg demuxer this code can be restored.
- //if( job->pass == 0 || job->pass == 2 )
+ if( job->pass == 0 || job->pass == 2 )
{
for( i = 0; i < hb_list_count(job->list_audio); i++ )
{
diff --git a/libhb/internal.h b/libhb/internal.h
index 73a5502da..5f3baecc5 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -117,7 +117,13 @@ int hb_libmpeg2_clear_aspect_ratio( hb_libmpeg2_t * );
/***********************************************************************
* mpegdemux.c
**********************************************************************/
-int hb_demux_ps( hb_buffer_t * ps_buf, hb_list_t * es_list );
+typedef struct {
+ int64_t last_scr; /* unadjusted SCR from most recent pack */
+ int64_t scr_offset; /* discontinuity correction adjustment */
+ int scr_changes; /* number of SCR discontinuities */
+} hb_psdemux_t;
+
+int hb_demux_ps( hb_buffer_t * ps_buf, hb_list_t * es_list, hb_psdemux_t * );
/***********************************************************************
* dvd.c
diff --git a/libhb/reader.c b/libhb/reader.c
index ac02f90ca..233319833 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -16,12 +16,9 @@ typedef struct
hb_buffer_t * ps;
hb_stream_t * stream;
+ hb_psdemux_t demux;
uint sequence;
int saw_video;
- int64_t scr_offset;
- int64_t last_scr;
- int scr_changes;
-
} hb_reader_t;
/***********************************************************************
@@ -161,7 +158,7 @@ static void ReaderFunc( void * _r )
hb_set_state( r->job->h, &state );
}
- hb_demux_ps( r->ps, list );
+ hb_demux_ps( r->ps, list, &r->demux );
while( ( buf = hb_list_item( list, 0 ) ) )
{
@@ -175,10 +172,9 @@ static void ReaderFunc( void * _r )
if ( buf->id == 0xE0 && buf->start != -1 )
{
r->saw_video = 1;
- r->scr_offset = buf->start;
- r->last_scr = buf->stop;
+ r->demux.scr_offset = buf->start;
hb_log( "reader: first SCR %llu scr_offset %llu",
- r->last_scr, r->scr_offset );
+ r->demux.last_scr, r->demux.scr_offset );
}
else
{
@@ -187,52 +183,13 @@ static void ReaderFunc( void * _r )
}
if( fifos )
{
- /*
- * 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).
- *
- * hb_demux_ps left the SCR for this pack in buf->stop.
- * 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.
- */
- int64_t scr_delta = buf->stop - r->last_scr;
- if ( scr_delta > (90*700) || scr_delta < -90 )
- {
- ++r->scr_changes;
- r->scr_offset += scr_delta - 1;
- }
- r->last_scr = buf->stop;
- buf->stop = -1;
-
- /*
- * The last section detected discontinuites and computed the
- * appropriate correction to remove them. The next couple of
- * lines apply the correction to the media timestamps so the
- * code downstream of us sees only timestamps relative to the
- * same, continuous clock with time zero on that clock being
- * the time of the first video packet.
- */
if ( buf->start != -1 )
{
/* this packet has a PTS - correct it for the initial
- video time offset & any timing discontinuities. */
- buf->start -= r->scr_offset;
+ video time offset & any timing discontinuities so that
+ everything after this sees a continuous clock with 0
+ being the time of the first video packet. */
+ buf->start -= r->demux.scr_offset;
}
buf->sequence = r->sequence++;
for( n = 0; fifos[n] != NULL; n++)
@@ -284,7 +241,7 @@ static void ReaderFunc( void * _r )
hb_stream_close(&r->stream);
}
- hb_log( "reader: done. %d scr changes", r->scr_changes );
+ hb_log( "reader: done. %d scr changes", r->demux.scr_changes );
free( r );
_r = NULL;
diff --git a/libhb/scan.c b/libhb/scan.c
index 8669fb01e..b139e5e4c 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -299,7 +299,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
goto skip_preview;
}
}
- hb_demux_ps( buf_ps, list_es );
+ hb_demux_ps( buf_ps, list_es, 0 );
while( ( buf_es = hb_list_item( list_es, 0 ) ) )
{
diff --git a/libhb/stream.c b/libhb/stream.c
index 9738eb36b..1d1ea2b26 100755
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -541,7 +541,7 @@ static uint64_t hb_ps_stream_getVideoPTS(hb_stream_t *stream)
hb_buffer_t *es;
// 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams
- hb_demux_ps(buf, list);
+ hb_demux_ps(buf, list, 0);
while ( ( es = hb_list_item( list, 0 ) ) )
{
@@ -884,7 +884,7 @@ static void hb_ps_stream_find_audio_ids(hb_stream_t *stream, hb_title_t *title)
hb_buffer_t *es;
// 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams
- hb_demux_ps(buf, list);
+ hb_demux_ps(buf, list, 0);
while ( ( es = hb_list_item( list, 0 ) ) )
{