[FFmpeg-cvslog] vc1: fix VC-1 Pulldown handling.

John Stebbins git at videolan.org
Fri Aug 26 01:53:30 CEST 2011


ffmpeg | branch: master | John Stebbins <stebbins at jetheaddev.com> | Thu Aug 25 12:36:13 2011 -0700| [0d802ac54e86aee587f5e9917a2eefbfecd73571] | committer: Ronald S. Bultje

vc1: fix VC-1 Pulldown handling.

Pulldown flags are being set incorrectly and AVFrame->repeat_pict is not
being set.  Also, skipped frames exit header parsing too early and do not
set pulldown flags appropriately. Ticks_per_frame needs to be set and
time_base adjusted so player can extend frame duration by a field time.

This fixes problems encountered when attempting to transcode HD-DVD EVOB
files with HandBrake. Also makes these files play smoothly in avplay.

Signed-off-by: Ronald S. Bultje <rsbultje at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=0d802ac54e86aee587f5e9917a2eefbfecd73571
---

 libavcodec/vc1.c        |   11 +++++++++--
 libavcodec/vc1_parser.c |   15 +++++++++++++++
 libavcodec/vc1dec.c     |   12 ++++++++++++
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index fe9781b..c3649ac 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -501,6 +501,10 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb)
                     v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000;
                 }
             }
+            if(v->broadcast) { // Pulldown may be present
+                v->s.avctx->time_base.den *= 2;
+                v->s.avctx->ticks_per_frame = 2;
+            }
         }
 
         if(get_bits1(gb)){
@@ -818,7 +822,7 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
     case 4:
         v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic
         v->p_frame_skipped = 1;
-        return 0;
+        break;
     }
     if(v->tfcntrflag)
         skip_bits(gb, 8);
@@ -827,13 +831,16 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             v->rptfrm = get_bits(gb, 2);
         } else {
             v->tff = get_bits1(gb);
-            v->rptfrm = get_bits1(gb);
+            v->rff = get_bits1(gb);
         }
     }
     if(v->panscanflag) {
         av_log_missing_feature(v->s.avctx, "Pan-scan", 0);
         //...
     }
+    if(v->p_frame_skipped) {
+        return 0;
+    }
     v->rnd = get_bits1(gb);
     if(v->interlace)
         v->uvsamp = get_bits1(gb);
diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c
index 27ff1bd..c4c15b3 100644
--- a/libavcodec/vc1_parser.c
+++ b/libavcodec/vc1_parser.c
@@ -45,6 +45,7 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
     vpc->v.s.avctx = avctx;
     vpc->v.parse_only = 1;
     next = buf;
+    s->repeat_pict = 0;
 
     for(start = buf, end = buf + buf_size; next < end; start = next){
         int buf2_size, size;
@@ -73,6 +74,20 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
             else
                 s->pict_type = vpc->v.s.pict_type;
 
+            if (avctx->ticks_per_frame > 1){
+                // process pulldown flags
+                s->repeat_pict = 1;
+                // Pulldown flags are only valid when 'broadcast' has been set.
+                // So ticks_per_frame will be 2
+                if (vpc->v.rff){
+                    // repeat field
+                    s->repeat_pict = 2;
+                }else if (vpc->v.rptfrm){
+                    // repeat frames
+                    s->repeat_pict = vpc->v.rptfrm * 2 + 1;
+                }
+            }
+
             break;
         }
     }
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 735d6c2..f4d6f99 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -3897,6 +3897,18 @@ static int vc1_decode_frame(AVCodecContext *avctx,
         goto err;
     }
 
+    // process pulldown flags
+    s->current_picture_ptr->f.repeat_pict = 0;
+    // Pulldown flags are only valid when 'broadcast' has been set.
+    // So ticks_per_frame will be 2
+    if (v->rff){
+        // repeat field
+        s->current_picture_ptr->f.repeat_pict = 1;
+    }else if (v->rptfrm){
+        // repeat frames
+        s->current_picture_ptr->f.repeat_pict = v->rptfrm * 2;
+    }
+
     // for skipping the frame
     s->current_picture.f.pict_type = s->pict_type;
     s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I;



More information about the ffmpeg-cvslog mailing list