FFmpeg  4.0
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 || FFMAX(avctx->width, avctx->height) >= (1<<16))
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  if ((width | height) & 1)
153  return AVERROR_INVALIDDATA;
154  segments = bytestream2_get_le16(gb);
155  while (segments--) {
156  if (bytestream2_get_bytes_left(gb) < 2)
157  return AVERROR_INVALIDDATA;
158  if (mask == 0x10000) {
159  bitbuf = bytestream2_get_le16u(gb);
160  mask = 1;
161  }
162 
163  if (bitbuf & mask) {
164  v = bytestream2_get_le16(gb);
165  offset = (v & 0x1FFF) << 2;
166  count = ((v >> 13) + 2) << 1;
167  if (frame - frame_start < offset || frame_end - frame < count*2 + width)
168  return AVERROR_INVALIDDATA;
169  for (i = 0; i < count; i++) {
170  frame[0] = frame[1] =
171  frame[width] = frame[width + 1] = frame[-offset];
172 
173  frame += 2;
174  }
175  } else if (bitbuf & (mask << 1)) {
176  v = bytestream2_get_le16(gb)*2;
177  if (frame - frame_end < v)
178  return AVERROR_INVALIDDATA;
179  frame += v;
180  } else {
181  if (width < 4 || frame_end - frame < width + 4)
182  return AVERROR_INVALIDDATA;
183  frame[0] = frame[1] =
184  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
185  frame += 2;
186  frame[0] = frame[1] =
187  frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
188  frame += 2;
189  }
190  mask <<= 2;
191  }
192 
193  return 0;
194 }
195 
196 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
197 {
198  uint8_t *line_ptr;
199  int count, lines, segments;
200 
201  count = bytestream2_get_le16(gb);
202  if (count >= height)
203  return AVERROR_INVALIDDATA;
204  frame += width * count;
205  lines = bytestream2_get_le16(gb);
206  if (count + lines > height)
207  return AVERROR_INVALIDDATA;
208 
209  while (lines--) {
210  if (bytestream2_get_bytes_left(gb) < 1)
211  return AVERROR_INVALIDDATA;
212  line_ptr = frame;
213  frame += width;
214  segments = bytestream2_get_byteu(gb);
215  while (segments--) {
216  if (frame - line_ptr <= bytestream2_peek_byte(gb))
217  return AVERROR_INVALIDDATA;
218  line_ptr += bytestream2_get_byte(gb);
219  count = (int8_t)bytestream2_get_byte(gb);
220  if (count >= 0) {
221  if (frame - line_ptr < count)
222  return AVERROR_INVALIDDATA;
223  if (bytestream2_get_buffer(gb, line_ptr, count) != count)
224  return AVERROR_INVALIDDATA;
225  } else {
226  count = -count;
227  if (frame - line_ptr < count)
228  return AVERROR_INVALIDDATA;
229  memset(line_ptr, bytestream2_get_byte(gb), count);
230  }
231  line_ptr += count;
232  }
233  }
234 
235  return 0;
236 }
237 
238 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
239 {
240  const uint8_t *frame_end = frame + width * height;
241  uint8_t *line_ptr;
242  int count, i, v, lines, segments;
243  int y = 0;
244 
245  lines = bytestream2_get_le16(gb);
246  if (lines > height)
247  return AVERROR_INVALIDDATA;
248 
249  while (lines--) {
250  if (bytestream2_get_bytes_left(gb) < 2)
251  return AVERROR_INVALIDDATA;
252  segments = bytestream2_get_le16u(gb);
253  while ((segments & 0xC000) == 0xC000) {
254  unsigned skip_lines = -(int16_t)segments;
255  int64_t delta = -((int16_t)segments * (int64_t)width);
256  if (frame_end - frame <= delta || y + lines + skip_lines > height)
257  return AVERROR_INVALIDDATA;
258  frame += delta;
259  y += skip_lines;
260  segments = bytestream2_get_le16(gb);
261  }
262 
263  if (frame_end <= frame)
264  return AVERROR_INVALIDDATA;
265  if (segments & 0x8000) {
266  frame[width - 1] = segments & 0xFF;
267  segments = bytestream2_get_le16(gb);
268  }
269  line_ptr = frame;
270  if (frame_end - frame < width)
271  return AVERROR_INVALIDDATA;
272  frame += width;
273  y++;
274  while (segments--) {
275  if (frame - line_ptr <= bytestream2_peek_byte(gb))
276  return AVERROR_INVALIDDATA;
277  line_ptr += bytestream2_get_byte(gb);
278  count = (int8_t)bytestream2_get_byte(gb);
279  if (count >= 0) {
280  if (frame - line_ptr < count * 2)
281  return AVERROR_INVALIDDATA;
282  if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
283  return AVERROR_INVALIDDATA;
284  line_ptr += count * 2;
285  } else {
286  count = -count;
287  if (frame - line_ptr < count * 2)
288  return AVERROR_INVALIDDATA;
289  v = bytestream2_get_le16(gb);
290  for (i = 0; i < count; i++)
291  bytestream_put_le16(&line_ptr, v);
292  }
293  }
294  }
295 
296  return 0;
297 }
298 
299 static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
300 {
301  const uint8_t *frame_end = frame + width * height;
302  uint32_t segments = bytestream2_get_le32(gb);
303  int skip, copy;
304 
305  while (segments--) {
306  if (bytestream2_get_bytes_left(gb) < 2)
307  return AVERROR_INVALIDDATA;
308  copy = bytestream2_get_byteu(gb) * 2;
309  skip = bytestream2_get_byteu(gb) * 2;
310  if (frame_end - frame < copy + skip ||
311  bytestream2_get_bytes_left(gb) < copy)
312  return AVERROR_INVALIDDATA;
313  frame += skip;
314  bytestream2_get_buffer(gb, frame, copy);
315  frame += copy;
316  }
317 
318  return 0;
319 }
320 
321 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
322 {
323  memset(frame, 0, width * height);
324  return 0;
325 }
326 
327 
329 
330 static const chunk_decoder decoder[8] = {
333 };
334 
335 static const char * const chunk_name[8] = {
336  "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
337 };
338 
340  void *data, int *got_frame,
341  AVPacket *avpkt)
342 {
343  AVFrame *frame = data;
344  DfaContext *s = avctx->priv_data;
345  GetByteContext gb;
346  const uint8_t *buf = avpkt->data;
347  uint32_t chunk_type, chunk_size;
348  uint8_t *dst;
349  int ret;
350  int i, pal_elems;
351  int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
352 
353  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
354  return ret;
355 
356  bytestream2_init(&gb, avpkt->data, avpkt->size);
357  while (bytestream2_get_bytes_left(&gb) > 0) {
358  bytestream2_skip(&gb, 4);
359  chunk_size = bytestream2_get_le32(&gb);
360  chunk_type = bytestream2_get_le32(&gb);
361  if (!chunk_type)
362  break;
363  if (chunk_type == 1) {
364  pal_elems = FFMIN(chunk_size / 3, 256);
365  for (i = 0; i < pal_elems; i++) {
366  s->pal[i] = bytestream2_get_be24(&gb) << 2;
367  s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
368  }
369  frame->palette_has_changed = 1;
370  } else if (chunk_type <= 9) {
371  if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
372  av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
373  chunk_name[chunk_type - 2]);
374  return AVERROR_INVALIDDATA;
375  }
376  } else {
377  av_log(avctx, AV_LOG_WARNING,
378  "Ignoring unknown chunk type %"PRIu32"\n",
379  chunk_type);
380  }
381  buf += chunk_size;
382  }
383 
384  buf = s->frame_buf;
385  dst = frame->data[0];
386  for (i = 0; i < avctx->height; i++) {
387  if(version == 0x100) {
388  int j;
389  for(j = 0; j < avctx->width; j++) {
390  dst[j] = buf[ (i&3)*(avctx->width /4) + (j/4) +
391  ((j&3)*(avctx->height/4) + (i/4))*avctx->width];
392  }
393  } else {
394  memcpy(dst, buf, avctx->width);
395  buf += avctx->width;
396  }
397  dst += frame->linesize[0];
398  }
399  memcpy(frame->data[1], s->pal, sizeof(s->pal));
400 
401  *got_frame = 1;
402 
403  return avpkt->size;
404 }
405 
407 {
408  DfaContext *s = avctx->priv_data;
409 
410  av_freep(&s->frame_buf);
411 
412  return 0;
413 }
414 
416  .name = "dfa",
417  .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
418  .type = AVMEDIA_TYPE_VIDEO,
419  .id = AV_CODEC_ID_DFA,
420  .priv_data_size = sizeof(DfaContext),
422  .close = dfa_decode_end,
424  .capabilities = AV_CODEC_CAP_DR1,
425 };
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)
int size
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
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:1431
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1727
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
#define AV_RL16
Definition: intreadwrite.h:42
int version
Definition: avisynth_c.h:766
AVCodec.
Definition: avcodec.h:3408
static av_cold int dfa_decode_end(AVCodecContext *avctx)
Definition: dfa.c:406
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:1618
static AVFrame * frame
const char data[16]
Definition: mxf.c:90
#define height
uint8_t * data
Definition: avcodec.h:1430
static const char *const chunk_name[8]
Definition: dfa.c:335
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:414
static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:321
static int dfa_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: dfa.c:339
static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:299
#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:186
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().
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
#define FFMAX(a, b)
Definition: common.h:94
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:282
#define FFMIN(a, b)
Definition: common.h:96
static const chunk_decoder decoder[8]
Definition: dfa.c:330
int width
picture width / height.
Definition: avcodec.h:1690
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:196
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:249
int(* chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:328
main external API structure.
Definition: avcodec.h:1518
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1891
static int frame_start(MpegEncContext *s)
void * buf
Definition: avisynth_c.h:690
int extradata_size
Definition: avcodec.h:1619
AVCodec ff_dfa_decoder
Definition: dfa.c:415
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:375
static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition: dfa.c:238
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
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:1545
#define av_freep(p)
void INT64 INT64 count
Definition: avisynth_c.h:690
uint8_t * frame_buf
Definition: dfa.c:35
This structure stores compressed data.
Definition: avcodec.h:1407
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:959