FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/smcenc.c
Date: 2024-04-19 07:31:02
Exec Total Coverage
Lines: 310 328 94.5%
Functions: 6 6 100.0%
Branches: 375 433 86.6%

Line Branch Exec 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 #define CPAIR 2
35 #define CQUAD 4
36 #define COCTET 8
37
38 #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 #define ADVANCE_BLOCK(pixel_ptr, row_ptr, nb_blocks) \
57 { \
58 for (int block = 0; block < nb_blocks && pixel_ptr && row_ptr; block++) { \
59 pixel_ptr += 4; \
60 cur_x += 4; \
61 if (pixel_ptr - row_ptr >= width) \
62 { \
63 row_ptr += stride * 4; \
64 pixel_ptr = row_ptr; \
65 cur_y += 4; \
66 cur_x = 0; \
67 } \
68 } \
69 }
70
71 81354609 static int smc_cmp_values(const void *a, const void *b)
72 {
73 81354609 const uint8_t *aa = a, *bb = b;
74
75 81354609 return FFDIFFSIGN(aa[0], bb[0]);
76 }
77
78 1841851 static int count_distinct_items(const uint8_t *block_values,
79 uint8_t *distinct_values,
80 int size)
81 {
82 1841851 int n = 1;
83
84 1841851 distinct_values[0] = block_values[0];
85
2/2
✓ Branch 0 taken 27613773 times.
✓ Branch 1 taken 1841851 times.
29455624 for (int i = 1; i < size; i++) {
86
2/2
✓ Branch 0 taken 10525322 times.
✓ Branch 1 taken 17088451 times.
27613773 if (block_values[i] != block_values[i-1]) {
87 10525322 distinct_values[n] = block_values[i];
88 10525322 n++;
89 }
90 }
91
92 1841851 return n;
93 }
94
95 #define CACHE_PAIR(x) \
96 (s->color_pairs[i][0] == distinct_values[x] || \
97 s->color_pairs[i][1] == distinct_values[x])
98
99 #define CACHE_QUAD(x) \
100 (s->color_quads[i][0] == distinct_values[x] || \
101 s->color_quads[i][1] == distinct_values[x] || \
102 s->color_quads[i][2] == distinct_values[x] || \
103 s->color_quads[i][3] == distinct_values[x])
104
105 #define CACHE_OCTET(x) \
106 (s->color_octets[i][0] == distinct_values[x] || \
107 s->color_octets[i][1] == distinct_values[x] || \
108 s->color_octets[i][2] == distinct_values[x] || \
109 s->color_octets[i][3] == distinct_values[x] || \
110 s->color_octets[i][4] == distinct_values[x] || \
111 s->color_octets[i][5] == distinct_values[x] || \
112 s->color_octets[i][6] == distinct_values[x] || \
113 s->color_octets[i][7] == distinct_values[x])
114
115 200 static void smc_encode_stream(SMCContext *s, const AVFrame *frame,
116 PutByteContext *pb)
117 {
118 200 const uint8_t *src_pixels = (const uint8_t *)frame->data[0];
119 200 const ptrdiff_t stride = frame->linesize[0];
120 200 const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0];
121 200 const ptrdiff_t prev_stride = s->prev_frame->linesize[0];
122 200 uint8_t *distinct_values = s->distinct_values;
123 const uint8_t *pixel_ptr, *row_ptr;
124 200 const int height = frame->height;
125 200 const int width = frame->width;
126 200 int block_counter = 0;
127 200 int color_pair_index = 0;
128 200 int color_quad_index = 0;
129 200 int color_octet_index = 0;
130 int color_table_index; /* indexes to color pair, quad, or octet tables */
131 int total_blocks;
132 200 int cur_y = 0;
133 200 int cur_x = 0;
134
135 /* Number of 4x4 blocks in frame. */
136 200 total_blocks = ((width + 3) / 4) * ((height + 3) / 4);
137
138 200 pixel_ptr = row_ptr = src_pixels;
139
140
2/2
✓ Branch 0 taken 889064 times.
✓ Branch 1 taken 200 times.
889264 while (block_counter < total_blocks) {
141 889064 const uint8_t *xpixel_ptr = pixel_ptr;
142 889064 const uint8_t *xrow_ptr = row_ptr;
143 889064 int intra_skip_blocks = 0;
144 889064 int inter_skip_blocks = 0;
145 889064 int coded_distinct = 0;
146 889064 int coded_blocks = 0;
147 int cache_index;
148 889064 int distinct = 0;
149 889064 int blocks = 0;
150 889064 int frame_y = cur_y;
151 889064 int frame_x = cur_x;
152
153
5/6
✓ Branch 0 taken 886487 times.
✓ Branch 1 taken 17353 times.
✓ Branch 2 taken 814927 times.
✓ Branch 3 taken 71560 times.
✓ Branch 4 taken 814927 times.
✗ Branch 5 not taken.
903840 while (prev_pixels && s->key_frame == 0 && block_counter + inter_skip_blocks < total_blocks) {
154 814927 const int y_size = FFMIN(4, height - cur_y);
155 814927 const int x_size = FFMIN(4, width - cur_x);
156 814927 int compare = 0;
157
158
2/2
✓ Branch 0 taken 997456 times.
✓ Branch 1 taken 14776 times.
1012232 for (int y = 0; y < y_size; y++) {
159 997456 const uint8_t *prev_pixel_ptr = prev_pixels + (y + cur_y) * prev_stride + cur_x;
160
161 997456 compare |= !!memcmp(prev_pixel_ptr, pixel_ptr + y * stride, x_size);
162
2/2
✓ Branch 0 taken 800151 times.
✓ Branch 1 taken 197305 times.
997456 if (compare)
163 800151 break;
164 }
165
166
2/2
✓ Branch 0 taken 800151 times.
✓ Branch 1 taken 14776 times.
814927 if (compare)
167 800151 break;
168
169 14776 inter_skip_blocks++;
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14776 times.
14776 if (inter_skip_blocks >= 256)
171 break;
172
173
6/8
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 14749 times.
✓ Branch 2 taken 14776 times.
✓ Branch 3 taken 14776 times.
✓ Branch 4 taken 14776 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14776 times.
✗ Branch 7 not taken.
29552 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
174 }
175
176 889064 pixel_ptr = xpixel_ptr;
177 889064 row_ptr = xrow_ptr;
178 889064 cur_y = frame_y;
179 889064 cur_x = frame_x;
180
181
3/4
✓ Branch 0 taken 888936 times.
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 888936 times.
✗ Branch 3 not taken.
889136 while (block_counter > 0 && block_counter + intra_skip_blocks < total_blocks) {
182 888936 const int y_size = FFMIN(4, height - cur_y);
183 888936 const int x_size = FFMIN(4, width - cur_x);
184 888936 const ptrdiff_t offset = xpixel_ptr - src_pixels;
185 888936 const int sy = offset / stride;
186 888936 const int sx = offset % stride;
187
2/2
✓ Branch 0 taken 11034 times.
✓ Branch 1 taken 877902 times.
888936 const int ny = sx < 4 ? sy - 4 : sy;
188
2/2
✓ Branch 0 taken 11034 times.
✓ Branch 1 taken 877902 times.
888936 const int nx = sx < 4 ? width - 4 + (width & 3) : sx - 4;
189 888936 const uint8_t *old_pixel_ptr = src_pixels + nx + ny * stride;
190 888936 int compare = 0;
191
192
2/2
✓ Branch 0 taken 951899 times.
✓ Branch 1 taken 72 times.
951971 for (int y = 0; y < y_size; y++) {
193 951899 compare |= !!memcmp(old_pixel_ptr + y * stride, pixel_ptr + y * stride, x_size);
194
2/2
✓ Branch 0 taken 888864 times.
✓ Branch 1 taken 63035 times.
951899 if (compare)
195 888864 break;
196 }
197
198
2/2
✓ Branch 0 taken 888864 times.
✓ Branch 1 taken 72 times.
888936 if (compare)
199 888864 break;
200
201 72 intra_skip_blocks++;
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (intra_skip_blocks >= 256)
203 break;
204
205
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 72 times.
✗ Branch 7 not taken.
144 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
206 }
207
208 889064 pixel_ptr = xpixel_ptr;
209 889064 row_ptr = xrow_ptr;
210 889064 cur_y = frame_y;
211 889064 cur_x = frame_x;
212
213
3/4
✓ Branch 0 taken 1841851 times.
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 1841851 times.
✗ Branch 3 not taken.
1842051 while (block_counter + coded_blocks < total_blocks && coded_blocks < 256) {
214 1841851 const int y_size = FFMIN(4, height - cur_y);
215 1841851 const int x_size = FFMIN(4, width - cur_x);
216 1841851 const int nb_elements = x_size * y_size;
217 1841851 uint8_t block_values[16] = { 0 };
218
2/2
✓ Branch 0 taken 7365604 times.
✓ Branch 1 taken 1841851 times.
9207455 for (int y = 0; y < y_size; y++)
219 7365604 memcpy(block_values + y * x_size, pixel_ptr + y * stride, x_size);
220
221 1841851 qsort(block_values, nb_elements, sizeof(block_values[0]), smc_cmp_values);
222 1841851 s->next_nb_distinct = count_distinct_items(block_values, s->next_distinct_values, nb_elements);
223
2/2
✓ Branch 0 taken 889064 times.
✓ Branch 1 taken 952787 times.
1841851 if (coded_blocks == 0) {
224 889064 memcpy(distinct_values, s->next_distinct_values, sizeof(s->distinct_values));
225 889064 s->nb_distinct = s->next_nb_distinct;
226 } else {
227
2/2
✓ Branch 0 taken 215197 times.
✓ Branch 1 taken 737590 times.
952787 if (s->next_nb_distinct != s->nb_distinct ||
228
2/2
✓ Branch 0 taken 63942 times.
✓ Branch 1 taken 151255 times.
215197 memcmp(distinct_values, s->next_distinct_values, s->nb_distinct)) {
229 break;
230 }
231 }
232 953006 s->mono_value = block_values[0];
233
234 953006 coded_distinct = s->nb_distinct;
235 953006 coded_blocks++;
236
4/4
✓ Branch 0 taken 950474 times.
✓ Branch 1 taken 2532 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 950455 times.
953006 if (coded_distinct > 1 && coded_blocks >= 16)
237 19 break;
238
239
6/8
✓ Branch 0 taken 11246 times.
✓ Branch 1 taken 941741 times.
✓ Branch 2 taken 952987 times.
✓ Branch 3 taken 952987 times.
✓ Branch 4 taken 952987 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 952987 times.
✗ Branch 7 not taken.
1905974 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
240 }
241
242 889064 pixel_ptr = xpixel_ptr;
243 889064 row_ptr = xrow_ptr;
244 889064 cur_y = frame_y;
245 889064 cur_x = frame_x;
246
247
2/2
✓ Branch 0 taken 682023 times.
✓ Branch 1 taken 207041 times.
889064 blocks = coded_distinct <= 8 ? coded_blocks : 0;
248 889064 distinct = coded_distinct;
249
250
4/4
✓ Branch 0 taken 207083 times.
✓ Branch 1 taken 681981 times.
✓ Branch 2 taken 207015 times.
✓ Branch 3 taken 68 times.
889064 if (intra_skip_blocks >= blocks && intra_skip_blocks >= inter_skip_blocks) {
251 207015 distinct = 17;
252 207015 blocks = intra_skip_blocks;
253 }
254
255
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 889064 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
889064 if (intra_skip_blocks > 16 && intra_skip_blocks >= inter_skip_blocks &&
256 intra_skip_blocks >= blocks) {
257 distinct = 18;
258 blocks = intra_skip_blocks;
259 }
260
261
4/4
✓ Branch 0 taken 215350 times.
✓ Branch 1 taken 673714 times.
✓ Branch 2 taken 8377 times.
✓ Branch 3 taken 206973 times.
889064 if (inter_skip_blocks >= blocks && inter_skip_blocks > intra_skip_blocks) {
262 8377 distinct = 19;
263 8377 blocks = inter_skip_blocks;
264 }
265
266
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 889060 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
889064 if (inter_skip_blocks > 16 && inter_skip_blocks > intra_skip_blocks &&
267 inter_skip_blocks >= blocks) {
268 2 distinct = 20;
269 2 blocks = inter_skip_blocks;
270 }
271
272
2/2
✓ Branch 0 taken 206973 times.
✓ Branch 1 taken 682091 times.
889064 if (blocks == 0) {
273 206973 blocks = coded_blocks;
274 206973 distinct = coded_distinct;
275 }
276
277
8/9
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 9960 times.
✓ Branch 2 taken 150047 times.
✓ Branch 3 taken 513154 times.
✓ Branch 4 taken 206973 times.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8375 times.
✓ Branch 8 taken 2 times.
889064 switch (distinct) {
278 511 case 1:
279
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 11 times.
511 if (blocks <= 16) {
280 500 bytestream2_put_byte(pb, 0x60 | (blocks - 1));
281 } else {
282 11 bytestream2_put_byte(pb, 0x70);
283 11 bytestream2_put_byte(pb, blocks - 1);
284 }
285 511 bytestream2_put_byte(pb, s->mono_value);
286
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1363 times.
✓ Branch 2 taken 1364 times.
✓ Branch 3 taken 511 times.
✓ Branch 4 taken 1364 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1364 times.
✗ Branch 7 not taken.
1875 ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
287 511 break;
288 9960 case 2:
289 9960 cache_index = -1;
290
2/2
✓ Branch 0 taken 345512 times.
✓ Branch 1 taken 839 times.
346351 for (int i = 0; i < COLORS_PER_TABLE; i++) {
291
4/4
✓ Branch 0 taken 298176 times.
✓ Branch 1 taken 47336 times.
✓ Branch 2 taken 2329 times.
✓ Branch 3 taken 295847 times.
345512 if (CACHE_PAIR(0) &&
292
3/4
✓ Branch 0 taken 49665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9121 times.
✓ Branch 3 taken 40544 times.
49665 CACHE_PAIR(1)) {
293 9121 cache_index = i;
294 9121 break;
295 }
296 }
297
298
2/2
✓ Branch 0 taken 9121 times.
✓ Branch 1 taken 839 times.
9960 if (cache_index >= 0) {
299 9121 bytestream2_put_byte(pb, 0x90 | (blocks - 1));
300 9121 bytestream2_put_byte(pb, cache_index);
301 9121 color_table_index = cache_index;
302 } else {
303 839 bytestream2_put_byte(pb, 0x80 | (blocks - 1));
304
305 839 color_table_index = color_pair_index;
306
2/2
✓ Branch 0 taken 1678 times.
✓ Branch 1 taken 839 times.
2517 for (int i = 0; i < CPAIR; i++) {
307 1678 s->color_pairs[color_table_index][i] = distinct_values[i];
308 1678 bytestream2_put_byte(pb, distinct_values[i]);
309 }
310
311 839 color_pair_index++;
312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 839 times.
839 if (color_pair_index == COLORS_PER_TABLE)
313 color_pair_index = 0;
314 }
315
316
2/2
✓ Branch 0 taken 16882 times.
✓ Branch 1 taken 9960 times.
26842 for (int i = 0; i < blocks; i++) {
317 16882 const int y_size = FFMIN(4, height - cur_y);
318 16882 const int x_size = FFMIN(4, width - cur_x);
319 16882 uint8_t value = s->color_pairs[color_table_index][1];
320 16882 uint16_t flags = 0;
321 16882 int shift = 15;
322
323
2/2
✓ Branch 0 taken 67526 times.
✓ Branch 1 taken 16882 times.
84408 for (int y = 0; y < y_size; y++) {
324
2/2
✓ Branch 0 taken 270060 times.
✓ Branch 1 taken 67526 times.
337586 for (int x = 0; x < x_size; x++) {
325 270060 flags |= (value == pixel_ptr[x + y * stride]) << shift;
326 270060 shift--;
327 }
328 67526 shift -= 4 - x_size;
329 }
330
331 16882 bytestream2_put_be16(pb, flags);
332
333
6/8
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 16747 times.
✓ Branch 2 taken 16882 times.
✓ Branch 3 taken 16882 times.
✓ Branch 4 taken 16882 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16882 times.
✗ Branch 7 not taken.
33764 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
334 }
335 9960 break;
336 150047 case 3:
337 case 4:
338 150047 cache_index = -1;
339
2/2
✓ Branch 0 taken 18552849 times.
✓ Branch 1 taken 27203 times.
18580052 for (int i = 0; i < COLORS_PER_TABLE; i++) {
340
8/8
✓ Branch 0 taken 17629383 times.
✓ Branch 1 taken 923466 times.
✓ Branch 2 taken 16977560 times.
✓ Branch 3 taken 651823 times.
✓ Branch 4 taken 16495647 times.
✓ Branch 5 taken 481913 times.
✓ Branch 6 taken 355550 times.
✓ Branch 7 taken 16140097 times.
18552849 if (CACHE_QUAD(0) &&
341
8/8
✓ Branch 0 taken 2405754 times.
✓ Branch 1 taken 6998 times.
✓ Branch 2 taken 2033720 times.
✓ Branch 3 taken 372034 times.
✓ Branch 4 taken 1716388 times.
✓ Branch 5 taken 317332 times.
✓ Branch 6 taken 161448 times.
✓ Branch 7 taken 1554940 times.
2412752 CACHE_QUAD(1) &&
342
7/8
✓ Branch 0 taken 857812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 853861 times.
✓ Branch 3 taken 3951 times.
✓ Branch 4 taken 623855 times.
✓ Branch 5 taken 230006 times.
✓ Branch 6 taken 133747 times.
✓ Branch 7 taken 490108 times.
857812 CACHE_QUAD(2) &&
343
8/8
✓ Branch 0 taken 364623 times.
✓ Branch 1 taken 3081 times.
✓ Branch 2 taken 359819 times.
✓ Branch 3 taken 4804 times.
✓ Branch 4 taken 343034 times.
✓ Branch 5 taken 16785 times.
✓ Branch 6 taken 98174 times.
✓ Branch 7 taken 244860 times.
367704 CACHE_QUAD(3)) {
344 122844 cache_index = i;
345 122844 break;
346 }
347 }
348
349
2/2
✓ Branch 0 taken 122844 times.
✓ Branch 1 taken 27203 times.
150047 if (cache_index >= 0) {
350 122844 bytestream2_put_byte(pb, 0xB0 | (blocks - 1));
351 122844 bytestream2_put_byte(pb, cache_index);
352 122844 color_table_index = cache_index;
353 } else {
354 27203 bytestream2_put_byte(pb, 0xA0 | (blocks - 1));
355
356 27203 color_table_index = color_quad_index;
357
2/2
✓ Branch 0 taken 108812 times.
✓ Branch 1 taken 27203 times.
136015 for (int i = 0; i < CQUAD; i++) {
358 108812 s->color_quads[color_table_index][i] = distinct_values[i];
359 108812 bytestream2_put_byte(pb, distinct_values[i]);
360 }
361
362 27203 color_quad_index++;
363
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 27154 times.
27203 if (color_quad_index == COLORS_PER_TABLE)
364 49 color_quad_index = 0;
365 }
366
367
2/2
✓ Branch 0 taken 191380 times.
✓ Branch 1 taken 150047 times.
341427 for (int i = 0; i < blocks; i++) {
368 191380 const int y_size = FFMIN(4, height - cur_y);
369 191380 const int x_size = FFMIN(4, width - cur_x);
370 191380 uint32_t flags = 0;
371 uint8_t quad[4];
372 191380 int shift = 30;
373
374
2/2
✓ Branch 0 taken 765520 times.
✓ Branch 1 taken 191380 times.
956900 for (int k = 0; k < 4; k++)
375 765520 quad[k] = s->color_quads[color_table_index][k];
376
377
2/2
✓ Branch 0 taken 765370 times.
✓ Branch 1 taken 191380 times.
956750 for (int y = 0; y < y_size; y++) {
378
2/2
✓ Branch 0 taken 3060500 times.
✓ Branch 1 taken 765370 times.
3825870 for (int x = 0; x < x_size; x++) {
379 3060500 int pixel = pixel_ptr[x + y * stride];
380 3060500 uint32_t idx = 0;
381
382
1/2
✓ Branch 0 taken 7561475 times.
✗ Branch 1 not taken.
7561475 for (int w = 0; w < CQUAD; w++) {
383
2/2
✓ Branch 0 taken 3060500 times.
✓ Branch 1 taken 4500975 times.
7561475 if (quad[w] == pixel) {
384 3060500 idx = w;
385 3060500 break;
386 }
387 }
388
389 3060500 flags |= idx << shift;
390 3060500 shift -= 2;
391 }
392
393 765370 shift -= 2 * (4 - x_size);
394 }
395
396 191380 bytestream2_put_be32(pb, flags);
397
398
6/8
✓ Branch 0 taken 2277 times.
✓ Branch 1 taken 189103 times.
✓ Branch 2 taken 191380 times.
✓ Branch 3 taken 191380 times.
✓ Branch 4 taken 191380 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 191380 times.
✗ Branch 7 not taken.
382760 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
399 }
400 150047 break;
401 513154 case 5:
402 case 6:
403 case 7:
404 case 8:
405 513154 cache_index = -1;
406
2/2
✓ Branch 0 taken 112804394 times.
✓ Branch 1 taken 389757 times.
113194151 for (int i = 0; i < COLORS_PER_TABLE; i++) {
407
16/16
✓ Branch 0 taken 107527819 times.
✓ Branch 1 taken 5276575 times.
✓ Branch 2 taken 104592429 times.
✓ Branch 3 taken 2935390 times.
✓ Branch 4 taken 102287481 times.
✓ Branch 5 taken 2304948 times.
✓ Branch 6 taken 100573539 times.
✓ Branch 7 taken 1713942 times.
✓ Branch 8 taken 99180757 times.
✓ Branch 9 taken 1392782 times.
✓ Branch 10 taken 98049379 times.
✓ Branch 11 taken 1131378 times.
✓ Branch 12 taken 97094574 times.
✓ Branch 13 taken 954805 times.
✓ Branch 14 taken 807117 times.
✓ Branch 15 taken 96287457 times.
112804394 if (CACHE_OCTET(0) &&
408
16/16
✓ Branch 0 taken 16459827 times.
✓ Branch 1 taken 57110 times.
✓ Branch 2 taken 14398018 times.
✓ Branch 3 taken 2061809 times.
✓ Branch 4 taken 12646681 times.
✓ Branch 5 taken 1751337 times.
✓ Branch 6 taken 11302896 times.
✓ Branch 7 taken 1343785 times.
✓ Branch 8 taken 10333897 times.
✓ Branch 9 taken 968999 times.
✓ Branch 10 taken 9703535 times.
✓ Branch 11 taken 630362 times.
✓ Branch 12 taken 9281954 times.
✓ Branch 13 taken 421581 times.
✓ Branch 14 taken 305956 times.
✓ Branch 15 taken 8975998 times.
16516937 CACHE_OCTET(1) &&
409
16/16
✓ Branch 0 taken 7531465 times.
✓ Branch 1 taken 9474 times.
✓ Branch 2 taken 7485772 times.
✓ Branch 3 taken 45693 times.
✓ Branch 4 taken 6207739 times.
✓ Branch 5 taken 1278033 times.
✓ Branch 6 taken 5021646 times.
✓ Branch 7 taken 1186093 times.
✓ Branch 8 taken 4185187 times.
✓ Branch 9 taken 836459 times.
✓ Branch 10 taken 3687627 times.
✓ Branch 11 taken 497560 times.
✓ Branch 12 taken 3403032 times.
✓ Branch 13 taken 284595 times.
✓ Branch 14 taken 159510 times.
✓ Branch 15 taken 3243522 times.
7540939 CACHE_OCTET(2) &&
410
16/16
✓ Branch 0 taken 4296784 times.
✓ Branch 1 taken 633 times.
✓ Branch 2 taken 4291176 times.
✓ Branch 3 taken 5608 times.
✓ Branch 4 taken 4262159 times.
✓ Branch 5 taken 29017 times.
✓ Branch 6 taken 3505056 times.
✓ Branch 7 taken 757103 times.
✓ Branch 8 taken 2749491 times.
✓ Branch 9 taken 755565 times.
✓ Branch 10 taken 2297158 times.
✓ Branch 11 taken 452333 times.
✓ Branch 12 taken 2067134 times.
✓ Branch 13 taken 230024 times.
✓ Branch 14 taken 110566 times.
✓ Branch 15 taken 1956568 times.
4297417 CACHE_OCTET(3) &&
411
15/16
✓ Branch 0 taken 2340849 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2340594 times.
✓ Branch 3 taken 255 times.
✓ Branch 4 taken 2337809 times.
✓ Branch 5 taken 2785 times.
✓ Branch 6 taken 2319162 times.
✓ Branch 7 taken 18647 times.
✓ Branch 8 taken 1858328 times.
✓ Branch 9 taken 460834 times.
✓ Branch 10 taken 1411831 times.
✓ Branch 11 taken 446497 times.
✓ Branch 12 taken 1179148 times.
✓ Branch 13 taken 232683 times.
✓ Branch 14 taken 101691 times.
✓ Branch 15 taken 1077457 times.
2340849 CACHE_OCTET(4) &&
412
16/16
✓ Branch 0 taken 1257025 times.
✓ Branch 1 taken 6367 times.
✓ Branch 2 taken 1247939 times.
✓ Branch 3 taken 9086 times.
✓ Branch 4 taken 1233843 times.
✓ Branch 5 taken 14096 times.
✓ Branch 6 taken 1207748 times.
✓ Branch 7 taken 26095 times.
✓ Branch 8 taken 1143495 times.
✓ Branch 9 taken 64253 times.
✓ Branch 10 taken 884890 times.
✓ Branch 11 taken 258605 times.
✓ Branch 12 taken 719691 times.
✓ Branch 13 taken 165199 times.
✓ Branch 14 taken 81444 times.
✓ Branch 15 taken 638247 times.
1263392 CACHE_OCTET(5) &&
413
16/16
✓ Branch 0 taken 619937 times.
✓ Branch 1 taken 5208 times.
✓ Branch 2 taken 611734 times.
✓ Branch 3 taken 8203 times.
✓ Branch 4 taken 600389 times.
✓ Branch 5 taken 11345 times.
✓ Branch 6 taken 585605 times.
✓ Branch 7 taken 14784 times.
✓ Branch 8 taken 562783 times.
✓ Branch 9 taken 22822 times.
✓ Branch 10 taken 525813 times.
✓ Branch 11 taken 36970 times.
✓ Branch 12 taken 409789 times.
✓ Branch 13 taken 116024 times.
✓ Branch 14 taken 51499 times.
✓ Branch 15 taken 358290 times.
625145 CACHE_OCTET(6) &&
414
16/16
✓ Branch 0 taken 264361 times.
✓ Branch 1 taken 2494 times.
✓ Branch 2 taken 260110 times.
✓ Branch 3 taken 4251 times.
✓ Branch 4 taken 253931 times.
✓ Branch 5 taken 6179 times.
✓ Branch 6 taken 245661 times.
✓ Branch 7 taken 8270 times.
✓ Branch 8 taken 235957 times.
✓ Branch 9 taken 9704 times.
✓ Branch 10 taken 224144 times.
✓ Branch 11 taken 11813 times.
✓ Branch 12 taken 209304 times.
✓ Branch 13 taken 14840 times.
✓ Branch 14 taken 65846 times.
✓ Branch 15 taken 143458 times.
266855 CACHE_OCTET(7)) {
415 123397 cache_index = i;
416 123397 break;
417 }
418 }
419
420
2/2
✓ Branch 0 taken 123397 times.
✓ Branch 1 taken 389757 times.
513154 if (cache_index >= 0) {
421 123397 bytestream2_put_byte(pb, 0xD0 | (blocks - 1));
422 123397 bytestream2_put_byte(pb, cache_index);
423 123397 color_table_index = cache_index;
424 } else {
425 389757 bytestream2_put_byte(pb, 0xC0 | (blocks - 1));
426
427 389757 color_table_index = color_octet_index;
428
2/2
✓ Branch 0 taken 3118056 times.
✓ Branch 1 taken 389757 times.
3507813 for (int i = 0; i < COCTET; i++) {
429 3118056 s->color_octets[color_table_index][i] = distinct_values[i];
430 3118056 bytestream2_put_byte(pb, distinct_values[i]);
431 }
432
433 389757 color_octet_index++;
434
2/2
✓ Branch 0 taken 1434 times.
✓ Branch 1 taken 388323 times.
389757 if (color_octet_index == COLORS_PER_TABLE)
435 1434 color_octet_index = 0;
436 }
437
438
2/2
✓ Branch 0 taken 526571 times.
✓ Branch 1 taken 513154 times.
1039725 for (int i = 0; i < blocks; i++) {
439 526571 const int y_size = FFMIN(4, height - cur_y);
440 526571 const int x_size = FFMIN(4, width - cur_x);
441 526571 uint64_t flags = 0;
442 uint8_t octet[8];
443 526571 int shift = 45;
444
445
2/2
✓ Branch 0 taken 4212568 times.
✓ Branch 1 taken 526571 times.
4739139 for (int k = 0; k < 8; k++)
446 4212568 octet[k] = s->color_octets[color_table_index][k];
447
448
2/2
✓ Branch 0 taken 2105536 times.
✓ Branch 1 taken 526571 times.
2632107 for (int y = 0; y < y_size; y++) {
449
2/2
✓ Branch 0 taken 8419768 times.
✓ Branch 1 taken 2105536 times.
10525304 for (int x = 0; x < x_size; x++) {
450 8419768 int pixel = pixel_ptr[x + y * stride];
451 8419768 uint64_t idx = 0;
452
453
1/2
✓ Branch 0 taken 32084590 times.
✗ Branch 1 not taken.
32084590 for (int w = 0; w < COCTET; w++) {
454
2/2
✓ Branch 0 taken 8419768 times.
✓ Branch 1 taken 23664822 times.
32084590 if (octet[w] == pixel) {
455 8419768 idx = w;
456 8419768 break;
457 }
458 }
459
460 8419768 flags |= idx << shift;
461 8419768 shift -= 3;
462 }
463
464 2105536 shift -= 3 * (4 - x_size);
465 }
466
467 526571 bytestream2_put_be16(pb, ((flags >> 32) & 0xFFF0) | ((flags >> 8) & 0xF));
468 526571 bytestream2_put_be16(pb, ((flags >> 20) & 0xFFF0) | ((flags >> 4) & 0xF));
469 526571 bytestream2_put_be16(pb, ((flags >> 8) & 0xFFF0) | ((flags >> 0) & 0xF));
470
471
6/8
✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 520137 times.
✓ Branch 2 taken 526571 times.
✓ Branch 3 taken 526571 times.
✓ Branch 4 taken 526571 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 526571 times.
✗ Branch 7 not taken.
1053142 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
472 }
473 513154 break;
474 206973 default:
475 206973 bytestream2_put_byte(pb, 0xE0 | (blocks - 1));
476
2/2
✓ Branch 0 taken 206986 times.
✓ Branch 1 taken 206973 times.
413959 for (int i = 0; i < blocks; i++) {
477 206986 const int y_size = FFMIN(4, height - cur_y);
478 206986 const int x_size = FFMIN(4, width - cur_x);
479
2/2
✓ Branch 0 taken 827944 times.
✓ Branch 1 taken 206986 times.
1034930 for (int y = 0; y < y_size; y++) {
480
2/2
✓ Branch 0 taken 3311776 times.
✓ Branch 1 taken 827944 times.
4139720 for (int x = 0; x < x_size; x++)
481 3311776 bytestream2_put_byte(pb, pixel_ptr[x + y * stride]);
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 827944 times.
827944 for (int x = x_size; x < 4; x++)
483 bytestream2_put_byte(pb, 0);
484 }
485
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206986 times.
206986 for (int y = y_size; y < 4; y++) {
487 for (int x = 0; x < 4; x++)
488 bytestream2_put_byte(pb, 0);
489 }
490
491
6/8
✓ Branch 0 taken 2375 times.
✓ Branch 1 taken 204611 times.
✓ Branch 2 taken 206986 times.
✓ Branch 3 taken 206986 times.
✓ Branch 4 taken 206986 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 206986 times.
✗ Branch 7 not taken.
413972 ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
492 }
493 206973 break;
494 42 case 17:
495 42 bytestream2_put_byte(pb, 0x20 | (blocks - 1));
496
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
91 ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
497 42 break;
498 case 18:
499 bytestream2_put_byte(pb, 0x30);
500 bytestream2_put_byte(pb, blocks - 1);
501 ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
502 break;
503 8375 case 19:
504 8375 bytestream2_put_byte(pb, 0x00 | (blocks - 1));
505
6/8
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 11155 times.
✓ Branch 2 taken 11182 times.
✓ Branch 3 taken 8375 times.
✓ Branch 4 taken 11182 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11182 times.
✗ Branch 7 not taken.
19557 ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
506 8375 break;
507 2 case 20:
508 2 bytestream2_put_byte(pb, 0x10);
509 2 bytestream2_put_byte(pb, blocks - 1);
510
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
38 ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
511 2 break;
512 }
513
514 889064 block_counter += blocks;
515 }
516 200 }
517
518 4 static int smc_encode_init(AVCodecContext *avctx)
519 {
520 4 SMCContext *s = avctx->priv_data;
521
522 4 avctx->bits_per_coded_sample = 8;
523
524 4 s->prev_frame = av_frame_alloc();
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->prev_frame)
526 return AVERROR(ENOMEM);
527
528 4 return 0;
529 }
530
531 200 static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
532 const AVFrame *frame, int *got_packet)
533 {
534 200 SMCContext *s = avctx->priv_data;
535 200 const AVFrame *pict = frame;
536 PutByteContext pb;
537 uint8_t *pal;
538 int ret;
539
540 200 ret = ff_alloc_packet(avctx, pkt, 8LL * avctx->height * avctx->width);
541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (ret < 0)
542 return ret;
543
544
3/4
✓ Branch 0 taken 200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
✓ Branch 3 taken 4 times.
200 if (avctx->gop_size == 0 || !s->prev_frame->data[0] ||
545
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 180 times.
196 (avctx->frame_num % avctx->gop_size) == 0) {
546 20 s->key_frame = 1;
547 } else {
548 180 s->key_frame = 0;
549 }
550
551 200 bytestream2_init_writer(&pb, pkt->data, pkt->size);
552
553 200 bytestream2_put_be32(&pb, 0x00);
554
555 200 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (!pal)
557 return AVERROR(ENOMEM);
558 200 memcpy(pal, frame->data[1], AVPALETTE_SIZE);
559
560 200 smc_encode_stream(s, pict, &pb);
561
562 200 av_shrink_packet(pkt, bytestream2_tell_p(&pb));
563
564 200 pkt->data[0] = 0x0;
565
566 // write chunk length
567 200 AV_WB24(pkt->data + 1, pkt->size);
568
569 200 ret = av_frame_replace(s->prev_frame, frame);
570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (ret < 0) {
571 av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
572 return ret;
573 }
574
575
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 180 times.
200 if (s->key_frame)
576 20 pkt->flags |= AV_PKT_FLAG_KEY;
577
578 200 *got_packet = 1;
579
580 200 return 0;
581 }
582
583 4 static int smc_encode_end(AVCodecContext *avctx)
584 {
585 4 SMCContext *s = avctx->priv_data;
586
587 4 av_frame_free(&s->prev_frame);
588
589 4 return 0;
590 }
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 .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8,
603 AV_PIX_FMT_NONE},
604 };
605