diff options
-rw-r--r-- | libhb/decmpeg2.c | 60 | ||||
-rw-r--r-- | libhb/dvd.c | 5 | ||||
-rw-r--r-- | libhb/encx264.c | 4 | ||||
-rw-r--r-- | libhb/muxmkv.c | 7 | ||||
-rw-r--r-- | libhb/muxmp4.c | 22 | ||||
-rw-r--r-- | libhb/sync.c | 13 | ||||
-rw-r--r-- | libhb/work.c | 5 |
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 ) |