summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/decmpeg2.c60
-rw-r--r--libhb/dvd.c5
-rw-r--r--libhb/encx264.c4
-rw-r--r--libhb/muxmkv.c7
-rw-r--r--libhb/muxmp4.c22
-rw-r--r--libhb/sync.c13
-rw-r--r--libhb/work.c5
7 files changed, 77 insertions, 39 deletions
diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c
index 4f0c27ddd..76bece134 100644
--- a/libhb/decmpeg2.c
+++ b/libhb/decmpeg2.c
@@ -37,12 +37,15 @@ struct hb_libmpeg2_s
{
mpeg2dec_t * libmpeg2;
const mpeg2_info_t * info;
+ hb_job_t * job;
int width;
int height;
int rate;
int aspect_ratio;
- int got_iframe;
- int look_for_break;
+ int got_iframe; /* set when we get our first iframe */
+ int look_for_iframe; /* need an iframe to add chap break */
+ int look_for_break; /* need gop start to add chap break */
+ uint32_t nframes; /* number of frames we've decoded */
int64_t last_pts;
};
@@ -58,7 +61,6 @@ hb_libmpeg2_t * hb_libmpeg2_init()
m->libmpeg2 = mpeg2_init();
m->info = mpeg2_info( m->libmpeg2 );
m->last_pts = -1;
- m->look_for_break = 0;
return m;
}
@@ -74,7 +76,6 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
mpeg2_state_t state;
hb_buffer_t * buf;
uint8_t * data;
- int chap_break = 0;
/* Feed libmpeg2 */
if( buf_es->start > -1 )
@@ -117,10 +118,12 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
}
}
}
- else if( state == STATE_GOP && m->look_for_break == 2)
+ else if( state == STATE_GOP && m->look_for_break)
{
- hb_log("MPEG2: Group of pictures found, searching for I-Frame");
- m->look_for_break = 1;
+ // we were looking for a gop to add a chapter break - we found it
+ // so now start looking for an iframe.
+ m->look_for_iframe = m->look_for_break;
+ m->look_for_break = 0;
}
else if( ( state == STATE_SLICE || state == STATE_END ) &&
m->info->display_fbuf )
@@ -128,15 +131,8 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
if( ( m->info->display_picture->flags &
PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
{
+ // we got an iframe so we can start decoding video now
m->got_iframe = 1;
-
- // If we are looking for a break, insert the chapter break on an I-Frame
- if( m->look_for_break == 1 )
- {
- hb_log("MPEG2: I-Frame Found");
- m->look_for_break = 0;
- chap_break = 1;
- }
}
if( m->got_iframe )
@@ -146,14 +142,6 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
buf->sequence = buf_es->sequence;
- // Was a good break point found?
- if( chap_break )
- {
- hb_log("MPEG2: Chapter Break Inserted");
- chap_break = 0;
- buf->new_chap = 1;
- }
-
memcpy( data, m->info->display_fbuf->buf[0],
m->width * m->height );
data += m->width * m->height;
@@ -187,6 +175,27 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
}
m->last_pts = buf->start;
+ if( m->look_for_iframe && ( m->info->display_picture->flags &
+ PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
+ {
+ // we were waiting for an iframe to insert a chapter mark
+ // and we have one.
+ buf->new_chap = m->look_for_iframe;
+ m->look_for_iframe = 0;
+ const char *chap_name = "";
+ if ( m->job && buf->new_chap > 0 &&
+ hb_list_item( m->job->title->list_chapter,
+ buf->new_chap - 1 ) )
+ {
+ hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
+ buf->new_chap - 1 );
+ chap_name = c->title;
+ }
+ hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld",
+ chap_name, buf->new_chap, m->nframes, buf->start );
+ }
+ ++m->nframes;
+
flag = m->info->display_picture->flags;
/* Uncomment this block to see frame-by-frame picture flags, as the video encodes.
@@ -362,6 +371,8 @@ int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
pv->libmpeg2 = hb_libmpeg2_init();
pv->list = hb_list_init();
+ pv->libmpeg2->job = job;
+
return 0;
}
@@ -380,8 +391,7 @@ int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
// stream. We need to shift it.
if( (*buf_in)->new_chap )
{
- hb_log("MPEG2: Chapter Break Cell Found, searching for GOP");
- pv->libmpeg2->look_for_break = 2;
+ pv->libmpeg2->look_for_break = (*buf_in)->new_chap;
(*buf_in)->new_chap = 0;
}
diff --git a/libhb/dvd.c b/libhb/dvd.c
index 3c78e2cbd..cca1e8003 100644
--- a/libhb/dvd.c
+++ b/libhb/dvd.c
@@ -962,7 +962,7 @@ int hb_dvd_chapter( hb_dvd_t * d )
/***********************************************************************
* hb_dvd_is_break
***********************************************************************
- * Returns 1 if the current block is a new chapter start
+ * Returns chapter number if the current block is a new chapter start
**********************************************************************/
int hb_dvd_is_break( hb_dvd_t * d )
{
@@ -988,8 +988,7 @@ int hb_dvd_is_break( hb_dvd_t * d )
// This must not match against the start cell.
if( pgc->cell_playback[cell].first_sector == d->block && cell != d->cell_start )
{
- hb_log("dvd: Chapter Break Cell Found");
- return 1;
+ return i + 1;
}
}
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 8f976748d..c9fbffec9 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -50,6 +50,7 @@ struct hb_work_private_s
x264_picture_t pic_in;
uint8_t *x264_allocated_pic;
+ int chap_mark; // saved chap mark when we're propagating it
int64_t dts_next; // DTS start time value for next output frame
int64_t last_stop; // Debugging - stop time of previous input frame
int64_t init_delay;
@@ -384,6 +385,7 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
if( pv->next_chap == 0 )
{
pv->next_chap = in->start;
+ pv->chap_mark = in->new_chap;
}
/* don't let 'work_loop' put a chapter mark on the wrong buffer */
in->new_chap = 0;
@@ -496,7 +498,7 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
if( pv->next_chap != 0 && pv->next_chap <= pic_out.i_pts )
{
pv->next_chap = 0;
- buf->new_chap = 1;
+ buf->new_chap = pv->chap_mark;
}
break;
case X264_TYPE_I:
diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c
index 76fc48b6f..c90f73ea7 100644
--- a/libhb/muxmkv.c
+++ b/libhb/muxmkv.c
@@ -265,7 +265,12 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
/* Make sure we're not writing a chapter that has 0 length */
if (mux_data->prev_chapter_tc != timecode)
{
- chapter_data = hb_list_item( title->list_chapter, mux_data->current_chapter++ );
+ if ( buf->new_chap )
+ {
+ mux_data->current_chapter = buf->new_chap - 2;
+ }
+ chapter_data = hb_list_item( title->list_chapter,
+ mux_data->current_chapter++ );
tmp_buffer[0] = '\0';
if( chapter_data != NULL )
diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c
index 59c228f70..0515e5636 100644
--- a/libhb/muxmp4.c
+++ b/libhb/muxmp4.c
@@ -100,10 +100,16 @@ static struct hb_text_sample_s *MP4CreateTextSample( char *textString, uint64_t
**********************************************************************
* Creates a buffer for a text track sample
*********************************************************************/
-static struct hb_text_sample_s *MP4GenerateChapterSample( hb_mux_object_t * m, uint64_t duration )
+static struct hb_text_sample_s *MP4GenerateChapterSample( hb_mux_object_t * m,
+ uint64_t duration,
+ int chapter )
{
- int chapter = m->current_chapter;
- hb_chapter_t *chapter_data = hb_list_item( m->job->title->list_chapter, chapter - 1 );
+ // We substract 1 from the chapter number because the chapters start at
+ // 1 but our name array starts at 0. We substract another 1 because we're
+ // writing the text of the previous chapter mark (when we get the start
+ // of chapter 2 we know the duration of chapter 1 & can write its mark).
+ hb_chapter_t *chapter_data = hb_list_item( m->job->title->list_chapter,
+ chapter - 2 );
char tmp_buffer[1024];
char *string = tmp_buffer;
@@ -116,7 +122,7 @@ static struct hb_text_sample_s *MP4GenerateChapterSample( hb_mux_object_t * m, u
if( strlen(string) == 0 || strlen(string) >= 1024 )
{
- snprintf( tmp_buffer, 1023, "Chapter %03i", chapter );
+ snprintf( tmp_buffer, 1023, "Chapter %03i", chapter - 2 );
string = tmp_buffer;
}
@@ -383,7 +389,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
duration += buf->renderOffset * m->samplerate / 90000;
}
- sample = MP4GenerateChapterSample( m, duration );
+ sample = MP4GenerateChapterSample( m, duration, buf->new_chap );
if( !MP4WriteSample(m->file,
m->chapter_track,
@@ -396,7 +402,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
*job->die = 1;
}
free(sample);
- m->current_chapter++;
+ m->current_chapter = buf->new_chap;
m->chapter_duration += duration;
}
@@ -461,7 +467,9 @@ static int MP4End( hb_mux_object_t * m )
/* Write our final chapter marker */
if( m->job->chapter_markers )
{
- struct hb_text_sample_s *sample = MP4GenerateChapterSample( m, (m->sum_dur - m->chapter_duration) );
+ struct hb_text_sample_s *sample = MP4GenerateChapterSample( m,
+ (m->sum_dur - m->chapter_duration),
+ m->current_chapter + 1 );
if( !MP4WriteSample(m->file,
m->chapter_track,
diff --git a/libhb/sync.c b/libhb/sync.c
index b787106f7..233863391 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -52,6 +52,7 @@ struct hb_work_private_s
int video_sequence;
int count_frames;
int count_frames_max;
+ int chap_mark; /* to propagate chapter mark across a drop */
hb_buffer_t * cur; /* The next picture to process */
/* Audio */
@@ -344,6 +345,11 @@ static int SyncVideo( hb_work_object_t * w )
}
++pv->drop_count;
buf_tmp = hb_fifo_get( job->fifo_raw );
+ if ( buf_tmp->new_chap )
+ {
+ // don't drop a chapter mark when we drop the buffer
+ pv->chap_mark = buf_tmp->new_chap;
+ }
hb_buffer_close( &buf_tmp );
continue;
}
@@ -521,6 +527,13 @@ static int SyncVideo( hb_work_object_t * w )
buf_tmp->start = pv->next_start;
pv->next_start += duration;
buf_tmp->stop = pv->next_start;
+ if ( pv->chap_mark )
+ {
+ // we have a pending chapter mark from a recent drop - put it on this
+ // buffer (this may make it one frame late but we can't do any better).
+ buf_tmp->new_chap = pv->chap_mark;
+ pv->chap_mark = 0;
+ }
/* If we have a subtitle for this picture, copy it */
/* FIXME: we should avoid this memcpy */
diff --git a/libhb/work.c b/libhb/work.c
index e867a2bfe..a3507027e 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -840,8 +840,9 @@ static void work_loop( void * _w )
// 'buf_in' to NULL so that this code won't generate spurious duplicates.)
if( buf_in && buf_out && buf_in->new_chap && buf_in->start == buf_out->start)
{
- hb_log("work %s: Copying Chapter Break @ %lld", w->name, buf_in->start);
- buf_out->new_chap = 1;
+ // restore log below to debug chapter mark propagation problems
+ //hb_log("work %s: Copying Chapter Break @ %lld", w->name, buf_in->start);
+ buf_out->new_chap = buf_in->new_chap;
}
if( buf_in )