FFmpeg
vp5.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * VP5 compatible video decoder
24  */
25 
26 #include <string.h>
27 
28 #include "avcodec.h"
29 #include "codec_internal.h"
30 #include "decode.h"
31 
32 #include "vp56.h"
33 #include "vp56data.h"
34 #include "vp5data.h"
35 #include "vpx_rac.h"
36 
37 
38 static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
39 {
40  VPXRangeCoder *c = &s->c;
41  int rows, cols;
42  int ret;
43 
44  ret = ff_vpx_init_range_decoder(&s->c, buf, buf_size);
45  if (ret < 0)
46  return ret;
47  s->frames[VP56_FRAME_CURRENT]->key_frame = !vpx_rac_get(c);
48  vpx_rac_get(c);
50  if (s->frames[VP56_FRAME_CURRENT]->key_frame)
51  {
52  int render_x, render_y;
53 
54  vp56_rac_gets(c, 8);
55  if(vp56_rac_gets(c, 5) > 5)
56  return AVERROR_INVALIDDATA;
57  vp56_rac_gets(c, 2);
58  if (vpx_rac_get(c)) {
59  avpriv_report_missing_feature(s->avctx, "Interlacing");
60  return AVERROR_PATCHWELCOME;
61  }
62  rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */
63  cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */
64  if (!rows || !cols) {
65  av_log(s->avctx, AV_LOG_ERROR, "Invalid size %dx%d\n",
66  cols << 4, rows << 4);
67  return AVERROR_INVALIDDATA;
68  }
69  render_y = vp56_rac_gets(c, 8); /* number of displayed macroblock rows */
70  render_x = vp56_rac_gets(c, 8); /* number of displayed macroblock cols */
71  if (render_x == 0 || render_x > cols ||
72  render_y == 0 || render_y > rows)
73  return AVERROR_INVALIDDATA;
74  vp56_rac_gets(c, 2);
75  if (!s->macroblocks || /* first frame */
76  16*cols != s->avctx->coded_width ||
77  16*rows != s->avctx->coded_height) {
78  int ret = ff_set_dimensions(s->avctx, 16 * cols, 16 * rows);
79  if (ret < 0)
80  return ret;
81  return VP56_SIZE_CHANGE;
82  }
83  } else if (!s->macroblocks)
84  return AVERROR_INVALIDDATA;
85  return 0;
86 }
87 
88 static void vp5_parse_vector_adjustment(VP56Context *s, VP56mv *vect)
89 {
90  VPXRangeCoder *c = &s->c;
91  VP56Model *model = s->modelp;
92  int comp, di;
93 
94  for (comp=0; comp<2; comp++) {
95  int delta = 0;
96  if (vpx_rac_get_prob_branchy(c, model->vector_dct[comp])) {
97  int sign = vpx_rac_get_prob(c, model->vector_sig[comp]);
98  di = vpx_rac_get_prob(c, model->vector_pdi[comp][0]);
99  di |= vpx_rac_get_prob(c, model->vector_pdi[comp][1]) << 1;
101  model->vector_pdv[comp]);
102  delta = di | (delta << 2);
103  delta = (delta ^ -sign) + sign;
104  }
105  if (!comp)
106  vect->x = delta;
107  else
108  vect->y = delta;
109  }
110 }
111 
112 static void vp5_parse_vector_models(VP56Context *s)
113 {
114  VPXRangeCoder *c = &s->c;
115  VP56Model *model = s->modelp;
116  int comp, node;
117 
118  for (comp=0; comp<2; comp++) {
120  model->vector_dct[comp] = vp56_rac_gets_nn(c, 7);
122  model->vector_sig[comp] = vp56_rac_gets_nn(c, 7);
124  model->vector_pdi[comp][0] = vp56_rac_gets_nn(c, 7);
126  model->vector_pdi[comp][1] = vp56_rac_gets_nn(c, 7);
127  }
128 
129  for (comp=0; comp<2; comp++)
130  for (node=0; node<7; node++)
131  if (vpx_rac_get_prob_branchy(c, vp5_vmc_pct[comp][4 + node]))
132  model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7);
133 }
134 
135 static int vp5_parse_coeff_models(VP56Context *s)
136 {
137  VPXRangeCoder *c = &s->c;
138  VP56Model *model = s->modelp;
139  uint8_t def_prob[11];
140  int node, cg, ctx;
141  int ct; /* code type */
142  int pt; /* plane type (0 for Y, 1 for U or V) */
143 
144  memset(def_prob, 0x80, sizeof(def_prob));
145 
146  for (pt=0; pt<2; pt++)
147  for (node=0; node<11; node++)
148  if (vpx_rac_get_prob_branchy(c, vp5_dccv_pct[pt][node])) {
149  def_prob[node] = vp56_rac_gets_nn(c, 7);
150  model->coeff_dccv[pt][node] = def_prob[node];
151  } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
152  model->coeff_dccv[pt][node] = def_prob[node];
153  }
154 
155  for (ct=0; ct<3; ct++)
156  for (pt=0; pt<2; pt++)
157  for (cg=0; cg<6; cg++)
158  for (node=0; node<11; node++)
159  if (vpx_rac_get_prob_branchy(c, vp5_ract_pct[ct][pt][cg][node])) {
160  def_prob[node] = vp56_rac_gets_nn(c, 7);
161  model->coeff_ract[pt][ct][cg][node] = def_prob[node];
162  } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
163  model->coeff_ract[pt][ct][cg][node] = def_prob[node];
164  }
165 
166  /* coeff_dcct is a linear combination of coeff_dccv */
167  for (pt=0; pt<2; pt++)
168  for (ctx=0; ctx<36; ctx++)
169  for (node=0; node<5; node++)
170  model->coeff_dcct[pt][ctx][node] = av_clip(((model->coeff_dccv[pt][node] * vp5_dccv_lc[node][ctx][0] + 128) >> 8) + vp5_dccv_lc[node][ctx][1], 1, 254);
171 
172  /* coeff_acct is a linear combination of coeff_ract */
173  for (ct=0; ct<3; ct++)
174  for (pt=0; pt<2; pt++)
175  for (cg=0; cg<3; cg++)
176  for (ctx=0; ctx<6; ctx++)
177  for (node=0; node<5; node++)
178  model->coeff_acct[pt][ct][cg][ctx][node] = av_clip(((model->coeff_ract[pt][ct][cg][node] * vp5_ract_lc[ct][cg][node][ctx][0] + 128) >> 8) + vp5_ract_lc[ct][cg][node][ctx][1], 1, 254);
179  return 0;
180 }
181 
182 static int vp5_parse_coeff(VP56Context *s)
183 {
184  VPXRangeCoder *c = &s->c;
185  VP56Model *model = s->modelp;
186  uint8_t *permute = s->idct_scantable;
187  uint8_t *model1, *model2;
188  int coeff, sign, coeff_idx;
189  int b, i, cg, idx, ctx, ctx_last;
190  int pt = 0; /* plane type (0 for Y, 1 for U or V) */
191 
192  if (vpx_rac_is_end(c)) {
193  av_log(s->avctx, AV_LOG_ERROR, "End of AC stream reached in vp5_parse_coeff\n");
194  return AVERROR_INVALIDDATA;
195  }
196 
197  for (b=0; b<6; b++) {
198  int ct = 1; /* code type */
199 
200  if (b > 3) pt = 1;
201 
202  ctx = 6*s->coeff_ctx[ff_vp56_b6to4[b]][0]
203  + s->above_blocks[s->above_block_idx[b]].not_null_dc;
204  model1 = model->coeff_dccv[pt];
205  model2 = model->coeff_dcct[pt][ctx];
206 
207  coeff_idx = 0;
208  for (;;) {
209  if (vpx_rac_get_prob_branchy(c, model2[0])) {
210  if (vpx_rac_get_prob_branchy(c, model2[2])) {
211  if (vpx_rac_get_prob_branchy(c, model2[3])) {
212  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 4;
213  idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1);
214  sign = vpx_rac_get(c);
215  coeff = ff_vp56_coeff_bias[idx+5];
216  for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--)
218  } else {
219  if (vpx_rac_get_prob_branchy(c, model2[4])) {
220  coeff = 3 + vpx_rac_get_prob(c, model1[5]);
221  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 3;
222  } else {
223  coeff = 2;
224  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 2;
225  }
226  sign = vpx_rac_get(c);
227  }
228  ct = 2;
229  } else {
230  ct = 1;
231  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 1;
232  sign = vpx_rac_get(c);
233  coeff = 1;
234  }
235  coeff = (coeff ^ -sign) + sign;
236  if (coeff_idx)
237  coeff *= s->dequant_ac;
238  s->block_coeff[b][permute[coeff_idx]] = coeff;
239  } else {
240  if (ct && !vpx_rac_get_prob_branchy(c, model2[1]))
241  break;
242  ct = 0;
243  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 0;
244  }
245  coeff_idx++;
246  if (coeff_idx >= 64)
247  break;
248 
249  cg = vp5_coeff_groups[coeff_idx];
250  ctx = s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx];
251  model1 = model->coeff_ract[pt][ct][cg];
252  model2 = cg > 2 ? model1 : model->coeff_acct[pt][ct][cg][ctx];
253  }
254 
255  ctx_last = FFMIN(s->coeff_ctx_last[ff_vp56_b6to4[b]], 24);
256  s->coeff_ctx_last[ff_vp56_b6to4[b]] = coeff_idx;
257  if (coeff_idx < ctx_last)
258  for (i=coeff_idx; i<=ctx_last; i++)
259  s->coeff_ctx[ff_vp56_b6to4[b]][i] = 5;
260  s->above_blocks[s->above_block_idx[b]].not_null_dc = s->coeff_ctx[ff_vp56_b6to4[b]][0];
261  s->idct_selector[b] = 63;
262  }
263  return 0;
264 }
265 
266 static void vp5_default_models_init(VP56Context *s)
267 {
268  VP56Model *model = s->modelp;
269  int i;
270 
271  for (i=0; i<2; i++) {
272  model->vector_sig[i] = 0x80;
273  model->vector_dct[i] = 0x80;
274  model->vector_pdi[i][0] = 0x55;
275  model->vector_pdi[i][1] = 0x80;
276  }
277  memcpy(model->mb_types_stats, ff_vp56_def_mb_types_stats, sizeof(model->mb_types_stats));
278  memset(model->vector_pdv, 0x80, sizeof(model->vector_pdv));
279 }
280 
282 {
283  VP56Context *s = avctx->priv_data;
284  int ret;
285 
286  if ((ret = ff_vp56_init_context(avctx, s, 1, 0)) < 0)
287  return ret;
288  ff_vp5dsp_init(&s->vp56dsp);
289  s->vp56_coord_div = vp5_coord_div;
290  s->parse_vector_adjustment = vp5_parse_vector_adjustment;
291  s->parse_coeff = vp5_parse_coeff;
292  s->default_models_init = vp5_default_models_init;
293  s->parse_vector_models = vp5_parse_vector_models;
294  s->parse_coeff_models = vp5_parse_coeff_models;
295  s->parse_header = vp5_parse_header;
296 
297  return 0;
298 }
299 
300 static av_cold int vp56_free(AVCodecContext *avctx)
301 {
302  VP56Context *const s = avctx->priv_data;
303  return ff_vp56_free_context(s);
304 }
305 
307  .p.name = "vp5",
308  CODEC_LONG_NAME("On2 VP5"),
309  .p.type = AVMEDIA_TYPE_VIDEO,
310  .p.id = AV_CODEC_ID_VP5,
311  .priv_data_size = sizeof(VP56Context),
313  .close = vp56_free,
315  .p.capabilities = AV_CODEC_CAP_DR1,
316  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
317 };
vp5_decode_init
static av_cold int vp5_decode_init(AVCodecContext *avctx)
Definition: vp5.c:281
vp56_rac_get_tree
static av_always_inline int vp56_rac_get_tree(VPXRangeCoder *c, const VP56Tree *tree, const uint8_t *probs)
Definition: vp56.h:243
vp5_parse_coeff
static int vp5_parse_coeff(VP56Context *s)
Definition: vp5.c:182
av_clip
#define av_clip
Definition: common.h:95
VP56mv::x
int16_t x
Definition: vp56.h:68
vp56data.h
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
ff_vp5dsp_init
void ff_vp5dsp_init(VP56DSPContext *s)
vp5_default_models_init
static void vp5_default_models_init(VP56Context *s)
Definition: vp5.c:266
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:80
VP56Model::mb_types_stats
uint8_t mb_types_stats[3][10][2]
Definition: vp56.h:112
VP56Model::coeff_acct
uint8_t coeff_acct[2][3][3][6][5]
Definition: vp56.h:108
ff_vp56_coeff_bit_length
const uint8_t ff_vp56_coeff_bit_length[]
Definition: vp56data.c:68
ff_vp5_decoder
const FFCodec ff_vp5_decoder
Definition: vp5.c:306
ff_vp56_init_context
av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, int flip, int has_alpha)
Initializes an VP56Context.
Definition: vp56.c:777
b
#define b
Definition: input.c:41
FFCodec
Definition: codec_internal.h:127
vp5_coord_div
static const uint8_t vp5_coord_div[]
Definition: vp5data.h:175
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:91
VP56Model::coeff_ract
uint8_t coeff_ract[2][3][6][11]
Definition: vp56.h:107
VPXRangeCoder
Definition: vpx_rac.h:35
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
ff_vp56_b6to4
const uint8_t ff_vp56_b6to4[]
Definition: vp56data.c:29
VP56_SIZE_CHANGE
#define VP56_SIZE_CHANGE
Definition: vp56.h:72
vp5_parse_vector_adjustment
static void vp5_parse_vector_adjustment(VP56Context *s, VP56mv *vect)
Definition: vp5.c:88
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
vp56_rac_gets_nn
static av_unused int vp56_rac_gets_nn(VPXRangeCoder *c, int bits)
Definition: vp56.h:236
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:306
s
#define s(width, name)
Definition: cbs_vp9.c:256
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
permute
static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64])
Definition: proresdec2.c:47
ctx
AVFormatContext * ctx
Definition: movenc.c:48
decode.h
ff_vp56_free_context
av_cold int ff_vp56_free_context(VP56Context *s)
Definition: vp56.c:828
VP56mv::y
int16_t y
Definition: vp56.h:69
vp5_ract_pct
static const uint8_t vp5_ract_pct[3][2][6][11]
Definition: vp5data.h:52
VP56mv
Definition: vp56.h:67
VP56Model::coeff_dccv
uint8_t coeff_dccv[2][11]
Definition: vp56.h:106
VP56Model::coeff_dcct
uint8_t coeff_dcct[2][36][5]
Definition: vp56.h:109
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
vp56.h
vp5_parse_header
static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
Definition: vp5.c:38
VP56Model::vector_sig
uint8_t vector_sig[2]
Definition: vp56.h:101
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
vp5_ract_lc
static const int16_t vp5_ract_lc[3][3][5][6][2]
Definition: vp5data.h:124
ff_vp56_def_mb_types_stats
const uint8_t ff_vp56_def_mb_types_stats[3][10][2]
Definition: vp56data.c:40
vp5_dccv_pct
static const uint8_t vp5_dccv_pct[2][11]
Definition: vp5data.h:47
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
vp5_dccv_lc
static const int16_t vp5_dccv_lc[5][36][2]
Definition: vp5data.h:91
vp5data.h
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
codec_internal.h
ff_vp56_coeff_parse_table
const uint8_t ff_vp56_coeff_parse_table[6][11]
Definition: vp56data.c:31
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
vp5_parse_vector_models
static void vp5_parse_vector_models(VP56Context *s)
Definition: vp5.c:112
pt
int pt
Definition: rtp.c:35
vp56_rac_gets
static int vp56_rac_gets(VPXRangeCoder *c, int bits)
vp56 specific range coder implementation
Definition: vp56.h:224
ff_vp56_pva_tree
const VP56Tree ff_vp56_pva_tree[]
Definition: vp56data.c:49
vpx_rac_is_end
static av_always_inline int vpx_rac_is_end(VPXRangeCoder *c)
returns 1 if the end of the stream has been reached, 0 otherwise.
Definition: vpx_rac.h:51
VP56Model::vector_pdi
uint8_t vector_pdi[2][2]
Definition: vp56.h:103
AV_CODEC_ID_VP5
@ AV_CODEC_ID_VP5
Definition: codec_id.h:142
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
vpx_rac.h
delta
float delta
Definition: vorbis_enc_data.h:430
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
vpx_rac_get_prob_branchy
static av_always_inline int vpx_rac_get_prob_branchy(VPXRangeCoder *c, int prob)
Definition: vpx_rac.h:99
ff_vp56_pc_tree
const VP56Tree ff_vp56_pc_tree[]
Definition: vp56data.c:59
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:191
avcodec.h
ret
ret
Definition: filter_design.txt:187
ff_vp56_coeff_bias
const uint8_t ff_vp56_coeff_bias[]
Definition: vp56data.c:67
ff_vpx_init_range_decoder
int ff_vpx_init_range_decoder(VPXRangeCoder *c, const uint8_t *buf, int buf_size)
Definition: vpx_rac.c:42
ff_vp56_decode_frame
int ff_vp56_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition: vp56.c:569
VP56_FRAME_CURRENT
@ VP56_FRAME_CURRENT
Definition: vp56.h:44
AVCodecContext
main external API structure.
Definition: avcodec.h:426
VP56Model
Definition: vp56.h:97
ff_vp56_init_dequant
void ff_vp56_init_dequant(VP56Context *s, int quantizer)
Definition: vp56.c:35
vp56_free
static av_cold int vp56_free(AVCodecContext *avctx)
Definition: vp5.c:300
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
vpx_rac_get
static av_always_inline int vpx_rac_get(VPXRangeCoder *c)
Definition: vpx_rac.h:117
vp5_coeff_groups
static const uint8_t vp5_coeff_groups[]
Definition: vp5data.h:31
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:453
vp5_parse_coeff_models
static int vp5_parse_coeff_models(VP56Context *s)
Definition: vp5.c:135
VP56Model::vector_dct
uint8_t vector_dct[2]
Definition: vp56.h:102
coeff
static const double coeff[2][5]
Definition: vf_owdenoise.c:78
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
vp5_vmc_pct
static const uint8_t vp5_vmc_pct[2][11]
Definition: vp5data.h:42
vpx_rac_get_prob
#define vpx_rac_get_prob
Definition: vpx_rac.h:82
VP56Model::vector_pdv
uint8_t vector_pdv[2][7]
Definition: vp56.h:104