mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
9f00fa5369
Also adds some extra fields to the main context structure that may be needed by a hwaccel decoder. The current behaviour of the WebP decoder is maintained by adding an additional field to the VP8 decoder private context to indicate that it is actually being used as WebP (no hwaccel is supported for that case).
352 lines
9.8 KiB
C
352 lines
9.8 KiB
C
/*
|
|
* 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
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef AVCODEC_VP8_H
|
|
#define AVCODEC_VP8_H
|
|
|
|
#include <stdatomic.h>
|
|
|
|
#include "libavutil/buffer.h"
|
|
#include "libavutil/thread.h"
|
|
|
|
#include "h264pred.h"
|
|
#include "thread.h"
|
|
#include "vp56.h"
|
|
#include "vp8dsp.h"
|
|
|
|
#define VP8_MAX_QUANT 127
|
|
|
|
enum dct_token {
|
|
DCT_0,
|
|
DCT_1,
|
|
DCT_2,
|
|
DCT_3,
|
|
DCT_4,
|
|
DCT_CAT1,
|
|
DCT_CAT2,
|
|
DCT_CAT3,
|
|
DCT_CAT4,
|
|
DCT_CAT5,
|
|
DCT_CAT6,
|
|
DCT_EOB,
|
|
|
|
NUM_DCT_TOKENS
|
|
};
|
|
|
|
// used to signal 4x4 intra pred in luma MBs
|
|
#define MODE_I4x4 4
|
|
|
|
enum inter_mvmode {
|
|
VP8_MVMODE_ZERO = MODE_I4x4 + 1,
|
|
VP8_MVMODE_MV,
|
|
VP8_MVMODE_SPLIT
|
|
};
|
|
|
|
enum inter_splitmvmode {
|
|
VP8_SPLITMVMODE_16x8 = 0, ///< 2 16x8 blocks (vertical)
|
|
VP8_SPLITMVMODE_8x16, ///< 2 8x16 blocks (horizontal)
|
|
VP8_SPLITMVMODE_8x8, ///< 2x2 blocks of 8x8px each
|
|
VP8_SPLITMVMODE_4x4, ///< 4x4 blocks of 4x4px each
|
|
VP8_SPLITMVMODE_NONE, ///< (only used in prediction) no split MVs
|
|
};
|
|
|
|
typedef struct VP8FilterStrength {
|
|
uint8_t filter_level;
|
|
uint8_t inner_limit;
|
|
uint8_t inner_filter;
|
|
} VP8FilterStrength;
|
|
|
|
typedef struct VP8Macroblock {
|
|
uint8_t skip;
|
|
// TODO: make it possible to check for at least (i4x4 or split_mv)
|
|
// in one op. are others needed?
|
|
uint8_t mode;
|
|
uint8_t ref_frame;
|
|
uint8_t partitioning;
|
|
uint8_t chroma_pred_mode;
|
|
uint8_t segment;
|
|
uint8_t intra4x4_pred_mode_mb[16];
|
|
DECLARE_ALIGNED(4, uint8_t, intra4x4_pred_mode_top)[4];
|
|
VP56mv mv;
|
|
VP56mv bmv[16];
|
|
} VP8Macroblock;
|
|
|
|
typedef struct VP8intmv {
|
|
int x;
|
|
int y;
|
|
} VP8intmv;
|
|
|
|
typedef struct VP8mvbounds {
|
|
VP8intmv mv_min;
|
|
VP8intmv mv_max;
|
|
} VP8mvbounds;
|
|
|
|
typedef struct VP8ThreadData {
|
|
DECLARE_ALIGNED(16, int16_t, block)[6][4][16];
|
|
DECLARE_ALIGNED(16, int16_t, block_dc)[16];
|
|
/**
|
|
* This is the index plus one of the last non-zero coeff
|
|
* for each of the blocks in the current macroblock.
|
|
* So, 0 -> no coeffs
|
|
* 1 -> dc-only (special transform)
|
|
* 2+-> full transform
|
|
*/
|
|
DECLARE_ALIGNED(16, uint8_t, non_zero_count_cache)[6][4];
|
|
/**
|
|
* For coeff decode, we need to know whether the above block had non-zero
|
|
* coefficients. This means for each macroblock, we need data for 4 luma
|
|
* blocks, 2 u blocks, 2 v blocks, and the luma dc block, for a total of 9
|
|
* per macroblock. We keep the last row in top_nnz.
|
|
*/
|
|
DECLARE_ALIGNED(8, uint8_t, left_nnz)[9];
|
|
int thread_nr;
|
|
#if HAVE_THREADS
|
|
pthread_mutex_t lock;
|
|
pthread_cond_t cond;
|
|
#endif
|
|
atomic_int thread_mb_pos; // (mb_y << 16) | (mb_x & 0xFFFF)
|
|
atomic_int wait_mb_pos; // What the current thread is waiting on.
|
|
|
|
#define EDGE_EMU_LINESIZE 32
|
|
DECLARE_ALIGNED(16, uint8_t, edge_emu_buffer)[21 * EDGE_EMU_LINESIZE];
|
|
VP8FilterStrength *filter_strength;
|
|
VP8mvbounds mv_bounds;
|
|
} VP8ThreadData;
|
|
|
|
typedef struct VP8Frame {
|
|
ThreadFrame tf;
|
|
AVBufferRef *seg_map;
|
|
|
|
AVBufferRef *hwaccel_priv_buf;
|
|
void *hwaccel_picture_private;
|
|
} VP8Frame;
|
|
|
|
#define MAX_THREADS 8
|
|
typedef struct VP8Context {
|
|
VP8ThreadData *thread_data;
|
|
AVCodecContext *avctx;
|
|
enum AVPixelFormat pix_fmt;
|
|
int actually_webp;
|
|
|
|
VP8Frame *framep[4];
|
|
VP8Frame *next_framep[4];
|
|
VP8Frame *curframe;
|
|
VP8Frame *prev_frame;
|
|
|
|
uint16_t mb_width; /* number of horizontal MB */
|
|
uint16_t mb_height; /* number of vertical MB */
|
|
ptrdiff_t linesize;
|
|
ptrdiff_t uvlinesize;
|
|
|
|
uint8_t keyframe;
|
|
uint8_t deblock_filter;
|
|
uint8_t mbskip_enabled;
|
|
uint8_t profile;
|
|
VP8mvbounds mv_bounds;
|
|
|
|
int8_t sign_bias[4]; ///< one state [0, 1] per ref frame type
|
|
int ref_count[3];
|
|
|
|
/**
|
|
* Base parameters for segmentation, i.e. per-macroblock parameters.
|
|
* These must be kept unchanged even if segmentation is not used for
|
|
* a frame, since the values persist between interframes.
|
|
*/
|
|
struct {
|
|
uint8_t enabled;
|
|
uint8_t absolute_vals;
|
|
uint8_t update_map;
|
|
uint8_t update_feature_data;
|
|
int8_t base_quant[4];
|
|
int8_t filter_level[4]; ///< base loop filter level
|
|
} segmentation;
|
|
|
|
struct {
|
|
uint8_t simple;
|
|
uint8_t level;
|
|
uint8_t sharpness;
|
|
} filter;
|
|
|
|
VP8Macroblock *macroblocks;
|
|
|
|
uint8_t *intra4x4_pred_mode_top;
|
|
uint8_t intra4x4_pred_mode_left[4];
|
|
|
|
/**
|
|
* Macroblocks can have one of 4 different quants in a frame when
|
|
* segmentation is enabled.
|
|
* If segmentation is disabled, only the first segment's values are used.
|
|
*/
|
|
struct {
|
|
// [0] - DC qmul [1] - AC qmul
|
|
int16_t luma_qmul[2];
|
|
int16_t luma_dc_qmul[2]; ///< luma dc-only block quant
|
|
int16_t chroma_qmul[2];
|
|
} qmat[4];
|
|
|
|
// Raw quantisation values, which may be needed by hwaccel decode.
|
|
struct {
|
|
int yac_qi;
|
|
int ydc_delta;
|
|
int y2dc_delta;
|
|
int y2ac_delta;
|
|
int uvdc_delta;
|
|
int uvac_delta;
|
|
} quant;
|
|
|
|
struct {
|
|
uint8_t enabled; ///< whether each mb can have a different strength based on mode/ref
|
|
uint8_t update;
|
|
|
|
/**
|
|
* filter strength adjustment for the following macroblock modes:
|
|
* [0-3] - i16x16 (always zero)
|
|
* [4] - i4x4
|
|
* [5] - zero mv
|
|
* [6] - inter modes except for zero or split mv
|
|
* [7] - split mv
|
|
* i16x16 modes never have any adjustment
|
|
*/
|
|
int8_t mode[VP8_MVMODE_SPLIT + 1];
|
|
|
|
/**
|
|
* filter strength adjustment for macroblocks that reference:
|
|
* [0] - intra / VP56_FRAME_CURRENT
|
|
* [1] - VP56_FRAME_PREVIOUS
|
|
* [2] - VP56_FRAME_GOLDEN
|
|
* [3] - altref / VP56_FRAME_GOLDEN2
|
|
*/
|
|
int8_t ref[4];
|
|
} lf_delta;
|
|
|
|
uint8_t (*top_border)[16 + 8 + 8];
|
|
uint8_t (*top_nnz)[9];
|
|
|
|
VP56RangeCoder c; ///< header context, includes mb modes and motion vectors
|
|
|
|
/* This contains the entropy coder state at the end of the header
|
|
* block, in the form specified by the standard. For use by
|
|
* hwaccels, so that a hardware decoder has the information to
|
|
* start decoding at the macroblock layer.
|
|
*/
|
|
struct {
|
|
const uint8_t *input;
|
|
uint32_t range;
|
|
uint32_t value;
|
|
int bit_count;
|
|
} coder_state_at_header_end;
|
|
|
|
int header_partition_size;
|
|
|
|
/**
|
|
* These are all of the updatable probabilities for binary decisions.
|
|
* They are only implicitly reset on keyframes, making it quite likely
|
|
* for an interframe to desync if a prior frame's header was corrupt
|
|
* or missing outright!
|
|
*/
|
|
struct {
|
|
uint8_t segmentid[3];
|
|
uint8_t mbskip;
|
|
uint8_t intra;
|
|
uint8_t last;
|
|
uint8_t golden;
|
|
uint8_t pred16x16[4];
|
|
uint8_t pred8x8c[3];
|
|
uint8_t token[4][16][3][NUM_DCT_TOKENS - 1];
|
|
uint8_t mvc[2][19];
|
|
uint8_t scan[16];
|
|
} prob[2];
|
|
|
|
VP8Macroblock *macroblocks_base;
|
|
int invisible;
|
|
int update_last; ///< update VP56_FRAME_PREVIOUS with the current one
|
|
int update_golden; ///< VP56_FRAME_NONE if not updated, or which frame to copy if so
|
|
int update_altref;
|
|
|
|
/**
|
|
* If this flag is not set, all the probability updates
|
|
* are discarded after this frame is decoded.
|
|
*/
|
|
int update_probabilities;
|
|
|
|
/**
|
|
* All coefficients are contained in separate arith coding contexts.
|
|
* There can be 1, 2, 4, or 8 of these after the header context.
|
|
*/
|
|
int num_coeff_partitions;
|
|
VP56RangeCoder coeff_partition[8];
|
|
int coeff_partition_size[8];
|
|
VideoDSPContext vdsp;
|
|
VP8DSPContext vp8dsp;
|
|
H264PredContext hpc;
|
|
vp8_mc_func put_pixels_tab[3][3][3];
|
|
VP8Frame frames[5];
|
|
|
|
uint8_t colorspace; ///< 0 is the only value allowed (meaning bt601)
|
|
uint8_t fullrange; ///< whether we can skip clamping in dsp functions
|
|
|
|
int num_jobs;
|
|
/**
|
|
* This describes the macroblock memory layout.
|
|
* 0 -> Only width+height*2+1 macroblocks allocated (frame/single thread).
|
|
* 1 -> Macroblocks for entire frame allocated (sliced thread).
|
|
*/
|
|
int mb_layout;
|
|
|
|
int (*decode_mb_row_no_filter)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr);
|
|
void (*filter_mb_row)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr);
|
|
|
|
int vp7;
|
|
|
|
/**
|
|
* Fade bit present in bitstream (VP7)
|
|
*/
|
|
int fade_present;
|
|
|
|
/**
|
|
* Interframe DC prediction (VP7)
|
|
* [0] VP56_FRAME_PREVIOUS
|
|
* [1] VP56_FRAME_GOLDEN
|
|
*/
|
|
uint16_t inter_dc_pred[2][2];
|
|
|
|
/**
|
|
* Macroblock features (VP7)
|
|
*/
|
|
uint8_t feature_enabled[4];
|
|
uint8_t feature_present_prob[4];
|
|
uint8_t feature_index_prob[4][3];
|
|
uint8_t feature_value[4][4];
|
|
} VP8Context;
|
|
|
|
int ff_vp8_decode_init(AVCodecContext *avctx);
|
|
|
|
int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
|
|
AVPacket *avpkt);
|
|
|
|
int ff_vp8_decode_free(AVCodecContext *avctx);
|
|
|
|
#endif /* AVCODEC_VP8_H */
|