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;
71  unsigned segments;
72  unsigned offset;
73 
74  segments = bytestream2_get_le32(gb);
75  offset = bytestream2_get_le32(gb);
76  if (segments == 0 && offset == frame_end - frame)
77  return 0; // skip frame
78  if (frame_end - frame <= offset)
79  return AVERROR_INVALIDDATA;
80  frame += offset;
81  while (segments--) {
82  if (bytestream2_get_bytes_left(gb) < 2)
83  return AVERROR_INVALIDDATA;
84  if (mask == 0x10000) {
85  bitbuf = bytestream2_get_le16u(gb);
86  mask = 1;
87  }
88  if (frame_end - frame < 2)
89  return AVERROR_INVALIDDATA;
90  if (bitbuf & mask) {
91  v = bytestream2_get_le16(gb);
92  offset = (v & 0x1FFF) << 1;
93  count = ((v >> 13) + 2) << 1;
94  if (frame - frame_start < offset || frame_end - frame < count)
95  return AVERROR_INVALIDDATA;
96  av_memcpy_backptr(frame, offset, count);
97  frame += count;
98  } else {
99  *frame++ = bytestream2_get_byte(gb);
100  *frame++ = bytestream2_get_byte(gb);
101  }
102  mask <<= 1;
103  }
104 
105  return 0;
106 }
107 
108 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
109 {
110  const uint8_t *frame_start = frame;
111  const uint8_t *frame_end = frame + width * height;
112  int mask = 0x10000, bitbuf = 0;
113  int v, offset, count, segments;
114 
115  segments = bytestream2_get_le16(gb);
116  while (segments--) {
117  if (bytestream2_get_bytes_left(gb) < 2)
118  return AVERROR_INVALIDDATA;
119  if (mask == 0x10000) {
120  bitbuf = bytestream2_get_le16u(gb);
121  mask = 1;
122  }
123  if (frame_end - frame < 2)
124  return AVERROR_INVALIDDATA;
125  if (bitbuf & mask) {
126  v = bytestream2_get_le16(gb);
127  offset = (v & 0x1FFF) << 1;
128  count = ((v >> 13) + 2) << 1;
129  if (frame - frame_start < offset || frame_end - frame < count)
130  return AVERROR_INVALIDDATA;
131  av_memcpy_backptr(frame, offset, count);
132  frame += count;
133  } else if (bitbuf & (mask << 1)) {
134  frame += bytestream2_get_le16(gb);
135  } else {
136  *frame++ = bytestream2_get_byte(gb);
137  *frame++ = bytestream2_get_byte(gb);
138  }
139  mask <<= 2;
140  }
141 
142  return 0;
143 }
144 
145 static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
146 {
147  const uint8_t *frame_start = frame;
148  const uint8_t *frame_end = frame + width * height;
149  int mask = 0x10000, bitbuf = 0;
150  int i, v, offset, count, segments;
151 
152  segments = bytestream2_get_le16(gb);
153  while (segments--) {
154  if (bytestream2_get_bytes_left(gb) < 2)
155  return AVERROR_INVALIDDATA;
156  if (mask == 0x10000) {
157  bitbuf = bytestream2_get_le16u(gb);
158  mask = 1;
159  }
160 
161  if (bitbuf & mask) {
162  v = bytestream2_get_le16(gb);
163  offset = (v & 0x1FFF) << 2;
164  count = ((v >> 13) + 2) << 1;
165  if (frame - frame_start < offset || frame_end - frame < count*2 + width)
166  return AVERROR_INVALIDDATA;
167  for (i = 0; i < count; i++) {
168  frame[0] = frame[1] =
169  frame[width] = frame[width + 1] = frame[-offset];
170 
171  frame += 2;
172  }
173  } else if (bitbuf & (mask << 1)) {
174  v = bytestream2_get_le16(gb)*2;
175  if (frame - frame_end < v)
176  return AVERROR_INVALIDDATA;
177  frame += v;
178  } else {
179  if (frame_end - frame < width + 4)
180  return AVERROR_INVALIDDATA;
181  frame[0] = frame[1] =
182  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
183  frame += 2;
184  frame[0] = frame[1] =
185  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
186  frame += 2;
187  }
188  mask <<= 2;
189  }
190 
191  return 0;
192 }
193 
194 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
195 {
196  uint8_t *line_ptr;
197  int count, lines, segments;
198 
199  count = bytestream2_get_le16(gb);
200  if (count >= height)
201  return AVERROR_INVALIDDATA;
202  frame += width * count;
203  lines = bytestream2_get_le16(gb);
204  if (count + lines > height)
205  return AVERROR_INVALIDDATA;
206 
207  while (lines--) {
208  if (bytestream2_get_bytes_left(gb) < 1)
209  return AVERROR_INVALIDDATA;
210  line_ptr = frame;
211  frame += width;
212  segments = bytestream2_get_byteu(gb);
213  while (segments--) {
214  if (frame - line_ptr <= bytestream2_peek_byte(gb))
215  return AVERROR_INVALIDDATA;
216  line_ptr += bytestream2_get_byte(gb);
217  count = (int8_t)bytestream2_get_byte(gb);
218  if (count >= 0) {
219  if (frame - line_ptr < count)
220  return AVERROR_INVALIDDATA;
221  if (bytestream2_get_buffer(gb, line_ptr, count) != count)
222  return AVERROR_INVALIDDATA;
223  } else {
224  count = -count;
225  if (frame - line_ptr < count)
226  return AVERROR_INVALIDDATA;
227  memset(line_ptr, bytestream2_get_byte(gb), count);
228  }
229  line_ptr += count;
230  }
231  }
232 
233  return 0;
234 }
235 
236 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
237 {
238  const uint8_t *frame_end = frame + width * height;
239  uint8_t *line_ptr;
240  int count, i, v, lines, segments;
241  int y = 0;
242 
243  lines = bytestream2_get_le16(gb);
244  if (lines > height)
245  return AVERROR_INVALIDDATA;
246 
247  while (lines--) {
248  if (bytestream2_get_bytes_left(gb) < 2)
249  return AVERROR_INVALIDDATA;
250  segments = bytestream2_get_le16u(gb);
251  while ((segments & 0xC000) == 0xC000) {
252  unsigned skip_lines = -(int16_t)segments;
253  int64_t delta = -((int16_t)segments * (int64_t)width);
254  if (frame_end - frame <= delta || y + lines + skip_lines > height)
255  return AVERROR_INVALIDDATA;
256  frame += delta;
257  y += skip_lines;
258  segments = bytestream2_get_le16(gb);
259  }
260 
261  if (frame_end <= frame)
262  return AVERROR_INVALIDDATA;
263  if (segments & 0x8000) {
264  frame[width - 1] = segments & 0xFF;
265  segments = bytestream2_get_le16(gb);
266  }
267  line_ptr = frame;
268  if (frame_end - frame < width)
269  return AVERROR_INVALIDDATA;
270  frame += width;
271  y++;
272  while (segments--) {
273  if (frame - line_ptr <= bytestream2_peek_byte(gb))
274  return AVERROR_INVALIDDATA;
275  line_ptr += bytestream2_get_byte(gb);
276  count = (int8_t)bytestream2_get_byte(gb);
277  if (count >= 0) {
278  if (frame - line_ptr < count * 2)
279  return AVERROR_INVALIDDATA;
280  if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
281  return AVERROR_INVALIDDATA;
282  line_ptr += count * 2;
283  } else {
284  count = -count;
285  if (frame - line_ptr < count * 2)
286  return AVERROR_INVALIDDATA;
287  v = bytestream2_get_le16(gb);
288  for (i = 0; i < count; i++)
289  bytestream_put_le16(&line_ptr, v);
290  }
291  }
292  }
293 
294  return 0;
295 }
296 
297 static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
298 {
299  const uint8_t *frame_end = frame + width * height;
300  uint32_t segments = bytestream2_get_le32(gb);
301  int skip, copy;
302 
303  while (segments--) {
304  if (bytestream2_get_bytes_left(gb) < 2)
305  return AVERROR_INVALIDDATA;
306  copy = bytestream2_get_byteu(gb) * 2;
307  skip = bytestream2_get_byteu(gb) * 2;
308  if (frame_end - frame < copy + skip ||
309  bytestream2_get_bytes_left(gb) < copy)
310  return AVERROR_INVALIDDATA;
311  frame += skip;
312  bytestream2_get_buffer(gb, frame, copy);
313  frame += copy;
314  }
315 
316  return 0;
317 }
318 
319 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
320 {
321  memset(frame, 0, width * height);
322  return 0;
323 }
324 
325 
327 
328 static const chunk_decoder decoder[8] = {
331 };
332 
333 static const char * const chunk_name[8] = {
334  "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
335 };
336 
338  void *data, int *got_frame,
339  AVPacket *avpkt)
340 {
341  AVFrame *frame = data;
342  DfaContext *s = avctx->priv_data;
343  GetByteContext gb;
344  const uint8_t *buf = avpkt->data;
345  uint32_t chunk_type, chunk_size;
346  uint8_t *dst;
347  int ret;
348  int i, pal_elems;
349  int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
350 
351  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
352  return ret;
353 
354  bytestream2_init(&gb, avpkt->data, avpkt->size);
355  while (bytestream2_get_bytes_left(&gb) > 0) {
356  bytestream2_skip(&gb, 4);
357  chunk_size = bytestream2_get_le32(&gb);
358  chunk_type = bytestream2_get_le32(&gb);
359  if (!chunk_type)
360  break;
361  if (chunk_type == 1) {
362  pal_elems = FFMIN(chunk_size / 3, 256);
363  for (i = 0; i < pal_elems; i++) {
364  s->pal[i] = bytestream2_get_be24(&gb) << 2;
365  s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
366  }
367  frame->palette_has_changed = 1;
368  } else if (chunk_type <= 9) {
369  if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
370  av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
371  chunk_name[chunk_type - 2]);
372  return AVERROR_INVALIDDATA;
373  }
374  } else {
375  av_log(avctx, AV_LOG_WARNING,
376  "Ignoring unknown chunk type %"PRIu32"\n",
377  chunk_type);
378  }
379  buf += chunk_size;
380  }
381 
382  buf = s->frame_buf;
383  dst = frame->data[0];
384  for (i = 0; i < avctx->height; i++) {
385  if(version == 0x100) {
386  int j;
387  for(j = 0; j < avctx->width; j++) {
388  dst[j] = buf[ (i&3)*(avctx->width /4) + (j/4) +
389  ((j&3)*(avctx->height/4) + (i/4))*avctx->width];
390  }
391  } else {
392  memcpy(dst, buf, avctx->width);
393  buf += avctx->width;
394  }
395  dst += frame->linesize[0];
396  }
397  memcpy(frame->data[1], s->pal, sizeof(s->pal));
398 
399  *got_frame = 1;
400 
401  return avpkt->size;
402 }
403 
405 {
406  DfaContext *s = avctx->priv_data;
407 
408  av_freep(&s->frame_buf);
409 
410  return 0;
411 }
412 
414  .name = "dfa",
415  .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
416  .type = AVMEDIA_TYPE_VIDEO,
417  .id = AV_CODEC_ID_DFA,
418  .priv_data_size = sizeof(DfaContext),
420  .close = dfa_decode_end,
422  .capabilities = AV_CODEC_CAP_DR1,
423 };
const char * s
Definition: avisynth_c.h:768
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void copy(const float *p1, float *p2, const int length)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:201
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
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:1680
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1989
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:766
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
AVCodec.
Definition: avcodec.h:3739
static av_cold int dfa_decode_end(AVCodecContext *avctx)
Definition: dfa.c:404
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:87
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:42
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
#define av_cold
Definition: attributes.h:82
float delta
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:73
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1876
static AVFrame * frame
#define height
uint8_t * data
Definition: avcodec.h:1679
static const char *const chunk_name[8]
Definition: dfa.c:333
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:400
static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:319
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:337
static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:297
#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:108
#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:179
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
uint16_t width
Definition: gdv.c:47
simple assert() macros that are a bit more flexible than ISO C assert().
const char * name
Name of the codec implementation.
Definition: avcodec.h:3746
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
GLsizei count
Definition: opengl_enc.c:109
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:281
#define FFMIN(a, b)
Definition: common.h:96
static const chunk_decoder decoder[8]
Definition: dfa.c:328
int width
picture width / height.
Definition: avcodec.h:1948
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:194
static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:145
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:232
main external API structure.
Definition: avcodec.h:1761
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1669
static int frame_start(MpegEncContext *s)
void * buf
Definition: avisynth_c.h:690
int extradata_size
Definition: avcodec.h:1877
AVCodec ff_dfa_decoder
Definition: dfa.c:413
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:358
static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:236
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:215
int
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:1803
#define av_freep(p)
int(* chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:326
uint8_t * frame_buf
Definition: dfa.c:35
This structure stores compressed data.
Definition: avcodec.h:1656
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:1002