Source code
Revision control
Copy as Markdown
Other Tools
/*
* VP7/VP8 compatible video decoder
*
* Copyright (C) 2010 David Conrad
* Copyright (C) 2010 Ronald S. Bultje
* Copyright (C) 2010 Fiona Glaser
* Copyright (C) 2012 Daniel Kang
* Copyright (C) 2014 Peter Ross
*
* 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.
*
* 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config_components.h"
#include "libavutil/mem.h"
#include "libavutil/mem_internal.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "decode.h"
#include "hwaccel_internal.h"
#include "hwconfig.h"
#include "mathops.h"
#include "progressframe.h"
#include "libavutil/refstruct.h"
#include "thread.h"
#include "vp8.h"
#include "vp89_rac.h"
#include "vp8data.h"
#include "vpx_rac.h"
#if ARCH_ARM
# include "arm/vp8.h"
#endif
// fixme: add 1 bit to all the calls to this?
static int vp8_rac_get_sint(VPXRangeCoder *c, int bits)
{
int v;
if (!vp89_rac_get(c))
return 0;
v = vp89_rac_get_uint(c, bits);
if (vp89_rac_get(c))
v = -v;
return v;
}
static int vp8_rac_get_nn(VPXRangeCoder *c)
{
int v = vp89_rac_get_uint(c, 7) << 1;
return v + !v;
}
// DCTextra
static int vp8_rac_get_coeff(VPXRangeCoder *c, const uint8_t *prob)
{
int v = 0;
do {
v = (v<<1) + vpx_rac_get_prob(c, *prob++);
} while (*prob);
return v;
}
static void free_buffers(VP8Context *s)
{
int i;
if (s->thread_data)
for (i = 0; i < MAX_THREADS; i++) {
#if HAVE_THREADS
pthread_cond_destroy(&s->thread_data[i].cond);
pthread_mutex_destroy(&s->thread_data[i].lock);
#endif
av_freep(&s->thread_data[i].filter_strength);
}
av_freep(&s->thread_data);
av_freep(&s->macroblocks_base);
av_freep(&s->intra4x4_pred_mode_top);
av_freep(&s->top_nnz);
av_freep(&s->top_border);
s->macroblocks = NULL;
}
static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref)
{
int ret = ff_progress_frame_get_buffer(s->avctx, &f->tf,
ref ? AV_GET_BUFFER_FLAG_REF : 0);
if (ret < 0)
return ret;
f->seg_map = av_refstruct_allocz(s->mb_width * s->mb_height);
if (!f->seg_map) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = ff_hwaccel_frame_priv_alloc(s->avctx, &f->hwaccel_picture_private);
if (ret < 0)
goto fail;
return 0;
fail:
av_refstruct_unref(&f->seg_map);
ff_progress_frame_unref(&f->tf);
return ret;
}
static void vp8_release_frame(VP8Frame *f)
{
av_refstruct_unref(&f->seg_map);
av_refstruct_unref(&f->hwaccel_picture_private);
ff_progress_frame_unref(&f->tf);
}
static av_cold void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem)
{
VP8Context *s = avctx->priv_data;
int i;
for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++)
vp8_release_frame(&s->frames[i]);
memset(s->framep, 0, sizeof(s->framep));
if (free_mem)
free_buffers(s);
if (FF_HW_HAS_CB(avctx, flush))
FF_HW_SIMPLE_CALL(avctx, flush);
}
static av_cold void vp8_decode_flush(AVCodecContext *avctx)
{
vp8_decode_flush_impl(avctx, 0);
}
static VP8Frame *vp8_find_free_buffer(VP8Context *s)
{
VP8Frame *frame = NULL;
int i;
// find a free buffer
for (i = 0; i < 5; i++)
if (&s->frames[i] != s->framep[VP8_FRAME_CURRENT] &&
&s->frames[i] != s->framep[VP8_FRAME_PREVIOUS] &&
&s->frames[i] != s->framep[VP8_FRAME_GOLDEN] &&
&s->frames[i] != s->framep[VP8_FRAME_ALTREF]) {
frame = &s->frames[i];
break;
}
if (i == 5) {
av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
abort();
}
if (frame->tf.f)
vp8_release_frame(frame);
return frame;
}
static enum AVPixelFormat get_pixel_format(VP8Context *s)
{
enum AVPixelFormat pix_fmts[] = {
#if CONFIG_VP8_VAAPI_HWACCEL
AV_PIX_FMT_VAAPI,
#endif
#if CONFIG_VP8_NVDEC_HWACCEL
AV_PIX_FMT_CUDA,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE,
};
return ff_get_format(s->avctx, pix_fmts);
}
static av_always_inline
int update_dimensions(VP8Context *s, int width, int height, int is_vp7)
{
AVCodecContext *avctx = s->avctx;
int i, ret, dim_reset = 0;
if (width != s->avctx->width || ((width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) && s->macroblocks_base ||
height != s->avctx->height) {
vp8_decode_flush_impl(s->avctx, 1);
ret = ff_set_dimensions(s->avctx, width, height);
if (ret < 0)
return ret;
dim_reset = (s->macroblocks_base != NULL);
}
if ((s->pix_fmt == AV_PIX_FMT_NONE || dim_reset) &&
!s->actually_webp && !is_vp7) {
s->pix_fmt = get_pixel_format(s);
if (s->pix_fmt < 0)
return AVERROR(EINVAL);
avctx->pix_fmt = s->pix_fmt;
}
s->mb_width = (s->avctx->coded_width + 15) / 16;
s->mb_height = (s->avctx->coded_height + 15) / 16;
s->mb_layout = is_vp7 || avctx->active_thread_type == FF_THREAD_SLICE &&
avctx->thread_count > 1;
if (!s->mb_layout) { // Frame threading and one thread
s->macroblocks_base = av_mallocz((s->mb_width + s->mb_height * 2 + 1) *
sizeof(*s->macroblocks));
s->intra4x4_pred_mode_top = av_mallocz(s->mb_width * 4);
} else // Sliced threading
s->macroblocks_base = av_mallocz((s->mb_width + 2) * (s->mb_height + 2) *
sizeof(*s->macroblocks));
s->top_nnz = av_mallocz(s->mb_width * sizeof(*s->top_nnz));
s->top_border = av_mallocz((s->mb_width + 1) * sizeof(*s->top_border));
s->thread_data = av_mallocz(MAX_THREADS * sizeof(VP8ThreadData));
if (!s->macroblocks_base || !s->top_nnz || !s->top_border ||
!s->thread_data || (!s->intra4x4_pred_mode_top && !s->mb_layout)) {
free_buffers(s);
return AVERROR(ENOMEM);
}
for (i = 0; i < MAX_THREADS; i++) {
s->thread_data[i].filter_strength =
av_mallocz(s->mb_width * sizeof(*s->thread_data[0].filter_strength));
if (!s->thread_data[i].filter_strength) {
free_buffers(s);
return AVERROR(ENOMEM);
}
#if HAVE_THREADS
ret = pthread_mutex_init(&s->thread_data[i].lock, NULL);
if (ret) {
free_buffers(s);
return AVERROR(ret);
}
ret = pthread_cond_init(&s->thread_data[i].cond, NULL);
if (ret) {
free_buffers(s);
return AVERROR(ret);
}
#endif
}
s->macroblocks = s->macroblocks_base + 1;
return 0;
}
static int vp7_update_dimensions(VP8Context *s, int width, int height)
{
return update_dimensions(s, width, height, IS_VP7);
}
static int vp8_update_dimensions(VP8Context *s, int width, int height)
{
return update_dimensions(s, width, height, IS_VP8);
}
static void parse_segment_info(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int i;
s->segmentation.update_map = vp89_rac_get(c);
s->segmentation.update_feature_data = vp89_rac_get(c);
if (s->segmentation.update_feature_data) {
s->segmentation.absolute_vals = vp89_rac_get(c);
for (i = 0; i < 4; i++)
s->segmentation.base_quant[i] = vp8_rac_get_sint(c, 7);
for (i = 0; i < 4; i++)
s->segmentation.filter_level[i] = vp8_rac_get_sint(c, 6);
}
if (s->segmentation.update_map)
for (i = 0; i < 3; i++)
s->prob->segmentid[i] = vp89_rac_get(c) ? vp89_rac_get_uint(c, 8) : 255;
}
static void update_lf_deltas(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int i;
for (i = 0; i < 4; i++) {
if (vp89_rac_get(c)) {
s->lf_delta.ref[i] = vp89_rac_get_uint(c, 6);
if (vp89_rac_get(c))
s->lf_delta.ref[i] = -s->lf_delta.ref[i];
}
}
for (i = MODE_I4x4; i <= VP8_MVMODE_SPLIT; i++) {
if (vp89_rac_get(c)) {
s->lf_delta.mode[i] = vp89_rac_get_uint(c, 6);
if (vp89_rac_get(c))
s->lf_delta.mode[i] = -s->lf_delta.mode[i];
}
}
}
static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
{
const uint8_t *sizes = buf;
int i;
int ret;
s->num_coeff_partitions = 1 << vp89_rac_get_uint(&s->c, 2);
buf += 3 * (s->num_coeff_partitions - 1);
buf_size -= 3 * (s->num_coeff_partitions - 1);
if (buf_size < 0)
return -1;
for (i = 0; i < s->num_coeff_partitions - 1; i++) {
int size = AV_RL24(sizes + 3 * i);
if (buf_size - size < 0)
return -1;
s->coeff_partition_size[i] = size;
ret = ff_vpx_init_range_decoder(&s->coeff_partition[i], buf, size);
if (ret < 0)
return ret;
buf += size;
buf_size -= size;
}
s->coeff_partition_size[i] = buf_size;
return ff_vpx_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
}
static void vp7_get_quants(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int yac_qi = vp89_rac_get_uint(c, 7);
int ydc_qi = vp89_rac_get(c) ? vp89_rac_get_uint(c, 7) : yac_qi;
int y2dc_qi = vp89_rac_get(c) ? vp89_rac_get_uint(c, 7) : yac_qi;
int y2ac_qi = vp89_rac_get(c) ? vp89_rac_get_uint(c, 7) : yac_qi;
int uvdc_qi = vp89_rac_get(c) ? vp89_rac_get_uint(c, 7) : yac_qi;
int uvac_qi = vp89_rac_get(c) ? vp89_rac_get_uint(c, 7) : yac_qi;
s->qmat[0].luma_qmul[0] = vp7_ydc_qlookup[ydc_qi];
s->qmat[0].luma_qmul[1] = vp7_yac_qlookup[yac_qi];
s->qmat[0].luma_dc_qmul[0] = vp7_y2dc_qlookup[y2dc_qi];
s->qmat[0].luma_dc_qmul[1] = vp7_y2ac_qlookup[y2ac_qi];
s->qmat[0].chroma_qmul[0] = FFMIN(vp7_ydc_qlookup[uvdc_qi], 132);
s->qmat[0].chroma_qmul[1] = vp7_yac_qlookup[uvac_qi];
}
static void vp8_get_quants(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int i, base_qi;
s->quant.yac_qi = vp89_rac_get_uint(c, 7);
s->quant.ydc_delta = vp8_rac_get_sint(c, 4);
s->quant.y2dc_delta = vp8_rac_get_sint(c, 4);
s->quant.y2ac_delta = vp8_rac_get_sint(c, 4);
s->quant.uvdc_delta = vp8_rac_get_sint(c, 4);
s->quant.uvac_delta = vp8_rac_get_sint(c, 4);
for (i = 0; i < 4; i++) {
if (s->segmentation.enabled) {
base_qi = s->segmentation.base_quant[i];
if (!s->segmentation.absolute_vals)
base_qi += s->quant.yac_qi;
} else
base_qi = s->quant.yac_qi;
s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.ydc_delta, 7)];
s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)];
s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7)] * 2;
/* 101581>>16 is equivalent to 155/100 */
s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7)] * 101581 >> 16;
s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7)];
s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.uvac_delta, 7)];
s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8);
s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132);
}
}
/**
* Determine which buffers golden and altref should be updated with after this frame.
* The spec isn't clear here, so I'm going by my understanding of what libvpx does
*
* Intra frames update all 3 references
* Inter frames update VP8_FRAME_PREVIOUS if the update_last flag is set
* If the update (golden|altref) flag is set, it's updated with the current frame
* if update_last is set, and VP8_FRAME_PREVIOUS otherwise.
* If the flag is not set, the number read means:
* 0: no update
* 1: VP8_FRAME_PREVIOUS
* 2: update golden with altref, or update altref with golden
*/
static VP8FrameType ref_to_update(VP8Context *s, int update, VP8FrameType ref)
{
VPXRangeCoder *c = &s->c;
if (update)
return VP8_FRAME_CURRENT;
switch (vp89_rac_get_uint(c, 2)) {
case 1:
return VP8_FRAME_PREVIOUS;
case 2:
return (ref == VP8_FRAME_GOLDEN) ? VP8_FRAME_ALTREF : VP8_FRAME_GOLDEN;
}
return VP8_FRAME_NONE;
}
static void vp78_reset_probability_tables(VP8Context *s)
{
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 16; j++)
memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]],
sizeof(s->prob->token[i][j]));
}
static void vp78_update_probability_tables(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int i, j, k, l, m;
for (i = 0; i < 4; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 3; k++)
for (l = 0; l < NUM_DCT_TOKENS-1; l++)
if (vpx_rac_get_prob_branchy(c, ff_vp8_token_update_probs[i][j][k][l])) {
int prob = vp89_rac_get_uint(c, 8);
for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++)
s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob;
}
}
#define VP7_MVC_SIZE 17
#define VP8_MVC_SIZE 19
static void vp78_update_pred16x16_pred8x8_mvc_probabilities(VP8Context *s,
int mvc_size)
{
VPXRangeCoder *c = &s->c;
int i, j;
if (vp89_rac_get(c))
for (i = 0; i < 4; i++)
s->prob->pred16x16[i] = vp89_rac_get_uint(c, 8);
if (vp89_rac_get(c))
for (i = 0; i < 3; i++)
s->prob->pred8x8c[i] = vp89_rac_get_uint(c, 8);
// 17.2 MV probability update
for (i = 0; i < 2; i++)
for (j = 0; j < mvc_size; j++)
if (vpx_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j]))
s->prob->mvc[i][j] = vp8_rac_get_nn(c);
}
static void update_refs(VP8Context *s)
{
VPXRangeCoder *c = &s->c;
int update_golden = vp89_rac_get(c);
int update_altref = vp89_rac_get(c);
s->update_golden = ref_to_update(s, update_golden, VP8_FRAME_GOLDEN);
s->update_altref = ref_to_update(s, update_altref, VP8_FRAME_ALTREF);
}
static void copy_chroma(AVFrame *dst, const AVFrame *src, int width, int height)
{
int i, j;
for (j = 1; j < 3; j++) {
for (i = 0; i < height / 2; i++)
memcpy(dst->data[j] + i * dst->linesize[j],
src->data[j] + i * src->linesize[j], width / 2);
}
}
static void fade(uint8_t *dst, ptrdiff_t dst_linesize,
const uint8_t *src, ptrdiff_t src_linesize,
int width, int height,
int alpha, int beta)
{
int i, j;
for (j = 0; j < height; j++) {
const uint8_t *src2 = src + j * src_linesize;
uint8_t *dst2 = dst + j * dst_linesize;
for (i = 0; i < width; i++) {
uint8_t y = src2[i];
dst2[i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha);
}
}
}
static int vp7_fade_frame(VP8Context *s, int alpha, int beta)
{
int ret;
if (!s->keyframe && (alpha || beta)) {
int width = s->mb_width * 16;
int height = s->mb_height * 16;
const AVFrame *src;
AVFrame *dst;
if (!s->framep[VP8_FRAME_PREVIOUS] ||
!s->framep[VP8_FRAME_GOLDEN]) {
av_log(s->avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");
return AVERROR_INVALIDDATA;
}
src =
dst = s->framep[VP8_FRAME_PREVIOUS]->tf.f;
/* preserve the golden frame, write a new previous frame */
if (s->framep[VP8_FRAME_GOLDEN] == s->framep[VP8_FRAME_PREVIOUS]) {
s->framep[VP8_FRAME_PREVIOUS] = vp8_find_free_buffer(s);
if ((ret = vp8_alloc_frame(s, s->framep[VP8_FRAME_PREVIOUS], 1)) < 0)
return ret;
dst = s->framep[VP8_FRAME_PREVIOUS]->tf.f;
copy_chroma(dst, src, width, height);
}
fade(dst->data[0], dst->linesize[0],
src->data[0], src->linesize[0],
width, height, alpha, beta);
}
return 0;
}
static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
{
VPXRangeCoder *c = &s->c;
int part1_size, hscale, vscale, i, j, ret;
int width = s->avctx->width;
int height = s->avctx->height;
int alpha = 0;
int beta = 0;
int fade_present = 1;
if (buf_size < 4) {
return AVERROR_INVALIDDATA;
}
s->profile = (buf[0] >> 1) & 7;
if (s->profile > 1) {
avpriv_request_sample(s->avctx, "Unknown profile %d", s->profile);
return AVERROR_INVALIDDATA;
}
s->keyframe = !(buf[0] & 1);
s->invisible = 0;
part1_size = AV_RL24(buf) >> 4;
if (buf_size < 4 - s->profile + part1_size) {
av_log(s->avctx, AV_LOG_ERROR, "Buffer size %d is too small, needed : %d\n", buf_size, 4 - s->profile + part1_size);
return AVERROR_INVALIDDATA;
}
buf += 4 - s->profile;
buf_size -= 4 - s->profile;
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab));
ret = ff_vpx_init_range_decoder(c, buf, part1_size);
if (ret < 0)
return ret;
buf += part1_size;
buf_size -= part1_size;
/* A. Dimension information (keyframes only) */
if (s->keyframe) {
width = vp89_rac_get_uint(c, 12);
height = vp89_rac_get_uint(c, 12);
hscale = vp89_rac_get_uint(c, 2);
vscale = vp89_rac_get_uint(c, 2);
if (hscale || vscale)
avpriv_request_sample(s->avctx, "Upscaling");
s->update_golden = s->update_altref = VP8_FRAME_CURRENT;
vp78_reset_probability_tables(s);
memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter,
sizeof(s->prob->pred16x16));
memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter,
sizeof(s->prob->pred8x8c));
for (i = 0; i < 2; i++)
memcpy(s->prob->mvc[i], vp7_mv_default_prob[i],
sizeof(vp7_mv_default_prob[i]));
memset(&s->segmentation, 0, sizeof(s->segmentation));
memset(&s->lf_delta, 0, sizeof(s->lf_delta));
memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan));
}
if (s->keyframe || s->profile > 0)
memset(s->inter_dc_pred, 0 , sizeof(s->inter_dc_pred));
/* B. Decoding information for all four macroblock-level features */
for (i = 0; i < 4; i++) {
s->feature_enabled[i] = vp89_rac_get(c);
if (s->feature_enabled[i]) {
s->feature_present_prob[i] = vp89_rac_get_uint(c, 8);
for (j = 0; j < 3; j++)
s->feature_index_prob[i][j] =
vp89_rac_get(c) ? vp89_rac_get_uint(c, 8) : 255;
if (vp7_feature_value_size[s->profile][i])
for (j = 0; j < 4; j++)
s->feature_value[i][j] =
vp89_rac_get(c) ? vp89_rac_get_uint(c, vp7_feature_value_size[s->profile][i]) : 0;
}
}
s->segmentation.enabled = 0;
s->segmentation.update_map = 0;
s->lf_delta.enabled = 0;
s->num_coeff_partitions = 1;
ret = ff_vpx_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
if (ret < 0)
return ret;
if (!s->macroblocks_base || /* first frame */
width != s->avctx->width || height != s->avctx->height ||
(width + 15) / 16 != s->mb_width || (height + 15) / 16 != s->mb_height) {
if ((ret = vp7_update_dimensions(s, width, height)) < 0)
return ret;
}
/* C. Dequantization indices */
vp7_get_quants(s);
/* D. Golden frame update flag (a Flag) for interframes only */
if (!s->keyframe) {
s->update_golden = vp89_rac_get(c) ? VP8_FRAME_CURRENT : VP8_FRAME_NONE;
s->sign_bias[VP8_FRAME_GOLDEN] = 0;
}
s->update_last = 1;
s->update_probabilities = 1;
if (s->profile > 0) {
s->update_probabilities = vp89_rac_get(c);
if (!s->update_probabilities)
s->prob[1] = s->prob[0];
if (!s->keyframe)
fade_present = vp89_rac_get(c);
}
if (vpx_rac_is_end(c))
return AVERROR_INVALIDDATA;
/* E. Fading information for previous frame */
if (fade_present && vp89_rac_get(c)) {
alpha = (int8_t) vp89_rac_get_uint(c, 8);
beta = (int8_t) vp89_rac_get_uint(c, 8);
}
/* F. Loop filter type */
if (!s->profile)
s->filter.simple = vp89_rac_get(c);
/* G. DCT coefficient ordering specification */
if (vp89_rac_get(c))
for (i = 1; i < 16; i++)
s->prob[0].scan[i] = ff_zigzag_scan[vp89_rac_get_uint(c, 4)];
/* H. Loop filter levels */
if (s->profile > 0)
s->filter.simple = vp89_rac_get(c);
s->filter.level = vp89_rac_get_uint(c, 6);
s->filter.sharpness = vp89_rac_get_uint(c, 3);
/* I. DCT coefficient probability update; 13.3 Token Probability Updates */
vp78_update_probability_tables(s);
s->mbskip_enabled = 0;
/* J. The remaining frame header data occurs ONLY FOR INTERFRAMES */
if (!s->keyframe) {
s->prob->intra = vp89_rac_get_uint(c, 8);
s->prob->last = vp89_rac_get_uint(c, 8);
vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP7_MVC_SIZE);
}
if (vpx_rac_is_end(c))
return AVERROR_INVALIDDATA;
if ((ret = vp7_fade_frame(s, alpha, beta)) < 0)
return ret;
return 0;
}
static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
{
VPXRangeCoder *c = &s->c;
int header_size, hscale, vscale, ret;
int width = s->avctx->width;
int height = s->avctx->height;
if (buf_size < 3) {
av_log(s->avctx, AV_LOG_ERROR, "Insufficent data (%d) for header\n", buf_size);
return AVERROR_INVALIDDATA;
}
s->keyframe = !(buf[0] & 1);
s->profile = (buf[0]>>1) & 7;
s->invisible = !(buf[0] & 0x10);
header_size = AV_RL24(buf) >> 5;
buf += 3;
buf_size -= 3;
s->header_partition_size = header_size;
if (s->profile > 3)
av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);
if (!s->profile)
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab,
sizeof(s->put_pixels_tab));
else // profile 1-3 use bilinear, 4+ aren't defined so whatever
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab,
sizeof(s->put_pixels_tab));
if (header_size > buf_size - 7 * s->keyframe) {
av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n");
return AVERROR_INVALIDDATA;
}
if (s->keyframe) {
if (AV_RL24(buf) != 0x2a019d) {
av_log(s->avctx, AV_LOG_ERROR,
"Invalid start code 0x%x\n", AV_RL24(buf));
return AVERROR_INVALIDDATA;
}
width = AV_RL16(buf + 3) & 0x3fff;
height = AV_RL16(buf + 5) & 0x3fff;
hscale = buf[4] >> 6;
vscale = buf[6] >> 6;
buf += 7;
buf_size -= 7;
if (hscale || vscale)
avpriv_request_sample(s->avctx, "Upscaling");
s->update_golden = s->update_altref = VP8_FRAME_CURRENT;
vp78_reset_probability_tables(s);
memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter,
sizeof(s->prob->pred16x16));
memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter,
sizeof(s->prob->pred8x8c));
memcpy(s->prob->mvc, vp8_mv_default_prob,
sizeof(s->prob->mvc));
memset(&s->segmentation, 0, sizeof(s->segmentation));
memset(&s->lf_delta, 0, sizeof(s->lf_delta));
}
ret = ff_vpx_init_range_decoder(c, buf, header_size);
if (ret < 0)
return ret;
buf += header_size;
buf_size -= header_size;
if (s->keyframe) {
s->colorspace = vp89_rac_get(c);
if (s->colorspace)
av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n");
s->fullrange = vp89_rac_get(c);
}
if ((s->segmentation.enabled = vp89_rac_get(c)))
parse_segment_info(s);
else
s->segmentation.update_map = 0; // FIXME: move this to some init function?
s->filter.simple = vp89_rac_get(c);
s->filter.level = vp89_rac_get_uint(c, 6);
s->filter.sharpness = vp89_rac_get_uint(c, 3);
if ((s->lf_delta.enabled = vp89_rac_get(c))) {
s->lf_delta.update = vp89_rac_get(c);
if (s->lf_delta.update)
update_lf_deltas(s);
}
if (setup_partitions(s, buf, buf_size)) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");
return AVERROR_INVALIDDATA;
}
if (!s->macroblocks_base || /* first frame */
width != s->avctx->width || height != s->avctx->height ||
(width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height)
if ((ret = vp8_update_dimensions(s, width, height)) < 0)
return ret;
vp8_get_quants(s);
if (!s->keyframe) {
update_refs(s);
s->sign_bias[VP8_FRAME_GOLDEN] = vp89_rac_get(c);
s->sign_bias[VP8_FRAME_ALTREF] = vp89_rac_get(c);
}
// if we aren't saving this frame's probabilities for future frames,
// make a copy of the current probabilities
if (!(s->update_probabilities = vp89_rac_get(c)))
s->prob[1] = s->prob[0];
s->update_last = s->keyframe || vp89_rac_get(c);
vp78_update_probability_tables(s);
if ((s->mbskip_enabled = vp89_rac_get(c)))
s->prob->mbskip = vp89_rac_get_uint(c, 8);
if (!s->keyframe) {
s->prob->intra = vp89_rac_get_uint(c, 8);
s->prob->last = vp89_rac_get_uint(c, 8);
s->prob->golden = vp89_rac_get_uint(c, 8);
vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE);
}
// Record the entropy coder state here so that hwaccels can use it.
s->c.code_word = vpx_rac_renorm(&s->c);
s->coder_state_at_header_end.input = s->c.buffer - (-s->c.bits / 8);
s->coder_state_at_header_end.range = s->c.high;
s->coder_state_at_header_end.value = s->c.code_word >> 16;
s->coder_state_at_header_end.bit_count = -s->c.bits % 8;
return 0;
}
static av_always_inline
void clamp_mv(const VP8mvbounds *s, VP8mv *dst, const VP8mv *src)
{
dst->x = av_clip(src->x, av_clip(s->mv_min.x, INT16_MIN, INT16_MAX),
av_clip(s->mv_max.x, INT16_MIN, INT16_MAX));
dst->y = av_clip(src->y, av_clip(s->mv_min.y, INT16_MIN, INT16_MAX),
av_clip(s->mv_max.y, INT16_MIN, INT16_MAX));
}
/**
* Motion vector coding, 17.1.
*/
static av_always_inline int read_mv_component(VPXRangeCoder *c, const uint8_t *p, int vp7)
{
int bit, x = 0;
if (vpx_rac_get_prob_branchy(c, p[0])) {
int i;
for (i = 0; i < 3; i++)
x += vpx_rac_get_prob(c, p[9 + i]) << i;
for (i = (vp7 ? 7 : 9); i > 3; i--)
x += vpx_rac_get_prob(c, p[9 + i]) << i;
if (!(x & (vp7 ? 0xF0 : 0xFFF0)) || vpx_rac_get_prob(c, p[12]))
x += 8;
} else {
// small_mvtree
const uint8_t *ps = p + 2;
bit = vpx_rac_get_prob(c, *ps);
ps += 1 + 3 * bit;
x += 4 * bit;
bit = vpx_rac_get_prob(c, *ps);
ps += 1 + bit;
x += 2 * bit;
x += vpx_rac_get_prob(c, *ps);
}
return (x && vpx_rac_get_prob(c, p[1])) ? -x : x;
}
static int vp7_read_mv_component(VPXRangeCoder *c, const uint8_t *p)
{
return read_mv_component(c, p, 1);
}
static int vp8_read_mv_component(VPXRangeCoder *c, const uint8_t *p)
{
return read_mv_component(c, p, 0);
}
static av_always_inline
const uint8_t *get_submv_prob(uint32_t left, uint32_t top, int is_vp7)
{
if (is_vp7)
return vp7_submv_prob;
if (left == top)
return vp8_submv_prob[4 - !!left];
if (!top)
return vp8_submv_prob[2];
return vp8_submv_prob[1 - !!left];
}
/**
* Split motion vector prediction, 16.4.
* @returns the number of motion vectors parsed (2, 4 or 16)
*/
static av_always_inline
int decode_splitmvs(const VP8Context *s, VPXRangeCoder *c, VP8Macroblock *mb,
int layout, int is_vp7)
{
int part_idx;
int n, num;
const VP8Macroblock *top_mb;
const VP8Macroblock *left_mb = &mb[-1];
const uint8_t *mbsplits_left = vp8_mbsplits[left_mb->partitioning];
const uint8_t *mbsplits_top, *mbsplits_cur, *firstidx;
const VP8mv *top_mv;
const VP8mv *left_mv = left_mb->bmv;
const VP8mv *cur_mv = mb->bmv;
if (!layout) // layout is inlined, s->mb_layout is not
top_mb = &mb[2];
else
top_mb = &mb[-s->mb_width - 1];
mbsplits_top = vp8_mbsplits[top_mb->partitioning];
top_mv = top_mb->bmv;
if (vpx_rac_get_prob_branchy(c, vp8_mbsplit_prob[0])) {
if (vpx_rac_get_prob_branchy(c, vp8_mbsplit_prob[1]))
part_idx = VP8_SPLITMVMODE_16x8 + vpx_rac_get_prob(c, vp8_mbsplit_prob[2]);
else
part_idx = VP8_SPLITMVMODE_8x8;
} else {
part_idx = VP8_SPLITMVMODE_4x4;
}
num = vp8_mbsplit_count[part_idx];
mbsplits_cur = vp8_mbsplits[part_idx],
firstidx = vp8_mbfirstidx[part_idx];
mb->partitioning = part_idx;
for (n = 0; n < num; n++) {
int k = firstidx[n];
uint32_t left, above;
const uint8_t *submv_prob;
if (!(k & 3))
left = AV_RN32A(&left_mv[mbsplits_left[k + 3]]);
else
left = AV_RN32A(&cur_mv[mbsplits_cur[k - 1]]);
if (k <= 3)
above = AV_RN32A(&top_mv[mbsplits_top[k + 12]]);
else
above = AV_RN32A(&cur_mv[mbsplits_cur[k - 4]]);
submv_prob = get_submv_prob(left, above, is_vp7);
if (vpx_rac_get_prob_branchy(c, submv_prob[0])) {
if (vpx_rac_get_prob_branchy(c, submv_prob[1])) {
if (vpx_rac_get_prob_branchy(c, submv_prob[2])) {
mb->bmv[n].y = mb->mv.y +
read_mv_component(c, s->prob->mvc[0], is_vp7);
mb->bmv[n].x = mb->mv.x +
read_mv_component(c, s->prob->mvc[1], is_vp7);
} else {
AV_ZERO32(&mb->bmv[n]);
}
} else {
AV_WN32A(&mb->bmv[n], above);
}
} else {
AV_WN32A(&mb->bmv[n], left);
}
}
return num;
}
/**
* The vp7 reference decoder uses a padding macroblock column (added to right
* edge of the frame) to guard against illegal macroblock offsets. The
* algorithm has bugs that permit offsets to straddle the padding column.
* This function replicates those bugs.
*
* @param[out] edge_x macroblock x address
* @param[out] edge_y macroblock y address
*
* @return macroblock offset legal (boolean)
*/
static int vp7_calculate_mb_offset(int mb_x, int mb_y, int mb_width,
int xoffset, int yoffset, int boundary,
int *edge_x, int *edge_y)
{
int vwidth = mb_width + 1;
int new = (mb_y + yoffset) * vwidth + mb_x + xoffset;
if (new < boundary || new % vwidth == vwidth - 1)
return 0;
*edge_y = new / vwidth;
*edge_x = new % vwidth;
return 1;
}
static const VP8mv *get_bmv_ptr(const VP8Macroblock *mb, int subblock)
{
return &mb->bmv[mb->mode == VP8_MVMODE_SPLIT ? vp8_mbsplits[mb->partitioning][subblock] : 0];
}
static av_always_inline
void vp7_decode_mvs(VP8Context *s, VP8Macroblock *mb,
int mb_x, int mb_y, int layout)
{
enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR };
enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT };
int idx = CNT_ZERO;
VP8mv near_mv[3];
uint8_t cnt[3] = { 0 };
VPXRangeCoder *c = &s->c;
int i;
AV_ZERO32(&near_mv[0]);
AV_ZERO32(&near_mv[1]);
AV_ZERO32(&near_mv[2]);
for (i = 0; i < VP7_MV_PRED_COUNT; i++) {
const VP7MVPred * pred = &vp7_mv_pred[i];
int edge_x, edge_y;
if (vp7_calculate_mb_offset(mb_x, mb_y, s->mb_width, pred->xoffset,
pred->yoffset, !s->profile, &edge_x, &edge_y)) {
const VP8Macroblock *edge = (s->mb_layout == 1)
? s->macroblocks_base + 1 + edge_x +
(s->mb_width + 1) * (edge_y + 1)
: s->macroblocks + edge_x +
(s->mb_height - edge_y - 1) * 2;
uint32_t mv = AV_RN32A(get_bmv_ptr(edge, vp7_mv_pred[i].subblock));
if (mv) {
if (AV_RN32A(&near_mv[CNT_NEAREST])) {
if (mv == AV_RN32A(&near_mv[CNT_NEAREST])) {
idx = CNT_NEAREST;
} else if (AV_RN32A(&near_mv[CNT_NEAR])) {
if (mv != AV_RN32A(&near_mv[CNT_NEAR]))
continue;
idx = CNT_NEAR;
} else {
AV_WN32A(&near_mv[CNT_NEAR], mv);
idx = CNT_NEAR;
}
} else {
AV_WN32A(&near_mv[CNT_NEAREST], mv);
idx = CNT_NEAREST;
}
} else {
idx = CNT_ZERO;
}
} else {
idx = CNT_ZERO;
}
cnt[idx] += vp7_mv_pred[i].score;
}
mb->partitioning = VP8_SPLITMVMODE_NONE;
if (vpx_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_ZERO]][0])) {
mb->mode = VP8_MVMODE_MV;
if (vpx_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAREST]][1])) {
if (vpx_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][2])) {
if (cnt[CNT_NEAREST] > cnt[CNT_NEAR])
AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAREST] ? 0 : AV_RN32A(&near_mv[CNT_NEAREST]));
else
AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAR] ? 0 : AV_RN32A(&near_mv[CNT_NEAR]));
if (vpx_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][3])) {
mb->mode = VP8_MVMODE_SPLIT;
mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP7) - 1];
} else {
mb->mv.y += vp7_read_mv_component(c, s->prob->mvc[0]);
mb->mv.x += vp7_read_mv_component(c, s->prob->mvc[1]);
mb->bmv[0] = mb->mv;
}
} else {
mb->mv = near_mv[CNT_NEAR];
mb->bmv[0] = mb->mv;
}
} else {
mb->mv = near_mv[CNT_NEAREST];
mb->bmv[0] = mb->mv;
}
} else {
mb->mode = VP8_MVMODE_ZERO;
AV_ZERO32(&mb->mv);
mb->bmv[0] = mb->mv;
}
}
static av_always_inline
void vp8_decode_mvs(VP8Context *s, const VP8mvbounds *mv_bounds, VP8Macroblock *mb,
int mb_x, int mb_y, int layout)
{
VP8Macroblock *mb_edge[3] = { 0 /* top */,
mb - 1 /* left */,
0 /* top-left */ };
enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV };
enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT };
int idx = CNT_ZERO;
int cur_sign_bias = s->sign_bias[mb->ref_frame];
const int8_t *sign_bias = s->sign_bias;
VP8mv near_mv[4];
uint8_t cnt[4] = { 0 };
VPXRangeCoder *c = &s->c;
if (!layout) { // layout is inlined (s->mb_layout is not)
mb_edge[0] = mb + 2;
mb_edge[2] = mb + 1;
} else {
mb_edge[0] = mb - s->mb_width - 1;
mb_edge[2] = mb - s->mb_width - 2;
}
AV_ZERO32(&near_mv[0]);
AV_ZERO32(&near_mv[1]);
AV_ZERO32(&near_mv[2]);
/* Process MB on top, left and top-left */
#define MV_EDGE_CHECK(n) \
{ \
const VP8Macroblock *edge = mb_edge[n]; \
int edge_ref = edge->ref_frame; \
if (edge_ref != VP8_FRAME_CURRENT) { \
uint32_t mv = AV_RN32A(&edge->mv); \
if (mv) { \
if (cur_sign_bias != sign_bias[edge_ref]) { \
/* SWAR negate of the values in mv. */ \
mv = ~mv; \
mv = ((mv & 0x7fff7fff) + \
0x00010001) ^ (mv & 0x80008000); \
} \
if (!n || mv != AV_RN32A(&near_mv[idx])) \
AV_WN32A(&near_mv[++idx], mv); \
cnt[idx] += 1 + (n != 2); \
} else \
cnt[CNT_ZERO] += 1 + (n != 2); \
} \
}
MV_EDGE_CHECK(0)
MV_EDGE_CHECK(1)
MV_EDGE_CHECK(2)
mb->partitioning = VP8_SPLITMVMODE_NONE;
if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_ZERO]][0])) {
mb->mode = VP8_MVMODE_MV;
/* If we have three distinct MVs, merge first and last if they're the same */
if (cnt[CNT_SPLITMV] &&
AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT]))
cnt[CNT_NEAREST] += 1;
/* Swap near and nearest if necessary */
if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
FFSWAP(uint8_t, cnt[CNT_NEAREST], cnt[CNT_NEAR]);
FFSWAP(VP8mv, near_mv[CNT_NEAREST], near_mv[CNT_NEAR]);
}
if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) {
if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) {
/* Choose the best mv out of 0,0 and the nearest mv */
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode == VP8_MVMODE_SPLIT) +
(mb_edge[VP8_EDGE_TOP]->mode == VP8_MVMODE_SPLIT)) * 2 +
(mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT);
if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_SPLITMV]][3])) {
mb->mode = VP8_MVMODE_SPLIT;
mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP8) - 1];
} else {
mb->mv.y += vp8_read_mv_component(c, s->prob->mvc[0]);
mb->mv.x += vp8_read_mv_component(c, s->prob->mvc[1]);
mb->bmv[0] = mb->mv;
}
} else {
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAR]);
mb->bmv[0] = mb->mv;
}
} else {
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAREST]);
mb->bmv[0] = mb->mv;
}
} else {
mb->mode = VP8_MVMODE_ZERO;
AV_ZERO32(&mb->mv);
mb->bmv[0] = mb->mv;
}
}
static av_always_inline
void decode_intra4x4_modes(VP8Context *s, VPXRangeCoder *c, VP8Macroblock *mb,
int mb_x, int keyframe, int layout)
{
uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb;
if (layout) {
VP8Macroblock *mb_top = mb - s->mb_width - 1;
memcpy(mb->intra4x4_pred_mode_top, mb_top->intra4x4_pred_mode_top, 4);
}
if (keyframe) {
int x, y;
uint8_t *top;
uint8_t *const left = s->intra4x4_pred_mode_left;
if (layout)
top = mb->intra4x4_pred_mode_top;
else
top = s->intra4x4_pred_mode_top + 4 * mb_x;
for (y = 0; y < 4; y++) {
for (x = 0; x < 4; x++) {
const uint8_t *ctx;
ctx = vp8_pred4x4_prob_intra[top[x]][left[y]];
*intra4x4 = vp89_rac_get_tree(c