Coverage Report

Created: 2026-09-14 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/smcenc.c
Line
Count
Source
1
/*
2
 * QuickTime Graphics (SMC) Video Encoder
3
 * Copyright (c) 2021 The FFmpeg project
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
/**
23
 * @file smcenc.c
24
 * QT SMC Video Encoder by Paul B. Mahol
25
 */
26
27
#include "libavutil/common.h"
28
29
#include "avcodec.h"
30
#include "codec_internal.h"
31
#include "encode.h"
32
#include "bytestream.h"
33
34
92.9k
#define CPAIR 2
35
3.57M
#define CQUAD 4
36
10.4M
#define COCTET 8
37
38
93.3M
#define COLORS_PER_TABLE 256
39
40
typedef struct SMCContext {
41
    AVFrame *prev_frame;    // buffer for previous source frame
42
43
    uint8_t mono_value;
44
    int nb_distinct;
45
    int next_nb_distinct;
46
    uint8_t distinct_values[16];
47
    uint8_t next_distinct_values[16];
48
49
    uint8_t color_pairs[COLORS_PER_TABLE][CPAIR];
50
    uint8_t color_quads[COLORS_PER_TABLE][CQUAD];
51
    uint8_t color_octets[COLORS_PER_TABLE][COCTET];
52
53
    int key_frame;
54
} SMCContext;
55
56
6.85M
#define ADVANCE_BLOCK(pixel_ptr, row_ptr, nb_blocks) \
57
6.85M
{ \
58
16.5M
    for (int block = 0; block < nb_blocks && pixel_ptr && row_ptr; block++) { \
59
9.73M
        pixel_ptr += 4; \
60
9.73M
        cur_x += 4; \
61
9.73M
        if (pixel_ptr - row_ptr >= width) \
62
9.73M
        { \
63
1.56M
            row_ptr += stride * 4; \
64
1.56M
            pixel_ptr = row_ptr; \
65
1.56M
            cur_y += 4; \
66
1.56M
            cur_x  = 0; \
67
1.56M
        } \
68
9.73M
    } \
69
6.85M
}
70
71
static int smc_cmp_values(const void *a, const void *b)
72
96.7M
{
73
96.7M
    const uint8_t *aa = a, *bb = b;
74
75
96.7M
    return FFDIFFSIGN(aa[0], bb[0]);
76
96.7M
}
77
78
static int count_distinct_items(const uint8_t *block_values,
79
                                uint8_t *distinct_values,
80
                                int size)
81
4.11M
{
82
4.11M
    int n = 1;
83
84
4.11M
    distinct_values[0] = block_values[0];
85
48.4M
    for (int i = 1; i < size; i++) {
86
44.3M
        if (block_values[i] != block_values[i-1]) {
87
5.26M
            distinct_values[n] = block_values[i];
88
5.26M
            n++;
89
5.26M
        }
90
44.3M
    }
91
92
4.11M
    return n;
93
4.11M
}
94
95
#define CACHE_PAIR(x) \
96
21.2M
    (s->color_pairs[i][0] == distinct_values[x] || \
97
21.2M
     s->color_pairs[i][1] == distinct_values[x])
98
99
#define CACHE_QUAD(x) \
100
140M
    (s->color_quads[i][0] == distinct_values[x] || \
101
48.2M
     s->color_quads[i][1] == distinct_values[x] || \
102
48.2M
     s->color_quads[i][2] == distinct_values[x] || \
103
140M
     s->color_quads[i][3] == distinct_values[x])
104
105
#define CACHE_OCTET(x) \
106
476M
    (s->color_octets[i][0] == distinct_values[x] || \
107
106M
     s->color_octets[i][1] == distinct_values[x] || \
108
106M
     s->color_octets[i][2] == distinct_values[x] || \
109
106M
     s->color_octets[i][3] == distinct_values[x] || \
110
106M
     s->color_octets[i][4] == distinct_values[x] || \
111
106M
     s->color_octets[i][5] == distinct_values[x] || \
112
106M
     s->color_octets[i][6] == distinct_values[x] || \
113
476M
     s->color_octets[i][7] == distinct_values[x])
114
115
static void smc_encode_stream(SMCContext *s, const AVFrame *frame,
116
                              PutByteContext *pb)
117
9.46k
{
118
9.46k
    const uint8_t *src_pixels = (const uint8_t *)frame->data[0];
119
9.46k
    const ptrdiff_t stride = frame->linesize[0];
120
9.46k
    const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0];
121
9.46k
    const ptrdiff_t prev_stride = s->prev_frame->linesize[0];
122
9.46k
    uint8_t *distinct_values = s->distinct_values;
123
9.46k
    const uint8_t *pixel_ptr, *row_ptr;
124
9.46k
    const int height = frame->height;
125
9.46k
    const int width = frame->width;
126
9.46k
    int block_counter = 0;
127
9.46k
    int color_pair_index = 0;
128
9.46k
    int color_quad_index = 0;
129
9.46k
    int color_octet_index = 0;
130
9.46k
    int color_table_index;  /* indexes to color pair, quad, or octet tables */
131
9.46k
    int total_blocks;
132
9.46k
    int cur_y = 0;
133
9.46k
    int cur_x = 0;
134
135
    /* Number of 4x4 blocks in frame. */
136
9.46k
    total_blocks = ((width + 3) / 4) * ((height + 3) / 4);
137
138
9.46k
    pixel_ptr = row_ptr = src_pixels;
139
140
614k
    while (block_counter < total_blocks) {
141
604k
        const uint8_t *xpixel_ptr = pixel_ptr;
142
604k
        const uint8_t *xrow_ptr = row_ptr;
143
604k
        int intra_skip_blocks = 0;
144
604k
        int inter_skip_blocks = 0;
145
604k
        int coded_distinct = 0;
146
604k
        int coded_blocks = 0;
147
604k
        int cache_index;
148
604k
        int distinct = 0;
149
604k
        int blocks = 0;
150
604k
        int frame_y = cur_y;
151
604k
        int frame_x = cur_x;
152
153
748k
        while (prev_pixels && s->key_frame == 0 && block_counter + inter_skip_blocks < total_blocks) {
154
296k
            const int y_size = FFMIN(4, height - cur_y);
155
296k
            const int x_size = FFMIN(4, width  - cur_x);
156
296k
            int compare = 0;
157
158
874k
            for (int y = 0; y < y_size; y++) {
159
731k
                const uint8_t *prev_pixel_ptr = prev_pixels + (y + cur_y) * prev_stride + cur_x;
160
161
731k
                compare |= !!memcmp(prev_pixel_ptr, pixel_ptr + y * stride, x_size);
162
731k
                if (compare)
163
152k
                    break;
164
731k
            }
165
166
296k
            if (compare)
167
152k
                break;
168
169
143k
            inter_skip_blocks++;
170
143k
            if (inter_skip_blocks >= 256)
171
238
                break;
172
173
143k
            ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
174
143k
        }
175
176
604k
        pixel_ptr = xpixel_ptr;
177
604k
        row_ptr = xrow_ptr;
178
604k
        cur_y = frame_y;
179
604k
        cur_x = frame_x;
180
181
3.12M
        while (block_counter > 0 && block_counter + intra_skip_blocks < total_blocks) {
182
3.10M
            const int y_size = FFMIN(4, height - cur_y);
183
3.10M
            const int x_size = FFMIN(4, width  - cur_x);
184
3.10M
            const ptrdiff_t offset = xpixel_ptr - src_pixels;
185
3.10M
            const int sy = offset / stride;
186
3.10M
            const int sx = offset % stride;
187
3.10M
            const int ny = sx < 4 ? FFMAX(sy - 4, 0) : sy;
188
3.10M
            const int nx = sx < 4 ? FFMAX(width - 4 + (width & 3), 0) : sx - 4;
189
3.10M
            const uint8_t *old_pixel_ptr = src_pixels + nx + ny * stride;
190
3.10M
            int compare = 0;
191
192
11.1M
            for (int y = 0; y < y_size; y++) {
193
8.59M
                compare |= !!memcmp(old_pixel_ptr + y * stride, pixel_ptr + y * stride, x_size);
194
8.59M
                if (compare)
195
584k
                    break;
196
8.59M
            }
197
198
3.10M
            if (compare)
199
584k
                break;
200
201
2.52M
            intra_skip_blocks++;
202
2.52M
            if (intra_skip_blocks >= 256)
203
9.52k
                break;
204
205
2.51M
            ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
206
2.51M
        }
207
208
604k
        pixel_ptr = xpixel_ptr;
209
604k
        row_ptr = xrow_ptr;
210
604k
        cur_y = frame_y;
211
604k
        cur_x = frame_x;
212
213
4.13M
        while (block_counter + coded_blocks < total_blocks && coded_blocks < 256) {
214
4.11M
            const int y_size = FFMIN(4, height - cur_y);
215
4.11M
            const int x_size = FFMIN(4, width  - cur_x);
216
4.11M
            const int nb_elements = x_size * y_size;
217
4.11M
            uint8_t block_values[16] = { 0 };
218
17.0M
            for (int y = 0; y < y_size; y++)
219
12.9M
                memcpy(block_values + y * x_size, pixel_ptr + y * stride, x_size);
220
221
4.11M
            qsort(block_values, nb_elements, sizeof(block_values[0]), smc_cmp_values);
222
4.11M
            s->next_nb_distinct = count_distinct_items(block_values, s->next_distinct_values, nb_elements);
223
4.11M
            if (coded_blocks == 0) {
224
604k
                memcpy(distinct_values, s->next_distinct_values, sizeof(s->distinct_values));
225
604k
                s->nb_distinct = s->next_nb_distinct;
226
3.50M
            } else {
227
3.50M
                if (s->next_nb_distinct != s->nb_distinct ||
228
3.18M
                    memcmp(distinct_values, s->next_distinct_values, s->nb_distinct)) {
229
582k
                    break;
230
582k
                }
231
3.50M
            }
232
3.52M
            s->mono_value = block_values[0];
233
234
3.52M
            coded_distinct = s->nb_distinct;
235
3.52M
            coded_blocks++;
236
3.52M
            if (coded_distinct > 1 && coded_blocks >= 16)
237
3.35k
                break;
238
239
3.52M
            ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
240
3.52M
        }
241
242
604k
        pixel_ptr = xpixel_ptr;
243
604k
        row_ptr = xrow_ptr;
244
604k
        cur_y = frame_y;
245
604k
        cur_x = frame_x;
246
247
604k
        blocks = coded_distinct <= 8 ? coded_blocks : 0;
248
604k
        distinct = coded_distinct;
249
250
604k
        if (intra_skip_blocks >= blocks && intra_skip_blocks >= inter_skip_blocks) {
251
107k
            distinct = 17;
252
107k
            blocks = intra_skip_blocks;
253
107k
        }
254
255
604k
        if (intra_skip_blocks > 16 && intra_skip_blocks >= inter_skip_blocks &&
256
10.6k
            intra_skip_blocks >= blocks) {
257
10.6k
            distinct = 18;
258
10.6k
            blocks = intra_skip_blocks;
259
10.6k
        }
260
261
604k
        if (inter_skip_blocks >= blocks && inter_skip_blocks > intra_skip_blocks) {
262
4.68k
            distinct = 19;
263
4.68k
            blocks = inter_skip_blocks;
264
4.68k
        }
265
266
604k
        if (inter_skip_blocks > 16 && inter_skip_blocks > intra_skip_blocks &&
267
1.20k
            inter_skip_blocks >= blocks) {
268
904
            distinct = 20;
269
904
            blocks = inter_skip_blocks;
270
904
        }
271
272
604k
        if (blocks == 0) {
273
93.6k
            blocks = coded_blocks;
274
93.6k
            distinct = coded_distinct;
275
93.6k
        }
276
277
604k
        switch (distinct) {
278
24.3k
        case 1:
279
24.3k
            if (blocks <= 16) {
280
20.3k
                bytestream2_put_byte(pb, 0x60 | (blocks - 1));
281
20.3k
            } else {
282
3.95k
                bytestream2_put_byte(pb, 0x70);
283
3.95k
                bytestream2_put_byte(pb, blocks - 1);
284
3.95k
            }
285
24.3k
            bytestream2_put_byte(pb, s->mono_value);
286
24.3k
            ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
287
24.3k
            break;
288
73.9k
        case 2:
289
73.9k
            cache_index = -1;
290
9.09M
            for (int i = 0; i < COLORS_PER_TABLE; i++) {
291
9.06M
                if (CACHE_PAIR(0) &&
292
3.09M
                    CACHE_PAIR(1)) {
293
42.9k
                    cache_index = i;
294
42.9k
                    break;
295
42.9k
                }
296
9.06M
            }
297
298
73.9k
            if (cache_index >= 0) {
299
42.9k
                bytestream2_put_byte(pb, 0x90 | (blocks - 1));
300
42.9k
                bytestream2_put_byte(pb, cache_index);
301
42.9k
                color_table_index = cache_index;
302
42.9k
            } else {
303
30.9k
                bytestream2_put_byte(pb, 0x80 | (blocks - 1));
304
305
30.9k
                color_table_index = color_pair_index;
306
92.9k
                for (int i = 0; i < CPAIR; i++) {
307
61.9k
                    s->color_pairs[color_table_index][i] = distinct_values[i];
308
61.9k
                    bytestream2_put_byte(pb, distinct_values[i]);
309
61.9k
                }
310
311
30.9k
                color_pair_index++;
312
30.9k
                if (color_pair_index == COLORS_PER_TABLE)
313
67
                    color_pair_index = 0;
314
30.9k
            }
315
316
200k
            for (int i = 0; i < blocks; i++) {
317
126k
                const int y_size = FFMIN(4, height - cur_y);
318
126k
                const int x_size = FFMIN(4, width  - cur_x);
319
126k
                uint8_t value = s->color_pairs[color_table_index][1];
320
126k
                uint16_t flags = 0;
321
126k
                int shift = 15;
322
323
486k
                for (int y = 0; y < y_size; y++) {
324
1.75M
                    for (int x = 0; x < x_size; x++) {
325
1.39M
                        flags |= (value == pixel_ptr[x + y * stride]) << shift;
326
1.39M
                        shift--;
327
1.39M
                    }
328
359k
                    shift -= 4 - x_size;
329
359k
                }
330
331
126k
                bytestream2_put_be16(pb, flags);
332
333
126k
                ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
334
126k
            }
335
73.9k
            break;
336
60.4k
        case 3:
337
165k
        case 4:
338
165k
            cache_index = -1;
339
30.8M
            for (int i = 0; i < COLORS_PER_TABLE; i++) {
340
30.7M
                if (CACHE_QUAD(0) &&
341
15.3M
                    CACHE_QUAD(1) &&
342
1.52M
                    CACHE_QUAD(2) &&
343
646k
                    CACHE_QUAD(3)) {
344
65.4k
                    cache_index = i;
345
65.4k
                    break;
346
65.4k
                }
347
30.7M
            }
348
349
165k
            if (cache_index >= 0) {
350
65.4k
                bytestream2_put_byte(pb, 0xB0 | (blocks - 1));
351
65.4k
                bytestream2_put_byte(pb, cache_index);
352
65.4k
                color_table_index = cache_index;
353
99.7k
            } else {
354
99.7k
                bytestream2_put_byte(pb, 0xA0 | (blocks - 1));
355
356
99.7k
                color_table_index = color_quad_index;
357
498k
                for (int i = 0; i < CQUAD; i++) {
358
398k
                    s->color_quads[color_table_index][i] = distinct_values[i];
359
398k
                    bytestream2_put_byte(pb, distinct_values[i]);
360
398k
                }
361
362
99.7k
                color_quad_index++;
363
99.7k
                if (color_quad_index == COLORS_PER_TABLE)
364
208
                    color_quad_index = 0;
365
99.7k
            }
366
367
342k
            for (int i = 0; i < blocks; i++) {
368
177k
                const int y_size = FFMIN(4, height - cur_y);
369
177k
                const int x_size = FFMIN(4, width  - cur_x);
370
177k
                uint32_t flags = 0;
371
177k
                uint8_t quad[4];
372
177k
                int shift = 30;
373
374
887k
                for (int k = 0; k < 4; k++)
375
709k
                    quad[k] = s->color_quads[color_table_index][k];
376
377
621k
                for (int y = 0; y < y_size; y++) {
378
2.10M
                    for (int x = 0; x < x_size; x++) {
379
1.66M
                        int pixel = pixel_ptr[x + y * stride];
380
1.66M
                        uint32_t idx = 0;
381
382
3.07M
                        for (int w = 0; w < CQUAD; w++) {
383
3.07M
                            if (quad[w] == pixel) {
384
1.66M
                                idx = w;
385
1.66M
                                break;
386
1.66M
                            }
387
3.07M
                        }
388
389
1.66M
                        flags |= idx << shift;
390
1.66M
                        shift -= 2;
391
1.66M
                    }
392
393
443k
                    shift -= 2 * (4 - x_size);
394
443k
                }
395
396
177k
                bytestream2_put_be32(pb, flags);
397
398
177k
                ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
399
177k
            }
400
165k
            break;
401
126k
        case 5:
402
163k
        case 6:
403
194k
        case 7:
404
228k
        case 8:
405
228k
            cache_index = -1;
406
53.0M
            for (int i = 0; i < COLORS_PER_TABLE; i++) {
407
52.8M
                if (CACHE_OCTET(0) &&
408
46.8M
                    CACHE_OCTET(1) &&
409
4.43M
                    CACHE_OCTET(2) &&
410
1.32M
                    CACHE_OCTET(3) &&
411
573k
                    CACHE_OCTET(4) &&
412
266k
                    CACHE_OCTET(5) &&
413
140k
                    CACHE_OCTET(6) &&
414
78.9k
                    CACHE_OCTET(7)) {
415
33.8k
                    cache_index = i;
416
33.8k
                    break;
417
33.8k
                }
418
52.8M
            }
419
420
228k
            if (cache_index >= 0) {
421
33.8k
                bytestream2_put_byte(pb, 0xD0 | (blocks - 1));
422
33.8k
                bytestream2_put_byte(pb, cache_index);
423
33.8k
                color_table_index = cache_index;
424
194k
            } else {
425
194k
                bytestream2_put_byte(pb, 0xC0 | (blocks - 1));
426
427
194k
                color_table_index = color_octet_index;
428
1.75M
                for (int i = 0; i < COCTET; i++) {
429
1.55M
                    s->color_octets[color_table_index][i] = distinct_values[i];
430
1.55M
                    bytestream2_put_byte(pb, distinct_values[i]);
431
1.55M
                }
432
433
194k
                color_octet_index++;
434
194k
                if (color_octet_index == COLORS_PER_TABLE)
435
580
                    color_octet_index = 0;
436
194k
            }
437
438
459k
            for (int i = 0; i < blocks; i++) {
439
231k
                const int y_size = FFMIN(4, height - cur_y);
440
231k
                const int x_size = FFMIN(4, width  - cur_x);
441
231k
                uint64_t flags = 0;
442
231k
                uint8_t octet[8];
443
231k
                int shift = 45;
444
445
2.07M
                for (int k = 0; k < 8; k++)
446
1.84M
                    octet[k] = s->color_octets[color_table_index][k];
447
448
1.05M
                for (int y = 0; y < y_size; y++) {
449
4.10M
                    for (int x = 0; x < x_size; x++) {
450
3.28M
                        int pixel = pixel_ptr[x + y * stride];
451
3.28M
                        uint64_t idx = 0;
452
453
8.74M
                        for (int w = 0; w < COCTET; w++) {
454
8.74M
                            if (octet[w] == pixel) {
455
3.28M
                                idx = w;
456
3.28M
                                break;
457
3.28M
                            }
458
8.74M
                        }
459
460
3.28M
                        flags |= idx << shift;
461
3.28M
                        shift -= 3;
462
3.28M
                    }
463
464
822k
                    shift -= 3 * (4 - x_size);
465
822k
                }
466
467
231k
                bytestream2_put_be16(pb, ((flags >> 32) & 0xFFF0) | ((flags >> 8) & 0xF));
468
231k
                bytestream2_put_be16(pb, ((flags >> 20) & 0xFFF0) | ((flags >> 4) & 0xF));
469
231k
                bytestream2_put_be16(pb, ((flags >>  8) & 0xFFF0) | ((flags >> 0) & 0xF));
470
471
231k
                ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
472
231k
            }
473
228k
            break;
474
93.6k
        default:
475
93.6k
            bytestream2_put_byte(pb, 0xE0 | (blocks - 1));
476
188k
            for (int i = 0; i < blocks; i++) {
477
94.5k
                const int y_size = FFMIN(4, height - cur_y);
478
94.5k
                const int x_size = FFMIN(4, width  - cur_x);
479
462k
                for (int y = 0; y < y_size; y++) {
480
1.83M
                    for (int x = 0; x < x_size; x++)
481
1.46M
                        bytestream2_put_byte(pb, pixel_ptr[x + y * stride]);
482
370k
                    for (int x = x_size; x < 4; x++)
483
2.96k
                        bytestream2_put_byte(pb, 0);
484
367k
                }
485
486
104k
                for (int y = y_size; y < 4; y++) {
487
51.7k
                    for (int x = 0; x < 4; x++)
488
41.4k
                        bytestream2_put_byte(pb, 0);
489
10.3k
                }
490
491
94.5k
                ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
492
94.5k
            }
493
93.6k
            break;
494
3.50k
        case 17:
495
3.50k
            bytestream2_put_byte(pb, 0x20 | (blocks - 1));
496
3.50k
            ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
497
3.50k
            break;
498
10.6k
        case 18:
499
10.6k
            bytestream2_put_byte(pb, 0x30);
500
10.6k
            bytestream2_put_byte(pb, blocks - 1);
501
10.6k
            ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
502
10.6k
            break;
503
3.78k
        case 19:
504
3.78k
            bytestream2_put_byte(pb, 0x00 | (blocks - 1));
505
3.78k
            ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
506
3.78k
            break;
507
904
        case 20:
508
904
            bytestream2_put_byte(pb, 0x10);
509
904
            bytestream2_put_byte(pb, blocks - 1);
510
904
            ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
511
904
            break;
512
604k
        }
513
514
604k
        block_counter += blocks;
515
604k
    }
516
9.46k
}
517
518
static av_cold int smc_encode_init(AVCodecContext *avctx)
519
867
{
520
867
    SMCContext *s = avctx->priv_data;
521
522
867
    avctx->bits_per_coded_sample = 8;
523
524
867
    s->prev_frame = av_frame_alloc();
525
867
    if (!s->prev_frame)
526
0
        return AVERROR(ENOMEM);
527
528
867
    return 0;
529
867
}
530
531
static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
532
                                const AVFrame *frame, int *got_packet)
533
9.46k
{
534
9.46k
    SMCContext *s = avctx->priv_data;
535
9.46k
    const AVFrame *pict = frame;
536
9.46k
    PutByteContext pb;
537
9.46k
    uint8_t *pal;
538
9.46k
    int ret;
539
540
9.46k
    ret = ff_alloc_packet(avctx, pkt, 8LL * avctx->height * avctx->width);
541
9.46k
    if (ret < 0)
542
0
        return ret;
543
544
9.46k
    if (avctx->gop_size == 0 || !s->prev_frame->data[0] ||
545
8.38k
        (avctx->frame_num % avctx->gop_size) == 0) {
546
1.40k
        s->key_frame = 1;
547
8.06k
    } else {
548
8.06k
        s->key_frame = 0;
549
8.06k
    }
550
551
9.46k
    bytestream2_init_writer(&pb, pkt->data, pkt->size);
552
553
9.46k
    bytestream2_put_be32(&pb, 0x00);
554
555
9.46k
    pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
556
9.46k
    if (!pal)
557
0
        return AVERROR(ENOMEM);
558
9.46k
    memcpy(pal, frame->data[1], AVPALETTE_SIZE);
559
560
9.46k
    smc_encode_stream(s, pict, &pb);
561
562
9.46k
    av_shrink_packet(pkt, bytestream2_tell_p(&pb));
563
564
9.46k
    pkt->data[0] = 0x0;
565
566
    // write chunk length
567
9.46k
    AV_WB24(pkt->data + 1, pkt->size);
568
569
9.46k
    ret = av_frame_replace(s->prev_frame, frame);
570
9.46k
    if (ret < 0) {
571
0
        av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
572
0
        return ret;
573
0
    }
574
575
9.46k
    if (s->key_frame)
576
1.40k
        pkt->flags |= AV_PKT_FLAG_KEY;
577
578
9.46k
    *got_packet = 1;
579
580
9.46k
    return 0;
581
9.46k
}
582
583
static av_cold int smc_encode_end(AVCodecContext *avctx)
584
867
{
585
867
    SMCContext *s = avctx->priv_data;
586
587
867
    av_frame_free(&s->prev_frame);
588
589
867
    return 0;
590
867
}
591
592
const FFCodec ff_smc_encoder = {
593
    .p.name         = "smc",
594
    CODEC_LONG_NAME("QuickTime Graphics (SMC)"),
595
    .p.type         = AVMEDIA_TYPE_VIDEO,
596
    .p.id           = AV_CODEC_ID_SMC,
597
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
598
    .priv_data_size = sizeof(SMCContext),
599
    .init           = smc_encode_init,
600
    FF_CODEC_ENCODE_CB(smc_encode_frame),
601
    .close          = smc_encode_end,
602
    CODEC_PIXFMTS(AV_PIX_FMT_PAL8),
603
};