FFmpeg
dfa.c
Go to the documentation of this file.
1 /*
2  * Chronomaster DFA Video Decoder
3  * Copyright (c) 2011 Konstantin Shishkov
4  * based on work by Vladimir "VAG" Gneushev
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <inttypes.h>
24 
25 #include "avcodec.h"
26 #include "bytestream.h"
27 #include "codec_internal.h"
28 #include "decode.h"
29 
30 #include "libavutil/avassert.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/mem.h"
33 
34 typedef struct DfaContext {
35  uint32_t pal[256];
36  uint8_t *frame_buf;
37 } DfaContext;
38 
40 {
41  DfaContext *s = avctx->priv_data;
42 
43  avctx->pix_fmt = AV_PIX_FMT_PAL8;
44 
45  if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16))
46  return AVERROR_INVALIDDATA;
47 
48  av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0);
49 
50  s->frame_buf = av_mallocz(avctx->width * avctx->height);
51  if (!s->frame_buf)
52  return AVERROR(ENOMEM);
53 
54  return 0;
55 }
56 
57 static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
58 {
59  const int size = width * height;
60 
62  return AVERROR_INVALIDDATA;
63  return 0;
64 }
65 
66 static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
67 {
68  const uint8_t *frame_start = frame;
69  const uint8_t *frame_end = frame + width * height;
70  int mask = 0x10000, bitbuf = 0;
71  int v, count;
72  unsigned segments;
73  unsigned offset;
74 
75  segments = bytestream2_get_le32(gb);
76  offset = bytestream2_get_le32(gb);
77  if (segments == 0 && offset == frame_end - frame)
78  return 0; // skip frame
79  if (frame_end - frame <= offset)
80  return AVERROR_INVALIDDATA;
81  frame += offset;
82  while (segments--) {
83  if (bytestream2_get_bytes_left(gb) < 2)
84  return AVERROR_INVALIDDATA;
85  if (mask == 0x10000) {
86  bitbuf = bytestream2_get_le16u(gb);
87  mask = 1;
88  }
89  if (frame_end - frame < 2)
90  return AVERROR_INVALIDDATA;
91  if (bitbuf & mask) {
92  v = bytestream2_get_le16(gb);
93  offset = (v & 0x1FFF) << 1;
94  count = ((v >> 13) + 2) << 1;
95  if (frame - frame_start < offset || frame_end - frame < count)
96  return AVERROR_INVALIDDATA;
98  frame += count;
99  } else {
100  *frame++ = bytestream2_get_byte(gb);
101  *frame++ = bytestream2_get_byte(gb);
102  }
103  mask <<= 1;
104  }
105 
106  return 0;
107 }
108 
109 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
110 {
111  const uint8_t *frame_start = frame;
112  const uint8_t *frame_end = frame + width * height;
113  int mask = 0x10000, bitbuf = 0;
114  int v, offset, count, segments;
115 
116  segments = bytestream2_get_le16(gb);
117  while (segments--) {
118  if (bytestream2_get_bytes_left(gb) < 2)
119  return AVERROR_INVALIDDATA;
120  if (mask == 0x10000) {
121  bitbuf = bytestream2_get_le16u(gb);
122  mask = 1;
123  }
124  if (frame_end - frame < 2)
125  return AVERROR_INVALIDDATA;
126  if (bitbuf & mask) {
127  v = bytestream2_get_le16(gb);
128  offset = (v & 0x1FFF) << 1;
129  count = ((v >> 13) + 2) << 1;
130  if (frame - frame_start < offset || frame_end - frame < count)
131  return AVERROR_INVALIDDATA;
132  av_memcpy_backptr(frame, offset, count);
133  frame += count;
134  } else if (bitbuf & (mask << 1)) {
135  frame += bytestream2_get_le16(gb);
136  } else {
137  *frame++ = bytestream2_get_byte(gb);
138  *frame++ = bytestream2_get_byte(gb);
139  }
140  mask <<= 2;
141  }
142 
143  return 0;
144 }
145 
146 static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
147 {
148  const uint8_t *frame_start = frame;
149  const uint8_t *frame_end = frame + width * height;
150  int mask = 0x10000, bitbuf = 0;
151  int i, v, offset, count, segments;
152 
153  if ((width | height) & 1)
154  return AVERROR_INVALIDDATA;
155  segments = bytestream2_get_le16(gb);
156  while (segments--) {
157  if (bytestream2_get_bytes_left(gb) < 2)
158  return AVERROR_INVALIDDATA;
159  if (mask == 0x10000) {
160  bitbuf = bytestream2_get_le16u(gb);
161  mask = 1;
162  }
163 
164  if (bitbuf & mask) {
165  v = bytestream2_get_le16(gb);
166  offset = (v & 0x1FFF) << 2;
167  count = ((v >> 13) + 2) << 1;
168  if (frame - frame_start < offset || frame_end - frame < count*2 + width)
169  return AVERROR_INVALIDDATA;
170  for (i = 0; i < count; i++) {
171  frame[0] = frame[1] =
172  frame[width] = frame[width + 1] = frame[-offset];
173 
174  frame += 2;
175  }
176  } else if (bitbuf & (mask << 1)) {
177  v = bytestream2_get_le16(gb)*2;
178  if (frame - frame_end < v)
179  return AVERROR_INVALIDDATA;
180  frame += v;
181  } else {
182  if (width < 4 || frame_end - frame < width + 4)
183  return AVERROR_INVALIDDATA;
184  frame[0] = frame[1] =
185  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
186  frame += 2;
187  frame[0] = frame[1] =
188  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
189  frame += 2;
190  }
191  mask <<= 2;
192  }
193 
194  return 0;
195 }
196 
197 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
198 {
199  uint8_t *line_ptr;
200  int count, lines, segments;
201 
202  count = bytestream2_get_le16(gb);
203  if (count >= height)
204  return AVERROR_INVALIDDATA;
205  frame += width * count;
206  lines = bytestream2_get_le16(gb);
207  if (count + lines > height)
208  return AVERROR_INVALIDDATA;
209 
210  while (lines--) {
211  if (bytestream2_get_bytes_left(gb) < 1)
212  return AVERROR_INVALIDDATA;
213  line_ptr = frame;
214  frame += width;
215  segments = bytestream2_get_byteu(gb);
216  while (segments--) {
217  if (frame - line_ptr <= bytestream2_peek_byte(gb))
218  return AVERROR_INVALIDDATA;
219  line_ptr += bytestream2_get_byte(gb);
220  count = (int8_t)bytestream2_get_byte(gb);
221  if (count >= 0) {
222  if (frame - line_ptr < count)
223  return AVERROR_INVALIDDATA;
224  if (bytestream2_get_buffer(gb, line_ptr, count) != count)
225  return AVERROR_INVALIDDATA;
226  } else {
227  count = -count;
228  if (frame - line_ptr < count)
229  return AVERROR_INVALIDDATA;
230  memset(line_ptr, bytestream2_get_byte(gb), count);
231  }
232  line_ptr += count;
233  }
234  }
235 
236  return 0;
237 }
238 
239 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
240 {
241  const uint8_t *frame_end = frame + width * height;
242  uint8_t *line_ptr;
243  int count, i, v, lines, segments;
244  int y = 0;
245 
246  lines = bytestream2_get_le16(gb);
247  if (lines > height)
248  return AVERROR_INVALIDDATA;
249 
250  while (lines--) {
251  if (bytestream2_get_bytes_left(gb) < 2)
252  return AVERROR_INVALIDDATA;
253  segments = bytestream2_get_le16u(gb);
254  while ((segments & 0xC000) == 0xC000) {
255  unsigned skip_lines = -(int16_t)segments;
256  int64_t delta = -((int16_t)segments * (int64_t)width);
257  if (frame_end - frame <= delta || y + lines + skip_lines > height)
258  return AVERROR_INVALIDDATA;
259  frame += delta;
260  y += skip_lines;
261  segments = bytestream2_get_le16(gb);
262  }
263 
264  if (frame_end <= frame)
265  return AVERROR_INVALIDDATA;
266  if (segments & 0x8000) {
267  frame[width - 1] = segments & 0xFF;
268  segments = bytestream2_get_le16(gb);
269  }
270  line_ptr = frame;
271  if (frame_end - frame < width)
272  return AVERROR_INVALIDDATA;
273  frame += width;
274  y++;
275  while (segments--) {
276  if (frame - line_ptr <= bytestream2_peek_byte(gb))
277  return AVERROR_INVALIDDATA;
278  line_ptr += bytestream2_get_byte(gb);
279  count = (int8_t)bytestream2_get_byte(gb);
280  if (count >= 0) {
281  if (frame - line_ptr < count * 2)
282  return AVERROR_INVALIDDATA;
283  if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
284  return AVERROR_INVALIDDATA;
285  line_ptr += count * 2;
286  } else {
287  count = -count;
288  if (frame - line_ptr < count * 2)
289  return AVERROR_INVALIDDATA;
290  v = bytestream2_get_le16(gb);
291  for (i = 0; i < count; i++)
292  bytestream_put_le16(&line_ptr, v);
293  }
294  }
295  }
296 
297  return 0;
298 }
299 
300 static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
301 {
302  const uint8_t *frame_end = frame + width * height;
303  uint32_t segments = bytestream2_get_le32(gb);
304  int skip, copy;
305 
306  while (segments--) {
307  if (bytestream2_get_bytes_left(gb) < 2)
308  return AVERROR_INVALIDDATA;
309  copy = bytestream2_get_byteu(gb) * 2;
310  skip = bytestream2_get_byteu(gb) * 2;
311  if (frame_end - frame < copy + skip ||
313  return AVERROR_INVALIDDATA;
314  frame += skip;
316  frame += copy;
317  }
318 
319  return 0;
320 }
321 
322 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
323 {
324  memset(frame, 0, width * height);
325  return 0;
326 }
327 
328 
329 typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height);
330 
331 static const chunk_decoder decoder[8] = {
334 };
335 
336 static const char chunk_name[8][5] = {
337  "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
338 };
339 
341  int *got_frame, AVPacket *avpkt)
342 {
343  DfaContext *s = avctx->priv_data;
344  GetByteContext gb;
345  const uint8_t *buf = avpkt->data;
346  uint32_t chunk_type, chunk_size;
347  uint8_t *dst;
348  int ret;
349  int i, pal_elems;
350  int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
351 
352  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
353  return ret;
354 
355  bytestream2_init(&gb, avpkt->data, avpkt->size);
356  while (bytestream2_get_bytes_left(&gb) > 0) {
357  if (bytestream2_get_bytes_left(&gb) < 12)
358  return AVERROR_INVALIDDATA;
359  bytestream2_skip(&gb, 4);
360  chunk_size = bytestream2_get_le32(&gb);
361  chunk_type = bytestream2_get_le32(&gb);
362  if (!chunk_type)
363  break;
364  if (chunk_type == 1) {
365  pal_elems = FFMIN(chunk_size / 3, 256);
366  for (i = 0; i < pal_elems; i++) {
367  s->pal[i] = bytestream2_get_be24(&gb) << 2;
368  s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
369  }
370  frame->palette_has_changed = 1;
371  } else if (chunk_type <= 9) {
372  if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
373  av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
374  chunk_name[chunk_type - 2]);
375  return AVERROR_INVALIDDATA;
376  }
377  } else {
378  av_log(avctx, AV_LOG_WARNING,
379  "Ignoring unknown chunk type %"PRIu32"\n",
380  chunk_type);
381  }
382  buf += chunk_size;
383  }
384 
385  buf = s->frame_buf;
386  dst = frame->data[0];
387  if (version == 0x100) {
388  for (i = 0; i < avctx->height; i++) {
389  int j;
390  const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width;
391  int stride = (avctx->height/4)*avctx->width;
392  for(j = 0; j < avctx->width/4; j++) {
393  dst[4*j+0] = buf1[j + 0*stride];
394  dst[4*j+1] = buf1[j + 1*stride];
395  dst[4*j+2] = buf1[j + 2*stride];
396  dst[4*j+3] = buf1[j + 3*stride];
397  }
398  j *= 4;
399  for(; j < avctx->width; j++) {
400  dst[j] = buf1[(j/4) + (j&3)*stride];
401  }
402  dst += frame->linesize[0];
403  }
404  } else
405  av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width,
406  avctx->width, avctx->height);
407 
408  memcpy(frame->data[1], s->pal, sizeof(s->pal));
409 
410  *got_frame = 1;
411 
412  return avpkt->size;
413 }
414 
416 {
417  DfaContext *s = avctx->priv_data;
418 
419  av_freep(&s->frame_buf);
420 
421  return 0;
422 }
423 
425  .p.name = "dfa",
426  CODEC_LONG_NAME("Chronomaster DFA"),
427  .p.type = AVMEDIA_TYPE_VIDEO,
428  .p.id = AV_CODEC_ID_DFA,
429  .priv_data_size = sizeof(DfaContext),
431  .close = dfa_decode_end,
433  .p.capabilities = AV_CODEC_CAP_DR1,
434 };
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
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
dfa_decode_init
static av_cold int dfa_decode_init(AVCodecContext *avctx)
Definition: dfa.c:39
GetByteContext
Definition: bytestream.h:33
decode_wdlt
static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:239
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
AVPacket::data
uint8_t * data
Definition: packet.h:374
FFCodec
Definition: codec_internal.h:127
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
decoder
static const chunk_decoder decoder[8]
Definition: dfa.c:331
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
decode_dsw1
static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:109
avassert.h
frame_start
static int frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1687
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
mask
static const uint16_t mask[17]
Definition: lzw.c:38
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:445
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:528
width
#define width
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
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
decode.h
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
decode_tsw1
static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:66
decode_tdlt
static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:300
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
DfaContext::frame_buf
uint8_t * frame_buf
Definition: dfa.c:36
DfaContext::pal
uint32_t pal[256]
Definition: dfa.c:35
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
decode_bdlt
static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:197
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1473
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:375
copy
static void copy(const float *p1, float *p2, const int length)
Definition: vf_vaguedenoiser.c:187
codec_internal.h
size
int size
Definition: twinvq_data.h:10344
height
#define height
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
DfaContext
Definition: dfa.c:34
version
version
Definition: libkvazaar.c:313
dfa_decode_frame
static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: dfa.c:340
chunk_name
static const char chunk_name[8][5]
Definition: dfa.c:336
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:527
delta
float delta
Definition: vorbis_enc_data.h:430
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:191
AVCodecContext::height
int height
Definition: avcodec.h:598
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:635
avcodec.h
stride
#define stride
Definition: h264pred_template.c:537
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
U
#define U(x)
Definition: vpx_arith.h:37
AVCodecContext
main external API structure.
Definition: avcodec.h:426
dfa_decode_end
static av_cold int dfa_decode_end(AVCodecContext *avctx)
Definition: dfa.c:415
frame_end
static void frame_end(MpegEncContext *s)
Definition: mpegvideo_enc.c:1629
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:453
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:598
bytestream.h
imgutils.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
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
ff_dfa_decoder
const FFCodec ff_dfa_decoder
Definition: dfa.c:424
chunk_decoder
int(* chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:329
av_image_check_size
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:318
AV_CODEC_ID_DFA
@ AV_CODEC_ID_DFA
Definition: codec_id.h:202
int
int
Definition: ffmpeg_filter.c:156
decode_blck
static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:322
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
decode_dds1
static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:146
decode_copy
static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:57