]> git.sesse.net Git - ffmpeg/blob - libavcodec/gdv.c
avcodec/gdv: Factor terms out of inner loops in rescale()
[ffmpeg] / libavcodec / gdv.c
1 /*
2  * Gremlin Digital Video (GDV) decoder
3  * Copyright (c) 2017 Konstantin Shishkov
4  * Copyright (c) 2017 Paul B Mahol
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 "libavutil/common.h"
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "internal.h"
27
28 typedef struct GDVContext {
29     AVCodecContext *avctx;
30
31     GetByteContext gb;
32     GetByteContext g2;
33     PutByteContext pb;
34
35     uint32_t pal[256];
36     uint8_t *frame;
37     unsigned frame_size;
38     unsigned scale_h, scale_v;
39 } GDVContext;
40
41 typedef struct Bits8 {
42     uint8_t queue;
43     uint8_t fill;
44 } Bits8;
45
46 typedef struct Bits32 {
47     uint32_t queue;
48     uint8_t  fill;
49 } Bits32;
50
51 #define PREAMBLE_SIZE 4096
52
53 static av_cold int gdv_decode_init(AVCodecContext *avctx)
54 {
55     GDVContext *gdv = avctx->priv_data;
56     int i, j, k;
57
58     avctx->pix_fmt  = AV_PIX_FMT_PAL8;
59     gdv->frame_size = avctx->width * avctx->height + PREAMBLE_SIZE;
60     gdv->frame = av_calloc(gdv->frame_size, 1);
61     if (!gdv->frame)
62         return AVERROR(ENOMEM);
63
64     for (i = 0; i < 2; i++) {
65         for (j = 0; j < 256; j++) {
66             for (k = 0; k < 8; k++) {
67                 gdv->frame[i * 2048 + j * 8 + k] = j;
68             }
69         }
70     }
71
72     return 0;
73 }
74
75 static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, int scale_h)
76 {
77     int i, j, y, x;
78
79     if ((gdv->scale_v == scale_v) && (gdv->scale_h == scale_h)) {
80         return;
81     }
82
83     if (gdv->scale_h && gdv->scale_v) {
84         for (j = 0; j < h; j++) {
85             int y = h - j - 1;
86             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
87             uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>1) * (w>>1);
88             for (i = 0; i < w; i++) {
89                 int x = w - i - 1;
90                 dst1[x] = src1[(x>>1)];
91             }
92         }
93     } else if (gdv->scale_h) {
94         for (j = 0; j < h; j++) {
95             int y = h - j - 1;
96             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
97             uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>1) * w;
98             memcpy(dst1, src1, w);
99         }
100     } else if (gdv->scale_v) {
101         for (j = 0; j < h; j++) {
102             int y = h - j - 1;
103             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
104             uint8_t *src1 = dst + PREAMBLE_SIZE + y * (w>>1);
105             for (i = 0; i < w; i++) {
106                 int x = w - i - 1;
107                 dst1[x] = src1[(x>>1)];
108             }
109         }
110     }
111
112     if (scale_h && scale_v) {
113         for (y = 0; y < (h>>1); y++) {
114             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * (w>>1);
115             uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w;
116             for (x = 0; x < (w>>1); x++) {
117                 dst1[x] = src1[x*2];
118             }
119         }
120     } else if (scale_h) {
121         for (y = 0; y < (h>>1); y++) {
122             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
123             uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w;
124             memcpy(dst1, src1, w);
125         }
126     } else if (scale_v) {
127         for (y = 0; y < h; y++) {
128             uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
129             for (x = 0; x < (w>>1); x++) {
130                 dst1[x] = dst1[x*2];
131             }
132         }
133     }
134
135     gdv->scale_v = scale_v;
136     gdv->scale_h = scale_h;
137 }
138
139 static int read_bits2(Bits8 *bits, GetByteContext *gb)
140 {
141     int res;
142
143     if (bits->fill == 0) {
144         bits->queue |= bytestream2_get_byte(gb);
145         bits->fill   = 8;
146     }
147     res = bits->queue >> 6;
148     bits->queue <<= 2;
149     bits->fill   -= 2;
150
151     return res;
152 }
153
154 static void fill_bits32(Bits32 *bits, GetByteContext *gb)
155 {
156     bits->queue = bytestream2_get_le32(gb);
157     bits->fill  = 32;
158 }
159
160 static int read_bits32(Bits32 *bits, GetByteContext *gb, int nbits)
161 {
162     int res = bits->queue & ((1 << nbits) - 1);
163
164     bits->queue >>= nbits;
165     bits->fill   -= nbits;
166     if (bits->fill <= 16) {
167         bits->queue |= bytestream2_get_le16(gb) << bits->fill;
168         bits->fill  += 16;
169     }
170
171     return res;
172 }
173
174 static void lz_copy(PutByteContext *pb, GetByteContext *g2, int offset, unsigned len)
175 {
176     int i;
177
178     if (offset == -1) {
179         int c;
180
181         bytestream2_seek(g2, bytestream2_tell_p(pb) - 1, SEEK_SET);
182         c = bytestream2_get_byte(g2);
183         for (i = 0; i < len; i++) {
184             bytestream2_put_byte(pb, c);
185         }
186     } else if (offset < 0) {
187         int start = bytestream2_tell_p(pb) - (-offset);
188
189         bytestream2_seek(g2, start, SEEK_SET);
190         for (i = 0; i < len; i++) {
191             bytestream2_put_byte(pb, bytestream2_get_byte(g2));
192         }
193     } else {
194         int start = bytestream2_tell_p(pb) + offset;
195
196         bytestream2_seek(g2, start, SEEK_SET);
197         for (i = 0; i < len; i++) {
198             bytestream2_put_byte(pb, bytestream2_get_byte(g2));
199         }
200     }
201 }
202
203 static int decompress_2(AVCodecContext *avctx)
204 {
205     GDVContext *gdv = avctx->priv_data;
206     GetByteContext *gb = &gdv->gb;
207     GetByteContext *g2 = &gdv->g2;
208     PutByteContext *pb = &gdv->pb;
209     Bits8 bits = { 0 };
210     int c, i;
211
212     bytestream2_init(g2, gdv->frame, gdv->frame_size);
213     bytestream2_skip_p(pb, PREAMBLE_SIZE);
214
215     for (c = 0; c < 256; c++) {
216         for (i = 0; i < 16; i++) {
217             gdv->frame[c * 16 + i] = c;
218         }
219     }
220
221     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
222         int tag = read_bits2(&bits, gb);
223         if (tag == 0) {
224             bytestream2_put_byte(pb, bytestream2_get_byte(gb));
225         } else if (tag == 1) {
226             int b = bytestream2_get_byte(gb);
227             int len = (b & 0xF) + 3;
228             int top = (b >> 4) & 0xF;
229             int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
230             lz_copy(pb, g2, off, len);
231         } else if (tag == 2) {
232             int len = (bytestream2_get_byte(gb)) + 2;
233             bytestream2_skip_p(pb, len);
234         } else {
235             break;
236         }
237     }
238     return 0;
239 }
240
241 static int decompress_5(AVCodecContext *avctx, unsigned skip)
242 {
243     GDVContext *gdv = avctx->priv_data;
244     GetByteContext *gb = &gdv->gb;
245     GetByteContext *g2 = &gdv->g2;
246     PutByteContext *pb = &gdv->pb;
247     Bits8 bits = { 0 };
248
249     bytestream2_init(g2, gdv->frame, gdv->frame_size);
250     bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
251
252     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
253         int tag = read_bits2(&bits, gb);
254         if (tag == 0) {
255             bytestream2_put_byte(pb, bytestream2_get_byte(gb));
256         } else if (tag == 1) {
257             int b = bytestream2_get_byte(gb);
258             int len = (b & 0xF) + 3;
259             int top = b >> 4;
260             int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
261             lz_copy(pb, g2, off, len);
262         } else if (tag == 2) {
263             int len;
264             int b = bytestream2_get_byte(gb);
265             if (b == 0) {
266                 break;
267             }
268             if (b != 0xFF) {
269                 len = b;
270             } else {
271                 len = bytestream2_get_le16(gb);
272             }
273             bytestream2_skip_p(pb, len + 1);
274         } else {
275             int b = bytestream2_get_byte(gb);
276             int len = (b & 0x3) + 2;
277             int off = -(b >> 2) - 1;
278             lz_copy(pb, g2, off, len);
279         }
280     }
281     return 0;
282 }
283
284 static int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8)
285 {
286     GDVContext *gdv = avctx->priv_data;
287     GetByteContext *gb = &gdv->gb;
288     GetByteContext *g2 = &gdv->g2;
289     PutByteContext *pb = &gdv->pb;
290     Bits32 bits;
291
292     bytestream2_init(g2, gdv->frame, gdv->frame_size);
293     bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
294     fill_bits32(&bits, gb);
295
296     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
297         int tag = read_bits32(&bits, gb, 2);
298         if (tag == 0) {
299             int b = read_bits32(&bits, gb, 1);
300             if (b == 0) {
301                 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
302             } else {
303                 int i, len = 2;
304                 int lbits = 0;
305                 while (1) {
306                     int val;
307
308                     lbits += 1;
309                     val = read_bits32(&bits, gb, lbits);
310                     len += val;
311                     if (val != ((1 << lbits) - 1)) {
312                         break;
313                     }
314                     assert(lbits < 16);
315                 }
316                 for (i = 0; i < len; i++) {
317                     bytestream2_put_byte(pb, bytestream2_get_byte(gb));
318                 }
319             }
320         } else if (tag == 1) {
321             int b = read_bits32(&bits, gb, 1);
322             int len;
323
324             if (b == 0) {
325                 len = (read_bits32(&bits, gb, 4)) + 2;
326             } else {
327                 int bb = bytestream2_get_byte(gb);
328                 if ((bb & 0x80) == 0) {
329                     len = bb + 18;
330                 } else {
331                     int top = (bb & 0x7F) << 8;
332                     len = top + bytestream2_get_byte(gb) + 146;
333                 }
334             }
335             bytestream2_skip_p(pb, len);
336         } else if (tag == 2) {
337             int i, subtag = read_bits32(&bits, gb, 2);
338
339             if (subtag != 3) {
340                 int top = (read_bits32(&bits, gb, 4)) << 8;
341                 int offs = top + bytestream2_get_byte(gb);
342                 if ((subtag != 0) || (offs <= 0xF80)) {
343                     int len = (subtag) + 3;
344                     lz_copy(pb, g2, (offs) - 4096, len);
345                 } else {
346                     int real_off, len, c1, c2;
347
348                     if (offs == 0xFFF) {
349                         return 0;
350                     }
351
352                     real_off = ((offs >> 4) & 0x7) + 1;
353                     len = ((offs & 0xF) + 2) * 2;
354                     c1 = gdv->frame[bytestream2_tell_p(pb) - real_off];
355                     c2 = gdv->frame[bytestream2_tell_p(pb) - real_off + 1];
356                     for (i = 0; i < len/2; i++) {
357                         bytestream2_put_byte(pb, c1);
358                         bytestream2_put_byte(pb, c2);
359                     }
360                 }
361             } else {
362                 int b = bytestream2_get_byte(gb);
363                 int off = ((b & 0x7F)) + 1;
364                 int len = ((b & 0x80) == 0) ? 2 : 3;
365
366                 lz_copy(pb, g2, -off, len);
367             }
368         } else {
369             int len;
370             int off;
371             if (use8) {
372                 int q, b = bytestream2_get_byte(gb);
373                 if ((b & 0xC0) == 0xC0) {
374                     len = ((b & 0x3F)) + 8;
375                     q = read_bits32(&bits, gb, 4);
376                     off = (q << 8) + (bytestream2_get_byte(gb)) + 1;
377                 } else {
378                     int ofs1;
379                     if ((b & 0x80) == 0) {
380                         len = ((b >> 4)) + 6;
381                         ofs1 = (b & 0xF);
382                     } else {
383                         len = ((b & 0x3F)) + 14;
384                         ofs1 = read_bits32(&bits, gb, 4);
385                     }
386                     off = (ofs1 << 8) + (bytestream2_get_byte(gb)) - 4096;
387                 }
388             } else {
389                 int ofs1, b = bytestream2_get_byte(gb);
390
391                 if ((b >> 4) == 0xF) {
392                     len = bytestream2_get_byte(gb) + 21;
393                 } else {
394                     len = (b >> 4) + 6;
395                 }
396                 ofs1 = (b & 0xF);
397                 off = (ofs1 << 8) + bytestream2_get_byte(gb) - 4096;
398             }
399             lz_copy(pb, g2, off, len);
400         }
401     }
402
403     return 0;
404 }
405
406 static int gdv_decode_frame(AVCodecContext *avctx, void *data,
407                             int *got_frame, AVPacket *avpkt)
408 {
409     GDVContext *gdv = avctx->priv_data;
410     GetByteContext *gb = &gdv->gb;
411     PutByteContext *pb = &gdv->pb;
412     AVFrame *frame = data;
413     int ret, i, pal_size;
414     const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
415     int compression;
416     unsigned flags;
417     uint8_t *dst;
418
419     bytestream2_init(gb, avpkt->data, avpkt->size);
420     bytestream2_init_writer(pb, gdv->frame, gdv->frame_size);
421
422     flags = bytestream2_get_le32(gb);
423     compression = flags & 0xF;
424
425     if (compression == 4 || compression == 7 || compression > 8)
426         return AVERROR_INVALIDDATA;
427
428     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
429         return ret;
430     if (pal && pal_size == AVPALETTE_SIZE)
431         memcpy(gdv->pal, pal, AVPALETTE_SIZE);
432
433     rescale(gdv, gdv->frame, avctx->width, avctx->height,
434             !!(flags & 0x10), !!(flags & 0x20));
435
436     switch (compression) {
437     case 1:
438         memset(gdv->frame + PREAMBLE_SIZE, 0, gdv->frame_size - PREAMBLE_SIZE);
439     case 0:
440         if (bytestream2_get_bytes_left(gb) < 256*3)
441             return AVERROR_INVALIDDATA;
442         for (i = 0; i < 256; i++) {
443             unsigned r = bytestream2_get_byte(gb);
444             unsigned g = bytestream2_get_byte(gb);
445             unsigned b = bytestream2_get_byte(gb);
446             gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
447         }
448         break;
449     case 2:
450         ret = decompress_2(avctx);
451         break;
452     case 3:
453         break;
454     case 5:
455         ret = decompress_5(avctx, flags >> 8);
456         break;
457     case 6:
458         ret = decompress_68(avctx, flags >> 8, 0);
459         break;
460     case 8:
461         ret = decompress_68(avctx, flags >> 8, 1);
462         break;
463     default:
464         av_assert0(0);
465     }
466
467     memcpy(frame->data[1], gdv->pal, AVPALETTE_SIZE);
468     dst = frame->data[0];
469
470     if (!gdv->scale_v && !gdv->scale_h) {
471         int sidx = PREAMBLE_SIZE, didx = 0;
472         int y, x;
473
474         for (y = 0; y < avctx->height; y++) {
475             for (x = 0; x < avctx->width; x++) {
476                 dst[x+didx] = gdv->frame[x+sidx];
477             }
478             sidx += avctx->width;
479             didx += frame->linesize[0];
480         }
481     } else {
482         int sidx = PREAMBLE_SIZE, didx = 0;
483         int y, x;
484
485         for (y = 0; y < avctx->height; y++) {
486             if (!gdv->scale_v) {
487                 for (x = 0; x < avctx->width; x++) {
488                     dst[didx + x] = gdv->frame[sidx + x];
489                 }
490             } else {
491                 for (x = 0; x < avctx->width; x++) {
492                     dst[didx + x] = gdv->frame[sidx + x/2];
493                 }
494             }
495             if (!gdv->scale_h || ((y & 1) == 1)) {
496                 sidx += !gdv->scale_v ? avctx->width : avctx->width/2;
497             }
498             didx += frame->linesize[0];
499         }
500     }
501
502     *got_frame = 1;
503
504     return ret < 0 ? ret : avpkt->size;
505 }
506
507 static av_cold int gdv_decode_close(AVCodecContext *avctx)
508 {
509     GDVContext *gdv = avctx->priv_data;
510     av_freep(&gdv->frame);
511     return 0;
512 }
513
514 AVCodec ff_gdv_decoder = {
515     .name           = "gdv",
516     .long_name      = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"),
517     .type           = AVMEDIA_TYPE_VIDEO,
518     .id             = AV_CODEC_ID_GDV,
519     .priv_data_size = sizeof(GDVContext),
520     .init           = gdv_decode_init,
521     .close          = gdv_decode_close,
522     .decode         = gdv_decode_frame,
523     .capabilities   = AV_CODEC_CAP_DR1,
524     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
525 };