[cvs] / xvidcore / src / encoder.c Repository:
ViewVC logotype

Diff of /xvidcore/src/encoder.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.76.2.44, Sat Feb 15 05:57:14 2003 UTC revision 1.134, Sat Dec 18 16:02:00 2010 UTC
# Line 3  Line 3 
3   *  XVID MPEG-4 VIDEO CODEC   *  XVID MPEG-4 VIDEO CODEC
4   *  -  Encoder main module  -   *  -  Encoder main module  -
5   *   *
6   *  This program is an implementation of a part of one or more MPEG-4   *  Copyright(C) 2002-2010 Michael Militzer <isibaar@xvid.org>
7   *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending   *               2002-2003 Peter Ross <pross@xvid.org>
8   *  to use this software module in hardware or software products are   *               2002      Daniel Smith <danielsmith@astroboymail.com>
  *  advised that its use may infringe existing patents or copyrights, and  
  *  any such use would be at such party's own risk.  The original  
  *  developer of this software module and his/her company, and subsequent  
  *  editors and their companies, will have no liability for use of this  
  *  software or modifications or derivatives thereof.  
9   *   *
10   *  This program is free software; you can redistribute it and/or modify   *  This program is free software; you can redistribute it and/or modify
11   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 26  Line 21 
21   *  along with this program; if not, write to the Free Software   *  along with this program; if not, write to the Free Software
22   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23   *   *
  ****************************************************************************/  
   
 /*****************************************************************************  
  *  
  *  History  
  *  
  *  10.07.2002  added BFRAMES_DEC_DEBUG support  
  *              MinChen <chenm001@163.com>  
  *  20.06.2002 bframe patch  
  *  08.05.2002 fix some problem in DEBUG mode;  
  *             MinChen <chenm001@163.com>  
  *  14.04.2002 added FrameCodeB()  
  *  
24   *  $Id$   *  $Id$
25   *   *
26   ****************************************************************************/   ****************************************************************************/
# Line 56  Line 38 
38  #include "image/font.h"  #include "image/font.h"
39  #include "motion/sad.h"  #include "motion/sad.h"
40  #include "motion/motion.h"  #include "motion/motion.h"
41    #include "motion/gmc.h"
42    
43  #include "bitstream/cbp.h"  #include "bitstream/cbp.h"
44  #include "utils/mbfunctions.h"  #include "utils/mbfunctions.h"
45  #include "bitstream/bitstream.h"  #include "bitstream/bitstream.h"
46  #include "bitstream/mbcoding.h"  #include "bitstream/mbcoding.h"
 #include "utils/ratecontrol.h"  
47  #include "utils/emms.h"  #include "utils/emms.h"
48  #include "bitstream/mbcoding.h"  #include "bitstream/mbcoding.h"
 #include "quant/adapt_quant.h"  
49  #include "quant/quant_matrix.h"  #include "quant/quant_matrix.h"
50  #include "utils/mem_align.h"  #include "utils/mem_align.h"
51    
52  /*****************************************************************************  # include "motion/motion_smp.h"
  * Local macros  
  ****************************************************************************/  
53    
 #define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT  
 #define SWAP(_T_,A,B)    { _T_ tmp = A; A = B; B = tmp; }  
54    
55  /*****************************************************************************  /*****************************************************************************
56   * Local function prototypes   * Local function prototypes
57   ****************************************************************************/   ****************************************************************************/
58    
59  static int FrameCodeI(Encoder * pEnc,  static int FrameCodeI(Encoder * pEnc,
60                                            Bitstream * bs,                                            Bitstream * bs);
                                           uint32_t * pBits);  
61    
62  static int FrameCodeP(Encoder * pEnc,  static int FrameCodeP(Encoder * pEnc,
63                                            Bitstream * bs,                                            Bitstream * bs);
                                           uint32_t * pBits,  
                                           bool force_inter,  
                                           bool vol_header);  
64    
65  static void FrameCodeB(Encoder * pEnc,  static void FrameCodeB(Encoder * pEnc,
66                                             FRAMEINFO * frame,                                             FRAMEINFO * frame,
67                                             Bitstream * bs,                                             Bitstream * bs);
                                            uint32_t * pBits);  
   
 /*****************************************************************************  
  * Local data  
  ****************************************************************************/  
   
 static int DQtab[4] = {  
         -1, -2, 1, 2  
 };  
   
 static int iDQtab[5] = {  
         1, 0, NO_CHANGE, 2, 3  
 };  
68    
69    
70  /*****************************************************************************  /*****************************************************************************
# Line 117  Line 78 
78   * and cleaning code.   * and cleaning code.
79   *   *
80   * Returned values :   * Returned values :
81   *    - XVID_ERR_OK     - no errors   *      - 0                             - no errors
82   *    - XVID_ERR_MEMORY - the libc could not allocate memory, the function   *    - XVID_ERR_MEMORY - the libc could not allocate memory, the function
83   *                        cleans the structure before exiting.   *                        cleans the structure before exiting.
84   *                        pParam->handle is also set to NULL.   *                        pParam->handle is also set to NULL.
85   *   *
86   ****************************************************************************/   ****************************************************************************/
87    
 int  
 encoder_create(XVID_ENC_PARAM * pParam)  
 {  
         Encoder *pEnc;  
         int i;  
   
         pParam->handle = NULL;  
   
         ENC_CHECK(pParam);  
   
         ENC_CHECK(pParam->width > 0 && pParam->width <= 1920);  
         ENC_CHECK(pParam->height > 0 && pParam->height <= 1280);  
         ENC_CHECK(!(pParam->width % 2));  
         ENC_CHECK(!(pParam->height % 2));  
   
         /* Fps */  
   
         if (pParam->fincr <= 0 || pParam->fbase <= 0) {  
                 pParam->fincr = 1;  
                 pParam->fbase = 25;  
         }  
   
88          /*          /*
89           * Simplify the "fincr/fbase" fraction           * Simplify the "fincr/fbase" fraction
          * (neccessary, since windows supplies us with huge numbers)  
90           */           */
91    static int
92    gcd(int a, int b)
93    {
94            int r ;
95    
96          i = pParam->fincr;          if (b > a) {
97          while (i > 1) {                  r = a;
98                  if (pParam->fincr % i == 0 && pParam->fbase % i == 0) {                  a = b;
99                          pParam->fincr /= i;                  b = r;
                         pParam->fbase /= i;  
                         i = pParam->fincr;  
                         continue;  
                 }  
                 i--;  
100          }          }
101    
102          if (pParam->fbase > 65535) {          while ((r = a % b)) {
103                  float div = (float) pParam->fbase / 65535;                  a = b;
104                    b = r;
105                  pParam->fbase = (int) (pParam->fbase / div);          }
106                  pParam->fincr = (int) (pParam->fincr / div);          return b;
107          }          }
108    
109          /* Bitrate allocator defaults */  static void
110    simplify_time(int *inc, int *base)
111          if (pParam->rc_bitrate <= 0)  {
112                  pParam->rc_bitrate = 900000;          /* common factor */
113            const int s = gcd(*inc, *base);
114      *inc  /= s;
115      *base /= s;
116    
117          if (pParam->rc_reaction_delay_factor <= 0)          if (*base > 65535 || *inc > 65535) {
118                  pParam->rc_reaction_delay_factor = 16;                  int *biggest;
119                    int *other;
120                    float div;
121    
122          if (pParam->rc_averaging_period <= 0)                  if (*base > *inc) {
123                  pParam->rc_averaging_period = 100;                          biggest = base;
124                            other = inc;
125                    } else {
126                            biggest = inc;
127                            other = base;
128                    }
129    
130          if (pParam->rc_buffer <= 0)                  div = ((float)*biggest)/((float)65535);
131                  pParam->rc_buffer = 100;                  *biggest = (unsigned int)(((float)*biggest)/div);
132                    *other = (unsigned int)(((float)*other)/div);
133            }
134    }
135    
         /* Max and min quantizers */  
136    
137          if ((pParam->min_quantizer <= 0) || (pParam->min_quantizer > 31))  int
138                  pParam->min_quantizer = 1;  enc_create(xvid_enc_create_t * create)
139    {
140            Encoder *pEnc;
141            int n;
142    
143          if ((pParam->max_quantizer <= 0) || (pParam->max_quantizer > 31))          if (XVID_VERSION_MAJOR(create->version) != 1) /* v1.x.x */
144                  pParam->max_quantizer = 31;                  return XVID_ERR_VERSION;
145    
146          if (pParam->max_quantizer < pParam->min_quantizer)          if (create->width%2 || create->height%2)
147                  pParam->max_quantizer = pParam->min_quantizer;                  return XVID_ERR_FAIL;
148    
149          /* 1 keyframe each 10 seconds */          if (create->width<=0 || create->height<=0)
150                    return XVID_ERR_FAIL;
151    
152          if (pParam->max_key_interval <= 0)          /* allocate encoder struct */
                 pParam->max_key_interval = 10 * pParam->fincr / pParam->fbase;  
153    
154          pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);          pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);
155          if (pEnc == NULL)          if (pEnc == NULL)
156                  return XVID_ERR_MEMORY;                  return XVID_ERR_MEMORY;
   
         /* Zero the Encoder Structure */  
   
157          memset(pEnc, 0, sizeof(Encoder));          memset(pEnc, 0, sizeof(Encoder));
158    
159          /* Fill members of Encoder structure */          pEnc->mbParam.profile = create->profile;
   
         pEnc->mbParam.width = pParam->width;  
         pEnc->mbParam.height = pParam->height;  
160    
161            /* global flags */
162            pEnc->mbParam.global_flags = create->global;
163      if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED))
164        pEnc->mbParam.global_flags |= XVID_GLOBAL_DIVX5_USERDATA;
165    
166            /* width, height */
167            pEnc->mbParam.width = create->width;
168            pEnc->mbParam.height = create->height;
169          pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16;          pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16;
170          pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16;          pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16;
   
171          pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE;          pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE;
172          pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE;          pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE;
173    
174          pEnc->mbParam.fbase = pParam->fbase;          /* framerate */
175          pEnc->mbParam.fincr = pParam->fincr;          pEnc->mbParam.fincr = MAX(create->fincr, 0);
176            pEnc->mbParam.fbase = create->fincr <= 0 ? 25 : create->fbase;
177            if (pEnc->mbParam.fincr>0)
178                    simplify_time((int*)&pEnc->mbParam.fincr, (int*)&pEnc->mbParam.fbase);
179    
180          pEnc->mbParam.m_quant_type = H263_QUANT;          /* zones */
181            if(create->num_zones > 0) {
182                    pEnc->num_zones = create->num_zones;
183                    pEnc->zones = xvid_malloc(sizeof(xvid_enc_zone_t) * pEnc->num_zones, CACHE_LINE);
184                    if (pEnc->zones == NULL)
185                            goto xvid_err_memory0;
186                    memcpy(pEnc->zones, create->zones, sizeof(xvid_enc_zone_t) * pEnc->num_zones);
187            } else {
188                    pEnc->num_zones = 0;
189                    pEnc->zones = NULL;
190            }
191    
192          pEnc->fMvPrevSigma = -1;          /* plugins */
193            if(create->num_plugins > 0) {
194                    pEnc->num_plugins = create->num_plugins;
195                    pEnc->plugins = xvid_malloc(sizeof(xvid_enc_plugin_t) * pEnc->num_plugins, CACHE_LINE);
196                    if (pEnc->plugins == NULL)
197                            goto xvid_err_memory0;
198            } else {
199                    pEnc->num_plugins = 0;
200                    pEnc->plugins = NULL;
201            }
202    
203            for (n=0; n<pEnc->num_plugins;n++) {
204                    xvid_plg_create_t pcreate;
205                    xvid_plg_info_t pinfo;
206    
207                    memset(&pinfo, 0, sizeof(xvid_plg_info_t));
208                    pinfo.version = XVID_VERSION;
209                    if (create->plugins[n].func(NULL, XVID_PLG_INFO, &pinfo, NULL) >= 0) {
210                            pEnc->mbParam.plugin_flags |= pinfo.flags;
211                    }
212    
213                    memset(&pcreate, 0, sizeof(xvid_plg_create_t));
214                    pcreate.version = XVID_VERSION;
215                    pcreate.num_zones = pEnc->num_zones;
216                    pcreate.zones = pEnc->zones;
217                    pcreate.width = pEnc->mbParam.width;
218                    pcreate.height = pEnc->mbParam.height;
219                    pcreate.mb_width = pEnc->mbParam.mb_width;
220                    pcreate.mb_height = pEnc->mbParam.mb_height;
221                    pcreate.fincr = pEnc->mbParam.fincr;
222                    pcreate.fbase = pEnc->mbParam.fbase;
223                    pcreate.param = create->plugins[n].param;
224    
225                    pEnc->plugins[n].func = NULL;   /* disable plugins that fail */
226                    if (create->plugins[n].func(NULL, XVID_PLG_CREATE, &pcreate, &pEnc->plugins[n].param) >= 0) {
227                            pEnc->plugins[n].func = create->plugins[n].func;
228                    }
229            }
230    
231            if ((pEnc->mbParam.global_flags & XVID_GLOBAL_EXTRASTATS_ENABLE) ||
232                    (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) {
233                    pEnc->mbParam.plugin_flags |= XVID_REQORIGINAL; /* psnr calculation requires the original */
234            }
235    
236            /* temp dquants */
237            if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
238                    pEnc->temp_dquants = (int *) xvid_malloc(pEnc->mbParam.mb_width *
239                                                    pEnc->mbParam.mb_height * sizeof(int), CACHE_LINE);
240                    if (pEnc->temp_dquants==NULL)
241                            goto xvid_err_memory1a;
242            }
243    
244            /* temp lambdas */
245            if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
246                    pEnc->temp_lambda = (float *) xvid_malloc(pEnc->mbParam.mb_width *
247                                                    pEnc->mbParam.mb_height * 6 * sizeof(float), CACHE_LINE);
248                    if (pEnc->temp_lambda == NULL)
249                            goto xvid_err_memory1a;
250            }
251    
252            /* bframes */
253            pEnc->mbParam.max_bframes = MAX(create->max_bframes, 0);
254            pEnc->mbParam.bquant_ratio = MAX(create->bquant_ratio, 0);
255            pEnc->mbParam.bquant_offset = create->bquant_offset;
256    
257          /* Fill rate control parameters */          /* min/max quant */
258            for (n=0; n<3; n++) {
259                    pEnc->mbParam.min_quant[n] = create->min_quant[n] > 0 ? create->min_quant[n] : 2;
260                    pEnc->mbParam.max_quant[n] = create->max_quant[n] > 0 ? create->max_quant[n] : 31;
261            }
262    
263          pEnc->bitrate = pParam->rc_bitrate;          /* frame drop ratio */
264            pEnc->mbParam.frame_drop_ratio = MAX(create->frame_drop_ratio, 0);
265    
266          pEnc->iFrameNum = -1;          /* max keyframe interval */
267          pEnc->mbParam.iMaxKeyInterval = pParam->max_key_interval;          pEnc->mbParam.iMaxKeyInterval = create->max_key_interval <= 0 ? (10 * (int)pEnc->mbParam.fbase) / (int)pEnc->mbParam.fincr : create->max_key_interval;
268    
269          /* try to allocate frame memory */          /* allocate working frame-image memory */
270    
271          pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);          pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
272          pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);          pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
# Line 240  Line 274 
274          if (pEnc->current == NULL || pEnc->reference == NULL)          if (pEnc->current == NULL || pEnc->reference == NULL)
275                  goto xvid_err_memory1;                  goto xvid_err_memory1;
276    
277          /* try to allocate mb memory */          /* allocate macroblock memory */
278    
279          pEnc->current->mbs =          pEnc->current->mbs =
280                  xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *                  xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
# Line 252  Line 286 
286          if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)          if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)
287                  goto xvid_err_memory2;                  goto xvid_err_memory2;
288    
289          /* try to allocate image memory */          /* allocate quant matrix memory */
290    
291            pEnc->mbParam.mpeg_quant_matrices =
292                    xvid_malloc(sizeof(uint16_t) * 64 * 8, CACHE_LINE);
293    
294            if (pEnc->mbParam.mpeg_quant_matrices == NULL)
295                    goto xvid_err_memory2a;
296    
297            /* allocate interpolation image memory */
298    
299          if (pParam->global & XVID_GLOBAL_EXTRASTATS)          if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
300                  image_null(&pEnc->sOriginal);                  image_null(&pEnc->sOriginal);
301                    image_null(&pEnc->sOriginal2);
302            }
303    
304          image_null(&pEnc->f_refh);          image_null(&pEnc->f_refh);
305          image_null(&pEnc->f_refv);          image_null(&pEnc->f_refv);
# Line 265  Line 309 
309          image_null(&pEnc->reference->image);          image_null(&pEnc->reference->image);
310          image_null(&pEnc->vInterH);          image_null(&pEnc->vInterH);
311          image_null(&pEnc->vInterV);          image_null(&pEnc->vInterV);
         image_null(&pEnc->vInterVf);  
312          image_null(&pEnc->vInterHV);          image_null(&pEnc->vInterHV);
         image_null(&pEnc->vInterHVf);  
313    
314          if (pParam->global & XVID_GLOBAL_EXTRASTATS)          if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
315          {       if (image_create                  if (image_create
316                          (&pEnc->sOriginal, pEnc->mbParam.edged_width,                          (&pEnc->sOriginal, pEnc->mbParam.edged_width,
317                           pEnc->mbParam.edged_height) < 0)                           pEnc->mbParam.edged_height) < 0)
318                          goto xvid_err_memory3;                          goto xvid_err_memory3;
319    
320                    if (image_create
321                            (&pEnc->sOriginal2, pEnc->mbParam.edged_width,
322                             pEnc->mbParam.edged_height) < 0)
323                            goto xvid_err_memory3;
324          }          }
325    
326          if (image_create          if (image_create
# Line 306  Line 353 
353                   pEnc->mbParam.edged_height) < 0)                   pEnc->mbParam.edged_height) < 0)
354                  goto xvid_err_memory3;                  goto xvid_err_memory3;
355          if (image_create          if (image_create
                 (&pEnc->vInterVf, pEnc->mbParam.edged_width,  
                  pEnc->mbParam.edged_height) < 0)  
                 goto xvid_err_memory3;  
         if (image_create  
356                  (&pEnc->vInterHV, pEnc->mbParam.edged_width,                  (&pEnc->vInterHV, pEnc->mbParam.edged_width,
357                   pEnc->mbParam.edged_height) < 0)                   pEnc->mbParam.edged_height) < 0)
358                  goto xvid_err_memory3;                  goto xvid_err_memory3;
         if (image_create  
                 (&pEnc->vInterHVf, pEnc->mbParam.edged_width,  
                  pEnc->mbParam.edged_height) < 0)  
                 goto xvid_err_memory3;  
359    
360  /* Create full bitplane for GMC, this might be wasteful */  /* Create full bitplane for GMC, this might be wasteful */
361          if (image_create          if (image_create
# Line 324  Line 363 
363                   pEnc->mbParam.edged_height) < 0)                   pEnc->mbParam.edged_height) < 0)
364                  goto xvid_err_memory3;                  goto xvid_err_memory3;
365    
366            /* init bframe image buffers */
367    
368            pEnc->bframenum_head = 0;
369          pEnc->mbParam.global = pParam->global;          pEnc->bframenum_tail = 0;
370            pEnc->flush_bframes = 0;
371            pEnc->closed_bframenum = -1;
372    
373          /* B Frames specific init */          /* B Frames specific init */
         pEnc->mbParam.max_bframes = pParam->max_bframes;  
         pEnc->mbParam.bquant_ratio = pParam->bquant_ratio;  
         pEnc->mbParam.bquant_offset = pParam->bquant_offset;  
         pEnc->mbParam.frame_drop_ratio = pParam->frame_drop_ratio;  
374          pEnc->bframes = NULL;          pEnc->bframes = NULL;
375    
376          if (pEnc->mbParam.max_bframes > 0) {          if (pEnc->mbParam.max_bframes > 0) {
                 int n;  
377    
378                  pEnc->bframes =                  pEnc->bframes =
379                          xvid_malloc(pEnc->mbParam.max_bframes * sizeof(FRAMEINFO *),                          xvid_malloc(pEnc->mbParam.max_bframes * sizeof(FRAMEINFO *),
# Line 372  Line 409 
409                  }                  }
410          }          }
411    
412          pEnc->bframenum_head = 0;          /* init incoming frame queue */
413          pEnc->bframenum_tail = 0;          pEnc->queue_head = 0;
414          pEnc->flush_bframes = 0;          pEnc->queue_tail = 0;
415          pEnc->bframenum_dx50bvop = -1;          pEnc->queue_size = 0;
   
         pEnc->queue = NULL;  
   
   
         if (pEnc->mbParam.max_bframes > 0) {  
                 int n;  
416    
417                  pEnc->queue =                  pEnc->queue =
418                          xvid_malloc(pEnc->mbParam.max_bframes * sizeof(IMAGE),                  xvid_malloc((pEnc->mbParam.max_bframes+1) * sizeof(QUEUEINFO),
419                                                  CACHE_LINE);                                                  CACHE_LINE);
420    
421                  if (pEnc->queue == NULL)                  if (pEnc->queue == NULL)
422                          goto xvid_err_memory4;                          goto xvid_err_memory4;
423    
424                  for (n = 0; n < pEnc->mbParam.max_bframes; n++)          for (n = 0; n < pEnc->mbParam.max_bframes+1; n++)
425                          image_null(&pEnc->queue[n]);                  image_null(&pEnc->queue[n].image);
426    
427                  for (n = 0; n < pEnc->mbParam.max_bframes; n++) {  
428            for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) {
429                          if (image_create                          if (image_create
430                                  (&pEnc->queue[n], pEnc->mbParam.edged_width,                          (&pEnc->queue[n].image, pEnc->mbParam.edged_width,
431                                   pEnc->mbParam.edged_height) < 0)                                   pEnc->mbParam.edged_height) < 0)
432                                  goto xvid_err_memory5;                                  goto xvid_err_memory5;
   
                 }  
433          }          }
434    
435          pEnc->queue_head = 0;          /* timestamp stuff */
         pEnc->queue_tail = 0;  
         pEnc->queue_size = 0;  
436    
437          pEnc->mbParam.m_stamp = 0;          pEnc->mbParam.m_stamp = 0;
438            pEnc->m_framenum = create->start_frame_num;
         pEnc->m_framenum = 0;  
439          pEnc->current->stamp = 0;          pEnc->current->stamp = 0;
440          pEnc->reference->stamp = 0;          pEnc->reference->stamp = 0;
441    
442          pParam->handle = (void *) pEnc;          /* other stuff */
443    
444            pEnc->iFrameNum = 0;
445            pEnc->fMvPrevSigma = -1;
446    
447            /* slices */
448            pEnc->num_slices = MIN(MAX(1, create->num_slices), (int) pEnc->mbParam.mb_height);
449    
450            /* multithreaded stuff */
451            if (create->num_threads > 0) {
452                    int t = MIN(create->num_threads, (int) (pEnc->mbParam.mb_height>>1)); /* at least two rows per thread */
453                    int threads_per_slice = MAX(1, (t / pEnc->num_slices));
454                    int rows_per_thread = (pEnc->mbParam.mb_height + threads_per_slice - 1) / threads_per_slice;
455    
456                    pEnc->num_threads = t;
457                    pEnc->smpData = xvid_malloc(t*sizeof(SMPData), CACHE_LINE);
458                    if (!pEnc->smpData)
459                            goto xvid_err_nosmp;
460    
461                    /* tmp bitstream buffer for slice coding */
462                    pEnc->smpData[0].tmp_buffer = xvid_malloc(16*pEnc->mbParam.edged_width*pEnc->mbParam.mb_height*sizeof(uint8_t), CACHE_LINE);
463                    if (! pEnc->smpData[0].tmp_buffer) goto xvid_err_nosmp;
464    
465          if (pParam->rc_bitrate) {                  for (n = 0; n < t; n++) {
466                  RateControlInit(&pEnc->rate_control, pParam->rc_bitrate,                          int s = MIN(pEnc->num_threads, pEnc->num_slices);
467                                                  pParam->rc_reaction_delay_factor,  
468                                                  pParam->rc_averaging_period, pParam->rc_buffer,                          pEnc->smpData[n].complete_count_self =
469                                                  pParam->fbase * 1000 / pParam->fincr,                                  xvid_malloc(rows_per_thread * sizeof(int), CACHE_LINE);
470                                                  pParam->max_quantizer, pParam->min_quantizer);  
471                            if (!pEnc->smpData[n].complete_count_self)
472                                    goto xvid_err_nosmp;
473    
474                            if (n > 0 && n < s) {
475                                    pEnc->smpData[n].bs = (Bitstream *) xvid_malloc(sizeof(Bitstream), CACHE_LINE);
476                                    if (!pEnc->smpData[n].bs)
477                                            goto xvid_err_nosmp;
478    
479                                    pEnc->smpData[n].sStat = (Statistics *) xvid_malloc(sizeof(Statistics), CACHE_LINE);
480                                    if (!pEnc->smpData[n].sStat)
481                                            goto xvid_err_nosmp;
482    
483                                    pEnc->smpData[n].tmp_buffer = pEnc->smpData[0].tmp_buffer + 16*(((n-1)*pEnc->mbParam.edged_width*pEnc->mbParam.mb_height)/s);
484                                    BitstreamInit(pEnc->smpData[n].bs, pEnc->smpData[n].tmp_buffer, 0);
485                            }
486    
487                            if (n != 0)
488                                    pEnc->smpData[n].complete_count_above =
489                                            pEnc->smpData[n-1].complete_count_self;
490                    }
491                    pEnc->smpData[0].complete_count_above =
492                            pEnc->smpData[t-1].complete_count_self - 1;
493    
494            } else {
495      xvid_err_nosmp:
496                    /* no SMP */
497                    if (pEnc->smpData) {
498                            if (pEnc->smpData[0].tmp_buffer)
499                                    xvid_free(pEnc->smpData[0].tmp_buffer);
500                    }
501                    else {
502                            pEnc->smpData = xvid_malloc(1*sizeof(SMPData), CACHE_LINE);
503                            if (pEnc->smpData == NULL)
504                                    goto xvid_err_memory5;
505                    }
506    
507                    create->num_threads = 0;
508          }          }
509    
510            create->handle = (void *) pEnc;
511    
512          init_timer();          init_timer();
513            init_mpeg_matrix(pEnc->mbParam.mpeg_quant_matrices);
514    
515          return XVID_ERR_OK;          return 0;   /* ok */
516    
517          /*          /*
518           * We handle all XVID_ERR_MEMORY here, this makes the code lighter           * We handle all XVID_ERR_MEMORY here, this makes the code lighter
# Line 432  Line 520 
520    
521    xvid_err_memory5:    xvid_err_memory5:
522    
523            for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) {
524          if (pEnc->mbParam.max_bframes > 0) {                          image_destroy(&pEnc->queue[n].image, pEnc->mbParam.edged_width,
   
                 for (i = 0; i < pEnc->mbParam.max_bframes; i++) {  
                         image_destroy(&pEnc->queue[i], pEnc->mbParam.edged_width,  
525                                                    pEnc->mbParam.edged_height);                                                    pEnc->mbParam.edged_height);
526                  }                  }
527    
528                  xvid_free(pEnc->queue);                  xvid_free(pEnc->queue);
         }  
529    
530    xvid_err_memory4:    xvid_err_memory4:
531    
532          if (pEnc->mbParam.max_bframes > 0) {          if (pEnc->mbParam.max_bframes > 0) {
533                    int i;
534    
535                  for (i = 0; i < pEnc->mbParam.max_bframes; i++) {                  for (i = 0; i < pEnc->mbParam.max_bframes; i++) {
536    
# Line 453  Line 539 
539    
540                          image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,                          image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,
541                                                    pEnc->mbParam.edged_height);                                                    pEnc->mbParam.edged_height);
   
542                          xvid_free(pEnc->bframes[i]->mbs);                          xvid_free(pEnc->bframes[i]->mbs);
   
543                          xvid_free(pEnc->bframes[i]);                          xvid_free(pEnc->bframes[i]);
   
544                  }                  }
545    
546                  xvid_free(pEnc->bframes);                  xvid_free(pEnc->bframes);
# Line 465  Line 548 
548    
549    xvid_err_memory3:    xvid_err_memory3:
550    
551          if (pEnc->mbParam.global & XVID_GLOBAL_EXTRASTATS)          if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
552          {       image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,                  image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
553                                              pEnc->mbParam.edged_height);
554                    image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width,
555                                            pEnc->mbParam.edged_height);                                            pEnc->mbParam.edged_height);
556          }          }
557    
# Line 485  Line 570 
570                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
571          image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,          image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
572                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
         image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,  
                                   pEnc->mbParam.edged_height);  
573          image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,          image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
574                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
         image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,  
                                   pEnc->mbParam.edged_height);  
575    
576  /* destroy GMC image */  /* destroy GMC image */
577          image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width,          image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width,
578                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
579    
580      xvid_err_memory2a:
581            xvid_free(pEnc->mbParam.mpeg_quant_matrices);
582    
583    xvid_err_memory2:    xvid_err_memory2:
584          xvid_free(pEnc->current->mbs);          xvid_free(pEnc->current->mbs);
# Line 504  Line 587 
587    xvid_err_memory1:    xvid_err_memory1:
588          xvid_free(pEnc->current);          xvid_free(pEnc->current);
589          xvid_free(pEnc->reference);          xvid_free(pEnc->reference);
590    
591      xvid_err_memory1a:
592            if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
593                    xvid_free(pEnc->temp_dquants);
594            }
595    
596            if(pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
597                    xvid_free(pEnc->temp_lambda);
598            }
599    
600      xvid_err_memory0:
601            for (n=0; n<pEnc->num_plugins;n++) {
602                    if (pEnc->plugins[n].func) {
603                            pEnc->plugins[n].func(pEnc->plugins[n].param, XVID_PLG_DESTROY, NULL, NULL);
604                    }
605            }
606            xvid_free(pEnc->plugins);
607    
608            xvid_free(pEnc->zones);
609    
610          xvid_free(pEnc);          xvid_free(pEnc);
611    
612          pParam->handle = NULL;          create->handle = NULL;
613    
614          return XVID_ERR_MEMORY;          return XVID_ERR_MEMORY;
615  }  }
# Line 515  Line 618 
618   * Encoder destruction   * Encoder destruction
619   *   *
620   * This function destroy the entire encoder structure created by a previous   * This function destroy the entire encoder structure created by a previous
621   * successful encoder_create call.   * successful enc_create call.
622   *   *
623   * Returned values (for now only one returned value) :   * Returned values (for now only one returned value) :
624   *    - XVID_ERR_OK     - no errors   *      - 0      - no errors
625   *   *
626   ****************************************************************************/   ****************************************************************************/
627    
628  int  int
629  encoder_destroy(Encoder * pEnc)  enc_destroy(Encoder * pEnc)
630  {  {
631          int i;          int i;
632    
         ENC_CHECK(pEnc);  
   
633          /* B Frames specific */          /* B Frames specific */
634          if (pEnc->mbParam.max_bframes > 0) {          for (i = 0; i < pEnc->mbParam.max_bframes+1; i++) {
635                    image_destroy(&pEnc->queue[i].image, pEnc->mbParam.edged_width,
                 for (i = 0; i < pEnc->mbParam.max_bframes; i++) {  
   
                         image_destroy(&pEnc->queue[i], pEnc->mbParam.edged_width,  
636                                            pEnc->mbParam.edged_height);                                            pEnc->mbParam.edged_height);
637                  }                  }
                 xvid_free(pEnc->queue);  
         }  
638    
639            xvid_free(pEnc->queue);
640    
641          if (pEnc->mbParam.max_bframes > 0) {          if (pEnc->mbParam.max_bframes > 0) {
642    
# Line 550  Line 647 
647    
648                          image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,                          image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,
649                                            pEnc->mbParam.edged_height);                                            pEnc->mbParam.edged_height);
   
650                          xvid_free(pEnc->bframes[i]->mbs);                          xvid_free(pEnc->bframes[i]->mbs);
   
651                          xvid_free(pEnc->bframes[i]);                          xvid_free(pEnc->bframes[i]);
652                  }                  }
653    
# Line 570  Line 665 
665                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
666          image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,          image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
667                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
         image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,  
                                   pEnc->mbParam.edged_height);  
668          image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,          image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
669                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
         image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,  
                                   pEnc->mbParam.edged_height);  
   
670          image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width,          image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width,
671                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
672          image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width,          image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width,
673                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
674          image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width,          image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width,
675                                    pEnc->mbParam.edged_height);                                    pEnc->mbParam.edged_height);
676            image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width,
677                                      pEnc->mbParam.edged_height);
678    
679          if (pEnc->mbParam.global & XVID_GLOBAL_EXTRASTATS)          if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
680          {       image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,                  image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
681                                              pEnc->mbParam.edged_height);
682                    image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width,
683                                            pEnc->mbParam.edged_height);                                            pEnc->mbParam.edged_height);
684          }          }
685    
# Line 597  Line 691 
691          xvid_free(pEnc->reference->mbs);          xvid_free(pEnc->reference->mbs);
692          xvid_free(pEnc->reference);          xvid_free(pEnc->reference);
693    
694          xvid_free(pEnc);          if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
695                    xvid_free(pEnc->temp_dquants);
         return XVID_ERR_OK;  
696  }  }
697    
698            if ((pEnc->mbParam.plugin_flags & XVID_REQLAMBDA)) {
699  static __inline void inc_frame_num(Encoder * pEnc)                  xvid_free(pEnc->temp_lambda);
 {  
         pEnc->current->stamp = pEnc->mbParam.m_stamp;   // first frame is zero  
         pEnc->mbParam.m_stamp += pEnc->mbParam.fincr;  
700  }  }
701    
702            if (pEnc->num_plugins>0) {
703                    xvid_plg_destroy_t pdestroy;
704                    memset(&pdestroy, 0, sizeof(xvid_plg_destroy_t));
705    
706  static __inline void                  pdestroy.version = XVID_VERSION;
707  queue_image(Encoder * pEnc, XVID_ENC_FRAME * pFrame)                  pdestroy.num_frames = pEnc->m_framenum;
 {  
         if (pEnc->queue_size >= pEnc->mbParam.max_bframes)  
         {  
                 DPRINTF(DPRINTF_DEBUG,"FATAL: QUEUE FULL");  
                 return;  
         }  
708    
709          DPRINTF(DPRINTF_DEBUG,"*** QUEUE bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",                  for (i=0; i<pEnc->num_plugins;i++) {
710                                  pEnc->bframenum_head, pEnc->bframenum_tail,                          if (pEnc->plugins[i].func) {
711                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);                                  pEnc->plugins[i].func(pEnc->plugins[i].param, XVID_PLG_DESTROY, &pdestroy, NULL);
712                            }
713                    }
714                    xvid_free(pEnc->plugins);
715            }
716    
717            xvid_free(pEnc->mbParam.mpeg_quant_matrices);
718    
719          start_timer();          if (pEnc->num_zones > 0)
720          if (image_input                  xvid_free(pEnc->zones);
                 (&pEnc->queue[pEnc->queue_tail], pEnc->mbParam.width, pEnc->mbParam.height,  
                  pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING))  
                 return;  
         stop_conv_timer();  
721    
722          if ((pFrame->general & XVID_CHROMAOPT)) {          if (pEnc->num_threads > 0) {
723                  image_chroma_optimize(&pEnc->queue[pEnc->queue_tail],                  for (i = 1; i < MAX(1, MIN(pEnc->num_threads, pEnc->num_slices)); i++) {
724                          pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);                          xvid_free(pEnc->smpData[i].bs);
725                            xvid_free(pEnc->smpData[i].sStat);
726          }          }
727                    if (pEnc->smpData[0].tmp_buffer) xvid_free(pEnc->smpData[0].tmp_buffer);
728    
729          pEnc->queue_size++;                  for (i = 0; i < pEnc->num_threads; i++)
730          pEnc->queue_tail =  (pEnc->queue_tail + 1) % pEnc->mbParam.max_bframes;                          xvid_free(pEnc->smpData[i].complete_count_self);
731  }  }
732            xvid_free(pEnc->smpData);
733    
734  static __inline void          xvid_free(pEnc);
 set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base)  
 {  
   
                 pCur->ticks = (int32_t)pCur->stamp % time_base;  
                 pCur->seconds =  ((int32_t)pCur->stamp / time_base)     - ((int32_t)pRef->stamp / time_base) ;  
   
                 //HEAVY DEBUG OUTPUT    remove when timecodes prove to be stable  
   
 /*              fprintf(stderr,"WriteVop:   %d - %d \n",  
                         ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base));  
                 fprintf(stderr,"set_timecodes: VOP %1d   stamp=%lld ref_stamp=%lld  base=%d\n",  
                         pCur->coding_type, pCur->stamp, pRef->stamp, time_base);  
                 fprintf(stderr,"set_timecodes: VOP %1d   seconds=%d   ticks=%d   (ref-sec=%d  ref-tick=%d)\n",  
                         pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks);  
735    
736  */          return 0;  /* ok */
737  }  }
738    
739    
740    /*
741      call the plugins
742      */
743    
744  /* convert pFrame->intra to coding_type */  static void call_plugins(Encoder * pEnc, FRAMEINFO * frame, IMAGE * original,
745  static int intra2coding_type(int intra)                                                   int opt, int * type, int * quant, xvid_enc_stats_t * stats)
746  {  {
747          if (intra < 0)  return -1;          unsigned int i, j, k;
748          if (intra == 1) return I_VOP;          xvid_plg_data_t data;
         if (intra == 2) return B_VOP;  
749    
750          return P_VOP;          /* set data struct */
 }  
751    
752            memset(&data, 0, sizeof(xvid_plg_data_t));
753            data.version = XVID_VERSION;
754    
755            /* find zone */
756            for(i=0; i<pEnc->num_zones && pEnc->zones[i].frame<=frame->frame_num; i++) ;
757            data.zone = i>0 ? &pEnc->zones[i-1] : NULL;
758    
759            data.width = pEnc->mbParam.width;
760            data.height = pEnc->mbParam.height;
761            data.mb_width = pEnc->mbParam.mb_width;
762            data.mb_height = pEnc->mbParam.mb_height;
763            data.fincr = frame->fincr;
764            data.fbase = pEnc->mbParam.fbase;
765            data.bquant_ratio = pEnc->mbParam.bquant_ratio;
766            data.bquant_offset = pEnc->mbParam.bquant_offset;
767    
768            for (i=0; i<3; i++) {
769                    data.min_quant[i] = pEnc->mbParam.min_quant[i];
770                    data.max_quant[i] = pEnc->mbParam.max_quant[i];
771            }
772    
773            data.reference.csp = XVID_CSP_PLANAR;
774            data.reference.plane[0] = pEnc->reference->image.y;
775            data.reference.plane[1] = pEnc->reference->image.u;
776            data.reference.plane[2] = pEnc->reference->image.v;
777            data.reference.stride[0] = pEnc->mbParam.edged_width;
778            data.reference.stride[1] = pEnc->mbParam.edged_width/2;
779            data.reference.stride[2] = pEnc->mbParam.edged_width/2;
780    
781            data.current.csp = XVID_CSP_PLANAR;
782            data.current.plane[0] = frame->image.y;
783            data.current.plane[1] = frame->image.u;
784            data.current.plane[2] = frame->image.v;
785            data.current.stride[0] = pEnc->mbParam.edged_width;
786            data.current.stride[1] = pEnc->mbParam.edged_width/2;
787            data.current.stride[2] = pEnc->mbParam.edged_width/2;
788    
789            data.frame_num = frame->frame_num;
790    
791            if (opt == XVID_PLG_BEFORE) {
792                    data.type = *type;
793                    data.quant = *quant;
794    
795                    data.vol_flags = frame->vol_flags;
796                    data.vop_flags = frame->vop_flags;
797                    data.motion_flags = frame->motion_flags;
798    
799            } else if (opt == XVID_PLG_FRAME) {
800                    data.type = coding2type(frame->coding_type);
801                    data.quant = frame->quant;
802    
803                    if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
804                            data.dquant = pEnc->temp_dquants;
805                            data.dquant_stride = pEnc->mbParam.mb_width;
806                            memset(data.dquant, 0, data.mb_width*data.mb_height*sizeof(int));
807                    }
808    
809                    if(pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
810                            int block = 0;
811                            emms();
812                            data.lambda = pEnc->temp_lambda;
813                            for(i = 0;i < pEnc->mbParam.mb_height; i++)
814                                    for(j = 0;j < pEnc->mbParam.mb_width; j++)
815                                            for (k = 0; k < 6; k++)
816                                                    data.lambda[block++] = 1.0f;
817                    }
818    
819            } else { /* XVID_PLG_AFTER */
820                    if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
821                            data.original.csp = XVID_CSP_PLANAR;
822                            data.original.plane[0] = original->y;
823                            data.original.plane[1] = original->u;
824                            data.original.plane[2] = original->v;
825                            data.original.stride[0] = pEnc->mbParam.edged_width;
826                            data.original.stride[1] = pEnc->mbParam.edged_width/2;
827                            data.original.stride[2] = pEnc->mbParam.edged_width/2;
828                    }
829    
830  /*****************************************************************************                  if ((frame->vol_flags & XVID_VOL_EXTRASTATS) ||
831   * IPB frame encoder entry point                          (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) {
  *  
  * Returned values :  
  *    - XVID_ERR_OK     - no errors  
  *    - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong  
  *                        format  
  ****************************************************************************/  
832    
833  int                          data.sse_y =
834  encoder_encode_bframes(Encoder * pEnc,                                  plane_sse( original->y, frame->image.y,
835                             XVID_ENC_FRAME * pFrame,                                                     pEnc->mbParam.edged_width, pEnc->mbParam.width,
836                             XVID_ENC_STATS * pResult)                                                     pEnc->mbParam.height);
 {  
         uint16_t x, y;  
         Bitstream bs;  
         uint32_t bits;  
         int mode;  
837    
838          int input_valid = 1;                          data.sse_u =
839          int bframes_count = 0;                                  plane_sse( original->u, frame->image.u,
840                                                       pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,
841                                                       pEnc->mbParam.height/2);
842    
843          ENC_CHECK(pEnc);                          data.sse_v =
844          ENC_CHECK(pFrame);                                  plane_sse( original->v, frame->image.v,
845          ENC_CHECK(pFrame->image);                                                     pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,
846                                                       pEnc->mbParam.height/2);
847                    }
848    
849          start_global_timer();                  data.type = coding2type(frame->coding_type);
850                    data.quant = frame->quant;
851    
852          BitstreamInit(&bs, pFrame->bitstream, 0);                  if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
853                            data.dquant = pEnc->temp_dquants;
854                            data.dquant_stride = pEnc->mbParam.mb_width;
855    
856                            for (j=0; j<pEnc->mbParam.mb_height; j++)
857                            for (i=0; i<pEnc->mbParam.mb_width; i++) {
858                                    data.dquant[j*data.dquant_stride + i] = frame->mbs[j*pEnc->mbParam.mb_width + i].dquant;
859                            }
860                    }
861    
862  ipvop_loop:                  data.vol_flags = frame->vol_flags;
863                    data.vop_flags = frame->vop_flags;
864                    data.motion_flags = frame->motion_flags;
865    
866                    data.length = frame->length;
867                    data.kblks = frame->sStat.kblks;
868                    data.mblks = frame->sStat.mblks;
869                    data.ublks = frame->sStat.ublks;
870    
871                    /* New code */
872                    data.stats.type      = coding2type(frame->coding_type);
873                    data.stats.quant     = frame->quant;
874                    data.stats.vol_flags = frame->vol_flags;
875                    data.stats.vop_flags = frame->vop_flags;
876                    data.stats.length    = frame->length;
877                    data.stats.hlength   = frame->length - (frame->sStat.iTextBits / 8);
878                    data.stats.kblks     = frame->sStat.kblks;
879                    data.stats.mblks     = frame->sStat.mblks;
880                    data.stats.ublks     = frame->sStat.ublks;
881                    data.stats.sse_y     = data.sse_y;
882                    data.stats.sse_u     = data.sse_u;
883                    data.stats.sse_v     = data.sse_v;
884    
885          /*                  if (stats)
886           * bframe "flush" code                          *stats = data.stats;
887           */          }
888    
889          if ((pFrame->image == NULL || pEnc->flush_bframes)          /* call plugins */
890                  && (pEnc->bframenum_head < pEnc->bframenum_tail)) {          for (i=0; i<(unsigned int)pEnc->num_plugins;i++) {
891                    emms();
892                    if (pEnc->plugins[i].func) {
893                            if (pEnc->plugins[i].func(pEnc->plugins[i].param, opt, &data, NULL) < 0) {
894                                    continue;
895                            }
896                    }
897            }
898            emms();
899    
900                  if (pEnc->flush_bframes == 0) {          /* copy modified values back into frame*/
901                          /*          if (opt == XVID_PLG_BEFORE) {
902                           * we have reached the end of stream without getting                  *type = data.type;
903                           * a future reference frame... so encode last final                  *quant = data.quant > 0 ? data.quant : 2;   /* default */
                          * frame as a pframe  
                          */  
904    
905                          DPRINTF(DPRINTF_DEBUG,"*** BFRAME (final frame) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",                  frame->vol_flags = data.vol_flags;
906                                  pEnc->bframenum_head, pEnc->bframenum_tail,                  frame->vop_flags = data.vop_flags;
907                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);                  frame->motion_flags = data.motion_flags;
908    
909                          pEnc->bframenum_tail--;          } else if (opt == XVID_PLG_FRAME) {
                         SWAP(FRAMEINFO *, pEnc->current, pEnc->reference);  
910    
911                          SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);                  if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
912                            for (j=0; j<pEnc->mbParam.mb_height; j++)
913                            for (i=0; i<pEnc->mbParam.mb_width; i++) {
914                                    frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = data.dquant[j*data.mb_width + i];
915                            }
916                    } else {
917                            for (j=0; j<pEnc->mbParam.mb_height; j++)
918                            for (i=0; i<pEnc->mbParam.mb_width; i++) {
919                                    frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = 0;
920                            }
921                    }
922    
923                          FrameCodeP(pEnc, &bs, &bits, 1, 0);                  if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
924                          bframes_count = 0;                          for (j = 0; j < pEnc->mbParam.mb_height; j++)
925                                    for (i = 0; i < pEnc->mbParam.mb_width; i++)
926                                            for (k = 0; k < 6; k++) {
927                                                    frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] =
928                                                            (int) ((float)(1<<LAMBDA_EXP) * data.lambda[6 * (j * data.mb_width + i) + k]);
929                                            }
930                    } else {
931                            for (j = 0; j<pEnc->mbParam.mb_height; j++)
932                                    for (i = 0; i<pEnc->mbParam.mb_width; i++)
933                                            for (k = 0; k < 6; k++) {
934                                                    frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] = 1<<LAMBDA_EXP;
935                                            }
936                    }
937    
                         BitstreamPadAlways(&bs);  
                         pFrame->length = BitstreamLength(&bs);  
                         pFrame->intra = 0;  
938    
939                    frame->mbs[0].quant = data.quant; /* FRAME will not affect the quant in stats */
940            }
941    
                         emms();  
942    
                         if (pResult) {  
                                 pResult->quant = pEnc->current->quant;  
                                 pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);  
                                 pResult->kblks = pEnc->current->sStat.kblks;  
                                 pResult->mblks = pEnc->current->sStat.mblks;  
                                 pResult->ublks = pEnc->current->sStat.ublks;  
943                          }                          }
944    
                         return XVID_ERR_OK;  
                 }  
945    
946    static __inline void inc_frame_num(Encoder * pEnc)
947    {
948            pEnc->current->frame_num = pEnc->m_framenum;
949            pEnc->current->stamp = pEnc->mbParam.m_stamp;   /* first frame is zero */
950    
951                  DPRINTF(DPRINTF_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",          pEnc->mbParam.m_stamp += pEnc->current->fincr;
952                                  pEnc->bframenum_head, pEnc->bframenum_tail,          pEnc->m_framenum++;     /* debug ticker */
                                 pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);  
   
                 FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs, &bits);  
                 pEnc->bframenum_head++;  
   
                 BitstreamPadAlways(&bs);  
                 pFrame->length = BitstreamLength(&bs);  
                 pFrame->intra = 2;  
   
                 if (pResult) {  
                         pResult->quant = pEnc->current->quant;  
                         pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);  
                         pResult->kblks = pEnc->current->sStat.kblks;  
                         pResult->mblks = pEnc->current->sStat.mblks;  
                         pResult->ublks = pEnc->current->sStat.ublks;  
953                  }                  }
954    
955                  if (input_valid)  static __inline void dec_frame_num(Encoder * pEnc)
956                          queue_image(pEnc, pFrame);  {
957            pEnc->mbParam.m_stamp -= pEnc->mbParam.fincr;
958                  emms();          pEnc->m_framenum--;     /* debug ticker */
   
                 return XVID_ERR_OK;  
959          }          }
960    
961          if (pEnc->bframenum_head > 0) {  static __inline void
962                  pEnc->bframenum_head = pEnc->bframenum_tail = 0;  MBSetDquant(MACROBLOCK * pMB, int x, int y, MBParam * mbParam)
963    {
964                  /* write an empty marker to the bitstream.          if (pMB->cbp == 0) {
965                    /* we want to code dquant but the quantizer value will not be used yet
966                     for divx5 decoder compatibility, this marker must consist                          let's find out if we can postpone dquant to next MB
                    of a not-coded p-vop, with a time_base of zero, and time_increment  
                    indentical to the future-referece frame.  
967                  */                  */
968                    if (x == mbParam->mb_width-1 && y == mbParam->mb_height-1) {
969                            pMB->dquant = 0; /* it's the last MB of all, the easiest case */
970                            return;
971                    } else {
972                            MACROBLOCK * next = pMB + 1;
973                            const MACROBLOCK * prev = pMB - 1;
974                            if (next->mode != MODE_INTER4V && next->mode != MODE_NOT_CODED)
975                                    /* mode allows dquant change in the future */
976                                    if (abs(next->quant - prev->quant) <= 2) {
977                                            /* quant change is not out of range */
978                                            pMB->quant = prev->quant;
979                                            pMB->dquant = 0;
980                                            next->dquant = next->quant - prev->quant;
981                                            return;
982                                    }
983                    }
984            }
985            /* couldn't skip this dquant */
986            pMB->mode = MODE_INTER_Q;
987    }
988    
                 if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED)) {  
                         int tmp;  
   
                         DPRINTF(DPRINTF_DEBUG,"*** EMPTY bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",  
                                 pEnc->bframenum_head, pEnc->bframenum_tail,  
                                 pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);  
989    
990    
991                          tmp = pEnc->current->seconds;  static __inline void
992                          pEnc->current->seconds = 0; /* force time_base = 0 */  set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base)
993    {
994    
995                          BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0);          pCur->ticks = (int32_t)pCur->stamp % time_base;
996                          pEnc->current->seconds = tmp;          pCur->seconds =  ((int32_t)pCur->stamp / time_base)     - ((int32_t)pRef->stamp / time_base) ;
997    
998                          BitstreamPadAlways(&bs);  #if 0   /* HEAVY DEBUG OUTPUT */
999                          pFrame->length = BitstreamLength(&bs);          fprintf(stderr,"WriteVop:   %d - %d \n",
1000                          pFrame->intra = 4;                          ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base));
1001            fprintf(stderr,"set_timecodes: VOP %1d   stamp=%lld ref_stamp=%lld  base=%d\n",
1002                          if (pResult) {                          pCur->coding_type, pCur->stamp, pRef->stamp, time_base);
1003                                  pResult->quant = pEnc->current->quant;          fprintf(stderr,"set_timecodes: VOP %1d   seconds=%d   ticks=%d   (ref-sec=%d  ref-tick=%d)\n",
1004                                  pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);                          pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks);
1005                                  pResult->kblks = pEnc->current->sStat.kblks;  #endif
                                 pResult->mblks = pEnc->current->sStat.mblks;  
                                 pResult->ublks = pEnc->current->sStat.ublks;  
1006                          }                          }
1007    
1008                          if (input_valid)  static void
1009                                  queue_image(pEnc, pFrame);  simplify_par(int *par_width, int *par_height)
1010    {
1011    
1012            int _par_width  = (!*par_width)  ? 1 : (*par_width<0)  ? -*par_width:  *par_width;
1013            int _par_height = (!*par_height) ? 1 : (*par_height<0) ? -*par_height: *par_height;
1014            int divisor = gcd(_par_width, _par_height);
1015    
1016            _par_width  /= divisor;
1017            _par_height /= divisor;
1018    
1019            /* 2^8 precision maximum */
1020            if (_par_width>255 || _par_height>255) {
1021                    float div;
1022                          emms();                          emms();
1023                    if (_par_width>_par_height)
1024                            div = (float)_par_width/255;
1025                    else
1026                            div = (float)_par_height/255;
1027    
1028                          return XVID_ERR_OK;                  _par_width  = (int)((float)_par_width/div);
1029                    _par_height = (int)((float)_par_height/div);
1030                  }                  }
1031    
1032            *par_width = _par_width;
1033            *par_height = _par_height;
1034    
1035            return;
1036          }          }
1037    
1038    /*****************************************************************************
1039     * IPB frame encoder entry point
1040     *
1041     * Returned values :
1042     *      - >0                       - output bytes
1043     *      - 0                             - no output
1044     *      - XVID_ERR_VERSION - wrong version passed to core
1045     *      - XVID_ERR_END   - End of stream reached before end of coding
1046     *      - XVID_ERR_FORMAT  - the image subsystem reported the image had a wrong
1047     *                                               format
1048     ****************************************************************************/
1049    
 bvop_loop:  
1050    
1051          if (pEnc->bframenum_dx50bvop != -1)  int
1052    enc_encode(Encoder * pEnc,
1053                               xvid_enc_frame_t * xFrame,
1054                               xvid_enc_stats_t * stats)
1055          {          {
1056            xvid_enc_frame_t * frame;
1057            int type;
1058            Bitstream bs;
1059    
1060                  SWAP(FRAMEINFO *, pEnc->current, pEnc->reference);          if (XVID_VERSION_MAJOR(xFrame->version) != 1 || (stats && XVID_VERSION_MAJOR(stats->version) != 1))     /* v1.x.x */
1061                  SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]);                  return XVID_ERR_VERSION;
1062    
1063                  if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {          xFrame->out_flags = 0;
                         image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP");  
                 }  
1064    
1065                  if (input_valid)          start_global_timer();
1066                  {          BitstreamInit(&bs, xFrame->bitstream, 0);
                         queue_image(pEnc, pFrame);  
                         input_valid = 0;  
                 }  
1067    
         } else if (input_valid) {  
1068    
1069                  SWAP(FRAMEINFO *, pEnc->current, pEnc->reference);          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070             * enqueue image to the encoding-queue
1071             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1072    
1073            if (xFrame->input.csp != XVID_CSP_NULL)
1074            {
1075                    QUEUEINFO * q = &pEnc->queue[pEnc->queue_tail];
1076    
1077                  start_timer();                  start_timer();
1078                  if (image_input                  if (image_input
1079                          (&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height,                          (&q->image, pEnc->mbParam.width, pEnc->mbParam.height,
1080                          pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING))                          pEnc->mbParam.edged_width, (uint8_t**)xFrame->input.plane, xFrame->input.stride,
1081                            xFrame->input.csp, xFrame->vol_flags & XVID_VOL_INTERLACING))
1082                  {                  {
1083                          emms();                          emms();
1084                          return XVID_ERR_FORMAT;                          return XVID_ERR_FORMAT;
1085                  }                  }
1086                  stop_conv_timer();                  stop_conv_timer();
1087    
1088                  if ((pFrame->general & XVID_CHROMAOPT)) {                  if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) {
1089                          image_chroma_optimize(&pEnc->current->image,                          image_chroma_optimize(&q->image,
1090                                  pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);                                  pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
1091                  }                  }
1092    
1093                  // queue input frame, and dequue next image                  q->frame = *xFrame;
1094                  if (pEnc->queue_size > 0)  
1095                  {                  if (xFrame->quant_intra_matrix)
                         image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_tail]);  
                         if (pEnc->queue_head != pEnc->queue_tail)  
1096                          {                          {
1097                                  image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head]);                          memcpy(q->quant_intra_matrix, xFrame->quant_intra_matrix, 64*sizeof(unsigned char));
1098                          }                          q->frame.quant_intra_matrix = q->quant_intra_matrix;
                         pEnc->queue_head =  (pEnc->queue_head + 1) % pEnc->mbParam.max_bframes;  
                         pEnc->queue_tail =  (pEnc->queue_tail + 1) % pEnc->mbParam.max_bframes;  
1099                  }                  }
1100    
1101          } else if (pEnc->queue_size > 0) {                  if (xFrame->quant_inter_matrix)
1102                    {
1103                            memcpy(q->quant_inter_matrix, xFrame->quant_inter_matrix, 64*sizeof(unsigned char));
1104                            q->frame.quant_inter_matrix = q->quant_inter_matrix;
1105                    }
1106    
1107                  SWAP(FRAMEINFO *, pEnc->current, pEnc->reference);                  pEnc->queue_tail = (pEnc->queue_tail + 1) % (pEnc->mbParam.max_bframes+1);
1108                    pEnc->queue_size++;
1109            }
1110    
                 image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head]);  
                 pEnc->queue_head =  (pEnc->queue_head + 1) % pEnc->mbParam.max_bframes;  
                 pEnc->queue_size--;  
1111    
1112          } else {          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113             * bframe flush code
1114             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1115    
1116                  /* if nothing was encoded, write an 'ignore this frame' flag  repeat:
                    to the bitstream */  
1117    
1118                  if (BitstreamPos(&bs) == 0) {          if (pEnc->flush_bframes)
1119            {
1120                    if (pEnc->bframenum_head < pEnc->bframenum_tail) {
1121    
1122                          DPRINTF(DPRINTF_DEBUG,"*** SKIP bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",                          DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1123                                  pEnc->bframenum_head, pEnc->bframenum_tail,                                  pEnc->bframenum_head, pEnc->bframenum_tail,
1124                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1125    
1126                  //      BitstreamPutBits(&bs, 0x7f, 8);                          if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1127                          pFrame->intra = 5;                                  image_copy(&pEnc->sOriginal2, &pEnc->bframes[pEnc->bframenum_head]->image,
1128                                                       pEnc->mbParam.edged_width, pEnc->mbParam.height);
                         if (pResult) {  
                                 /*  
                                  * We must decide what to put there because i know some apps  
                                  * are storing statistics about quantizers and just do  
                                  * stats[quant]++ or stats[quant-1]++  
                                  * transcode is one of these app with its 2pass module  
                                  */  
   
                                 /*  
                                  * For now i prefer 31 than 0 that could lead to a segfault  
                                  * in transcode  
                                  */  
                                 pResult->quant = 31;  
   
                                 pResult->hlength = 0;  
                                 pResult->kblks = 0;  
                                 pResult->mblks = 0;  
                                 pResult->ublks = 0;  
1129                          }                          }
1130    
1131                  } else {                          FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs);
1132                            call_plugins(pEnc, pEnc->bframes[pEnc->bframenum_head], &pEnc->sOriginal2, XVID_PLG_AFTER, NULL, NULL, stats);
1133                          if (pResult) {                          pEnc->bframenum_head++;
                                 pResult->quant = pEnc->current->quant;  
                                 pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);  
                                 pResult->kblks = pEnc->current->sStat.kblks;  
                                 pResult->mblks = pEnc->current->sStat.mblks;  
                                 pResult->ublks = pEnc->current->sStat.ublks;  
                         }  
1134    
1135                            goto done;
1136                  }                  }
1137    
1138                  pFrame->length = BitstreamLength(&bs);                  /* write an empty marker to the bitstream.
   
                 emms();  
1139    
1140                  return XVID_ERR_OK;                     for divx5 decoder compatibility, this marker must consist
1141          }                     of a not-coded p-vop, with a time_base of zero, and time_increment
1142                       indentical to the future-referece frame.
1143                    */
1144    
1145          pEnc->flush_bframes = 0;                  if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED && pEnc->bframenum_tail > 0)) {
1146                            int tmp;
1147                            int bits;
1148    
1149          emms();                          DPRINTF(XVID_DEBUG_DEBUG,"*** EMPTY bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1150                                    pEnc->bframenum_head, pEnc->bframenum_tail,
1151                                    pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1152    
1153          // only inc frame num, adapt quant, etc. if we havent seen it before                          bits = BitstreamPos(&bs);
         if (pEnc->bframenum_dx50bvop < 0 )  
         {  
                 mode = intra2coding_type(pFrame->intra);  
                 if (pFrame->quant == 0)  
                         pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0);  
                 else  
                         pEnc->current->quant = pFrame->quant;  
1154    
1155  /*              if (pEnc->current->quant < 1)                          tmp = pEnc->current->seconds;
1156                          pEnc->current->quant = 1;                          pEnc->current->seconds = 0; /* force time_base = 0 */
1157    
1158                  if (pEnc->current->quant > 31)                          BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0, pEnc->current->quant);
1159                          pEnc->current->quant = 31;                          BitstreamPad(&bs);
1160  */                          pEnc->current->seconds = tmp;
                 pEnc->current->global_flags = pFrame->general;  
                 pEnc->current->motion_flags = pFrame->motion;  
1161    
1162                  /* ToDo : dynamic fcode (in both directions) */                          /* add the not-coded length to the reference frame size */
1163                  pEnc->current->fcode = pEnc->mbParam.m_fcode;                          pEnc->current->length += (BitstreamPos(&bs) - bits) / 8;
1164                  pEnc->current->bcode = pEnc->mbParam.m_fcode;                          call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
1165    
1166                  inc_frame_num(pEnc);                          /* flush complete: reset counters */
1167                            pEnc->flush_bframes = 0;
1168                            pEnc->bframenum_head = pEnc->bframenum_tail = 0;
1169                            goto done;
1170    
                 if (pFrame->general & XVID_EXTRASTATS)  
                 {       image_copy(&pEnc->sOriginal, &pEnc->current->image,  
                                    pEnc->mbParam.edged_width, pEnc->mbParam.height);  
1171                  }                  }
1172    
1173                  emms();                  /* flush complete: reset counters */
1174                    pEnc->flush_bframes = 0;
1175                  if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {                  pEnc->bframenum_head = pEnc->bframenum_tail = 0;
                         image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5,  
                                 "%i  if:%i  st:%i", pEnc->m_framenum++, pEnc->iFrameNum, pEnc->current->stamp);  
1176                  }                  }
1177    
1178          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179           * Luminance masking           * dequeue frame from the encoding queue
1180           * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */           * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1181    
1182                  if ((pEnc->current->global_flags & XVID_LUMIMASKING)) {          if (pEnc->queue_size == 0)              /* empty */
1183                          int *temp_dquants =          {
1184                                  (int *) xvid_malloc(pEnc->mbParam.mb_width *                  if (xFrame->input.csp == XVID_CSP_NULL) /* no futher input */
1185                                                                  pEnc->mbParam.mb_height * sizeof(int),                  {
                                                                 CACHE_LINE);  
1186    
1187                          pEnc->current->quant =                          DPRINTF(XVID_DEBUG_DEBUG,"*** FINISH bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1188                                  adaptive_quantization(pEnc->current->image.y,                                  pEnc->bframenum_head, pEnc->bframenum_tail,
1189                                                                    pEnc->mbParam.edged_width, temp_dquants,                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
                                                                   pEnc->current->quant, pEnc->current->quant,  
                                                                   2 * pEnc->current->quant,  
                                                                   pEnc->mbParam.mb_width,  
                                                                   pEnc->mbParam.mb_height);  
1190    
1191                          for (y = 0; y < pEnc->mbParam.mb_height; y++) {                          if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) {
1192                                    call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
1193                            }
1194    
1195  #define OFFSET(x,y) ((x) + (y)*pEnc->mbParam.mb_width)                          /* if the very last frame is to be b-vop, we must change it to a p-vop */
1196                            if (pEnc->bframenum_tail > 0) {
1197    
1198                                  for (x = 0; x < pEnc->mbParam.mb_width; x++) {                                  SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
1199                                          MACROBLOCK *pMB = &pEnc->current->mbs[OFFSET(x, y)];                                  pEnc->bframenum_tail--;
1200                                    SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
1201    
1202                                          pMB->dquant = iDQtab[temp_dquants[OFFSET(x, y)] + 2];                                  /* convert B-VOP to P-VOP */
1203                                  }                                  pEnc->current->quant  = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset;
1204                                    pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */
1205                                    pEnc->current->quant /= pEnc->mbParam.bquant_ratio;
1206    
1207  #undef OFFSET                                  if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1208                                            image_copy(&pEnc->sOriginal, &pEnc->current->image,
1209                                                       pEnc->mbParam.edged_width, pEnc->mbParam.height);
1210                          }                          }
1211    
1212                          xvid_free(temp_dquants);                                  DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1213                  }                                  pEnc->bframenum_head, pEnc->bframenum_tail,
1214                                    pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1215                                    pEnc->mbParam.frame_drop_ratio = -1; /* it must be a coded vop */
1216    
1217          }                                  FrameCodeP(pEnc, &bs);
1218    
         /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
          * ivop/pvop/bvop selection  
          * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */  
         pEnc->iFrameNum++;  
1219    
1220          if (pEnc->iFrameNum == 0 || pEnc->bframenum_dx50bvop >= 0 ||                                  if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail==0) {
1221                  (mode < 0 && pEnc->mbParam.iMaxKeyInterval > 0 &&                                          call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
                         pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval))  
         {  
                 mode = I_VOP;  
1222          }else{          }else{
1223                  mode = MEanalysis(&pEnc->reference->image, pEnc->current,                                          pEnc->flush_bframes = 1;
1224                                          &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval,                                          goto done;
                                         (mode < 0) ? pEnc->iFrameNum : 0,  
                                         bframes_count++);  
1225          }          }
   
         if (mode == I_VOP) {  
                 /*  
                  * This will be coded as an Intra Frame  
                  */  
                 if ((pEnc->current->global_flags & XVID_QUARTERPEL))  
                         pEnc->mbParam.m_quarterpel = 1;  
                 else  
                         pEnc->mbParam.m_quarterpel = 0;  
   
                 if (pEnc->current->global_flags & XVID_MPEGQUANT) pEnc->mbParam.m_quant_type = MPEG4_QUANT;  
   
                 if ((pEnc->current->global_flags & XVID_CUSTOM_QMATRIX) > 0) {  
                         if (pFrame->quant_intra_matrix != NULL)  
                                 set_intra_matrix(pFrame->quant_intra_matrix);  
                         if (pFrame->quant_inter_matrix != NULL)  
                                 set_inter_matrix(pFrame->quant_inter_matrix);  
1226                  }                  }
1227                            DPRINTF(XVID_DEBUG_DEBUG, "*** END\n");
1228    
1229                            emms();
1230                  DPRINTF(DPRINTF_DEBUG,"*** IFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",                          return XVID_ERR_END;    /* end of stream reached */
1231                                  pEnc->bframenum_head, pEnc->bframenum_tail,                  }
1232                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);                  goto done;      /* nothing to encode yet; encoder lag */
   
                 if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {  
                         image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP");  
1233                  }                  }
1234    
1235                  // when we reach an iframe in DX50BVOP mode, encode the last bframe as a pframe          /* the current FRAME becomes the reference */
1236            SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
1237    
1238                  if ((pEnc->mbParam.global & XVID_GLOBAL_DX50BVOP) && pEnc->bframenum_tail > 0) {          /* remove frame from encoding-queue (head), and move it into the current */
1239            image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);
1240            frame = &pEnc->queue[pEnc->queue_head].frame;
1241            pEnc->queue_head = (pEnc->queue_head + 1) % (pEnc->mbParam.max_bframes+1);
1242            pEnc->queue_size--;
1243    
                         pEnc->bframenum_tail--;  
                         pEnc->bframenum_dx50bvop = pEnc->bframenum_tail;  
1244    
1245                          SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]);          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246                          if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {           * init pEnc->current fields
1247                                  image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP");           * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
                         }  
                         FrameCodeP(pEnc, &bs, &bits, 1, 0);  
                         bframes_count = 0;  
                         pFrame->intra = 0;  
1248    
1249                  } else {          pEnc->current->fincr = pEnc->mbParam.fincr>0 ? pEnc->mbParam.fincr : frame->fincr;
1250            inc_frame_num(pEnc);
1251            pEnc->current->vol_flags = frame->vol_flags;
1252            pEnc->current->vop_flags = frame->vop_flags;
1253            pEnc->current->motion_flags = frame->motion;
1254            pEnc->current->fcode = pEnc->mbParam.m_fcode;
1255            pEnc->current->bcode = pEnc->mbParam.m_fcode;
1256    
                         FrameCodeI(pEnc, &bs, &bits);  
                         bframes_count = 0;  
                         pFrame->intra = 1;  
1257    
1258                          pEnc->bframenum_dx50bvop = -1;          if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) {
1259                    image_chroma_optimize(&pEnc->current->image,
1260                            pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
1261                  }                  }
1262    
1263                  pEnc->flush_bframes = 1;          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264             * frame type & quant selection
1265                  if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) {           * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
                         BitstreamPadAlways(&bs);  
                         input_valid = 0;  
                         goto ipvop_loop;  
                 }  
1266    
1267                  /*          type = frame->type;
1268                   * NB : sequences like "IIBB" decode fine with msfdam but,          pEnc->current->quant = frame->quant;
                  *      go screwy with divx 5.00  
                  */  
         } else if (mode == P_VOP || mode == S_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) {  
                 /*  
                  * This will be coded as a Predicted Frame  
                  */  
1269    
1270                  DPRINTF(DPRINTF_DEBUG,"*** PFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i",          call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_BEFORE, &type, (int*)&pEnc->current->quant, stats);
                                 pEnc->bframenum_head, pEnc->bframenum_tail,  
                                 pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);  
1271    
1272                  if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {          if (type > 0){  /* XVID_TYPE_?VOP */
1273                          image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP");                  type = type2coding(type);       /* convert XVID_TYPE_?VOP to bitstream coding type */
1274            } else{         /* XVID_TYPE_AUTO */
1275                    if (pEnc->iFrameNum == 0 || (pEnc->mbParam.iMaxKeyInterval > 0 && pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)){
1276                            pEnc->iFrameNum = 0;
1277                            type = I_VOP;
1278                    }else{
1279                            type = MEanalysis(&pEnc->reference->image, pEnc->current,
1280                                                              &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval,
1281                                                              pEnc->iFrameNum, pEnc->bframenum_tail, xFrame->bframe_threshold,
1282                                                              (pEnc->bframes) ? pEnc->bframes[pEnc->bframenum_head]->mbs: NULL);
1283                    }
1284                  }                  }
1285    
1286                  FrameCodeP(pEnc, &bs, &bits, 1, 0);          if (type != I_VOP)
1287                  bframes_count = 0;                  pEnc->current->vol_flags = pEnc->mbParam.vol_flags; /* don't allow VOL changes here */
                 pFrame->intra = 0;  
                 pEnc->flush_bframes = 1;  
1288    
1289                  if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED) && (pEnc->bframenum_tail > 0)) {          /* bframes buffer overflow check */
1290                          BitstreamPadAlways(&bs);          if (type == B_VOP && pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) {
1291                          input_valid = 0;                  type = P_VOP;
                         goto ipvop_loop;  
1292                  }                  }
1293    
1294          } else {        /* mode == B_VOP */          pEnc->iFrameNum++;
                 /*  
                  * This will be coded as a Bidirectional Frame  
                  */  
1295    
1296                  if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) {          if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
1297                    image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5,
1298                            "%d  st:%lld  if:%d", pEnc->current->frame_num, pEnc->current->stamp, pEnc->iFrameNum);
1299            }
1300    
1301            /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1302             * encode this frame as a b-vop
1303             * (we dont encode here, rather we store the frame in the bframes queue, to be encoded later)
1304             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1305            if (type == B_VOP) {
1306                    if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
1307                          image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP");                          image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP");
1308                  }                  }
1309    
1310                  if (pFrame->bquant < 1) {                  if (frame->quant < 1) {
1311                          pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) *                          pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) *
1312                                  pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100;                                  pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100;
1313    
1314                  } else {                  } else {
1315                          pEnc->current->quant = pFrame->bquant;                          pEnc->current->quant = frame->quant;
1316                  }                  }
1317    
1318                  if (pEnc->current->quant < 1)                  if (pEnc->current->quant < 1)
# Line 1135  Line 1320 
1320                  else if (pEnc->current->quant > 31)                  else if (pEnc->current->quant > 31)
1321              pEnc->current->quant = 31;              pEnc->current->quant = 31;
1322    
1323                  DPRINTF(DPRINTF_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i  quant=%i\n",                  DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i  quant=%i\n",
1324                                  pEnc->bframenum_head, pEnc->bframenum_tail,                                  pEnc->bframenum_head, pEnc->bframenum_tail,
1325                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant);                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant);
1326    
# Line 1145  Line 1330 
1330    
1331                  pEnc->bframenum_tail++;                  pEnc->bframenum_tail++;
1332    
1333  // bframe report by koepi                  goto repeat;
1334                  pFrame->intra = 2;          }
                 pFrame->length = 0;  
   
                 input_valid = 0;  
                 goto bvop_loop;  
         }  
   
         BitstreamPadAlways(&bs);  
         pFrame->length = BitstreamLength(&bs);  
   
         if (pResult) {  
                 pResult->quant = pEnc->current->quant;  
                 pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);  
                 pResult->kblks = pEnc->current->sStat.kblks;  
                 pResult->mblks = pEnc->current->sStat.mblks;  
                 pResult->ublks = pEnc->current->sStat.ublks;  
   
                 if (pFrame->general & XVID_EXTRASTATS)  
                 {       pResult->sse_y =  
                                 plane_sse( pEnc->sOriginal.y, pEnc->current->image.y,  
                                                    pEnc->mbParam.edged_width, pEnc->mbParam.width,  
                                                    pEnc->mbParam.height);  
1335    
                         pResult->sse_u =  
                                 plane_sse( pEnc->sOriginal.u, pEnc->current->image.u,  
                                                    pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,  
                                                    pEnc->mbParam.height/2);  
1336    
1337                          pResult->sse_v =                  DPRINTF(XVID_DEBUG_DEBUG,"*** XXXXXX bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1338                                  plane_sse( pEnc->sOriginal.v, pEnc->current->image.v,                                  pEnc->bframenum_head, pEnc->bframenum_tail,
1339                                                     pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,                                  pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1340                                                     pEnc->mbParam.height/2);  
1341            /* for unpacked bframes, output the stats for the last encoded frame */
1342            if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0)
1343            {
1344                    if (pEnc->current->stamp > 0) {
1345                            call_plugins(pEnc, pEnc->reference, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
1346                  }                  }
1347            else if (stats) {
1348                stats->type = XVID_TYPE_NOTHING;
1349          }          }
   
         emms();  
   
         if (pFrame->quant == 0) {  
                 RateControlUpdate(&pEnc->rate_control, pEnc->current->quant,  
                                                   pFrame->length, pFrame->intra);  
1350          }          }
1351    
1352          stop_global_timer();          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1353          write_timer();           * closed-gop
1354             * if the frame prior to an iframe is scheduled as a bframe, we must change it to a pframe
1355             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1356    
1357          emms();          if (type == I_VOP && (pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP) && pEnc->bframenum_tail > 0) {
         return XVID_ERR_OK;  
 }  
1358    
1359                    /* place this frame back on the encoding-queue (head) */
1360                    /* we will deal with it next time */
1361                    dec_frame_num(pEnc);
1362                    pEnc->iFrameNum--;
1363    
1364                    pEnc->queue_head = (pEnc->queue_head + (pEnc->mbParam.max_bframes+1) - 1) % (pEnc->mbParam.max_bframes+1);
1365                    pEnc->queue_size++;
1366                    image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);
1367    
1368  /*****************************************************************************                  /* grab the last frame from the bframe-queue */
  * "original" IP frame encoder entry point  
  *  
  * Returned values :  
  *    - XVID_ERR_OK     - no errors  
  *    - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong  
  *                        format  
  ****************************************************************************/  
1369    
1370  int                  pEnc->bframenum_tail--;
1371  encoder_encode(Encoder * pEnc,                  SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
                            XVID_ENC_FRAME * pFrame,  
                            XVID_ENC_STATS * pResult)  
 {  
         uint16_t x, y;  
         Bitstream bs;  
         uint32_t bits;  
         uint16_t write_vol_header = 0;  
1372    
1373          float psnr;                  if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
1374          uint8_t temp[128];                          image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "CLOSED GOP BVOP->PVOP");
1375                    }
1376    
1377          start_global_timer();                  /* convert B-VOP quant to P-VOP */
1378                    pEnc->current->quant  = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset;
1379                    pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */
1380                    pEnc->current->quant /= pEnc->mbParam.bquant_ratio;
1381                    type = P_VOP;
1382            }
1383    
         ENC_CHECK(pEnc);  
         ENC_CHECK(pFrame);  
         ENC_CHECK(pFrame->bitstream);  
         ENC_CHECK(pFrame->image);  
1384    
1385          SWAP(FRAMEINFO *, pEnc->current, pEnc->reference);          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386             * encode this frame as an i-vop
1387             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1388    
1389          pEnc->current->global_flags = pFrame->general;          if (type == I_VOP) {
         pEnc->current->motion_flags = pFrame->motion;  
         pEnc->mbParam.hint = &pFrame->hint;  
1390    
1391          inc_frame_num(pEnc);                  DPRINTF(XVID_DEBUG_DEBUG,"*** IFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1392                                    pEnc->bframenum_head, pEnc->bframenum_tail,
1393                                    pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1394    
1395          /* disable alternate scan flag if interlacing is not enabled */                  if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
1396          if ((pEnc->current->global_flags & XVID_ALTERNATESCAN) &&                          image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP");
                 !(pEnc->current->global_flags & XVID_INTERLACING))  
         {  
                 pEnc->current->global_flags -= XVID_ALTERNATESCAN;  
1397          }          }
1398    
1399          start_timer();                  pEnc->iFrameNum = 1;
         if (image_input  
                 (&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height,  
                  pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING) < 0)  
                 return XVID_ERR_FORMAT;  
         stop_conv_timer();  
1400    
1401          if ((pFrame->general & XVID_CHROMAOPT)) {                  /* ---- update vol flags at IVOP ----------- */
1402                  image_chroma_optimize(&pEnc->current->image,                  pEnc->mbParam.vol_flags = pEnc->current->vol_flags;
                         pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);  
         }  
1403    
1404          if (pFrame->general & XVID_EXTRASTATS)                  /* Aspect ratio */
1405          {       image_copy(&pEnc->sOriginal, &pEnc->current->image,                  switch(frame->par) {
1406                                     pEnc->mbParam.edged_width, pEnc->mbParam.height);                  case XVID_PAR_11_VGA:
1407                    case XVID_PAR_43_PAL:
1408                    case XVID_PAR_43_NTSC:
1409                    case XVID_PAR_169_PAL:
1410                    case XVID_PAR_169_NTSC:
1411                    case XVID_PAR_EXT:
1412                            pEnc->mbParam.par = frame->par;
1413                            break;
1414                    default:
1415                            pEnc->mbParam.par = XVID_PAR_11_VGA;
1416                            break;
1417          }          }
1418    
1419          emms();                  /* For extended PAR only, we try to sanityse/simplify par values */
1420                    if (pEnc->mbParam.par == XVID_PAR_EXT) {
1421          BitstreamInit(&bs, pFrame->bitstream, 0);                          pEnc->mbParam.par_width  = frame->par_width;
1422                            pEnc->mbParam.par_height = frame->par_height;
1423                            simplify_par(&pEnc->mbParam.par_width, &pEnc->mbParam.par_height);
1424                    }
1425    
1426          if (pFrame->quant == 0) {                  if ((pEnc->mbParam.vol_flags & XVID_VOL_MPEGQUANT)) {
1427                  pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0);                          if (frame->quant_intra_matrix != NULL)
1428          } else {                                  set_intra_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_intra_matrix);
1429                  pEnc->current->quant = pFrame->quant;                          if (frame->quant_inter_matrix != NULL)
1430                                    set_inter_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_inter_matrix);
1431          }          }
1432    
1433          if ((pEnc->current->global_flags & XVID_QUARTERPEL))                  /* prevent vol/vop misuse */
                 pEnc->mbParam.m_quarterpel = 1;  
         else  
                 pEnc->mbParam.m_quarterpel = 0;  
1434    
1435          if ((pEnc->current->global_flags & XVID_LUMIMASKING)) {                  if (!(pEnc->current->vol_flags & XVID_VOL_INTERLACING))
1436                  int *temp_dquants =                          pEnc->current->vop_flags &= ~(XVID_VOP_TOPFIELDFIRST|XVID_VOP_ALTERNATESCAN);
                         (int *) xvid_malloc(pEnc->mbParam.mb_width *  
                                                                 pEnc->mbParam.mb_height * sizeof(int),  
                                                                 CACHE_LINE);  
1437    
1438                  pEnc->current->quant =                  /* ^^^------------------------ */
                         adaptive_quantization(pEnc->current->image.y,  
                                                                   pEnc->mbParam.edged_width, temp_dquants,  
                                                                   pEnc->current->quant, pEnc->current->quant,  
                                                                   2 * pEnc->current->quant,  
                                                                   pEnc->mbParam.mb_width,  
                                                                   pEnc->mbParam.mb_height);  
1439    
1440                  for (y = 0; y < pEnc->mbParam.mb_height; y++) {                  if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1441                            image_copy(&pEnc->sOriginal, &pEnc->current->image,
1442                                       pEnc->mbParam.edged_width, pEnc->mbParam.height);
1443                    }
1444    
1445  #define OFFSET(x,y) ((x) + (y)*pEnc->mbParam.mb_width)                  FrameCodeI(pEnc, &bs);
1446                    xFrame->out_flags |= XVID_KEYFRAME;
1447    
1448                          for (x = 0; x < pEnc->mbParam.mb_width; x++) {          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1449             * encode this frame as an p-vop
1450             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1451    
1452            } else { /* (type == P_VOP || type == S_VOP) */
1453    
1454                                  MACROBLOCK *pMB = &pEnc->current->mbs[OFFSET(x, y)];                  DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
1455                                    pEnc->bframenum_head, pEnc->bframenum_tail,
1456                                    pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1457    
1458                                  pMB->dquant = iDQtab[temp_dquants[OFFSET(x, y)] + 2];                  if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
1459                            image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP");
1460                          }                          }
1461    
1462  #undef OFFSET                  if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1463                            image_copy(&pEnc->sOriginal, &pEnc->current->image,
1464                                       pEnc->mbParam.edged_width, pEnc->mbParam.height);
1465                  }                  }
1466    
1467                  xvid_free(temp_dquants);                  if ( FrameCodeP(pEnc, &bs) == 0 ) {
1468                            /* N-VOP, we mustn't code b-frames yet */
1469                            if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) ||
1470                                     pEnc->mbParam.max_bframes == 0)
1471                                    call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
1472                            goto done;
1473                    }
1474          }          }
1475    
         if (pEnc->current->global_flags & XVID_H263QUANT) {  
                 if (pEnc->mbParam.m_quant_type != H263_QUANT)  
                         write_vol_header = 1;  
                 pEnc->mbParam.m_quant_type = H263_QUANT;  
         } else if (pEnc->current->global_flags & XVID_MPEGQUANT) {  
                 int matrix1_changed, matrix2_changed;  
1476    
1477                  matrix1_changed = matrix2_changed = 0;          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478             * on next enc_encode call we must flush bframes
1479             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1480    
1481                  if (pEnc->mbParam.m_quant_type != MPEG4_QUANT)  /*done_flush:*/
                         write_vol_header = 1;  
1482    
1483                  pEnc->mbParam.m_quant_type = MPEG4_QUANT;          pEnc->flush_bframes = 1;
1484    
1485                  if ((pEnc->current->global_flags & XVID_CUSTOM_QMATRIX) > 0) {          /* packed & queued_bframes: dont bother outputting stats here, we do so after the flush */
1486                          if (pFrame->quant_intra_matrix != NULL)          if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) {
1487                                  matrix1_changed = set_intra_matrix(pFrame->quant_intra_matrix);                  goto repeat;
                         if (pFrame->quant_inter_matrix != NULL)  
                                 matrix2_changed = set_inter_matrix(pFrame->quant_inter_matrix);  
                 } else {  
                         matrix1_changed = set_intra_matrix(get_default_intra_matrix());  
                         matrix2_changed = set_inter_matrix(get_default_inter_matrix());  
                 }  
                 if (write_vol_header == 0)  
                         write_vol_header = matrix1_changed | matrix2_changed;  
1488          }          }
1489    
1490          if (pFrame->intra < 0) {          /* packed or no-bframes or no-bframes-queued: output stats */
1491                  if ((pEnc->iFrameNum == -1)          if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) || pEnc->mbParam.max_bframes == 0 ) {
1492                          || ((pEnc->mbParam.iMaxKeyInterval > 0)                  call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
                                 && (pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval))) {  
                         pFrame->intra = FrameCodeI(pEnc, &bs, &bits);  
                 } else {  
                         pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 0, write_vol_header);  
                 }  
         } else {  
                 if (pFrame->intra == 1) {  
                         pFrame->intra = FrameCodeI(pEnc, &bs, &bits);  
                 } else {  
                         pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 1, write_vol_header);  
1493                  }                  }
1494    
1495          }          /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496             * done; return number of bytes consumed
1497             * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1498    
1499  //      BitstreamPutBits(&bs, 0xFFFF, 16);  done:
 //      BitstreamPutBits(&bs, 0xFFFF, 16);  
         BitstreamPadAlways(&bs);  
         pFrame->length = BitstreamLength(&bs);  
1500    
1501          if (pResult) {          stop_global_timer();
1502                  pResult->quant = pEnc->current->quant;          write_timer();
                 pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8);  
                 pResult->kblks = pEnc->current->sStat.kblks;  
                 pResult->mblks = pEnc->current->sStat.mblks;  
                 pResult->ublks = pEnc->current->sStat.ublks;  
         }  
1503    
1504          emms();          emms();
1505            return BitstreamLength(&bs);
         if (pFrame->quant == 0) {  
                 RateControlUpdate(&pEnc->rate_control, pEnc->current->quant,  
                                                   pFrame->length, pFrame->intra);  
1506          }          }
         if (pFrame->general & XVID_EXTRASTATS)  
         {  
                 psnr =  
                         image_psnr(&pEnc->sOriginal, &pEnc->current->image,  
                                            pEnc->mbParam.edged_width, pEnc->mbParam.width,  
                                            pEnc->mbParam.height);  
1507    
                 snprintf(temp, 127, "PSNR: %f\n", psnr);  
         }  
   
         pEnc->iFrameNum++;  
1508    
1509          stop_global_timer();  static void SetMacroblockQuants(MBParam * const pParam, FRAMEINFO * frame)
1510          write_timer();  {
1511            unsigned int i;
1512          return XVID_ERR_OK;          MACROBLOCK * pMB = frame->mbs;
1513            int quant = frame->mbs[0].quant; /* set by XVID_PLG_FRAME */
1514            if (quant > 31)
1515                    frame->quant = quant = 31;
1516            else if (quant < 1)
1517                    frame->quant = quant = 1;
1518    
1519            for (i = 0; i < pParam->mb_height * pParam->mb_width; i++) {
1520                    quant += pMB->dquant;
1521                    if (quant > 31)
1522                            quant = 31;
1523                    else if (quant < 1)
1524                            quant = 1;
1525                    pMB->quant = quant;
1526                    pMB++;
1527            }
1528  }  }
1529    
1530    
1531  static __inline void  static __inline void
1532  CodeIntraMB(Encoder * pEnc,  CodeIntraMB(MACROBLOCK * pMB)
                         MACROBLOCK * pMB)  
1533  {  {
   
1534          pMB->mode = MODE_INTRA;          pMB->mode = MODE_INTRA;
1535    
1536          /* zero mv statistics */          /* zero mv statistics */
# Line 1400  Line 1539 
1539          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
1540          pMB->sad16 = 0;          pMB->sad16 = 0;
1541    
1542          if ((pEnc->current->global_flags & XVID_LUMIMASKING)) {          if (pMB->dquant != 0) {
                 if (pMB->dquant != NO_CHANGE) {  
1543                          pMB->mode = MODE_INTRA_Q;                          pMB->mode = MODE_INTRA_Q;
                         pEnc->current->quant += DQtab[pMB->dquant];  
   
                         if (pEnc->current->quant > 31)  
                                 pEnc->current->quant = 31;  
                         if (pEnc->current->quant < 1)  
                                 pEnc->current->quant = 1;  
1544                  }                  }
1545          }          }
1546    
1547          pMB->quant = pEnc->current->quant;  static void
1548  }  SliceCodeI(SMPData *data)
   
   
 #define FCODEBITS       3  
 #define MODEBITS        5  
   
 void  
 HintedMESet(Encoder * pEnc,  
                         int *intra)  
1549  {  {
1550          HINTINFO *hint;          Encoder *pEnc = (Encoder *) data->pEnc;
1551          Bitstream bs;          Bitstream *bs = (Bitstream *) data->bs;
1552          int length, high;  
1553          uint32_t x, y;          uint16_t x, y;
1554            int mb_width = pEnc->mbParam.mb_width;
1555            int mb_height = pEnc->mbParam.mb_height;
1556    
1557          hint = pEnc->mbParam.hint;          int bound = 0, num_slices = pEnc->num_slices;
1558            FRAMEINFO *const current = pEnc->current;
1559    
1560          if (hint->rawhints) {          DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
1561                  *intra = hint->mvhint.intra;          DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
         } else {  
                 BitstreamInit(&bs, hint->hintstream, hint->hintlength);  
                 *intra = BitstreamGetBit(&bs);  
         }  
1562    
1563          if (*intra) {          if (data->start_y > 0) { /* write resync marker */
1564                  return;                  bound = data->start_y*mb_width;
1565                    write_video_packet_header(bs, &pEnc->mbParam, current, bound);
1566          }          }
1567    
1568          pEnc->current->fcode =          for (y = data->start_y; y < data->stop_y; y++) {
1569                  (hint->rawhints) ? hint->mvhint.fcode : BitstreamGetBits(&bs,                  int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices);
                                                                                                                                  FCODEBITS);  
   
         length = pEnc->current->fcode + 5;  
         high = 1 << (length - 1);  
   
         for (y = 0; y < pEnc->mbParam.mb_height; ++y) {  
                 for (x = 0; x < pEnc->mbParam.mb_width; ++x) {  
                         MACROBLOCK *pMB =  
                                 &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];  
                         MVBLOCKHINT *bhint =  
                                 &hint->mvhint.block[x + y * pEnc->mbParam.mb_width];  
                         VECTOR pred;  
                         VECTOR tmp;  
                         int vec;  
   
                         pMB->mode =  
                                 (hint->rawhints) ? bhint->mode : BitstreamGetBits(&bs,  
                                                                                                                                   MODEBITS);  
   
                         pMB->mode = (pMB->mode == MODE_INTER_Q) ? MODE_INTER : pMB->mode;  
                         pMB->mode = (pMB->mode == MODE_INTRA_Q) ? MODE_INTRA : pMB->mode;  
   
                         if (pMB->mode == MODE_INTER) {  
                                 tmp.x =  
                                         (hint->rawhints) ? bhint->mvs[0].x : BitstreamGetBits(&bs,  
                                                                                                                                                   length);  
                                 tmp.y =  
                                         (hint->rawhints) ? bhint->mvs[0].y : BitstreamGetBits(&bs,  
                                                                                                                                                   length);  
                                 tmp.x -= (tmp.x >= high) ? high * 2 : 0;  
                                 tmp.y -= (tmp.y >= high) ? high * 2 : 0;  
   
                                 pred = get_pmv2(pEnc->current->mbs,pEnc->mbParam.mb_width,0,x,y,0);  
   
                                 for (vec = 0; vec < 4; ++vec) {  
                                         pMB->mvs[vec].x = tmp.x;  
                                         pMB->mvs[vec].y = tmp.y;  
                                         pMB->pmvs[vec].x = pMB->mvs[0].x - pred.x;  
                                         pMB->pmvs[vec].y = pMB->mvs[0].y - pred.y;  
                                 }  
                         } else if (pMB->mode == MODE_INTER4V) {  
                                 for (vec = 0; vec < 4; ++vec) {  
                                         tmp.x =  
                                                 (hint->rawhints) ? bhint->mvs[vec].  
                                                 x : BitstreamGetBits(&bs, length);  
                                         tmp.y =  
                                                 (hint->rawhints) ? bhint->mvs[vec].  
                                                 y : BitstreamGetBits(&bs, length);  
                                         tmp.x -= (tmp.x >= high) ? high * 2 : 0;  
                                         tmp.y -= (tmp.y >= high) ? high * 2 : 0;  
   
                                         pred = get_pmv2(pEnc->current->mbs,pEnc->mbParam.mb_width,0,x,y,vec);  
   
                                         pMB->mvs[vec].x = tmp.x;  
                                         pMB->mvs[vec].y = tmp.y;  
                                         pMB->pmvs[vec].x = pMB->mvs[vec].x - pred.x;  
                                         pMB->pmvs[vec].y = pMB->mvs[vec].y - pred.y;  
                                 }  
                         } else                          // intra / stuffing / not_coded  
                         {  
                                 for (vec = 0; vec < 4; ++vec) {  
                                         pMB->mvs[vec].x = pMB->mvs[vec].y = 0;  
                                 }  
                         }  
   
                         if (pMB->mode == MODE_INTER4V &&  
                                 (pEnc->current->global_flags & XVID_LUMIMASKING)  
                                 && pMB->dquant != NO_CHANGE) {  
                                 pMB->mode = MODE_INTRA;  
1570    
1571                                  for (vec = 0; vec < 4; ++vec) {                  if (new_bound > bound) {
1572                                          pMB->mvs[vec].x = pMB->mvs[vec].y = 0;                          bound = new_bound;
1573                                  }                          BitstreamPadAlways(bs);
1574                          }                          write_video_packet_header(bs, &pEnc->mbParam, current, bound);
                 }  
         }  
1575  }  }
1576    
1577                    for (x = 0; x < mb_width; x++) {
1578                            MACROBLOCK *pMB = &current->mbs[x + y * mb_width];
1579    
1580                            CodeIntraMB(pMB);
1581    
1582  void                          MBTransQuantIntra(&pEnc->mbParam, current, pMB, x, y,
1583  HintedMEGet(Encoder * pEnc,                                                            dct_codes, qcoeff);
                         int intra)  
 {  
         HINTINFO *hint;  
         Bitstream bs;  
         uint32_t x, y;  
         int length, high;  
1584    
1585          hint = pEnc->mbParam.hint;                          start_timer();
1586                            MBPrediction(current, x, y, mb_width, qcoeff, bound);
1587                            stop_prediction_timer();
1588    
1589          if (hint->rawhints) {                          start_timer();
1590                  hint->mvhint.intra = intra;                          MBCoding(current, pMB, qcoeff, bs, data->sStat);
1591          } else {                          stop_coding_timer();
                 BitstreamInit(&bs, hint->hintstream, 0);  
                 BitstreamPutBit(&bs, intra);  
         }  
1592    
         if (intra) {  
                 if (!hint->rawhints) {  
                         BitstreamPadAlways(&bs);  
                         hint->hintlength = BitstreamLength(&bs);  
1593                  }                  }
                 return;  
1594          }          }
1595    
1596          length = pEnc->current->fcode + 5;          emms();
1597          high = 1 << (length - 1);          BitstreamPadAlways(bs);
   
         if (hint->rawhints) {  
                 hint->mvhint.fcode = pEnc->current->fcode;  
         } else {  
                 BitstreamPutBits(&bs, pEnc->current->fcode, FCODEBITS);  
1598          }          }
1599    
1600          for (y = 0; y < pEnc->mbParam.mb_height; ++y) {  static __inline void
1601                  for (x = 0; x < pEnc->mbParam.mb_width; ++x) {  SerializeBitstreams(Encoder *pEnc, FRAMEINFO *current, Bitstream *bs, int num_threads)
1602                          MACROBLOCK *pMB =  {
1603                                  &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];          int k;
1604                          MVBLOCKHINT *bhint =          uint32_t pos = BitstreamLength(bs);
                                 &hint->mvhint.block[x + y * pEnc->mbParam.mb_width];  
                         VECTOR tmp;  
1605    
1606                          if (hint->rawhints) {          for (k = 1; k < num_threads; k++) {
1607                                  bhint->mode = pMB->mode;                  uint32_t len = BitstreamLength(pEnc->smpData[k].bs);
                         } else {  
                                 BitstreamPutBits(&bs, pMB->mode, MODEBITS);  
                         }  
1608    
1609                          if (pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q) {                  memcpy((void *)((ptr_t)bs->start + pos),
1610                                  tmp.x = pMB->mvs[0].x;                             (void *)((ptr_t)pEnc->smpData[k].bs->start), len);
1611                                  tmp.y = pMB->mvs[0].y;  
1612                                  tmp.x += (tmp.x < 0) ? high * 2 : 0;                  current->length = pos += len;
1613                                  tmp.y += (tmp.y < 0) ? high * 2 : 0;  
1614                    /* collect stats */
1615                                  if (hint->rawhints) {                  current->sStat.iTextBits += pEnc->smpData[k].sStat->iTextBits;
1616                                          bhint->mvs[0].x = tmp.x;                  current->sStat.kblks += pEnc->smpData[k].sStat->kblks;
1617                                          bhint->mvs[0].y = tmp.y;                  current->sStat.mblks += pEnc->smpData[k].sStat->mblks;
1618                                  } else {                  current->sStat.ublks += pEnc->smpData[k].sStat->ublks;
1619                                          BitstreamPutBits(&bs, tmp.x, length);                  current->sStat.iMVBits += pEnc->smpData[k].sStat->iMVBits;
1620                                          BitstreamPutBits(&bs, tmp.y, length);          }
1621                                  }  
1622                          } else if (pMB->mode == MODE_INTER4V) {          if (num_threads > 1) {
1623                                  int vec;                  uint32_t pos32 = pos>>2;
1624                    bs->tail = bs->start + pos32;
1625                                  for (vec = 0; vec < 4; ++vec) {                  bs->pos = 8*(pos - (pos32<<2));
1626                                          tmp.x = pMB->mvs[vec].x;                  bs->buf = 0;
1627                                          tmp.y = pMB->mvs[vec].y;  
1628                                          tmp.x += (tmp.x < 0) ? high * 2 : 0;                  if (bs->pos > 0) {
1629                                          tmp.y += (tmp.y < 0) ? high * 2 : 0;                          uint32_t pos8 = bs->pos/8;
1630                            memset((void *)((ptr_t)bs->tail+pos8), 0, (4-pos8));
1631                                          if (hint->rawhints) {                          pos = *bs->tail;
1632                                                  bhint->mvs[vec].x = tmp.x;  #ifndef ARCH_IS_BIG_ENDIAN
1633                                                  bhint->mvs[vec].y = tmp.y;                          BSWAP(pos);
1634                                          } else {  #endif
1635                                                  BitstreamPutBits(&bs, tmp.x, length);                          bs->buf = pos;
                                                 BitstreamPutBits(&bs, tmp.y, length);  
                                         }  
                                 }  
                         }  
                 }  
1636          }          }
   
         if (!hint->rawhints) {  
                 BitstreamPad(&bs);  
                 hint->hintlength = BitstreamLength(&bs);  
1637          }          }
1638  }  }
1639    
   
1640  static int  static int
1641  FrameCodeI(Encoder * pEnc,  FrameCodeI(Encoder * pEnc,
1642                     Bitstream * bs,                     Bitstream * bs)
                    uint32_t * pBits)  
1643  {  {
1644            int bits = BitstreamPos(bs);
1645            int bound = 0, num_slices = pEnc->num_slices;
1646            int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices));
1647            int slices_per_thread = (num_slices*1024 / num_threads);
1648          int mb_width = pEnc->mbParam.mb_width;          int mb_width = pEnc->mbParam.mb_width;
1649          int mb_height = pEnc->mbParam.mb_height;          int mb_height = pEnc->mbParam.mb_height;
1650            void * status = NULL;
1651            uint16_t k;
1652    
         DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);  
         DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);  
   
         uint16_t x, y;  
   
         if ((pEnc->current->global_flags & XVID_REDUCED))  
         {  
                 mb_width = (pEnc->mbParam.width + 31) / 32;  
                 mb_height = (pEnc->mbParam.height + 31) / 32;  
   
                 /* 16x16->8x8 downsample requires 1 additional edge pixel*/  
                 /* XXX: setedges is overkill */  
                 start_timer();  
                 image_setedges(&pEnc->current->image,  
                         pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,  
                         pEnc->mbParam.width, pEnc->mbParam.height);  
                 stop_edges_timer();  
         }  
   
         pEnc->iFrameNum = 0;  
1653          pEnc->mbParam.m_rounding_type = 1;          pEnc->mbParam.m_rounding_type = 1;
1654          pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;          pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;
         pEnc->current->quarterpel =  pEnc->mbParam.m_quarterpel;  
1655          pEnc->current->coding_type = I_VOP;          pEnc->current->coding_type = I_VOP;
1656    
1657          BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current);          call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);
1658    
1659            SetMacroblockQuants(&pEnc->mbParam, pEnc->current);
1660    
1661            BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current, num_slices);
1662    
1663          set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);          set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);
1664    
1665          BitstreamPadAlways(bs);          BitstreamPad(bs);
         BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1);  
1666    
1667          *pBits = BitstreamPos(bs);          BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1, pEnc->current->mbs[0].quant);
1668    
1669          pEnc->current->sStat.iTextBits = 0;          pEnc->current->sStat.iTextBits = 0;
         pEnc->current->sStat.kblks = mb_width * mb_height;  
         pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;  
1670    
1671          for (y = 0; y < mb_height; y++)          /* multithreaded intra coding - dispatch threads */
1672                  for (x = 0; x < mb_width; x++) {          for (k = 0; k < num_threads; k++) {
1673                          MACROBLOCK *pMB =                  int add = ((slices_per_thread + 512) >> 10);
                                 &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];  
1674    
1675                          CodeIntraMB(pEnc, pMB);                  slices_per_thread += ((num_slices*1024 / num_threads) - add*1024);
1676    
1677                          MBTransQuantIntra(&pEnc->mbParam, pEnc->current, pMB, x, y,                  pEnc->smpData[k].pEnc = (void *) pEnc;
1678                                                            dct_codes, qcoeff);                  pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices);
1679                    pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices);
1680    
1681                          start_timer();                  bound += add;
                         MBPrediction(pEnc->current, x, y, pEnc->mbParam.mb_width, qcoeff);  
                         stop_prediction_timer();  
1682    
1683                          start_timer();                  if (k > 0) {
1684                          if (pEnc->current->global_flags & XVID_GREYSCALE)                          BitstreamReset(pEnc->smpData[k].bs);
1685                          {       pMB->cbp &= 0x3C;               /* keep only bits 5-2 */                          pEnc->smpData[k].sStat->iTextBits = 0;
                                 qcoeff[4*64+0]=0;               /* zero, because for INTRA MBs DC value is saved */  
                                 qcoeff[5*64+0]=0;  
1686                          }                          }
                         MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);  
                         stop_coding_timer();  
1687                  }                  }
1688            pEnc->smpData[0].bs = bs;
1689            pEnc->smpData[0].sStat = &pEnc->current->sStat;
1690    
1691          if ((pEnc->current->global_flags & XVID_REDUCED))          /* create threads */
1692          {          for (k = 1; k < num_threads; k++) {
1693                  image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width,                  pthread_create(&pEnc->smpData[k].handle, NULL,
1694                          pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width,                                 (void*)SliceCodeI, (void*)&pEnc->smpData[k]);
                         16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV);  
1695          }          }
         emms();  
1696    
1697          *pBits = BitstreamPos(bs) - *pBits;          SliceCodeI(&pEnc->smpData[0]);
         pEnc->fMvPrevSigma = -1;  
         pEnc->mbParam.m_fcode = 2;  
1698    
1699          if (pEnc->current->global_flags & XVID_HINTEDME_GET) {          /* wait until all threads are finished */
1700                  HintedMEGet(pEnc, 1);          for (k = 1; k < num_threads; k++) {
1701                    pthread_join(pEnc->smpData[k].handle, &status);
1702          }          }
1703    
1704          return 1;                                       // intra          pEnc->current->length = BitstreamLength(bs) - (bits/8);
 }  
   
   
 #define INTRA_THRESHOLD 0.5  
 #define BFRAME_SKIP_THRESHHOLD 30  
   
   
 /* FrameCodeP also handles S(GMC)-VOPs */  
 static int  
 FrameCodeP(Encoder * pEnc,  
                    Bitstream * bs,  
                    uint32_t * pBits,  
                    bool force_inter,  
                    bool vol_header)  
 {  
         float fSigma;  
   
         DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);  
         DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);  
   
         int mb_width = pEnc->mbParam.mb_width;  
         int mb_height = pEnc->mbParam.mb_height;  
   
         int iLimit;  
         int x, y, k;  
         int iSearchRange;  
         int bIntra, skip_possible;  
   
         /* IMAGE *pCurrent = &pEnc->current->image; */  
         IMAGE *pRef = &pEnc->reference->image;  
1705    
1706          if ((pEnc->current->global_flags & XVID_REDUCED))          /* reassemble the pieces together */
1707          {          SerializeBitstreams(pEnc, pEnc->current, bs, num_threads);
                 mb_width = (pEnc->mbParam.width + 31) / 32;  
                 mb_height = (pEnc->mbParam.height + 31) / 32;  
         }  
1708    
1709            pEnc->current->sStat.iMVBits = 0;
1710            pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;
1711            pEnc->current->sStat.kblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height;
1712    
1713          start_timer();          pEnc->fMvPrevSigma = -1;
1714          image_setedges(pRef, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,          pEnc->mbParam.m_fcode = 2;
                                    pEnc->mbParam.width, pEnc->mbParam.height);  
         stop_edges_timer();  
   
         pEnc->mbParam.m_rounding_type = 1 - pEnc->mbParam.m_rounding_type;  
         pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;  
         pEnc->current->quarterpel =  pEnc->mbParam.m_quarterpel;  
         pEnc->current->fcode = pEnc->mbParam.m_fcode;  
1715    
1716          if (!force_inter)          pEnc->current->is_edged = 0; /* not edged */
1717                  iLimit = (int)(mb_width * mb_height *  INTRA_THRESHOLD);          pEnc->current->is_interpolated = -1; /* not interpolated (fake rounding -1) */
         else  
                 iLimit = mb_width * mb_height + 1;  
1718    
1719          if ((pEnc->current->global_flags & XVID_HALFPEL)) {          return 1;                                       /* intra */
                 start_timer();  
                 image_interpolate(pRef, &pEnc->vInterH, &pEnc->vInterV,  
                                                   &pEnc->vInterHV, pEnc->mbParam.edged_width,  
                                                   pEnc->mbParam.edged_height,  
                                                   pEnc->mbParam.m_quarterpel,  
                                                   pEnc->current->rounding_type);  
                 stop_inter_timer();  
1720          }          }
1721    
1722          pEnc->current->coding_type = P_VOP;  static __inline void
1723    updateFcode(Statistics * sStat, Encoder * pEnc)
1724    {
1725            float fSigma;
1726            int iSearchRange;
1727    
1728          start_timer();          if (sStat->iMvCount == 0)
1729          if (pEnc->current->global_flags & XVID_HINTEDME_SET)                  sStat->iMvCount = 1;
                 HintedMESet(pEnc, &bIntra);  
         else  
                 bIntra =  
                         MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference,  
                          &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,  
                          iLimit);  
1730    
1731          stop_motion_timer();          fSigma = (float) sqrt((float) sStat->iMvSum / sStat->iMvCount);
1732    
1733          if (bIntra == 1) return FrameCodeI(pEnc, bs, pBits);          iSearchRange = 16 << pEnc->mbParam.m_fcode;
1734    
1735          if ( ( pEnc->current->global_flags & XVID_GMC )          if ((3.0 * fSigma > iSearchRange) && (pEnc->mbParam.m_fcode <= 5) )
1736                  && ( (pEnc->current->warp.duv[1].x != 0) || (pEnc->current->warp.duv[1].y != 0) ) )                  pEnc->mbParam.m_fcode++;
         {  
                 pEnc->current->coding_type = S_VOP;  
1737    
1738                  generate_GMCparameters( 2, 16, &pEnc->current->warp,          else if ((5.0 * fSigma < iSearchRange)
1739                                          pEnc->mbParam.width, pEnc->mbParam.height,                             && (4.0 * pEnc->fMvPrevSigma < iSearchRange)
1740                                          &pEnc->current->gmc_data);                             && (pEnc->mbParam.m_fcode >= 2) )
1741                    pEnc->mbParam.m_fcode--;
                 generate_GMCimage(&pEnc->current->gmc_data, &pEnc->reference->image,  
                                 pEnc->mbParam.mb_width, pEnc->mbParam.mb_height,  
                                 pEnc->mbParam.edged_width, pEnc->mbParam.edged_width/2,  
                                 pEnc->mbParam.m_fcode, pEnc->mbParam.m_quarterpel, 0,  
                                 pEnc->current->rounding_type, pEnc->current->mbs, &pEnc->vGMC);  
1742    
1743            pEnc->fMvPrevSigma = fSigma;
1744          }          }
1745    
1746          set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);  #define BFRAME_SKIP_THRESHHOLD 30
         if (vol_header)  
         {       BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current);  
                 BitstreamPadAlways(bs);  
         }  
1747    
1748          BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1);  static void
1749    SliceCodeP(SMPData *data)
1750    {
1751            Encoder *pEnc = (Encoder *) data->pEnc;
1752            Bitstream *bs = (Bitstream *) data->bs;
1753    
1754            int x, y, k;
1755            FRAMEINFO *const current = pEnc->current;
1756            FRAMEINFO *const reference = pEnc->reference;
1757            MBParam * const pParam = &pEnc->mbParam;
1758            IMAGE *pRef = &reference->image;
1759            int mb_width = pParam->mb_width;
1760            int mb_height = pParam->mb_height;
1761    
1762          *pBits = BitstreamPos(bs);          DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
1763            DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
1764    
1765          pEnc->current->sStat.iTextBits = pEnc->current->sStat.iMvSum = pEnc->current->sStat.iMvCount =          int bound = 0, num_slices = pEnc->num_slices;
                 pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;  
1766    
1767            if (data->start_y > 0) { /* write resync marker */
1768                    bound = data->start_y*mb_width;
1769                    write_video_packet_header(bs, pParam, current, bound);
1770            }
1771    
1772          for (y = 0; y < mb_height; y++) {          for (y = data->start_y; y < data->stop_y; y++) {
1773                  for (x = 0; x < mb_width; x++) {                  int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices);
                         MACROBLOCK *pMB =  
                                 &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];  
1774    
1775  /* Mode decision: Check, if the block should be INTRA / INTER or GMC-coded */                  if (new_bound > bound) {
1776  /* For a start, leave INTRA decision as is, only choose only between INTER/GMC  - gruel, 9.1.2002 */                          bound = new_bound;
1777                            BitstreamPadAlways(bs);
1778                            write_video_packet_header(bs, pParam, current, bound);
1779                    }
1780    
1781                          bIntra = (pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q);                  for (x = 0; x < mb_width; x++) {
1782                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
1783                            int skip_possible;
1784    
1785                          if (bIntra) {                          if (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q) {
1786                                  CodeIntraMB(pEnc, pMB);                                  CodeIntraMB(pMB);
1787                                  MBTransQuantIntra(&pEnc->mbParam, pEnc->current, pMB, x, y,                                  MBTransQuantIntra(pParam, current, pMB, x, y,
1788                                                                    dct_codes, qcoeff);                                                                    dct_codes, qcoeff);
1789    
1790                                  start_timer();                                  start_timer();
1791                                  MBPrediction(pEnc->current, x, y, pEnc->mbParam.mb_width, qcoeff);                                  MBPrediction(current, x, y, pParam->mb_width, qcoeff, bound);
1792                                  stop_prediction_timer();                                  stop_prediction_timer();
1793    
1794                                  pEnc->current->sStat.kblks++;                                  data->sStat->kblks++;
1795    
1796                                  MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);                                  MBCoding(current, pMB, qcoeff, bs, data->sStat);
1797                                  stop_coding_timer();                                  stop_coding_timer();
1798                                  continue;                                  continue;
1799                          }                          }
1800    
                         if (pEnc->current->coding_type == S_VOP) {  
   
                                 int32_t iSAD = sad16(pEnc->current->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,  
                                         pEnc->vGMC.y + 16*y*pEnc->mbParam.edged_width + 16*x,  
                                         pEnc->mbParam.edged_width, 65536);  
   
                                 if (pEnc->current->motion_flags & PMV_CHROMA16) {  
                                         iSAD += sad8(pEnc->current->image.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x,  
                                         pEnc->vGMC.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2);  
   
                                         iSAD += sad8(pEnc->current->image.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x,  
                                         pEnc->vGMC.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2);  
                                 }  
   
                                 if (iSAD <= pMB->sad16) {               /* mode decision GMC */  
   
                                         if (pEnc->mbParam.m_quarterpel)  
                                                 pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = pMB->amv;  
                                         else  
                                                 pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;  
   
                                         pMB->mode = MODE_INTER;  
                                         pMB->mcsel = 1;  
                                         pMB->sad16 = iSAD;  
                                 } else {  
                                         pMB->mcsel = 0;  
                                 }  
                         } else {  
                                 pMB->mcsel = 0; /* just a precaution */  
                         }  
   
1801                          start_timer();                          start_timer();
1802                          MBMotionCompensation(pMB, x, y, &pEnc->reference->image,                          MBMotionCompensation(pMB, x, y, &reference->image,
1803                                                                   &pEnc->vInterH, &pEnc->vInterV,                                                                   &pEnc->vInterH, &pEnc->vInterV,
1804                                                                   &pEnc->vInterHV, &pEnc->vGMC,                                                                   &pEnc->vInterHV, &pEnc->vGMC,
1805                                                                   &pEnc->current->image,                                                                   &current->image,
1806                                                                   dct_codes, pEnc->mbParam.width,                                                                   dct_codes, pParam->width,
1807                                                                   pEnc->mbParam.height,                                                                   pParam->height,
1808                                                                   pEnc->mbParam.edged_width,                                                                   pParam->edged_width,
1809                                                                   pEnc->mbParam.m_quarterpel,                                                                   (current->vol_flags & XVID_VOL_QUARTERPEL),
1810                                                                   (pEnc->current->global_flags & XVID_REDUCED),                                                                   current->rounding_type,
1811                                                                   pEnc->current->rounding_type);                                                                   data->RefQ);
1812    
1813                          stop_comp_timer();                          stop_comp_timer();
1814    
                         if ((pEnc->current->global_flags & XVID_LUMIMASKING)) {  
                                 if (pMB->dquant != NO_CHANGE) {  
                                         pMB->mode = MODE_INTER_Q;  
                                         pEnc->current->quant += DQtab[pMB->dquant];  
                                         if (pEnc->current->quant > 31)  
                                                 pEnc->current->quant = 31;  
                                         else if (pEnc->current->quant < 1)  
                                                 pEnc->current->quant = 1;  
                                 }  
                         }  
                         pMB->quant = pEnc->current->quant;  
   
1815                          pMB->field_pred = 0;                          pMB->field_pred = 0;
1816    
1817                          if (pMB->mode != MODE_NOT_CODED)                          if (pMB->cbp != 0) {
1818                          {       pMB->cbp =                                  pMB->cbp = MBTransQuantInter(pParam, current, pMB, x, y,
                                         MBTransQuantInter(&pEnc->mbParam, pEnc->current, pMB, x, y,  
1819                                                                            dct_codes, qcoeff);                                                                            dct_codes, qcoeff);
1820                          }                          }
1821    
1822                            if (pMB->dquant != 0)
1823                                    MBSetDquant(pMB, x, y, pParam);
1824    
1825    
1826                          if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y ||                          if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y ||
1827                                     pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x ||                                     pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x ||
1828                                     pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) {                                     pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) {
1829                                  pEnc->current->sStat.mblks++;                                  data->sStat->mblks++;
1830                          }  else {                          }  else {
1831                                  pEnc->current->sStat.ublks++;                                  data->sStat->ublks++;
1832                          }                          }
1833    
1834                          start_timer();                          start_timer();
1835    
1836                          /* Finished processing the MB, now check if to CODE or SKIP */                          /* Finished processing the MB, now check if to CODE or SKIP */
1837    
1838                          skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER) &&                          skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER);
                                                         (pMB->dquant == NO_CHANGE);  
1839    
1840                          if (pEnc->current->coding_type == S_VOP)                          if (current->coding_type == S_VOP)
1841                                  skip_possible &= (pMB->mcsel == 1);                                  skip_possible &= (pMB->mcsel == 1);
1842                          else if (pEnc->current->coding_type == P_VOP) {                          else { /* PVOP */
1843                                  if (pEnc->mbParam.m_quarterpel)                                  const VECTOR * const mv = (pParam->vol_flags & XVID_VOL_QUARTERPEL) ?
1844                                          skip_possible &= ( (pMB->qmvs[0].x == 0) && (pMB->qmvs[0].y == 0) );                                                                                  pMB->qmvs : pMB->mvs;
1845                                  else                                  skip_possible &= ((mv->x|mv->y) == 0);
                                         skip_possible &= ( (pMB->mvs[0].x == 0) && (pMB->mvs[0].y == 0) );  
1846                          }                          }
1847    
1848                          if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) {                          if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) {
   
1849  /* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */  /* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */
   
                                 if (pEnc->current->coding_type == P_VOP)        /* special rule for P-VOP's SKIP */  
                                 {  
1850                                          int bSkip = 1;                                          int bSkip = 1;
1851    
1852                                          for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++)                                  if (current->coding_type == P_VOP) {    /* special rule for P-VOP's SKIP */
1853                                          {                                          for (k = pEnc->bframenum_head; k < pEnc->bframenum_tail; k++) {
1854                                                  int iSAD;                                                  int iSAD;
1855                                                  iSAD = sad16(pEnc->reference->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,                                                  iSAD = sad16(reference->image.y + 16*y*pParam->edged_width + 16*x,
1856                                                                          pEnc->bframes[k]->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,                                                                                  pEnc->bframes[k]->image.y + 16*y*pParam->edged_width + 16*x,
1857                                                                  pEnc->mbParam.edged_width,BFRAME_SKIP_THRESHHOLD);                                                                                  pParam->edged_width, BFRAME_SKIP_THRESHHOLD * pMB->quant);
1858                                                  if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant)                                                  if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant) {
1859                                                  {       bSkip = 0;                                                          bSkip = 0; /* could not SKIP */
1860                                                          break;                                                          if (pParam->vol_flags & XVID_VOL_QUARTERPEL) {
1861                                                  }                                                                  VECTOR predMV = get_qpmv2(current->mbs, pParam->mb_width, bound, x, y, 0);
                                         }  
   
                                         if (!bSkip) {   /* no SKIP, but trivial block */  
                                                 if(pEnc->mbParam.m_quarterpel) {  
                                                         VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);  
1862                                                          pMB->pmvs[0].x = - predMV.x;                                                          pMB->pmvs[0].x = - predMV.x;
1863                                                          pMB->pmvs[0].y = - predMV.y;                                                          pMB->pmvs[0].y = - predMV.y;
1864                                                  }                                                          } else {
1865                                                  else {                                                                  VECTOR predMV = get_pmv2(current->mbs, pParam->mb_width, bound, x, y, 0);
                                                         VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);  
1866                                                          pMB->pmvs[0].x = - predMV.x;                                                          pMB->pmvs[0].x = - predMV.x;
1867                                                          pMB->pmvs[0].y = - predMV.y;                                                          pMB->pmvs[0].y = - predMV.y;
1868                                                  }                                                  }
1869                                                  pMB->mode = MODE_INTER;                                                  pMB->mode = MODE_INTER;
1870                                                  pMB->cbp = 0;                                                  pMB->cbp = 0;
1871                                                  MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);                                                          break;
1872                                                  stop_coding_timer();                                                  }
   
                                                 continue;       /* next MB */  
1873                                          }                                          }
1874                                  }                                  }
                                 /* do SKIP */  
1875    
1876                                    if (bSkip) {
1877                                            /* do SKIP */
1878                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1879                                  MBSkip(bs);                                  MBSkip(bs);
1880                                  stop_coding_timer();                                  stop_coding_timer();
1881                                  continue;       /* next MB */                                  continue;       /* next MB */
1882                          }                          }
1883                            }
1884    
1885                          /* ordinary case: normal coded INTER/INTER4V block */                          /* ordinary case: normal coded INTER/INTER4V block */
1886                            MBCoding(current, pMB, qcoeff, bs, data->sStat);
1887                            stop_coding_timer();
1888                    }
1889            }
1890    
1891                          if (pEnc->current->global_flags & XVID_GREYSCALE)          BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */
1892                          {       pMB->cbp &= 0x3C;               /* keep only bits 5-2 */          emms();
                                 qcoeff[4*64+0]=0;               /* zero, because DC for INTRA MBs DC value is saved */  
                                 qcoeff[5*64+0]=0;  
1893                          }                          }
1894    
1895                          if(pEnc->mbParam.m_quarterpel) {  /* FrameCodeP also handles S(GMC)-VOPs */
1896                                  VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);  static int
1897                                  pMB->pmvs[0].x = pMB->qmvs[0].x - predMV.x;  FrameCodeP(Encoder * pEnc, Bitstream * bs)
1898                                  pMB->pmvs[0].y = pMB->qmvs[0].y - predMV.y;  {
1899                                  DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y);          int bits = BitstreamPos(bs);
1900                          } else {  
1901                                  VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);          FRAMEINFO *const current = pEnc->current;
1902                                  pMB->pmvs[0].x = pMB->mvs[0].x - predMV.x;          FRAMEINFO *const reference = pEnc->reference;
1903                                  pMB->pmvs[0].y = pMB->mvs[0].y - predMV.y;          MBParam * const pParam = &pEnc->mbParam;
1904                                  DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y);          int mb_width = pParam->mb_width;
1905            int mb_height = pParam->mb_height;
1906            int coded = 1;
1907    
1908            int k = 0, bound = 0, num_slices = pEnc->num_slices;
1909            int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices));
1910            void * status = NULL;
1911            int slices_per_thread = (num_slices*1024 / num_threads);
1912            int threads_per_slice = (pEnc->num_threads*1024 / num_threads);
1913    
1914            IMAGE *pRef = &reference->image;
1915    
1916            if (!reference->is_edged) {
1917                    start_timer();
1918                    image_setedges(pRef, pParam->edged_width, pParam->edged_height,
1919                                               pParam->width, pParam->height, 0);
1920                    stop_edges_timer();
1921                    reference->is_edged = 1;
1922            }
1923    
1924            pParam->m_rounding_type = 1 - pParam->m_rounding_type;
1925            current->rounding_type = pParam->m_rounding_type;
1926            current->fcode = pParam->m_fcode;
1927    
1928            if ((current->vop_flags & XVID_VOP_HALFPEL)) {
1929                    if (reference->is_interpolated != current->rounding_type) {
1930                            start_timer();
1931                            image_interpolate(pRef->y, pEnc->vInterH.y, pEnc->vInterV.y,
1932                                                              pEnc->vInterHV.y, pParam->edged_width,
1933                                                              pParam->edged_height,
1934                                                              (pParam->vol_flags & XVID_VOL_QUARTERPEL),
1935                                                              current->rounding_type);
1936                            stop_inter_timer();
1937                            reference->is_interpolated = current->rounding_type;
1938                          }                          }
1939            }
1940    
1941            current->sStat.iTextBits = current->sStat.iMvSum = current->sStat.iMvCount =
1942                    current->sStat.kblks = current->sStat.mblks = current->sStat.ublks =
1943                    current->sStat.iMVBits = 0;
1944    
1945            current->coding_type = P_VOP;
1946    
1947            if (current->vop_flags & XVID_VOP_RD_PSNRHVSM) {
1948                    image_block_variance(&current->image, pParam->edged_width, current->mbs,
1949                                         pParam->mb_width, pParam->mb_height);
1950            }
1951    
1952            call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);
1953    
1954            SetMacroblockQuants(&pEnc->mbParam, current);
1955    
1956            start_timer();
1957            if (current->vol_flags & XVID_VOL_GMC)  /* GMC only for S(GMC)-VOPs */
1958            {       int gmcval;
1959                    current->warp = GlobalMotionEst( current->mbs, pParam, current, reference,
1960                                                                     &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, num_slices);
1961    
1962                          if (pMB->mode == MODE_INTER4V)                  if (current->motion_flags & XVID_ME_GME_REFINE) {
1963                          {       int k;                          gmcval = GlobalMotionEstRefine(&current->warp,
1964                                  for (k=1;k<4;k++)                                                                                     current->mbs, pParam,
1965                                  {                                                                                     current, reference,
1966                                          if(pEnc->mbParam.m_quarterpel) {                                                                                     &current->image,
1967                                                  VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k);                                                                                     &reference->image,
1968                                                  pMB->pmvs[k].x = pMB->qmvs[k].x - predMV.x;                                                                                     &pEnc->vInterH,
1969                                                  pMB->pmvs[k].y = pMB->qmvs[k].y - predMV.y;                                                                                     &pEnc->vInterV,
1970                                  DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y);                                                                                     &pEnc->vInterHV);
1971                                          } else {                                          } else {
1972                                                  VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k);                          gmcval = globalSAD(&current->warp, pParam, current->mbs,
1973                                                  pMB->pmvs[k].x = pMB->mvs[k].x - predMV.x;                                                             current,
1974                                                  pMB->pmvs[k].y = pMB->mvs[k].y - predMV.y;                                                             &reference->image,
1975                                  DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y);                                                             &current->image,
1976                                                               pEnc->vGMC.y);
1977                                          }                                          }
1978    
1979                    gmcval += /*current->quant*/ 2 * (int)(pParam->mb_width*pParam->mb_height);
1980    
1981                    /* 1st '3': 3 warpoints, 2nd '3': 16th pel res (2<<3) */
1982                    generate_GMCparameters( 3, 3, &current->warp,
1983                                    pParam->width, pParam->height,
1984                                    &current->new_gmc_data);
1985    
1986                    if ( (gmcval<0) && ( (current->warp.duv[1].x != 0) || (current->warp.duv[1].y != 0) ||
1987                             (current->warp.duv[2].x != 0) || (current->warp.duv[2].y != 0) ) )
1988                    {
1989                            current->coding_type = S_VOP;
1990    
1991                            generate_GMCimage(&current->new_gmc_data, &reference->image,
1992                                    pParam->mb_width, pParam->mb_height,
1993                                    pParam->edged_width, pParam->edged_width/2,
1994                                    pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0,
1995                                    current->rounding_type, current->mbs, &pEnc->vGMC);
1996    
1997                    } else {
1998    
1999                            generate_GMCimage(&current->new_gmc_data, &reference->image,
2000                                    pParam->mb_width, pParam->mb_height,
2001                                    pParam->edged_width, pParam->edged_width/2,
2002                                    pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0,
2003                                    current->rounding_type, current->mbs, NULL);    /* no warping, just AMV */
2004                                  }                                  }
2005                          }                          }
2006    
2007                          MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);          if (pEnc->num_threads > 0) {
                         stop_coding_timer();  
2008    
2009                    /* multithreaded motion estimation - dispatch threads */
2010                    while (k < pEnc->num_threads) {
2011                            int i, add_s = (slices_per_thread + 512) >> 10;
2012                            int add_t = (threads_per_slice + 512) >> 10;
2013    
2014                            int start_y = (bound * mb_height + (num_slices-1)) / num_slices;
2015                            int stop_y = ((bound+add_s) * mb_height + (num_slices-1)) / num_slices;
2016                            int rows_per_thread = (stop_y - start_y + add_t - 1) / add_t;
2017    
2018                            slices_per_thread += ((num_slices*1024 / num_threads) - add_s*1024);
2019                            threads_per_slice += ((pEnc->num_threads*1024 / num_threads) - add_t*1024);
2020    
2021                            for (i = 0; i < add_t; i++) {
2022                                    memset(pEnc->smpData[k+i].complete_count_self, 0, rows_per_thread * sizeof(int));
2023    
2024                                    pEnc->smpData[k+i].pEnc = (void *) pEnc;
2025                                    pEnc->smpData[k+i].y_row = i;
2026                                    pEnc->smpData[k+i].y_step = add_t;
2027                                    pEnc->smpData[k+i].stop_y = stop_y;
2028                                    pEnc->smpData[k+i].start_y = start_y;
2029    
2030                                    /* todo: sort out temp space once and for all */
2031                                    pEnc->smpData[k+i].RefQ = (((k+i)&1) ? pEnc->vInterV.u : pEnc->vInterV.v) +
2032                                                                                            16*((k+i)>>1)*pParam->edged_width;
2033                  }                  }
2034    
2035                            pEnc->smpData[k].complete_count_above =
2036                                    pEnc->smpData[k+add_t-1].complete_count_self - 1;
2037    
2038                            bound += add_s;
2039                            k += add_t;
2040          }          }
2041    
2042          if ((pEnc->current->global_flags & XVID_REDUCED))                  for (k = 1; k < pEnc->num_threads; k++) {
2043          {                          pthread_create(&pEnc->smpData[k].handle, NULL,
2044                  image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width,                                  (void*)MotionEstimateSMP, (void*)&pEnc->smpData[k]);
                         pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width,  
                         16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV);  
2045          }          }
2046    
2047          emms();                  MotionEstimateSMP(&pEnc->smpData[0]);
2048    
2049          if (pEnc->current->global_flags & XVID_HINTEDME_GET) {                  for (k = 1; k < pEnc->num_threads; k++) {
2050                  HintedMEGet(pEnc, 0);                          pthread_join(pEnc->smpData[k].handle, &status);
2051          }          }
2052    
2053          if (pEnc->current->sStat.iMvCount == 0)                  current->fcode = 0;
2054                  pEnc->current->sStat.iMvCount = 1;                  for (k = 0; k < pEnc->num_threads; k++) {
2055                            current->sStat.iMvSum += pEnc->smpData[k].mvSum;
2056                            current->sStat.iMvCount += pEnc->smpData[k].mvCount;
2057                            if (pEnc->smpData[k].minfcode > current->fcode)
2058                                    current->fcode = pEnc->smpData[k].minfcode;
2059                    }
2060    
2061          fSigma = (float) sqrt((float) pEnc->current->sStat.iMvSum / pEnc->current->sStat.iMvCount);          } else {
2062    
2063          iSearchRange = 1 << (3 + pEnc->mbParam.m_fcode);                  /* regular ME */
2064    
2065                    MotionEstimation(&pEnc->mbParam, current, reference,
2066                                                     &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,
2067                                                     &pEnc->vGMC, 256*4096, num_slices);
2068    
         if ((fSigma > iSearchRange / 3)  
                 && (pEnc->mbParam.m_fcode <= (3 + pEnc->mbParam.m_quarterpel))) // maximum search range 128  
         {  
                 pEnc->mbParam.m_fcode++;  
                 iSearchRange *= 2;  
         } else if ((fSigma < iSearchRange / 6)  
                            && (pEnc->fMvPrevSigma >= 0)  
                            && (pEnc->fMvPrevSigma < iSearchRange / 6)  
                         && (pEnc->mbParam.m_fcode >= (2 + pEnc->mbParam.m_quarterpel))) // minimum search range 16  
         {  
                 pEnc->mbParam.m_fcode--;  
                 iSearchRange /= 2;  
2069          }          }
2070    
2071          pEnc->fMvPrevSigma = fSigma;          stop_motion_timer();
2072    
2073            set_timecodes(current,reference,pParam->fbase);
2074    
2075            BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 1, current->mbs[0].quant);
2076    
2077            /* multithreaded inter coding - dispatch threads */
2078    
2079            bound = 0;
2080            slices_per_thread = (num_slices*1024 / num_threads);
2081    
2082            for (k = 0; k < num_threads; k++) {
2083                    int add = ((slices_per_thread + 512) >> 10);
2084    
2085                    slices_per_thread += ((num_slices*1024 / num_threads) - add*1024);
2086    
2087                    pEnc->smpData[k].pEnc = (void *) pEnc;
2088                    pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices);
2089                    pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices);
2090                    pEnc->smpData[k].RefQ = ((k&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + 16*(k>>1)*pParam->edged_width;
2091    
2092                    bound += add;
2093    
2094                    if (k > 0) {
2095                            pEnc->smpData[k].sStat->iTextBits = pEnc->smpData[k].sStat->kblks =
2096                            pEnc->smpData[k].sStat->mblks = pEnc->smpData[k].sStat->ublks =
2097                            pEnc->smpData[k].sStat->iMVBits = 0;
2098    
2099                            BitstreamReset(pEnc->smpData[k].bs);
2100                    }
2101            }
2102            pEnc->smpData[0].bs = bs;
2103            pEnc->smpData[0].sStat = &current->sStat;
2104    
2105            /* create threads */
2106            for (k = 1; k < num_threads; k++) {
2107                    pthread_create(&pEnc->smpData[k].handle, NULL,
2108                            (void*)SliceCodeP, (void*)&pEnc->smpData[k]);
2109            }
2110    
2111            SliceCodeP(&pEnc->smpData[0]);
2112    
2113            /* wait until all threads are finished */
2114            for (k = 1; k < num_threads; k++) {
2115                    pthread_join(pEnc->smpData[k].handle, &status);
2116            }
2117    
2118            current->length = BitstreamLength(bs) - (bits/8);
2119    
2120            /* reassemble the pieces together */
2121            SerializeBitstreams(pEnc, pEnc->current, bs, num_threads);
2122    
2123            updateFcode(&current->sStat, pEnc);
2124    
2125          /* frame drop code */          /* frame drop code */
2126          DPRINTF(DPRINTF_DEBUG, "kmu %i %i %i", pEnc->current->sStat.kblks, pEnc->current->sStat.mblks, pEnc->current->sStat.ublks);  #if 0
2127          if (pEnc->current->sStat.kblks + pEnc->current->sStat.mblks <          DPRINTF(XVID_DEBUG_DEBUG, "kmu %i %i %i\n", current->sStat.kblks, current->sStat.mblks, current->sStat.ublks);
2128                  (pEnc->mbParam.frame_drop_ratio * mb_width * mb_height) / 100)  #endif
2129    
2130            if (current->sStat.kblks + current->sStat.mblks <
2131                    (pParam->frame_drop_ratio * mb_width * mb_height) / 100 &&
2132                    ( (pEnc->bframenum_head >= pEnc->bframenum_tail) || !(pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP)) )
2133          {          {
2134                  pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = 0;                  current->sStat.kblks = current->sStat.mblks = current->sStat.iTextBits = 0;
2135                  pEnc->current->sStat.ublks = mb_width * mb_height;                  current->sStat.ublks = mb_width * mb_height;
2136    
2137                  BitstreamReset(bs);                  BitstreamReset(bs);
2138    
2139                  set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);                  set_timecodes(current,reference,pParam->fbase);
2140                  BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 0);                  BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 0, current->mbs[0].quant);
2141    
2142                    /* copy reference frame details into the current frame */
2143                    current->quant = reference->quant;
2144                    current->motion_flags = reference->motion_flags;
2145                    current->rounding_type = reference->rounding_type;
2146                    current->fcode = reference->fcode;
2147                    current->bcode = reference->bcode;
2148                    current->stamp = reference->stamp;
2149                    image_copy(&current->image, &reference->image, pParam->edged_width, pParam->height);
2150                    memcpy(current->mbs, reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height);
2151                    coded = 0;
2152    
2153                    BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */
2154    
2155                    current->length = (BitstreamPos(bs) - bits) / 8;
2156    
2157            } else {
2158    
2159                    pEnc->current->is_edged = 0; /* not edged */
2160                    pEnc->current->is_interpolated = -1; /* not interpolated (fake rounding -1) */
2161    
2162                  // copy reference frame details into the current frame                  /* what was this frame's interpolated reference will become
2163                  pEnc->current->quant = pEnc->reference->quant;                          forward (past) reference in b-frame coding */
2164                  pEnc->current->motion_flags = pEnc->reference->motion_flags;  
2165                  pEnc->current->rounding_type = pEnc->reference->rounding_type;                  image_swap(&pEnc->vInterH, &pEnc->f_refh);
2166                  pEnc->current->quarterpel =  pEnc->reference->quarterpel;                  image_swap(&pEnc->vInterV, &pEnc->f_refv);
2167                  pEnc->current->fcode = pEnc->reference->fcode;                  image_swap(&pEnc->vInterHV, &pEnc->f_refhv);
                 pEnc->current->bcode = pEnc->reference->bcode;  
                 image_copy(&pEnc->current->image, &pEnc->reference->image, pEnc->mbParam.edged_width, pEnc->mbParam.height);  
                 memcpy(pEnc->current->mbs, pEnc->reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height);  
2168          }          }
2169    
2170          /* XXX: debug          /* XXX: debug
2171          {          {
2172                  char s[100];                  char s[100];
2173                  sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum);                  sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum);
2174                  image_dump_yuvpgm(&pEnc->current->image,                  image_dump_yuvpgm(&current->image,
2175                          pEnc->mbParam.edged_width,                          pParam->edged_width,
2176                          pEnc->mbParam.width, pEnc->mbParam.height, s);                          pParam->width, pParam->height, s);
2177    
2178                  sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum);                  sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum);
2179                  image_dump_yuvpgm(&pEnc->reference->image,                  image_dump_yuvpgm(&reference->image,
2180                          pEnc->mbParam.edged_width,                          pParam->edged_width,
2181                          pEnc->mbParam.width, pEnc->mbParam.height, s);                          pParam->width, pParam->height, s);
2182          }          }
2183          */          */
2184    
2185            return coded;
2186    }
2187    
2188    static void
2189    SliceCodeB(SMPData *data)
2190    {
2191            Encoder *pEnc = (Encoder *) data->pEnc;
2192            Bitstream *bs = (Bitstream *) data->bs;
2193    
2194            DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
2195            DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
2196    
2197            int x, y;
2198            FRAMEINFO * const frame = (FRAMEINFO * const) data->current;
2199            MBParam * const pParam = &pEnc->mbParam;
2200            int mb_width = pParam->mb_width;
2201            int mb_height = pParam->mb_height;
2202            IMAGE *f_ref = &pEnc->reference->image;
2203            IMAGE *b_ref = &pEnc->current->image;
2204    
2205            int bound = data->start_y*mb_width;
2206            int num_slices = pEnc->num_slices;
2207    
2208            if (data->start_y > 0) { /* write resync marker */
2209                    write_video_packet_header(bs, pParam, frame, bound);
2210            }
2211    
2212            for (y = data->start_y; y < data->stop_y; y++) {
2213                    int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices);
2214    
2215                    if (new_bound > bound) {
2216                            bound = new_bound;
2217                            BitstreamPadAlways(bs);
2218                            write_video_packet_header(bs, pParam, frame, bound);
2219                    }
2220    
2221                    for (x = 0; x < mb_width; x++) {
2222                            MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width];
2223    
2224                            /* decoder ignores mb when refence block is INTER(0,0), CBP=0 */
2225                            if (mb->mode == MODE_NOT_CODED) {
2226                                    if (pParam->plugin_flags & XVID_REQORIGINAL) {
2227                                            MBMotionCompensation(mb, x, y, f_ref, NULL, f_ref, NULL, NULL, &frame->image,
2228                                                                                     NULL, 0, 0, pParam->edged_width, 0, 0, data->RefQ);
2229                                    }
2230                                    continue;
2231                            }
2232    
2233                            mb->quant = frame->quant;
2234    
2235                            if (mb->cbp != 0 || pParam->plugin_flags & XVID_REQORIGINAL) {
2236                                    /* we have to motion-compensate, transfer etc,
2237                                            because there might be blocks to code */
2238    
2239                                    MBMotionCompensationBVOP(pParam, mb, x, y, &frame->image,
2240                                                                                     f_ref, &pEnc->f_refh, &pEnc->f_refv,
2241                                                                                     &pEnc->f_refhv, b_ref, &pEnc->vInterH,
2242                                                                                     &pEnc->vInterV, &pEnc->vInterHV, dct_codes,
2243                                                                                     data->RefQ);
2244    
2245                                    mb->cbp = MBTransQuantInterBVOP(pParam, frame, mb, x, y,  dct_codes, qcoeff);
2246                            }
2247    
2248                            if (mb->mode == MODE_DIRECT_NO4V)
2249                                    mb->mode = MODE_DIRECT;
2250    
2251          *pBits = BitstreamPos(bs) - *pBits;                          if (mb->mode == MODE_DIRECT && (mb->cbp | mb->pmvs[3].x | mb->pmvs[3].y) == 0)
2252                                    mb->mode = MODE_DIRECT_NONE_MV; /* skipped */
2253                            else
2254                                    if (frame->vop_flags & XVID_VOP_GREYSCALE)
2255                                            /* keep only bits 5-2 -- Chroma blocks will just be skipped by MBCodingBVOP */
2256                                            mb->cbp &= 0x3C;
2257    
2258          return 0;                                       // inter                          start_timer();
2259                            MBCodingBVOP(frame, mb, qcoeff, frame->fcode, frame->bcode, bs, data->sStat);
2260                            stop_coding_timer();
2261                    }
2262  }  }
2263    
2264            BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */
2265            emms();
2266    }
2267    
2268  static void  static void
2269  FrameCodeB(Encoder * pEnc,  FrameCodeB(Encoder * pEnc,
2270                     FRAMEINFO * frame,                     FRAMEINFO * frame,
2271                     Bitstream * bs,                     Bitstream * bs)
                    uint32_t * pBits)  
2272  {  {
2273          DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);          int bits = BitstreamPos(bs);
2274          DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);          int k = 0, bound = 0, num_slices = pEnc->num_slices;
2275          uint32_t x, y;          int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices));
2276            void * status = NULL;
2277            int slices_per_thread = (num_slices*1024 / num_threads);
2278            int threads_per_slice = (pEnc->num_threads*1024 / num_threads);
2279    
2280          IMAGE *f_ref = &pEnc->reference->image;          IMAGE *f_ref = &pEnc->reference->image;
2281          IMAGE *b_ref = &pEnc->current->image;          IMAGE *b_ref = &pEnc->current->image;
2282    
2283            MBParam * const pParam = &pEnc->mbParam;
2284            int mb_width = pParam->mb_width;
2285            int mb_height = pParam->mb_height;
2286    
2287  #ifdef BFRAMES_DEC_DEBUG  #ifdef BFRAMES_DEC_DEBUG
2288          FILE *fp;          FILE *fp;
2289          static char first=0;          static char first=0;
# Line 2117  Line 2291 
2291                  fprintf(fp,"Y=%3d   X=%3d   MB=%2d   CBP=%02X\n",y,x,mb->mode,mb->cbp); \                  fprintf(fp,"Y=%3d   X=%3d   MB=%2d   CBP=%02X\n",y,x,mb->mode,mb->cbp); \
2292          }          }
2293    
         pEnc->current->global_flags &= ~XVID_REDUCED;   /* reduced resoltion not yet supported */  
   
2294          if (!first){          if (!first){
2295                  fp=fopen("C:\\XVIDDBGE.TXT","w");                  fp=fopen("C:\\XVIDDBGE.TXT","w");
2296          }          }
2297  #endif  #endif
2298    
2299          frame->quarterpel =  pEnc->mbParam.m_quarterpel;          /* forward  */
2300            if (!pEnc->reference->is_edged) {
         // forward  
2301          image_setedges(f_ref, pEnc->mbParam.edged_width,          image_setedges(f_ref, pEnc->mbParam.edged_width,
2302                                     pEnc->mbParam.edged_height, pEnc->mbParam.width,                                     pEnc->mbParam.edged_height, pEnc->mbParam.width,
2303                                     pEnc->mbParam.height);                                             pEnc->mbParam.height, 0);
2304                    pEnc->current->is_edged = 1;
2305            }
2306    
2307            if (pEnc->reference->is_interpolated != 0) {
2308          start_timer();          start_timer();
2309          image_interpolate(f_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,                  image_interpolate(f_ref->y, pEnc->f_refh.y, pEnc->f_refv.y, pEnc->f_refhv.y,
2310                                            pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,                                            pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
2311                                            pEnc->mbParam.m_quarterpel, 0);                                                    (pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0);
2312          stop_inter_timer();          stop_inter_timer();
2313                    pEnc->reference->is_interpolated = 0;
2314            }
2315    
2316          // backward          /* backward */
2317            if (!pEnc->current->is_edged) {
2318          image_setedges(b_ref, pEnc->mbParam.edged_width,          image_setedges(b_ref, pEnc->mbParam.edged_width,
2319                                     pEnc->mbParam.edged_height, pEnc->mbParam.width,                                     pEnc->mbParam.edged_height, pEnc->mbParam.width,
2320                                     pEnc->mbParam.height);                                             pEnc->mbParam.height, 0);
2321                    pEnc->current->is_edged = 1;
2322            }
2323    
2324            if (pEnc->current->is_interpolated != 0) {
2325          start_timer();          start_timer();
2326          image_interpolate(b_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,                  image_interpolate(b_ref->y, pEnc->vInterH.y, pEnc->vInterV.y, pEnc->vInterHV.y,
2327                                            pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,                                            pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
2328                                            pEnc->mbParam.m_quarterpel, 0);                                                  (pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0);
2329          stop_inter_timer();          stop_inter_timer();
2330                    pEnc->current->is_interpolated = 0;
2331            }
2332    
2333            frame->coding_type = B_VOP;
2334    
2335            if (pEnc->current->vop_flags & XVID_VOP_RD_PSNRHVSM) {
2336                    image_block_variance(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->current->mbs,
2337                                         pEnc->mbParam.mb_width, pEnc->mbParam.mb_height);
2338            }
2339    
2340            call_plugins(pEnc, frame, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);
2341    
2342            frame->fcode = frame->bcode = pEnc->current->fcode;
2343    
2344          start_timer();          start_timer();
2345    
2346            if (pEnc->num_threads > 0) {
2347    
2348                    /* multithreaded motion estimation - dispatch threads */
2349                    while (k < pEnc->num_threads) {
2350                            int i, add_s = (slices_per_thread + 512) >> 10;
2351                            int add_t = (threads_per_slice + 512) >> 10;
2352    
2353                            int start_y = (bound * mb_height + (num_slices-1)) / num_slices;
2354                            int stop_y = ((bound+add_s) * mb_height + (num_slices-1)) / num_slices;
2355                            int rows_per_thread = (stop_y - start_y + add_t - 1) / add_t;
2356    
2357                            slices_per_thread += ((num_slices*1024 / num_threads) - add_s*1024);
2358                            threads_per_slice += ((pEnc->num_threads*1024 / num_threads) - add_t*1024);
2359    
2360                            for (i = 0; i < add_t; i++) {
2361                                    memset(pEnc->smpData[k+i].complete_count_self, 0, rows_per_thread * sizeof(int));
2362    
2363                                    pEnc->smpData[k+i].pEnc = (void *) pEnc;
2364                                    pEnc->smpData[k+i].current = frame;
2365    
2366                                    pEnc->smpData[k+i].y_row = i;
2367                                    pEnc->smpData[k+i].y_step = add_t;
2368                                    pEnc->smpData[k+i].stop_y = stop_y;
2369                                    pEnc->smpData[k+i].start_y = start_y;
2370    
2371                                    /* todo: sort out temp space once and for all */
2372                                    pEnc->smpData[k+i].RefQ = (((k+i)&1) ? pEnc->vInterV.u : pEnc->vInterV.v) +
2373                                                                                            16*((k+i)>>1)*pParam->edged_width;
2374                            }
2375    
2376                            pEnc->smpData[k].complete_count_above =
2377                                    pEnc->smpData[k+add_t-1].complete_count_self - 1;
2378    
2379                            bound += add_s;
2380                            k += add_t;
2381                    }
2382    
2383                    for (k = 1; k < pEnc->num_threads; k++) {
2384                            pthread_create(&pEnc->smpData[k].handle, NULL,
2385                                    (void*)SMPMotionEstimationBVOP, (void*)&pEnc->smpData[k]);
2386                    }
2387    
2388                    SMPMotionEstimationBVOP(&pEnc->smpData[0]);
2389    
2390                    for (k = 1; k < pEnc->num_threads; k++) {
2391                            pthread_join(pEnc->smpData[k].handle, &status);
2392                    }
2393    
2394                    frame->fcode = frame->bcode = 0;
2395                    for (k = 0; k < pEnc->num_threads; k++) {
2396                            if (pEnc->smpData[k].minfcode > frame->fcode)
2397                                    frame->fcode = pEnc->smpData[k].minfcode;
2398                            if (pEnc->smpData[k].minbcode > frame->bcode)
2399                                    frame->bcode = pEnc->smpData[k].minbcode;
2400                    }
2401            } else {
2402    
2403          MotionEstimationBVOP(&pEnc->mbParam, frame,          MotionEstimationBVOP(&pEnc->mbParam, frame,
2404                  ((int32_t)(pEnc->current->stamp - frame->stamp)),                               // time_bp                                                           ((int32_t)(pEnc->current->stamp - frame->stamp)),                              /* time_bp */
2405                  ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)),     // time_pp                                                           ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)),    /* time_pp */
2406                          pEnc->reference->mbs, f_ref,                          pEnc->reference->mbs, f_ref,
2407                                                   &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,                                                   &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,
2408                                                   pEnc->current, b_ref, &pEnc->vInterH,                                                   pEnc->current, b_ref, &pEnc->vInterH,
2409                                                   &pEnc->vInterV, &pEnc->vInterHV);                                                   &pEnc->vInterV, &pEnc->vInterHV);
2410            }
   
2411          stop_motion_timer();          stop_motion_timer();
2412    
         /*if (test_quant_type(&pEnc->mbParam, pEnc->current))  
            {  
            BitstreamWriteVolHeader(bs, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.quant_type);  
            } */  
   
         frame->coding_type = B_VOP;  
   
2413          set_timecodes(frame, pEnc->reference,pEnc->mbParam.fbase);          set_timecodes(frame, pEnc->reference,pEnc->mbParam.fbase);
2414          BitstreamWriteVopHeader(bs, &pEnc->mbParam, frame, 1);          BitstreamWriteVopHeader(bs, &pEnc->mbParam, frame, 1, frame->quant);
   
         *pBits = BitstreamPos(bs);  
2415    
2416            /* reset stats */
2417          frame->sStat.iTextBits = 0;          frame->sStat.iTextBits = 0;
2418            frame->sStat.iMVBits = 0;
2419          frame->sStat.iMvSum = 0;          frame->sStat.iMvSum = 0;
2420          frame->sStat.iMvCount = 0;          frame->sStat.iMvCount = 0;
2421          frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0;          frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0;
2422            frame->sStat.mblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height;
2423            frame->sStat.kblks = frame->sStat.ublks = 0;
2424    
2425            /* multithreaded inter coding - dispatch threads */
2426            bound = 0;
2427            slices_per_thread = (num_slices*1024 / num_threads);
2428    
2429          for (y = 0; y < pEnc->mbParam.mb_height; y++) {          for (k = 0; k < num_threads; k++) {
2430                  for (x = 0; x < pEnc->mbParam.mb_width; x++) {                  int add = ((slices_per_thread + 512) >> 10);
                         MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width];  
                         int direction = pEnc->mbParam.global & XVID_ALTERNATESCAN ? 2 : 0;  
   
                         // decoder ignores mb when refence block is INTER(0,0), CBP=0  
                         if (mb->mode == MODE_NOT_CODED) {  
                                 //mb->mvs[0].x = mb->mvs[0].y = mb->cbp = 0;  
                                 continue;  
                         }  
2431    
2432                          if (mb->mode != MODE_DIRECT_NONE_MV) {                  slices_per_thread += ((num_slices*1024 / num_threads) - add*1024);
                                 MBMotionCompensationBVOP(&pEnc->mbParam, mb, x, y, &frame->image,  
                                                                          f_ref, &pEnc->f_refh, &pEnc->f_refv,  
                                                                          &pEnc->f_refhv, b_ref, &pEnc->vInterH,  
                                                                          &pEnc->vInterV, &pEnc->vInterHV,  
                                                                          dct_codes);  
2433    
2434                                  if (mb->mode == MODE_DIRECT_NO4V) mb->mode = MODE_DIRECT;                  pEnc->smpData[k].pEnc = (void *) pEnc;
2435                                  mb->quant = frame->quant;                  pEnc->smpData[k].current = frame;
2436                    pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices);
2437                    pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices);
2438                    bound += add;
2439    
2440                                  mb->cbp =                  /* todo: sort out temp space once and for all */
2441                                          MBTransQuantInterBVOP(&pEnc->mbParam, frame, mb, dct_codes, qcoeff);                  pEnc->smpData[k].RefQ = ((k&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + 16*(k>>1)*pParam->edged_width;
2442    
2443                                  if ( (mb->mode == MODE_DIRECT) && (mb->cbp == 0)                  if (k > 0) {
2444                                          && (mb->pmvs[3].x == 0) && (mb->pmvs[3].y == 0) ) {                          BitstreamReset(pEnc->smpData[k].bs);
2445                                          mb->mode = MODE_DIRECT_NONE_MV; // skipped                          pEnc->smpData[k].sStat->iTextBits = pEnc->smpData[k].sStat->kblks =
2446                            pEnc->smpData[k].sStat->mblks = pEnc->smpData[k].sStat->ublks = pEnc->smpData[k].sStat->iMVBits = 0;
2447                                  }                                  }
2448                          }                          }
2449    
2450  #ifdef BFRAMES_DEC_DEBUG          for (k = 1; k < num_threads; k++) {
2451          BFRAME_DEBUG                  pthread_create(&pEnc->smpData[k].handle, NULL,
2452  #endif                          (void*)SliceCodeB, (void*)&pEnc->smpData[k]);
                         start_timer();  
                         MBCodingBVOP(mb, qcoeff, frame->fcode, frame->bcode, bs,  
                                                  &frame->sStat, direction);  
                         stop_coding_timer();  
                 }  
2453          }          }
2454    
2455          emms();          pEnc->smpData[0].bs = bs;
2456            pEnc->smpData[0].sStat = &frame->sStat;
2457            SliceCodeB(&pEnc->smpData[0]);
2458    
2459            for (k = 1; k < num_threads; k++) {
2460                    pthread_join(pEnc->smpData[k].handle, &status);
2461            }
2462    
2463          // TODO: dynamic fcode/bcode ???          frame->length = BitstreamLength(bs) - (bits/8);
2464    
2465          *pBits = BitstreamPos(bs) - *pBits;          /* reassemble the pieces together */
2466            SerializeBitstreams(pEnc, frame, bs, num_threads);
2467    
2468  #ifdef BFRAMES_DEC_DEBUG  #ifdef BFRAMES_DEC_DEBUG
2469          if (!first){          if (!first){

Legend:
Removed from v.1.76.2.44  
changed lines
  Added in v.1.134

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4