]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/vp6.c
clarify codec_tag
[ffmpeg] / libavcodec / vp6.c
index bf528f826a9aebe6d473f0ce4b51ee96dd441ed9..2e904b7e0af77547f7365664861a14074602e1ba 100644 (file)
@@ -4,23 +4,29 @@
  *
  * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
  *
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *
+ * The VP6F decoder accept an optional 1 byte extradata. It is composed of:
+ *  - upper 4bits: difference between encoded width and visible width
+ *  - lower 4bits: difference between encoded height and visible height
  */
 
 #include <stdlib.h>
-#include <inttypes.h>
 
 #include "avcodec.h"
 #include "dsputil.h"
@@ -36,23 +42,31 @@ static int vp6_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
                             int *golden_frame)
 {
     vp56_range_coder_t *c = &s->c;
-    int parse_filter_info;
+    int parse_filter_info = 0;
+    int coeff_offset = 0;
+    int vrt_shift = 0;
+    int sub_version;
     int rows, cols;
     int res = 1;
+    int separated_coeff = buf[0] & 1;
 
-    if (buf[0] & 1)
-        return 0;
-
-    s->frames[VP56_FRAME_CURRENT].key_frame = !(buf[0] & 0x80);
+    s->framep[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80);
     vp56_init_dequant(s, (buf[0] >> 1) & 0x3F);
 
-    if (s->frames[VP56_FRAME_CURRENT].key_frame) {
-        if ((buf[1] & 0xFE) != 0x46)  /* would be 0x36 for VP61 */
+    if (s->framep[VP56_FRAME_CURRENT]->key_frame) {
+        sub_version = buf[1] >> 3;
+        if (sub_version > 8)
             return 0;
+        s->filter_header = buf[1] & 0x06;
         if (buf[1] & 1) {
             av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n");
             return 0;
         }
+        if (separated_coeff || !s->filter_header) {
+            coeff_offset = AV_RB16(buf+2) - 2;
+            buf += 2;
+            buf_size -= 2;
+        }
 
         rows = buf[2];  /* number of stored macroblock rows */
         cols = buf[3];  /* number of stored macroblock cols */
@@ -62,37 +76,67 @@ static int vp6_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
         if (16*cols != s->avctx->coded_width ||
             16*rows != s->avctx->coded_height) {
             avcodec_set_dimensions(s->avctx, 16*cols, 16*rows);
+            if (s->avctx->extradata_size == 1) {
+                s->avctx->width  -= s->avctx->extradata[0] >> 4;
+                s->avctx->height -= s->avctx->extradata[0] & 0x0F;
+            }
             res = 2;
         }
 
         vp56_init_range_decoder(c, buf+6, buf_size-6);
         vp56_rac_gets(c, 2);
 
-        parse_filter_info = 1;
+        parse_filter_info = s->filter_header;
+        if (sub_version < 8)
+            vrt_shift = 5;
+        s->sub_version = sub_version;
     } else {
+        if (!s->sub_version)
+            return 0;
+
+        if (separated_coeff || !s->filter_header) {
+            coeff_offset = AV_RB16(buf+1) - 2;
+            buf += 2;
+            buf_size -= 2;
+        }
         vp56_init_range_decoder(c, buf+1, buf_size-1);
 
         *golden_frame = vp56_rac_get(c);
-        s->deblock_filtering = vp56_rac_get(c);
-        if (s->deblock_filtering)
-            vp56_rac_get(c);
-        parse_filter_info = vp56_rac_get(c);
+        if (s->filter_header) {
+            s->deblock_filtering = vp56_rac_get(c);
+            if (s->deblock_filtering)
+                vp56_rac_get(c);
+            if (s->sub_version > 7)
+                parse_filter_info = vp56_rac_get(c);
+        }
     }
 
     if (parse_filter_info) {
         if (vp56_rac_get(c)) {
             s->filter_mode = 2;
-            s->sample_variance_threshold = vp56_rac_gets(c, 5);
+            s->sample_variance_threshold = vp56_rac_gets(c, 5) << vrt_shift;
             s->max_vector_length = 2 << vp56_rac_gets(c, 3);
         } else if (vp56_rac_get(c)) {
             s->filter_mode = 1;
         } else {
             s->filter_mode = 0;
         }
-        s->filter_selection = vp56_rac_gets(c, 4);
+        if (s->sub_version > 7)
+            s->filter_selection = vp56_rac_gets(c, 4);
+        else
+            s->filter_selection = 16;
     }
 
     vp56_rac_get(c);
+
+    if (coeff_offset) {
+        vp56_init_range_decoder(&s->cc, buf+coeff_offset,
+                                buf_size-coeff_offset);
+        s->ccp = &s->cc;
+    } else {
+        s->ccp = &s->c;
+    }
+
     return res;
 }
 
@@ -161,7 +205,7 @@ static void vp6_parse_coeff_models(vp56_context_t *s)
             if (vp56_rac_get_prob(c, vp6_dccv_pct[pt][node])) {
                 def_prob[node] = vp56_rac_gets_nn(c, 7);
                 s->coeff_model_dccv[pt][node] = def_prob[node];
-            } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+            } else if (s->framep[VP56_FRAME_CURRENT]->key_frame) {
                 s->coeff_model_dccv[pt][node] = def_prob[node];
             }
 
@@ -184,7 +228,7 @@ static void vp6_parse_coeff_models(vp56_context_t *s)
                     if (vp56_rac_get_prob(c, vp6_ract_pct[ct][pt][cg][node])) {
                         def_prob[node] = vp56_rac_gets_nn(c, 7);
                         s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
-                    } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+                    } else if (s->framep[VP56_FRAME_CURRENT]->key_frame) {
                         s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
                     }
 
@@ -192,17 +236,17 @@ static void vp6_parse_coeff_models(vp56_context_t *s)
     for (pt=0; pt<2; pt++)
         for (ctx=0; ctx<3; ctx++)
             for (node=0; node<5; node++)
-                s->coeff_model_dcct[pt][ctx][node] = clip(((s->coeff_model_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255);
+                s->coeff_model_dcct[pt][ctx][node] = av_clip(((s->coeff_model_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255);
 }
 
-static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vector)
+static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vect)
 {
     vp56_range_coder_t *c = &s->c;
     int comp;
 
-    *vector = (vp56_mv_t) {0,0};
+    *vect = (vp56_mv_t) {0,0};
     if (s->vector_candidate_pos < 2)
-        *vector = s->vector_candidate[0];
+        *vect = s->vector_candidate[0];
 
     for (comp=0; comp<2; comp++) {
         int i, delta = 0;
@@ -226,15 +270,15 @@ static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vector)
             delta = -delta;
 
         if (!comp)
-            vector->x += delta;
+            vect->x += delta;
         else
-            vector->y += delta;
+            vect->y += delta;
     }
 }
 
 static void vp6_parse_coeff(vp56_context_t *s)
 {
-    vp56_range_coder_t *c = &s->c;
+    vp56_range_coder_t *c = s->ccp;
     uint8_t *permute = s->scantable.permutated;
     uint8_t *model, *model2, *model3;
     int coeff, sign, coeff_idx;
@@ -333,7 +377,7 @@ static int vp6_block_variance(uint8_t *src, int stride)
         }
         src += 2*stride;
     }
-    return (16*square_sum - sum*sum) / (16*16);
+    return (16*square_sum - sum*sum) >> 8;
 }
 
 static void vp6_filter_hv2(vp56_context_t *s, uint8_t *dst, uint8_t *src,
@@ -351,7 +395,7 @@ static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, int stride,
 
     for (y=0; y<8; y++) {
         for (x=0; x<8; x++) {
-            dst[x] = clip_uint8((  src[x-delta  ] * weights[0]
+            dst[x] = av_clip_uint8((  src[x-delta  ] * weights[0]
                                  + src[x        ] * weights[1]
                                  + src[x+delta  ] * weights[2]
                                  + src[x+2*delta] * weights[3] + 64) >> 7);
@@ -390,7 +434,7 @@ static void vp6_filter_diag4(uint8_t *dst, uint8_t *src, int stride,
 
     for (y=0; y<11; y++) {
         for (x=0; x<8; x++) {
-            t[x] = clip_uint8((  src[x-1] * h_weights[0]
+            t[x] = av_clip_uint8((  src[x-1] * h_weights[0]
                                + src[x  ] * h_weights[1]
                                + src[x+1] * h_weights[2]
                                + src[x+2] * h_weights[3] + 64) >> 7);
@@ -402,7 +446,7 @@ static void vp6_filter_diag4(uint8_t *dst, uint8_t *src, int stride,
     t = tmp + 8;
     for (y=0; y<8; y++) {
         for (x=0; x<8; x++) {
-            dst[x] = clip_uint8((  t[x-8 ] * v_weights[0]
+            dst[x] = av_clip_uint8((  t[x-8 ] * v_weights[0]
                                  + t[x   ] * v_weights[1]
                                  + t[x+8 ] * v_weights[2]
                                  + t[x+16] * v_weights[3] + 64) >> 7);
@@ -426,11 +470,11 @@ static void vp6_filter(vp56_context_t *s, uint8_t *dst, uint8_t *src,
         filter4 = s->filter_mode;
         if (filter4 == 2) {
             if (s->max_vector_length &&
-                (ABS(mv.x) > s->max_vector_length ||
-                 ABS(mv.y) > s->max_vector_length)) {
+                (FFABS(mv.x) > s->max_vector_length ||
+                 FFABS(mv.y) > s->max_vector_length)) {
                 filter4 = 0;
-            } else if (!s->sample_variance_threshold
-                       || (vp6_block_variance(src+offset1, stride)
+            } else if (s->sample_variance_threshold
+                       && (vp6_block_variance(src+offset1, stride)
                            < s->sample_variance_threshold)) {
                 filter4 = 0;
             }