📄 vp3.c
字号:
/*
* Copyright (C) 2003-2004 the ffmpeg project
*
* 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
*/
/**
* @file vp3.c
* On2 VP3 Video Decoder
*
* VP3 Video Decoder by Mike Melanson (mike at multimedia.cx)
* For more information about the VP3 coding process, visit:
* http://multimedia.cx/
*
* Theora decoder by Alex Beregszaszi
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "vp3data.h"
#include "xiph.h"
#define FRAGMENT_PIXELS 8
/*
* Debugging Variables
*
* Define one or more of the following compile-time variables to 1 to obtain
* elaborate information about certain aspects of the decoding process.
*
* KEYFRAMES_ONLY: set this to 1 to only see keyframes (VP3 slideshow mode)
* DEBUG_VP3: high-level decoding flow
* DEBUG_INIT: initialization parameters
* DEBUG_DEQUANTIZERS: display how the dequanization tables are built
* DEBUG_BLOCK_CODING: unpacking the superblock/macroblock/fragment coding
* DEBUG_MODES: unpacking the coding modes for individual fragments
* DEBUG_VECTORS: display the motion vectors
* DEBUG_TOKEN: display exhaustive information about each DCT token
* DEBUG_VLC: display the VLCs as they are extracted from the stream
* DEBUG_DC_PRED: display the process of reversing DC prediction
* DEBUG_IDCT: show every detail of the IDCT process
*/
#define KEYFRAMES_ONLY 0
#define DEBUG_VP3 0
#define DEBUG_INIT 0
#define DEBUG_DEQUANTIZERS 0
#define DEBUG_BLOCK_CODING 0
#define DEBUG_MODES 0
#define DEBUG_VECTORS 0
#define DEBUG_TOKEN 0
#define DEBUG_VLC 0
#define DEBUG_DC_PRED 0
#define DEBUG_IDCT 0
#if DEBUG_VP3
#define debug_vp3(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_vp3(const char *format, ...) { }
#endif
#if DEBUG_INIT
#define debug_init(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_init(const char *format, ...) { }
#endif
#if DEBUG_DEQUANTIZERS
#define debug_dequantizers(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_dequantizers(const char *format, ...) { }
#endif
#if DEBUG_BLOCK_CODING
#define debug_block_coding(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_block_coding(const char *format, ...) { }
#endif
#if DEBUG_MODES
#define debug_modes(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_modes(const char *format, ...) { }
#endif
#if DEBUG_VECTORS
#define debug_vectors(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_vectors(const char *format, ...) { }
#endif
#if DEBUG_TOKEN
#define debug_token(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_token(const char *format, ...) { }
#endif
#if DEBUG_VLC
#define debug_vlc(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_vlc(const char *format, ...) { }
#endif
#if DEBUG_DC_PRED
#define debug_dc_pred(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_dc_pred(const char *format, ...) { }
#endif
#if DEBUG_IDCT
#define debug_idct(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
#else
static inline void debug_idct(const char *format, ...) { }
#endif
typedef struct Coeff {
struct Coeff *next;
DCTELEM coeff;
uint8_t index;
} Coeff;
//FIXME split things out into their own arrays
typedef struct Vp3Fragment {
Coeff *next_coeff;
/* address of first pixel taking into account which plane the fragment
* lives on as well as the plane stride */
int first_pixel;
/* this is the macroblock that the fragment belongs to */
uint16_t macroblock;
uint8_t coding_method;
uint8_t coeff_count;
int8_t motion_x;
int8_t motion_y;
} Vp3Fragment;
#define SB_NOT_CODED 0
#define SB_PARTIALLY_CODED 1
#define SB_FULLY_CODED 2
#define MODE_INTER_NO_MV 0
#define MODE_INTRA 1
#define MODE_INTER_PLUS_MV 2
#define MODE_INTER_LAST_MV 3
#define MODE_INTER_PRIOR_LAST 4
#define MODE_USING_GOLDEN 5
#define MODE_GOLDEN_MV 6
#define MODE_INTER_FOURMV 7
#define CODING_MODE_COUNT 8
/* special internal mode */
#define MODE_COPY 8
/* There are 6 preset schemes, plus a free-form scheme */
static int ModeAlphabet[7][CODING_MODE_COUNT] =
{
/* this is the custom scheme */
{ 0, 0, 0, 0, 0, 0, 0, 0 },
/* scheme 1: Last motion vector dominates */
{ MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST,
MODE_INTER_PLUS_MV, MODE_INTER_NO_MV,
MODE_INTRA, MODE_USING_GOLDEN,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
/* scheme 2 */
{ MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST,
MODE_INTER_NO_MV, MODE_INTER_PLUS_MV,
MODE_INTRA, MODE_USING_GOLDEN,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
/* scheme 3 */
{ MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV,
MODE_INTER_PRIOR_LAST, MODE_INTER_NO_MV,
MODE_INTRA, MODE_USING_GOLDEN,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
/* scheme 4 */
{ MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV,
MODE_INTER_NO_MV, MODE_INTER_PRIOR_LAST,
MODE_INTRA, MODE_USING_GOLDEN,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
/* scheme 5: No motion vector dominates */
{ MODE_INTER_NO_MV, MODE_INTER_LAST_MV,
MODE_INTER_PRIOR_LAST, MODE_INTER_PLUS_MV,
MODE_INTRA, MODE_USING_GOLDEN,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
/* scheme 6 */
{ MODE_INTER_NO_MV, MODE_USING_GOLDEN,
MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST,
MODE_INTER_PLUS_MV, MODE_INTRA,
MODE_GOLDEN_MV, MODE_INTER_FOURMV },
};
#define MIN_DEQUANT_VAL 2
typedef struct Vp3DecodeContext {
AVCodecContext *avctx;
int theora, theora_tables;
int version;
int width, height;
AVFrame golden_frame;
AVFrame last_frame;
AVFrame current_frame;
int keyframe;
DSPContext dsp;
int flipped_image;
int qis[3];
int nqis;
int quality_index;
int last_quality_index;
int superblock_count;
int superblock_width;
int superblock_height;
int y_superblock_width;
int y_superblock_height;
int c_superblock_width;
int c_superblock_height;
int u_superblock_start;
int v_superblock_start;
unsigned char *superblock_coding;
int macroblock_count;
int macroblock_width;
int macroblock_height;
int fragment_count;
int fragment_width;
int fragment_height;
Vp3Fragment *all_fragments;
Coeff *coeffs;
Coeff *next_coeff;
int fragment_start[3];
ScanTable scantable;
/* tables */
uint16_t coded_dc_scale_factor[64];
uint32_t coded_ac_scale_factor[64];
uint8_t base_matrix[384][64];
uint8_t qr_count[2][3];
uint8_t qr_size [2][3][64];
uint16_t qr_base[2][3][64];
/* this is a list of indices into the all_fragments array indicating
* which of the fragments are coded */
int *coded_fragment_list;
int coded_fragment_list_index;
int pixel_addresses_inited;
VLC dc_vlc[16];
VLC ac_vlc_1[16];
VLC ac_vlc_2[16];
VLC ac_vlc_3[16];
VLC ac_vlc_4[16];
VLC superblock_run_length_vlc;
VLC fragment_run_length_vlc;
VLC mode_code_vlc;
VLC motion_vector_vlc;
/* these arrays need to be on 16-byte boundaries since SSE2 operations
* index into them */
DECLARE_ALIGNED_16(int16_t, qmat[2][4][64]); //<qmat[is_inter][plane]
/* This table contains superblock_count * 16 entries. Each set of 16
* numbers corresponds to the fragment indices 0..15 of the superblock.
* An entry will be -1 to indicate that no entry corresponds to that
* index. */
int *superblock_fragments;
/* This table contains superblock_count * 4 entries. Each set of 4
* numbers corresponds to the macroblock indices 0..3 of the superblock.
* An entry will be -1 to indicate that no entry corresponds to that
* index. */
int *superblock_macroblocks;
/* This table contains macroblock_count * 6 entries. Each set of 6
* numbers corresponds to the fragment indices 0..5 which comprise
* the macroblock (4 Y fragments and 2 C fragments). */
int *macroblock_fragments;
/* This is an array that indicates how a particular macroblock
* is coded. */
unsigned char *macroblock_coding;
int first_coded_y_fragment;
int first_coded_c_fragment;
int last_coded_y_fragment;
int last_coded_c_fragment;
uint8_t edge_emu_buffer[9*2048]; //FIXME dynamic alloc
int8_t qscale_table[2048]; //FIXME dynamic alloc (width+15)/16
/* Huffman decode */
int hti;
unsigned int hbits;
int entries;
int huff_code_size;
uint16_t huffman_table[80][32][2];
uint32_t filter_limit_values[64];
int bounding_values_array[256];
} Vp3DecodeContext;
/************************************************************************
* VP3 specific functions
************************************************************************/
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -