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 {
137  uint64_t lambda;
138 
141 
144 
145  unsigned int framesSinceKeyframe;
146 
148  uint8_t *out_buf;
152 
155  int *points; // Allocated together with closest_cb
156 
158  int quake3_compat; // Quake 3 compatibility option
159 } RoqEncContext;
160 
161 /* Macroblock support functions */
162 static void unpack_roq_cell(roq_cell *cell, uint8_t u[4*3])
163 {
164  memcpy(u , cell->y, 4);
165  memset(u+4, cell->u, 4);
166  memset(u+8, cell->v, 4);
167 }
168 
169 static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4*4*3])
170 {
171  int i,cp;
172  static const int offsets[4] = {0, 2, 8, 10};
173 
174  for (cp=0; cp<3; cp++)
175  for (i=0; i<4; i++) {
176  u[4*4*cp + offsets[i] ] = cb2[qcell->idx[i]*2*2*3 + 4*cp ];
177  u[4*4*cp + offsets[i]+1] = cb2[qcell->idx[i]*2*2*3 + 4*cp+1];
178  u[4*4*cp + offsets[i]+4] = cb2[qcell->idx[i]*2*2*3 + 4*cp+2];
179  u[4*4*cp + offsets[i]+5] = cb2[qcell->idx[i]*2*2*3 + 4*cp+3];
180  }
181 }
182 
183 
184 static void enlarge_roq_mb4(uint8_t base[3*16], uint8_t u[3*64])
185 {
186  int x,y,cp;
187 
188  for(cp=0; cp<3; cp++)
189  for(y=0; y<8; y++)
190  for(x=0; x<8; x++)
191  *u++ = base[(y/2)*4 + (x/2) + 16*cp];
192 }
193 
194 static inline int square(int x)
195 {
196  return x*x;
197 }
198 
199 static inline int eval_sse(const uint8_t *a, const uint8_t *b, int count)
200 {
201  int diff=0;
202 
203  while(count--)
204  diff += square(*b++ - *a++);
205 
206  return diff;
207 }
208 
209 // FIXME Could use DSPContext.sse, but it is not so speed critical (used
210 // just for motion estimation).
211 static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y1,
212  int x2, int y2, const int *stride1, const int *stride2, int size)
213 {
214  int i, k;
215  int sse=0;
216 
217  for (k=0; k<3; k++) {
218  int bias = (k ? CHROMA_BIAS : 4);
219  for (i=0; i<size; i++)
220  sse += bias*eval_sse(buf1[k] + (y1+i)*stride1[k] + x1,
221  buf2[k] + (y2+i)*stride2[k] + x2, size);
222  }
223 
224  return sse;
225 }
226 
227 static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect,
228  int size)
229 {
230  RoqContext *const roq = &enc->common;
231  int mx=vect.d[0];
232  int my=vect.d[1];
233 
234  if (mx < -7 || mx > 7)
235  return INT_MAX;
236 
237  if (my < -7 || my > 7)
238  return INT_MAX;
239 
240  mx += x;
241  my += y;
242 
243  if ((unsigned) mx > roq->width-size || (unsigned) my > roq->height-size)
244  return INT_MAX;
245 
246  return block_sse(enc->frame_to_enc->data, roq->last_frame->data, x, y,
247  mx, my,
249  size);
250 }
251 
252 /**
253  * @return distortion between two macroblocks
254  */
255 static inline int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size)
256 {
257  int cp, sdiff=0;
258 
259  for(cp=0;cp<3;cp++) {
260  int bias = (cp ? CHROMA_BIAS : 4);
261  sdiff += bias*eval_sse(a, b, size*size);
262  a += size*size;
263  b += size*size;
264  }
265 
266  return sdiff;
267 }
268 
269 /**
270  * Initialize cel evaluators and set their source coordinates
271  */
273 {
274  RoqContext *const roq = &enc->common;
275 
276  enc->cel_evals = av_malloc_array(roq->width * roq->height / 64, sizeof(CelEvaluation));
277  if (!enc->cel_evals)
278  return AVERROR(ENOMEM);
279 
280  /* Map to the ROQ quadtree order */
281  for (int y = 0, n = 0; y < roq->height; y += 16)
282  for (int x = 0; x < roq->width; x += 16)
283  for(int i = 0; i < 4; i++) {
284  enc->cel_evals[n ].sourceX = x + (i&1)*8;
285  enc->cel_evals[n++].sourceY = y + (i&2)*4;
286  }
287 
288  return 0;
289 }
290 
291 /**
292  * Get macroblocks from parts of the image
293  */
294 static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim)
295 {
296  int i, j, cp;
297 
298  for (cp=0; cp<3; cp++) {
299  int stride = frame->linesize[cp];
300  for (i=0; i<dim; i++)
301  for (j=0; j<dim; j++)
302  *mb++ = frame->data[cp][(y+i)*stride + x + j];
303  }
304 }
305 
306 /**
307  * Find the codebook with the lowest distortion from an image
308  */
309 static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB,
310  int *outIndex, int dim)
311 {
312  int i, lDiff = INT_MAX, pick=0;
313 
314  /* Diff against the others */
315  for (i=0; i<numCB; i++) {
316  int diff = squared_diff_macroblock(cluster, cb + i*dim*dim*3, dim);
317  if (diff < lDiff) {
318  lDiff = diff;
319  pick = i;
320  }
321  }
322 
323  *outIndex = pick;
324  return lDiff;
325 }
326 
327 #define EVAL_MOTION(MOTION) \
328  do { \
329  diff = eval_motion_dist(enc, j, i, MOTION, blocksize); \
330  \
331  if (diff < lowestdiff) { \
332  lowestdiff = diff; \
333  bestpick = MOTION; \
334  } \
335  } while(0)
336 
337 static void motion_search(RoqEncContext *enc, int blocksize)
338 {
339  static const motion_vect offsets[8] = {
340  {{ 0,-1}},
341  {{ 0, 1}},
342  {{-1, 0}},
343  {{ 1, 0}},
344  {{-1, 1}},
345  {{ 1,-1}},
346  {{-1,-1}},
347  {{ 1, 1}},
348  };
349 
350  RoqContext *const roq = &enc->common;
351  int diff, lowestdiff, oldbest;
352  int off[3];
353  motion_vect bestpick = {{0,0}};
354  int i, j, k, offset;
355 
356  motion_vect *last_motion;
357  motion_vect *this_motion;
358  motion_vect vect, vect2;
359  const int max = (roq->width / blocksize) * roq->height / blocksize;
360 
361  if (blocksize == 4) {
362  last_motion = enc->last_motion4;
363  this_motion = enc->this_motion4;
364  } else {
365  last_motion = enc->last_motion8;
366  this_motion = enc->this_motion8;
367  }
368 
369  for (i = 0; i< roq->height; i += blocksize)
370  for (j = 0; j < roq->width; j += blocksize) {
371  lowestdiff = eval_motion_dist(enc, j, i, (motion_vect) {{0,0}},
372  blocksize);
373  bestpick.d[0] = 0;
374  bestpick.d[1] = 0;
375 
376  if (blocksize == 4)
377  EVAL_MOTION(enc->this_motion8[(i/8) * (roq->width/8) + j/8]);
378 
379  offset = (i/blocksize) * roq->width / blocksize + j / blocksize;
380  if (offset < max && offset >= 0)
381  EVAL_MOTION(last_motion[offset]);
382 
383  offset++;
384  if (offset < max && offset >= 0)
385  EVAL_MOTION(last_motion[offset]);
386 
387  offset = (i/blocksize + 1) * roq->width / blocksize + j / blocksize;
388  if (offset < max && offset >= 0)
389  EVAL_MOTION(last_motion[offset]);
390 
391  off[0]= (i/blocksize) * roq->width / blocksize + j/blocksize - 1;
392  off[1]= off[0] - roq->width / blocksize + 1;
393  off[2]= off[1] + 1;
394 
395  if (i) {
396 
397  for(k=0; k<2; k++)
398  vect.d[k]= mid_pred(this_motion[off[0]].d[k],
399  this_motion[off[1]].d[k],
400  this_motion[off[2]].d[k]);
401 
402  EVAL_MOTION(vect);
403  for(k=0; k<3; k++)
404  EVAL_MOTION(this_motion[off[k]]);
405  } else if(j)
406  EVAL_MOTION(this_motion[off[0]]);
407 
408  vect = bestpick;
409 
410  oldbest = -1;
411  while (oldbest != lowestdiff) {
412  oldbest = lowestdiff;
413  for (k=0; k<8; k++) {
414  vect2 = vect;
415  vect2.d[0] += offsets[k].d[0];
416  vect2.d[1] += offsets[k].d[1];
417  EVAL_MOTION(vect2);
418  }
419  vect = bestpick;
420  }
421  offset = (i/blocksize) * roq->width / blocksize + j/blocksize;
422  this_motion[offset] = bestpick;
423  }
424 }
425 
426 /**
427  * Get distortion for all options available to a subcel
428  */
429 static void gather_data_for_subcel(SubcelEvaluation *subcel, int x,
430  int y, RoqEncContext *enc)
431 {
432  RoqContext *const roq = &enc->common;
433  RoqTempData *const tempData = &enc->tmp_data;
434  uint8_t mb4[4*4*3];
435  uint8_t mb2[2*2*3];
436  int cluster_index;
437  int i, best_dist;
438 
439  static const int bitsUsed[4] = {2, 10, 10, 34};
440 
441  if (enc->framesSinceKeyframe >= 1) {
442  subcel->motion = enc->this_motion4[y * roq->width / 16 + x / 4];
443 
444  subcel->eval_dist[RoQ_ID_FCC] =
445  eval_motion_dist(enc, x, y,
446  enc->this_motion4[y * roq->width / 16 + x / 4], 4);
447  } else
448  subcel->eval_dist[RoQ_ID_FCC] = INT_MAX;
449 
450  if (enc->framesSinceKeyframe >= 2)
452  roq->current_frame->data, x,
453  y, x, y,
454  enc->frame_to_enc->linesize,
455  roq->current_frame->linesize,
456  4);
457  else
458  subcel->eval_dist[RoQ_ID_MOT] = INT_MAX;
459 
460  cluster_index = y * roq->width / 16 + x / 4;
461 
462  get_frame_mb(enc->frame_to_enc, x, y, mb4, 4);
463 
464  subcel->eval_dist[RoQ_ID_SLD] = index_mb(mb4,
465  tempData->codebooks.unpacked_cb4,
466  tempData->codebooks.numCB4,
467  &subcel->cbEntry, 4);
468 
469  subcel->eval_dist[RoQ_ID_CCC] = 0;
470 
471  for(i=0;i<4;i++) {
472  subcel->subCels[i] = enc->closest_cb[cluster_index*4+i];
473 
474  get_frame_mb(enc->frame_to_enc, x+2*(i&1),
475  y+(i&2), mb2, 2);
476 
477  subcel->eval_dist[RoQ_ID_CCC] +=
478  squared_diff_macroblock(tempData->codebooks.unpacked_cb2 + subcel->subCels[i]*2*2*3, mb2, 2);
479  }
480 
481  best_dist = INT_MAX;
482  for (i=0; i<4; i++)
483  if (ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + enc->lambda*bitsUsed[i] <
484  best_dist) {
485  subcel->best_coding = i;
486  subcel->best_bit_use = bitsUsed[i];
487  best_dist = ROQ_LAMBDA_SCALE*subcel->eval_dist[i] +
488  enc->lambda*bitsUsed[i];
489  }
490 }
491 
492 /**
493  * Get distortion for all options available to a cel
494  */
496 {
497  RoqContext *const roq = &enc->common;
498  RoqTempData *const tempData = &enc->tmp_data;
499  uint8_t mb8[8*8*3];
500  int index = cel->sourceY * roq->width / 64 + cel->sourceX/8;
501  int i, j, best_dist, divide_bit_use;
502 
503  int bitsUsed[4] = {2, 10, 10, 0};
504 
505  if (enc->framesSinceKeyframe >= 1) {
506  cel->motion = enc->this_motion8[index];
507 
508  cel->eval_dist[RoQ_ID_FCC] =
509  eval_motion_dist(enc, cel->sourceX, cel->sourceY,
510  enc->this_motion8[index], 8);
511  } else
512  cel->eval_dist[RoQ_ID_FCC] = INT_MAX;
513 
514  if (enc->framesSinceKeyframe >= 2)
516  roq->current_frame->data,
517  cel->sourceX, cel->sourceY,
518  cel->sourceX, cel->sourceY,
519  enc->frame_to_enc->linesize,
520  roq->current_frame->linesize,8);
521  else
522  cel->eval_dist[RoQ_ID_MOT] = INT_MAX;
523 
524  get_frame_mb(enc->frame_to_enc, cel->sourceX, cel->sourceY, mb8, 8);
525 
526  cel->eval_dist[RoQ_ID_SLD] =
528  tempData->codebooks.numCB4, &cel->cbEntry, 8);
529 
530  gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc);
531  gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc);
532  gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc);
533  gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc);
534 
535  cel->eval_dist[RoQ_ID_CCC] = 0;
536  divide_bit_use = 0;
537  for (i=0; i<4; i++) {
538  cel->eval_dist[RoQ_ID_CCC] +=
539  cel->subCels[i].eval_dist[cel->subCels[i].best_coding];
540  divide_bit_use += cel->subCels[i].best_bit_use;
541  }
542 
543  best_dist = INT_MAX;
544  bitsUsed[3] = 2 + divide_bit_use;
545 
546  for (i=0; i<4; i++)
547  if (ROQ_LAMBDA_SCALE*cel->eval_dist[i] + enc->lambda*bitsUsed[i] <
548  best_dist) {
549  cel->best_coding = i;
550  best_dist = ROQ_LAMBDA_SCALE*cel->eval_dist[i] +
551  enc->lambda*bitsUsed[i];
552  }
553 
554  tempData->used_option[cel->best_coding]++;
555  tempData->mainChunkSize += bitsUsed[cel->best_coding];
556 
557  if (cel->best_coding == RoQ_ID_SLD)
558  tempData->codebooks.usedCB4[cel->cbEntry]++;
559 
560  if (cel->best_coding == RoQ_ID_CCC)
561  for (i=0; i<4; i++) {
562  if (cel->subCels[i].best_coding == RoQ_ID_SLD)
563  tempData->codebooks.usedCB4[cel->subCels[i].cbEntry]++;
564  else if (cel->subCels[i].best_coding == RoQ_ID_CCC)
565  for (j=0; j<4; j++)
566  tempData->codebooks.usedCB2[cel->subCels[i].subCels[j]]++;
567  }
568 }
569 
571 {
572  RoqContext *const roq = &enc->common;
573  RoqTempData *const tempData = &enc->tmp_data;
574  int i, j, idx=0;
575 
576  /* Make remaps for the final codebook usage */
577  for (i=0; i<(enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); i++) {
578  if (tempData->codebooks.usedCB4[i]) {
579  tempData->i2f4[i] = idx;
580  tempData->f2i4[idx] = i;
581  for (j=0; j<4; j++)
582  tempData->codebooks.usedCB2[roq->cb4x4[i].idx[j]]++;
583  idx++;
584  }
585  }
586 
587  tempData->numCB4 = idx;
588 
589  idx = 0;
590  for (i=0; i<MAX_CBS_2x2; i++) {
591  if (tempData->codebooks.usedCB2[i]) {
592  tempData->i2f2[i] = idx;
593  tempData->f2i2[idx] = i;
594  idx++;
595  }
596  }
597  tempData->numCB2 = idx;
598 
599 }
600 
601 /**
602  * Write codebook chunk
603  */
605 {
606  RoqContext *const roq = &enc->common;
607  RoqTempData *const tempData = &enc->tmp_data;
608  int i, j;
609  uint8_t **outp= &enc->out_buf;
610 
611  if (tempData->numCB2) {
612  bytestream_put_le16(outp, RoQ_QUAD_CODEBOOK);
613  bytestream_put_le32(outp, tempData->numCB2*6 + tempData->numCB4*4);
614  bytestream_put_byte(outp, tempData->numCB4);
615  bytestream_put_byte(outp, tempData->numCB2);
616 
617  for (i=0; i<tempData->numCB2; i++) {
618  bytestream_put_buffer(outp, roq->cb2x2[tempData->f2i2[i]].y, 4);
619  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].u);
620  bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].v);
621  }
622 
623  for (i=0; i<tempData->numCB4; i++)
624  for (j=0; j<4; j++)
625  bytestream_put_byte(outp, tempData->i2f2[roq->cb4x4[tempData->f2i4[i]].idx[j]]);
626 
627  }
628 }
629 
630 static inline uint8_t motion_arg(motion_vect mot)
631 {
632  uint8_t ax = 8 - ((uint8_t) mot.d[0]);
633  uint8_t ay = 8 - ((uint8_t) mot.d[1]);
634  return ((ax&15)<<4) | (ay&15);
635 }
636 
637 typedef struct CodingSpool {
640  uint8_t argumentSpool[64];
641  uint8_t *args;
642  uint8_t **pout;
643 } CodingSpool;
644 
645 /* NOTE: Typecodes must be spooled AFTER arguments!! */
646 static void write_typecode(CodingSpool *s, uint8_t type)
647 {
648  s->typeSpool |= (type & 3) << (14 - s->typeSpoolLength);
649  s->typeSpoolLength += 2;
650  if (s->typeSpoolLength == 16) {
651  bytestream_put_le16(s->pout, s->typeSpool);
652  bytestream_put_buffer(s->pout, s->argumentSpool,
653  s->args - s->argumentSpool);
654  s->typeSpoolLength = 0;
655  s->typeSpool = 0;
656  s->args = s->argumentSpool;
657  }
658 }
659 
661  int w, int h, int numBlocks)
662 {
663  RoqContext *const roq = &enc->common;
664  RoqTempData *const tempData = &enc->tmp_data;
665  int i, j, k;
666  int x, y;
667  int subX, subY;
668  int dist=0;
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  dist += eval->eval_dist[eval->best_coding];
695 
696  switch (eval->best_coding) {
697  case RoQ_ID_MOT:
698  write_typecode(&spool, RoQ_ID_MOT);
699  break;
700 
701  case RoQ_ID_FCC:
702  bytestream_put_byte(&spool.args, motion_arg(eval->motion));
703 
704  write_typecode(&spool, RoQ_ID_FCC);
705  ff_apply_motion_8x8(roq, x, y,
706  eval->motion.d[0], eval->motion.d[1]);
707  break;
708 
709  case RoQ_ID_SLD:
710  bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]);
711  write_typecode(&spool, RoQ_ID_SLD);
712 
713  qcell = roq->cb4x4 + eval->cbEntry;
714  ff_apply_vector_4x4(roq, x , y , roq->cb2x2 + qcell->idx[0]);
715  ff_apply_vector_4x4(roq, x+4, y , roq->cb2x2 + qcell->idx[1]);
716  ff_apply_vector_4x4(roq, x , y+4, roq->cb2x2 + qcell->idx[2]);
717  ff_apply_vector_4x4(roq, x+4, y+4, roq->cb2x2 + qcell->idx[3]);
718  break;
719 
720  case RoQ_ID_CCC:
721  write_typecode(&spool, RoQ_ID_CCC);
722 
723  for (j=0; j<4; j++) {
724  subX = x + 4*(j&1);
725  subY = y + 2*(j&2);
726 
727  switch(eval->subCels[j].best_coding) {
728  case RoQ_ID_MOT:
729  break;
730 
731  case RoQ_ID_FCC:
732  bytestream_put_byte(&spool.args,
733  motion_arg(eval->subCels[j].motion));
734 
735  ff_apply_motion_4x4(roq, subX, subY,
736  eval->subCels[j].motion.d[0],
737  eval->subCels[j].motion.d[1]);
738  break;
739 
740  case RoQ_ID_SLD:
741  bytestream_put_byte(&spool.args,
742  tempData->i2f4[eval->subCels[j].cbEntry]);
743 
744  qcell = roq->cb4x4 + eval->subCels[j].cbEntry;
745 
746  ff_apply_vector_2x2(roq, subX , subY ,
747  roq->cb2x2 + qcell->idx[0]);
748  ff_apply_vector_2x2(roq, subX+2, subY ,
749  roq->cb2x2 + qcell->idx[1]);
750  ff_apply_vector_2x2(roq, subX , subY+2,
751  roq->cb2x2 + qcell->idx[2]);
752  ff_apply_vector_2x2(roq, subX+2, subY+2,
753  roq->cb2x2 + qcell->idx[3]);
754  break;
755 
756  case RoQ_ID_CCC:
757  for (k=0; k<4; k++) {
758  int cb_idx = eval->subCels[j].subCels[k];
759  bytestream_put_byte(&spool.args,
760  tempData->i2f2[cb_idx]);
761 
762  ff_apply_vector_2x2(roq, subX + 2*(k&1), subY + (k&2),
763  roq->cb2x2 + cb_idx);
764  }
765  break;
766  }
767  write_typecode(&spool, eval->subCels[j].best_coding);
768  }
769  break;
770  }
771  }
772 
773  /* Flush the remainder of the argument/type spool */
774  while (spool.typeSpoolLength)
775  write_typecode(&spool, 0x0);
776 }
777 
778 
779 /**
780  * Create a single YUV cell from a 2x2 section of the image
781  */
782 static inline void frame_block_to_cell(int *block, uint8_t * const *data,
783  int top, int left, const int *stride)
784 {
785  int i, j, u=0, v=0;
786 
787  for (i=0; i<2; i++)
788  for (j=0; j<2; j++) {
789  int x = (top+i)*stride[0] + left + j;
790  *block++ = data[0][x];
791  x = (top+i)*stride[1] + left + j;
792  u += data[1][x];
793  v += data[2][x];
794  }
795 
796  *block++ = (u + 2) / 4 * CHROMA_BIAS;
797  *block++ = (v + 2) / 4 * CHROMA_BIAS;
798 }
799 
800 /**
801  * Create YUV clusters for the entire image
802  */
803 static void create_clusters(const AVFrame *frame, int w, int h, int *points)
804 {
805  int i, j, k, l;
806 
807  for (i=0; i<h; i+=4)
808  for (j=0; j<w; j+=4) {
809  for (k=0; k < 2; k++)
810  for (l=0; l < 2; l++)
811  frame_block_to_cell(points + (l + 2*k)*6, frame->data,
812  i+2*k, j+2*l, frame->linesize);
813  points += 24;
814  }
815 }
816 
818  int *points, int inputCount, roq_cell *results,
819  int size, int cbsize)
820 {
821  int i, j, k, ret = 0;
822  int c_size = size*size/4;
823  int *buf;
824  int *codebook = enc->tmp_codebook_buf;
825  int *closest_cb = enc->closest_cb;
826 
827  ret = avpriv_init_elbg(points, 6 * c_size, inputCount, codebook,
828  cbsize, 1, closest_cb, &enc->randctx);
829  if (ret < 0)
830  return ret;
831  ret = avpriv_do_elbg(points, 6 * c_size, inputCount, codebook,
832  cbsize, 1, closest_cb, &enc->randctx);
833  if (ret < 0)
834  return ret;
835 
836  buf = codebook;
837  for (i=0; i<cbsize; i++)
838  for (k=0; k<c_size; k++) {
839  for(j=0; j<4; j++)
840  results->y[j] = *buf++;
841 
842  results->u = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
843  results->v = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS;
844  results++;
845  }
846  return 0;
847 }
848 
850 {
851  int i, j, ret = 0;
853  RoqContext *const roq = &enc->common;
854  int max = roq->width * roq->height / 16;
855  uint8_t mb2[3*4];
856  int *points = enc->points;
857 
858  /* Subsample YUV data */
859  create_clusters(enc->frame_to_enc, roq->width, roq->height, points);
860 
861  codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4);
862 
863  /* Create 4x4 codebooks */
864  if ((ret = generate_codebook(enc, points, max, enc->results4,
865  4, codebooks->numCB4)) < 0)
866  return ret;
867 
868  /* Create 2x2 codebooks */
869  if ((ret = generate_codebook(enc, points, max * 4,
870  roq->cb2x2, 2, MAX_CBS_2x2)) < 0)
871  return ret;
872 
873  codebooks->numCB2 = MAX_CBS_2x2;
874 
875  /* Unpack 2x2 codebook clusters */
876  for (i=0; i<codebooks->numCB2; i++)
877  unpack_roq_cell(roq->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3);
878 
879  /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */
880  for (i=0; i<codebooks->numCB4; i++) {
881  for (j=0; j<4; j++) {
882  unpack_roq_cell(&enc->results4[4*i + j], mb2);
883  index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2,
884  &roq->cb4x4[i].idx[j], 2);
885  }
886  unpack_roq_qcell(codebooks->unpacked_cb2, roq->cb4x4 + i,
887  codebooks->unpacked_cb4 + i*4*4*3);
888  enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3,
889  codebooks->unpacked_cb4_enlarged + i*8*8*3);
890  }
891 
892  return 0;
893 }
894 
896 {
897  RoqTempData *const tempData = &enc->tmp_data;
898  RoqContext *const roq = &enc->common;
899  int ret;
900 
901  memset(tempData, 0, sizeof(*tempData));
902 
904  if (ret < 0)
905  return ret;
906 
907  if (enc->framesSinceKeyframe >= 1) {
908  motion_search(enc, 8);
909  motion_search(enc, 4);
910  }
911 
912  retry_encode:
913  for (int i = 0; i < roq->width * roq->height / 64; i++)
914  gather_data_for_cel(enc->cel_evals + i, enc);
915 
916  /* Quake 3 can't handle chunks bigger than 65535 bytes */
917  if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) {
918  if (enc->lambda > 100000) {
919  av_log(roq->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n");
920  return AVERROR(EINVAL);
921  }
922  av_log(roq->avctx, AV_LOG_ERROR,
923  "Warning, generated a frame too big for Quake (%d > 65535), "
924  "now switching to a bigger qscale value.\n",
925  tempData->mainChunkSize/8);
926  enc->lambda *= 1.5;
927  tempData->mainChunkSize = 0;
928  memset(tempData->used_option, 0, sizeof(tempData->used_option));
929  memset(tempData->codebooks.usedCB4, 0,
930  sizeof(tempData->codebooks.usedCB4));
931  memset(tempData->codebooks.usedCB2, 0,
932  sizeof(tempData->codebooks.usedCB2));
933 
934  goto retry_encode;
935  }
936 
937  remap_codebooks(enc);
938 
939  write_codebooks(enc);
940 
941  reconstruct_and_encode_image(enc, roq->width, roq->height,
942  roq->width * roq->height / 64);
943 
944  /* Rotate frame history */
945  FFSWAP(AVFrame *, roq->current_frame, roq->last_frame);
948 
949  enc->framesSinceKeyframe++;
950 
951  return 0;
952 }
953 
955 {
956  RoqEncContext *const enc = avctx->priv_data;
957 
960 
961  av_freep(&enc->cel_evals);
962  av_freep(&enc->closest_cb);
963  av_freep(&enc->this_motion4);
964  av_freep(&enc->last_motion4);
965  av_freep(&enc->this_motion8);
966  av_freep(&enc->last_motion8);
967 
968  return 0;
969 }
970 
972 {
973  RoqEncContext *const enc = avctx->priv_data;
974  RoqContext *const roq = &enc->common;
975 
976  av_lfg_init(&enc->randctx, 1);
977 
978  roq->avctx = avctx;
979 
980  enc->framesSinceKeyframe = 0;
981  if ((avctx->width & 0xf) || (avctx->height & 0xf)) {
982  av_log(avctx, AV_LOG_ERROR, "Dimensions must be divisible by 16\n");
983  return AVERROR(EINVAL);
984  }
985 
986  if (avctx->width > 65535 || avctx->height > 65535) {
987  av_log(avctx, AV_LOG_ERROR, "Dimensions are max %d\n", enc->quake3_compat ? 32768 : 65535);
988  return AVERROR(EINVAL);
989  }
990 
991  if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1)))
992  av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n");
993 
994  roq->width = avctx->width;
995  roq->height = avctx->height;
996 
997  enc->framesSinceKeyframe = 0;
998  enc->first_frame = 1;
999 
1000  roq->last_frame = av_frame_alloc();
1001  roq->current_frame = av_frame_alloc();
1002  if (!roq->last_frame || !roq->current_frame)
1003  return AVERROR(ENOMEM);
1004 
1005  enc->this_motion4 =
1006  av_mallocz_array(roq->width * roq->height / 16, sizeof(motion_vect));
1007 
1008  enc->last_motion4 =
1009  av_malloc_array (roq->width * roq->height / 16, sizeof(motion_vect));
1010 
1011  enc->this_motion8 =
1012  av_mallocz_array(roq->width * roq->height / 64, sizeof(motion_vect));
1013 
1014  enc->last_motion8 =
1015  av_malloc_array (roq->width * roq->height / 64, sizeof(motion_vect));
1016 
1017  /* 4x4 codebook needs 6 * 4 * 4 / 4 * width * height / 16 * sizeof(int);
1018  * and so does the points buffer. */
1019  enc->closest_cb =
1020  av_malloc_array(roq->width * roq->height, 3 * sizeof(int));
1021 
1022  if (!enc->this_motion4 || !enc->last_motion4 ||
1023  !enc->this_motion8 || !enc->last_motion8 || !enc->closest_cb)
1024  return AVERROR(ENOMEM);
1025 
1026  enc->points = enc->closest_cb + roq->width * roq->height * 3 / 2;
1027 
1028  return create_cel_evals(enc);
1029 }
1030 
1032 {
1033  /* ROQ info chunk */
1034  bytestream_put_le16(&enc->out_buf, RoQ_INFO);
1035 
1036  /* Size: 8 bytes */
1037  bytestream_put_le32(&enc->out_buf, 8);
1038 
1039  /* Unused argument */
1040  bytestream_put_byte(&enc->out_buf, 0x00);
1041  bytestream_put_byte(&enc->out_buf, 0x00);
1042 
1043  /* Width */
1044  bytestream_put_le16(&enc->out_buf, enc->common.width);
1045 
1046  /* Height */
1047  bytestream_put_le16(&enc->out_buf, enc->common.height);
1048 
1049  /* Unused in Quake 3, mimics the output of the real encoder */
1050  bytestream_put_byte(&enc->out_buf, 0x08);
1051  bytestream_put_byte(&enc->out_buf, 0x00);
1052  bytestream_put_byte(&enc->out_buf, 0x04);
1053  bytestream_put_byte(&enc->out_buf, 0x00);
1054 }
1055 
1057  const AVFrame *frame, int *got_packet)
1058 {
1059  RoqEncContext *const enc = avctx->priv_data;
1060  RoqContext *const roq = &enc->common;
1061  int size, ret;
1062 
1063  roq->avctx = avctx;
1064 
1065  enc->frame_to_enc = frame;
1066 
1067  if (frame->quality)
1068  enc->lambda = frame->quality - 1;
1069  else
1070  enc->lambda = 2*ROQ_LAMBDA_SCALE;
1071 
1072  /* 138 bits max per 8x8 block +
1073  * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */
1074  size = ((roq->width * roq->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8;
1075  if ((ret = ff_alloc_packet(avctx, pkt, size)) < 0)
1076  return ret;
1077  enc->out_buf = pkt->data;
1078 
1079  /* Check for I-frame */
1080  if (enc->framesSinceKeyframe == avctx->gop_size)
1081  enc->framesSinceKeyframe = 0;
1082 
1083  if (enc->first_frame) {
1084  /* Alloc memory for the reconstruction data (we must know the stride
1085  for that) */
1086  if ((ret = ff_get_buffer(avctx, roq->current_frame, 0)) < 0 ||
1087  (ret = ff_get_buffer(avctx, roq->last_frame, 0)) < 0)
1088  return ret;
1089 
1090  /* Before the first video frame, write a "video info" chunk */
1092 
1093  enc->first_frame = 0;
1094  }
1095 
1096  /* Encode the actual frame */
1097  ret = roq_encode_video(enc);
1098  if (ret < 0)
1099  return ret;
1100 
1101  pkt->size = enc->out_buf - pkt->data;
1102  if (enc->framesSinceKeyframe == 1)
1104  *got_packet = 1;
1105 
1106  return 0;
1107 }
1108 
1109 #define OFFSET(x) offsetof(RoqEncContext, x)
1110 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1111 static const AVOption options[] = {
1112  { "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
1113  { NULL },
1114 };
1115 
1116 static const AVClass roq_class = {
1117  .class_name = "RoQ",
1118  .item_name = av_default_item_name,
1119  .option = options,
1120  .version = LIBAVUTIL_VERSION_INT,
1121 };
1122 
1124  .name = "roqvideo",
1125  .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
1126  .type = AVMEDIA_TYPE_VIDEO,
1127  .id = AV_CODEC_ID_ROQ,
1128  .priv_data_size = sizeof(RoqEncContext),
1129  .init = roq_encode_init,
1130  .encode2 = roq_encode_frame,
1131  .close = roq_encode_end,
1132  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P,
1133  AV_PIX_FMT_NONE },
1134  .priv_class = &roq_class,
1136 };
AVCodec
AVCodec.
Definition: codec.h:197
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:640
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:264
VE
#define VE
Definition: roqvideoenc.c:1110
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:646
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:151
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:169
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
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:196
roq_cell
Definition: roqvideo.h:27
base
uint8_t base
Definition: vp3data.h:141
unpack_roq_cell
static void unpack_roq_cell(roq_cell *cell, uint8_t u[4 *3])
Definition: roqvideoenc.c:162
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:337
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:404
SubcelEvaluation::subCels
int subCels[4]
Definition: roqvideoenc.c:117
RoqEncContext::last_motion8
motion_vect * last_motion8
Definition: roqvideoenc.c:143
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:604
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
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:638
RoqEncContext::points
int * points
Definition: roqvideoenc.c:155
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:99
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:145
s
#define s(width, name)
Definition: cbs_vp9.c:257
RoqEncContext::this_motion4
motion_vect * this_motion4
Definition: roqvideoenc.c:139
motion_arg
static uint8_t motion_arg(motion_vect mot)
Definition: roqvideoenc.c:630
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:895
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:2567
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:147
RoqEncContext
Definition: roqvideoenc.c:134
CodingSpool::args
uint8_t * args
Definition: roqvideoenc.c:641
RoqEncContext::closest_cb
int * closest_cb
Definition: roqvideoenc.c:154
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:429
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:817
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:309
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:184
RoqTempData::codebooks
RoqCodebooks codebooks
Definition: roqvideoenc.c:107
avpriv_init_elbg
int avpriv_init_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Initialize the **codebook vector for the elbg algorithm.
Definition: elbg.c:336
reconstruct_and_encode_image
static void reconstruct_and_encode_image(RoqEncContext *enc, int w, int h, int numBlocks)
Definition: roqvideoenc.c:660
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:153
RoqEncContext::tmp_data
RoqTempData tmp_data
Definition: roqvideoenc.c:149
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:495
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:255
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:971
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:1648
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:116
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:574
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:782
SubcelEvaluation::motion
motion_vect motion
Definition: roqvideoenc.c:118
CodingSpool::pout
uint8_t ** pout
Definition: roqvideoenc.c:642
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:294
size
int size
Definition: twinvq_data.h:10344
ff_roq_encoder
const AVCodec ff_roq_encoder
Definition: roqvideoenc.c:1123
EVAL_MOTION
#define EVAL_MOTION(MOTION)
Definition: roqvideoenc.c:327
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:140
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:142
roq_encode_end
static av_cold int roq_encode_end(AVCodecContext *avctx)
Definition: roqvideoenc.c:954
roq_write_video_info_chunk
static void roq_write_video_info_chunk(RoqEncContext *enc)
Definition: roqvideoenc.c:1031
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:1111
generate_new_codebooks
static int generate_new_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:849
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:803
bytestream_put_buffer
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:372
i
int i
Definition: input.c:406
eval_motion_dist
static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect, int size)
Definition: roqvideoenc.c:227
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:211
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:639
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:204
AVCodecContext::height
int height
Definition: avcodec.h:552
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:148
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:1056
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:194
remap_codebooks
static void remap_codebooks(RoqEncContext *enc)
Definition: roqvideoenc.c:570
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:379
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:272
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:637
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
RoqEncContext::results4
roq_cell results4[4 *MAX_CBS_4x4]
Definition: roqvideoenc.c:150
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:136
OFFSET
#define OFFSET(x)
Definition: roqvideoenc.c:1109
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:406
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:199
d
d
Definition: ffmpeg_filter.c:156
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:552
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:136
roq_class
static const AVClass roq_class
Definition: roqvideoenc.c:1116
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:137
RoqEncContext::quake3_compat
int quake3_compat
Definition: roqvideoenc.c:158
SubcelEvaluation::best_bit_use
int best_bit_use
Definition: roqvideoenc.c:114
RoqEncContext::first_frame
int first_frame
Definition: roqvideoenc.c:157
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
avpriv_do_elbg
int avpriv_do_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
Definition: elbg.c:370
RoqContext::cb2x2
roq_cell cb2x2[256]
Definition: roqvideo.h:47