FFmpeg
cdtoons.c
Go to the documentation of this file.
1 /*
2  * CDToons video decoder
3  * Copyright (C) 2020 Alyssa Milburn <amilburn@zall.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * CDToons video decoder
25  * @author Alyssa Milburn <amilburn@zall.org>
26  */
27 
28 #include <stdint.h>
29 
30 #include "libavutil/attributes.h"
31 #include "libavutil/internal.h"
32 #include "avcodec.h"
33 #include "bytestream.h"
34 #include "codec_internal.h"
35 #include "decode.h"
36 
37 #define CDTOONS_HEADER_SIZE 44
38 #define CDTOONS_MAX_SPRITES 1200
39 
40 typedef struct CDToonsSprite {
41  uint16_t flags;
42  uint16_t owner_frame;
43  uint16_t start_frame;
44  uint16_t end_frame;
45  unsigned int alloc_size;
46  uint32_t size;
47  uint8_t *data;
48  int active;
50 
51 typedef struct CDToonsContext {
53 
54  uint16_t last_pal_id; ///< The index of the active palette sprite.
55  uint32_t pal[256]; ///< The currently-used palette data.
58 
59 static int cdtoons_render_sprite(AVCodecContext *avctx, const uint8_t *data,
60  uint32_t data_size,
61  int dst_x, int dst_y, int width, int height)
62 {
63  CDToonsContext *c = avctx->priv_data;
64  const uint8_t *next_line = data;
65  const uint8_t *end = data + data_size;
66  uint16_t line_size;
67  uint8_t *dest;
68  int skip = 0, to_skip, x;
69 
70  if (dst_x + width > avctx->width)
71  width = avctx->width - dst_x;
72  if (dst_y + height > avctx->height)
73  height = avctx->height - dst_y;
74 
75  if (dst_x < 0) {
76  /* we need to skip the start of the scanlines */
77  skip = -dst_x;
78  if (width <= skip)
79  return 0;
80  dst_x = 0;
81  }
82 
83  for (int y = 0; y < height; y++) {
84  /* one scanline at a time, size is provided */
85  data = next_line;
86  if (end - data < 2)
87  return 1;
88  line_size = bytestream_get_be16(&data);
89  if (end - data < line_size)
90  return 1;
91  next_line = data + line_size;
92  if (dst_y + y < 0)
93  continue;
94 
95  dest = c->frame->data[0] + (dst_y + y) * c->frame->linesize[0] + dst_x;
96 
97  to_skip = skip;
98  x = 0;
99  while (x < width - skip) {
100  int raw, size, step;
101  uint8_t val;
102 
103  if (data >= end)
104  return 1;
105 
106  val = bytestream_get_byte(&data);
107  raw = !(val & 0x80);
108  size = (int)(val & 0x7F) + 1;
109 
110  /* skip the start of a scanline if it is off-screen */
111  if (to_skip >= size) {
112  to_skip -= size;
113  if (raw) {
114  step = size;
115  } else {
116  step = 1;
117  }
118  if (next_line - data < step)
119  return 1;
120  data += step;
121  continue;
122  } else if (to_skip) {
123  size -= to_skip;
124  if (raw) {
125  if (next_line - data < to_skip)
126  return 1;
127  data += to_skip;
128  }
129  to_skip = 0;
130  }
131 
132  if (x + size >= width - skip)
133  size = width - skip - x;
134 
135  /* either raw data, or a run of a single color */
136  if (raw) {
137  if (next_line - data < size)
138  return 1;
139  memcpy(dest + x, data, size);
140  data += size;
141  } else {
142  uint8_t color = bytestream_get_byte(&data);
143  /* ignore transparent runs */
144  if (color)
145  memset(dest + x, color, size);
146  }
147  x += size;
148  }
149  }
150 
151  return 0;
152 }
153 
154 static int cdtoons_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
155  int *got_frame, AVPacket *avpkt)
156 {
157  CDToonsContext *c = avctx->priv_data;
158  const uint8_t *buf = avpkt->data;
159  const uint8_t *eod = avpkt->data + avpkt->size;
160  const int buf_size = avpkt->size;
161  uint16_t frame_id;
162  uint8_t background_color;
163  uint16_t sprite_count, sprite_offset;
164  uint8_t referenced_count;
165  uint16_t palette_id;
166  uint8_t palette_set;
167  int ret;
168  int saw_embedded_sprites = 0;
169 
170  if (buf_size < CDTOONS_HEADER_SIZE)
171  return AVERROR_INVALIDDATA;
172 
173  if ((ret = ff_reget_buffer(avctx, c->frame, 0)) < 0)
174  return ret;
175 
176  /* a lot of the header is useless junk in the absence of
177  * dirty rectangling etc */
178  buf += 2; /* version? (always 9?) */
179  frame_id = bytestream_get_be16(&buf);
180  buf += 2; /* blocks_valid_until */
181  buf += 1;
182  background_color = bytestream_get_byte(&buf);
183  buf += 16; /* clip rect, dirty rect */
184  buf += 4; /* flags */
185  sprite_count = bytestream_get_be16(&buf);
186  sprite_offset = bytestream_get_be16(&buf);
187  buf += 2; /* max block id? */
188  referenced_count = bytestream_get_byte(&buf);
189  buf += 1;
190  palette_id = bytestream_get_be16(&buf);
191  palette_set = bytestream_get_byte(&buf);
192  buf += 5;
193 
194  if (sprite_offset > buf_size)
195  return AVERROR_INVALIDDATA;
196 
197  /* read new sprites introduced in this frame */
198  buf = avpkt->data + sprite_offset;
199  while (sprite_count--) {
200  uint32_t size;
201  uint16_t sprite_id;
202 
203  if (buf + 14 > eod)
204  return AVERROR_INVALIDDATA;
205 
206  sprite_id = bytestream_get_be16(&buf);
207  if (sprite_id >= CDTOONS_MAX_SPRITES) {
208  av_log(avctx, AV_LOG_ERROR,
209  "Sprite ID %d is too high.\n", sprite_id);
210  return AVERROR_INVALIDDATA;
211  }
212  if (c->sprites[sprite_id].active) {
213  av_log(avctx, AV_LOG_ERROR,
214  "Sprite ID %d is a duplicate.\n", sprite_id);
215  return AVERROR_INVALIDDATA;
216  }
217 
218  c->sprites[sprite_id].flags = bytestream_get_be16(&buf);
219  size = bytestream_get_be32(&buf);
220  if (size < 14) {
221  av_log(avctx, AV_LOG_ERROR,
222  "Sprite only has %d bytes of data.\n", size);
223  return AVERROR_INVALIDDATA;
224  }
225  size -= 14;
226  c->sprites[sprite_id].size = size;
227  c->sprites[sprite_id].owner_frame = frame_id;
228  c->sprites[sprite_id].start_frame = bytestream_get_be16(&buf);
229  c->sprites[sprite_id].end_frame = bytestream_get_be16(&buf);
230  buf += 2;
231 
232  if (size > buf_size || buf + size > eod)
233  return AVERROR_INVALIDDATA;
234 
235  av_fast_padded_malloc(&c->sprites[sprite_id].data, &c->sprites[sprite_id].alloc_size, size);
236  if (!c->sprites[sprite_id].data)
237  return AVERROR(ENOMEM);
238 
239  c->sprites[sprite_id].active = 1;
240 
241  bytestream_get_buffer(&buf, c->sprites[sprite_id].data, size);
242  }
243 
244  /* render any embedded sprites */
245  while (buf < eod) {
246  uint32_t tag, size;
247  if (buf + 8 > eod) {
248  av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for embedded sprites.\n");
249  return AVERROR_INVALIDDATA;
250  }
251  tag = bytestream_get_be32(&buf);
252  size = bytestream_get_be32(&buf);
253  if (tag == MKBETAG('D', 'i', 'f', 'f')) {
254  uint16_t diff_count;
255  if (buf + 10 > eod) {
256  av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame.\n");
257  return AVERROR_INVALIDDATA;
258  }
259  diff_count = bytestream_get_be16(&buf);
260  buf += 8; /* clip rect? */
261  for (int i = 0; i < diff_count; i++) {
262  int16_t top, left;
263  uint16_t diff_size, width, height;
264 
265  if (buf + 16 > eod) {
266  av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame header.\n");
267  return AVERROR_INVALIDDATA;
268  }
269 
270  top = bytestream_get_be16(&buf);
271  left = bytestream_get_be16(&buf);
272  buf += 4; /* bottom, right */
273  diff_size = bytestream_get_be32(&buf);
274  width = bytestream_get_be16(&buf);
275  height = bytestream_get_be16(&buf);
276  if (diff_size < 8 || diff_size - 4 > eod - buf) {
277  av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame data.\n");
278  return AVERROR_INVALIDDATA;
279  }
280  if (cdtoons_render_sprite(avctx, buf + 4, diff_size - 8,
281  left, top, width, height)) {
282  av_log(avctx, AV_LOG_WARNING, "Ran beyond end of sprite while rendering.\n");
283  }
284  buf += diff_size - 4;
285  }
286  saw_embedded_sprites = 1;
287  } else {
288  /* we don't care about any other entries */
289  if (size < 8 || size - 8 > eod - buf) {
290  av_log(avctx, AV_LOG_WARNING, "Ran out of data for ignored entry (size %X, %d left).\n", size, (int)(eod - buf));
291  return AVERROR_INVALIDDATA;
292  }
293  buf += (size - 8);
294  }
295  }
296 
297  /* was an intra frame? */
298  if (saw_embedded_sprites)
299  goto done;
300 
301  /* render any referenced sprites */
302  buf = avpkt->data + CDTOONS_HEADER_SIZE;
303  eod = avpkt->data + sprite_offset;
304  for (int i = 0; i < referenced_count; i++) {
305  const uint8_t *block_data;
306  uint16_t sprite_id, width, height;
307  int16_t top, left, right;
308 
309  if (buf + 10 > eod) {
310  av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data when rendering.\n");
311  return AVERROR_INVALIDDATA;
312  }
313 
314  sprite_id = bytestream_get_be16(&buf);
315  top = bytestream_get_be16(&buf);
316  left = bytestream_get_be16(&buf);
317  buf += 2; /* bottom */
318  right = bytestream_get_be16(&buf);
319 
320  if ((i == 0) && (sprite_id == 0)) {
321  /* clear background */
322  memset(c->frame->data[0], background_color,
323  c->frame->linesize[0] * avctx->height);
324  }
325 
326  if (!right)
327  continue;
328  if (sprite_id >= CDTOONS_MAX_SPRITES) {
329  av_log(avctx, AV_LOG_ERROR,
330  "Sprite ID %d is too high.\n", sprite_id);
331  return AVERROR_INVALIDDATA;
332  }
333 
334  block_data = c->sprites[sprite_id].data;
335  if (!c->sprites[sprite_id].active) {
336  /* this can happen when seeking around */
337  av_log(avctx, AV_LOG_WARNING, "Sprite %d is missing.\n", sprite_id);
338  continue;
339  }
340  if (c->sprites[sprite_id].size < 14) {
341  av_log(avctx, AV_LOG_ERROR, "Sprite %d is too small.\n", sprite_id);
342  continue;
343  }
344 
345  height = bytestream_get_be16(&block_data);
346  width = bytestream_get_be16(&block_data);
347  block_data += 10;
348  if (cdtoons_render_sprite(avctx, block_data,
349  c->sprites[sprite_id].size - 14,
350  left, top, width, height)) {
351  av_log(avctx, AV_LOG_WARNING, "Ran beyond end of sprite while rendering.\n");
352  }
353  }
354 
355  if (palette_id && (palette_id != c->last_pal_id)) {
356  if (palette_id >= CDTOONS_MAX_SPRITES) {
357  av_log(avctx, AV_LOG_ERROR,
358  "Palette ID %d is too high.\n", palette_id);
359  return AVERROR_INVALIDDATA;
360  }
361  if (!c->sprites[palette_id].active) {
362  /* this can happen when seeking around */
363  av_log(avctx, AV_LOG_WARNING,
364  "Palette ID %d is missing.\n", palette_id);
365  goto done;
366  }
367  if (c->sprites[palette_id].size != 256 * 2 * 3) {
368  av_log(avctx, AV_LOG_ERROR,
369  "Palette ID %d is wrong size (%d).\n",
370  palette_id, c->sprites[palette_id].size);
371  return AVERROR_INVALIDDATA;
372  }
373  c->last_pal_id = palette_id;
374  if (!palette_set) {
375  uint8_t *palette_data = c->sprites[palette_id].data;
376  for (int i = 0; i < 256; i++) {
377  /* QuickTime-ish palette: 16-bit RGB components */
378  unsigned r, g, b;
379  r = *palette_data;
380  g = *(palette_data + 2);
381  b = *(palette_data + 4);
382  c->pal[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
383  palette_data += 6;
384  }
385  /* first palette entry indicates transparency */
386  c->pal[0] = 0;
387 #if FF_API_PALETTE_HAS_CHANGED
389  c->frame->palette_has_changed = 1;
391 #endif
392  }
393  }
394 
395 done:
396  /* discard outdated blocks */
397  for (int i = 0; i < CDTOONS_MAX_SPRITES; i++) {
398  if (c->sprites[i].end_frame > frame_id)
399  continue;
400  c->sprites[i].active = 0;
401  }
402 
403  memcpy(c->frame->data[1], c->pal, AVPALETTE_SIZE);
404 
405  if ((ret = av_frame_ref(rframe, c->frame)) < 0)
406  return ret;
407 
408  *got_frame = 1;
409 
410  /* always report that the buffer was completely consumed */
411  return buf_size;
412 }
413 
415 {
416  CDToonsContext *c = avctx->priv_data;
417 
418  avctx->pix_fmt = AV_PIX_FMT_PAL8;
419  c->last_pal_id = 0;
420  c->frame = av_frame_alloc();
421  if (!c->frame)
422  return AVERROR(ENOMEM);
423 
424  return 0;
425 }
426 
427 static void cdtoons_flush(AVCodecContext *avctx)
428 {
429  CDToonsContext *c = avctx->priv_data;
430 
431  c->last_pal_id = 0;
432  for (int i = 0; i < CDTOONS_MAX_SPRITES; i++)
433  c->sprites[i].active = 0;
434 }
435 
437 {
438  CDToonsContext *c = avctx->priv_data;
439 
440  for (int i = 0; i < CDTOONS_MAX_SPRITES; i++) {
441  av_freep(&c->sprites[i].data);
442  c->sprites[i].active = 0;
443  }
444 
445  av_frame_free(&c->frame);
446 
447  return 0;
448 }
449 
451  .p.name = "cdtoons",
452  CODEC_LONG_NAME("CDToons video"),
453  .p.type = AVMEDIA_TYPE_VIDEO,
454  .p.id = AV_CODEC_ID_CDTOONS,
455  .priv_data_size = sizeof(CDToonsContext),
457  .close = cdtoons_decode_end,
459  .p.capabilities = AV_CODEC_CAP_DR1,
460  .flush = cdtoons_flush,
461 };
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:73
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
CDToonsContext::frame
AVFrame * frame
Definition: cdtoons.c:52
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
color
Definition: vf_paletteuse.c:511
CDToonsSprite::active
int active
Definition: cdtoons.c:48
CDToonsSprite::owner_frame
uint16_t owner_frame
Definition: cdtoons.c:42
CDToonsSprite::size
uint32_t size
Definition: cdtoons.c:46
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
AVPacket::data
uint8_t * data
Definition: packet.h:491
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:148
AV_CODEC_ID_CDTOONS
@ AV_CODEC_ID_CDTOONS
Definition: codec_id.h:303
CDToonsSprite
Definition: cdtoons.c:40
FFCodec
Definition: codec_internal.h:127
CDToonsSprite::end_frame
uint16_t end_frame
Definition: cdtoons.c:44
cdtoons_decode_end
static av_cold int cdtoons_decode_end(AVCodecContext *avctx)
Definition: cdtoons.c:436
CDToonsSprite::data
uint8_t * data
Definition: cdtoons.c:47
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
val
static double val(void *priv, double ch)
Definition: aeval.c:78
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:88
CDTOONS_HEADER_SIZE
#define CDTOONS_HEADER_SIZE
Definition: cdtoons.c:37
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
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:306
cdtoons_decode_frame
static int cdtoons_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition: cdtoons.c:154
g
const char * g
Definition: vf_curves.c:127
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
decode.h
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
cdtoons_flush
static void cdtoons_flush(AVCodecContext *avctx)
Definition: cdtoons.c:427
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
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
CDTOONS_MAX_SPRITES
#define CDTOONS_MAX_SPRITES
Definition: cdtoons.c:38
CDToonsSprite::alloc_size
unsigned int alloc_size
Definition: cdtoons.c:45
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
AVPacket::size
int size
Definition: packet.h:492
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:361
codec_internal.h
size
int size
Definition: twinvq_data.h:10344
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
CDToonsContext::sprites
CDToonsSprite sprites[CDTOONS_MAX_SPRITES]
Definition: cdtoons.c:56
CDToonsSprite::flags
uint16_t flags
Definition: cdtoons.c:41
height
#define height
CDToonsContext
Definition: cdtoons.c:51
attributes.h
ff_cdtoons_decoder
const FFCodec ff_cdtoons_decoder
Definition: cdtoons.c:450
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
internal.h
av_fast_padded_malloc
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition: utils.c:52
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::height
int height
Definition: avcodec.h:621
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:658
avcodec.h
bytestream_get_buffer
static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
Definition: bytestream.h:363
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
tag
uint32_t tag
Definition: movenc.c:1737
ff_reget_buffer
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition: decode.c:1735
ret
ret
Definition: filter_design.txt:187
CDToonsContext::pal
uint32_t pal[256]
The currently-used palette data.
Definition: cdtoons.c:55
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
U
#define U(x)
Definition: vpx_arith.h:37
AVCodecContext
main external API structure.
Definition: avcodec.h:441
CDToonsContext::last_pal_id
uint16_t last_pal_id
The index of the active palette sprite.
Definition: cdtoons.c:54
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:72
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
cdtoons_render_sprite
static int cdtoons_render_sprite(AVCodecContext *avctx, const uint8_t *data, uint32_t data_size, int dst_x, int dst_y, int width, int height)
Definition: cdtoons.c:59
AVPacket
This structure stores compressed data.
Definition: packet.h:468
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:468
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:621
bytestream.h
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
cdtoons_decode_init
static av_cold int cdtoons_decode_init(AVCodecContext *avctx)
Definition: cdtoons.c:414
int
int
Definition: ffmpeg_filter.c:368
CDToonsSprite::start_frame
uint16_t start_frame
Definition: cdtoons.c:43
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375