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 "encode.h"
66 #include "internal.h"
67 #include "mathops.h"
68 
69 #define CHROMA_BIAS 1
70 
71 /**
72  * Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a
73  * Quake 3 bug.
74  */
75 #define MAX_CBS_4x4 256
76 
77 #define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks.
78 
79 /* The cast is useful when multiplying it by INT_MAX */
80 #define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE)
81 
82 typedef struct RoqCodebooks {
83  int numCB4;
84  int numCB2;
87  uint8_t unpacked_cb2[MAX_CBS_2x2*2*2*3];
88  uint8_t unpacked_cb4[MAX_CBS_4x4*4*4*3];
90 } RoqCodebooks;
91 
92 /**
93  * Temporary vars
94  */
95 typedef struct RoqTempData
96 {
101 
103 
104  int numCB4;
105  int numCB2;
106 
108 
109  int used_option[4];
110 } RoqTempData;
111 
112 typedef struct SubcelEvaluation {
113  int eval_dist[4];
116 
117  int subCels[4];
119  int cbEntry;
121 
122 typedef struct CelEvaluation {
123  int eval_dist[4];
125 
127 
129  int cbEntry;
130 
132 } CelEvaluation;
133 
134 typedef struct RoqEncContext {
136  struct ELBGContext *elbg;
138  uint64_t lambda;
139 
142 
145 
146  unsigned int framesSinceKeyframe;
147 
149  uint8_t *out_buf;
153 
156  int *points; // Allocated together with closest_cb
157 
159  int quake3_compat; // Quake 3 compatibility option
160 } RoqEncContext;
161 
162 /* Macroblock support functions */
163 static void unpack_roq_cell(roq_cell *cell, uint8_t u[4*3])
164 {
165  memcpy(u , cell->y, 4);
166  memset(u+4, cell->u, 4);
167  memset(u+8, cell->v, 4);
168 }
169 
170 static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4*4*3])
171 {
172  int i,cp;
173  static const int offsets[4] = {0, 2, 8, 10};
174 
175  for (cp=0; cp<3; cp++)
176  for (i=0; i<4; i++) {
177  u[4*4*cp + offsets[i] ] = cb2[qcell->idx[i]*2*2*3 + 4*cp ];
178  u[4*4*cp + offsets[i]+1] = cb2[qcell->idx[i]*2*2*3 + 4*cp+1];
179  u[4*4*cp + offsets[i]+4] = cb2[qcell->idx[i]*2*2*3 + 4*cp+2];
180  u[4*4*cp + offsets[i]+5] = cb2[qcell->idx[i]*2*2*3 + 4*cp+3];
181  }
182 }
183 
184 
185 static void enlarge_roq_mb4(uint8_t base[3*16], uint8_t u[3*64])
186 {
187  int x,y,cp;
188 
189  for(cp=0; cp<3; cp++)
190  for(y=0; y<8; y++)
191  for(x=0; x<8; x++)
192  *u++ = base[(y/2)*4 + (x/2) + 16*cp];
193 }
194 
195 static inline int square(int x)
196 {
197  return x*x;
198 }
199 
200 static inline int eval_sse(const uint8_t *a, const uint8_t *b, int count)
201 {
202  int diff=0;
203 
204  while(count--)
205  diff += square(*b++ - *a++);
206 
207  return diff;
208 }
209 
210 // FIXME Could use DSPContext.sse, but it is not so speed critical (used
211 // just for motion estimation).
212 static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y1,
213  int x2, int y2, const int *stride1, const int *stride2, int size)
214 {
215  int i, k;
216  int sse=0;
217 
218  for (k=0; k<3; k++) {
219  int bias = (k ? CHROMA_BIAS : 4);
220  for (i=0; i<size; i++)
221  sse += bias*eval_sse(buf1[k] + (y1+i)*stride1[k] + x1,
222  buf2[k] + (y2+i)*stride2[k] + x2, size);
223  }
224 
225  return sse;
226 }
227 
228 static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect,
229  int size)
230 {
231  RoqContext *const roq = &enc->common;
232  int mx=vect.d[0];
233  int my=vect.d[1];
234 
235  if (mx < -7 || mx > 7)
236  return INT_MAX;
237 
238  if (my < -7 || my > 7)
239  return INT_MAX;
240 
241  mx += x;
242  my += y;
243 
244  if ((unsigned) mx > roq->width-size || (unsigned) my > roq->height-size)
245  return INT_MAX;
246 
247  return block_sse(enc->frame_to_enc->data, roq->last_frame->data, x, y,
248  mx, my,
250  size);
251 }
252 
253 /**
254  * @return distortion between two macroblocks
255  */
256 static inline int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
257 {
258  int cp, sdiff=0;
259 
260  for(cp=0;cp<3;cp++) {
261  int bias = (cp ? CHROMA_BIAS : 4);
262  sdiff += bias*eval_sse(a, b, size*size);
263  a += size*size;
264  b += size*size;
265  }
266 
267  return sdiff;
268 }
269 
270 /**
271  * Initialize cel evaluators and set their source coordinates
272  */
274 {
275  RoqContext *const roq = &enc->common;
276 
277  enc->cel_evals = av_malloc_array(roq->width * roq->height / 64, sizeof(CelEvaluation));
278  if (!enc->cel_evals)
279  return AVERROR(ENOMEM);
280 
281  /* Map to the ROQ quadtree order */
282  for (int y = 0, n = 0; y < roq->height; y += 16)
283  for (int x = 0; x < roq->width; x += 16)
284  for(int i = 0; i < 4; i++) {
285  enc->cel_evals[n ].sourceX = x + (i&1)*8;
286  enc->cel_evals[n++].sourceY = y + (i&2)*4;
287  }
288 
289  return 0;
290 }
291 
292 /**
293  * Get macroblocks from parts of the image
294  */
295 static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim)
296 {
297  int i, j, cp;
298 
299  for (cp=0; cp<3; cp++) {
300  int stride = frame->linesize[cp];
301  for (i=0; i<dim; i++)
302  for (j=0; j<dim; j++)
303  *mb++ = frame->data[cp][(y+i)*stride + x + j];
304  }
305 }
306 
307 /**
308  * Find the codebook with the lowest distortion from an image
309  */
310 static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB,
311  int *outIndex, int dim)
312 {
313  int i, lDiff = INT_MAX, pick=0;
314 
315  /* Diff against the others */
316  for (i=0; i<numCB; i++) {
317  int diff = squared_diff_macroblock(cluster, cb + i*dim*dim*3, dim);
318  if (diff < lDiff) {
319  lDiff = diff;
320  pick = i;
321  }
322  }
323 
324  *outIndex = pick;
325  return lDiff;
326 }
327 
328 #define EVAL_MOTION(MOTION) \
329  do { \
330  diff = eval_motion_dist(enc, j, i, MOTION, blocksize); \
331  \
332  if (diff < lowestdiff) { \
333  lowestdiff = diff; \
334  bestpick = MOTION; \
335  } \
336  } while(0)
337 
338 static void motion_search(RoqEncContext *enc, int blocksize)
339 {
340  static const motion_vect offsets[8] = {
341  {{ 0,-1}},
342  {{ 0, 1}},
343  {{-1, 0}},
344  {{ 1, 0}},
345  {{-1, 1}},
346  {{ 1,-1}},
347  {{-1,-1}},
348  {{ 1, 1}},
349  };
350 
351  RoqContext *const roq = &enc->common;
352  int diff, lowestdiff, oldbest;
353  int off[3];
354  motion_vect bestpick = {{0,0}};
355  int i, j, k, offset;
356 
357  motion_vect *last_motion;
358  motion_vect *this_motion;
359  motion_vect vect, vect2;
360  const int max = (roq->width / blocksize) * roq->height / blocksize;
361 
362  if (blocksize == 4) {
363  last_motion = enc->last_motion4;
364  this_motion = enc->this_motion4;
365  } else {
366  last_motion = enc->last_motion8;
367  this_motion = enc->this_motion8;
368  }
369 
370  for (i = 0; i< roq->height; i += blocksize)
371  for (j = 0; j < roq->width; j += blocksize) {
372  lowestdiff = eval_motion_dist(enc, j, i, (motion_vect) {{0,0}},
373  blocksize);
374  bestpick.d[0] = 0;
375  bestpick.d[1] = 0;
376 
377  if (blocksize == 4)
378  EVAL_MOTION(enc->this_motion8[(i/8) * (roq->width/8) + j/8]);
379 
380  offset = (i/blocksize) * roq->width / blocksize + j / blocksize;
381  if (offset < max && offset >= 0)
382  EVAL_MOTION(last_motion[offset]);
383 
384  offset++;
385  if (offset < max && offset >= 0)
386  EVAL_MOTION(last_motion[offset]);
387 
388  offset = (i/blocksize + 1) * roq->width / blocksize + j / blocksize;
389  if (offset < max && offset >= 0)
390  EVAL_MOTION(last_motion[offset]);
391 
392  off[0]= (i/blocksize) * roq->width / blocksize + j/blocksize - 1;
393  off[1]= off[0] - roq->width / blocksize + 1;
394  off[2]= off[1] + 1;
395 
396  if (i) {
397 
398  for(k=0; k<2; k++)
399  vect.d[k]= mid_pred(this_motion[off[0]].d[k],
400  this_motion[off[1]].d[k],
401  this_motion[off[2]].d[k]);
402 
403  EVAL_MOTION(vect);
404  for(k=0; k<3; k++)
405  EVAL_MOTION(this_motion[off[k]]);
406  } else if(j)
407  EVAL_MOTION(this_motion[off[0]]);
408 
409  vect = bestpick;
410 
411  oldbest = -1;
412  while (oldbest != lowestdiff) {
413  oldbest = lowestdiff;
414  for (k=0; k<8; k++) {
415  vect2 = vect;
416  vect2.d[0] += offsets[k].d[0];
417  vect2.d[1] += offsets[k].d[1];
418  EVAL_MOTION(vect2);
419  }
420  vect = bestpick;
421  }
422  offset = (i/blocksize) * roq->width / blocksize + j/blocksize;
423  this_motion[offset] = bestpick;
424  }
425 }
426 
427 /**
428  * Get distortion for all options available to a subcel
429  */
430 static void gather_data_for_subcel(SubcelEvaluation *subcel, int x,
431  int y, RoqEncContext *enc)
432 {
433  RoqContext *const roq = &enc->common;
434  RoqTempData *const tempData = &enc->tmp_data;
435  uint8_t mb4[4*4*3];
436  uint8_t mb2[2*2*3];
437  int cluster_index;
438  int i, best_dist;
439 
440  static const int bitsUsed[4] = {2, 10, 10, 34};
441 
442  if (enc->framesSinceKeyframe >= 1) {
443  subcel->motion = enc->this_motion4[y * roq->width / 16 + x / 4];
444 
445  subcel->eval_dist[RoQ_ID_FCC] =
446  eval_motion_dist(enc, x, y,
447  enc->this_motion4[y * roq->width / 16 + x / 4], 4);
448  } else
449  subcel->eval_dist[RoQ_ID_FCC] = INT_MAX;
450 
451  if (enc->framesSinceKeyframe >= 2)
453  roq->current_frame->data, x,
454  y, x, y,
455  enc->frame_to_enc->linesize,
456  roq->current_frame->linesize,
457  4);
458  else
459  subcel->eval_dist[RoQ_ID_MOT] = INT_MAX;
460 
461  cluster_index = y * roq->width / 16 + x / 4;
462 
463  get_frame_mb(enc->frame_to_enc, x, y, mb4, 4);
464 
465  subcel->eval_dist[RoQ_ID_SLD] = index_mb(mb4,
466  tempData->codebooks.unpacked_cb4,
467  tempData->codebooks.numCB4,
468  &subcel->cbEntry, 4);
469 
470  subcel->eval_dist[RoQ_ID_CCC] = 0;
471 
472  for(i=0;i<4;i++) {
473  subcel->subCels[i] = enc->closest_cb[cluster_index*4+i];
474 
475  get_frame_mb(enc->frame_to_enc, x+2*(i&1),
476  y+(i&2), mb2, 2);
477 
478  subcel->eval_dist[RoQ_ID_CCC] +=
479  squared_diff_macroblock(tempData->codebooks.unpacked_cb2 + subcel->subCels[i]*2*2*3, mb2, 2);
480  }
481 
482  best_dist = INT_MAX;
483  for (i=0; i<4; i++)
484  if (ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + enc->lambda*bitsUsed[i] <
485  best_dist) {
486  subcel->best_coding = i;
487  subcel->best_bit_use = bitsUsed[i];
488  best_dist = ROQ_LAMBDA_SCALE*subcel->eval_dist[i] +
489  enc->lambda*bitsUsed[i];
490  }
491 }
492 
493 /**
494  * Get distortion for all options available to a cel
495  */
497 {
498  RoqContext *const roq = &enc->common;
499  RoqTempData *const tempData = &enc->tmp_data;
500  uint8_t mb8[8*8*3];
501  int index = cel->sourceY * roq->width / 64 + cel->sourceX/8;
502  int i, j, best_dist, divide_bit_use;
503 
504  int bitsUsed[4] = {2, 10, 10, 0};
505 
506  if (enc->framesSinceKeyframe >= 1) {
507  cel->motion = enc->this_motion8[index];
508 
509  cel->eval_dist[RoQ_ID_FCC] =
510  eval_motion_dist(enc, cel->sourceX, cel->sourceY,
511  enc->this_motion8[index], 8);
512  } else
513  cel->eval_dist[RoQ_ID_FCC] = INT_MAX;
514 
515  if (enc->framesSinceKeyframe >= 2)
517  roq->current_frame->data,
518  cel->sourceX, cel->sourceY,
519  cel->sourceX, cel->sourceY,
520  enc->frame_to_enc->linesize,
521  roq->current_frame->linesize,8);
522  else
523  cel->eval_dist[RoQ_ID_MOT] = INT_MAX;
524 
525  get_frame_mb(enc->frame_to_enc, cel->sourceX, cel->sourceY, mb8, 8);
526 
527  cel->eval_dist[RoQ_ID_SLD] =
529  tempData->codebooks.numCB4, &cel->cbEntry, 8);
530 
531  gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc);
532  gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc);
533  gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc);
534  gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc);
535 
536  cel->eval_dist[RoQ_ID_CCC] = 0;
537  divide_bit_use = 0;
538  for (i=0; i<4; i++) {
539  cel->eval_dist[RoQ_ID_CCC] +=
540  cel->subCels[i].eval_dist[cel->subCels[i].best_coding];
541  divide_bit_use += cel->subCels[i].best_bit_use;
542  }
543 
544  best_dist = INT_MAX;
545  bitsUsed[3] = 2 + divide_bit_use;
546 
547  for (i=0; i<4; i++)
548  if (ROQ_LAMBDA_SCALE*cel->eval_dist[i] + enc->lambda*bitsUsed[i] <
549  best_dist) {
550  cel->best_coding = i;
551  best_dist = ROQ_LAMBDA_SCALE*cel->eval_dist[i] +
552  enc->lambda*bitsUsed[i];
553  }
554 
555  tempData->used_option[cel->best_coding]++;
556  tempData->mainChunkSize += bitsUsed[cel->best_coding];
557 
558  if (cel->best_coding == RoQ_ID_SLD)
559  tempData->codebooks.usedCB4[cel->cbEntry]++;
560 
561  if (cel->best_coding == RoQ_ID_CCC)
562  for (i=0; i<4; i++) {
563  if (cel->subCels[i].best_coding == RoQ_ID_SLD)
564  tempData->codebooks.usedCB4[cel->subCels[i].cbEntry]++;
565  else if (cel->subCels[i].best_coding == RoQ_ID_CCC)
566  for (j=0; j<4; j++)
567  tempData->codebooks.usedCB2[cel->subCels[i].subCels[j]]++;
568  }
569 }
570 
572 {
573  RoqContext *const roq = &enc->common;
574  RoqTempData *const tempData = &enc->tmp_data;
575  int i, j, idx=0;
576 
577  /* Make remaps for the final codebook usage */
578  for (i=0; i<(enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); i++) {
579  if (tempData->codebooks.usedCB4[i]) {
580  tempData->i2f4[i] = idx;
581  tempData->f2i4[idx] = i;
582  for (j=0; j<4; j++)
583  tempData->codebooks.usedCB2[roq->cb4x4[i].idx[j]]++;
584  idx++;
585  }
586  }
587 
588  tempData->numCB4 = idx;
589 
590  idx = 0;
591  for (i=0; i<MAX_CBS_2x2; i++) {
592  if (tempData->codebooks.usedCB2[i]) {
593  tempData->i2f2[i] = idx;
594  tempData->f2i2[idx] = i;
595  idx++;
596  }
597  }
598  tempData->numCB2 = idx;
599 
600 }
601 
602 /**
603  * Write codebook chunk
604  */
606 {
607  RoqContext *const roq = &enc->common;
608  RoqTempData *const tempData = &enc->tmp_data;
609  int i, j;
610  uint8_t **outp= &enc->out_buf;
611 
612  if (tempData->numCB2) {
613  bytestream_put_le16(outp, RoQ_QUAD_CODEBOOK);
614  bytestream_put_le32(outp, tempData->numCB2*6 + tempData->numCB4*4);
615  bytestream_put_byte(outp, tempData->numCB4);
616  bytestream_put_byte(outp, tempData->numCB2);
617 
618  for (i=0; i<tempData->numCB2; i++) {
619  bytestream_put_buffer(outp, roq->cb2x2[tempData->f2i2[i]].y, 4);
620  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].u);
621  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].v);
622  }
623 
624  for (i=0; i<tempData->numCB4; i++)
625  for (j=0; j<4; j++)
626  bytestream_put_byte(outp, tempData->i2f2[roq->cb4x4[tempData->f2i4[i]].idx[j]]);
627 
628  }
629 }
630 
631 static inline uint8_t motion_arg(motion_vect mot)
632 {
633  uint8_t ax = 8 - ((uint8_t) mot.d[0]);
634  uint8_t ay = 8 - ((uint8_t) mot.d[1]);
635  return ((ax&15)<<4) | (ay&15);
636 }
637 
638 typedef struct CodingSpool {
641  uint8_t argumentSpool[64];
642  uint8_t *args;
643  uint8_t **pout;
644 } CodingSpool;
645 
646 /* NOTE: Typecodes must be spooled AFTER arguments!! */
647 static void write_typecode(CodingSpool *s, uint8_t type)
648 {
649  s->typeSpool |= (type & 3) << (14 - s->typeSpoolLength);
650  s->typeSpoolLength += 2;
651  if (s->typeSpoolLength == 16) {
652  bytestream_put_le16(s->pout, s->typeSpool);
653  bytestream_put_buffer(s->pout, s->argumentSpool,
654  s->args - s->argumentSpool);
655  s->typeSpoolLength = 0;
656  s->typeSpool = 0;
657  s->args = s->argumentSpool;
658  }
659 }
660 
662  int w, int h, int numBlocks)
663 {
664  RoqContext *const roq = &enc->common;
665  RoqTempData *const tempData = &enc->tmp_data;
666  int i, j, k;
667  int x, y;
668  int subX, subY;
669  int dist=0;
670 
671  roq_qcell *qcell;
672  CelEvaluation *eval;
673 
674  CodingSpool spool;
675 
676  spool.typeSpool=0;
677  spool.typeSpoolLength=0;
678  spool.args = spool.argumentSpool;
679  spool.pout = &enc->out_buf;
680 
681  if (tempData->used_option[RoQ_ID_CCC]%2)
682  tempData->mainChunkSize+=8; //FIXME
683 
684  /* Write the video chunk header */
685  bytestream_put_le16(&enc->out_buf, RoQ_QUAD_VQ);
686  bytestream_put_le32(&enc->out_buf, tempData->mainChunkSize/8);
687  bytestream_put_byte(&enc->out_buf, 0x0);
688  bytestream_put_byte(&enc->out_buf, 0x0);
689 
690  for (i=0; i<numBlocks; i++) {
691  eval = enc->cel_evals + i;
692 
693  x = eval->sourceX;
694  y = eval->sourceY;
695  dist += eval->eval_dist[eval->best_coding];
696 
697  switch (eval->best_coding) {
698  case RoQ_ID_MOT:
699  write_typecode(&spool, RoQ_ID_MOT);
700  break;
701 
702  case RoQ_ID_FCC:
703  bytestream_put_byte(&spool.args, motion_arg(eval->motion));
704 
705  write_typecode(&spool, RoQ_ID_FCC);
706  ff_apply_motion_8x8(roq, x, y,
707  eval->motion.d[0], eval->motion.d[1]);
708  break;
709 
710  case RoQ_ID_SLD:
711  bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]);
712  write_typecode(&spool, RoQ_ID_SLD);
713 
714  qcell = roq->cb4x4 + eval->cbEntry;
715  ff_apply_vector_4x4(roq, x , y , roq->cb2x2 + qcell->idx[0]);
716  ff_apply_vector_4x4(roq, x+4, y , roq->cb2x2 + qcell->idx[1]);
717  ff_apply_vector_4x4(roq, x , y+4, roq->cb2x2 + qcell->idx[2]);
718  ff_apply_vector_4x4(roq, x+4, y+4, roq->cb2x2 + qcell->idx[3]);
719  break;
720 
721  case RoQ_ID_CCC:
722  write_typecode(&spool, RoQ_ID_CCC);
723 
724  for (j=0; j<4; j++) {
725  subX = x + 4*(j&1);
726  subY = y + 2*(j&2);
727 
728  switch(eval->subCels[j].best_coding) {
729  case RoQ_ID_MOT:
730  break;
731 
732  case RoQ_ID_FCC:
733  bytestream_put_byte(&spool.args,
734  motion_arg(eval->subCels[j].motion));
735 
736  ff_apply_motion_4x4(roq, subX, subY,
737  eval->subCels[j].motion.d[0],
738  eval->subCels[j].motion.d[1]);
739  break;
740 
741  case RoQ_ID_SLD:
742  bytestream_put_byte(&spool.args,
743  tempData->i2f4[eval->subCels[j].cbEntry]);
744 
745  qcell = roq->cb4x4 + eval->subCels[j].cbEntry;
746 
747  ff_apply_vector_2x2(roq, subX , subY ,
748  roq->cb2x2 + qcell->idx[0]);
749  ff_apply_vector_2x2(roq, subX+2, subY ,
750  roq->cb2x2 + qcell->idx[1]);
751  ff_apply_vector_2x2(roq, subX , subY+2,
752  roq->cb2x2 + qcell->idx[2]);
753  ff_apply_vector_2x2(roq, subX+2, subY+2,
754  roq->cb2x2 + qcell->idx[3]);
755  break;
756 
757  case RoQ_ID_CCC:
758  for (k=0; k<4; k++) {
759  int cb_idx = eval->subCels[j].subCels[k];
760  bytestream_put_byte(&spool.args,
761  tempData->i2f2[cb_idx]);
762 
763  ff_apply_vector_2x2(roq, subX + 2*(k&1), subY + (k&2),
764  roq->cb2x2 + cb_idx);
765  }
766  break;
767  }
768  write_typecode(&spool, eval->subCels[j].best_coding);
769  }
770  break;
771  }
772  }
773 
774  /* Flush the remainder of the argument/type spool */
775  while (spool.typeSpoolLength)
776  write_typecode(&spool, 0x0);
777 }
778 
779 
780 /**
781  * Create a single YUV cell from a 2x2 section of the image
782  */
783 static inline void frame_block_to_cell(int *block, uint8_t * const *data,
784  int top, int left, const int *stride)
785 {
786  int i, j, u=0, v=0;
787 
788  for (i=0; i<2; i++)
789  for (j=0; j<2; j++) {
790  int x = (top+i)*stride[0] + left + j;
791  *block++ = data[0][x];
792  x = (top+i)*stride[1] + left + j;
793  u += data[1][x];
794  v += data[2][x];
795  }
796 
797  *block++ = (u + 2) / 4 * CHROMA_BIAS;
798  *block++ = (v + 2) / 4 * CHROMA_BIAS;
799 }
800 
801 /**
802  * Create YUV clusters for the entire image
803  */
804 static void create_clusters(const AVFrame *frame, int w, int h, int *points)
805 {
806  int i, j, k, l;
807 
808  for (i=0; i<h; i+=4)
809  for (j=0; j<w; j+=4) {
810  for (k=0; k < 2; k++)
811  for (l=0; l < 2; l++)
812  frame_block_to_cell(points + (l + 2*k)*6, frame->data,
813  i+2*k, j+2*l, frame->linesize);
814  points += 24;
815  }
816 }
817 
819  int *points, int inputCount, roq_cell *results,
820  int size, int cbsize)
821 {
822  int i, j, k, ret = 0;
823  int c_size = size*size/4;
824  int *buf;
825  int *codebook = enc->tmp_codebook_buf;
826  int *closest_cb = enc->closest_cb;
827 
828  ret = avpriv_elbg_do(&enc->elbg, points, 6 * c_size, inputCount, codebook,
829  cbsize, 1, closest_cb, &enc->randctx, 0);
830  if (ret < 0)
831  return ret;
832 
833  buf = codebook;
834  for (i=0; i<cbsize; i++)
835  for (k=0; k<c_size; k++) {
836  for(j=0; j<4; j++)
837  results->y[j] = *buf++;
838 
839  results->u = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
840  results->v = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
841  results++;
842  }
843  return 0;
844 }
845 
847 {
848  int i, j, ret = 0;
850  RoqContext *const roq = &enc->common;
851  int max = roq->width * roq->height / 16;
852  uint8_t mb2[3*4];
853  int *points = enc->points;
854 
855  /* Subsample YUV data */
856  create_clusters(enc->frame_to_enc, roq->width, roq->height, points);
857 
858  codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4);
859 
860  /* Create 4x4 codebooks */
861  if ((ret = generate_codebook(enc, points, max, enc->results4,
862  4, codebooks->numCB4)) < 0)
863  return ret;
864 
865  /* Create 2x2 codebooks */
866  if ((ret = generate_codebook(enc, points, max * 4,
867  roq->cb2x2, 2, MAX_CBS_2x2)) < 0)
868  return ret;
869 
870  codebooks->numCB2 = MAX_CBS_2x2;
871 
872  /* Unpack 2x2 codebook clusters */
873  for (i=0; i<codebooks->numCB2; i++)
874  unpack_roq_cell(roq->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3);
875 
876  /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */
877  for (i=0; i<codebooks->numCB4; i++) {
878  for (j=0; j<4; j++) {
879  unpack_roq_cell(&enc->results4[4*i + j], mb2);
880  index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2,
881  &roq->cb4x4[i].idx[j], 2);
882  }
883  unpack_roq_qcell(codebooks->unpacked_cb2, roq->cb4x4 + i,
884  codebooks->unpacked_cb4 + i*4*4*3);
885  enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3,
886  codebooks->unpacked_cb4_enlarged + i*8*8*3);
887  }
888 
889  return 0;
890 }
891 
893 {
894  RoqTempData *const tempData = &enc->tmp_data;
895  RoqContext *const roq = &enc->common;
896  int ret;
897 
898  memset(tempData, 0, sizeof(*tempData));
899 
901  if (ret < 0)
902  return ret;
903 
904  if (enc->framesSinceKeyframe >= 1) {
905  motion_search(enc, 8);
906  motion_search(enc, 4);
907  }
908 
909  retry_encode:
910  for (int i = 0; i < roq->width * roq->height / 64; i++)
911  gather_data_for_cel(enc->cel_evals + i, enc);
912 
913  /* Quake 3 can't handle chunks bigger than 65535 bytes */
914  if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
915  if (enc->lambda > 100000) {
916  av_log(roq->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
917  return AVERROR(EINVAL);
918  }
919  av_log(roq->avctx, AV_LOG_ERROR,
920  "Warning, generated a frame too big for Quake (%d > 65535), "
921  "now switching to a bigger qscale value.\n",
922  tempData->mainChunkSize/8);
923  enc->lambda *= 1.5;
924  tempData->mainChunkSize = 0;
925  memset(tempData->used_option, 0, sizeof(tempData->used_option));
926  memset(tempData->codebooks.usedCB4, 0,
927  sizeof(tempData->codebooks.usedCB4));
928  memset(tempData->codebooks.usedCB2, 0,
929  sizeof(tempData->codebooks.usedCB2));
930 
931  goto retry_encode;
932  }
933 
934  remap_codebooks(enc);
935 
936  write_codebooks(enc);
937 
938  reconstruct_and_encode_image(enc, roq->width, roq->height,
939  roq->width * roq->height / 64);
940 
941  /* Rotate frame history */
942  FFSWAP(AVFrame *, roq->current_frame, roq->last_frame);
945 
946  enc->framesSinceKeyframe++;
947 
948  return 0;
949 }
950 
952 {
953  RoqEncContext *const enc = avctx->priv_data;
954 
957 
958  av_freep(&enc->cel_evals);
959  av_freep(&enc->closest_cb);
960  av_freep(&enc->this_motion4);
961  av_freep(&enc->last_motion4);
962  av_freep(&enc->this_motion8);
963  av_freep(&enc->last_motion8);
964 
965  avpriv_elbg_free(&enc->elbg);
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_calloc(roq->width * roq->height / 16, sizeof(*enc->this_motion4));
1006 
1007  enc->last_motion4 =
1008  av_malloc_array (roq->width * roq->height / 16, sizeof(motion_vect));
1009 
1010  enc->this_motion8 =
1011  av_calloc(roq->width * roq->height / 64, sizeof(*enc->this_motion8));
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_packet(avctx, pkt, size)) < 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:202
stride
int stride
Definition: mace.c:144
RoqCodebooks
Definition: roqvideoenc.c:82
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
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:86
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:641
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:88
write_typecode
static void write_typecode(CodingSpool *s, uint8_t type)
Definition: roqvideoenc.c:647
SubcelEvaluation
Definition: roqvideoenc.c:112
RoqCodebooks::unpacked_cb2
uint8_t unpacked_cb2[MAX_CBS_2x2 *2 *2 *3]
Definition: roqvideoenc.c:87
RoqEncContext::tmp_codebook_buf
int tmp_codebook_buf[FFMAX(24 *MAX_CBS_4x4, 6 *MAX_CBS_2x2)]
Definition: roqvideoenc.c:152
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
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:38
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:373
ROQ_LAMBDA_SCALE
#define ROQ_LAMBDA_SCALE
Definition: roqvideoenc.c:80
roq_cell::y
unsigned char y[4]
Definition: roqvideo.h:28
RoqTempData::f2i4
int f2i4[MAX_CBS_4x4]
Definition: roqvideoenc.c:97
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:89
AVOption
AVOption.
Definition: opt.h:247
encode.h
b
#define b
Definition: input.c:40
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:143
unpack_roq_qcell
static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4 *4 *3])
Definition: roqvideoenc.c:170
CelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:128
ff_apply_motion_8x8
void ff_apply_motion_8x8(RoqContext *ri, int x, int y, int deltax, int deltay)
Definition: roqvideo.c:140
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:163
max
#define max(a, b)
Definition: cuda_runtime.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
motion_search
static void motion_search(RoqEncContext *enc, int blocksize)
Definition: roqvideoenc.c:338
RoqTempData::mainChunkSize
int mainChunkSize
Definition: roqvideoenc.c:102
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:425
SubcelEvaluation::subCels
int subCels[4]
Definition: roqvideoenc.c:117
RoqEncContext::last_motion8
motion_vect * last_motion8
Definition: roqvideoenc.c:144
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:605
RoqTempData::i2f4
int i2f4[MAX_CBS_4x4]
Definition: roqvideoenc.c:98
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
RoqEncContext::elbg
struct ELBGContext * elbg
Definition: roqvideoenc.c:136
RoQ_ID_CCC
#define RoQ_ID_CCC
Definition: roqvideo.h:60
SubcelEvaluation::eval_dist
int eval_dist[4]
Definition: roqvideoenc.c:113
CelEvaluation::best_coding
int best_coding
Definition: roqvideoenc.c:124
CodingSpool::typeSpool
int typeSpool
Definition: roqvideoenc.c:639
RoqEncContext::points
int * points
Definition: roqvideoenc.c:156
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:99
avpriv_elbg_do
int avpriv_elbg_do(ELBGContext **elbgp, int *points, int dim, int numpoints, int *codebook, int num_cb, int max_steps, int *closest_cb, AVLFG *rand_state, uintptr_t flags)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
Definition: elbg.c:446
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
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:42
RoqEncContext::framesSinceKeyframe
unsigned int framesSinceKeyframe
Definition: roqvideoenc.c:146
s
#define s(width, name)
Definition: cbs_vp9.c:257
RoqEncContext::this_motion4
motion_vect * this_motion4
Definition: roqvideoenc.c:140
motion_arg
static uint8_t motion_arg(motion_vect mot)
Definition: roqvideoenc.c:631
RoQ_QUAD_CODEBOOK
#define RoQ_QUAD_CODEBOOK
Definition: roqvideo.h:52
RoqCodebooks::numCB2
int numCB2
Definition: roqvideoenc.c:84
offsets
static const int offsets[]
Definition: hevc_pel.c:34
roq_encode_video
static int roq_encode_video(RoqEncContext *enc)
Definition: roqvideoenc.c:892
RoQ_ID_MOT
#define RoQ_ID_MOT
Definition: roqvideo.h:57
motion_vect
Definition: roqvideo.h:36
SubcelEvaluation::cbEntry
int cbEntry
Definition: roqvideoenc.c:119
sse
static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride)
Definition: mpegvideo_enc.c:2571
lfg.h
CelEvaluation::cbEntry
int cbEntry
Definition: roqvideoenc.c:129
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:290
RoqEncContext::frame_to_enc
const AVFrame * frame_to_enc
Definition: roqvideoenc.c:148
RoqEncContext
Definition: roqvideoenc.c:134
CodingSpool::args
uint8_t * args
Definition: roqvideoenc.c:642
RoqEncContext::closest_cb
int * closest_cb
Definition: roqvideoenc.c:155
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:430
if
if(ret)
Definition: filter_design.txt:179
elbg.h
SubcelEvaluation::best_coding
int best_coding
Definition: roqvideoenc.c:115
generate_codebook
static int generate_codebook(RoqEncContext *enc, int *points, int inputCount, roq_cell *results, int size, int cbsize)
Definition: roqvideoenc.c:818
RoqTempData
Temporary vars.
Definition: roqvideoenc.c:95
CelEvaluation::subCels
SubcelEvaluation subCels[4]
Definition: roqvideoenc.c:126
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
RoqTempData::used_option
int used_option[4]
Definition: roqvideoenc.c:109
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:310
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
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:185
RoqTempData::codebooks
RoqCodebooks codebooks
Definition: roqvideoenc.c:107
reconstruct_and_encode_image
static void reconstruct_and_encode_image(RoqEncContext *enc, int w, int h, int numBlocks)
Definition: roqvideoenc.c:661
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:154
RoqEncContext::tmp_data
RoqTempData tmp_data
Definition: roqvideoenc.c:150
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:496
RoqTempData::i2f2
int i2f2[MAX_CBS_2x2]
Definition: roqvideoenc.c:100
squared_diff_macroblock
static int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
Definition: roqvideoenc.c:256
roq_qcell
Definition: roqvideo.h:32
CelEvaluation::sourceX
int sourceX
Definition: roqvideoenc.c:131
CelEvaluation::sourceY
int sourceY
Definition: roqvideoenc.c:131
RoqEncContext::common
RoqContext common
Definition: roqvideoenc.c:135
CelEvaluation::eval_dist
int eval_dist[4]
Definition: roqvideoenc.c:123
RoqCodebooks::numCB4
int numCB4
Definition: roqvideoenc.c:83
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:88
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1652
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
MAX_CBS_2x2
#define MAX_CBS_2x2
Maximum number of 2x2 codebooks.
Definition: roqvideoenc.c:77
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:783
SubcelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:118
CodingSpool::pout
uint8_t ** pout
Definition: roqvideoenc.c:643
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:295
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:328
avpriv_elbg_free
av_cold void avpriv_elbg_free(ELBGContext **elbgp)
Free an ELBGContext and reset the pointer to it.
Definition: elbg.c:499
CHROMA_BIAS
#define CHROMA_BIAS
Definition: roqvideoenc.c:69
ff_apply_vector_4x4
void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
Definition: roqvideo.c:72
RoqEncContext::last_motion4
motion_vect * last_motion4
Definition: roqvideoenc.c:141
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:143
roq_encode_end
static av_cold int roq_encode_end(AVCodecContext *avctx)
Definition: roqvideoenc.c:951
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:379
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:846
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:804
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
eval_motion_dist
static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect, int size)
Definition: roqvideoenc.c:228
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
RoqCodebooks::usedCB2
int usedCB2[MAX_CBS_2x2]
Definition: roqvideoenc.c:85
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:50
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:212
ELBGContext
ELBG internal data.
Definition: elbg.c:46
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:640
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:209
AVCodecContext::height
int height
Definition: avcodec.h:556
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:75
RoqEncContext::out_buf
uint8_t * out_buf
Definition: roqvideoenc.c:149
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:271
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
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
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:71
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:195
remap_codebooks
static void remap_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:571
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:383
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:273
ff_apply_motion_4x4
void ff_apply_motion_4x4(RoqContext *ri, int x, int y, int deltax, int deltay)
Definition: roqvideo.c:134
CodingSpool
Definition: roqvideoenc.c:638
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
RoqEncContext::results4
roq_cell results4[4 *MAX_CBS_4x4]
Definition: roqvideoenc.c:151
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:139
OFFSET
#define OFFSET(x)
Definition: roqvideoenc.c:1108
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:410
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:241
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:122
eval_sse
static int eval_sse(const uint8_t *a, const uint8_t *b, int count)
Definition: roqvideoenc.c:200
d
d
Definition: ffmpeg_filter.c:156
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:556
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:137
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:104
RoqTempData::numCB2
int numCB2
Definition: roqvideoenc.c:105
h
h
Definition: vp9dsp_template.c:2038
RoqEncContext::lambda
uint64_t lambda
Definition: roqvideoenc.c:138
RoqEncContext::quake3_compat
int quake3_compat
Definition: roqvideoenc.c:159
SubcelEvaluation::best_bit_use
int best_bit_use
Definition: roqvideoenc.c:114
RoqEncContext::first_frame
int first_frame
Definition: roqvideoenc.c:158
ff_alloc_packet
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition: encode.c:34
RoqContext::width
int width
Definition: roqvideo.h:45
RoqTempData::f2i2
int f2i2[MAX_CBS_2x2]
Definition: roqvideoenc.c:99
codebook
static const unsigned codebook[256][2]
Definition: cfhdenc.c:42
RoqContext::cb2x2
roq_cell cb2x2[256]
Definition: roqvideo.h:47