LCOV - code coverage report
Current view: top level - libavcodec - roqvideoenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 511 549 93.1 %
Date: 2017-12-18 06:23:41 Functions: 28 28 100.0 %

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

Generated by: LCOV version 1.13