FFmpeg
smcenc.c
Go to the documentation of this file.
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 "encode.h"
31 #include "internal.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
43 
44  uint8_t mono_value;
47  uint8_t distinct_values[16];
48  uint8_t next_distinct_values[16];
49 
53 
54  int key_frame;
55 } SMCContext;
56 
57 #define ADVANCE_BLOCK(pixel_ptr, row_ptr, nb_blocks) \
58 { \
59  for (int block = 0; block < nb_blocks && pixel_ptr && row_ptr; block++) { \
60  pixel_ptr += 4; \
61  if (pixel_ptr - row_ptr >= width) \
62  { \
63  row_ptr += stride * 4; \
64  pixel_ptr = row_ptr; \
65  } \
66  } \
67 }
68 
69 static int smc_cmp_values(const void *a, const void *b)
70 {
71  const uint8_t *aa = a, *bb = b;
72 
73  return FFDIFFSIGN(aa[0], bb[0]);
74 }
75 
76 static int count_distinct_items(const uint8_t *block_values,
77  uint8_t *distinct_values,
78  int size)
79 {
80  int n = 1;
81 
82  distinct_values[0] = block_values[0];
83  for (int i = 1; i < size; i++) {
84  if (block_values[i] != block_values[i-1]) {
85  distinct_values[n] = block_values[i];
86  n++;
87  }
88  }
89 
90  return n;
91 }
92 
93 #define CACHE_PAIR(x) \
94  (s->color_pairs[i][0] == distinct_values[x] || \
95  s->color_pairs[i][1] == distinct_values[x])
96 
97 #define CACHE_QUAD(x) \
98  (s->color_quads[i][0] == distinct_values[x] || \
99  s->color_quads[i][1] == distinct_values[x] || \
100  s->color_quads[i][2] == distinct_values[x] || \
101  s->color_quads[i][3] == distinct_values[x])
102 
103 #define CACHE_OCTET(x) \
104  (s->color_octets[i][0] == distinct_values[x] || \
105  s->color_octets[i][1] == distinct_values[x] || \
106  s->color_octets[i][2] == distinct_values[x] || \
107  s->color_octets[i][3] == distinct_values[x] || \
108  s->color_octets[i][4] == distinct_values[x] || \
109  s->color_octets[i][5] == distinct_values[x] || \
110  s->color_octets[i][6] == distinct_values[x] || \
111  s->color_octets[i][7] == distinct_values[x])
112 
114 {
115  PutByteContext *pb = &s->pb;
116  const uint8_t *src_pixels = (const uint8_t *)frame->data[0];
117  const int stride = frame->linesize[0];
118  const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0];
119  uint8_t *distinct_values = s->distinct_values;
120  const uint8_t *pixel_ptr, *row_ptr;
121  const int width = frame->width;
122  uint8_t block_values[16];
123  int block_counter = 0;
124  int color_pair_index = 0;
125  int color_quad_index = 0;
126  int color_octet_index = 0;
127  int color_table_index; /* indexes to color pair, quad, or octet tables */
128  int total_blocks;
129 
130  memset(s->color_pairs, 0, sizeof(s->color_pairs));
131  memset(s->color_quads, 0, sizeof(s->color_quads));
132  memset(s->color_octets, 0, sizeof(s->color_octets));
133 
134  /* Number of 4x4 blocks in frame. */
135  total_blocks = ((frame->width + 3) / 4) * ((frame->height + 3) / 4);
136 
137  pixel_ptr = row_ptr = src_pixels;
138 
139  while (block_counter < total_blocks) {
140  const uint8_t *xpixel_ptr = pixel_ptr;
141  const uint8_t *xrow_ptr = row_ptr;
142  int intra_skip_blocks = 0;
143  int inter_skip_blocks = 0;
144  int coded_distinct = 0;
145  int coded_blocks = 0;
146  int cache_index;
147  int distinct = 0;
148  int blocks = 0;
149 
150  while (prev_pixels && s->key_frame == 0 && block_counter + inter_skip_blocks < total_blocks) {
151  int compare = 0;
152 
153  for (int y = 0; y < 4; y++) {
154  const ptrdiff_t offset = pixel_ptr - src_pixels;
155  const uint8_t *prev_pixel_ptr = prev_pixels + offset;
156 
157  compare |= memcmp(prev_pixel_ptr + y * stride, pixel_ptr + y * stride, 4);
158  if (compare)
159  break;
160  }
161 
162  if (compare)
163  break;
164 
165  if (inter_skip_blocks >= 256)
166  break;
167  inter_skip_blocks++;
168 
169  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
170  }
171 
172  pixel_ptr = xpixel_ptr;
173  row_ptr = xrow_ptr;
174 
175  while (block_counter > 0 && block_counter + intra_skip_blocks < total_blocks) {
176  const ptrdiff_t offset = pixel_ptr - src_pixels;
177  const int sy = offset / stride;
178  const int sx = offset % stride;
179  const int ny = sx < 4 ? sy - 4 : sy;
180  const int nx = sx < 4 ? width - 4 : sx - 4;
181  const uint8_t *old_pixel_ptr = src_pixels + nx + ny * stride;
182  int compare = 0;
183 
184  for (int y = 0; y < 4; y++) {
185  compare |= memcmp(old_pixel_ptr + y * stride, pixel_ptr + y * stride, 4);
186  if (compare)
187  break;
188  }
189 
190  if (compare)
191  break;
192 
193  if (intra_skip_blocks >= 256)
194  break;
195  intra_skip_blocks++;
196  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
197  }
198 
199  pixel_ptr = xpixel_ptr;
200  row_ptr = xrow_ptr;
201 
202  while (block_counter + coded_blocks < total_blocks && coded_blocks < 256) {
203  for (int y = 0; y < 4; y++)
204  memcpy(block_values + y * 4, pixel_ptr + y * stride, 4);
205 
206  qsort(block_values, 16, sizeof(block_values[0]), smc_cmp_values);
207  s->next_nb_distinct = count_distinct_items(block_values, s->next_distinct_values, 16);
208  if (coded_blocks == 0) {
209  memcpy(distinct_values, s->next_distinct_values, sizeof(s->distinct_values));
210  s->nb_distinct = s->next_nb_distinct;
211  } else {
212  if (s->next_nb_distinct != s->nb_distinct ||
213  memcmp(distinct_values, s->next_distinct_values, s->nb_distinct)) {
214  break;
215  }
216  }
217  s->mono_value = block_values[0];
218 
219  coded_distinct = s->nb_distinct;
220  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
221  coded_blocks++;
222  if (coded_distinct > 1 && coded_blocks >= 16)
223  break;
224  }
225 
226  pixel_ptr = xpixel_ptr;
227  row_ptr = xrow_ptr;
228 
229  blocks = coded_blocks;
230  distinct = coded_distinct;
231 
232  if (intra_skip_blocks > 0 && intra_skip_blocks >= inter_skip_blocks &&
233  intra_skip_blocks > 0) {
234  distinct = 17;
235  blocks = intra_skip_blocks;
236  }
237 
238  if (intra_skip_blocks > 16 && intra_skip_blocks >= inter_skip_blocks &&
239  intra_skip_blocks > 0) {
240  distinct = 18;
241  blocks = intra_skip_blocks;
242  }
243 
244  if (inter_skip_blocks > 0 && inter_skip_blocks > intra_skip_blocks &&
245  inter_skip_blocks > 0) {
246  distinct = 19;
247  blocks = inter_skip_blocks;
248  }
249 
250  if (inter_skip_blocks > 16 && inter_skip_blocks > intra_skip_blocks &&
251  inter_skip_blocks > 0) {
252  distinct = 20;
253  blocks = inter_skip_blocks;
254  }
255 
256  switch (distinct) {
257  case 1:
258  if (blocks <= 16) {
259  bytestream2_put_byte(pb, 0x60 | (blocks - 1));
260  } else {
261  bytestream2_put_byte(pb, 0x70);
262  bytestream2_put_byte(pb, blocks - 1);
263  }
264  bytestream2_put_byte(pb, s->mono_value);
265  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
266  break;
267  case 2:
268  cache_index = -1;
269  for (int i = 0; i < COLORS_PER_TABLE; i++) {
270  if (CACHE_PAIR(0) &&
271  CACHE_PAIR(1)) {
272  cache_index = i;
273  break;
274  }
275  }
276 
277  if (cache_index >= 0) {
278  bytestream2_put_byte(pb, 0x90 | (blocks - 1));
279  bytestream2_put_byte(pb, cache_index);
280  color_table_index = cache_index;
281  } else {
282  bytestream2_put_byte(pb, 0x80 | (blocks - 1));
283 
284  color_table_index = color_pair_index;
285  for (int i = 0; i < CPAIR; i++) {
286  s->color_pairs[color_table_index][i] = distinct_values[i];
287  bytestream2_put_byte(pb, distinct_values[i]);
288  }
289 
290  color_pair_index++;
291  if (color_pair_index == COLORS_PER_TABLE)
292  color_pair_index = 0;
293  }
294 
295  for (int i = 0; i < blocks; i++) {
296  uint8_t value = s->color_pairs[color_table_index][1];
297  uint16_t flags = 0;
298  int shift = 15;
299 
300  for (int y = 0; y < 4; y++) {
301  for (int x = 0; x < 4; x++) {
302  flags |= (value == pixel_ptr[x + y * stride]) << shift;
303  shift--;
304  }
305  }
306 
307  bytestream2_put_be16(pb, flags);
308 
309  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
310  }
311  break;
312  case 3:
313  case 4:
314  cache_index = -1;
315  for (int i = 0; i < COLORS_PER_TABLE; i++) {
316  if (CACHE_QUAD(0) &&
317  CACHE_QUAD(1) &&
318  CACHE_QUAD(2) &&
319  CACHE_QUAD(3)) {
320  cache_index = i;
321  break;
322  }
323  }
324 
325  if (cache_index >= 0) {
326  bytestream2_put_byte(pb, 0xB0 | (blocks - 1));
327  bytestream2_put_byte(pb, cache_index);
328  color_table_index = cache_index;
329  } else {
330  bytestream2_put_byte(pb, 0xA0 | (blocks - 1));
331 
332  color_table_index = color_quad_index;
333  for (int i = 0; i < CQUAD; i++) {
334  s->color_quads[color_table_index][i] = distinct_values[i];
335  bytestream2_put_byte(pb, distinct_values[i]);
336  }
337 
338  color_quad_index++;
339  if (color_quad_index == COLORS_PER_TABLE)
340  color_quad_index = 0;
341  }
342 
343  for (int i = 0; i < blocks; i++) {
344  uint32_t flags = 0;
345  uint8_t quad[4];
346  int shift = 30;
347 
348  for (int k = 0; k < 4; k++)
349  quad[k] = s->color_quads[color_table_index][k];
350 
351  for (int y = 0; y < 4; y++) {
352  for (int x = 0; x < 4; x++) {
353  int pixel = pixel_ptr[x + y * stride];
354  uint32_t idx = 0;
355 
356  for (int w = 0; w < CQUAD; w++) {
357  if (quad[w] == pixel) {
358  idx = w;
359  break;
360  }
361  }
362 
363  flags |= idx << shift;
364  shift -= 2;
365  }
366  }
367 
368  bytestream2_put_be32(pb, flags);
369 
370  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
371  }
372  break;
373  case 5:
374  case 6:
375  case 7:
376  case 8:
377  cache_index = -1;
378  for (int i = 0; i < COLORS_PER_TABLE; i++) {
379  if (CACHE_OCTET(0) &&
380  CACHE_OCTET(1) &&
381  CACHE_OCTET(2) &&
382  CACHE_OCTET(3) &&
383  CACHE_OCTET(4) &&
384  CACHE_OCTET(5) &&
385  CACHE_OCTET(6) &&
386  CACHE_OCTET(7)) {
387  cache_index = i;
388  break;
389  }
390  }
391 
392  if (cache_index >= 0) {
393  bytestream2_put_byte(pb, 0xD0 | (blocks - 1));
394  bytestream2_put_byte(pb, cache_index);
395  color_table_index = cache_index;
396  } else {
397  bytestream2_put_byte(pb, 0xC0 | (blocks - 1));
398 
399  color_table_index = color_octet_index;
400  for (int i = 0; i < COCTET; i++) {
401  s->color_octets[color_table_index][i] = distinct_values[i];
402  bytestream2_put_byte(pb, distinct_values[i]);
403  }
404 
405  color_octet_index++;
406  if (color_octet_index == COLORS_PER_TABLE)
407  color_octet_index = 0;
408  }
409 
410  for (int i = 0; i < blocks; i++) {
411  uint64_t flags = 0;
412  uint8_t octet[8];
413  int shift = 45;
414 
415  for (int k = 0; k < 8; k++)
416  octet[k] = s->color_octets[color_table_index][k];
417 
418  for (int y = 0; y < 4; y++) {
419  for (int x = 0; x < 4; x++) {
420  int pixel = pixel_ptr[x + y * stride];
421  uint64_t idx = 0;
422 
423  for (int w = 0; w < COCTET; w++) {
424  if (octet[w] == pixel) {
425  idx = w;
426  break;
427  }
428  }
429 
430  flags |= idx << shift;
431  shift -= 3;
432  }
433  }
434 
435  bytestream2_put_be16(pb, ((flags >> 32) & 0xFFF0) | ((flags >> 8) & 0xF));
436  bytestream2_put_be16(pb, ((flags >> 20) & 0xFFF0) | ((flags >> 4) & 0xF));
437  bytestream2_put_be16(pb, ((flags >> 8) & 0xFFF0) | ((flags >> 0) & 0xF));
438 
439  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
440  }
441  break;
442  default:
443  bytestream2_put_byte(pb, 0xE0 | (blocks - 1));
444  for (int i = 0; i < blocks; i++) {
445  for (int y = 0; y < 4; y++) {
446  for (int x = 0; x < 4; x++)
447  bytestream2_put_byte(pb, pixel_ptr[x + y * stride]);
448  }
449 
450  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
451  }
452  break;
453  case 17:
454  bytestream2_put_byte(pb, 0x20 | (blocks - 1));
455  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
456  break;
457  case 18:
458  bytestream2_put_byte(pb, 0x30);
459  bytestream2_put_byte(pb, blocks - 1);
460  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
461  break;
462  case 19:
463  bytestream2_put_byte(pb, 0x00 | (blocks - 1));
464  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
465  break;
466  case 20:
467  bytestream2_put_byte(pb, 0x10);
468  bytestream2_put_byte(pb, blocks - 1);
469  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
470  break;
471  }
472 
473  block_counter += blocks;
474  }
475 }
476 
477 static int smc_encode_init(AVCodecContext *avctx)
478 {
479  SMCContext *s = avctx->priv_data;
480 
481  avctx->bits_per_coded_sample = 8;
482 
483  s->prev_frame = av_frame_alloc();
484  if (!s->prev_frame)
485  return AVERROR(ENOMEM);
486 
487  return 0;
488 }
489 
491  const AVFrame *frame, int *got_packet)
492 {
493  SMCContext *s = avctx->priv_data;
494  const AVFrame *pict = frame;
495  uint8_t *pal;
496  int ret;
497 
498  ret = ff_alloc_packet(avctx, pkt, 8LL * avctx->height * avctx->width);
499  if (ret < 0)
500  return ret;
501 
502  if (avctx->gop_size == 0 || !s->prev_frame->data[0] ||
503  (avctx->frame_number % avctx->gop_size) == 0) {
504  s->key_frame = 1;
505  } else {
506  s->key_frame = 0;
507  }
508 
510 
511  bytestream2_put_be32(&s->pb, 0x00);
512 
514  if (!pal)
515  return AVERROR(ENOMEM);
516  memcpy(pal, frame->data[1], AVPALETTE_SIZE);
517 
518  smc_encode_stream(s, pict);
519 
521 
522  pkt->data[0] = 0x0;
523 
524  // write chunk length
525  AV_WB24(pkt->data + 1, pkt->size);
526 
527  av_frame_unref(s->prev_frame);
528  ret = av_frame_ref(s->prev_frame, frame);
529  if (ret < 0) {
530  av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
531  return ret;
532  }
533 
534  if (s->key_frame)
536 
537  *got_packet = 1;
538 
539  return 0;
540 }
541 
542 static int smc_encode_end(AVCodecContext *avctx)
543 {
544  SMCContext *s = (SMCContext *)avctx->priv_data;
545 
546  av_frame_free(&s->prev_frame);
547 
548  return 0;
549 }
550 
552  .name = "smc",
553  .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
554  .type = AVMEDIA_TYPE_VIDEO,
555  .id = AV_CODEC_ID_SMC,
556  .priv_data_size = sizeof(SMCContext),
558  .encode2 = smc_encode_frame,
559  .close = smc_encode_end,
560  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
561  .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8,
563 };
AVCodec
AVCodec.
Definition: codec.h:202
stride
int stride
Definition: mace.c:144
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:42
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ADVANCE_BLOCK
#define ADVANCE_BLOCK(pixel_ptr, row_ptr, nb_blocks)
Definition: smcenc.c:57
COCTET
#define COCTET
Definition: smcenc.c:36
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
SMCContext::prev_frame
AVFrame * prev_frame
Definition: smcenc.c:41
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
w
uint8_t w
Definition: llviddspenc.c:38
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:373
encode.h
b
#define b
Definition: input.c:40
smc_encode_frame
static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Definition: smcenc.c:490
AV_PKT_DATA_PALETTE
@ AV_PKT_DATA_PALETTE
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette.
Definition: packet.h:46
bytestream2_tell_p
static av_always_inline int bytestream2_tell_p(PutByteContext *p)
Definition: bytestream.h:197
smc_encode_init
static int smc_encode_init(AVCodecContext *avctx)
Definition: smcenc.c:477
CPAIR
#define CPAIR
Definition: smcenc.c:34
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:425
av_shrink_packet
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: avpacket.c:114
AV_CODEC_ID_SMC
@ AV_CODEC_ID_SMC
Definition: codec_id.h:99
FFDIFFSIGN
#define FFDIFFSIGN(x, y)
Comparator.
Definition: macros.h:45
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:99
SMCContext
Definition: smcenc.c:40
SMCContext::next_nb_distinct
int next_nb_distinct
Definition: smcenc.c:46
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
bytestream2_init_writer
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:147
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:257
SMCContext::next_distinct_values
uint8_t next_distinct_values[16]
Definition: smcenc.c:48
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:290
SMCContext::mono_value
uint8_t mono_value
Definition: smcenc.c:44
pixel
uint8_t pixel
Definition: tiny_ssim.c:42
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
SMCContext::pb
PutByteContext pb
Definition: smcenc.c:42
CQUAD
#define CQUAD
Definition: smcenc.c:35
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
PutByteContext
Definition: bytestream.h:37
smc_encode_stream
static void smc_encode_stream(SMCContext *s, const AVFrame *frame)
Definition: smcenc.c:113
AVPacket::size
int size
Definition: packet.h:374
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:578
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:327
size
int size
Definition: twinvq_data.h:10344
AV_WB24
#define AV_WB24(p, d)
Definition: intreadwrite.h:450
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
count_distinct_items
static int count_distinct_items(const uint8_t *block_values, uint8_t *distinct_values, int size)
Definition: smcenc.c:76
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:379
ff_smc_encoder
const AVCodec ff_smc_encoder
Definition: smcenc.c:551
AVCodecContext::bits_per_coded_sample
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1418
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
common.h
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
COLORS_PER_TABLE
#define COLORS_PER_TABLE
Definition: smcenc.c:38
CACHE_QUAD
#define CACHE_QUAD(x)
Definition: smcenc.c:97
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:437
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:209
AVCodecContext::height
int height
Definition: avcodec.h:556
avcodec.h
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
ret
ret
Definition: filter_design.txt:187
SMCContext::color_quads
uint8_t color_quads[COLORS_PER_TABLE][CQUAD]
Definition: smcenc.c:51
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AVCodecContext
main external API structure.
Definition: avcodec.h:383
compare
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
Definition: vf_find_rect.c:95
SMCContext::color_octets
uint8_t color_octets[COLORS_PER_TABLE][COCTET]
Definition: smcenc.c:52
av_packet_new_side_data
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition: avpacket.c:225
SMCContext::distinct_values
uint8_t distinct_values[16]
Definition: smcenc.c:47
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
SMCContext::key_frame
int key_frame
Definition: smcenc.c:54
shift
static int shift(int a, int b)
Definition: sonic.c:83
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
CACHE_OCTET
#define CACHE_OCTET(x)
Definition: smcenc.c:103
AVCodecContext::frame_number
int frame_number
Frame counter, set by libavcodec.
Definition: avcodec.h:1023
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:410
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:556
bytestream.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
CACHE_PAIR
#define CACHE_PAIR(x)
Definition: smcenc.c:93
SMCContext::color_pairs
uint8_t color_pairs[COLORS_PER_TABLE][CPAIR]
Definition: smcenc.c:50
ff_alloc_packet
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition: encode.c:34
smc_cmp_values
static int smc_cmp_values(const void *a, const void *b)
Definition: smcenc.c:69
SMCContext::nb_distinct
int nb_distinct
Definition: smcenc.c:45
smc_encode_end
static int smc_encode_end(AVCodecContext *avctx)
Definition: smcenc.c:542