diff options
-rw-r--r-- | contrib/Jamfile | 1 | ||||
-rw-r--r-- | contrib/patch-x264-idr.patch | 17 | ||||
-rw-r--r-- | libhb/encx264.c | 31 |
3 files changed, 48 insertions, 1 deletions
diff --git a/contrib/Jamfile b/contrib/Jamfile index f321d293d..1ece7d902 100644 --- a/contrib/Jamfile +++ b/contrib/Jamfile @@ -332,6 +332,7 @@ rule LibX264 LIBX264_PATCH += "patch -p1 < ../patch-x264-cygwin.patch && " ; } LIBX264_PATCH += "patch -p0 < ../patch-x264-aq.patch && " ; + LIBX264_PATCH += "patch -p0 < ../patch-x264-idr.patch && " ; Depends $(<) : $(>) ; Depends lib : $(<) ; } diff --git a/contrib/patch-x264-idr.patch b/contrib/patch-x264-idr.patch new file mode 100644 index 000000000..df4294f12 --- /dev/null +++ b/contrib/patch-x264-idr.patch @@ -0,0 +1,17 @@ +Index: encoder/slicetype.c +=================================================================== +--- encoder/slicetype.c (revision 665) ++++ encoder/slicetype.c (working copy) +@@ -379,7 +379,12 @@ + return; + frames[0] = h->frames.last_nonb; + for( j = 0; h->frames.next[j]; j++ ) ++ { ++ // if the app wants an IDR, give it to them ++ if ( h->frames.next[j]->i_type == X264_TYPE_IDR ) ++ return; + frames[j+1] = h->frames.next[j]; ++ } + keyint_limit = h->param.i_keyint_max - frames[0]->i_frame + h->frames.i_last_idr - 1; + num_frames = X264_MIN( j, keyint_limit ); + if( num_frames == 0 ) diff --git a/libhb/encx264.c b/libhb/encx264.c index 98ede9704..95922d504 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -38,6 +38,7 @@ struct hb_work_private_s int64_t dts_write_index; int64_t dts_read_index; + int64_t next_chap; char filename[1024]; }; @@ -232,6 +233,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) pv->dts_write_index = 0; pv->dts_read_index = 0; + pv->next_chap = 0; return 0; } @@ -276,7 +278,25 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in, job->height / 4, job->width * job->height / 4 ); } - pv->pic_in.i_type = X264_TYPE_AUTO; + if( in->new_chap && job->chapter_markers ) + { + /* chapters have to start with an IDR frame so request that this + frame be coded as IDR. Since there may be up to 16 frames + currently buffered in the encoder remember the timestamp so + when this frame finally pops out of the encoder we'll mark + its buffer as the start of a chapter. */ + pv->pic_in.i_type = X264_TYPE_IDR; + if( pv->next_chap == 0 ) + { + pv->next_chap = in->start; + } + /* don't let 'work_loop' put a chapter mark on the wrong buffer */ + in->new_chap = 0; + } + else + { + pv->pic_in.i_type = X264_TYPE_AUTO; + } pv->pic_in.i_qpplus1 = 0; // Remember current PTS value, use as DTS later @@ -365,6 +385,15 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in, /* Decide what type of frame we have. */ case X264_TYPE_IDR: buf->frametype = HB_FRAME_IDR; + /* if we have a chapter marker pending and this + frame's presentation time stamp is at or after + the marker's time stamp, use this as the + chapter start. */ + if( pv->next_chap != 0 && pv->next_chap <= pic_out.i_pts ) + { + pv->next_chap = 0; + buf->new_chap = 1; + } break; case X264_TYPE_I: buf->frametype = HB_FRAME_I; |