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 "codec_internal.h"
65 #include "elbg.h"
66 #include "encode.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 
670  roq_qcell *qcell;
671  CelEvaluation *eval;
672 
673  CodingSpool spool;
674 
675  spool.typeSpool=0;
676  spool.typeSpoolLength=0;
677  spool.args = spool.argumentSpool;
678  spool.pout = &enc->out_buf;
679 
680  if (tempData->used_option[RoQ_ID_CCC]%2)
681  tempData->mainChunkSize+=8; //FIXME
682 
683  /* Write the video chunk header */
684  bytestream_put_le16(&enc->out_buf, RoQ_QUAD_VQ);
685  bytestream_put_le32(&enc->out_buf, tempData->mainChunkSize/8);
686  bytestream_put_byte(&enc->out_buf, 0x0);
687  bytestream_put_byte(&enc->out_buf, 0x0);
688 
689  for (i=0; i<numBlocks; i++) {
690  eval = enc->cel_evals + i;
691 
692  x = eval->sourceX;
693  y = eval->sourceY;
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_elbg_do(&enc->elbg, points, 6 * c_size, inputCount, codebook,
827  cbsize, 1, closest_cb, &enc->randctx, 0);
828  if (ret < 0)
829  return ret;
830 
831  buf = codebook;
832  for (i=0; i<cbsize; i++)
833  for (k=0; k<c_size; k++) {
834  for(j=0; j<4; j++)
835  results->y[j] = *buf++;
836 
837  results->u = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
838  results->v = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
839  results++;
840  }
841  return 0;
842 }
843 
845 {
846  int i, j, ret = 0;
848  RoqContext *const roq = &enc->common;
849  int max = roq->width * roq->height / 16;
850  uint8_t mb2[3*4];
851  int *points = enc->points;
852 
853  /* Subsample YUV data */
854  create_clusters(enc->frame_to_enc, roq->width, roq->height, points);
855 
856  codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4);
857 
858  /* Create 4x4 codebooks */
859  if ((ret = generate_codebook(enc, points, max, enc->results4,
860  4, codebooks->numCB4)) < 0)
861  return ret;
862 
863  /* Create 2x2 codebooks */
864  if ((ret = generate_codebook(enc, points, max * 4,
865  roq->cb2x2, 2, MAX_CBS_2x2)) < 0)
866  return ret;
867 
868  codebooks->numCB2 = MAX_CBS_2x2;
869 
870  /* Unpack 2x2 codebook clusters */
871  for (i=0; i<codebooks->numCB2; i++)
872  unpack_roq_cell(roq->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3);
873 
874  /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */
875  for (i=0; i<codebooks->numCB4; i++) {
876  for (j=0; j<4; j++) {
877  unpack_roq_cell(&enc->results4[4*i + j], mb2);
878  index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2,
879  &roq->cb4x4[i].idx[j], 2);
880  }
881  unpack_roq_qcell(codebooks->unpacked_cb2, roq->cb4x4 + i,
882  codebooks->unpacked_cb4 + i*4*4*3);
883  enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3,
884  codebooks->unpacked_cb4_enlarged + i*8*8*3);
885  }
886 
887  return 0;
888 }
889 
891 {
892  RoqTempData *const tempData = &enc->tmp_data;
893  RoqContext *const roq = &enc->common;
894  int ret;
895 
896  memset(tempData, 0, sizeof(*tempData));
897 
899  if (ret < 0)
900  return ret;
901 
902  if (enc->framesSinceKeyframe >= 1) {
903  motion_search(enc, 8);
904  motion_search(enc, 4);
905  }
906 
907  retry_encode:
908  for (int i = 0; i < roq->width * roq->height / 64; i++)
909  gather_data_for_cel(enc->cel_evals + i, enc);
910 
911  /* Quake 3 can't handle chunks bigger than 65535 bytes */
912  if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
913  if (enc->lambda > 100000) {
914  av_log(roq->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
915  return AVERROR(EINVAL);
916  }
917  av_log(roq->avctx, AV_LOG_ERROR,
918  "Warning, generated a frame too big for Quake (%d > 65535), "
919  "now switching to a bigger qscale value.\n",
920  tempData->mainChunkSize/8);
921  enc->lambda *= 1.5;
922  tempData->mainChunkSize = 0;
923  memset(tempData->used_option, 0, sizeof(tempData->used_option));
924  memset(tempData->codebooks.usedCB4, 0,
925  sizeof(tempData->codebooks.usedCB4));
926  memset(tempData->codebooks.usedCB2, 0,
927  sizeof(tempData->codebooks.usedCB2));
928 
929  goto retry_encode;
930  }
931 
932  remap_codebooks(enc);
933 
934  write_codebooks(enc);
935 
936  reconstruct_and_encode_image(enc, roq->width, roq->height,
937  roq->width * roq->height / 64);
938 
939  /* Rotate frame history */
940  FFSWAP(AVFrame *, roq->current_frame, roq->last_frame);
943 
944  enc->framesSinceKeyframe++;
945 
946  return 0;
947 }
948 
950 {
951  RoqEncContext *const enc = avctx->priv_data;
952 
955 
956  av_freep(&enc->cel_evals);
957  av_freep(&enc->closest_cb);
958  av_freep(&enc->this_motion4);
959  av_freep(&enc->last_motion4);
960  av_freep(&enc->this_motion8);
961  av_freep(&enc->last_motion8);
962 
963  avpriv_elbg_free(&enc->elbg);
964 
965  return 0;
966 }
967 
969 {
970  RoqEncContext *const enc = avctx->priv_data;
971  RoqContext *const roq = &enc->common;
972 
973  av_lfg_init(&enc->randctx, 1);
974 
975  roq->avctx = avctx;
976 
977  enc->framesSinceKeyframe = 0;
978  if ((avctx->width & 0xf) || (avctx->height & 0xf)) {
979  av_log(avctx, AV_LOG_ERROR, "Dimensions must be divisible by 16\n");
980  return AVERROR(EINVAL);
981  }
982 
983  if (avctx->width > 65535 || avctx->height > 65535) {
984  av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc->quake3_compat ? 32768 : 65535);
985  return AVERROR(EINVAL);
986  }
987 
988  if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
989  av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n");
990 
991  roq->width = avctx->width;
992  roq->height = avctx->height;
993 
994  enc->framesSinceKeyframe = 0;
995  enc->first_frame = 1;
996 
997  roq->last_frame = av_frame_alloc();
998  roq->current_frame = av_frame_alloc();
999  if (!roq->last_frame || !roq->current_frame)
1000  return AVERROR(ENOMEM);
1001 
1002  enc->this_motion4 =
1003  av_calloc(roq->width * roq->height / 16, sizeof(*enc->this_motion4));
1004 
1005  enc->last_motion4 =
1006  av_malloc_array (roq->width * roq->height / 16, sizeof(motion_vect));
1007 
1008  enc->this_motion8 =
1009  av_calloc(roq->width * roq->height / 64, sizeof(*enc->this_motion8));
1010 
1011  enc->last_motion8 =
1012  av_malloc_array (roq->width * roq->height / 64, sizeof(motion_vect));
1013 
1014  /* 4x4 codebook needs 6 * 4 * 4 / 4 * width * height / 16 * sizeof(int);
1015  * and so does the points buffer. */
1016  enc->closest_cb =
1017  av_malloc_array(roq->width * roq->height, 3 * sizeof(int));
1018 
1019  if (!enc->this_motion4 || !enc->last_motion4 ||
1020  !enc->this_motion8 || !enc->last_motion8 || !enc->closest_cb)
1021  return AVERROR(ENOMEM);
1022 
1023  enc->points = enc->closest_cb + roq->width * roq->height * 3 / 2;
1024 
1025  return create_cel_evals(enc);
1026 }
1027 
1029 {
1030  /* ROQ info chunk */
1031  bytestream_put_le16(&enc->out_buf, RoQ_INFO);
1032 
1033  /* Size: 8 bytes */
1034  bytestream_put_le32(&enc->out_buf, 8);
1035 
1036  /* Unused argument */
1037  bytestream_put_byte(&enc->out_buf, 0x00);
1038  bytestream_put_byte(&enc->out_buf, 0x00);
1039 
1040  /* Width */
1041  bytestream_put_le16(&enc->out_buf, enc->common.width);
1042 
1043  /* Height */
1044  bytestream_put_le16(&enc->out_buf, enc->common.height);
1045 
1046  /* Unused in Quake 3, mimics the output of the real encoder */
1047  bytestream_put_byte(&enc->out_buf, 0x08);
1048  bytestream_put_byte(&enc->out_buf, 0x00);
1049  bytestream_put_byte(&enc->out_buf, 0x04);
1050  bytestream_put_byte(&enc->out_buf, 0x00);
1051 }
1052 
1054  const AVFrame *frame, int *got_packet)
1055 {
1056  RoqEncContext *const enc = avctx->priv_data;
1057  RoqContext *const roq = &enc->common;
1058  int size, ret;
1059 
1060  roq->avctx = avctx;
1061 
1062  enc->frame_to_enc = frame;
1063 
1064  if (frame->quality)
1065  enc->lambda = frame->quality - 1;
1066  else
1067  enc->lambda = 2*ROQ_LAMBDA_SCALE;
1068 
1069  /* 138 bits max per 8x8 block +
1070  * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
1071  size = ((roq->width * roq->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8;
1072  if ((ret = ff_alloc_packet(avctx, pkt, size)) < 0)
1073  return ret;
1074  enc->out_buf = pkt->data;
1075 
1076  /* Check for I-frame */
1077  if (enc->framesSinceKeyframe == avctx->gop_size)
1078  enc->framesSinceKeyframe = 0;
1079 
1080  if (enc->first_frame) {
1081  /* Alloc memory for the reconstruction data (we must know the stride
1082  for that) */
1083  if ((ret = ff_encode_alloc_frame(avctx, roq->current_frame)) < 0 ||
1084  (ret = ff_encode_alloc_frame(avctx, roq->last_frame )) < 0)
1085  return ret;
1086 
1087  /* Before the first video frame, write a "video info" chunk */
1089 
1090  enc->first_frame = 0;
1091  }
1092 
1093  /* Encode the actual frame */
1094  ret = roq_encode_video(enc);
1095  if (ret < 0)
1096  return ret;
1097 
1098  pkt->size = enc->out_buf - pkt->data;
1099  if (enc->framesSinceKeyframe == 1)
1101  *got_packet = 1;
1102 
1103  return 0;
1104 }
1105 
1106 #define OFFSET(x) offsetof(RoqEncContext, x)
1107 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1108 static const AVOption options[] = {
1109  { "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
1110  { NULL },
1111 };
1112 
1113 static const AVClass roq_class = {
1114  .class_name = "RoQ",
1115  .item_name = av_default_item_name,
1116  .option = options,
1117  .version = LIBAVUTIL_VERSION_INT,
1118 };
1119 
1121  .p.name = "roqvideo",
1122  CODEC_LONG_NAME("id RoQ video"),
1123  .p.type = AVMEDIA_TYPE_VIDEO,
1124  .p.id = AV_CODEC_ID_ROQ,
1126  .priv_data_size = sizeof(RoqEncContext),
1127  .init = roq_encode_init,
1129  .close = roq_encode_end,
1130  .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P,
1131  AV_PIX_FMT_NONE },
1132  .p.priv_class = &roq_class,
1133  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1134 };
RoqCodebooks
Definition: roqvideoenc.c:82
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
RoqContext::cb4x4
roq_qcell cb4x4[256]
Definition: roqvideo.h:48
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: codec_internal.h:42
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:239
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:262
VE
#define VE
Definition: roqvideoenc.c:1107
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:99
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
RoqContext
Definition: roqvideo.h:40
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:374
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:251
encode.h
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:146
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
FFCodec
Definition: codec_internal.h:127
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:128
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:429
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:351
write_codebooks
static void write_codebooks(RoqEncContext *enc)
Write codebook chunk.
Definition: roqvideoenc.c:605
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
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
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:315
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:87
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:256
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:890
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
lfg.h
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition: codec.h:156
CelEvaluation::cbEntry
int cbEntry
Definition: roqvideoenc.c:129
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
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
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:816
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
bias
static int bias(int x, int c)
Definition: vqcdec.c:113
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:237
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
index
int index
Definition: gxfenc.c:89
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
ff_encode_alloc_frame
int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
Allocate buffers for a frame.
Definition: encode.c:729
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:968
AV_CODEC_ID_ROQ
@ AV_CODEC_ID_ROQ
Definition: codec_id.h:90
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:375
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:620
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:781
codec_internal.h
SubcelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:118
CodingSpool::pout
uint8_t ** pout
Definition: roqvideoenc.c:643
ff_roq_encoder
const FFCodec ff_roq_encoder
Definition: roqvideoenc.c:1120
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
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
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:162
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:949
roq_write_video_info_chunk
static void roq_write_video_info_chunk(RoqEncContext *enc)
Definition: roqvideoenc.c:1028
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:380
mb
#define mb
Definition: vf_colormatrix.c:101
options
static const AVOption options[]
Definition: roqvideoenc.c:1108
generate_new_codebooks
static int generate_new_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:844
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
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:269
RoqCodebooks::usedCB2
int usedCB2[MAX_CBS_2x2]
Definition: roqvideoenc.c:85
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:31
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:191
AVCodecContext::height
int height
Definition: avcodec.h:598
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:262
stride
#define stride
Definition: h264pred_template.c:537
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:1053
dim
int dim
Definition: vorbis_enc_data.h:425
mid_pred
#define mid_pred
Definition: mathops.h:98
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:426
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
OFFSET
#define OFFSET(x)
Definition: roqvideoenc.c:1106
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:453
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
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:598
bytestream.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:375
RoqEncContext::randctx
AVLFG randctx
Definition: roqvideoenc.c:137
roq_class
static const AVClass roq_class
Definition: roqvideoenc.c:1113
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:27
sse
static int sse(MpegEncContext *s, const uint8_t *src1, const uint8_t *src2, int w, int h, int stride)
Definition: mpegvideo_enc.c:2629
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:35
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