FFmpeg
roqvideoenc.c
Go to the documentation of this file.
1 /*
2  * RoQ Video Encoder.
3  *
4  * Copyright (C) 2007 Vitor Sessak <vitor1001@gmail.com>
5  * Copyright (C) 2004-2007 Eric Lasota
6  * Based on RoQ specs (C) 2001 Tim Ferguson
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 /**
26  * @file
27  * id RoQ encoder by Vitor. Based on the Switchblade3 library and the
28  * Switchblade3 FFmpeg glue by Eric Lasota.
29  */
30 
31 /*
32  * COSTS:
33  * Level 1:
34  * SKIP - 2 bits
35  * MOTION - 2 + 8 bits
36  * CODEBOOK - 2 + 8 bits
37  * SUBDIVIDE - 2 + combined subcel cost
38  *
39  * Level 2:
40  * SKIP - 2 bits
41  * MOTION - 2 + 8 bits
42  * CODEBOOK - 2 + 8 bits
43  * SUBDIVIDE - 2 + 4*8 bits
44  *
45  * Maximum cost: 138 bits per cel
46  *
47  * Proper evaluation requires LCD fraction comparison, which requires
48  * Squared Error (SE) loss * savings increase
49  *
50  * Maximum savings increase: 136 bits
51  * Maximum SE loss without overflow: 31580641
52  * Components in 8x8 supercel: 192
53  * Maximum SE precision per component: 164482
54  * >65025, so no truncation is needed (phew)
55  */
56 
57 #include <string.h>
58 
59 #include "libavutil/attributes.h"
60 #include "libavutil/lfg.h"
61 #include "libavutil/opt.h"
62 #include "roqvideo.h"
63 #include "bytestream.h"
64 #include "elbg.h"
65 #include "internal.h"
66 #include "mathops.h"
67 
68 #define CHROMA_BIAS 1
69 
70 /**
71  * Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a
72  * Quake 3 bug.
73  */
74 #define MAX_CBS_4x4 256
75 
76 #define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks.
77 
78 /* The cast is useful when multiplying it by INT_MAX */
79 #define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
80 
81 typedef struct RoqCodebooks {
82  int numCB4;
83  int numCB2;
86  uint8_t unpacked_cb2[MAX_CBS_2x2*2*2*3];
87  uint8_t unpacked_cb4[MAX_CBS_4x4*4*4*3];
89 } RoqCodebooks;
90 
91 /**
92  * Temporary vars
93  */
94 typedef struct RoqTempData
95 {
100 
102 
103  int numCB4;
104  int numCB2;
105 
107 
108  int used_option[4];
109 } RoqTempData;
110 
111 typedef struct SubcelEvaluation {
112  int eval_dist[4];
115 
116  int subCels[4];
118  int cbEntry;
120 
121 typedef struct CelEvaluation {
122  int eval_dist[4];
124 
126 
128  int cbEntry;
129 
131 } CelEvaluation;
132 
133 typedef struct RoqEncContext {
136  uint64_t lambda;
137 
140 
143 
144  unsigned int framesSinceKeyframe;
145 
147  uint8_t *out_buf;
151 
154  int *points; // Allocated together with closest_cb
155 
157  int quake3_compat; // Quake 3 compatibility option
158 } RoqEncContext;
159 
160 /* Macroblock support functions */
161 static void unpack_roq_cell(roq_cell *cell, uint8_t u[4*3])
162 {
163  memcpy(u , cell->y, 4);
164  memset(u+4, cell->u, 4);
165  memset(u+8, cell->v, 4);
166 }
167 
168 static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4*4*3])
169 {
170  int i,cp;
171  static const int offsets[4] = {0, 2, 8, 10};
172 
173  for (cp=0; cp<3; cp++)
174  for (i=0; i<4; i++) {
175  u[4*4*cp + offsets[i] ] = cb2[qcell->idx[i]*2*2*3 + 4*cp ];
176  u[4*4*cp + offsets[i]+1] = cb2[qcell->idx[i]*2*2*3 + 4*cp+1];
177  u[4*4*cp + offsets[i]+4] = cb2[qcell->idx[i]*2*2*3 + 4*cp+2];
178  u[4*4*cp + offsets[i]+5] = cb2[qcell->idx[i]*2*2*3 + 4*cp+3];
179  }
180 }
181 
182 
183 static void enlarge_roq_mb4(uint8_t base[3*16], uint8_t u[3*64])
184 {
185  int x,y,cp;
186 
187  for(cp=0; cp<3; cp++)
188  for(y=0; y<8; y++)
189  for(x=0; x<8; x++)
190  *u++ = base[(y/2)*4 + (x/2) + 16*cp];
191 }
192 
193 static inline int square(int x)
194 {
195  return x*x;
196 }
197 
198 static inline int eval_sse(const uint8_t *a, const uint8_t *b, int count)
199 {
200  int diff=0;
201 
202  while(count--)
203  diff += square(*b++ - *a++);
204 
205  return diff;
206 }
207 
208 // FIXME Could use DSPContext.sse, but it is not so speed critical (used
209 // just for motion estimation).
210 static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y1,
211  int x2, int y2, const int *stride1, const int *stride2, int size)
212 {
213  int i, k;
214  int sse=0;
215 
216  for (k=0; k<3; k++) {
217  int bias = (k ? CHROMA_BIAS : 4);
218  for (i=0; i<size; i++)
219  sse += bias*eval_sse(buf1[k] + (y1+i)*stride1[k] + x1,
220  buf2[k] + (y2+i)*stride2[k] + x2, size);
221  }
222 
223  return sse;
224 }
225 
226 static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect,
227  int size)
228 {
229  RoqContext *const roq = &enc->common;
230  int mx=vect.d[0];
231  int my=vect.d[1];
232 
233  if (mx < -7 || mx > 7)
234  return INT_MAX;
235 
236  if (my < -7 || my > 7)
237  return INT_MAX;
238 
239  mx += x;
240  my += y;
241 
242  if ((unsigned) mx > roq->width-size || (unsigned) my > roq->height-size)
243  return INT_MAX;
244 
245  return block_sse(enc->frame_to_enc->data, roq->last_frame->data, x, y,
246  mx, my,
248  size);
249 }
250 
251 /**
252  * @return distortion between two macroblocks
253  */
254 static inline int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
255 {
256  int cp, sdiff=0;
257 
258  for(cp=0;cp<3;cp++) {
259  int bias = (cp ? CHROMA_BIAS : 4);
260  sdiff += bias*eval_sse(a, b, size*size);
261  a += size*size;
262  b += size*size;
263  }
264 
265  return sdiff;
266 }
267 
268 /**
269  * Initialize cel evaluators and set their source coordinates
270  */
272 {
273  RoqContext *const roq = &enc->common;
274 
275  enc->cel_evals = av_malloc_array(roq->width * roq->height / 64, sizeof(CelEvaluation));
276  if (!enc->cel_evals)
277  return AVERROR(ENOMEM);
278 
279  /* Map to the ROQ quadtree order */
280  for (int y = 0, n = 0; y < roq->height; y += 16)
281  for (int x = 0; x < roq->width; x += 16)
282  for(int i = 0; i < 4; i++) {
283  enc->cel_evals[n ].sourceX = x + (i&1)*8;
284  enc->cel_evals[n++].sourceY = y + (i&2)*4;
285  }
286 
287  return 0;
288 }
289 
290 /**
291  * Get macroblocks from parts of the image
292  */
293 static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim)
294 {
295  int i, j, cp;
296 
297  for (cp=0; cp<3; cp++) {
298  int stride = frame->linesize[cp];
299  for (i=0; i<dim; i++)
300  for (j=0; j<dim; j++)
301  *mb++ = frame->data[cp][(y+i)*stride + x + j];
302  }
303 }
304 
305 /**
306  * Find the codebook with the lowest distortion from an image
307  */
308 static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB,
309  int *outIndex, int dim)
310 {
311  int i, lDiff = INT_MAX, pick=0;
312 
313  /* Diff against the others */
314  for (i=0; i<numCB; i++) {
315  int diff = squared_diff_macroblock(cluster, cb + i*dim*dim*3, dim);
316  if (diff < lDiff) {
317  lDiff = diff;
318  pick = i;
319  }
320  }
321 
322  *outIndex = pick;
323  return lDiff;
324 }
325 
326 #define EVAL_MOTION(MOTION) \
327  do { \
328  diff = eval_motion_dist(enc, j, i, MOTION, blocksize); \
329  \
330  if (diff < lowestdiff) { \
331  lowestdiff = diff; \
332  bestpick = MOTION; \
333  } \
334  } while(0)
335 
336 static void motion_search(RoqEncContext *enc, int blocksize)
337 {
338  static const motion_vect offsets[8] = {
339  {{ 0,-1}},
340  {{ 0, 1}},
341  {{-1, 0}},
342  {{ 1, 0}},
343  {{-1, 1}},
344  {{ 1,-1}},
345  {{-1,-1}},
346  {{ 1, 1}},
347  };
348 
349  RoqContext *const roq = &enc->common;
350  int diff, lowestdiff, oldbest;
351  int off[3];
352  motion_vect bestpick = {{0,0}};
353  int i, j, k, offset;
354 
355  motion_vect *last_motion;
356  motion_vect *this_motion;
357  motion_vect vect, vect2;
358  const int max = (roq->width / blocksize) * roq->height / blocksize;
359 
360  if (blocksize == 4) {
361  last_motion = enc->last_motion4;
362  this_motion = enc->this_motion4;
363  } else {
364  last_motion = enc->last_motion8;
365  this_motion = enc->this_motion8;
366  }
367 
368  for (i = 0; i< roq->height; i += blocksize)
369  for (j = 0; j < roq->width; j += blocksize) {
370  lowestdiff = eval_motion_dist(enc, j, i, (motion_vect) {{0,0}},
371  blocksize);
372  bestpick.d[0] = 0;
373  bestpick.d[1] = 0;
374 
375  if (blocksize == 4)
376  EVAL_MOTION(enc->this_motion8[(i/8) * (roq->width/8) + j/8]);
377 
378  offset = (i/blocksize) * roq->width / blocksize + j / blocksize;
379  if (offset < max && offset >= 0)
380  EVAL_MOTION(last_motion[offset]);
381 
382  offset++;
383  if (offset < max && offset >= 0)
384  EVAL_MOTION(last_motion[offset]);
385 
386  offset = (i/blocksize + 1) * roq->width / blocksize + j / blocksize;
387  if (offset < max && offset >= 0)
388  EVAL_MOTION(last_motion[offset]);
389 
390  off[0]= (i/blocksize) * roq->width / blocksize + j/blocksize - 1;
391  off[1]= off[0] - roq->width / blocksize + 1;
392  off[2]= off[1] + 1;
393 
394  if (i) {
395 
396  for(k=0; k<2; k++)
397  vect.d[k]= mid_pred(this_motion[off[0]].d[k],
398  this_motion[off[1]].d[k],
399  this_motion[off[2]].d[k]);
400 
401  EVAL_MOTION(vect);
402  for(k=0; k<3; k++)
403  EVAL_MOTION(this_motion[off[k]]);
404  } else if(j)
405  EVAL_MOTION(this_motion[off[0]]);
406 
407  vect = bestpick;
408 
409  oldbest = -1;
410  while (oldbest != lowestdiff) {
411  oldbest = lowestdiff;
412  for (k=0; k<8; k++) {
413  vect2 = vect;
414  vect2.d[0] += offsets[k].d[0];
415  vect2.d[1] += offsets[k].d[1];
416  EVAL_MOTION(vect2);
417  }
418  vect = bestpick;
419  }
420  offset = (i/blocksize) * roq->width / blocksize + j/blocksize;
421  this_motion[offset] = bestpick;
422  }
423 }
424 
425 /**
426  * Get distortion for all options available to a subcel
427  */
428 static void gather_data_for_subcel(SubcelEvaluation *subcel, int x,
429  int y, RoqEncContext *enc)
430 {
431  RoqContext *const roq = &enc->common;
432  RoqTempData *const tempData = &enc->tmp_data;
433  uint8_t mb4[4*4*3];
434  uint8_t mb2[2*2*3];
435  int cluster_index;
436  int i, best_dist;
437 
438  static const int bitsUsed[4] = {2, 10, 10, 34};
439 
440  if (enc->framesSinceKeyframe >= 1) {
441  subcel->motion = enc->this_motion4[y * roq->width / 16 + x / 4];
442 
443  subcel->eval_dist[RoQ_ID_FCC] =
444  eval_motion_dist(enc, x, y,
445  enc->this_motion4[y * roq->width / 16 + x / 4], 4);
446  } else
447  subcel->eval_dist[RoQ_ID_FCC] = INT_MAX;
448 
449  if (enc->framesSinceKeyframe >= 2)
451  roq->current_frame->data, x,
452  y, x, y,
453  enc->frame_to_enc->linesize,
454  roq->current_frame->linesize,
455  4);
456  else
457  subcel->eval_dist[RoQ_ID_MOT] = INT_MAX;
458 
459  cluster_index = y * roq->width / 16 + x / 4;
460 
461  get_frame_mb(enc->frame_to_enc, x, y, mb4, 4);
462 
463  subcel->eval_dist[RoQ_ID_SLD] = index_mb(mb4,
464  tempData->codebooks.unpacked_cb4,
465  tempData->codebooks.numCB4,
466  &subcel->cbEntry, 4);
467 
468  subcel->eval_dist[RoQ_ID_CCC] = 0;
469 
470  for(i=0;i<4;i++) {
471  subcel->subCels[i] = enc->closest_cb[cluster_index*4+i];
472 
473  get_frame_mb(enc->frame_to_enc, x+2*(i&1),
474  y+(i&2), mb2, 2);
475 
476  subcel->eval_dist[RoQ_ID_CCC] +=
477  squared_diff_macroblock(tempData->codebooks.unpacked_cb2 + subcel->subCels[i]*2*2*3, mb2, 2);
478  }
479 
480  best_dist = INT_MAX;
481  for (i=0; i<4; i++)
482  if (ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + enc->lambda*bitsUsed[i] <
483  best_dist) {
484  subcel->best_coding = i;
485  subcel->best_bit_use = bitsUsed[i];
486  best_dist = ROQ_LAMBDA_SCALE*subcel->eval_dist[i] +
487  enc->lambda*bitsUsed[i];
488  }
489 }
490 
491 /**
492  * Get distortion for all options available to a cel
493  */
495 {
496  RoqContext *const roq = &enc->common;
497  RoqTempData *const tempData = &enc->tmp_data;
498  uint8_t mb8[8*8*3];
499  int index = cel->sourceY * roq->width / 64 + cel->sourceX/8;
500  int i, j, best_dist, divide_bit_use;
501 
502  int bitsUsed[4] = {2, 10, 10, 0};
503 
504  if (enc->framesSinceKeyframe >= 1) {
505  cel->motion = enc->this_motion8[index];
506 
507  cel->eval_dist[RoQ_ID_FCC] =
508  eval_motion_dist(enc, cel->sourceX, cel->sourceY,
509  enc->this_motion8[index], 8);
510  } else
511  cel->eval_dist[RoQ_ID_FCC] = INT_MAX;
512 
513  if (enc->framesSinceKeyframe >= 2)
515  roq->current_frame->data,
516  cel->sourceX, cel->sourceY,
517  cel->sourceX, cel->sourceY,
518  enc->frame_to_enc->linesize,
519  roq->current_frame->linesize,8);
520  else
521  cel->eval_dist[RoQ_ID_MOT] = INT_MAX;
522 
523  get_frame_mb(enc->frame_to_enc, cel->sourceX, cel->sourceY, mb8, 8);
524 
525  cel->eval_dist[RoQ_ID_SLD] =
527  tempData->codebooks.numCB4, &cel->cbEntry, 8);
528 
529  gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc);
530  gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc);
531  gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc);
532  gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc);
533 
534  cel->eval_dist[RoQ_ID_CCC] = 0;
535  divide_bit_use = 0;
536  for (i=0; i<4; i++) {
537  cel->eval_dist[RoQ_ID_CCC] +=
538  cel->subCels[i].eval_dist[cel->subCels[i].best_coding];
539  divide_bit_use += cel->subCels[i].best_bit_use;
540  }
541 
542  best_dist = INT_MAX;
543  bitsUsed[3] = 2 + divide_bit_use;
544 
545  for (i=0; i<4; i++)
546  if (ROQ_LAMBDA_SCALE*cel->eval_dist[i] + enc->lambda*bitsUsed[i] <
547  best_dist) {
548  cel->best_coding = i;
549  best_dist = ROQ_LAMBDA_SCALE*cel->eval_dist[i] +
550  enc->lambda*bitsUsed[i];
551  }
552 
553  tempData->used_option[cel->best_coding]++;
554  tempData->mainChunkSize += bitsUsed[cel->best_coding];
555 
556  if (cel->best_coding == RoQ_ID_SLD)
557  tempData->codebooks.usedCB4[cel->cbEntry]++;
558 
559  if (cel->best_coding == RoQ_ID_CCC)
560  for (i=0; i<4; i++) {
561  if (cel->subCels[i].best_coding == RoQ_ID_SLD)
562  tempData->codebooks.usedCB4[cel->subCels[i].cbEntry]++;
563  else if (cel->subCels[i].best_coding == RoQ_ID_CCC)
564  for (j=0; j<4; j++)
565  tempData->codebooks.usedCB2[cel->subCels[i].subCels[j]]++;
566  }
567 }
568 
570 {
571  RoqContext *const roq = &enc->common;
572  RoqTempData *const tempData = &enc->tmp_data;
573  int i, j, idx=0;
574 
575  /* Make remaps for the final codebook usage */
576  for (i=0; i<(enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); i++) {
577  if (tempData->codebooks.usedCB4[i]) {
578  tempData->i2f4[i] = idx;
579  tempData->f2i4[idx] = i;
580  for (j=0; j<4; j++)
581  tempData->codebooks.usedCB2[roq->cb4x4[i].idx[j]]++;
582  idx++;
583  }
584  }
585 
586  tempData->numCB4 = idx;
587 
588  idx = 0;
589  for (i=0; i<MAX_CBS_2x2; i++) {
590  if (tempData->codebooks.usedCB2[i]) {
591  tempData->i2f2[i] = idx;
592  tempData->f2i2[idx] = i;
593  idx++;
594  }
595  }
596  tempData->numCB2 = idx;
597 
598 }
599 
600 /**
601  * Write codebook chunk
602  */
604 {
605  RoqContext *const roq = &enc->common;
606  RoqTempData *const tempData = &enc->tmp_data;
607  int i, j;
608  uint8_t **outp= &enc->out_buf;
609 
610  if (tempData->numCB2) {
611  bytestream_put_le16(outp, RoQ_QUAD_CODEBOOK);
612  bytestream_put_le32(outp, tempData->numCB2*6 + tempData->numCB4*4);
613  bytestream_put_byte(outp, tempData->numCB4);
614  bytestream_put_byte(outp, tempData->numCB2);
615 
616  for (i=0; i<tempData->numCB2; i++) {
617  bytestream_put_buffer(outp, roq->cb2x2[tempData->f2i2[i]].y, 4);
618  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].u);
619  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].v);
620  }
621 
622  for (i=0; i<tempData->numCB4; i++)
623  for (j=0; j<4; j++)
624  bytestream_put_byte(outp, tempData->i2f2[roq->cb4x4[tempData->f2i4[i]].idx[j]]);
625 
626  }
627 }
628 
629 static inline uint8_t motion_arg(motion_vect mot)
630 {
631  uint8_t ax = 8 - ((uint8_t) mot.d[0]);
632  uint8_t ay = 8 - ((uint8_t) mot.d[1]);
633  return ((ax&15)<<4) | (ay&15);
634 }
635 
636 typedef struct CodingSpool {
639  uint8_t argumentSpool[64];
640  uint8_t *args;
641  uint8_t **pout;
642 } CodingSpool;
643 
644 /* NOTE: Typecodes must be spooled AFTER arguments!! */
645 static void write_typecode(CodingSpool *s, uint8_t type)
646 {
647  s->typeSpool |= (type & 3) << (14 - s->typeSpoolLength);
648  s->typeSpoolLength += 2;
649  if (s->typeSpoolLength == 16) {
650  bytestream_put_le16(s->pout, s->typeSpool);
651  bytestream_put_buffer(s->pout, s->argumentSpool,
652  s->args - s->argumentSpool);
653  s->typeSpoolLength = 0;
654  s->typeSpool = 0;
655  s->args = s->argumentSpool;
656  }
657 }
658 
660  int w, int h, int numBlocks)
661 {
662  RoqContext *const roq = &enc->common;
663  RoqTempData *const tempData = &enc->tmp_data;
664  int i, j, k;
665  int x, y;
666  int subX, subY;
667  int dist=0;
668 
669  roq_qcell *qcell;
670  CelEvaluation *eval;
671 
672  CodingSpool spool;
673 
674  spool.typeSpool=0;
675  spool.typeSpoolLength=0;
676  spool.args = spool.argumentSpool;
677  spool.pout = &enc->out_buf;
678 
679  if (tempData->used_option[RoQ_ID_CCC]%2)
680  tempData->mainChunkSize+=8; //FIXME
681 
682  /* Write the video chunk header */
683  bytestream_put_le16(&enc->out_buf, RoQ_QUAD_VQ);
684  bytestream_put_le32(&enc->out_buf, tempData->mainChunkSize/8);
685  bytestream_put_byte(&enc->out_buf, 0x0);
686  bytestream_put_byte(&enc->out_buf, 0x0);
687 
688  for (i=0; i<numBlocks; i++) {
689  eval = enc->cel_evals + i;
690 
691  x = eval->sourceX;
692  y = eval->sourceY;
693  dist += eval->eval_dist[eval->best_coding];
694 
695  switch (eval->best_coding) {
696  case RoQ_ID_MOT:
697  write_typecode(&spool, RoQ_ID_MOT);
698  break;
699 
700  case RoQ_ID_FCC:
701  bytestream_put_byte(&spool.args, motion_arg(eval->motion));
702 
703  write_typecode(&spool, RoQ_ID_FCC);
704  ff_apply_motion_8x8(roq, x, y,
705  eval->motion.d[0], eval->motion.d[1]);
706  break;
707 
708  case RoQ_ID_SLD:
709  bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]);
710  write_typecode(&spool, RoQ_ID_SLD);
711 
712  qcell = roq->cb4x4 + eval->cbEntry;
713  ff_apply_vector_4x4(roq, x , y , roq->cb2x2 + qcell->idx[0]);
714  ff_apply_vector_4x4(roq, x+4, y , roq->cb2x2 + qcell->idx[1]);
715  ff_apply_vector_4x4(roq, x , y+4, roq->cb2x2 + qcell->idx[2]);
716  ff_apply_vector_4x4(roq, x+4, y+4, roq->cb2x2 + qcell->idx[3]);
717  break;
718 
719  case RoQ_ID_CCC:
720  write_typecode(&spool, RoQ_ID_CCC);
721 
722  for (j=0; j<4; j++) {
723  subX = x + 4*(j&1);
724  subY = y + 2*(j&2);
725 
726  switch(eval->subCels[j].best_coding) {
727  case RoQ_ID_MOT:
728  break;
729 
730  case RoQ_ID_FCC:
731  bytestream_put_byte(&spool.args,
732  motion_arg(eval->subCels[j].motion));
733 
734  ff_apply_motion_4x4(roq, subX, subY,
735  eval->subCels[j].motion.d[0],
736  eval->subCels[j].motion.d[1]);
737  break;
738 
739  case RoQ_ID_SLD:
740  bytestream_put_byte(&spool.args,
741  tempData->i2f4[eval->subCels[j].cbEntry]);
742 
743  qcell = roq->cb4x4 + eval->subCels[j].cbEntry;
744 
745  ff_apply_vector_2x2(roq, subX , subY ,
746  roq->cb2x2 + qcell->idx[0]);
747  ff_apply_vector_2x2(roq, subX+2, subY ,
748  roq->cb2x2 + qcell->idx[1]);
749  ff_apply_vector_2x2(roq, subX , subY+2,
750  roq->cb2x2 + qcell->idx[2]);
751  ff_apply_vector_2x2(roq, subX+2, subY+2,
752  roq->cb2x2 + qcell->idx[3]);
753  break;
754 
755  case RoQ_ID_CCC:
756  for (k=0; k<4; k++) {
757  int cb_idx = eval->subCels[j].subCels[k];
758  bytestream_put_byte(&spool.args,
759  tempData->i2f2[cb_idx]);
760 
761  ff_apply_vector_2x2(roq, subX + 2*(k&1), subY + (k&2),
762  roq->cb2x2 + cb_idx);
763  }
764  break;
765  }
766  write_typecode(&spool, eval->subCels[j].best_coding);
767  }
768  break;
769  }
770  }
771 
772  /* Flush the remainder of the argument/type spool */
773  while (spool.typeSpoolLength)
774  write_typecode(&spool, 0x0);
775 }
776 
777 
778 /**
779  * Create a single YUV cell from a 2x2 section of the image
780  */
781 static inline void frame_block_to_cell(int *block, uint8_t * const *data,
782  int top, int left, const int *stride)
783 {
784  int i, j, u=0, v=0;
785 
786  for (i=0; i<2; i++)
787  for (j=0; j<2; j++) {
788  int x = (top+i)*stride[0] + left + j;
789  *block++ = data[0][x];
790  x = (top+i)*stride[1] + left + j;
791  u += data[1][x];
792  v += data[2][x];
793  }
794 
795  *block++ = (u + 2) / 4 * CHROMA_BIAS;
796  *block++ = (v + 2) / 4 * CHROMA_BIAS;
797 }
798 
799 /**
800  * Create YUV clusters for the entire image
801  */
802 static void create_clusters(const AVFrame *frame, int w, int h, int *points)
803 {
804  int i, j, k, l;
805 
806  for (i=0; i<h; i+=4)
807  for (j=0; j<w; j+=4) {
808  for (k=0; k < 2; k++)
809  for (l=0; l < 2; l++)
810  frame_block_to_cell(points + (l + 2*k)*6, frame->data,
811  i+2*k, j+2*l, frame->linesize);
812  points += 24;
813  }
814 }
815 
817  int *points, int inputCount, roq_cell *results,
818  int size, int cbsize)
819 {
820  int i, j, k, ret = 0;
821  int c_size = size*size/4;
822  int *buf;
823  int *codebook = enc->tmp_codebook_buf;
824  int *closest_cb = enc->closest_cb;
825 
826  ret = avpriv_init_elbg(points, 6 * c_size, inputCount, codebook,
827  cbsize, 1, closest_cb, &enc->randctx);
828  if (ret < 0)
829  return ret;
830  ret = avpriv_do_elbg(points, 6 * c_size, inputCount, codebook,
831  cbsize, 1, closest_cb, &enc->randctx);
832  if (ret < 0)
833  return ret;
834 
835  buf = codebook;
836  for (i=0; i<cbsize; i++)
837  for (k=0; k<c_size; k++) {
838  for(j=0; j<4; j++)
839  results->y[j] = *buf++;
840 
841  results->u = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
842  results->v = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
843  results++;
844  }
845  return 0;
846 }
847 
849 {
850  int i, j, ret = 0;
852  RoqContext *const roq = &enc->common;
853  int max = roq->width * roq->height / 16;
854  uint8_t mb2[3*4];
855  int *points = enc->points;
856 
857  /* Subsample YUV data */
858  create_clusters(enc->frame_to_enc, roq->width, roq->height, points);
859 
860  codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4);
861 
862  /* Create 4x4 codebooks */
863  if ((ret = generate_codebook(enc, points, max, enc->results4,
864  4, codebooks->numCB4)) < 0)
865  return ret;
866 
867  /* Create 2x2 codebooks */
868  if ((ret = generate_codebook(enc, points, max * 4,
869  roq->cb2x2, 2, MAX_CBS_2x2)) < 0)
870  return ret;
871 
872  codebooks->numCB2 = MAX_CBS_2x2;
873 
874  /* Unpack 2x2 codebook clusters */
875  for (i=0; i<codebooks->numCB2; i++)
876  unpack_roq_cell(roq->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3);
877 
878  /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */
879  for (i=0; i<codebooks->numCB4; i++) {
880  for (j=0; j<4; j++) {
881  unpack_roq_cell(&enc->results4[4*i + j], mb2);
882  index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2,
883  &roq->cb4x4[i].idx[j], 2);
884  }
885  unpack_roq_qcell(codebooks->unpacked_cb2, roq->cb4x4 + i,
886  codebooks->unpacked_cb4 + i*4*4*3);
887  enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3,
888  codebooks->unpacked_cb4_enlarged + i*8*8*3);
889  }
890 
891  return 0;
892 }
893 
895 {
896  RoqTempData *const tempData = &enc->tmp_data;
897  RoqContext *const roq = &enc->common;
898  int ret;
899 
900  memset(tempData, 0, sizeof(*tempData));
901 
903  if (ret < 0)
904  return ret;
905 
906  if (enc->framesSinceKeyframe >= 1) {
907  motion_search(enc, 8);
908  motion_search(enc, 4);
909  }
910 
911  retry_encode:
912  for (int i = 0; i < roq->width * roq->height / 64; i++)
913  gather_data_for_cel(enc->cel_evals + i, enc);
914 
915  /* Quake 3 can't handle chunks bigger than 65535 bytes */
916  if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
917  if (enc->lambda > 100000) {
918  av_log(roq->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
919  return AVERROR(EINVAL);
920  }
921  av_log(roq->avctx, AV_LOG_ERROR,
922  "Warning, generated a frame too big for Quake (%d > 65535), "
923  "now switching to a bigger qscale value.\n",
924  tempData->mainChunkSize/8);
925  enc->lambda *= 1.5;
926  tempData->mainChunkSize = 0;
927  memset(tempData->used_option, 0, sizeof(tempData->used_option));
928  memset(tempData->codebooks.usedCB4, 0,
929  sizeof(tempData->codebooks.usedCB4));
930  memset(tempData->codebooks.usedCB2, 0,
931  sizeof(tempData->codebooks.usedCB2));
932 
933  goto retry_encode;
934  }
935 
936  remap_codebooks(enc);
937 
938  write_codebooks(enc);
939 
940  reconstruct_and_encode_image(enc, roq->width, roq->height,
941  roq->width * roq->height / 64);
942 
943  /* Rotate frame history */
944  FFSWAP(AVFrame *, roq->current_frame, roq->last_frame);
947 
948  enc->framesSinceKeyframe++;
949 
950  return 0;
951 }
952 
954 {
955  RoqEncContext *const enc = avctx->priv_data;
956 
959 
960  av_freep(&enc->cel_evals);
961  av_freep(&enc->closest_cb);
962  av_freep(&enc->this_motion4);
963  av_freep(&enc->last_motion4);
964  av_freep(&enc->this_motion8);
965  av_freep(&enc->last_motion8);
966 
967  return 0;
968 }
969 
971 {
972  RoqEncContext *const enc = avctx->priv_data;
973  RoqContext *const roq = &enc->common;
974 
975  av_lfg_init(&enc->randctx, 1);
976 
977  roq->avctx = avctx;
978 
979  enc->framesSinceKeyframe = 0;
980  if ((avctx->width & 0xf) || (avctx->height & 0xf)) {
981  av_log(avctx, AV_LOG_ERROR, "Dimensions must be divisible by 16\n");
982  return AVERROR(EINVAL);
983  }
984 
985  if (avctx->width > 65535 || avctx->height > 65535) {
986  av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc->quake3_compat ? 32768 : 65535);
987  return AVERROR(EINVAL);
988  }
989 
990  if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
991  av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n");
992 
993  roq->width = avctx->width;
994  roq->height = avctx->height;
995 
996  enc->framesSinceKeyframe = 0;
997  enc->first_frame = 1;
998 
999  roq->last_frame = av_frame_alloc();
1000  roq->current_frame = av_frame_alloc();
1001  if (!roq->last_frame || !roq->current_frame)
1002  return AVERROR(ENOMEM);
1003 
1004  enc->this_motion4 =
1005  av_mallocz_array(roq->width * roq->height / 16, sizeof(motion_vect));
1006 
1007  enc->last_motion4 =
1008  av_malloc_array (roq->width * roq->height / 16, sizeof(motion_vect));
1009 
1010  enc->this_motion8 =
1011  av_mallocz_array(roq->width * roq->height / 64, sizeof(motion_vect));
1012 
1013  enc->last_motion8 =
1014  av_malloc_array (roq->width * roq->height / 64, sizeof(motion_vect));
1015 
1016  /* 4x4 codebook needs 6 * 4 * 4 / 4 * width * height / 16 * sizeof(int);
1017  * and so does the points buffer. */
1018  enc->closest_cb =
1019  av_malloc_array(roq->width * roq->height, 3 * sizeof(int));
1020 
1021  if (!enc->this_motion4 || !enc->last_motion4 ||
1022  !enc->this_motion8 || !enc->last_motion8 || !enc->closest_cb)
1023  return AVERROR(ENOMEM);
1024 
1025  enc->points = enc->closest_cb + roq->width * roq->height * 3 / 2;
1026 
1027  return create_cel_evals(enc);
1028 }
1029 
1031 {
1032  /* ROQ info chunk */
1033  bytestream_put_le16(&enc->out_buf, RoQ_INFO);
1034 
1035  /* Size: 8 bytes */
1036  bytestream_put_le32(&enc->out_buf, 8);
1037 
1038  /* Unused argument */
1039  bytestream_put_byte(&enc->out_buf, 0x00);
1040  bytestream_put_byte(&enc->out_buf, 0x00);
1041 
1042  /* Width */
1043  bytestream_put_le16(&enc->out_buf, enc->common.width);
1044 
1045  /* Height */
1046  bytestream_put_le16(&enc->out_buf, enc->common.height);
1047 
1048  /* Unused in Quake 3, mimics the output of the real encoder */
1049  bytestream_put_byte(&enc->out_buf, 0x08);
1050  bytestream_put_byte(&enc->out_buf, 0x00);
1051  bytestream_put_byte(&enc->out_buf, 0x04);
1052  bytestream_put_byte(&enc->out_buf, 0x00);
1053 }
1054 
1056  const AVFrame *frame, int *got_packet)
1057 {
1058  RoqEncContext *const enc = avctx->priv_data;
1059  RoqContext *const roq = &enc->common;
1060  int size, ret;
1061 
1062  roq->avctx = avctx;
1063 
1064  enc->frame_to_enc = frame;
1065 
1066  if (frame->quality)
1067  enc->lambda = frame->quality - 1;
1068  else
1069  enc->lambda = 2*ROQ_LAMBDA_SCALE;
1070 
1071  /* 138 bits max per 8x8 block +
1072  * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
1073  size = ((roq->width * roq->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8;
1074  if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0)
1075  return ret;
1076  enc->out_buf = pkt->data;
1077 
1078  /* Check for I-frame */
1079  if (enc->framesSinceKeyframe == avctx->gop_size)
1080  enc->framesSinceKeyframe = 0;
1081 
1082  if (enc->first_frame) {
1083  /* Alloc memory for the reconstruction data (we must know the stride
1084  for that) */
1085  if ((ret = ff_get_buffer(avctx, roq->current_frame, 0)) < 0 ||
1086  (ret = ff_get_buffer(avctx, roq->last_frame, 0)) < 0)
1087  return ret;
1088 
1089  /* Before the first video frame, write a "video info" chunk */
1091 
1092  enc->first_frame = 0;
1093  }
1094 
1095  /* Encode the actual frame */
1096  ret = roq_encode_video(enc);
1097  if (ret < 0)
1098  return ret;
1099 
1100  pkt->size = enc->out_buf - pkt->data;
1101  if (enc->framesSinceKeyframe == 1)
1103  *got_packet = 1;
1104 
1105  return 0;
1106 }
1107 
1108 #define OFFSET(x) offsetof(RoqEncContext, x)
1109 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1110 static const AVOption options[] = {
1111  { "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
1112  { NULL },
1113 };
1114 
1115 static const AVClass roq_class = {
1116  .class_name = "RoQ",
1117  .item_name = av_default_item_name,
1118  .option = options,
1119  .version = LIBAVUTIL_VERSION_INT,
1120 };
1121 
1123  .name = "roqvideo",
1124  .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
1125  .type = AVMEDIA_TYPE_VIDEO,
1126  .id = AV_CODEC_ID_ROQ,
1127  .priv_data_size = sizeof(RoqEncContext),
1128  .init = roq_encode_init,
1129  .encode2 = roq_encode_frame,
1130  .close = roq_encode_end,
1131  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P,
1132  AV_PIX_FMT_NONE },
1133  .priv_class = &roq_class,
1135 };
AVCodec
AVCodec.
Definition: codec.h:197
stride
int stride
Definition: mace.c:144
RoqCodebooks
Definition: roqvideoenc.c:81
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:41
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
RoqContext::cb4x4
roq_qcell cb4x4[256]
Definition: roqvideo.h:48
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
opt.h
roqvideo.h
RoQ_ID_SLD
#define RoQ_ID_SLD
Definition: roqvideo.h:59
RoqCodebooks::usedCB4
int usedCB4[MAX_CBS_4x4]
Definition: roqvideoenc.c:85
FFSWAP
#define FFSWAP(type, a, b)
Definition: common.h:108
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:215
RoqContext::current_frame
AVFrame * current_frame
Definition: roqvideo.h:44
CodingSpool::argumentSpool
uint8_t argumentSpool[64]
Definition: roqvideoenc.c:639
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:264
VE
#define VE
Definition: roqvideoenc.c:1109
RoqCodebooks::unpacked_cb4
uint8_t unpacked_cb4[MAX_CBS_4x4 *4 *4 *3]
Definition: roqvideoenc.c:87
write_typecode
static void write_typecode(CodingSpool *s, uint8_t type)
Definition: roqvideoenc.c:645
SubcelEvaluation
Definition: roqvideoenc.c:111
RoqCodebooks::unpacked_cb2
uint8_t unpacked_cb2[MAX_CBS_2x2 *2 *2 *3]
Definition: roqvideoenc.c:86
RoqEncContext::tmp_codebook_buf
int tmp_codebook_buf[FFMAX(24 *MAX_CBS_4x4, 6 *MAX_CBS_2x2)]
Definition: roqvideoenc.c:150
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:111
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
RoqContext
Definition: roqvideo.h:40
index
fg index
Definition: ffmpeg_filter.c:168
w
uint8_t w
Definition: llviddspenc.c:39
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:365
ROQ_LAMBDA_SCALE
#define ROQ_LAMBDA_SCALE
Definition: roqvideoenc.c:79
roq_cell::y
unsigned char y[4]
Definition: roqvideo.h:28
RoqTempData::f2i4
int f2i4[MAX_CBS_4x4]
Definition: roqvideoenc.c:96
RoqContext::avctx
AVCodecContext * avctx
Definition: roqvideo.h:42
RoqCodebooks::unpacked_cb4_enlarged
uint8_t unpacked_cb4_enlarged[MAX_CBS_4x4 *8 *8 *3]
Definition: roqvideoenc.c:88
AVOption
AVOption.
Definition: opt.h:248
b
#define b
Definition: input.c:41
RoQ_ID_FCC
#define RoQ_ID_FCC
Definition: roqvideo.h:58
codebooks
static const uint8_t codebooks[]
Definition: vorbis_enc_data.h:26
data
const char data[16]
Definition: mxf.c:142
unpack_roq_qcell
static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4 *4 *3])
Definition: roqvideoenc.c:168
CelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:127
ff_apply_motion_8x8
void ff_apply_motion_8x8(RoqContext *ri, int x, int y, int deltax, int deltay)
Definition: roqvideo.c:139
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:196
roq_cell
Definition: roqvideo.h:27
base
uint8_t base
Definition: vp3data.h:141
unpack_roq_cell
static void unpack_roq_cell(roq_cell *cell, uint8_t u[4 *3])
Definition: roqvideoenc.c:161
max
#define max(a, b)
Definition: cuda_runtime.h:33
motion_search
static void motion_search(RoqEncContext *enc, int blocksize)
Definition: roqvideoenc.c:336
RoqTempData::mainChunkSize
int mainChunkSize
Definition: roqvideoenc.c:101
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:396
SubcelEvaluation::subCels
int subCels[4]
Definition: roqvideoenc.c:116
RoqEncContext::last_motion8
motion_vect * last_motion8
Definition: roqvideoenc.c:142
RoqContext::height
int height
Definition: roqvideo.h:45
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
write_codebooks
static void write_codebooks(RoqEncContext *enc)
Write codebook chunk.
Definition: roqvideoenc.c:603
RoqTempData::i2f4
int i2f4[MAX_CBS_4x4]
Definition: roqvideoenc.c:97
type
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 type
Definition: writing_filters.txt:86
RoQ_ID_CCC
#define RoQ_ID_CCC
Definition: roqvideo.h:60
SubcelEvaluation::eval_dist
int eval_dist[4]
Definition: roqvideoenc.c:112
CelEvaluation::best_coding
int best_coding
Definition: roqvideoenc.c:123
CodingSpool::typeSpool
int typeSpool
Definition: roqvideoenc.c:637
RoqEncContext::points
int * points
Definition: roqvideoenc.c:154
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:98
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:181
av_cold
#define av_cold
Definition: attributes.h:90
ff_apply_vector_2x2
void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
Definition: roqvideo.c:41
RoqEncContext::framesSinceKeyframe
unsigned int framesSinceKeyframe
Definition: roqvideoenc.c:144
s
#define s(width, name)
Definition: cbs_vp9.c:257
RoqEncContext::this_motion4
motion_vect * this_motion4
Definition: roqvideoenc.c:138
motion_arg
static uint8_t motion_arg(motion_vect mot)
Definition: roqvideoenc.c:629
RoQ_QUAD_CODEBOOK
#define RoQ_QUAD_CODEBOOK
Definition: roqvideo.h:52
RoqCodebooks::numCB2
int numCB2
Definition: roqvideoenc.c:83
offsets
static const int offsets[]
Definition: hevc_pel.c:34
roq_encode_video
static int roq_encode_video(RoqEncContext *enc)
Definition: roqvideoenc.c:894
RoQ_ID_MOT
#define RoQ_ID_MOT
Definition: roqvideo.h:57
motion_vect
Definition: roqvideo.h:36
SubcelEvaluation::cbEntry
int cbEntry
Definition: roqvideoenc.c:118
sse
static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride)
Definition: mpegvideo_enc.c:2558
lfg.h
CelEvaluation::cbEntry
int cbEntry
Definition: roqvideoenc.c:128
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:289
RoqEncContext::frame_to_enc
const AVFrame * frame_to_enc
Definition: roqvideoenc.c:146
RoqEncContext
Definition: roqvideoenc.c:133
CodingSpool::args
uint8_t * args
Definition: roqvideoenc.c:640
RoqEncContext::closest_cb
int * closest_cb
Definition: roqvideoenc.c:153
roq_cell::v
unsigned char v
Definition: roqvideo.h:29
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
gather_data_for_subcel
static void gather_data_for_subcel(SubcelEvaluation *subcel, int x, int y, RoqEncContext *enc)
Get distortion for all options available to a subcel.
Definition: roqvideoenc.c:428
if
if(ret)
Definition: filter_design.txt:179
elbg.h
SubcelEvaluation::best_coding
int best_coding
Definition: roqvideoenc.c:114
generate_codebook
static int generate_codebook(RoqEncContext *enc, int *points, int inputCount, roq_cell *results, int size, int cbsize)
Definition: roqvideoenc.c:816
RoqTempData
Temporary vars.
Definition: roqvideoenc.c:94
CelEvaluation::subCels
SubcelEvaluation subCels[4]
Definition: roqvideoenc.c:125
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
RoqTempData::used_option
int used_option[4]
Definition: roqvideoenc.c:108
index_mb
static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB, int *outIndex, int dim)
Find the codebook with the lowest distortion from an image.
Definition: roqvideoenc.c:308
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
enlarge_roq_mb4
static void enlarge_roq_mb4(uint8_t base[3 *16], uint8_t u[3 *64])
Definition: roqvideoenc.c:183
RoqTempData::codebooks
RoqCodebooks codebooks
Definition: roqvideoenc.c:106
avpriv_init_elbg
int avpriv_init_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Initialize the **codebook vector for the elbg algorithm.
Definition: elbg.c:337
reconstruct_and_encode_image
static void reconstruct_and_encode_image(RoqEncContext *enc, int w, int h, int numBlocks)
Definition: roqvideoenc.c:659
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
mathops.h
RoqEncContext::cel_evals
CelEvaluation * cel_evals
Definition: roqvideoenc.c:152
RoqEncContext::tmp_data
RoqTempData tmp_data
Definition: roqvideoenc.c:148
gather_data_for_cel
static void gather_data_for_cel(CelEvaluation *cel, RoqEncContext *enc)
Get distortion for all options available to a cel.
Definition: roqvideoenc.c:494
RoqTempData::i2f2
int i2f2[MAX_CBS_2x2]
Definition: roqvideoenc.c:99
squared_diff_macroblock
static int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
Definition: roqvideoenc.c:254
roq_qcell
Definition: roqvideo.h:32
CelEvaluation::sourceX
int sourceX
Definition: roqvideoenc.c:130
CelEvaluation::sourceY
int sourceY
Definition: roqvideoenc.c:130
RoqEncContext::common
RoqContext common
Definition: roqvideoenc.c:134
CelEvaluation::eval_dist
int eval_dist[4]
Definition: roqvideoenc.c:122
RoqCodebooks::numCB4
int numCB4
Definition: roqvideoenc.c:82
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
roq_encode_init
static av_cold int roq_encode_init(AVCodecContext *avctx)
Definition: roqvideoenc.c:970
AV_CODEC_ID_ROQ
@ AV_CODEC_ID_ROQ
Definition: codec_id.h:87
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1638
AVPacket::size
int size
Definition: packet.h:366
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:696
MAX_CBS_2x2
#define MAX_CBS_2x2
Maximum number of 2x2 codebooks.
Definition: roqvideoenc.c:76
frame_block_to_cell
static void frame_block_to_cell(int *block, uint8_t *const *data, int top, int left, const int *stride)
Create a single YUV cell from a 2x2 section of the image.
Definition: roqvideoenc.c:781
SubcelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:117
CodingSpool::pout
uint8_t ** pout
Definition: roqvideoenc.c:641
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
get_frame_mb
static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim)
Get macroblocks from parts of the image.
Definition: roqvideoenc.c:293
size
int size
Definition: twinvq_data.h:10344
ff_roq_encoder
const AVCodec ff_roq_encoder
Definition: roqvideoenc.c:1122
EVAL_MOTION
#define EVAL_MOTION(MOTION)
Definition: roqvideoenc.c:326
CHROMA_BIAS
#define CHROMA_BIAS
Definition: roqvideoenc.c:68
ff_apply_vector_4x4
void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
Definition: roqvideo.c:71
RoqEncContext::last_motion4
motion_vect * last_motion4
Definition: roqvideoenc.c:139
RoQ_INFO
#define RoQ_INFO
Definition: roqvideo.h:51
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
RoqEncContext::this_motion8
motion_vect * this_motion8
Definition: roqvideoenc.c:141
roq_encode_end
static av_cold int roq_encode_end(AVCodecContext *avctx)
Definition: roqvideoenc.c:953
roq_write_video_info_chunk
static void roq_write_video_info_chunk(RoqEncContext *enc)
Definition: roqvideoenc.c:1030
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
attributes.h
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:371
mb
#define mb
Definition: vf_colormatrix.c:101
options
static const AVOption options[]
Definition: roqvideoenc.c:1110
generate_new_codebooks
static int generate_new_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:848
roq_qcell::idx
int idx[4]
Definition: roqvideo.h:33
create_clusters
static void create_clusters(const AVFrame *frame, int w, int h, int *points)
Create YUV clusters for the entire image.
Definition: roqvideoenc.c:802
bytestream_put_buffer
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:372
i
int i
Definition: input.c:407
eval_motion_dist
static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect, int size)
Definition: roqvideoenc.c:226
RoqCodebooks::usedCB2
int usedCB2[MAX_CBS_2x2]
Definition: roqvideoenc.c:84
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:49
block_sse
static int block_sse(uint8_t *const *buf1, uint8_t *const *buf2, int x1, int y1, int x2, int y2, const int *stride1, const int *stride2, int size)
Definition: roqvideoenc.c:210
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:664
RoqContext::last_frame
AVFrame * last_frame
Definition: roqvideo.h:43
CodingSpool::typeSpoolLength
int typeSpoolLength
Definition: roqvideoenc.c:638
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:204
AVCodecContext::height
int height
Definition: avcodec.h:674
motion_vect::d
int d[2]
Definition: roqvideo.h:37
MAX_CBS_4x4
#define MAX_CBS_4x4
Maximum number of generated 4x4 codebooks.
Definition: roqvideoenc.c:74
RoqEncContext::out_buf
uint8_t * out_buf
Definition: roqvideoenc.c:147
RoQ_QUAD_VQ
#define RoQ_QUAD_VQ
Definition: roqvideo.h:53
roq_encode_frame
static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Definition: roqvideoenc.c:1055
dim
int dim
Definition: vorbis_enc_data.h:425
mid_pred
#define mid_pred
Definition: mathops.h:97
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
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
square
static int square(int x)
Definition: roqvideoenc.c:193
remap_codebooks
static void remap_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:569
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
AVCodecContext
main external API structure.
Definition: avcodec.h:501
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
create_cel_evals
static int create_cel_evals(RoqEncContext *enc)
Initialize cel evaluators and set their source coordinates.
Definition: roqvideoenc.c:271
ff_apply_motion_4x4
void ff_apply_motion_4x4(RoqContext *ri, int x, int y, int deltax, int deltay)
Definition: roqvideo.c:133
CodingSpool
Definition: roqvideoenc.c:636
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
RoqEncContext::results4
roq_cell results4[4 *MAX_CBS_4x4]
Definition: roqvideoenc.c:149
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:136
OFFSET
#define OFFSET(x)
Definition: roqvideoenc.c:1108
AVPacket
This structure stores compressed data.
Definition: packet.h:342
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:528
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
roq_cell::u
unsigned char u
Definition: roqvideo.h:29
CelEvaluation
Definition: roqvideoenc.c:121
eval_sse
static int eval_sse(const uint8_t *a, const uint8_t *b, int count)
Definition: roqvideoenc.c:198
d
d
Definition: ffmpeg_filter.c:156
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:674
bytestream.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:334
RoqEncContext::randctx
AVLFG randctx
Definition: roqvideoenc.c:135
roq_class
static const AVClass roq_class
Definition: roqvideoenc.c:1115
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
RoqTempData::numCB4
int numCB4
Definition: roqvideoenc.c:103
RoqTempData::numCB2
int numCB2
Definition: roqvideoenc.c:104
h
h
Definition: vp9dsp_template.c:2038
RoqEncContext::lambda
uint64_t lambda
Definition: roqvideoenc.c:136
RoqEncContext::quake3_compat
int quake3_compat
Definition: roqvideoenc.c:157
SubcelEvaluation::best_bit_use
int best_bit_use
Definition: roqvideoenc.c:113
ff_alloc_packet2
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:33
RoqEncContext::first_frame
int first_frame
Definition: roqvideoenc.c:156
RoqContext::width
int width
Definition: roqvideo.h:45
RoqTempData::f2i2
int f2i2[MAX_CBS_2x2]
Definition: roqvideoenc.c:98
codebook
static const unsigned codebook[256][2]
Definition: cfhdenc.c:42
avpriv_do_elbg
int avpriv_do_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
Definition: elbg.c:371
RoqContext::cb2x2
roq_cell cb2x2[256]
Definition: roqvideo.h:47