GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/argo.c Lines: 0 465 0.0 %
Date: 2020-10-23 17:01:47 Branches: 0 276 0.0 %

Line Branch Exec Source
1
/*
2
 * Argonaut Games Video decoder
3
 * Copyright (c) 2020 Paul B Mahol
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "libavutil/imgutils.h"
27
#include "libavutil/internal.h"
28
#include "libavutil/intreadwrite.h"
29
#include "libavutil/mem.h"
30
31
#include "avcodec.h"
32
#include "bytestream.h"
33
#include "internal.h"
34
35
typedef struct ArgoContext {
36
    GetByteContext gb;
37
38
    int bpp;
39
    int key;
40
    int mv0[128][2];
41
    int mv1[16][2];
42
    uint32_t pal[256];
43
    AVFrame *frame;
44
} ArgoContext;
45
46
static int decode_pal8(AVCodecContext *avctx, uint32_t *pal)
47
{
48
    ArgoContext *s = avctx->priv_data;
49
    GetByteContext *gb = &s->gb;
50
    int start, count;
51
52
    start = bytestream2_get_le16(gb);
53
    count = bytestream2_get_le16(gb);
54
55
    if (start + count > 256)
56
        return AVERROR_INVALIDDATA;
57
58
    if (bytestream2_get_bytes_left(gb) < 3 * count)
59
        return AVERROR_INVALIDDATA;
60
61
    for (int i = 0; i < count; i++)
62
        pal[start + i] = (0xFF << 24U) | bytestream2_get_be24u(gb);
63
64
    return 0;
65
}
66
67
static int decode_avcf(AVCodecContext *avctx, AVFrame *frame)
68
{
69
    ArgoContext *s = avctx->priv_data;
70
    GetByteContext *gb = &s->gb;
71
    const int l = frame->linesize[0];
72
    const uint8_t *map = gb->buffer;
73
    uint8_t *dst = frame->data[0];
74
75
    if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2))
76
        return AVERROR_INVALIDDATA;
77
78
    bytestream2_skipu(gb, 1024);
79
    for (int y = 0; y < frame->height; y += 2) {
80
        for (int x = 0; x < frame->width; x += 2) {
81
            int index = bytestream2_get_byteu(gb);
82
            const uint8_t *block = map + index * 4;
83
84
            dst[x+0]   = block[0];
85
            dst[x+1]   = block[1];
86
            dst[x+l]   = block[2];
87
            dst[x+l+1] = block[3];
88
        }
89
90
        dst += frame->linesize[0] * 2;
91
    }
92
93
    return 0;
94
}
95
96
static int decode_alcd(AVCodecContext *avctx, AVFrame *frame)
97
{
98
    ArgoContext *s = avctx->priv_data;
99
    GetByteContext *gb = &s->gb;
100
    GetByteContext sb;
101
    const int l = frame->linesize[0];
102
    const uint8_t *map = gb->buffer;
103
    uint8_t *dst = frame->data[0];
104
    uint8_t codes = 0;
105
    int count = 0;
106
107
    if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3))
108
        return AVERROR_INVALIDDATA;
109
110
    bytestream2_skipu(gb, 1024);
111
    sb = *gb;
112
    bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3);
113
114
    for (int y = 0; y < frame->height; y += 2) {
115
        for (int x = 0; x < frame->width; x += 2) {
116
            const uint8_t *block;
117
            int index;
118
119
            if (count == 0) {
120
                codes = bytestream2_get_byteu(&sb);
121
                count = 8;
122
            }
123
124
            if (codes & 0x80) {
125
                index = bytestream2_get_byte(gb);
126
                block = map + index * 4;
127
128
                dst[x+0]   = block[0];
129
                dst[x+1]   = block[1];
130
                dst[x+l]   = block[2];
131
                dst[x+l+1] = block[3];
132
            }
133
134
            codes <<= 1;
135
            count--;
136
        }
137
138
        dst += frame->linesize[0] * 2;
139
    }
140
141
    return 0;
142
}
143
144
static int decode_mad1(AVCodecContext *avctx, AVFrame *frame)
145
{
146
    ArgoContext *s = avctx->priv_data;
147
    GetByteContext *gb = &s->gb;
148
    const int w = frame->width;
149
    const int h = frame->height;
150
    const int l = frame->linesize[0];
151
152
    while (bytestream2_get_bytes_left(gb) > 0) {
153
        int size, type, pos, dy;
154
        uint8_t *dst;
155
156
        type = bytestream2_get_byte(gb);
157
        if (type == 0xFF)
158
            break;
159
160
        switch (type) {
161
        case 8:
162
            dst = frame->data[0];
163
            for (int y = 0; y < h; y += 8) {
164
                for (int x = 0; x < w; x += 8) {
165
                    int fill = bytestream2_get_byte(gb);
166
                    uint8_t *ddst = dst + x;
167
168
                    for (int by = 0; by < 8; by++) {
169
                        memset(ddst, fill, 8);
170
                        ddst += l;
171
                    }
172
                }
173
174
                dst += 8 * l;
175
            }
176
            break;
177
        case 7:
178
            while (bytestream2_get_bytes_left(gb) > 0) {
179
                int bsize = bytestream2_get_byte(gb);
180
                uint8_t *src;
181
                int count;
182
183
                if (!bsize)
184
                    break;
185
186
                count = bytestream2_get_be16(gb);
187
                while (count > 0) {
188
                    int mvx, mvy, a, b, c, mx, my;
189
                    int bsize_w, bsize_h;
190
191
                    bsize_w = bsize_h = bsize;
192
                    if (bytestream2_get_bytes_left(gb) < 4)
193
                        return AVERROR_INVALIDDATA;
194
                    mvx = bytestream2_get_byte(gb) * bsize;
195
                    mvy = bytestream2_get_byte(gb) * bsize;
196
                    a = bytestream2_get_byte(gb);
197
                    b = bytestream2_get_byte(gb);
198
                    c = ((a & 0x3F) << 8) + b;
199
                    mx = mvx + (c  & 0x7F) - 64;
200
                    my = mvy + (c >>    7) - 64;
201
202
                    if (mvy < 0 || mvy >= h)
203
                        return AVERROR_INVALIDDATA;
204
205
                    if (mvx < 0 || mvx >= w)
206
                        return AVERROR_INVALIDDATA;
207
208
                    if (my < 0 || my >= h)
209
                        return AVERROR_INVALIDDATA;
210
211
                    if (mx < 0 || mx >= w)
212
                        return AVERROR_INVALIDDATA;
213
214
                    dst = frame->data[0] + mvx + l * mvy;
215
                    src = frame->data[0] + mx  + l * my;
216
217
                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
218
                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
219
220
                    if (mvy >= my && (mvy != my || mvx >= mx)) {
221
                        src += (bsize_h - 1) * l;
222
                        dst += (bsize_h - 1) * l;
223
                        for (int by = 0; by < bsize_h; by++) {
224
                            memmove(dst, src, bsize_w);
225
                            src -= l;
226
                            dst -= l;
227
                        }
228
                    } else {
229
                        for (int by = 0; by < bsize_h; by++) {
230
                            memmove(dst, src, bsize_w);
231
                            src += l;
232
                            dst += l;
233
                        }
234
                    }
235
236
                    count--;
237
                }
238
            }
239
            break;
240
        case 6:
241
            dst = frame->data[0];
242
            if (bytestream2_get_bytes_left(gb) < w * h)
243
                return AVERROR_INVALIDDATA;
244
            for (int y = 0; y < h; y++) {
245
                bytestream2_get_bufferu(gb, dst, w);
246
                dst += l;
247
            }
248
            break;
249
        case 5:
250
            dst = frame->data[0];
251
            for (int y = 0; y < h; y += 2) {
252
                for (int x = 0; x < w; x += 2) {
253
                    int fill = bytestream2_get_byte(gb);
254
                    uint8_t *ddst = dst + x;
255
256
                    fill = (fill << 8) | fill;
257
                    for (int by = 0; by < 2; by++) {
258
                            AV_WN16(ddst, fill);
259
260
                        ddst += l;
261
                    }
262
                }
263
264
                dst += 2 * l;
265
            }
266
            break;
267
        case 3:
268
            size = bytestream2_get_le16(gb);
269
            if (size > 0) {
270
                int x = bytestream2_get_byte(gb) * 4;
271
                int y = bytestream2_get_byte(gb) * 4;
272
                int count = bytestream2_get_byte(gb);
273
                int fill = bytestream2_get_byte(gb);
274
275
                av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill);
276
                for (int i = 0; i < count; i++)
277
                    ;
278
                return AVERROR_PATCHWELCOME;
279
            }
280
            break;
281
        case 2:
282
            dst = frame->data[0];
283
            pos = 0;
284
            dy  = 0;
285
            while (bytestream2_get_bytes_left(gb) > 0) {
286
                int count = bytestream2_get_byteu(gb);
287
                int skip = count & 0x3F;
288
289
                count = count >> 6;
290
                if (skip == 0x3F) {
291
                    pos += 0x3E;
292
                    while (pos >= w) {
293
                        pos -= w;
294
                        dst += l;
295
                        dy++;
296
                        if (dy >= h)
297
                            return 0;
298
                    }
299
                } else {
300
                    pos += skip;
301
                    while (pos >= w) {
302
                        pos -= w;
303
                        dst += l;
304
                        dy++;
305
                        if (dy >= h)
306
                            return 0;
307
                    }
308
                    while (count >= 0) {
309
                        int bits = bytestream2_get_byte(gb);
310
311
                        for (int i = 0; i < 4; i++) {
312
                            switch (bits & 3) {
313
                            case 0:
314
                                break;
315
                            case 1:
316
                                if (dy < 1 && !pos)
317
                                    return AVERROR_INVALIDDATA;
318
                                else
319
                                    dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1];
320
                                break;
321
                            case 2:
322
                                if (dy < 1)
323
                                    return AVERROR_INVALIDDATA;
324
                                dst[pos] = dst[pos - l];
325
                                break;
326
                            case 3:
327
                                dst[pos] = bytestream2_get_byte(gb);
328
                                break;
329
                            }
330
331
                            pos++;
332
                            if (pos >= w) {
333
                                pos -= w;
334
                                dst += l;
335
                                dy++;
336
                                if (dy >= h)
337
                                    return 0;
338
                            }
339
                            bits >>= 2;
340
                        }
341
                        count--;
342
                    }
343
                }
344
            }
345
            break;
346
        default:
347
            return AVERROR_INVALIDDATA;
348
        }
349
    }
350
351
    return 0;
352
}
353
354
static int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame)
355
{
356
    ArgoContext *s = avctx->priv_data;
357
    GetByteContext *gb = &s->gb;
358
    const int w = frame->width;
359
    const int h = frame->height;
360
    const int l = frame->linesize[0] / 4;
361
362
    while (bytestream2_get_bytes_left(gb) > 0) {
363
        int osize, type, pos, dy, di, bcode, value, v14;
364
        const uint8_t *bits;
365
        uint32_t *dst;
366
367
        type = bytestream2_get_byte(gb);
368
        if (type == 0xFF)
369
            return 0;
370
371
        switch (type) {
372
        case 8:
373
            dst = (uint32_t *)frame->data[0];
374
            for (int y = 0; y + 12 <= h; y += 12) {
375
                for (int x = 0; x + 12 <= w; x += 12) {
376
                    int fill = bytestream2_get_be24(gb);
377
                    uint32_t *dstp = dst + x;
378
379
                    for (int by = 0; by < 12; by++) {
380
                        for (int bx = 0; bx < 12; bx++)
381
                            dstp[bx] = fill;
382
383
                        dstp += l;
384
                    }
385
                }
386
387
                dst += 12 * l;
388
            }
389
            break;
390
        case 7:
391
            while (bytestream2_get_bytes_left(gb) > 0) {
392
                int bsize = bytestream2_get_byte(gb);
393
                uint32_t *src;
394
                int count;
395
396
                if (!bsize)
397
                    break;
398
399
                count = bytestream2_get_be16(gb);
400
                while (count > 0) {
401
                    int mvx, mvy, a, b, c, mx, my;
402
                    int bsize_w, bsize_h;
403
404
                    bsize_w = bsize_h = bsize;
405
                    if (bytestream2_get_bytes_left(gb) < 4)
406
                        return AVERROR_INVALIDDATA;
407
                    mvx = bytestream2_get_byte(gb) * bsize;
408
                    mvy = bytestream2_get_byte(gb) * bsize;
409
                    a = bytestream2_get_byte(gb);
410
                    b = bytestream2_get_byte(gb);
411
                    c = ((a & 0x3F) << 8) + b;
412
                    mx = mvx + (c  & 0x7F) - 64;
413
                    my = mvy + (c >>    7) - 64;
414
415
                    if (mvy < 0 || mvy >= h)
416
                        return AVERROR_INVALIDDATA;
417
418
                    if (mvx < 0 || mvx >= w)
419
                        return AVERROR_INVALIDDATA;
420
421
                    if (my < 0 || my >= h)
422
                        return AVERROR_INVALIDDATA;
423
424
                    if (mx < 0 || mx >= w)
425
                        return AVERROR_INVALIDDATA;
426
427
                    dst = (uint32_t *)frame->data[0] + mvx + l * mvy;
428
                    src = (uint32_t *)frame->data[0] + mx  + l * my;
429
430
                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
431
                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
432
433
                    if (mvy >= my && (mvy != my || mvx >= mx)) {
434
                        src += (bsize_h - 1) * l;
435
                        dst += (bsize_h - 1) * l;
436
                        for (int by = 0; by < bsize_h; by++) {
437
                            memmove(dst, src, bsize_w * 4);
438
                            src -= l;
439
                            dst -= l;
440
                        }
441
                    } else {
442
                        for (int by = 0; by < bsize_h; by++) {
443
                            memmove(dst, src, bsize_w * 4);
444
                            src += l;
445
                            dst += l;
446
                        }
447
                    }
448
449
                    count--;
450
                }
451
            }
452
            break;
453
        case 12:
454
            osize = ((h + 3) / 4) * ((w + 3) / 4) + 7;
455
            bits = gb->buffer;
456
            di   = 0;
457
            bcode = v14 = 0;
458
            if (bytestream2_get_bytes_left(gb) < osize >> 3)
459
                return AVERROR_INVALIDDATA;
460
            bytestream2_skip(gb, osize >> 3);
461
            for (int x = 0; x < w; x += 4) {
462
                for (int y = 0; y < h; y += 4) {
463
                    int astate = 0;
464
465
                    if (bits[di >> 3] & (1 << (di & 7))) {
466
                        int codes = bytestream2_get_byte(gb);
467
468
                        for (int count = 0; count < 4; count++) {
469
                            uint32_t *src = (uint32_t *)frame->data[0];
470
                            size_t src_size = l * (h - 1) + (w - 1);
471
                            int nv, v, code = codes & 3;
472
473
                            pos = x;
474
                            dy  = y + count;
475
                            dst = (uint32_t *)frame->data[0] + pos + dy * l;
476
                            if (code & 1)
477
                                bcode = bytestream2_get_byte(gb);
478
                            if (code == 3) {
479
                                for (int j = 0; j < 4; j++) {
480
                                    switch (bcode & 3) {
481
                                    case 0:
482
                                        break;
483
                                    case 1:
484
                                        if (dy < 1 && !pos)
485
                                            return AVERROR_INVALIDDATA;
486
                                        dst[0] = dst[-1];
487
                                        break;
488
                                    case 2:
489
                                        if (dy < 1)
490
                                            return AVERROR_INVALIDDATA;
491
                                        dst[0] = dst[-l];
492
                                        break;
493
                                    case 3:
494
                                        if (astate) {
495
                                            nv = value >> 4;
496
                                        } else {
497
                                            value = bytestream2_get_byte(gb);
498
                                            nv = value & 0xF;
499
                                        }
500
                                        astate ^= 1;
501
                                        dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos +
502
                                                             s->mv1[nv][0], 0, src_size)];
503
                                        break;
504
                                    }
505
506
                                    bcode >>= 2;
507
                                    dst++;
508
                                    pos++;
509
                                }
510
                            } else if (code) {
511
                                if (code == 1)
512
                                    v14 = bcode;
513
                                else
514
                                    bcode = v14;
515
                                for (int j = 0; j < 4; j++) {
516
                                    switch (bcode & 3) {
517
                                    case 0:
518
                                        break;
519
                                    case 1:
520
                                        if (dy < 1 && !pos)
521
                                            return AVERROR_INVALIDDATA;
522
                                        dst[0] = dst[-1];
523
                                        break;
524
                                    case 2:
525
                                        if (dy < 1)
526
                                            return AVERROR_INVALIDDATA;
527
                                        dst[0] = dst[-l];
528
                                        break;
529
                                    case 3:
530
                                        v = bytestream2_get_byte(gb);
531
                                        if (v < 128) {
532
                                            dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos +
533
                                                                 s->mv0[v][0], 0, src_size)];
534
                                        } else {
535
                                            dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb);
536
                                        }
537
                                        break;
538
                                    }
539
540
                                    bcode >>= 2;
541
                                    dst++;
542
                                    pos++;
543
                                }
544
                            }
545
546
                            codes >>= 2;
547
                        }
548
                    }
549
550
                    di++;
551
                }
552
            }
553
            break;
554
        default:
555
            return AVERROR_INVALIDDATA;
556
        }
557
    }
558
559
    return AVERROR_INVALIDDATA;
560
}
561
562
static int decode_rle(AVCodecContext *avctx, AVFrame *frame)
563
{
564
    ArgoContext *s = avctx->priv_data;
565
    GetByteContext *gb = &s->gb;
566
    const int w = frame->width;
567
    const int h = frame->height;
568
    const int l = frame->linesize[0] / 4;
569
    uint8_t *dst = frame->data[0];
570
    int pos = 0, y = 0;
571
572
    while (bytestream2_get_bytes_left(gb) > 0) {
573
        int count = bytestream2_get_byte(gb);
574
        int pixel = bytestream2_get_byte(gb);
575
576
        if (!count) {
577
            pos += pixel;
578
            while (pos >= w) {
579
                pos -= w;
580
                y++;
581
                if (y >= h)
582
                    return 0;
583
            }
584
        } else {
585
            while (count > 0) {
586
                dst[pos + y * l] = pixel;
587
                count--;
588
                pos++;
589
                if (pos >= w) {
590
                    pos = 0;
591
                    y++;
592
                    if (y >= h)
593
                        return 0;
594
                }
595
            }
596
        }
597
    }
598
599
    return 0;
600
}
601
602
static int decode_frame(AVCodecContext *avctx, void *data,
603
                        int *got_frame, AVPacket *avpkt)
604
{
605
    ArgoContext *s = avctx->priv_data;
606
    GetByteContext *gb = &s->gb;
607
    AVFrame *frame = s->frame;
608
    uint32_t chunk;
609
    int ret;
610
611
    bytestream2_init(gb, avpkt->data, avpkt->size);
612
613
    if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
614
        return ret;
615
616
    chunk = bytestream2_get_be32(gb);
617
    switch (chunk) {
618
    case MKBETAG('P', 'A', 'L', '8'):
619
        for (int y = 0; y < frame->height; y++)
620
            memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp);
621
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
622
            memset(frame->data[1], 0, AVPALETTE_SIZE);
623
        return decode_pal8(avctx, s->pal);
624
    case MKBETAG('M', 'A', 'D', '1'):
625
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
626
            ret = decode_mad1(avctx, frame);
627
        else
628
            ret = decode_mad1_24(avctx, frame);
629
        break;
630
    case MKBETAG('A', 'V', 'C', 'F'):
631
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
632
            s->key = 1;
633
            ret = decode_avcf(avctx, frame);
634
            break;
635
        }
636
    case MKBETAG('A', 'L', 'C', 'D'):
637
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
638
            s->key = 0;
639
            ret = decode_alcd(avctx, frame);
640
            break;
641
        }
642
    case MKBETAG('R', 'L', 'E', 'F'):
643
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
644
            s->key = 1;
645
            ret = decode_rle(avctx, frame);
646
            break;
647
        }
648
    case MKBETAG('R', 'L', 'E', 'D'):
649
        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
650
            s->key = 0;
651
            ret = decode_rle(avctx, frame);
652
            break;
653
        }
654
    default:
655
        av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk);
656
        break;
657
    }
658
659
    if (ret < 0)
660
        return ret;
661
662
    if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
663
        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
664
665
    if ((ret = av_frame_ref(data, s->frame)) < 0)
666
        return ret;
667
668
    frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
669
    frame->key_frame = s->key;
670
    *got_frame = 1;
671
672
    return avpkt->size;
673
}
674
675
static av_cold int decode_init(AVCodecContext *avctx)
676
{
677
    ArgoContext *s = avctx->priv_data;
678
679
    switch (avctx->bits_per_raw_sample) {
680
    case  8: s->bpp = 1;
681
             avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
682
    case 24: s->bpp = 4;
683
             avctx->pix_fmt = AV_PIX_FMT_BGR0; break;
684
    default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_raw_sample);
685
             return AVERROR_PATCHWELCOME;
686
    }
687
688
    s->frame = av_frame_alloc();
689
    if (!s->frame)
690
        return AVERROR(ENOMEM);
691
692
    for (int n = 0, i = -4; i < 4; i++) {
693
        for (int j = -14; j < 2; j++) {
694
            s->mv0[n][0] = j;
695
            s->mv0[n++][1] = i;
696
        }
697
    }
698
699
    for (int n = 0, i = -5; i <= 1; i += 2) {
700
        int j = -5;
701
702
        while (j <= 1) {
703
            s->mv1[n][0] = j;
704
            s->mv1[n++][1] = i;
705
            j += 2;
706
        }
707
    }
708
709
    return 0;
710
}
711
712
static void decode_flush(AVCodecContext *avctx)
713
{
714
    ArgoContext *s = avctx->priv_data;
715
716
    av_frame_unref(s->frame);
717
}
718
719
static av_cold int decode_close(AVCodecContext *avctx)
720
{
721
    ArgoContext *s = avctx->priv_data;
722
723
    av_frame_free(&s->frame);
724
725
    return 0;
726
}
727
728
AVCodec ff_argo_decoder = {
729
    .name           = "argo",
730
    .long_name      = NULL_IF_CONFIG_SMALL("Argonaut Games Video"),
731
    .type           = AVMEDIA_TYPE_VIDEO,
732
    .id             = AV_CODEC_ID_ARGO,
733
    .priv_data_size = sizeof(ArgoContext),
734
    .init           = decode_init,
735
    .decode         = decode_frame,
736
    .flush          = decode_flush,
737
    .close          = decode_close,
738
    .capabilities   = AV_CODEC_CAP_DR1,
739
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
740
};