FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 "internal.h"
28 
29 #include "libavutil/avassert.h"
30 #include "libavutil/imgutils.h"
31 #include "libavutil/mem.h"
32 
33 typedef struct DfaContext {
34  uint32_t pal[256];
36 } DfaContext;
37 
39 {
40  DfaContext *s = avctx->priv_data;
41 
42  avctx->pix_fmt = AV_PIX_FMT_PAL8;
43 
44  if (!avctx->width || !avctx->height)
45  return AVERROR_INVALIDDATA;
46 
47  av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0);
48 
49  s->frame_buf = av_mallocz(avctx->width * avctx->height);
50  if (!s->frame_buf)
51  return AVERROR(ENOMEM);
52 
53  return 0;
54 }
55 
56 static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
57 {
58  const int size = width * height;
59 
60  if (bytestream2_get_buffer(gb, frame, size) != size)
61  return AVERROR_INVALIDDATA;
62  return 0;
63 }
64 
65 static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
66 {
67  const uint8_t *frame_start = frame;
68  const uint8_t *frame_end = frame + width * height;
69  int mask = 0x10000, bitbuf = 0;
70  int v, count, segments;
71  unsigned offset;
72 
73  segments = bytestream2_get_le32(gb);
74  offset = bytestream2_get_le32(gb);
75  if (segments == 0 && offset == frame_end - frame)
76  return 0; // skip frame
77  if (frame_end - frame <= offset)
78  return AVERROR_INVALIDDATA;
79  frame += offset;
80  while (segments--) {
81  if (bytestream2_get_bytes_left(gb) < 2)
82  return AVERROR_INVALIDDATA;
83  if (mask == 0x10000) {
84  bitbuf = bytestream2_get_le16u(gb);
85  mask = 1;
86  }
87  if (frame_end - frame < 2)
88  return AVERROR_INVALIDDATA;
89  if (bitbuf & mask) {
90  v = bytestream2_get_le16(gb);
91  offset = (v & 0x1FFF) << 1;
92  count = ((v >> 13) + 2) << 1;
93  if (frame - frame_start < offset || frame_end - frame < count)
94  return AVERROR_INVALIDDATA;
95  av_memcpy_backptr(frame, offset, count);
96  frame += count;
97  } else {
98  *frame++ = bytestream2_get_byte(gb);
99  *frame++ = bytestream2_get_byte(gb);
100  }
101  mask <<= 1;
102  }
103 
104  return 0;
105 }
106 
107 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
108 {
109  const uint8_t *frame_start = frame;
110  const uint8_t *frame_end = frame + width * height;
111  int mask = 0x10000, bitbuf = 0;
112  int v, offset, count, segments;
113 
114  segments = bytestream2_get_le16(gb);
115  while (segments--) {
116  if (bytestream2_get_bytes_left(gb) < 2)
117  return AVERROR_INVALIDDATA;
118  if (mask == 0x10000) {
119  bitbuf = bytestream2_get_le16u(gb);
120  mask = 1;
121  }
122  if (frame_end - frame < 2)
123  return AVERROR_INVALIDDATA;
124  if (bitbuf & mask) {
125  v = bytestream2_get_le16(gb);
126  offset = (v & 0x1FFF) << 1;
127  count = ((v >> 13) + 2) << 1;
128  if (frame - frame_start < offset || frame_end - frame < count)
129  return AVERROR_INVALIDDATA;
130  av_memcpy_backptr(frame, offset, count);
131  frame += count;
132  } else if (bitbuf & (mask << 1)) {
133  frame += bytestream2_get_le16(gb);
134  } else {
135  *frame++ = bytestream2_get_byte(gb);
136  *frame++ = bytestream2_get_byte(gb);
137  }
138  mask <<= 2;
139  }
140 
141  return 0;
142 }
143 
144 static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
145 {
146  const uint8_t *frame_start = frame;
147  const uint8_t *frame_end = frame + width * height;
148  int mask = 0x10000, bitbuf = 0;
149  int i, v, offset, count, segments;
150 
151  segments = bytestream2_get_le16(gb);
152  while (segments--) {
153  if (bytestream2_get_bytes_left(gb) < 2)
154  return AVERROR_INVALIDDATA;
155  if (mask == 0x10000) {
156  bitbuf = bytestream2_get_le16u(gb);
157  mask = 1;
158  }
159 
160  if (bitbuf & mask) {
161  v = bytestream2_get_le16(gb);
162  offset = (v & 0x1FFF) << 2;
163  count = ((v >> 13) + 2) << 1;
164  if (frame - frame_start < offset || frame_end - frame < count*2 + width)
165  return AVERROR_INVALIDDATA;
166  for (i = 0; i < count; i++) {
167  frame[0] = frame[1] =
168  frame[width] = frame[width + 1] = frame[-offset];
169 
170  frame += 2;
171  }
172  } else if (bitbuf & (mask << 1)) {
173  v = bytestream2_get_le16(gb)*2;
174  if (frame - frame_end < v)
175  return AVERROR_INVALIDDATA;
176  frame += v;
177  } else {
178  if (frame_end - frame < width + 3)
179  return AVERROR_INVALIDDATA;
180  frame[0] = frame[1] =
181  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
182  frame += 2;
183  frame[0] = frame[1] =
184  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
185  frame += 2;
186  }
187  mask <<= 2;
188  }
189 
190  return 0;
191 }
192 
193 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
194 {
195  uint8_t *line_ptr;
196  int count, lines, segments;
197 
198  count = bytestream2_get_le16(gb);
199  if (count >= height)
200  return AVERROR_INVALIDDATA;
201  frame += width * count;
202  lines = bytestream2_get_le16(gb);
203  if (count + lines > height)
204  return AVERROR_INVALIDDATA;
205 
206  while (lines--) {
207  if (bytestream2_get_bytes_left(gb) < 1)
208  return AVERROR_INVALIDDATA;
209  line_ptr = frame;
210  frame += width;
211  segments = bytestream2_get_byteu(gb);
212  while (segments--) {
213  if (frame - line_ptr <= bytestream2_peek_byte(gb))
214  return AVERROR_INVALIDDATA;
215  line_ptr += bytestream2_get_byte(gb);
216  count = (int8_t)bytestream2_get_byte(gb);
217  if (count >= 0) {
218  if (frame - line_ptr < count)
219  return AVERROR_INVALIDDATA;
220  if (bytestream2_get_buffer(gb, line_ptr, count) != count)
221  return AVERROR_INVALIDDATA;
222  } else {
223  count = -count;
224  if (frame - line_ptr < count)
225  return AVERROR_INVALIDDATA;
226  memset(line_ptr, bytestream2_get_byte(gb), count);
227  }
228  line_ptr += count;
229  }
230  }
231 
232  return 0;
233 }
234 
235 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
236 {
237  const uint8_t *frame_end = frame + width * height;
238  uint8_t *line_ptr;
239  int count, i, v, lines, segments;
240  int y = 0;
241 
242  lines = bytestream2_get_le16(gb);
243  if (lines > height)
244  return AVERROR_INVALIDDATA;
245 
246  while (lines--) {
247  if (bytestream2_get_bytes_left(gb) < 2)
248  return AVERROR_INVALIDDATA;
249  segments = bytestream2_get_le16u(gb);
250  while ((segments & 0xC000) == 0xC000) {
251  unsigned skip_lines = -(int16_t)segments;
252  unsigned delta = -((int16_t)segments * width);
253  if (frame_end - frame <= delta || y + lines + skip_lines > height)
254  return AVERROR_INVALIDDATA;
255  frame += delta;
256  y += skip_lines;
257  segments = bytestream2_get_le16(gb);
258  }
259 
260  if (frame_end <= frame)
261  return AVERROR_INVALIDDATA;
262  if (segments & 0x8000) {
263  frame[width - 1] = segments & 0xFF;
264  segments = bytestream2_get_le16(gb);
265  }
266  line_ptr = frame;
267  if (frame_end - frame < width)
268  return AVERROR_INVALIDDATA;
269  frame += width;
270  y++;
271  while (segments--) {
272  if (frame - line_ptr <= bytestream2_peek_byte(gb))
273  return AVERROR_INVALIDDATA;
274  line_ptr += bytestream2_get_byte(gb);
275  count = (int8_t)bytestream2_get_byte(gb);
276  if (count >= 0) {
277  if (frame - line_ptr < count * 2)
278  return AVERROR_INVALIDDATA;
279  if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
280  return AVERROR_INVALIDDATA;
281  line_ptr += count * 2;
282  } else {
283  count = -count;
284  if (frame - line_ptr < count * 2)
285  return AVERROR_INVALIDDATA;
286  v = bytestream2_get_le16(gb);
287  for (i = 0; i < count; i++)
288  bytestream_put_le16(&line_ptr, v);
289  }
290  }
291  }
292 
293  return 0;
294 }
295 
296 static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
297 {
298  const uint8_t *frame_end = frame + width * height;
299  uint32_t segments = bytestream2_get_le32(gb);
300  int skip, copy;
301 
302  while (segments--) {
303  if (bytestream2_get_bytes_left(gb) < 2)
304  return AVERROR_INVALIDDATA;
305  copy = bytestream2_get_byteu(gb) * 2;
306  skip = bytestream2_get_byteu(gb) * 2;
307  if (frame_end - frame < copy + skip ||
308  bytestream2_get_bytes_left(gb) < copy)
309  return AVERROR_INVALIDDATA;
310  frame += skip;
311  bytestream2_get_buffer(gb, frame, copy);
312  frame += copy;
313  }
314 
315  return 0;
316 }
317 
318 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
319 {
320  memset(frame, 0, width * height);
321  return 0;
322 }
323 
324 
325 typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height);
326 
327 static const chunk_decoder decoder[8] = {
330 };
331 
332 static const char* chunk_name[8] = {
333  "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
334 };
335 
337  void *data, int *got_frame,
338  AVPacket *avpkt)
339 {
340  AVFrame *frame = data;
341  DfaContext *s = avctx->priv_data;
342  GetByteContext gb;
343  const uint8_t *buf = avpkt->data;
344  uint32_t chunk_type, chunk_size;
345  uint8_t *dst;
346  int ret;
347  int i, pal_elems;
348  int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
349 
350  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
351  return ret;
352 
353  bytestream2_init(&gb, avpkt->data, avpkt->size);
354  while (bytestream2_get_bytes_left(&gb) > 0) {
355  bytestream2_skip(&gb, 4);
356  chunk_size = bytestream2_get_le32(&gb);
357  chunk_type = bytestream2_get_le32(&gb);
358  if (!chunk_type)
359  break;
360  if (chunk_type == 1) {
361  pal_elems = FFMIN(chunk_size / 3, 256);
362  for (i = 0; i < pal_elems; i++) {
363  s->pal[i] = bytestream2_get_be24(&gb) << 2;
364  s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
365  }
366  frame->palette_has_changed = 1;
367  } else if (chunk_type <= 9) {
368  if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
369  av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
370  chunk_name[chunk_type - 2]);
371  return AVERROR_INVALIDDATA;
372  }
373  } else {
374  av_log(avctx, AV_LOG_WARNING,
375  "Ignoring unknown chunk type %"PRIu32"\n",
376  chunk_type);
377  }
378  buf += chunk_size;
379  }
380 
381  buf = s->frame_buf;
382  dst = frame->data[0];
383  for (i = 0; i < avctx->height; i++) {
384  if(version == 0x100) {
385  int j;
386  for(j = 0; j < avctx->width; j++) {
387  dst[j] = buf[ (i&3)*(avctx->width /4) + (j/4) +
388  ((j&3)*(avctx->height/4) + (i/4))*avctx->width];
389  }
390  } else {
391  memcpy(dst, buf, avctx->width);
392  buf += avctx->width;
393  }
394  dst += frame->linesize[0];
395  }
396  memcpy(frame->data[1], s->pal, sizeof(s->pal));
397 
398  *got_frame = 1;
399 
400  return avpkt->size;
401 }
402 
404 {
405  DfaContext *s = avctx->priv_data;
406 
407  av_freep(&s->frame_buf);
408 
409  return 0;
410 }
411 
413  .name = "dfa",
414  .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
415  .type = AVMEDIA_TYPE_VIDEO,
416  .id = AV_CODEC_ID_DFA,
417  .priv_data_size = sizeof(DfaContext),
419  .close = dfa_decode_end,
421  .capabilities = AV_CODEC_CAP_DR1,
422 };
float v
const char * s
Definition: avisynth_c.h:631
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:171
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static const char * chunk_name[8]
Definition: dfa.c:332
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
memory handling functions
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1424
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1722
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
int version
Definition: avisynth_c.h:629
AVCodec.
Definition: avcodec.h:3472
static av_cold int dfa_decode_end(AVCodecContext *avctx)
Definition: dfa.c:403
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:87
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
#define av_cold
Definition: attributes.h:74
float delta
8 bit with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:74
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1617
static AVFrame * frame
uint8_t * data
Definition: avcodec.h:1423
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:85
static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:318
ptrdiff_t size
Definition: opengl_enc.c:101
static int dfa_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: dfa.c:336
static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:296
#define av_log(a,...)
#define U(x)
Definition: vp56_arith.h:37
static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:107
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static const uint16_t mask[17]
Definition: lzw.c:38
#define AVERROR(e)
Definition: error.h:43
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
simple assert() macros that are a bit more flexible than ISO C assert().
const char * name
Name of the codec implementation.
Definition: avcodec.h:3479
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
GLsizei count
Definition: opengl_enc.c:109
Libavcodec external API header.
static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:56
Definition: dfa.c:33
static void frame_end(MpegEncContext *s)
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:241
#define FFMIN(a, b)
Definition: common.h:81
float y
static const chunk_decoder decoder[8]
Definition: dfa.c:327
int width
picture width / height.
Definition: avcodec.h:1681
uint32_t pal[256]
Definition: dfa.c:34
static av_cold int dfa_decode_init(AVCodecContext *avctx)
Definition: dfa.c:38
static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:193
static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:144
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
main external API structure.
Definition: avcodec.h:1502
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:1040
static int frame_start(MpegEncContext *s)
void * buf
Definition: avisynth_c.h:553
int extradata_size
Definition: avcodec.h:1618
BYTE int const BYTE int int int height
Definition: avisynth_c.h:676
AVCodec ff_dfa_decoder
Definition: dfa.c:412
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:377
static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:235
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:182
static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
Definition: ccaption_dec.c:523
common internal api header.
static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:65
void * priv_data
Definition: avcodec.h:1544
#define av_freep(p)
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
deliberately overlapping memcpy implementation
Definition: mem.c:430
int(* chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:325
uint8_t * frame_buf
Definition: dfa.c:35
This structure stores compressed data.
Definition: avcodec.h:1400
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:252
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:857
static int width