diff options
author | eddyg <[email protected]> | 2007-09-17 03:01:07 +0000 |
---|---|---|
committer | eddyg <[email protected]> | 2007-09-17 03:01:07 +0000 |
commit | 7b0444d5945ab264fa3b7086dd44a3c6ae383ee4 (patch) | |
tree | a02302e038fe02d941319d421ce7217a2aed5824 | |
parent | b67ea5e9820f3ed2e969da3ae94205e4097c5da6 (diff) |
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
-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; |