]> granicus.if.org Git - libx264/commitdiff
Improve flash detection's behavior near the end of the video
authorFiona Glaser <fiona@x264.com>
Sun, 7 Nov 2010 00:47:27 +0000 (17:47 -0700)
committerFiona Glaser <fiona@x264.com>
Wed, 10 Nov 2010 08:16:25 +0000 (00:16 -0800)
Flash detection catches situations like AAAABBCCDDDD, where A,B,C,D are frames in different scenes.
x264 would place a keyframe on the first "D".
However, if the video ended on the last "C", x264 would place a keyframe on the first "C", even though C classifies as a flash.
This change fixes this issue.

encoder/slicetype.c

index 168d008655d27f831b96638d29298dfff4ae277a..68fb3fae9fe98460c014b4224cff111db8ff9ceb 100644 (file)
@@ -1037,14 +1037,14 @@ static int scenecut( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, in
     /* Only do analysis during a normal scenecut check. */
     if( real_scenecut && h->param.i_bframe )
     {
-        int maxp1 = p0 + 1;
+        int origmaxp1 = p0 + 1;
         /* Look ahead to avoid coding short flashes as scenecuts. */
         if( h->param.i_bframe_adaptive == X264_B_ADAPT_TRELLIS )
             /* Don't analyse any more frames than the trellis would have covered. */
-            maxp1 += h->param.i_bframe;
+            origmaxp1 += h->param.i_bframe;
         else
-            maxp1++;
-        maxp1 = X264_MIN( maxp1, num_frames );
+            origmaxp1++;
+        int maxp1 = X264_MIN( origmaxp1, num_frames );
 
         /* Where A and B are scenes: AAAAAABBBAAAAAA
          * If BBB is shorter than (maxp1-p0), it is detected as a flash
@@ -1058,9 +1058,10 @@ static int scenecut( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, in
         /* Where A-F are scenes: AAAAABBCCDDEEFFFFFF
          * If each of BB ... EE are shorter than (maxp1-p0), they are
          * detected as flashes and not considered scenecuts.
-         * Instead, the first F frame becomes a scenecut. */
-        for( int curp0 = p0; curp0 < maxp1; curp0++ )
-            if( scenecut_internal( h, a, frames, curp0, maxp1, 0 ) )
+         * Instead, the first F frame becomes a scenecut.
+         * If the video ends before F, no frame becomes a scenecut. */
+        for( int curp0 = p0; curp0 <= maxp1; curp0++ )
+            if( maxp1 != origmaxp1 || (curp0 < maxp1 && scenecut_internal( h, a, frames, curp0, maxp1, 0 )) )
                 /* If cur_p0 is the p0 of a scenecut, it cannot be the p1 of a scenecut. */
                     frames[curp0]->b_scenecut = 0;
     }