Attached patch cherry-picked from FFmpeg. It fixes issue2076.
I uploaded a sample to http://titan.codemill.se/~tomhar/samples/double-free.vc1 in case the original went missing.

/Tomas
>From bde3e96195421df37d879f1cc481a6b542e11b61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <reimar.doeffin...@gmx.de>
Date: Sat, 13 Aug 2011 11:32:10 +0200
Subject: [PATCH] Fix VC-1 width/height handling.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

avcodec_set_dimensions should be used for size changes to ensure
compatibility with future changes.
avctx->width/avctx->height may not be set to display-only dimensions.
Even more so since vc1dec.c would later set coded_width/height based
on this.
coded_width/coded_height should be used instead of width/height for
decoder setup.
This fixes playback of e.g. zz-mcr-nsqr.vc1 sample (containing
display width/height settings) in MPlayer and should fix a crash
with MPC: http://forum.doom9.org/showthread.php?t=162221.

Signed-off-by: Reimar Döffinger <reimar.doeffin...@gmx.de>
---
 libavcodec/vc1.c    |   31 +++++++++++++++++--------------
 libavcodec/vc1dec.c |   10 ++++------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index c3649ac..b816ca0 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -385,8 +385,9 @@ int vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitConte
     v->finterpflag = get_bits1(gb); //common
 
     if (v->res_sprite) {
-        v->s.avctx->width  = v->s.avctx->coded_width  = get_bits(gb, 11);
-        v->s.avctx->height = v->s.avctx->coded_height = get_bits(gb, 11);
+        int w = get_bits(gb, 11);
+        int h = get_bits(gb, 11);
+        avcodec_set_dimensions(v->s.avctx, w, h);
         skip_bits(gb, 5); //frame rate
         v->res_x8 = get_bits1(gb);
         if (get_bits1(gb)) { // something to do with DC VLC selection
@@ -423,6 +424,7 @@ int vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitConte
 
 static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb)
 {
+    int w, h;
     v->res_rtm_flag = 1;
     v->level = get_bits(gb, 3);
     if(v->level >= 5)
@@ -443,18 +445,17 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb)
     v->bitrtq_postproc = get_bits(gb, 5); //common
     v->postprocflag = get_bits1(gb); //common
 
-    v->s.avctx->coded_width = (get_bits(gb, 12) + 1) << 1;
-    v->s.avctx->coded_height = (get_bits(gb, 12) + 1) << 1;
-    v->s.avctx->width = v->s.avctx->coded_width;
-    v->s.avctx->height = v->s.avctx->coded_height;
+    w = (get_bits(gb, 12) + 1) << 1;
+    h = (get_bits(gb, 12) + 1) << 1;
+    avcodec_set_dimensions(v->s.avctx, w, h);
     v->broadcast = get_bits1(gb);
     v->interlace = get_bits1(gb);
     v->tfcntrflag = get_bits1(gb);
     v->finterpflag = get_bits1(gb);
     skip_bits1(gb); // reserved
 
-    v->s.h_edge_pos = v->s.avctx->coded_width;
-    v->s.v_edge_pos = v->s.avctx->coded_height;
+    v->s.h_edge_pos = w;
+    v->s.v_edge_pos = h;
 
     av_log(v->s.avctx, AV_LOG_DEBUG,
                "Advanced Profile level %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n"
@@ -472,11 +473,12 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb)
     }
     v->s.max_b_frames = v->s.avctx->max_b_frames = 7;
     if(get_bits1(gb)) { //Display Info - decoding is not affected by it
-        int w, h, ar = 0;
+        int dw, dh, ar = 0;
         av_log(v->s.avctx, AV_LOG_DEBUG, "Display extended info:\n");
-        v->s.avctx->width  = w = get_bits(gb, 14) + 1;
-        v->s.avctx->height = h = get_bits(gb, 14) + 1;
-        av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", w, h);
+        dw = get_bits(gb, 14) + 1;
+        dh = get_bits(gb, 14) + 1;
+        v->s.avctx->sample_aspect_ratio = av_div_q((AVRational){dw, dh}, (AVRational){w, h});
+        av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", dw, dh);
         if(get_bits1(gb))
             ar = get_bits(gb, 4);
         if(ar && ar < 14){
@@ -552,8 +554,9 @@ int vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContext *
     }
 
     if(get_bits1(gb)){
-        avctx->coded_width = (get_bits(gb, 12)+1)<<1;
-        avctx->coded_height = (get_bits(gb, 12)+1)<<1;
+        int w = (get_bits(gb, 12)+1)<<1;
+        int h = (get_bits(gb, 12)+1)<<1;
+        avcodec_set_dimensions(avctx, w, h);
     }
     if(v->extended_mv)
         v->extended_dmv = get_bits1(gb);
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index f4d6f99..890d755 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -3585,8 +3585,8 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
     if (vc1_init_common(v) < 0) return -1;
     ff_vc1dsp_init(&v->vc1dsp);
 
-    cur_width = avctx->coded_width = avctx->width;
-    cur_height = avctx->coded_height = avctx->height;
+    cur_width = avctx->coded_width;
+    cur_height = avctx->coded_height;
     if (avctx->codec_id == CODEC_ID_WMV3 || avctx->codec_id == CODEC_ID_WMV3IMAGE)
     {
         int count = 0;
@@ -3661,13 +3661,11 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
     // yet when ff_msmpeg4_decode_init was called the fist time
     // above.  If sequence information changes, we need to call
     // it again.
-    if (cur_width != avctx->width ||
-        cur_height != avctx->height) {
+    if (cur_width != avctx->coded_width ||
+        cur_height != avctx->coded_height) {
         MPV_common_end(s);
         if(ff_msmpeg4_decode_init(avctx) < 0)
             return -1;
-        avctx->coded_width = avctx->width;
-        avctx->coded_height = avctx->height;
     }
 
     avctx->profile = v->profile;
-- 
1.7.1

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to