summaryrefslogtreecommitdiff
path: root/libavcodec/vp9.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/vp9.c')
-rw-r--r--libavcodec/vp9.c1732
1 files changed, 816 insertions, 916 deletions
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 906218565e..4d7310f6d4 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -4,43 +4,45 @@
* Copyright (C) 2013 Ronald S. Bultje <rsbultje gmail com>
* Copyright (C) 2013 Clément Bœsch <u pkh me>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * 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.
*
- * Libav 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "libavutil/avassert.h"
-
#include "avcodec.h"
#include "get_bits.h"
#include "internal.h"
+#include "profiles.h"
+#include "thread.h"
#include "videodsp.h"
#include "vp56.h"
#include "vp9.h"
#include "vp9data.h"
+#include "vp9dec.h"
+#include "libavutil/avassert.h"
+#include "libavutil/pixdesc.h"
#define VP9_SYNCCODE 0x498342
-#define MAX_PROB 255
static void vp9_frame_unref(AVCodecContext *avctx, VP9Frame *f)
{
ff_thread_release_buffer(avctx, &f->tf);
- av_buffer_unref(&f->segmentation_map_buf);
- av_buffer_unref(&f->mv_buf);
+ av_buffer_unref(&f->extradata);
+ av_buffer_unref(&f->hwaccel_priv_buf);
f->segmentation_map = NULL;
- f->mv = NULL;
+ f->hwaccel_picture_private = NULL;
}
static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f)
@@ -53,139 +55,205 @@ static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f)
return ret;
sz = 64 * s->sb_cols * s->sb_rows;
- f->segmentation_map_buf = av_buffer_allocz(sz * sizeof(*f->segmentation_map));
- f->mv_buf = av_buffer_allocz(sz * sizeof(*f->mv));
- if (!f->segmentation_map_buf || !f->mv_buf) {
- vp9_frame_unref(avctx, f);
- return AVERROR(ENOMEM);
+ f->extradata = av_buffer_allocz(sz * (1 + sizeof(VP9mvrefPair)));
+ if (!f->extradata) {
+ goto fail;
}
- f->segmentation_map = f->segmentation_map_buf->data;
- f->mv = (VP9MVRefPair*)f->mv_buf->data;
-
- if (s->segmentation.enabled && !s->segmentation.update_map &&
- !s->keyframe && !s->intraonly && !s->errorres)
- memcpy(f->segmentation_map, s->frames[LAST_FRAME].segmentation_map, sz);
+ f->segmentation_map = f->extradata->data;
+ f->mv = (VP9mvrefPair *) (f->extradata->data + sz);
+
+ if (avctx->hwaccel) {
+ const AVHWAccel *hwaccel = avctx->hwaccel;
+ av_assert0(!f->hwaccel_picture_private);
+ if (hwaccel->frame_priv_data_size) {
+ f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
+ if (!f->hwaccel_priv_buf)
+ goto fail;
+ f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
+ }
+ }
return 0;
+
+fail:
+ vp9_frame_unref(avctx, f);
+ return AVERROR(ENOMEM);
}
-static int vp9_frame_ref(VP9Frame *dst, VP9Frame *src)
+static int vp9_frame_ref(AVCodecContext *avctx, VP9Frame *dst, VP9Frame *src)
{
int ret;
- dst->segmentation_map_buf = av_buffer_ref(src->segmentation_map_buf);
- dst->mv_buf = av_buffer_ref(src->mv_buf);
- if (!dst->segmentation_map_buf || !dst->mv_buf) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
ret = ff_thread_ref_frame(&dst->tf, &src->tf);
if (ret < 0)
+ return ret;
+
+ dst->extradata = av_buffer_ref(src->extradata);
+ if (!dst->extradata)
goto fail;
dst->segmentation_map = src->segmentation_map;
- dst->mv = src->mv;
+ dst->mv = src->mv;
+ dst->uses_2pass = src->uses_2pass;
+
+ if (src->hwaccel_picture_private) {
+ dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
+ if (!dst->hwaccel_priv_buf)
+ goto fail;
+ dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
+ }
return 0;
+
fail:
- av_buffer_unref(&dst->segmentation_map_buf);
- av_buffer_unref(&dst->mv_buf);
- return ret;
+ vp9_frame_unref(avctx, dst);
+ return AVERROR(ENOMEM);
}
-static void vp9_decode_flush(AVCodecContext *avctx)
+static int update_size(AVCodecContext *avctx, int w, int h)
{
+#define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + CONFIG_VP9_D3D11VA_HWACCEL + CONFIG_VP9_VAAPI_HWACCEL)
+ enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts;
VP9Context *s = avctx->priv_data;
- int i;
+ uint8_t *p;
+ int bytesperpixel = s->bytesperpixel, ret, cols, rows;
- for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++)
- vp9_frame_unref(avctx, &s->frames[i]);
+ av_assert0(w > 0 && h > 0);
- for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++)
- ff_thread_release_buffer(avctx, &s->refs[i]);
+ if (!(s->pix_fmt == s->gf_fmt && w == s->w && h == s->h)) {
+ if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
+ return ret;
- s->use_last_frame_mvs = 0;
+ switch (s->pix_fmt) {
+ case AV_PIX_FMT_YUV420P:
+#if CONFIG_VP9_DXVA2_HWACCEL
+ *fmtp++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_VP9_D3D11VA_HWACCEL
+ *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_VP9_VAAPI_HWACCEL
+ *fmtp++ = AV_PIX_FMT_VAAPI;
+#endif
+ break;
+ case AV_PIX_FMT_YUV420P10:
+ case AV_PIX_FMT_YUV420P12:
+#if CONFIG_VP9_VAAPI_HWACCEL
+ *fmtp++ = AV_PIX_FMT_VAAPI;
+#endif
+ break;
+ }
- s->alloc_width = 0;
- s->alloc_height = 0;
-}
+ *fmtp++ = s->pix_fmt;
+ *fmtp = AV_PIX_FMT_NONE;
-static int update_size(AVCodecContext *avctx, int w, int h)
-{
- VP9Context *s = avctx->priv_data;
- uint8_t *p;
- int nb_blocks, nb_superblocks;
+ ret = ff_thread_get_format(avctx, pix_fmts);
+ if (ret < 0)
+ return ret;
- if (s->above_partition_ctx && w == s->alloc_width && h == s->alloc_height)
- return 0;
+ avctx->pix_fmt = ret;
+ s->gf_fmt = s->pix_fmt;
+ s->w = w;
+ s->h = h;
+ }
- vp9_decode_flush(avctx);
+ cols = (w + 7) >> 3;
+ rows = (h + 7) >> 3;
- if (w <= 0 || h <= 0)
- return AVERROR_INVALIDDATA;
+ if (s->intra_pred_data[0] && cols == s->cols && rows == s->rows && s->pix_fmt == s->last_fmt)
+ return 0;
- avctx->width = w;
- avctx->height = h;
- s->sb_cols = (w + 63) >> 6;
- s->sb_rows = (h + 63) >> 6;
- s->cols = (w + 7) >> 3;
- s->rows = (h + 7) >> 3;
-
-#define assign(var, type, n) var = (type)p; p += s->sb_cols * n * sizeof(*var)
- av_free(s->above_partition_ctx);
- p = av_malloc(s->sb_cols *
- (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx)));
+ s->last_fmt = s->pix_fmt;
+ s->sb_cols = (w + 63) >> 6;
+ s->sb_rows = (h + 63) >> 6;
+ s->cols = (w + 7) >> 3;
+ s->rows = (h + 7) >> 3;
+
+#define assign(var, type, n) var = (type) p; p += s->sb_cols * (n) * sizeof(*var)
+ av_freep(&s->intra_pred_data[0]);
+ // FIXME we slightly over-allocate here for subsampled chroma, but a little
+ // bit of padding shouldn't affect performance...
+ p = av_malloc(s->sb_cols * (128 + 192 * bytesperpixel +
+ sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx)));
if (!p)
return AVERROR(ENOMEM);
- assign(s->above_partition_ctx, uint8_t *, 8);
- assign(s->above_skip_ctx, uint8_t *, 8);
- assign(s->above_txfm_ctx, uint8_t *, 8);
- assign(s->above_mode_ctx, uint8_t *, 16);
- assign(s->above_y_nnz_ctx, uint8_t *, 16);
- assign(s->above_uv_nnz_ctx[0], uint8_t *, 8);
- assign(s->above_uv_nnz_ctx[1], uint8_t *, 8);
- assign(s->intra_pred_data[0], uint8_t *, 64);
- assign(s->intra_pred_data[1], uint8_t *, 32);
- assign(s->intra_pred_data[2], uint8_t *, 32);
- assign(s->above_segpred_ctx, uint8_t *, 8);
- assign(s->above_intra_ctx, uint8_t *, 8);
- assign(s->above_comp_ctx, uint8_t *, 8);
- assign(s->above_ref_ctx, uint8_t *, 8);
- assign(s->above_filter_ctx, uint8_t *, 8);
- assign(s->lflvl, VP9Filter *, 1);
- assign(s->above_mv_ctx, VP56mv(*)[2], 16);
+ assign(s->intra_pred_data[0], uint8_t *, 64 * bytesperpixel);
+ assign(s->intra_pred_data[1], uint8_t *, 64 * bytesperpixel);
+ assign(s->intra_pred_data[2], uint8_t *, 64 * bytesperpixel);
+ assign(s->above_y_nnz_ctx, uint8_t *, 16);
+ assign(s->above_mode_ctx, uint8_t *, 16);
+ assign(s->above_mv_ctx, VP56mv(*)[2], 16);
+ assign(s->above_uv_nnz_ctx[0], uint8_t *, 16);
+ assign(s->above_uv_nnz_ctx[1], uint8_t *, 16);
+ assign(s->above_partition_ctx, uint8_t *, 8);
+ assign(s->above_skip_ctx, uint8_t *, 8);
+ assign(s->above_txfm_ctx, uint8_t *, 8);
+ assign(s->above_segpred_ctx, uint8_t *, 8);
+ assign(s->above_intra_ctx, uint8_t *, 8);
+ assign(s->above_comp_ctx, uint8_t *, 8);
+ assign(s->above_ref_ctx, uint8_t *, 8);
+ assign(s->above_filter_ctx, uint8_t *, 8);
+ assign(s->lflvl, VP9Filter *, 1);
#undef assign
+ // these will be re-allocated a little later
av_freep(&s->b_base);
av_freep(&s->block_base);
- if (avctx->active_thread_type & FF_THREAD_FRAME) {
- nb_blocks = s->cols * s->rows;
- nb_superblocks = s->sb_cols * s->sb_rows;
- } else {
- nb_blocks = nb_superblocks = 1;
+ if (s->s.h.bpp != s->last_bpp) {
+ ff_vp9dsp_init(&s->dsp, s->s.h.bpp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ ff_videodsp_init(&s->vdsp, s->s.h.bpp);
+ s->last_bpp = s->s.h.bpp;
}
- s->b_base = av_malloc_array(nb_blocks, sizeof(*s->b_base));
- s->block_base = av_mallocz_array(nb_superblocks, (64 * 64 + 128) * 3);
- if (!s->b_base || !s->block_base)
- return AVERROR(ENOMEM);
- s->uvblock_base[0] = s->block_base + nb_superblocks * 64 * 64;
- s->uvblock_base[1] = s->uvblock_base[0] + nb_superblocks * 32 * 32;
- s->eob_base = (uint8_t *)(s->uvblock_base[1] + nb_superblocks * 32 * 32);
- s->uveob_base[0] = s->eob_base + nb_superblocks * 256;
- s->uveob_base[1] = s->uveob_base[0] + nb_superblocks * 64;
+ return 0;
+}
+
+static int update_block_buffers(AVCodecContext *avctx)
+{
+ VP9Context *s = avctx->priv_data;
+ int chroma_blocks, chroma_eobs, bytesperpixel = s->bytesperpixel;
- s->alloc_width = w;
- s->alloc_height = h;
+ if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->s.frames[CUR_FRAME].uses_2pass)
+ return 0;
+
+ av_free(s->b_base);
+ av_free(s->block_base);
+ chroma_blocks = 64 * 64 >> (s->ss_h + s->ss_v);
+ chroma_eobs = 16 * 16 >> (s->ss_h + s->ss_v);
+ if (s->s.frames[CUR_FRAME].uses_2pass) {
+ int sbs = s->sb_cols * s->sb_rows;
+
+ s->b_base = av_malloc_array(s->cols * s->rows, sizeof(VP9Block));
+ s->block_base = av_mallocz(((64 * 64 + 2 * chroma_blocks) * bytesperpixel * sizeof(int16_t) +
+ 16 * 16 + 2 * chroma_eobs) * sbs);
+ if (!s->b_base || !s->block_base)
+ return AVERROR(ENOMEM);
+ s->uvblock_base[0] = s->block_base + sbs * 64 * 64 * bytesperpixel;
+ s->uvblock_base[1] = s->uvblock_base[0] + sbs * chroma_blocks * bytesperpixel;
+ s->eob_base = (uint8_t *) (s->uvblock_base[1] + sbs * chroma_blocks * bytesperpixel);
+ s->uveob_base[0] = s->eob_base + 16 * 16 * sbs;
+ s->uveob_base[1] = s->uveob_base[0] + chroma_eobs * sbs;
+ } else {
+ s->b_base = av_malloc(sizeof(VP9Block));
+ s->block_base = av_mallocz((64 * 64 + 2 * chroma_blocks) * bytesperpixel * sizeof(int16_t) +
+ 16 * 16 + 2 * chroma_eobs);
+ if (!s->b_base || !s->block_base)
+ return AVERROR(ENOMEM);
+ s->uvblock_base[0] = s->block_base + 64 * 64 * bytesperpixel;
+ s->uvblock_base[1] = s->uvblock_base[0] + chroma_blocks * bytesperpixel;
+ s->eob_base = (uint8_t *) (s->uvblock_base[1] + chroma_blocks * bytesperpixel);
+ s->uveob_base[0] = s->eob_base + 16 * 16;
+ s->uveob_base[1] = s->uveob_base[0] + chroma_eobs;
+ }
+ s->block_alloc_using_2pass = s->s.frames[CUR_FRAME].uses_2pass;
return 0;
}
// The sign bit is at the end, not the start, of a bit sequence
-static av_always_inline int get_bits_with_sign(GetBitContext *gb, int n)
+static av_always_inline int get_sbits_inv(GetBitContext *gb, int n)
{
int v = get_bits(gb, n);
return get_bits1(gb) ? -v : v;
@@ -203,7 +271,7 @@ static av_always_inline int inv_recenter_nonneg(int v, int m)
// differential forward probability updates
static int update_prob(VP56RangeCoder *c, int p)
{
- static const int inv_map_table[MAX_PROB - 1] = {
+ static const int inv_map_table[255] = {
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176,
189, 202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24,
@@ -222,7 +290,7 @@ static int update_prob(VP56RangeCoder *c, int p)
207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221,
222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
- 252, 253,
+ 252, 253, 253,
};
int d;
@@ -249,16 +317,76 @@ static int update_prob(VP56RangeCoder *c, int p)
d = vp8_rac_get_uint(c, 5) + 32;
} else {
d = vp8_rac_get_uint(c, 7);
- if (d >= 65) {
+ if (d >= 65)
d = (d << 1) - 65 + vp8_rac_get(c);
- d = av_clip(d, 0, MAX_PROB - 65 - 1);
- }
d += 64;
+ av_assert2(d < FF_ARRAY_ELEMS(inv_map_table));
}
- return p <= 128
- ? 1 + inv_recenter_nonneg(inv_map_table[d], p - 1)
- : 255 - inv_recenter_nonneg(inv_map_table[d], 255 - p);
+ return p <= 128 ? 1 + inv_recenter_nonneg(inv_map_table[d], p - 1) :
+ 255 - inv_recenter_nonneg(inv_map_table[d], 255 - p);
+}
+
+static int read_colorspace_details(AVCodecContext *avctx)
+{
+ static const enum AVColorSpace colorspaces[8] = {
+ AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M,
+ AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB,
+ };
+ VP9Context *s = avctx->priv_data;
+ int bits = avctx->profile <= 1 ? 0 : 1 + get_bits1(&s->gb); // 0:8, 1:10, 2:12
+
+ s->bpp_index = bits;
+ s->s.h.bpp = 8 + bits * 2;
+ s->bytesperpixel = (7 + s->s.h.bpp) >> 3;
+ avctx->colorspace = colorspaces[get_bits(&s->gb, 3)];
+ if (avctx->colorspace == AVCOL_SPC_RGB) { // RGB = profile 1
+ static const enum AVPixelFormat pix_fmt_rgb[3] = {
+ AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12
+ };
+ s->ss_h = s->ss_v = 0;
+ avctx->color_range = AVCOL_RANGE_JPEG;
+ s->pix_fmt = pix_fmt_rgb[bits];
+ if (avctx->profile & 1) {
+ if (get_bits1(&s->gb)) {
+ av_log(avctx, AV_LOG_ERROR, "Reserved bit set in RGB\n");
+ return AVERROR_INVALIDDATA;
+ }
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "RGB not supported in profile %d\n",
+ avctx->profile);
+ return AVERROR_INVALIDDATA;
+ }
+ } else {
+ static const enum AVPixelFormat pix_fmt_for_ss[3][2 /* v */][2 /* h */] = {
+ { { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P },
+ { AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV420P } },
+ { { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10 },
+ { AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P10 } },
+ { { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12 },
+ { AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P12 } }
+ };
+ avctx->color_range = get_bits1(&s->gb) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
+ if (avctx->profile & 1) {
+ s->ss_h = get_bits1(&s->gb);
+ s->ss_v = get_bits1(&s->gb);
+ s->pix_fmt = pix_fmt_for_ss[bits][s->ss_v][s->ss_h];
+ if (s->pix_fmt == AV_PIX_FMT_YUV420P) {
+ av_log(avctx, AV_LOG_ERROR, "YUV 4:2:0 not supported in profile %d\n",
+ avctx->profile);
+ return AVERROR_INVALIDDATA;
+ } else if (get_bits1(&s->gb)) {
+ av_log(avctx, AV_LOG_ERROR, "Profile %d color details reserved bit set\n",
+ avctx->profile);
+ return AVERROR_INVALIDDATA;
+ }
+ } else {
+ s->ss_h = s->ss_v = 1;
+ s->pix_fmt = pix_fmt_for_ss[bits][1][1];
+ }
+ }
+
+ return 0;
}
static int decode_frame_header(AVCodecContext *avctx,
@@ -278,273 +406,302 @@ static int decode_frame_header(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "Invalid frame marker\n");
return AVERROR_INVALIDDATA;
}
- s->profile = get_bits1(&s->gb);
- if (get_bits1(&s->gb)) { // reserved bit
- av_log(avctx, AV_LOG_ERROR, "Reserved bit should be zero\n");
+ avctx->profile = get_bits1(&s->gb);
+ avctx->profile |= get_bits1(&s->gb) << 1;
+ if (avctx->profile == 3) avctx->profile += get_bits1(&s->gb);
+ if (avctx->profile > 3) {
+ av_log(avctx, AV_LOG_ERROR, "Profile %d is not yet supported\n", avctx->profile);
return AVERROR_INVALIDDATA;
}
+ s->s.h.profile = avctx->profile;
if (get_bits1(&s->gb)) {
*ref = get_bits(&s->gb, 3);
return 0;
}
- s->last_keyframe = s->keyframe;
- s->keyframe = !get_bits1(&s->gb);
+ s->last_keyframe = s->s.h.keyframe;
+ s->s.h.keyframe = !get_bits1(&s->gb);
- last_invisible = s->invisible;
- s->invisible = !get_bits1(&s->gb);
- s->errorres = get_bits1(&s->gb);
- s->use_last_frame_mvs = !s->errorres && !last_invisible;
+ last_invisible = s->s.h.invisible;
+ s->s.h.invisible = !get_bits1(&s->gb);
+ s->s.h.errorres = get_bits1(&s->gb);
+ s->s.h.use_last_frame_mvs = !s->s.h.errorres && !last_invisible;
- if (s->keyframe) {
+ if (s->s.h.keyframe) {
if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode
av_log(avctx, AV_LOG_ERROR, "Invalid sync code\n");
return AVERROR_INVALIDDATA;
}
- s->colorspace = get_bits(&s->gb, 3);
- if (s->colorspace == 7) { // RGB = profile 1
- av_log(avctx, AV_LOG_ERROR, "RGB not supported in profile 0\n");
- return AVERROR_INVALIDDATA;
- }
- s->fullrange = get_bits1(&s->gb);
-
- // subsampling bits
- if (s->profile == 1 || s->profile == 3) {
- s->sub_x = get_bits1(&s->gb);
- s->sub_y = get_bits1(&s->gb);
- if (s->sub_x && s->sub_y) {
- av_log(avctx, AV_LOG_ERROR,
- "4:2:0 color not supported in profile 1 or 3\n");
- return AVERROR_INVALIDDATA;
- }
- if (get_bits1(&s->gb)) { // reserved bit
- av_log(avctx, AV_LOG_ERROR, "Reserved bit should be zero\n");
- return AVERROR_INVALIDDATA;
- }
- } else {
- s->sub_x = s->sub_y = 1;
- }
- if (!s->sub_x || !s->sub_y) {
- avpriv_report_missing_feature(avctx, "Subsampling %d:%d",
- s->sub_x, s->sub_y);
- return AVERROR_PATCHWELCOME;
- }
-
- s->refreshrefmask = 0xff;
+ if ((ret = read_colorspace_details(avctx)) < 0)
+ return ret;
+ // for profile 1, here follows the subsampling bits
+ s->s.h.refreshrefmask = 0xff;
w = get_bits(&s->gb, 16) + 1;
h = get_bits(&s->gb, 16) + 1;
if (get_bits1(&s->gb)) // display size
skip_bits(&s->gb, 32);
} else {
- s->intraonly = s->invisible ? get_bits1(&s->gb) : 0;
- s->resetctx = s->errorres ? 0 : get_bits(&s->gb, 2);
- if (s->intraonly) {
+ s->s.h.intraonly = s->s.h.invisible ? get_bits1(&s->gb) : 0;
+ s->s.h.resetctx = s->s.h.errorres ? 0 : get_bits(&s->gb, 2);
+ if (s->s.h.intraonly) {
if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode
av_log(avctx, AV_LOG_ERROR, "Invalid sync code\n");
return AVERROR_INVALIDDATA;
}
- s->refreshrefmask = get_bits(&s->gb, 8);
+ if (avctx->profile >= 1) {
+ if ((ret = read_colorspace_details(avctx)) < 0)
+ return ret;
+ } else {
+ s->ss_h = s->ss_v = 1;
+ s->s.h.bpp = 8;
+ s->bpp_index = 0;
+ s->bytesperpixel = 1;
+ s->pix_fmt = AV_PIX_FMT_YUV420P;
+ avctx->colorspace = AVCOL_SPC_BT470BG;
+ avctx->color_range = AVCOL_RANGE_JPEG;
+ }
+ s->s.h.refreshrefmask = get_bits(&s->gb, 8);
w = get_bits(&s->gb, 16) + 1;
h = get_bits(&s->gb, 16) + 1;
if (get_bits1(&s->gb)) // display size
skip_bits(&s->gb, 32);
} else {
- s->refreshrefmask = get_bits(&s->gb, 8);
- s->refidx[0] = get_bits(&s->gb, 3);
- s->signbias[0] = get_bits1(&s->gb);
- s->refidx[1] = get_bits(&s->gb, 3);
- s->signbias[1] = get_bits1(&s->gb);
- s->refidx[2] = get_bits(&s->gb, 3);
- s->signbias[2] = get_bits1(&s->gb);
- if (!s->refs[s->refidx[0]].f->buf[0] ||
- !s->refs[s->refidx[1]].f->buf[0] ||
- !s->refs[s->refidx[2]].f->buf[0]) {
- av_log(avctx, AV_LOG_ERROR,
- "Not all references are available\n");
+ s->s.h.refreshrefmask = get_bits(&s->gb, 8);
+ s->s.h.refidx[0] = get_bits(&s->gb, 3);
+ s->s.h.signbias[0] = get_bits1(&s->gb) && !s->s.h.errorres;
+ s->s.h.refidx[1] = get_bits(&s->gb, 3);
+ s->s.h.signbias[1] = get_bits1(&s->gb) && !s->s.h.errorres;
+ s->s.h.refidx[2] = get_bits(&s->gb, 3);
+ s->s.h.signbias[2] = get_bits1(&s->gb) && !s->s.h.errorres;
+ if (!s->s.refs[s->s.h.refidx[0]].f->buf[0] ||
+ !s->s.refs[s->s.h.refidx[1]].f->buf[0] ||
+ !s->s.refs[s->s.h.refidx[2]].f->buf[0]) {
+ av_log(avctx, AV_LOG_ERROR, "Not all references are available\n");
return AVERROR_INVALIDDATA;
}
if (get_bits1(&s->gb)) {
- w = s->refs[s->refidx[0]].f->width;
- h = s->refs[s->refidx[0]].f->height;
+ w = s->s.refs[s->s.h.refidx[0]].f->width;
+ h = s->s.refs[s->s.h.refidx[0]].f->height;
} else if (get_bits1(&s->gb)) {
- w = s->refs[s->refidx[1]].f->width;
- h = s->refs[s->refidx[1]].f->height;
+ w = s->s.refs[s->s.h.refidx[1]].f->width;
+ h = s->s.refs[s->s.h.refidx[1]].f->height;
} else if (get_bits1(&s->gb)) {
- w = s->refs[s->refidx[2]].f->width;
- h = s->refs[s->refidx[2]].f->height;
+ w = s->s.refs[s->s.h.refidx[2]].f->width;
+ h = s->s.refs[s->s.h.refidx[2]].f->height;
} else {
w = get_bits(&s->gb, 16) + 1;
h = get_bits(&s->gb, 16) + 1;
}
+ // Note that in this code, "CUR_FRAME" is actually before we
+ // have formally allocated a frame, and thus actually represents
+ // the _last_ frame
+ s->s.h.use_last_frame_mvs &= s->s.frames[CUR_FRAME].tf.f->width == w &&
+ s->s.frames[CUR_FRAME].tf.f->height == h;
if (get_bits1(&s->gb)) // display size
skip_bits(&s->gb, 32);
- s->highprecisionmvs = get_bits1(&s->gb);
- s->filtermode = get_bits1(&s->gb) ? FILTER_SWITCHABLE :
- get_bits(&s->gb, 2);
- s->allowcompinter = s->signbias[0] != s->signbias[1] ||
- s->signbias[0] != s->signbias[2];
- if (s->allowcompinter) {
- if (s->signbias[0] == s->signbias[1]) {
- s->fixcompref = 2;
- s->varcompref[0] = 0;
- s->varcompref[1] = 1;
- } else if (s->signbias[0] == s->signbias[2]) {
- s->fixcompref = 1;
- s->varcompref[0] = 0;
- s->varcompref[1] = 2;
+ s->s.h.highprecisionmvs = get_bits1(&s->gb);
+ s->s.h.filtermode = get_bits1(&s->gb) ? FILTER_SWITCHABLE :
+ get_bits(&s->gb, 2);
+ s->s.h.allowcompinter = s->s.h.signbias[0] != s->s.h.signbias[1] ||
+ s->s.h.signbias[0] != s->s.h.signbias[2];
+ if (s->s.h.allowcompinter) {
+ if (s->s.h.signbias[0] == s->s.h.signbias[1]) {
+ s->s.h.fixcompref = 2;
+ s->s.h.varcompref[0] = 0;
+ s->s.h.varcompref[1] = 1;
+ } else if (s->s.h.signbias[0] == s->s.h.signbias[2]) {
+ s->s.h.fixcompref = 1;
+ s->s.h.varcompref[0] = 0;
+ s->s.h.varcompref[1] = 2;
} else {
- s->fixcompref = 0;
- s->varcompref[0] = 1;
- s->varcompref[1] = 2;
+ s->s.h.fixcompref = 0;
+ s->s.h.varcompref[0] = 1;
+ s->s.h.varcompref[1] = 2;
}
}
}
}
-
- s->refreshctx = s->errorres ? 0 : get_bits1(&s->gb);
- s->parallelmode = s->errorres ? 1 : get_bits1(&s->gb);
- s->framectxid = c = get_bits(&s->gb, 2);
+ s->s.h.refreshctx = s->s.h.errorres ? 0 : get_bits1(&s->gb);
+ s->s.h.parallelmode = s->s.h.errorres ? 1 : get_bits1(&s->gb);
+ s->s.h.framectxid = c = get_bits(&s->gb, 2);
+ if (s->s.h.keyframe || s->s.h.intraonly)
+ s->s.h.framectxid = 0; // BUG: libvpx ignores this field in keyframes
/* loopfilter header data */
- s->filter.level = get_bits(&s->gb, 6);
- sharp = get_bits(&s->gb, 3);
- /* If sharpness changed, reinit lim/mblim LUTs. if it didn't change,
- * keep the old cache values since they are still valid. */
- if (s->filter.sharpness != sharp)
- memset(s->filter.lim_lut, 0, sizeof(s->filter.lim_lut));
- s->filter.sharpness = sharp;
- if ((s->lf_delta.enabled = get_bits1(&s->gb))) {
- if (get_bits1(&s->gb)) {
+ if (s->s.h.keyframe || s->s.h.errorres || s->s.h.intraonly) {
+ // reset loopfilter defaults
+ s->s.h.lf_delta.ref[0] = 1;
+ s->s.h.lf_delta.ref[1] = 0;
+ s->s.h.lf_delta.ref[2] = -1;
+ s->s.h.lf_delta.ref[3] = -1;
+ s->s.h.lf_delta.mode[0] = 0;
+ s->s.h.lf_delta.mode[1] = 0;
+ memset(s->s.h.segmentation.feat, 0, sizeof(s->s.h.segmentation.feat));
+ }
+ s->s.h.filter.level = get_bits(&s->gb, 6);
+ sharp = get_bits(&s->gb, 3);
+ // if sharpness changed, reinit lim/mblim LUTs. if it didn't change, keep
+ // the old cache values since they are still valid
+ if (s->s.h.filter.sharpness != sharp)
+ memset(s->filter_lut.lim_lut, 0, sizeof(s->filter_lut.lim_lut));
+ s->s.h.filter.sharpness = sharp;
+ if ((s->s.h.lf_delta.enabled = get_bits1(&s->gb))) {
+ if ((s->s.h.lf_delta.updated = get_bits1(&s->gb))) {
for (i = 0; i < 4; i++)
if (get_bits1(&s->gb))
- s->lf_delta.ref[i] = get_bits_with_sign(&s->gb, 6);
+ s->s.h.lf_delta.ref[i] = get_sbits_inv(&s->gb, 6);
for (i = 0; i < 2; i++)
if (get_bits1(&s->gb))
- s->lf_delta.mode[i] = get_bits_with_sign(&s->gb, 6);
+ s->s.h.lf_delta.mode[i] = get_sbits_inv(&s->gb, 6);
}
- } else {
- memset(&s->lf_delta, 0, sizeof(s->lf_delta));
}
/* quantization header data */
- s->yac_qi = get_bits(&s->gb, 8);
- s->ydc_qdelta = get_bits1(&s->gb) ? get_bits_with_sign(&s->gb, 4) : 0;
- s->uvdc_qdelta = get_bits1(&s->gb) ? get_bits_with_sign(&s->gb, 4) : 0;
- s->uvac_qdelta = get_bits1(&s->gb) ? get_bits_with_sign(&s->gb, 4) : 0;
- s->lossless = s->yac_qi == 0 && s->ydc_qdelta == 0 &&
- s->uvdc_qdelta == 0 && s->uvac_qdelta == 0;
+ s->s.h.yac_qi = get_bits(&s->gb, 8);
+ s->s.h.ydc_qdelta = get_bits1(&s->gb) ? get_sbits_inv(&s->gb, 4) : 0;
+ s->s.h.uvdc_qdelta = get_bits1(&s->gb) ? get_sbits_inv(&s->gb, 4) : 0;
+ s->s.h.uvac_qdelta = get_bits1(&s->gb) ? get_sbits_inv(&s->gb, 4) : 0;
+ s->s.h.lossless = s->s.h.yac_qi == 0 && s->s.h.ydc_qdelta == 0 &&
+ s->s.h.uvdc_qdelta == 0 && s->s.h.uvac_qdelta == 0;
+ if (s->s.h.lossless)
+ avctx->properties |= FF_CODEC_PROPERTY_LOSSLESS;
/* segmentation header info */
- if ((s->segmentation.enabled = get_bits1(&s->gb))) {
- if ((s->segmentation.update_map = get_bits1(&s->gb))) {
+ if ((s->s.h.segmentation.enabled = get_bits1(&s->gb))) {
+ if ((s->s.h.segmentation.update_map = get_bits1(&s->gb))) {
for (i = 0; i < 7; i++)
- s->prob.seg[i] = get_bits1(&s->gb) ?
+ s->s.h.segmentation.prob[i] = get_bits1(&s->gb) ?
get_bits(&s->gb, 8) : 255;
- if ((s->segmentation.temporal = get_bits1(&s->gb)))
+ if ((s->s.h.segmentation.temporal = get_bits1(&s->gb)))
for (i = 0; i < 3; i++)
- s->prob.segpred[i] = get_bits1(&s->gb) ?
+ s->s.h.segmentation.pred_prob[i] = get_bits1(&s->gb) ?
get_bits(&s->gb, 8) : 255;
}
if (get_bits1(&s->gb)) {
- s->segmentation.absolute_vals = get_bits1(&s->gb);
+ s->s.h.segmentation.absolute_vals = get_bits1(&s->gb);
for (i = 0; i < 8; i++) {
- if ((s->segmentation.feat[i].q_enabled = get_bits1(&s->gb)))
- s->segmentation.feat[i].q_val = get_bits_with_sign(&s->gb, 8);
- if ((s->segmentation.feat[i].lf_enabled = get_bits1(&s->gb)))
- s->segmentation.feat[i].lf_val = get_bits_with_sign(&s->gb, 6);
- if ((s->segmentation.feat[i].ref_enabled = get_bits1(&s->gb)))
- s->segmentation.feat[i].ref_val = get_bits(&s->gb, 2);
- s->segmentation.feat[i].skip_enabled = get_bits1(&s->gb);
+ if ((s->s.h.segmentation.feat[i].q_enabled = get_bits1(&s->gb)))
+ s->s.h.segmentation.feat[i].q_val = get_sbits_inv(&s->gb, 8);
+ if ((s->s.h.segmentation.feat[i].lf_enabled = get_bits1(&s->gb)))
+ s->s.h.segmentation.feat[i].lf_val = get_sbits_inv(&s->gb, 6);
+ if ((s->s.h.segmentation.feat[i].ref_enabled = get_bits1(&s->gb)))
+ s->s.h.segmentation.feat[i].ref_val = get_bits(&s->gb, 2);
+ s->s.h.segmentation.feat[i].skip_enabled = get_bits1(&s->gb);
}
}
- } else {
- s->segmentation.feat[0].q_enabled = 0;
- s->segmentation.feat[0].lf_enabled = 0;
- s->segmentation.feat[0].skip_enabled = 0;
- s->segmentation.feat[0].ref_enabled = 0;
}
// set qmul[] based on Y/UV, AC/DC and segmentation Q idx deltas
- for (i = 0; i < (s->segmentation.enabled ? 8 : 1); i++) {
+ for (i = 0; i < (s->s.h.segmentation.enabled ? 8 : 1); i++) {
int qyac, qydc, quvac, quvdc, lflvl, sh;
- if (s->segmentation.feat[i].q_enabled) {
- if (s->segmentation.absolute_vals)
- qyac = s->segmentation.feat[i].q_val;
+ if (s->s.h.segmentation.enabled && s->s.h.segmentation.feat[i].q_enabled) {
+ if (s->s.h.segmentation.absolute_vals)
+ qyac = av_clip_uintp2(s->s.h.segmentation.feat[i].q_val, 8);
else
- qyac = s->yac_qi + s->segmentation.feat[i].q_val;
+ qyac = av_clip_uintp2(s->s.h.yac_qi + s->s.h.segmentation.feat[i].q_val, 8);
} else {
- qyac = s->yac_qi;
+ qyac = s->s.h.yac_qi;
}
- qydc = av_clip_uintp2(qyac + s->ydc_qdelta, 8);
- quvdc = av_clip_uintp2(qyac + s->uvdc_qdelta, 8);
- quvac = av_clip_uintp2(qyac + s->uvac_qdelta, 8);
+ qydc = av_clip_uintp2(qyac + s->s.h.ydc_qdelta, 8);
+ quvdc = av_clip_uintp2(qyac + s->s.h.uvdc_qdelta, 8);
+ quvac = av_clip_uintp2(qyac + s->s.h.uvac_qdelta, 8);
qyac = av_clip_uintp2(qyac, 8);
- s->segmentation.feat[i].qmul[0][0] = ff_vp9_dc_qlookup[qydc];
- s->segmentation.feat[i].qmul[0][1] = ff_vp9_ac_qlookup[qyac];
- s->segmentation.feat[i].qmul[1][0] = ff_vp9_dc_qlookup[quvdc];
- s->segmentation.feat[i].qmul[1][1] = ff_vp9_ac_qlookup[quvac];
+ s->s.h.segmentation.feat[i].qmul[0][0] = ff_vp9_dc_qlookup[s->bpp_index][qydc];
+ s->s.h.segmentation.feat[i].qmul[0][1] = ff_vp9_ac_qlookup[s->bpp_index][qyac];
+ s->s.h.segmentation.feat[i].qmul[1][0] = ff_vp9_dc_qlookup[s->bpp_index][quvdc];
+ s->s.h.segmentation.feat[i].qmul[1][1] = ff_vp9_ac_qlookup[s->bpp_index][quvac];
- sh = s->filter.level >= 32;
- if (s->segmentation.feat[i].lf_enabled) {
- if (s->segmentation.absolute_vals)
- lflvl = s->segmentation.feat[i].lf_val;
+ sh = s->s.h.filter.level >= 32;
+ if (s->s.h.segmentation.enabled && s->s.h.segmentation.feat[i].lf_enabled) {
+ if (s->s.h.segmentation.absolute_vals)
+ lflvl = av_clip_uintp2(s->s.h.segmentation.feat[i].lf_val, 6);
else
- lflvl = s->filter.level + s->segmentation.feat[i].lf_val;
+ lflvl = av_clip_uintp2(s->s.h.filter.level + s->s.h.segmentation.feat[i].lf_val, 6);
} else {
- lflvl = s->filter.level;
+ lflvl = s->s.h.filter.level;
}
- s->segmentation.feat[i].lflvl[0][0] =
- s->segmentation.feat[i].lflvl[0][1] =
- av_clip_uintp2(lflvl + (s->lf_delta.ref[0] << sh), 6);
- for (j = 1; j < 4; j++) {
- s->segmentation.feat[i].lflvl[j][0] =
- av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
- s->lf_delta.mode[0]) << sh), 6);
- s->segmentation.feat[i].lflvl[j][1] =
- av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
- s->lf_delta.mode[1]) << sh), 6);
+ if (s->s.h.lf_delta.enabled) {
+ s->s.h.segmentation.feat[i].lflvl[0][0] =
+ s->s.h.segmentation.feat[i].lflvl[0][1] =
+ av_clip_uintp2(lflvl + (s->s.h.lf_delta.ref[0] * (1 << sh)), 6);
+ for (j = 1; j < 4; j++) {
+ s->s.h.segmentation.feat[i].lflvl[j][0] =
+ av_clip_uintp2(lflvl + ((s->s.h.lf_delta.ref[j] +
+ s->s.h.lf_delta.mode[0]) * (1 << sh)), 6);
+ s->s.h.segmentation.feat[i].lflvl[j][1] =
+ av_clip_uintp2(lflvl + ((s->s.h.lf_delta.ref[j] +
+ s->s.h.lf_delta.mode[1]) * (1 << sh)), 6);
+ }
+ } else {
+ memset(s->s.h.segmentation.feat[i].lflvl, lflvl,
+ sizeof(s->s.h.segmentation.feat[i].lflvl));
}
}
/* tiling info */
if ((ret = update_size(avctx, w, h)) < 0) {
- av_log(avctx, AV_LOG_ERROR,
- "Failed to initialize decoder for %dx%d\n", w, h);
+ av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder for %dx%d @ %d\n",
+ w, h, s->pix_fmt);
return ret;
}
- for (s->tiling.log2_tile_cols = 0;
- (s->sb_cols >> s->tiling.log2_tile_cols) > 64;
- s->tiling.log2_tile_cols++) ;
+ for (s->s.h.tiling.log2_tile_cols = 0;
+ s->sb_cols > (64 << s->s.h.tiling.log2_tile_cols);
+ s->s.h.tiling.log2_tile_cols++) ;
for (max = 0; (s->sb_cols >> max) >= 4; max++) ;
max = FFMAX(0, max - 1);
- while (max > s->tiling.log2_tile_cols) {
+ while (max > s->s.h.tiling.log2_tile_cols) {
if (get_bits1(&s->gb))
- s->tiling.log2_tile_cols++;
+ s->s.h.tiling.log2_tile_cols++;
else
break;
}
- s->tiling.log2_tile_rows = decode012(&s->gb);
- s->tiling.tile_rows = 1 << s->tiling.log2_tile_rows;
- if (s->tiling.tile_cols != (1 << s->tiling.log2_tile_cols)) {
- s->tiling.tile_cols = 1 << s->tiling.log2_tile_cols;
- s->c_b = av_fast_realloc(s->c_b, &s->c_b_size,
- sizeof(VP56RangeCoder) *
- s->tiling.tile_cols);
+ s->s.h.tiling.log2_tile_rows = decode012(&s->gb);
+ s->s.h.tiling.tile_rows = 1 << s->s.h.tiling.log2_tile_rows;
+ if (s->s.h.tiling.tile_cols != (1 << s->s.h.tiling.log2_tile_cols)) {
+ s->s.h.tiling.tile_cols = 1 << s->s.h.tiling.log2_tile_cols;
+ s->c_b = av_fast_realloc(s->c_b, &s->c_b_size,
+ sizeof(VP56RangeCoder) * s->s.h.tiling.tile_cols);
if (!s->c_b) {
- av_log(avctx, AV_LOG_ERROR,
- "Ran out of memory during range coder init\n");
+ av_log(avctx, AV_LOG_ERROR, "Ran out of memory during range coder init\n");
return AVERROR(ENOMEM);
}
}
- if (s->keyframe || s->errorres || s->intraonly) {
- s->prob_ctx[0].p =
- s->prob_ctx[1].p =
- s->prob_ctx[2].p =
- s->prob_ctx[3].p = ff_vp9_default_probs;
+ /* check reference frames */
+ if (!s->s.h.keyframe && !s->s.h.intraonly) {
+ for (i = 0; i < 3; i++) {
+ AVFrame *ref = s->s.refs[s->s.h.refidx[i]].f;
+ int refw = ref->width, refh = ref->height;
+
+ if (ref->format != avctx->pix_fmt) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Ref pixfmt (%s) did not match current frame (%s)",
+ av_get_pix_fmt_name(ref->format),
+ av_get_pix_fmt_name(avctx->pix_fmt));
+ return AVERROR_INVALIDDATA;
+ } else if (refw == w && refh == h) {
+ s->mvscale[i][0] = s->mvscale[i][1] = 0;
+ } else {
+ if (w * 2 < refw || h * 2 < refh || w > 16 * refw || h > 16 * refh) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid ref frame dimensions %dx%d for frame size %dx%d\n",
+ refw, refh, w, h);
+ return AVERROR_INVALIDDATA;
+ }
+ s->mvscale[i][0] = (refw << 14) / w;
+ s->mvscale[i][1] = (refh << 14) / h;
+ s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14;
+ s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14;
+ }
+ }
+ }
+
+ if (s->s.h.keyframe || s->s.h.errorres || (s->s.h.intraonly && s->s.h.resetctx == 3)) {
+ s->prob_ctx[0].p = s->prob_ctx[1].p = s->prob_ctx[2].p =
+ s->prob_ctx[3].p = ff_vp9_default_probs;
memcpy(s->prob_ctx[0].coef, ff_vp9_default_coef_probs,
sizeof(ff_vp9_default_coef_probs));
memcpy(s->prob_ctx[1].coef, ff_vp9_default_coef_probs,
@@ -553,41 +710,50 @@ static int decode_frame_header(AVCodecContext *avctx,
sizeof(ff_vp9_default_coef_probs));
memcpy(s->prob_ctx[3].coef, ff_vp9_default_coef_probs,
sizeof(ff_vp9_default_coef_probs));
+ } else if (s->s.h.intraonly && s->s.h.resetctx == 2) {
+ s->prob_ctx[c].p = ff_vp9_default_probs;
+ memcpy(s->prob_ctx[c].coef, ff_vp9_default_coef_probs,
+ sizeof(ff_vp9_default_coef_probs));
}
// next 16 bits is size of the rest of the header (arith-coded)
- size2 = get_bits(&s->gb, 16);
+ s->s.h.compressed_header_size = size2 = get_bits(&s->gb, 16);
+ s->s.h.uncompressed_header_size = (get_bits_count(&s->gb) + 7) / 8;
+
data2 = align_get_bits(&s->gb);
if (size2 > size - (data2 - data)) {
av_log(avctx, AV_LOG_ERROR, "Invalid compressed header size\n");
return AVERROR_INVALIDDATA;
}
- ff_vp56_init_range_decoder(&s->c, data2, size2);
+ ret = ff_vp56_init_range_decoder(&s->c, data2, size2);
+ if (ret < 0)
+ return ret;
+
if (vp56_rac_get_prob_branchy(&s->c, 128)) { // marker bit
av_log(avctx, AV_LOG_ERROR, "Marker bit was set\n");
return AVERROR_INVALIDDATA;
}
- if (s->keyframe || s->intraonly)
- memset(s->counts.coef, 0,
- sizeof(s->counts.coef) + sizeof(s->counts.eob));
- else
+ if (s->s.h.keyframe || s->s.h.intraonly) {
+ memset(s->counts.coef, 0, sizeof(s->counts.coef));
+ memset(s->counts.eob, 0, sizeof(s->counts.eob));
+ } else {
memset(&s->counts, 0, sizeof(s->counts));
-
+ }
/* FIXME is it faster to not copy here, but do it down in the fw updates
* as explicit copies if the fw update is missing (and skip the copy upon
* fw update)? */
s->prob.p = s->prob_ctx[c].p;
// txfm updates
- if (s->lossless) {
- s->txfmmode = TX_4X4;
+ if (s->s.h.lossless) {
+ s->s.h.txfmmode = TX_4X4;
} else {
- s->txfmmode = vp8_rac_get_uint(&s->c, 2);
- if (s->txfmmode == 3)
- s->txfmmode += vp8_rac_get(&s->c);
+ s->s.h.txfmmode = vp8_rac_get_uint(&s->c, 2);
+ if (s->s.h.txfmmode == 3)
+ s->s.h.txfmmode += vp8_rac_get(&s->c);
- if (s->txfmmode == TX_SWITCHABLE) {
+ if (s->s.h.txfmmode == TX_SWITCHABLE) {
for (i = 0; i < 2; i++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.tx8p[i] = update_prob(&s->c, s->prob.p.tx8p[i]);
@@ -637,7 +803,7 @@ static int decode_frame_header(AVCodecContext *avctx,
p[3] = 0;
}
}
- if (s->txfmmode == i)
+ if (s->s.h.txfmmode == i)
break;
}
@@ -645,14 +811,14 @@ static int decode_frame_header(AVCodecContext *avctx,
for (i = 0; i < 3; i++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.skip[i] = update_prob(&s->c, s->prob.p.skip[i]);
- if (!s->keyframe && !s->intraonly) {
+ if (!s->s.h.keyframe && !s->s.h.intraonly) {
for (i = 0; i < 7; i++)
for (j = 0; j < 3; j++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.mv_mode[i][j] =
update_prob(&s->c, s->prob.p.mv_mode[i][j]);
- if (s->filtermode == FILTER_SWITCHABLE)
+ if (s->s.h.filtermode == FILTER_SWITCHABLE)
for (i = 0; i < 4; i++)
for (j = 0; j < 2; j++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
@@ -663,20 +829,20 @@ static int decode_frame_header(AVCodecContext *avctx,
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.intra[i] = update_prob(&s->c, s->prob.p.intra[i]);
- if (s->allowcompinter) {
- s->comppredmode = vp8_rac_get(&s->c);
- if (s->comppredmode)
- s->comppredmode += vp8_rac_get(&s->c);
- if (s->comppredmode == PRED_SWITCHABLE)
+ if (s->s.h.allowcompinter) {
+ s->s.h.comppredmode = vp8_rac_get(&s->c);
+ if (s->s.h.comppredmode)
+ s->s.h.comppredmode += vp8_rac_get(&s->c);
+ if (s->s.h.comppredmode == PRED_SWITCHABLE)
for (i = 0; i < 5; i++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.comp[i] =
update_prob(&s->c, s->prob.p.comp[i]);
} else {
- s->comppredmode = PRED_SINGLEREF;
+ s->s.h.comppredmode = PRED_SINGLEREF;
}
- if (s->comppredmode != PRED_COMPREF) {
+ if (s->s.h.comppredmode != PRED_COMPREF) {
for (i = 0; i < 5; i++) {
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.single_ref[i][0] =
@@ -687,7 +853,7 @@ static int decode_frame_header(AVCodecContext *avctx,
}
}
- if (s->comppredmode != PRED_SINGLEREF) {
+ if (s->s.h.comppredmode != PRED_SINGLEREF) {
for (i = 0; i < 5; i++)
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.comp_ref[i] =
@@ -746,7 +912,7 @@ static int decode_frame_header(AVCodecContext *avctx,
(vp8_rac_get_uint(&s->c, 7) << 1) | 1;
}
- if (s->highprecisionmvs) {
+ if (s->s.h.highprecisionmvs) {
for (i = 0; i < 2; i++) {
if (vp56_rac_get_prob_branchy(&s->c, 252))
s->prob.p.mv_comp[i].class0_hp =
@@ -762,602 +928,392 @@ static int decode_frame_header(AVCodecContext *avctx,
return (data2 - data) + size2;
}
-static int decode_subblock(AVCodecContext *avctx, int row, int col,
- VP9Filter *lflvl,
- ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl)
+static void decode_sb(AVCodecContext *avctx, int row, int col, VP9Filter *lflvl,
+ ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl)
{
VP9Context *s = avctx->priv_data;
- AVFrame *f = s->frames[CUR_FRAME].tf.f;
- int c = ((s->above_partition_ctx[col] >> (3 - bl)) & 1) |
+ int c = ((s->above_partition_ctx[col] >> (3 - bl)) & 1) |
(((s->left_partition_ctx[row & 0x7] >> (3 - bl)) & 1) << 1);
- int ret;
- const uint8_t *p = s->keyframe ? ff_vp9_default_kf_partition_probs[bl][c]
- : s->prob.p.partition[bl][c];
+ const uint8_t *p = s->s.h.keyframe || s->s.h.intraonly ? ff_vp9_default_kf_partition_probs[bl][c] :
+ s->prob.p.partition[bl][c];
enum BlockPartition bp;
ptrdiff_t hbs = 4 >> bl;
+ AVFrame *f = s->s.frames[CUR_FRAME].tf.f;
+ ptrdiff_t y_stride = f->linesize[0], uv_stride = f->linesize[1];
+ int bytesperpixel = s->bytesperpixel;
if (bl == BL_8X8) {
- bp = vp8_rac_get_tree(&s->c, ff_vp9_partition_tree, p);
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
- } else if (col + hbs < s->cols) {
- if (row + hbs < s->rows) {
+ bp = vp8_rac_get_tree(&s->c, ff_vp9_partition_tree, p);
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
+ } else if (col + hbs < s->cols) { // FIXME why not <=?
+ if (row + hbs < s->rows) { // FIXME why not <=?
bp = vp8_rac_get_tree(&s->c, ff_vp9_partition_tree, p);
switch (bp) {
case PARTITION_NONE:
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff,
- bl, bp);
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
break;
case PARTITION_H:
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff,
- bl, bp);
- if (!ret) {
- yoff += hbs * 8 * f->linesize[0];
- uvoff += hbs * 4 * f->linesize[1];
- ret = ff_vp9_decode_block(avctx, row + hbs, col, lflvl,
- yoff, uvoff, bl, bp);
- }
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
+ yoff += hbs * 8 * y_stride;
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ ff_vp9_decode_block(avctx, row + hbs, col, lflvl, yoff, uvoff, bl, bp);
break;
case PARTITION_V:
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff,
- bl, bp);
- if (!ret) {
- yoff += hbs * 8;
- uvoff += hbs * 4;
- ret = ff_vp9_decode_block(avctx, row, col + hbs, lflvl,
- yoff, uvoff, bl, bp);
- }
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
+ yoff += hbs * 8 * bytesperpixel;
+ uvoff += hbs * 8 * bytesperpixel >> s->ss_h;
+ ff_vp9_decode_block(avctx, row, col + hbs, lflvl, yoff, uvoff, bl, bp);
break;
case PARTITION_SPLIT:
- ret = decode_subblock(avctx, row, col, lflvl,
- yoff, uvoff, bl + 1);
- if (!ret) {
- ret = decode_subblock(avctx, row, col + hbs, lflvl,
- yoff + 8 * hbs, uvoff + 4 * hbs,
- bl + 1);
- if (!ret) {
- yoff += hbs * 8 * f->linesize[0];
- uvoff += hbs * 4 * f->linesize[1];
- ret = decode_subblock(avctx, row + hbs, col, lflvl,
- yoff, uvoff, bl + 1);
- if (!ret) {
- ret = decode_subblock(avctx, row + hbs, col + hbs,
- lflvl, yoff + 8 * hbs,
- uvoff + 4 * hbs, bl + 1);
- }
- }
- }
+ decode_sb(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
+ decode_sb(avctx, row, col + hbs, lflvl,
+ yoff + 8 * hbs * bytesperpixel,
+ uvoff + (8 * hbs * bytesperpixel >> s->ss_h), bl + 1);
+ yoff += hbs * 8 * y_stride;
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ decode_sb(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1);
+ decode_sb(avctx, row + hbs, col + hbs, lflvl,
+ yoff + 8 * hbs * bytesperpixel,
+ uvoff + (8 * hbs * bytesperpixel >> s->ss_h), bl + 1);
break;
default:
- av_log(avctx, AV_LOG_ERROR, "Unexpected partition %d.", bp);
- return AVERROR_INVALIDDATA;
+ av_assert0(0);
}
} else if (vp56_rac_get_prob_branchy(&s->c, p[1])) {
- bp = PARTITION_SPLIT;
- ret = decode_subblock(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
- if (!ret)
- ret = decode_subblock(avctx, row, col + hbs, lflvl,
- yoff + 8 * hbs, uvoff + 4 * hbs, bl + 1);
+ bp = PARTITION_SPLIT;
+ decode_sb(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
+ decode_sb(avctx, row, col + hbs, lflvl,
+ yoff + 8 * hbs * bytesperpixel,
+ uvoff + (8 * hbs * bytesperpixel >> s->ss_h), bl + 1);
} else {
- bp = PARTITION_H;
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff,
- bl, bp);
+ bp = PARTITION_H;
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
}
- } else if (row + hbs < s->rows) {
+ } else if (row + hbs < s->rows) { // FIXME why not <=?
if (vp56_rac_get_prob_branchy(&s->c, p[2])) {
- bp = PARTITION_SPLIT;
- ret = decode_subblock(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
- if (!ret) {
- yoff += hbs * 8 * f->linesize[0];
- uvoff += hbs * 4 * f->linesize[1];
- ret = decode_subblock(avctx, row + hbs, col, lflvl,
- yoff, uvoff, bl + 1);
- }
+ bp = PARTITION_SPLIT;
+ decode_sb(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
+ yoff += hbs * 8 * y_stride;
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ decode_sb(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1);
} else {
- bp = PARTITION_V;
- ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff,
- bl, bp);
+ bp = PARTITION_V;
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp);
}
} else {
- bp = PARTITION_SPLIT;
- ret = decode_subblock(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
+ bp = PARTITION_SPLIT;
+ decode_sb(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
}
s->counts.partition[bl][c][bp]++;
-
- return ret;
}
-static int decode_superblock_mem(AVCodecContext *avctx, int row, int col, struct VP9Filter *lflvl,
- ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl)
+static void decode_sb_mem(AVCodecContext *avctx, int row, int col, VP9Filter *lflvl,
+ ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl)
{
VP9Context *s = avctx->priv_data;
VP9Block *b = s->b;
ptrdiff_t hbs = 4 >> bl;
- AVFrame *f = s->frames[CUR_FRAME].tf.f;
+ AVFrame *f = s->s.frames[CUR_FRAME].tf.f;
ptrdiff_t y_stride = f->linesize[0], uv_stride = f->linesize[1];
- int res;
+ int bytesperpixel = s->bytesperpixel;
if (bl == BL_8X8) {
av_assert2(b->bl == BL_8X8);
- res = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp);
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp);
} else if (s->b->bl == bl) {
- if ((res = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp)) < 0)
- return res;
+ ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp);
if (b->bp == PARTITION_H && row + hbs < s->rows) {
yoff += hbs * 8 * y_stride;
- uvoff += hbs * 4 * uv_stride;
- res = ff_vp9_decode_block(avctx, row + hbs, col, lflvl, yoff, uvoff, b->bl, b->bp);
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ ff_vp9_decode_block(avctx, row + hbs, col, lflvl, yoff, uvoff, b->bl, b->bp);
} else if (b->bp == PARTITION_V && col + hbs < s->cols) {
- yoff += hbs * 8;
- uvoff += hbs * 4;
- res = ff_vp9_decode_block(avctx, row, col + hbs, lflvl, yoff, uvoff, b->bl, b->bp);
+ yoff += hbs * 8 * bytesperpixel;
+ uvoff += hbs * 8 * bytesperpixel >> s->ss_h;
+ ff_vp9_decode_block(avctx, row, col + hbs, lflvl, yoff, uvoff, b->bl, b->bp);
}
} else {
- if ((res = decode_superblock_mem(avctx, row, col, lflvl, yoff, uvoff, bl + 1)) < 0)
- return res;
+ decode_sb_mem(avctx, row, col, lflvl, yoff, uvoff, bl + 1);
if (col + hbs < s->cols) { // FIXME why not <=?
if (row + hbs < s->rows) {
- if ((res = decode_superblock_mem(avctx, row, col + hbs, lflvl, yoff + 8 * hbs,
- uvoff + 4 * hbs, bl + 1)) < 0)
- return res;
+ decode_sb_mem(avctx, row, col + hbs, lflvl, yoff + 8 * hbs * bytesperpixel,
+ uvoff + (8 * hbs * bytesperpixel >> s->ss_h), bl + 1);
yoff += hbs * 8 * y_stride;
- uvoff += hbs * 4 * uv_stride;
- if ((res = decode_superblock_mem(avctx, row + hbs, col, lflvl, yoff,
- uvoff, bl + 1)) < 0)
- return res;
- res = decode_superblock_mem(avctx, row + hbs, col + hbs, lflvl,
- yoff + 8 * hbs, uvoff + 4 * hbs, bl + 1);
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ decode_sb_mem(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1);
+ decode_sb_mem(avctx, row + hbs, col + hbs, lflvl,
+ yoff + 8 * hbs * bytesperpixel,
+ uvoff + (8 * hbs * bytesperpixel >> s->ss_h), bl + 1);
} else {
- yoff += hbs * 8;
- uvoff += hbs * 4;
- res = decode_superblock_mem(avctx, row, col + hbs, lflvl, yoff, uvoff, bl + 1);
+ yoff += hbs * 8 * bytesperpixel;
+ uvoff += hbs * 8 * bytesperpixel >> s->ss_h;
+ decode_sb_mem(avctx, row, col + hbs, lflvl, yoff, uvoff, bl + 1);
}
} else if (row + hbs < s->rows) {
yoff += hbs * 8 * y_stride;
- uvoff += hbs * 4 * uv_stride;
- res = decode_superblock_mem(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1);
- }
- }
-
- return res;
-}
-
-static void loopfilter_subblock(AVCodecContext *avctx, VP9Filter *lflvl,
- int row, int col,
- ptrdiff_t yoff, ptrdiff_t uvoff)
-{
- VP9Context *s = avctx->priv_data;
- AVFrame *f = s->frames[CUR_FRAME].tf.f;
- uint8_t *dst = f->data[0] + yoff;
- ptrdiff_t ls_y = f->linesize[0], ls_uv = f->linesize[1];
- uint8_t *lvl = lflvl->level;
- int y, x, p;
-
- /* FIXME: In how far can we interleave the v/h loopfilter calls? E.g.
- * if you think of them as acting on a 8x8 block max, we can interleave
- * each v/h within the single x loop, but that only works if we work on
- * 8 pixel blocks, and we won't always do that (we want at least 16px
- * to use SSE2 optimizations, perhaps 32 for AVX2). */
-
- // filter edges between columns, Y plane (e.g. block1 | block2)
- for (y = 0; y < 8; y += 2, dst += 16 * ls_y, lvl += 16) {
- uint8_t *ptr = dst, *l = lvl, *hmask1 = lflvl->mask[0][0][y];
- uint8_t *hmask2 = lflvl->mask[0][0][y + 1];
- unsigned hm1 = hmask1[0] | hmask1[1] | hmask1[2], hm13 = hmask1[3];
- unsigned hm2 = hmask2[1] | hmask2[2], hm23 = hmask2[3];
- unsigned hm = hm1 | hm2 | hm13 | hm23;
-
- for (x = 1; hm & ~(x - 1); x <<= 1, ptr += 8, l++) {
- if (hm1 & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- if (col || x > 1) {
- if (hmask1[0] & x) {
- if (hmask2[0] & x) {
- av_assert2(l[8] == L);
- s->dsp.loop_filter_16[0](ptr, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[2][0](ptr, ls_y, E, I, H);
- }
- } else if (hm2 & x) {
- L = l[8];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[!!(hmask1[1] & x)]
- [!!(hmask2[1] & x)]
- [0](ptr, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[!!(hmask1[1] & x)]
- [0](ptr, ls_y, E, I, H);
- }
- }
- } else if (hm2 & x) {
- int L = l[8], H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- if (col || x > 1) {
- s->dsp.loop_filter_8[!!(hmask2[1] & x)]
- [0](ptr + 8 * ls_y, ls_y, E, I, H);
- }
- }
- if (hm13 & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- if (hm23 & x) {
- L = l[8];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[0][0][0](ptr + 4, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[0][0](ptr + 4, ls_y, E, I, H);
- }
- } else if (hm23 & x) {
- int L = l[8], H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- s->dsp.loop_filter_8[0][0](ptr + 8 * ls_y + 4, ls_y, E, I, H);
- }
- }
- }
-
- // block1
- // filter edges between rows, Y plane (e.g. ------)
- // block2
- dst = f->data[0] + yoff;
- lvl = lflvl->level;
- for (y = 0; y < 8; y++, dst += 8 * ls_y, lvl += 8) {
- uint8_t *ptr = dst, *l = lvl, *vmask = lflvl->mask[0][1][y];
- unsigned vm = vmask[0] | vmask[1] | vmask[2], vm3 = vmask[3];
-
- for (x = 1; vm & ~(x - 1); x <<= 2, ptr += 16, l += 2) {
- if (row || y) {
- if (vm & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- if (vmask[0] & x) {
- if (vmask[0] & (x << 1)) {
- av_assert2(l[1] == L);
- s->dsp.loop_filter_16[1](ptr, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[2][1](ptr, ls_y, E, I, H);
- }
- } else if (vm & (x << 1)) {
- L = l[1];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[!!(vmask[1] & x)]
- [!!(vmask[1] & (x << 1))]
- [1](ptr, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[!!(vmask[1] & x)]
- [1](ptr, ls_y, E, I, H);
- }
- } else if (vm & (x << 1)) {
- int L = l[1], H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- s->dsp.loop_filter_8[!!(vmask[1] & (x << 1))]
- [1](ptr + 8, ls_y, E, I, H);
- }
- }
- if (vm3 & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- if (vm3 & (x << 1)) {
- L = l[1];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[0][0][1](ptr + ls_y * 4, ls_y, E, I, H);
- } else {
- s->dsp.loop_filter_8[0][1](ptr + ls_y * 4, ls_y, E, I, H);
- }
- } else if (vm3 & (x << 1)) {
- int L = l[1], H = L >> 4;
- int E = s->filter.mblim_lut[L], I = s->filter.lim_lut[L];
-
- s->dsp.loop_filter_8[0][1](ptr + ls_y * 4 + 8, ls_y, E, I, H);
- }
- }
- }
-
- // same principle but for U/V planes
- for (p = 0; p < 2; p++) {
- lvl = lflvl->level;
- dst = f->data[1 + p] + uvoff;
- for (y = 0; y < 8; y += 4, dst += 16 * ls_uv, lvl += 32) {
- uint8_t *ptr = dst, *l = lvl, *hmask1 = lflvl->mask[1][0][y];
- uint8_t *hmask2 = lflvl->mask[1][0][y + 2];
- unsigned hm1 = hmask1[0] | hmask1[1] | hmask1[2];
- unsigned hm2 = hmask2[1] | hmask2[2], hm = hm1 | hm2;
-
- for (x = 1; hm & ~(x - 1); x <<= 1, ptr += 4) {
- if (col || x > 1) {
- if (hm1 & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L];
- int I = s->filter.lim_lut[L];
-
- if (hmask1[0] & x) {
- if (hmask2[0] & x) {
- av_assert2(l[16] == L);
- s->dsp.loop_filter_16[0](ptr, ls_uv, E, I, H);
- } else {
- s->dsp.loop_filter_8[2][0](ptr, ls_uv, E, I, H);
- }
- } else if (hm2 & x) {
- L = l[16];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[!!(hmask1[1] & x)]
- [!!(hmask2[1] & x)]
- [0](ptr, ls_uv, E, I, H);
- } else {
- s->dsp.loop_filter_8[!!(hmask1[1] & x)]
- [0](ptr, ls_uv, E, I, H);
- }
- } else if (hm2 & x) {
- int L = l[16], H = L >> 4;
- int E = s->filter.mblim_lut[L];
- int I = s->filter.lim_lut[L];
-
- s->dsp.loop_filter_8[!!(hmask2[1] & x)]
- [0](ptr + 8 * ls_uv, ls_uv, E, I, H);
- }
- }
- if (x & 0xAA)
- l += 2;
- }
- }
- lvl = lflvl->level;
- dst = f->data[1 + p] + uvoff;
- for (y = 0; y < 8; y++, dst += 4 * ls_uv) {
- uint8_t *ptr = dst, *l = lvl, *vmask = lflvl->mask[1][1][y];
- unsigned vm = vmask[0] | vmask[1] | vmask[2];
-
- for (x = 1; vm & ~(x - 1); x <<= 4, ptr += 16, l += 4) {
- if (row || y) {
- if (vm & x) {
- int L = *l, H = L >> 4;
- int E = s->filter.mblim_lut[L];
- int I = s->filter.lim_lut[L];
-
- if (vmask[0] & x) {
- if (vmask[0] & (x << 2)) {
- av_assert2(l[2] == L);
- s->dsp.loop_filter_16[1](ptr, ls_uv, E, I, H);
- } else {
- s->dsp.loop_filter_8[2][1](ptr, ls_uv, E, I, H);
- }
- } else if (vm & (x << 2)) {
- L = l[2];
- H |= (L >> 4) << 8;
- E |= s->filter.mblim_lut[L] << 8;
- I |= s->filter.lim_lut[L] << 8;
- s->dsp.loop_filter_mix2[!!(vmask[1] & x)]
- [!!(vmask[1] & (x << 2))]
- [1](ptr, ls_uv, E, I, H);
- } else {
- s->dsp.loop_filter_8[!!(vmask[1] & x)]
- [1](ptr, ls_uv, E, I, H);
- }
- } else if (vm & (x << 2)) {
- int L = l[2], H = L >> 4;
- int E = s->filter.mblim_lut[L];
- int I = s->filter.lim_lut[L];
-
- s->dsp.loop_filter_8[!!(vmask[1] & (x << 2))]
- [1](ptr + 8, ls_uv, E, I, H);
- }
- }
- }
- if (y & 1)
- lvl += 16;
+ uvoff += hbs * 8 * uv_stride >> s->ss_v;
+ decode_sb_mem(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1);
}
}
}
static void set_tile_offset(int *start, int *end, int idx, int log2_n, int n)
{
- int sb_start = (idx * n) >> log2_n;
+ int sb_start = ( idx * n) >> log2_n;
int sb_end = ((idx + 1) * n) >> log2_n;
*start = FFMIN(sb_start, n) << 3;
*end = FFMIN(sb_end, n) << 3;
}
-static int update_refs(AVCodecContext *avctx)
+static void free_buffers(VP9Context *s)
+{
+ av_freep(&s->intra_pred_data[0]);
+ av_freep(&s->b_base);
+ av_freep(&s->block_base);
+}
+
+static av_cold int vp9_decode_free(AVCodecContext *avctx)
{
VP9Context *s = avctx->priv_data;
- int i, ret;
+ int i;
- for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++)
- if (s->refreshrefmask & (1 << i)) {
- ff_thread_release_buffer(avctx, &s->refs[i]);
- ret = ff_thread_ref_frame(&s->refs[i], &s->frames[CUR_FRAME].tf);
- if (ret < 0)
- return ret;
- }
+ for (i = 0; i < 3; i++) {
+ if (s->s.frames[i].tf.f->buf[0])
+ vp9_frame_unref(avctx, &s->s.frames[i]);
+ av_frame_free(&s->s.frames[i].tf.f);
+ }
+ for (i = 0; i < 8; i++) {
+ if (s->s.refs[i].f->buf[0])
+ ff_thread_release_buffer(avctx, &s->s.refs[i]);
+ av_frame_free(&s->s.refs[i].f);
+ if (s->next_refs[i].f->buf[0])
+ ff_thread_release_buffer(avctx, &s->next_refs[i]);
+ av_frame_free(&s->next_refs[i].f);
+ }
+ free_buffers(s);
+ av_freep(&s->c_b);
+ s->c_b_size = 0;
return 0;
}
-static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame, const uint8_t *data, int size,
- int can_finish_setup)
+
+static int vp9_decode_frame(AVCodecContext *avctx, void *frame,
+ int *got_frame, AVPacket *pkt)
{
+ const uint8_t *data = pkt->data;
+ int size = pkt->size;
VP9Context *s = avctx->priv_data;
+ int ret, tile_row, tile_col, i, ref, row, col;
+ int retain_segmap_ref = s->s.frames[REF_FRAME_SEGMAP].segmentation_map &&
+ (!s->s.h.segmentation.enabled || !s->s.h.segmentation.update_map);
+ ptrdiff_t yoff, uvoff, ls_y, ls_uv;
AVFrame *f;
- int ret, tile_row, tile_col, i, ref = -1, row, col;
+ int bytesperpixel;
- ret = decode_frame_header(avctx, data, size, &ref);
- if (ret < 0) {
+ if ((ret = decode_frame_header(avctx, data, size, &ref)) < 0) {
return ret;
- } else if (!ret) {
- if (!s->refs[ref].f->buf[0]) {
- av_log(avctx, AV_LOG_ERROR,
- "Requested reference %d not available\n", ref);
+ } else if (ret == 0) {
+ if (!s->s.refs[ref].f->buf[0]) {
+ av_log(avctx, AV_LOG_ERROR, "Requested reference %d not available\n", ref);
return AVERROR_INVALIDDATA;
}
-
- ret = av_frame_ref(frame, s->refs[ref].f);
- if (ret < 0)
+ if ((ret = av_frame_ref(frame, s->s.refs[ref].f)) < 0)
return ret;
+ ((AVFrame *)frame)->pts = pkt->pts;
+#if FF_API_PKT_PTS
+FF_DISABLE_DEPRECATION_WARNINGS
+ ((AVFrame *)frame)->pkt_pts = pkt->pts;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ ((AVFrame *)frame)->pkt_dts = pkt->dts;
+ for (i = 0; i < 8; i++) {
+ if (s->next_refs[i].f->buf[0])
+ ff_thread_release_buffer(avctx, &s->next_refs[i]);
+ if (s->s.refs[i].f->buf[0] &&
+ (ret = ff_thread_ref_frame(&s->next_refs[i], &s->s.refs[i])) < 0)
+ return ret;
+ }
*got_frame = 1;
- return 0;
+ return pkt->size;
}
data += ret;
size -= ret;
- vp9_frame_unref(avctx, &s->frames[LAST_FRAME]);
- if (!s->keyframe && s->frames[CUR_FRAME].tf.f->buf[0]) {
- ret = vp9_frame_ref(&s->frames[LAST_FRAME], &s->frames[CUR_FRAME]);
- if (ret < 0)
+ if (!retain_segmap_ref || s->s.h.keyframe || s->s.h.intraonly) {
+ if (s->s.frames[REF_FRAME_SEGMAP].tf.f->buf[0])
+ vp9_frame_unref(avctx, &s->s.frames[REF_FRAME_SEGMAP]);
+ if (!s->s.h.keyframe && !s->s.h.intraonly && !s->s.h.errorres && s->s.frames[CUR_FRAME].tf.f->buf[0] &&
+ (ret = vp9_frame_ref(avctx, &s->s.frames[REF_FRAME_SEGMAP], &s->s.frames[CUR_FRAME])) < 0)
return ret;
}
-
- vp9_frame_unref(avctx, &s->frames[CUR_FRAME]);
- ret = vp9_frame_alloc(avctx, &s->frames[CUR_FRAME]);
- if (ret < 0)
+ if (s->s.frames[REF_FRAME_MVPAIR].tf.f->buf[0])
+ vp9_frame_unref(avctx, &s->s.frames[REF_FRAME_MVPAIR]);
+ if (!s->s.h.intraonly && !s->s.h.keyframe && !s->s.h.errorres && s->s.frames[CUR_FRAME].tf.f->buf[0] &&
+ (ret = vp9_frame_ref(avctx, &s->s.frames[REF_FRAME_MVPAIR], &s->s.frames[CUR_FRAME])) < 0)
return ret;
+ if (s->s.frames[CUR_FRAME].tf.f->buf[0])
+ vp9_frame_unref(avctx, &s->s.frames[CUR_FRAME]);
+ if ((ret = vp9_frame_alloc(avctx, &s->s.frames[CUR_FRAME])) < 0)
+ return ret;
+ f = s->s.frames[CUR_FRAME].tf.f;
+ f->key_frame = s->s.h.keyframe;
+ f->pict_type = (s->s.h.keyframe || s->s.h.intraonly) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+ ls_y = f->linesize[0];
+ ls_uv =f->linesize[1];
+
+ if (s->s.frames[REF_FRAME_SEGMAP].tf.f->buf[0] &&
+ (s->s.frames[REF_FRAME_MVPAIR].tf.f->width != s->s.frames[CUR_FRAME].tf.f->width ||
+ s->s.frames[REF_FRAME_MVPAIR].tf.f->height != s->s.frames[CUR_FRAME].tf.f->height)) {
+ vp9_frame_unref(avctx, &s->s.frames[REF_FRAME_SEGMAP]);
+ }
- f = s->frames[CUR_FRAME].tf.f;
- f->key_frame = s->keyframe;
- f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
-
- if (s->fullrange)
- avctx->color_range = AVCOL_RANGE_JPEG;
- else
- avctx->color_range = AVCOL_RANGE_MPEG;
-
- switch (s->colorspace) {
- case 1: avctx->colorspace = AVCOL_SPC_BT470BG; break;
- case 2: avctx->colorspace = AVCOL_SPC_BT709; break;
- case 3: avctx->colorspace = AVCOL_SPC_SMPTE170M; break;
- case 4: avctx->colorspace = AVCOL_SPC_SMPTE240M; break;
+ // ref frame setup
+ for (i = 0; i < 8; i++) {
+ if (s->next_refs[i].f->buf[0])
+ ff_thread_release_buffer(avctx, &s->next_refs[i]);
+ if (s->s.h.refreshrefmask & (1 << i)) {
+ ret = ff_thread_ref_frame(&s->next_refs[i], &s->s.frames[CUR_FRAME].tf);
+ } else if (s->s.refs[i].f->buf[0]) {
+ ret = ff_thread_ref_frame(&s->next_refs[i], &s->s.refs[i]);
+ }
+ if (ret < 0)
+ return ret;
}
- s->pass = s->uses_2pass =
- avctx->active_thread_type & FF_THREAD_FRAME && s->refreshctx && !s->parallelmode;
+ if (avctx->hwaccel) {
+ ret = avctx->hwaccel->start_frame(avctx, NULL, 0);
+ if (ret < 0)
+ return ret;
+ ret = avctx->hwaccel->decode_slice(avctx, pkt->data, pkt->size);
+ if (ret < 0)
+ return ret;
+ ret = avctx->hwaccel->end_frame(avctx);
+ if (ret < 0)
+ return ret;
+ goto finish;
+ }
- if (s->refreshctx && s->parallelmode) {
+ // main tile decode loop
+ bytesperpixel = s->bytesperpixel;
+ memset(s->above_partition_ctx, 0, s->cols);
+ memset(s->above_skip_ctx, 0, s->cols);
+ if (s->s.h.keyframe || s->s.h.intraonly) {
+ memset(s->above_mode_ctx, DC_PRED, s->cols * 2);
+ } else {
+ memset(s->above_mode_ctx, NEARESTMV, s->cols);
+ }
+ memset(s->above_y_nnz_ctx, 0, s->sb_cols * 16);
+ memset(s->above_uv_nnz_ctx[0], 0, s->sb_cols * 16 >> s->ss_h);
+ memset(s->above_uv_nnz_ctx[1], 0, s->sb_cols * 16 >> s->ss_h);
+ memset(s->above_segpred_ctx, 0, s->cols);
+ s->pass = s->s.frames[CUR_FRAME].uses_2pass =
+ avctx->active_thread_type == FF_THREAD_FRAME && s->s.h.refreshctx && !s->s.h.parallelmode;
+ if ((ret = update_block_buffers(avctx)) < 0) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to allocate block buffers\n");
+ return ret;
+ }
+ if (s->s.h.refreshctx && s->s.h.parallelmode) {
int j, k, l, m;
+
for (i = 0; i < 4; i++) {
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
for (l = 0; l < 6; l++)
for (m = 0; m < 6; m++)
- memcpy(s->prob_ctx[s->framectxid].coef[i][j][k][l][m],
+ memcpy(s->prob_ctx[s->s.h.framectxid].coef[i][j][k][l][m],
s->prob.coef[i][j][k][l][m], 3);
- if (s->txfmmode == i)
+ if (s->s.h.txfmmode == i)
break;
}
- s->prob_ctx[s->framectxid].p = s->prob.p;
- }
- if ((s->parallelmode || !s->refreshctx) &&
- can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) {
+ s->prob_ctx[s->s.h.framectxid].p = s->prob.p;
+ ff_thread_finish_setup(avctx);
+ } else if (!s->s.h.refreshctx) {
ff_thread_finish_setup(avctx);
- s->setup_finished = 1;
}
- // main tile decode loop
- memset(s->above_partition_ctx, 0, s->cols);
- memset(s->above_skip_ctx, 0, s->cols);
- if (s->keyframe || s->intraonly)
- memset(s->above_mode_ctx, DC_PRED, s->cols * 2);
- else
- memset(s->above_mode_ctx, NEARESTMV, s->cols);
- memset(s->above_y_nnz_ctx, 0, s->sb_cols * 16);
- memset(s->above_uv_nnz_ctx[0], 0, s->sb_cols * 8);
- memset(s->above_uv_nnz_ctx[1], 0, s->sb_cols * 8);
- memset(s->above_segpred_ctx, 0, s->cols);
-
do {
- ptrdiff_t yoff = 0, uvoff = 0;
- s->b = s->b_base;
- s->block = s->block_base;
+ yoff = uvoff = 0;
+ s->b = s->b_base;
+ s->block = s->block_base;
s->uvblock[0] = s->uvblock_base[0];
s->uvblock[1] = s->uvblock_base[1];
- s->eob = s->eob_base;
- s->uveob[0] = s->uveob_base[0];
- s->uveob[1] = s->uveob_base[1];
-
- for (tile_row = 0; tile_row < s->tiling.tile_rows; tile_row++) {
- set_tile_offset(&s->tiling.tile_row_start, &s->tiling.tile_row_end,
- tile_row, s->tiling.log2_tile_rows, s->sb_rows);
+ s->eob = s->eob_base;
+ s->uveob[0] = s->uveob_base[0];
+ s->uveob[1] = s->uveob_base[1];
+ for (tile_row = 0; tile_row < s->s.h.tiling.tile_rows; tile_row++) {
+ set_tile_offset(&s->tile_row_start, &s->tile_row_end,
+ tile_row, s->s.h.tiling.log2_tile_rows, s->sb_rows);
if (s->pass != 2) {
- for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) {
+ for (tile_col = 0; tile_col < s->s.h.tiling.tile_cols; tile_col++) {
int64_t tile_size;
- if (tile_col == s->tiling.tile_cols - 1 &&
- tile_row == s->tiling.tile_rows - 1) {
+ if (tile_col == s->s.h.tiling.tile_cols - 1 &&
+ tile_row == s->s.h.tiling.tile_rows - 1) {
tile_size = size;
} else {
tile_size = AV_RB32(data);
- data += 4;
- size -= 4;
+ data += 4;
+ size -= 4;
}
if (tile_size > size) {
- ret = AVERROR_INVALIDDATA;
- goto fail;
+ ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0);
+ return AVERROR_INVALIDDATA;
}
- ff_vp56_init_range_decoder(&s->c_b[tile_col], data, tile_size);
+ ret = ff_vp56_init_range_decoder(&s->c_b[tile_col], data, tile_size);
+ if (ret < 0)
+ return ret;
if (vp56_rac_get_prob_branchy(&s->c_b[tile_col], 128)) { // marker bit
- ret = AVERROR_INVALIDDATA;
- goto fail;
+ ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0);
+ return AVERROR_INVALIDDATA;
}
data += tile_size;
size -= tile_size;
}
}
- for (row = s->tiling.tile_row_start;
- row < s->tiling.tile_row_end;
- row += 8, yoff += f->linesize[0] * 64,
- uvoff += f->linesize[1] * 32) {
- VP9Filter *lflvl = s->lflvl;
+ for (row = s->tile_row_start; row < s->tile_row_end;
+ row += 8, yoff += ls_y * 64, uvoff += ls_uv * 64 >> s->ss_v) {
+ VP9Filter *lflvl_ptr = s->lflvl;
ptrdiff_t yoff2 = yoff, uvoff2 = uvoff;
- for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) {
- set_tile_offset(&s->tiling.tile_col_start,
- &s->tiling.tile_col_end,
- tile_col, s->tiling.log2_tile_cols, s->sb_cols);
-
- memset(s->left_partition_ctx, 0, 8);
- memset(s->left_skip_ctx, 0, 8);
- if (s->keyframe || s->intraonly)
- memset(s->left_mode_ctx, DC_PRED, 16);
- else
- memset(s->left_mode_ctx, NEARESTMV, 8);
- memset(s->left_y_nnz_ctx, 0, 16);
- memset(s->left_uv_nnz_ctx, 0, 16);
- memset(s->left_segpred_ctx, 0, 8);
-
- memcpy(&s->c, &s->c_b[tile_col], sizeof(s->c));
- for (col = s->tiling.tile_col_start;
- col < s->tiling.tile_col_end;
- col += 8, yoff2 += 64, uvoff2 += 32, lflvl++) {
+ for (tile_col = 0; tile_col < s->s.h.tiling.tile_cols; tile_col++) {
+ set_tile_offset(&s->tile_col_start, &s->tile_col_end,
+ tile_col, s->s.h.tiling.log2_tile_cols, s->sb_cols);
+
+ if (s->pass != 2) {
+ memset(s->left_partition_ctx, 0, 8);
+ memset(s->left_skip_ctx, 0, 8);
+ if (s->s.h.keyframe || s->s.h.intraonly) {
+ memset(s->left_mode_ctx, DC_PRED, 16);
+ } else {
+ memset(s->left_mode_ctx, NEARESTMV, 8);
+ }
+ memset(s->left_y_nnz_ctx, 0, 16);
+ memset(s->left_uv_nnz_ctx, 0, 32);
+ memset(s->left_segpred_ctx, 0, 8);
+
+ memcpy(&s->c, &s->c_b[tile_col], sizeof(s->c));
+ }
+
+ for (col = s->tile_col_start;
+ col < s->tile_col_end;
+ col += 8, yoff2 += 64 * bytesperpixel,
+ uvoff2 += 64 * bytesperpixel >> s->ss_h, lflvl_ptr++) {
// FIXME integrate with lf code (i.e. zero after each
// use, similar to invtxfm coefficients, or similar)
- if (s->pass != 1)
- memset(lflvl->mask, 0, sizeof(lflvl->mask));
+ if (s->pass != 1) {
+ memset(lflvl_ptr->mask, 0, sizeof(lflvl_ptr->mask));
+ }
if (s->pass == 2) {
- ret = decode_superblock_mem(avctx, row, col, lflvl,
- yoff2, uvoff2, BL_64X64);
+ decode_sb_mem(avctx, row, col, lflvl_ptr,
+ yoff2, uvoff2, BL_64X64);
} else {
- ret = decode_subblock(avctx, row, col, lflvl,
- yoff2, uvoff2, BL_64X64);
+ decode_sb(avctx, row, col, lflvl_ptr,
+ yoff2, uvoff2, BL_64X64);
}
- if (ret < 0)
- goto fail;
}
if (s->pass != 2)
memcpy(&s->c_b[tile_col], &s->c, sizeof(s->c));
@@ -1370,218 +1326,161 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
// prediction of next row of sb64s
if (row + 8 < s->rows) {
memcpy(s->intra_pred_data[0],
- f->data[0] + yoff +
- 63 * f->linesize[0],
- 8 * s->cols);
+ f->data[0] + yoff + 63 * ls_y,
+ 8 * s->cols * bytesperpixel);
memcpy(s->intra_pred_data[1],
- f->data[1] + uvoff +
- 31 * f->linesize[1],
- 4 * s->cols);
+ f->data[1] + uvoff + ((64 >> s->ss_v) - 1) * ls_uv,
+ 8 * s->cols * bytesperpixel >> s->ss_h);
memcpy(s->intra_pred_data[2],
- f->data[2] + uvoff +
- 31 * f->linesize[2],
- 4 * s->cols);
+ f->data[2] + uvoff + ((64 >> s->ss_v) - 1) * ls_uv,
+ 8 * s->cols * bytesperpixel >> s->ss_h);
}
// loopfilter one row
- if (s->filter.level) {
- yoff2 = yoff;
+ if (s->s.h.filter.level) {
+ yoff2 = yoff;
uvoff2 = uvoff;
- lflvl = s->lflvl;
+ lflvl_ptr = s->lflvl;
for (col = 0; col < s->cols;
- col += 8, yoff2 += 64, uvoff2 += 32, lflvl++)
- loopfilter_subblock(avctx, lflvl, row, col, yoff2, uvoff2);
+ col += 8, yoff2 += 64 * bytesperpixel,
+ uvoff2 += 64 * bytesperpixel >> s->ss_h, lflvl_ptr++) {
+ ff_vp9_loopfilter_sb(avctx, lflvl_ptr, row, col,
+ yoff2, uvoff2);
+ }
}
// FIXME maybe we can make this more finegrained by running the
// loopfilter per-block instead of after each sbrow
// In fact that would also make intra pred left preparation easier?
- ff_thread_report_progress(&s->frames[CUR_FRAME].tf, row >> 3, 0);
+ ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, row >> 3, 0);
}
}
- if (s->pass < 2 && s->refreshctx && !s->parallelmode) {
+ if (s->pass < 2 && s->s.h.refreshctx && !s->s.h.parallelmode) {
ff_vp9_adapt_probs(s);
- if (can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) {
- ff_thread_finish_setup(avctx);
- s->setup_finished = 1;
- }
+ ff_thread_finish_setup(avctx);
}
} while (s->pass++ == 1);
-fail:
- ff_thread_report_progress(&s->frames[CUR_FRAME].tf, INT_MAX, 0);
- if (ret < 0)
- return ret;
+ ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0);
+finish:
// ref frame setup
- if (!s->setup_finished) {
- ret = update_refs(avctx);
- if (ret < 0)
+ for (i = 0; i < 8; i++) {
+ if (s->s.refs[i].f->buf[0])
+ ff_thread_release_buffer(avctx, &s->s.refs[i]);
+ if (s->next_refs[i].f->buf[0] &&
+ (ret = ff_thread_ref_frame(&s->s.refs[i], &s->next_refs[i])) < 0)
return ret;
}
- if (!s->invisible) {
- av_frame_unref(frame);
- ret = av_frame_ref(frame, s->frames[CUR_FRAME].tf.f);
- if (ret < 0)
+ if (!s->s.h.invisible) {
+ if ((ret = av_frame_ref(frame, s->s.frames[CUR_FRAME].tf.f)) < 0)
return ret;
*got_frame = 1;
}
- return 0;
+ return pkt->size;
}
-static int vp9_decode_packet(AVCodecContext *avctx, void *frame,
- int *got_frame, AVPacket *avpkt)
+static void vp9_decode_flush(AVCodecContext *avctx)
{
VP9Context *s = avctx->priv_data;
- const uint8_t *data = avpkt->data;
- int size = avpkt->size;
- int marker, ret;
-
- s->setup_finished = 0;
-
- /* Read superframe index - this is a collection of individual frames
- * that together lead to one visible frame */
- marker = data[size - 1];
- if ((marker & 0xe0) == 0xc0) {
- int nbytes = 1 + ((marker >> 3) & 0x3);
- int n_frames = 1 + (marker & 0x7);
- int idx_sz = 2 + n_frames * nbytes;
-
- if (size >= idx_sz && data[size - idx_sz] == marker) {
- const uint8_t *idx = data + size + 1 - idx_sz;
-
- while (n_frames--) {
- unsigned sz = AV_RL32(idx);
-
- if (nbytes < 4)
- sz &= (1 << (8 * nbytes)) - 1;
- idx += nbytes;
-
- if (sz > size) {
- av_log(avctx, AV_LOG_ERROR,
- "Superframe packet size too big: %u > %d\n",
- sz, size);
- return AVERROR_INVALIDDATA;
- }
-
- ret = vp9_decode_frame(avctx, frame, got_frame, data, sz,
- !n_frames);
- if (ret < 0)
- return ret;
- data += sz;
- size -= sz;
- }
- return avpkt->size;
- }
- }
+ int i;
- /* If we get here, there was no valid superframe index, i.e. this is just
- * one whole single frame. Decode it as such from the complete input buf. */
- if ((ret = vp9_decode_frame(avctx, frame, got_frame, data, size, 1)) < 0)
- return ret;
- return size;
+ for (i = 0; i < 3; i++)
+ vp9_frame_unref(avctx, &s->s.frames[i]);
+ for (i = 0; i < 8; i++)
+ ff_thread_release_buffer(avctx, &s->s.refs[i]);
}
-static av_cold int vp9_decode_free(AVCodecContext *avctx)
+static int init_frames(AVCodecContext *avctx)
{
VP9Context *s = avctx->priv_data;
int i;
- for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) {
- vp9_frame_unref(avctx, &s->frames[i]);
- av_frame_free(&s->frames[i].tf.f);
+ for (i = 0; i < 3; i++) {
+ s->s.frames[i].tf.f = av_frame_alloc();
+ if (!s->s.frames[i].tf.f) {
+ vp9_decode_free(avctx);
+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate frame buffer %d\n", i);
+ return AVERROR(ENOMEM);
+ }
}
-
- for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) {
- ff_thread_release_buffer(avctx, &s->refs[i]);
- av_frame_free(&s->refs[i].f);
+ for (i = 0; i < 8; i++) {
+ s->s.refs[i].f = av_frame_alloc();
+ s->next_refs[i].f = av_frame_alloc();
+ if (!s->s.refs[i].f || !s->next_refs[i].f) {
+ vp9_decode_free(avctx);
+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate frame buffer %d\n", i);
+ return AVERROR(ENOMEM);
+ }
}
- av_freep(&s->c_b);
- av_freep(&s->above_partition_ctx);
- av_freep(&s->b_base);
- av_freep(&s->block_base);
-
return 0;
}
static av_cold int vp9_decode_init(AVCodecContext *avctx)
{
VP9Context *s = avctx->priv_data;
- int i;
-
- memset(s, 0, sizeof(*s));
avctx->internal->allocate_progress = 1;
+ s->last_bpp = 0;
+ s->s.h.filter.sharpness = -1;
- avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-
- ff_vp9dsp_init(&s->dsp);
- ff_videodsp_init(&s->vdsp, 8);
-
- s->frames[0].tf.f = av_frame_alloc();
- s->frames[1].tf.f = av_frame_alloc();
- if (!s->frames[0].tf.f || !s->frames[1].tf.f)
- goto fail;
-
- for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) {
- s->refs[i].f = av_frame_alloc();
- if (!s->refs[i].f)
- goto fail;
- }
-
- s->filter.sharpness = -1;
+ return init_frames(avctx);
+}
- return 0;
-fail:
- vp9_decode_free(avctx);
- return AVERROR(ENOMEM);
+#if HAVE_THREADS
+static av_cold int vp9_decode_init_thread_copy(AVCodecContext *avctx)
+{
+ return init_frames(avctx);
}
static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
- VP9Context *s = dst->priv_data, *ssrc = src->priv_data;
int i, ret;
+ VP9Context *s = dst->priv_data, *ssrc = src->priv_data;
- ret = update_size(dst, ssrc->alloc_width, ssrc->alloc_height);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < 2; i++) {
- if (s->frames[i].tf.f->data[0])
- vp9_frame_unref(dst, &s->frames[i]);
- if (ssrc->frames[i].tf.f->data[0]) {
- if ((ret = vp9_frame_ref(&s->frames[i], &ssrc->frames[i])) < 0)
+ for (i = 0; i < 3; i++) {
+ if (s->s.frames[i].tf.f->buf[0])
+ vp9_frame_unref(dst, &s->s.frames[i]);
+ if (ssrc->s.frames[i].tf.f->buf[0]) {
+ if ((ret = vp9_frame_ref(dst, &s->s.frames[i], &ssrc->s.frames[i])) < 0)
return ret;
}
}
- for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) {
- ff_thread_release_buffer(dst, &s->refs[i]);
- if (ssrc->refs[i].f->buf[0]) {
- ret = ff_thread_ref_frame(&s->refs[i], &ssrc->refs[i]);
- if (ret < 0)
+ for (i = 0; i < 8; i++) {
+ if (s->s.refs[i].f->buf[0])
+ ff_thread_release_buffer(dst, &s->s.refs[i]);
+ if (ssrc->next_refs[i].f->buf[0]) {
+ if ((ret = ff_thread_ref_frame(&s->s.refs[i], &ssrc->next_refs[i])) < 0)
return ret;
}
}
- s->refreshrefmask = ssrc->refreshrefmask;
- ret = update_refs(dst);
- if (ret < 0)
- return ret;
-
- s->invisible = ssrc->invisible;
- s->keyframe = ssrc->keyframe;
- s->last_uses_2pass = ssrc->uses_2pass;
-
+ s->s.h.invisible = ssrc->s.h.invisible;
+ s->s.h.keyframe = ssrc->s.h.keyframe;
+ s->s.h.intraonly = ssrc->s.h.intraonly;
+ s->ss_v = ssrc->ss_v;
+ s->ss_h = ssrc->ss_h;
+ s->s.h.segmentation.enabled = ssrc->s.h.segmentation.enabled;
+ s->s.h.segmentation.update_map = ssrc->s.h.segmentation.update_map;
+ s->s.h.segmentation.absolute_vals = ssrc->s.h.segmentation.absolute_vals;
+ s->bytesperpixel = ssrc->bytesperpixel;
+ s->gf_fmt = ssrc->gf_fmt;
+ s->w = ssrc->w;
+ s->h = ssrc->h;
+ s->s.h.bpp = ssrc->s.h.bpp;
+ s->bpp_index = ssrc->bpp_index;
+ s->pix_fmt = ssrc->pix_fmt;
memcpy(&s->prob_ctx, &ssrc->prob_ctx, sizeof(s->prob_ctx));
- memcpy(&s->lf_delta, &ssrc->lf_delta, sizeof(s->lf_delta));
- memcpy(&s->segmentation.feat, &ssrc->segmentation.feat,
- sizeof(s->segmentation.feat));
+ memcpy(&s->s.h.lf_delta, &ssrc->s.h.lf_delta, sizeof(s->s.h.lf_delta));
+ memcpy(&s->s.h.segmentation.feat, &ssrc->s.h.segmentation.feat,
+ sizeof(s->s.h.segmentation.feat));
return 0;
}
+#endif
AVCodec ff_vp9_decoder = {
.name = "vp9",
@@ -1590,10 +1489,11 @@ AVCodec ff_vp9_decoder = {
.id = AV_CODEC_ID_VP9,
.priv_data_size = sizeof(VP9Context),
.init = vp9_decode_init,
- .decode = vp9_decode_packet,
- .flush = vp9_decode_flush,
.close = vp9_decode_free,
+ .decode = vp9_decode_frame,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
- .init_thread_copy = vp9_decode_init,
- .update_thread_context = vp9_decode_update_thread_context,
+ .flush = vp9_decode_flush,
+ .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp9_decode_init_thread_copy),
+ .update_thread_context = ONLY_IF_THREADS_ENABLED(vp9_decode_update_thread_context),
+ .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles),
};