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 "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;
46  uint8_t distinct_values[16];
47  uint8_t next_distinct_values[16];
48 
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 static int smc_cmp_values(const void *a, const void *b)
72 {
73  const uint8_t *aa = a, *bb = b;
74 
75  return FFDIFFSIGN(aa[0], bb[0]);
76 }
77 
78 static int count_distinct_items(const uint8_t *block_values,
79  uint8_t *distinct_values,
80  int size)
81 {
82  int n = 1;
83 
84  distinct_values[0] = block_values[0];
85  for (int i = 1; i < size; i++) {
86  if (block_values[i] != block_values[i-1]) {
87  distinct_values[n] = block_values[i];
88  n++;
89  }
90  }
91 
92  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 
116  PutByteContext *pb)
117 {
118  const uint8_t *src_pixels = (const uint8_t *)frame->data[0];
119  const ptrdiff_t stride = frame->linesize[0];
120  const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0];
121  const ptrdiff_t prev_stride = s->prev_frame->linesize[0];
122  uint8_t *distinct_values = s->distinct_values;
123  const uint8_t *pixel_ptr, *row_ptr;
124  const int height = frame->height;
125  const int width = frame->width;
126  int block_counter = 0;
127  int color_pair_index = 0;
128  int color_quad_index = 0;
129  int color_octet_index = 0;
130  int color_table_index; /* indexes to color pair, quad, or octet tables */
131  int total_blocks;
132  int cur_y = 0;
133  int cur_x = 0;
134 
135  /* Number of 4x4 blocks in frame. */
136  total_blocks = ((width + 3) / 4) * ((height + 3) / 4);
137 
138  pixel_ptr = row_ptr = src_pixels;
139 
140  while (block_counter < total_blocks) {
141  const uint8_t *xpixel_ptr = pixel_ptr;
142  const uint8_t *xrow_ptr = row_ptr;
143  int intra_skip_blocks = 0;
144  int inter_skip_blocks = 0;
145  int coded_distinct = 0;
146  int coded_blocks = 0;
147  int cache_index;
148  int distinct = 0;
149  int blocks = 0;
150  int frame_y = cur_y;
151  int frame_x = cur_x;
152 
153  while (prev_pixels && s->key_frame == 0 && block_counter + inter_skip_blocks < total_blocks) {
154  const int y_size = FFMIN(4, height - cur_y);
155  const int x_size = FFMIN(4, width - cur_x);
156  int compare = 0;
157 
158  for (int y = 0; y < y_size; y++) {
159  const uint8_t *prev_pixel_ptr = prev_pixels + (y + cur_y) * prev_stride + cur_x;
160 
161  compare |= !!memcmp(prev_pixel_ptr, pixel_ptr + y * stride, x_size);
162  if (compare)
163  break;
164  }
165 
166  if (compare)
167  break;
168 
169  inter_skip_blocks++;
170  if (inter_skip_blocks >= 256)
171  break;
172 
173  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
174  }
175 
176  pixel_ptr = xpixel_ptr;
177  row_ptr = xrow_ptr;
178  cur_y = frame_y;
179  cur_x = frame_x;
180 
181  while (block_counter > 0 && block_counter + intra_skip_blocks < total_blocks) {
182  const int y_size = FFMIN(4, height - cur_y);
183  const int x_size = FFMIN(4, width - cur_x);
184  const ptrdiff_t offset = xpixel_ptr - src_pixels;
185  const int sy = offset / stride;
186  const int sx = offset % stride;
187  const int ny = sx < 4 ? sy - 4 : sy;
188  const int nx = sx < 4 ? width - 4 + (width & 3) : sx - 4;
189  const uint8_t *old_pixel_ptr = src_pixels + nx + ny * stride;
190  int compare = 0;
191 
192  for (int y = 0; y < y_size; y++) {
193  compare |= !!memcmp(old_pixel_ptr + y * stride, pixel_ptr + y * stride, x_size);
194  if (compare)
195  break;
196  }
197 
198  if (compare)
199  break;
200 
201  intra_skip_blocks++;
202  if (intra_skip_blocks >= 256)
203  break;
204 
205  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
206  }
207 
208  pixel_ptr = xpixel_ptr;
209  row_ptr = xrow_ptr;
210  cur_y = frame_y;
211  cur_x = frame_x;
212 
213  while (block_counter + coded_blocks < total_blocks && coded_blocks < 256) {
214  const int y_size = FFMIN(4, height - cur_y);
215  const int x_size = FFMIN(4, width - cur_x);
216  const int nb_elements = x_size * y_size;
217  uint8_t block_values[16] = { 0 };
218  for (int y = 0; y < y_size; y++)
219  memcpy(block_values + y * x_size, pixel_ptr + y * stride, x_size);
220 
221  qsort(block_values, nb_elements, sizeof(block_values[0]), smc_cmp_values);
222  s->next_nb_distinct = count_distinct_items(block_values, s->next_distinct_values, nb_elements);
223  if (coded_blocks == 0) {
224  memcpy(distinct_values, s->next_distinct_values, sizeof(s->distinct_values));
225  s->nb_distinct = s->next_nb_distinct;
226  } else {
227  if (s->next_nb_distinct != s->nb_distinct ||
228  memcmp(distinct_values, s->next_distinct_values, s->nb_distinct)) {
229  break;
230  }
231  }
232  s->mono_value = block_values[0];
233 
234  coded_distinct = s->nb_distinct;
235  coded_blocks++;
236  if (coded_distinct > 1 && coded_blocks >= 16)
237  break;
238 
239  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
240  }
241 
242  pixel_ptr = xpixel_ptr;
243  row_ptr = xrow_ptr;
244  cur_y = frame_y;
245  cur_x = frame_x;
246 
247  blocks = coded_distinct <= 8 ? coded_blocks : 0;
248  distinct = coded_distinct;
249 
250  if (intra_skip_blocks >= blocks && intra_skip_blocks >= inter_skip_blocks) {
251  distinct = 17;
252  blocks = intra_skip_blocks;
253  }
254 
255  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  if (inter_skip_blocks >= blocks && inter_skip_blocks > intra_skip_blocks) {
262  distinct = 19;
263  blocks = inter_skip_blocks;
264  }
265 
266  if (inter_skip_blocks > 16 && inter_skip_blocks > intra_skip_blocks &&
267  inter_skip_blocks >= blocks) {
268  distinct = 20;
269  blocks = inter_skip_blocks;
270  }
271 
272  if (blocks == 0) {
273  blocks = coded_blocks;
274  distinct = coded_distinct;
275  }
276 
277  switch (distinct) {
278  case 1:
279  if (blocks <= 16) {
280  bytestream2_put_byte(pb, 0x60 | (blocks - 1));
281  } else {
282  bytestream2_put_byte(pb, 0x70);
283  bytestream2_put_byte(pb, blocks - 1);
284  }
285  bytestream2_put_byte(pb, s->mono_value);
286  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
287  break;
288  case 2:
289  cache_index = -1;
290  for (int i = 0; i < COLORS_PER_TABLE; i++) {
291  if (CACHE_PAIR(0) &&
292  CACHE_PAIR(1)) {
293  cache_index = i;
294  break;
295  }
296  }
297 
298  if (cache_index >= 0) {
299  bytestream2_put_byte(pb, 0x90 | (blocks - 1));
300  bytestream2_put_byte(pb, cache_index);
301  color_table_index = cache_index;
302  } else {
303  bytestream2_put_byte(pb, 0x80 | (blocks - 1));
304 
305  color_table_index = color_pair_index;
306  for (int i = 0; i < CPAIR; i++) {
307  s->color_pairs[color_table_index][i] = distinct_values[i];
308  bytestream2_put_byte(pb, distinct_values[i]);
309  }
310 
311  color_pair_index++;
312  if (color_pair_index == COLORS_PER_TABLE)
313  color_pair_index = 0;
314  }
315 
316  for (int i = 0; i < blocks; i++) {
317  const int y_size = FFMIN(4, height - cur_y);
318  const int x_size = FFMIN(4, width - cur_x);
319  uint8_t value = s->color_pairs[color_table_index][1];
320  uint16_t flags = 0;
321  int shift = 15;
322 
323  for (int y = 0; y < y_size; y++) {
324  for (int x = 0; x < x_size; x++) {
325  flags |= (value == pixel_ptr[x + y * stride]) << shift;
326  shift--;
327  }
328  shift -= 4 - x_size;
329  }
330 
331  bytestream2_put_be16(pb, flags);
332 
333  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
334  }
335  break;
336  case 3:
337  case 4:
338  cache_index = -1;
339  for (int i = 0; i < COLORS_PER_TABLE; i++) {
340  if (CACHE_QUAD(0) &&
341  CACHE_QUAD(1) &&
342  CACHE_QUAD(2) &&
343  CACHE_QUAD(3)) {
344  cache_index = i;
345  break;
346  }
347  }
348 
349  if (cache_index >= 0) {
350  bytestream2_put_byte(pb, 0xB0 | (blocks - 1));
351  bytestream2_put_byte(pb, cache_index);
352  color_table_index = cache_index;
353  } else {
354  bytestream2_put_byte(pb, 0xA0 | (blocks - 1));
355 
356  color_table_index = color_quad_index;
357  for (int i = 0; i < CQUAD; i++) {
358  s->color_quads[color_table_index][i] = distinct_values[i];
359  bytestream2_put_byte(pb, distinct_values[i]);
360  }
361 
362  color_quad_index++;
363  if (color_quad_index == COLORS_PER_TABLE)
364  color_quad_index = 0;
365  }
366 
367  for (int i = 0; i < blocks; i++) {
368  const int y_size = FFMIN(4, height - cur_y);
369  const int x_size = FFMIN(4, width - cur_x);
370  uint32_t flags = 0;
371  uint8_t quad[4];
372  int shift = 30;
373 
374  for (int k = 0; k < 4; k++)
375  quad[k] = s->color_quads[color_table_index][k];
376 
377  for (int y = 0; y < y_size; y++) {
378  for (int x = 0; x < x_size; x++) {
379  int pixel = pixel_ptr[x + y * stride];
380  uint32_t idx = 0;
381 
382  for (int w = 0; w < CQUAD; w++) {
383  if (quad[w] == pixel) {
384  idx = w;
385  break;
386  }
387  }
388 
389  flags |= idx << shift;
390  shift -= 2;
391  }
392 
393  shift -= 2 * (4 - x_size);
394  }
395 
396  bytestream2_put_be32(pb, flags);
397 
398  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
399  }
400  break;
401  case 5:
402  case 6:
403  case 7:
404  case 8:
405  cache_index = -1;
406  for (int i = 0; i < COLORS_PER_TABLE; i++) {
407  if (CACHE_OCTET(0) &&
408  CACHE_OCTET(1) &&
409  CACHE_OCTET(2) &&
410  CACHE_OCTET(3) &&
411  CACHE_OCTET(4) &&
412  CACHE_OCTET(5) &&
413  CACHE_OCTET(6) &&
414  CACHE_OCTET(7)) {
415  cache_index = i;
416  break;
417  }
418  }
419 
420  if (cache_index >= 0) {
421  bytestream2_put_byte(pb, 0xD0 | (blocks - 1));
422  bytestream2_put_byte(pb, cache_index);
423  color_table_index = cache_index;
424  } else {
425  bytestream2_put_byte(pb, 0xC0 | (blocks - 1));
426 
427  color_table_index = color_octet_index;
428  for (int i = 0; i < COCTET; i++) {
429  s->color_octets[color_table_index][i] = distinct_values[i];
430  bytestream2_put_byte(pb, distinct_values[i]);
431  }
432 
433  color_octet_index++;
434  if (color_octet_index == COLORS_PER_TABLE)
435  color_octet_index = 0;
436  }
437 
438  for (int i = 0; i < blocks; i++) {
439  const int y_size = FFMIN(4, height - cur_y);
440  const int x_size = FFMIN(4, width - cur_x);
441  uint64_t flags = 0;
442  uint8_t octet[8];
443  int shift = 45;
444 
445  for (int k = 0; k < 8; k++)
446  octet[k] = s->color_octets[color_table_index][k];
447 
448  for (int y = 0; y < y_size; y++) {
449  for (int x = 0; x < x_size; x++) {
450  int pixel = pixel_ptr[x + y * stride];
451  uint64_t idx = 0;
452 
453  for (int w = 0; w < COCTET; w++) {
454  if (octet[w] == pixel) {
455  idx = w;
456  break;
457  }
458  }
459 
460  flags |= idx << shift;
461  shift -= 3;
462  }
463 
464  shift -= 3 * (4 - x_size);
465  }
466 
467  bytestream2_put_be16(pb, ((flags >> 32) & 0xFFF0) | ((flags >> 8) & 0xF));
468  bytestream2_put_be16(pb, ((flags >> 20) & 0xFFF0) | ((flags >> 4) & 0xF));
469  bytestream2_put_be16(pb, ((flags >> 8) & 0xFFF0) | ((flags >> 0) & 0xF));
470 
471  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
472  }
473  break;
474  default:
475  bytestream2_put_byte(pb, 0xE0 | (blocks - 1));
476  for (int i = 0; i < blocks; i++) {
477  const int y_size = FFMIN(4, height - cur_y);
478  const int x_size = FFMIN(4, width - cur_x);
479  for (int y = 0; y < y_size; y++) {
480  for (int x = 0; x < x_size; x++)
481  bytestream2_put_byte(pb, pixel_ptr[x + y * stride]);
482  for (int x = x_size; x < 4; x++)
483  bytestream2_put_byte(pb, 0);
484  }
485 
486  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  ADVANCE_BLOCK(pixel_ptr, row_ptr, 1)
492  }
493  break;
494  case 17:
495  bytestream2_put_byte(pb, 0x20 | (blocks - 1));
496  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
497  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  case 19:
504  bytestream2_put_byte(pb, 0x00 | (blocks - 1));
505  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
506  break;
507  case 20:
508  bytestream2_put_byte(pb, 0x10);
509  bytestream2_put_byte(pb, blocks - 1);
510  ADVANCE_BLOCK(pixel_ptr, row_ptr, blocks)
511  break;
512  }
513 
514  block_counter += blocks;
515  }
516 }
517 
518 static int smc_encode_init(AVCodecContext *avctx)
519 {
520  SMCContext *s = avctx->priv_data;
521 
522  avctx->bits_per_coded_sample = 8;
523 
524  s->prev_frame = av_frame_alloc();
525  if (!s->prev_frame)
526  return AVERROR(ENOMEM);
527 
528  return 0;
529 }
530 
532  const AVFrame *frame, int *got_packet)
533 {
534  SMCContext *s = avctx->priv_data;
535  const AVFrame *pict = frame;
536  PutByteContext pb;
537  uint8_t *pal;
538  int ret;
539 
540  ret = ff_alloc_packet(avctx, pkt, 8LL * avctx->height * avctx->width);
541  if (ret < 0)
542  return ret;
543 
544  if (avctx->gop_size == 0 || !s->prev_frame->data[0] ||
545  (avctx->frame_num % avctx->gop_size) == 0) {
546  s->key_frame = 1;
547  } else {
548  s->key_frame = 0;
549  }
550 
552 
553  bytestream2_put_be32(&pb, 0x00);
554 
556  if (!pal)
557  return AVERROR(ENOMEM);
558  memcpy(pal, frame->data[1], AVPALETTE_SIZE);
559 
560  smc_encode_stream(s, pict, &pb);
561 
563 
564  pkt->data[0] = 0x0;
565 
566  // write chunk length
567  AV_WB24(pkt->data + 1, pkt->size);
568 
569  ret = av_frame_replace(s->prev_frame, frame);
570  if (ret < 0) {
571  av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
572  return ret;
573  }
574 
575  if (s->key_frame)
577 
578  *got_packet = 1;
579 
580  return 0;
581 }
582 
583 static int smc_encode_end(AVCodecContext *avctx)
584 {
585  SMCContext *s = avctx->priv_data;
586 
587  av_frame_free(&s->prev_frame);
588 
589  return 0;
590 }
591 
593  .p.name = "smc",
594  CODEC_LONG_NAME("QuickTime Graphics (SMC)"),
595  .p.type = AVMEDIA_TYPE_VIDEO,
596  .p.id = AV_CODEC_ID_SMC,
598  .priv_data_size = sizeof(SMCContext),
601  .close = smc_encode_end,
602  .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8,
604 };
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
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:56
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:160
SMCContext::prev_frame
AVFrame * prev_frame
Definition: smcenc.c:41
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:524
encode.h
b
#define b
Definition: input.c:41
smc_encode_frame
static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Definition: smcenc.c:531
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:518
FFCodec
Definition: codec_internal.h:127
CPAIR
#define CPAIR
Definition: smcenc.c:34
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:579
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
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:47
av_shrink_packet
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: packet.c:113
AV_CODEC_ID_SMC
@ AV_CODEC_ID_SMC
Definition: codec_id.h:101
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:296
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:148
SMCContext
Definition: smcenc.c:40
SMCContext::next_nb_distinct
int next_nb_distinct
Definition: smcenc.c:45
pkt
AVPacket * pkt
Definition: movenc.c:60
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:198
SMCContext::next_distinct_values
uint8_t next_distinct_values[16]
Definition: smcenc.c:47
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition: codec.h:159
SMCContext::mono_value
uint8_t mono_value
Definition: smcenc.c:43
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
pixel
uint8_t pixel
Definition: tiny_ssim.c:41
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
CQUAD
#define CQUAD
Definition: smcenc.c:35
PutByteContext
Definition: bytestream.h:37
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:525
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1031
codec_internal.h
shift
static int shift(int a, int b)
Definition: bonk.c:261
ff_smc_encoder
const FFCodec ff_smc_encoder
Definition: smcenc.c:592
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
size
int size
Definition: twinvq_data.h:10344
AV_WB24
#define AV_WB24(p, d)
Definition: intreadwrite.h:448
height
#define height
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:78
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:530
AVCodecContext::bits_per_coded_sample
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1567
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
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
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
COLORS_PER_TABLE
#define COLORS_PER_TABLE
Definition: smcenc.c:38
CACHE_QUAD
#define CACHE_QUAD(x)
Definition: smcenc.c:99
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::height
int height
Definition: avcodec.h:618
avcodec.h
stride
#define stride
Definition: h264pred_template.c:537
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
AVCodecContext::frame_num
int64_t frame_num
Frame counter, set by libavcodec.
Definition: avcodec.h:2030
ret
ret
Definition: filter_design.txt:187
SMCContext::color_quads
uint8_t color_quads[COLORS_PER_TABLE][CQUAD]
Definition: smcenc.c:50
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
av_frame_replace
int av_frame_replace(AVFrame *dst, const AVFrame *src)
Ensure the destination frame refers to the same data described by the source frame,...
Definition: frame.c:483
AVCodecContext
main external API structure.
Definition: avcodec.h:445
compare
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
Definition: vf_find_rect.c:96
SMCContext::color_octets
uint8_t color_octets[COLORS_PER_TABLE][COCTET]
Definition: smcenc.c:51
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: packet.c:231
SMCContext::distinct_values
uint8_t distinct_values[16]
Definition: smcenc.c:46
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
smc_encode_stream
static void smc_encode_stream(SMCContext *s, const AVFrame *frame, PutByteContext *pb)
Definition: smcenc.c:115
SMCContext::key_frame
int key_frame
Definition: smcenc.c:53
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
CACHE_OCTET
#define CACHE_OCTET(x)
Definition: smcenc.c:105
AVPacket
This structure stores compressed data.
Definition: packet.h:501
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
bytestream.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
CACHE_PAIR
#define CACHE_PAIR(x)
Definition: smcenc.c:95
SMCContext::color_pairs
uint8_t color_pairs[COLORS_PER_TABLE][CPAIR]
Definition: smcenc.c:49
ff_alloc_packet
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition: encode.c:62
smc_cmp_values
static int smc_cmp_values(const void *a, const void *b)
Definition: smcenc.c:71
SMCContext::nb_distinct
int nb_distinct
Definition: smcenc.c:44
smc_encode_end
static int smc_encode_end(AVCodecContext *avctx)
Definition: smcenc.c:583