Commit 3b636f21 authored by David Conrad's avatar David Conrad Committed by Ronald S. Bultje

Native VP8 decoder.

Patch by David Conrad <lessen42 gmail com> and myself.

Originally committed as revision 23719 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent c6ef6e14
......@@ -441,8 +441,8 @@ following image formats are supported:
@tab fourcc: VP50
@item On2 VP6 @tab @tab X
@tab fourcc: VP60,VP61,VP62
@item VP8 @tab X @tab X
@tab fourcc: VP80, de/encoding supported through external library libvpx
@item VP8 @tab E @tab X
@tab fourcc: VP80, encoding supported through external library libvpx
@item planar RGB @tab @tab X
@tab fourcc: 8BPS
@item Q-team QPEG @tab @tab X
......
......@@ -375,6 +375,8 @@ OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \
vp3dsp.o
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp56dsp.o \
vp3dsp.o vp6dsp.o huffman.o
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56.o vp56data.o \
h264pred.o
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o
......
......@@ -201,6 +201,7 @@ void avcodec_register_all(void)
REGISTER_DECODER (VP6, vp6);
REGISTER_DECODER (VP6A, vp6a);
REGISTER_DECODER (VP6F, vp6f);
REGISTER_DECODER (VP8, vp8);
REGISTER_DECODER (VQA, vqa);
REGISTER_ENCDEC (WMV1, wmv1);
REGISTER_ENCDEC (WMV2, wmv2);
......
......@@ -30,8 +30,8 @@
#include "libavutil/avutil.h"
#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 77
#define LIBAVCODEC_VERSION_MICRO 1
#define LIBAVCODEC_VERSION_MINOR 78
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
......
......@@ -39,6 +39,7 @@
#include "ac3dec.h"
#include "vorbis.h"
#include "png.h"
#include "vp8dsp.h"
uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP] = {0, };
uint32_t ff_squareTbl[512] = {0, };
......@@ -2656,6 +2657,18 @@ static void avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, int stride){
}
#endif /* CONFIG_RV40_DECODER */
#if CONFIG_VP8_DECODER
void ff_put_vp8_pixels16_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y) {
put_pixels16_c(dst, src, stride, h);
}
void ff_put_vp8_pixels8_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y) {
put_pixels8_c(dst, src, stride, h);
}
void ff_put_vp8_pixels4_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y) {
put_pixels4_c(dst, src, stride, h);
}
#endif
static void wmv2_mspel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int w){
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
int i;
......
......@@ -237,6 +237,12 @@ static inline int vp56_rac_get(VP56RangeCoder *c)
return bit;
}
// rounding is different than vp56_rac_get, is vp56_rac_get wrong?
static inline int vp8_rac_get(VP56RangeCoder *c)
{
return vp56_rac_get_prob(c, 128);
}
static inline int vp56_rac_gets(VP56RangeCoder *c, int bits)
{
int value = 0;
......@@ -248,12 +254,46 @@ static inline int vp56_rac_gets(VP56RangeCoder *c, int bits)
return value;
}
static inline int vp8_rac_get_uint(VP56RangeCoder *c, int bits)
{
int value = 0;
while (bits--) {
value = (value << 1) | vp8_rac_get(c);
}
return value;
}
// fixme: add 1 bit to all the calls to this?
static inline int vp8_rac_get_sint(VP56RangeCoder *c, int bits)
{
int v;
if (!vp8_rac_get(c))
return 0;
v = vp8_rac_get_uint(c, bits);
if (vp8_rac_get(c))
v = -v;
return v;
}
// P(7)
static inline int vp56_rac_gets_nn(VP56RangeCoder *c, int bits)
{
int v = vp56_rac_gets(c, 7) << 1;
return v + !v;
}
static inline int vp8_rac_get_nn(VP56RangeCoder *c)
{
int v = vp8_rac_get_uint(c, 7) << 1;
return v + !v;
}
static inline int vp56_rac_get_tree(VP56RangeCoder *c,
const VP56Tree *tree,
const uint8_t *probs)
......@@ -267,4 +307,39 @@ static inline int vp56_rac_get_tree(VP56RangeCoder *c,
return -tree->val;
}
/**
* This is identical to vp8_rac_get_tree except for the possibility of starting
* on a node other than the root node, needed for coeff decode where this is
* used to save a bit after a 0 token (by disallowing EOB to immediately follow.)
*/
static inline int vp8_rac_get_tree_with_offset(VP56RangeCoder *c, const int8_t (*tree)[2],
const uint8_t *probs, int i)
{
do {
i = tree[i][vp56_rac_get_prob(c, probs[i])];
} while (i > 0);
return -i;
}
// how probabilities are associated with decisions is different I think
// well, the new scheme fits in the old but this way has one fewer branches per decision
static inline int vp8_rac_get_tree(VP56RangeCoder *c, const int8_t (*tree)[2],
const uint8_t *probs)
{
return vp8_rac_get_tree_with_offset(c, tree, probs, 0);
}
// DCTextra
static inline int vp8_rac_get_coeff(VP56RangeCoder *c, const uint8_t *prob)
{
int v = 0;
do {
v = (v<<1) + vp56_rac_get_prob(c, *prob++);
} while (*prob);
return v;
}
#endif /* AVCODEC_VP56_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**
* VP8 compatible video decoder
*
* Copyright (C) 2010 David Conrad
* Copyright (C) 2010 Ronald S. Bultje
*
* 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_VP8DSP_H
#define AVCODEC_VP8DSP_H
#include "dsputil.h"
typedef struct VP8DSPContext {
void (*vp8_luma_dc_wht)(DCTELEM block[4][4][16], DCTELEM dc[16]);
void (*vp8_idct_add)(uint8_t *dst, DCTELEM block[16], int stride);
void (*vp8_idct_dc_add)(uint8_t *dst, DCTELEM block[16], int stride);
// loop filter applied to edges between macroblocks
void (*vp8_v_loop_filter16)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_h_loop_filter16)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_v_loop_filter8)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_h_loop_filter8)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
// loop filter applied to inner macroblock edges
void (*vp8_v_loop_filter16_inner)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_h_loop_filter16_inner)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_v_loop_filter8_inner)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_h_loop_filter8_inner)(uint8_t *dst, int stride, int flim_E, int flim_I, int hev_thresh);
void (*vp8_v_loop_filter_simple)(uint8_t *dst, int stride, int flim);
void (*vp8_h_loop_filter_simple)(uint8_t *dst, int stride, int flim);
/**
* first dimension: width>>3, height is assumed equal to width
* second dimension: 0 if no vertical interpolation is needed;
* 1 4-tap vertical interpolation filter (my & 1)
* 2 6-tap vertical interpolation filter (!(my & 1))
* third dimension: same as second dimention, for horizontal interpolation
* so something like put_vp8_epel_pixels_tab[width>>3][2*!!my-(my&1)][2*!!mx-(mx&1)](..., mx, my)
*/
h264_chroma_mc_func put_vp8_epel_pixels_tab[3][3][3];
} VP8DSPContext;
void ff_put_vp8_pixels16_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y);
void ff_put_vp8_pixels8_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y);
void ff_put_vp8_pixels4_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y);
void ff_vp8dsp_init(VP8DSPContext *c);
#endif /* AVCODEC_VP8DSP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment