OSDN Git Service

Van's changes to the x264 lib and HB encoder to ensure that an IDR frame is used...
authoreddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 17 Sep 2007 03:01:07 +0000 (03:01 +0000)
committereddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 17 Sep 2007 03:01:07 +0000 (03:01 +0000)
git-svn-id: svn://localhost/HandBrake/trunk@967 b64f7644-9d1e-0410-96f1-a4d463321fa5

contrib/Jamfile
contrib/patch-x264-idr.patch [new file with mode: 0644]
libhb/encx264.c

index f321d29..1ece7d9 100644 (file)
@@ -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 (file)
index 0000000..df4294f
--- /dev/null
@@ -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 )
index 98ede97..95922d5 100644 (file)
@@ -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;