From 7b0444d5945ab264fa3b7086dd44a3c6ae383ee4 Mon Sep 17 00:00:00 2001 From: eddyg Date: Mon, 17 Sep 2007 03:01:07 +0000 Subject: Van's changes to the x264 lib and HB encoder to ensure that an IDR frame is used for each new chapter. Well done and lots of thanks to Van for this one. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@967 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- contrib/Jamfile | 1 + contrib/patch-x264-idr.patch | 17 +++++++++++++++++ libhb/encx264.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 contrib/patch-x264-idr.patch 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; -- cgit v1.2.3