FFmpeg
Loading...
Searching...
No Matches
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
34typedef struct DfaContext {
35 uint32_t pal[256];
36 uint8_t *frame_buf;
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))
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
57static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
58{
59 const int size = width * height;
60
63 return 0;
64}
65
66static 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)
81 frame += offset;
82 while (segments--) {
85 if (mask == 0x10000) {
86 bitbuf = bytestream2_get_le16u(gb);
87 mask = 1;
88 }
89 if (frame_end - frame < 2)
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)
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
109static 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;
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
146static 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
197static 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
239static 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);
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
300static 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
322static 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
329typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height);
330
335
336static 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;
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 } 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 if (version == 0x100) {
387 for (i = 0; i < avctx->height; i++) {
388 int j;
389 const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width;
390 int stride = (avctx->height/4)*avctx->width;
391 for(j = 0; j < avctx->width/4; j++) {
392 dst[4*j+0] = buf1[j + 0*stride];
393 dst[4*j+1] = buf1[j + 1*stride];
394 dst[4*j+2] = buf1[j + 2*stride];
395 dst[4*j+3] = buf1[j + 3*stride];
396 }
397 j *= 4;
398 for(; j < avctx->width; j++) {
399 dst[j] = buf1[(j/4) + (j&3)*stride];
400 }
401 dst += frame->linesize[0];
402 }
403 } else
404 av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width,
405 avctx->width, avctx->height);
406
407 memcpy(frame->data[1], s->pal, sizeof(s->pal));
408
409 *got_frame = 1;
410
411 return avpkt->size;
412}
413
415{
416 DfaContext *s = avctx->priv_data;
417
418 av_freep(&s->frame_buf);
419
420 return 0;
421}
422
424 .p.name = "dfa",
425 CODEC_LONG_NAME("Chronomaster DFA"),
426 .p.type = AVMEDIA_TYPE_VIDEO,
427 .p.id = AV_CODEC_ID_DFA,
428 .priv_data_size = sizeof(DfaContext),
432 .p.capabilities = AV_CODEC_CAP_DR1,
433};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
const FFCodec ff_dfa_decoder
Definition dfa.c:423
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition bytestream.h:267
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
long long int64_t
Definition coverity.c:34
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_DFA
Definition codec_id.h:200
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition mem.c:445
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
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
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
misc image utilities
#define AV_RL16(p)
unsigned offset
Definition libaomenc.c:763
static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:109
static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition dfa.c:340
int(* chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:329
static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:197
static const char chunk_name[8][5]
Definition dfa.c:336
static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:66
static const chunk_decoder decoder[8]
Definition dfa.c:331
static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:146
static av_cold int dfa_decode_init(AVCodecContext *avctx)
Definition dfa.c:39
static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:300
static av_cold int dfa_decode_end(AVCodecContext *avctx)
Definition dfa.c:414
static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:239
static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:57
static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
Definition dfa.c:322
#define av_cold
Definition attributes.h:117
version
Definition libkvazaar.c:313
static const uint16_t mask[17]
Definition lzw.c:38
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
static void frame_start(MPVMainEncContext *const m)
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
int extradata_size
Definition avcodec.h:527
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
uint32_t pal[256]
Definition dfa.c:35
uint8_t * frame_buf
Definition dfa.c:36
#define stride
static int64_t frame_end(const SyncQueue *sq, SyncQueueFrame frame, int nb_samples)
Compute the end timestamp of a frame.
Definition sync_queue.c:118
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
int size
static void copy(const float *p1, float *p2, const int length)
float delta