source: SHVCSoftware/trunk/source/App/TAppDownConvert/TAppDownConvert.cpp @ 582

Last change on this file since 582 was 540, checked in by seregin, 11 years ago

merge SHM-4.1-dev branch

File size: 24.2 KB
RevLine 
[340]1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license. 
5 *
6 * Copyright (c) 2010-2013, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     TAppDownConvert.cpp
35    \brief    Down convert application main
36*/
37
[540]38#include <cmath>
39#include <cstdio>
40#include <cstdlib>
41#include <cstring>
42#include <ctime>
[340]43
[540]44#include "DownConvert.h"
[340]45
[540]46typedef struct
[340]47{
[540]48  int            stride;
49  int            lines;
50  unsigned char* data;
51  unsigned char* data2;
52} ColorComponent;
[340]53
[540]54typedef struct
55{
56  ColorComponent y;
57  ColorComponent u;
58  ColorComponent v;
59} YuvFrame;
[340]60
61
[540]62void
63  createColorComponent( ColorComponent& c, int maxwidth, int maxheight )
[340]64{
[540]65  maxwidth  = ( ( maxwidth  + 15 ) >> 4 ) << 4;
66  maxheight = ( ( maxheight + 15 ) >> 4 ) << 4;
67  int size  = maxwidth * maxheight;
68  c.stride  = maxwidth;
69  c.lines   = maxheight;
70  c.data    = new unsigned char [ size ];
71  c.data2   = new unsigned char [ size ];
[340]72
[540]73  if( ! c.data || ! c.data2 )
[340]74  {
[540]75    fprintf(stderr, "\nERROR: memory allocation failed!\n\n");
76    exit(1);
[340]77  }
[540]78}
[340]79
[540]80void
81  deleteColorComponent( ColorComponent& c )
82{
83  delete[] c.data;
84  delete[] c.data2;
85  c.stride  = 0;
86  c.lines   = 0;
87  c.data    = 0;
88  c.data2   = 0;
[340]89}
90
[540]91int
92  readColorComponent( ColorComponent& c, FILE* file, int width, int height, bool second )
[340]93{
[540]94  assert( width  <= c.stride );
95  assert( height <= c.lines  );
96
97  int iMaxPadWidth  = gMin( c.stride, ( ( width  + 15 ) >> 4 ) << 4 );
98  int iMaxPadHeight = gMin( c.lines,  ( ( height + 31 ) >> 5 ) << 5 );
99
100  for( int i = 0; i < height; i++ )
[340]101  {
[540]102    unsigned char* buffer = ( second ? c.data2 : c.data ) + i * c.stride;
103    int            rsize  = (int)fread( buffer, sizeof(unsigned char), width, file );
104    if( rsize != width )
[340]105    {
[540]106      return 1;
[340]107    }
[540]108    for( int xp = width; xp < iMaxPadWidth; xp++ )
[340]109    {
[540]110      buffer[xp] = buffer[xp-1];
[340]111    }
112  }
[540]113  for( int yp = height; yp < iMaxPadHeight; yp++ )
[340]114  {
[540]115    unsigned char* buffer  = ( second ? c.data2 : c.data ) + yp * c.stride;
116    unsigned char* bufferX = buffer - c.stride;
117    for( int xp = 0; xp < c.stride; xp++ )
[340]118    {
[540]119      buffer[xp] = bufferX[xp];
[340]120    }
121  }
[540]122  return 0;
[340]123}
124
[540]125void
126  duplicateColorComponent( ColorComponent& c )
[340]127{
[540]128  memcpy( c.data2, c.data, c.stride * c.lines * sizeof(unsigned char) );
129}
[340]130
[540]131void
132  combineTopAndBottomInColorComponent( ColorComponent& c, Bool bBotField )
133{
134  int            offs = ( bBotField ? c.stride : 0 );
135  unsigned char* pDes = c.data  + offs;
136  unsigned char* pSrc = c.data2 + offs;
137  for( int i = 0; i < c.lines / 2; i++, pDes += 2*c.stride, pSrc += 2*c.stride )
138  {
139    memcpy( pDes, pSrc, c.stride * sizeof(unsigned char) );
[340]140  }
141}
142
[540]143void
144  writeColorComponent( ColorComponent& c, FILE* file, int width, int height, bool second )
[340]145{
[540]146  assert( width  <= c.stride );
147  assert( height <= c.lines  );
[340]148
[540]149  for( int i = 0; i < height; i++ )
[340]150  {
[540]151    unsigned char* buffer = ( second ? c.data2 : c.data ) + i * c.stride;
152    int            wsize  = (int)fwrite( buffer, sizeof(unsigned char), width, file );
[340]153
[540]154    if( wsize != width )
[340]155    {
[540]156      fprintf(stderr, "\nERROR: while writing to output file!\n\n");
157      exit(1);
[340]158    }
159  }
160}
161
162
[540]163void
164  createFrame( YuvFrame& f, int width, int height )
[340]165{
[540]166  createColorComponent( f.y, width,      height      );
167  createColorComponent( f.u, width >> 1, height >> 1 );
168  createColorComponent( f.v, width >> 1, height >> 1 );
169}
[340]170
[540]171void
172  deleteFrame( YuvFrame& f )
173{
174  deleteColorComponent( f.y );
175  deleteColorComponent( f.u );
176  deleteColorComponent( f.v );
177}
[340]178
[540]179int
180  readFrame( YuvFrame& f, FILE* file, int width, int height, bool second = false )
181{
182  ROTRS( readColorComponent( f.y, file, width,      height,      second ), 1 );
183  ROTRS( readColorComponent( f.u, file, width >> 1, height >> 1, second ), 1 );
184  ROTRS( readColorComponent( f.v, file, width >> 1, height >> 1, second ), 1 );
185  return 0;
186}
[340]187
[540]188void
189  duplicateFrame( YuvFrame& f )
190{
191  duplicateColorComponent( f.y );
192  duplicateColorComponent( f.u );
193  duplicateColorComponent( f.v );
194}
[340]195
[540]196void
197  combineTopAndBottomInFrame( YuvFrame& f, Bool botField )
198{
199  combineTopAndBottomInColorComponent( f.y, botField );
200  combineTopAndBottomInColorComponent( f.u, botField );
201  combineTopAndBottomInColorComponent( f.v, botField );
202}
[340]203
[540]204void
205  writeFrame( YuvFrame& f, FILE* file, int width, int height, bool both = false )
206{
207  writeColorComponent( f.y, file, width,      height,      false );
208  writeColorComponent( f.u, file, width >> 1, height >> 1, false );
209  writeColorComponent( f.v, file, width >> 1, height >> 1, false );
[340]210
[540]211  if( both )
[340]212  {
[540]213    writeColorComponent( f.y, file, width,      height,      true );
214    writeColorComponent( f.u, file, width >> 1, height >> 1, true );
215    writeColorComponent( f.v, file, width >> 1, height >> 1, true );
[340]216  }
[540]217}
[340]218
219
[540]220void
221  print_usage_and_exit( int test, const char* name, const char* message = 0 )
222{
223  if( test )
[340]224  {
[540]225    if( message )
[340]226    {
[540]227      fprintf ( stderr, "\nERROR: %s\n", message );
[340]228    }
[540]229    fprintf (   stderr, "\nUsage: %s <win> <hin> <in> <wout> <hout> <out> [<t> [<skip> [<frms>]]] [[-phase <args>] ]\n\n", name );
230    fprintf (   stderr, "  win     : input width  (luma samples)\n" );
231    fprintf (   stderr, "  hin     : input height (luma samples)\n" );
232    fprintf (   stderr, "  in      : input file\n" );
233    fprintf (   stderr, "  wout    : output width  (luma samples)\n" );
234    fprintf (   stderr, "  hout    : output height (luma samples)\n" );
235    fprintf (   stderr, "  out     : output file\n" );
236    fprintf (   stderr, "\n--------------------------- OPTIONAL ---------------------------\n\n" );
237    fprintf (   stderr, "  t       : number of temporal downsampling stages (default: 0)\n" );
238    fprintf (   stderr, "  skip    : number of frames to skip at start (default: 0)\n" );
239    fprintf (   stderr, "  frms    : number of frames wanted in output file (default: max)\n" );
240    fprintf (   stderr, "\n-------------------------- OVERLOADED --------------------------\n\n" );
241    fprintf (   stderr, " -phase <in_uv_ph_x> <in_uv_ph_y> <out_uv_ph_x> <out_uv_ph_y>\n");
242    fprintf (   stderr, "   in_uv_ph_x : input  chroma phase shift in horizontal direction (default:-1)\n" );
243    fprintf (   stderr, "   in_uv_ph_y : input  chroma phase shift in vertical   direction (default: 0)\n" );
244    fprintf (   stderr, "   out_uv_ph_x: output chroma phase shift in horizontal direction (default:-1)\n" );
245    fprintf (   stderr, "   out_uv_ph_y: output chroma phase shift in vertical   direction (default: 0)\n" );
246    fprintf (   stderr, "\n\n");
247    exit    (   1 );
[340]248  }
[540]249}
[340]250
[540]251
252void
253  updateCropParametersFromFile( ResizeParameters& cRP, FILE* cropFile, int resamplingMethod, char* name )
254{
255  int crop_x0 = 0;
256  int crop_y0 = 0;
257  int crop_w  = 0;
258  int crop_h  = 0;
259  if( fscanf( cropFile, "%d,%d,%d,%d\n", &crop_x0, &crop_y0, &crop_w, &crop_h ) == 4 )
[340]260  {
[540]261    cRP.m_iLeftFrmOffset      = crop_x0;
262    cRP.m_iTopFrmOffset       = crop_y0;
263    cRP.m_iScaledRefFrmWidth  = crop_w;
264    cRP.m_iScaledRefFrmHeight = crop_h;
[340]265  }
[540]266  print_usage_and_exit( cRP.m_iLeftFrmOffset     & 1 || cRP.m_iTopFrmOffset       & 1,                                              name, "cropping parameters must be even values" );
267  print_usage_and_exit( cRP.m_iScaledRefFrmWidth & 1 || cRP.m_iScaledRefFrmHeight & 1,                                              name, "cropping parameters must be even values" );
268  print_usage_and_exit( resamplingMethod == 2 && cRP.m_iScaledRefFrmWidth  != gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),  name, "crop dimensions must be the same as the minimal dimensions" );
269  print_usage_and_exit( resamplingMethod == 2 && cRP.m_iScaledRefFrmHeight != gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),  name, "crop dimensions must be the same as the minimal dimensions" );
270  print_usage_and_exit( cRP.m_iScaledRefFrmWidth  > gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),                            name, "wrong crop window size" );
271  print_usage_and_exit( cRP.m_iScaledRefFrmHeight > gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),                            name, "wrong crop window size" );
272  print_usage_and_exit( cRP.m_iScaledRefFrmWidth  < gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),                            name, "wrong crop window size" );
273  print_usage_and_exit( cRP.m_iScaledRefFrmHeight < gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),                            name, "wrong crop window size" );
274  print_usage_and_exit( cRP.m_iLeftFrmOffset + cRP.m_iScaledRefFrmWidth  > gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),     name, "wrong crop window size and origin" );
275  print_usage_and_exit( cRP.m_iTopFrmOffset  + cRP.m_iScaledRefFrmHeight > gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),     name, "wrong crop window size and origin" );
276}
277
278
279void
280  resampleFrame( YuvFrame&          rcFrame,
281  DownConvert&       rcDownConvert,
282  ResizeParameters&  rcRP,
283  int                resamplingMethod,
284  int                resamplingMode,
285  bool               resampling,
286  bool               upsampling,
287  bool               bSecondInputFrame )
288{
289  assert( upsampling == 0 );
290
291  //===== downsampling =====
292  ResizeParameters cRP = rcRP;
[340]293  {
[540]294    Int iRefVerMbShift        = ( cRP.m_bRefLayerFrameMbsOnlyFlag ? 4 : 5 );
295    Int iScaledVerShift       = ( cRP.m_bFrameMbsOnlyFlag         ? 1 : 2 );
296    Int iHorDiv               = ( cRP.m_iFrameWidth    <<               1 );
297    Int iVerDiv               = ( cRP.m_iFrameHeight   << iScaledVerShift );
298    Int iRefFrmW              = ( ( cRP.m_iFrameWidth   + ( 1 <<               4 ) - 1 ) >>               4 ) <<               4;        // round to next multiple of 16
299    Int iRefFrmH              = ( ( cRP.m_iFrameHeight  + ( 1 <<  iRefVerMbShift ) - 1 ) >>  iRefVerMbShift ) <<  iRefVerMbShift;        // round to next multiple of 16 or 32 (for interlaced)
300    Int iScaledRefFrmW        = ( ( cRP.m_iScaledRefFrmWidth  * iRefFrmW + ( iHorDiv >> 1 ) ) / iHorDiv ) <<               1;  // scale and round to next multiple of  2
301    Int iScaledRefFrmH        = ( ( cRP.m_iScaledRefFrmHeight * iRefFrmH + ( iVerDiv >> 1 ) ) / iVerDiv ) << iScaledVerShift;  // scale and round to next multiple of  2 or  4 (for interlaced)
302    cRP.m_iFrameWidth         = iRefFrmW;
303    cRP.m_iFrameHeight        = iRefFrmH;
304    cRP.m_iScaledRefFrmWidth  = iScaledRefFrmW;
305    cRP.m_iScaledRefFrmHeight = iScaledRefFrmH;
[340]306  }
[540]307  assert( resamplingMethod == 0 );
308  if( resamplingMode < 4 )
[340]309  {
[540]310    rcDownConvert.downsamplingSVC       ( rcFrame.y.data,  rcFrame.y.stride, rcFrame.u.data,  rcFrame.u.stride, rcFrame.v.data,  rcFrame.v.stride, &cRP, resamplingMode == 3 );
311    return;
[340]312  }
[540]313}
[442]314
[340]315
316
[540]317int
318  main( int argc, char *argv[] )
319{
320  //===== set standard resize parameters =====
321  ResizeParameters cRP;
322  cRP.m_bRefLayerFrameMbsOnlyFlag   = true;
323  cRP.m_bFrameMbsOnlyFlag           = true;
324  cRP.m_bRefLayerFieldPicFlag       = false;
325  cRP.m_bFieldPicFlag               = false;
326  cRP.m_bRefLayerBotFieldFlag       = false;
327  cRP.m_bBotFieldFlag               = false;
328  cRP.m_bRefLayerIsMbAffFrame       = false;
329  cRP.m_bIsMbAffFrame               = false;
330#if ZERO_PHASE
331  cRP.m_iRefLayerChromaPhaseX       = 0;
332  cRP.m_iRefLayerChromaPhaseY       = 1;
333  cRP.m_iChromaPhaseX               = 0;
334  cRP.m_iChromaPhaseY               = 1;
335#else
336  cRP.m_iRefLayerChromaPhaseX       = -1;
337  cRP.m_iRefLayerChromaPhaseY       = 0;
338  cRP.m_iChromaPhaseX               = -1;
339  cRP.m_iChromaPhaseY               = 0;
340#endif
341  cRP.m_iRefLayerFrmWidth           = 0;
342  cRP.m_iRefLayerFrmHeight          = 0;
343  cRP.m_iScaledRefFrmWidth          = 0;
344  cRP.m_iScaledRefFrmHeight         = 0;
345  cRP.m_iFrameWidth                 = 0;
346  cRP.m_iFrameHeight                = 0;
347  cRP.m_iLeftFrmOffset              = 0;
348  cRP.m_iTopFrmOffset               = 0;
349  //cRP.m_iExtendedSpatialScalability = 0;
350  cRP.m_iLevelIdc                   = 0;
[340]351
[540]352  //===== init parameters =====
353  FILE* inputFile                   = 0;
354  FILE* outputFile                  = 0;
355  FILE* croppingParametersFile      = 0;
356  int   resamplingMethod            = 0;
357  int   resamplingMode              = 0;
358  bool  croppingInitialized         = false;
359  bool  phaseInitialized            = false;
360  bool  methodInitialized           = false;
361  bool  resampling                  = false;
362  bool  upsampling                  = false;
363  int   numSpatialDyadicStages      = 0;
364  int   skipBetween                 = 0;
365  int   skipAtStart                 = 0;
366  int   maxNumOutputFrames          = 0;
[340]367
368
[540]369  //===== read input parameters =====
370  print_usage_and_exit( ( argc < 7 || argc > 24 ), argv[0], "wrong number of arguments" );
371  cRP.m_iRefLayerFrmWidth   = atoi  ( argv[1] );
372  cRP.m_iRefLayerFrmHeight  = atoi  ( argv[2] );
373  inputFile                 = fopen ( argv[3], "rb" );
374  cRP.m_iFrameWidth         = atoi  ( argv[4] );
375  cRP.m_iFrameHeight        = atoi  ( argv[5] );
376  outputFile                = fopen ( argv[6], "wb" );
377  print_usage_and_exit( ! inputFile,  argv[0], "failed to open input file" );
378  print_usage_and_exit( ! outputFile, argv[0], "failed to open input file" );
379  print_usage_and_exit( cRP.m_iRefLayerFrmWidth > cRP.m_iFrameWidth && cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight, argv[0], "mixed upsampling and downsampling not supported" );
380  print_usage_and_exit( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth && cRP.m_iRefLayerFrmHeight > cRP.m_iFrameHeight, argv[0], "mixed upsampling and downsampling not supported" );
381  for( int i = 7; i < argc; )
[340]382  {
[540]383    if( ! strcmp( argv[i], "-phase" ) )
[340]384    {
[540]385      print_usage_and_exit( resamplingMethod != 0,          argv[0], "phases only supported in normative resampling" );
386      print_usage_and_exit( phaseInitialized || argc < i+5, argv[0], "wrong number of phase parameters" );
387      phaseInitialized = true;
388      i++;
389      cRP.m_iRefLayerChromaPhaseX = atoi( argv[i++] );
390      cRP.m_iRefLayerChromaPhaseY = atoi( argv[i++] );
391      cRP.m_iChromaPhaseX         = atoi( argv[i++] );
392      cRP.m_iChromaPhaseY         = atoi( argv[i++] );
393      print_usage_and_exit( cRP.m_iRefLayerChromaPhaseX > 0 || cRP.m_iRefLayerChromaPhaseX < -1, argv[0], "wrong phase x parameters (range : [-1, 0])");
394      print_usage_and_exit( cRP.m_iRefLayerChromaPhaseY > 1 || cRP.m_iRefLayerChromaPhaseY < -1, argv[0], "wrong phase x parameters (range : [-1, 1])");
395      print_usage_and_exit( cRP.m_iChromaPhaseX         > 0 || cRP.m_iChromaPhaseX         < -1, argv[0], "wrong phase x parameters (range : [-1, 0])");
396      print_usage_and_exit( cRP.m_iChromaPhaseY         > 1 || cRP.m_iChromaPhaseY         < -1, argv[0], "wrong phase x parameters (range : [-1, 1])");
397    }
398    else if (i == 7)
399    {
400      methodInitialized = true;
401      resamplingMethod  = atoi( argv[i++] );
402      print_usage_and_exit( resamplingMethod < 0 || resamplingMethod > 4, argv[0], "unsupported method" );
403      if( resamplingMethod > 2 )
[340]404      {
[540]405        print_usage_and_exit( cRP.m_iRefLayerFrmWidth  > cRP.m_iFrameWidth,  argv[0], "method 3 and 4 are not supported for downsampling" );
406        print_usage_and_exit( cRP.m_iRefLayerFrmHeight > cRP.m_iFrameHeight, argv[0], "method 3 and 4 are not supported for downsampling" );
[340]407      }
[540]408      if( resamplingMethod != 2 )
409      {
410        resampling  = true;
411        upsampling  = ( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth ) || ( cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight );
412      }
413      if( resamplingMethod == 1 )
414      {
415        if( upsampling )
416        {
417          int      div  = cRP.m_iFrameWidth / cRP.m_iRefLayerFrmWidth;
418          if     ( div == 1) numSpatialDyadicStages =  0;
419          else if( div == 2) numSpatialDyadicStages =  1;
420          else if( div == 4) numSpatialDyadicStages =  2;
421          else if( div == 8) numSpatialDyadicStages =  3;
422          else               numSpatialDyadicStages = -1;
423          print_usage_and_exit( numSpatialDyadicStages < 0,                           argv[0], "ratio not supported for dyadic upsampling method" );
424          print_usage_and_exit( div * cRP.m_iRefLayerFrmWidth  != cRP.m_iFrameWidth,  argv[0], "ratio is not dyadic in dyadic mode" );
425          print_usage_and_exit( div * cRP.m_iRefLayerFrmHeight != cRP.m_iFrameHeight, argv[0], "different horizontal and vertical ratio in dyadic mode" );
426        }
427        else
428        {
429          int      div  = cRP.m_iRefLayerFrmWidth / cRP.m_iFrameWidth;
430          if     ( div == 1) numSpatialDyadicStages =  0;
431          else if( div == 2) numSpatialDyadicStages =  1;
432          else if( div == 4) numSpatialDyadicStages =  2;
433          else if( div == 8) numSpatialDyadicStages =  3;
434          else               numSpatialDyadicStages = -1;
435          print_usage_and_exit( numSpatialDyadicStages < 0,                           argv[0], "ratio not supported for dyadic downsampling method" );
436          print_usage_and_exit( div * cRP.m_iFrameWidth  != cRP.m_iRefLayerFrmWidth,  argv[0], "ratio is not dyadic in dyadic mode" );
437          print_usage_and_exit( div * cRP.m_iFrameHeight != cRP.m_iRefLayerFrmHeight, argv[0], "different horizontal and vertical ratio in dyadic mode" );
438        }
439      }
[340]440    }
[540]441    else if( i == 8 )
442    {
443      int TStages = atoi( argv[i++] );
444      skipBetween = ( 1 << TStages ) - 1;
445      print_usage_and_exit( TStages < 0,              argv[0], "negative number of temporal stages" );
446    }
447    else if( i == 9 )
448    {
449      skipAtStart = atoi( argv[i++] );
450      print_usage_and_exit( skipAtStart < 0,          argv[0], "negative number of skipped frames at start" );
451    }
452    else if( i == 10 )
453    {
454      maxNumOutputFrames = atoi( argv[i++] );
455      print_usage_and_exit( maxNumOutputFrames < 0 ,  argv[0], "negative number of output frames" );
456    }
457    else
458    {
459      print_usage_and_exit( true, argv[0], "error in command line parameters" );
460    }
[340]461  }
[540]462  if( ! methodInitialized )
[340]463  {
[540]464    resampling  = true;
465    upsampling  = ( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth ) || ( cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight );
[340]466  }
[540]467  if( ! croppingInitialized )
[340]468  {
[540]469    if( resamplingMethod == 2 )
470    {
471      cRP.m_iScaledRefFrmWidth  = gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
472      cRP.m_iScaledRefFrmHeight = gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
473    }
474    else
475    {
476      cRP.m_iScaledRefFrmWidth  = gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
477      cRP.m_iScaledRefFrmHeight = gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
478    }
[340]479  }
480
[540]481  //===== set basic parameters for resampling control =====
482  if( resamplingMethod == 0 )
[340]483  {
[540]484    if( resamplingMode == 1 )
[340]485    {
[540]486      cRP.m_bRefLayerFrameMbsOnlyFlag = false;
487      cRP.m_bFrameMbsOnlyFlag         = false;
[340]488    }
[540]489    else if( resamplingMode == 2 || resamplingMode == 3 )
490    {
491      cRP.m_bFrameMbsOnlyFlag     = false;
492      if( ! upsampling )
493      {
494        cRP.m_bFieldPicFlag       = true;
495        cRP.m_bBotFieldFlag       = ( resamplingMode == 3 );
496      }
497    }
498    else if( resamplingMode == 4 || resamplingMode == 5 )
499    {
500      cRP.m_bRefLayerFrameMbsOnlyFlag = false;
501      cRP.m_bRefLayerFieldPicFlag     = true;
502    }
503  }
[340]504
[540]505  //===== initialize classes =====
506  YuvFrame    cFrame;
507  DownConvert cDownConvert;
508  {
509    int maxWidth  = gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
510    int maxHeight = gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
511    int minWidth  = gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
512    int minHeight = gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
513    int minWRnd16 = ( ( minWidth  + 15 ) >> 4 ) << 4;
514    int minHRnd32 = ( ( minHeight + 31 ) >> 5 ) << 5;
515    maxWidth      = ( ( maxWidth  * minWRnd16 + ( minWidth  << 4 ) - 1 ) / ( minWidth  << 4 ) ) << 4;
516    maxHeight     = ( ( maxHeight * minHRnd32 + ( minHeight << 4 ) - 1 ) / ( minHeight << 4 ) ) << 4;
517    createFrame( cFrame, maxWidth, maxHeight );
518    cDownConvert.init(   maxWidth, maxHeight );
[340]519  }
520
[540]521  printf("Resampler\n\n");
[340]522
[540]523  //===== loop over frames =====
524  int   skip              = skipAtStart;
525  int   writtenFrames     = 0;
526  int   numInputFrames    = ( resamplingMode >= 4 && ! upsampling ? 2 : 1 );
527  int   numOutputFrames   = ( resamplingMode >= 4 &&   upsampling ? 2 : 1 );
528  bool  bFinished         = false;
529  long  startTime         = clock();
530  while( ! bFinished )
531  {
532    for( int inputFrame = 0; inputFrame < numInputFrames && ! bFinished; inputFrame++ )
533    {
534      //===== read input frame =====
535      for( int numToRead = skip + 1; numToRead > 0 && ! bFinished; numToRead-- )
536      {
537        bFinished = ( readFrame( cFrame, inputFile, cRP.m_iRefLayerFrmWidth, cRP.m_iRefLayerFrmHeight, inputFrame != 0 ) != 0 );
538      }
539      skip = skipBetween;
540      if( cRP.m_iExtendedSpatialScalability == 2 && ! bFinished )
541      {
542        updateCropParametersFromFile( cRP, croppingParametersFile, resamplingMethod, argv[0] );
543      }
[340]544
[540]545      //===== set resampling parameter =====
546      if( resamplingMethod != 0 &&
547        cRP.m_iScaledRefFrmWidth  == gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ) &&
548        cRP.m_iScaledRefFrmHeight == gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight )   )
549      {
550        resampling = false;
551      }
552      else
553      {
554        resampling = true;
555      }
[340]556
[540]557      //===== resample input frame =====
558      if( ! bFinished )
559      {
560        resampleFrame( cFrame, cDownConvert, cRP, resamplingMethod, resamplingMode, resampling, upsampling, inputFrame != 0 );
561      }
562    }
[340]563
[540]564    //===== write output frame =====
565    if( ! bFinished )
566    {
567      Bool bWriteTwoFrames = ( numOutputFrames == 2 && ( maxNumOutputFrames == 0 || writtenFrames + 1 < maxNumOutputFrames ) );
568      writeFrame( cFrame, outputFile, cRP.m_iFrameWidth, cRP.m_iFrameHeight, bWriteTwoFrames );
569      writtenFrames += ( bWriteTwoFrames ? 2 : 1 );
570      bFinished      = ( maxNumOutputFrames != 0 && writtenFrames == maxNumOutputFrames );
571      fprintf( stderr, "\r%6d frames converted", writtenFrames );
572    }
573  }
574  long  endTime           = clock();
[340]575
[540]576  deleteFrame( cFrame );
577  fclose     ( inputFile );
578  fclose     ( outputFile );
579  if( croppingParametersFile )
580  {
581    fclose   ( croppingParametersFile );
582  }
[340]583
[540]584  fprintf( stderr, "\n" );
585  double deltaInSecond = (double)( endTime - startTime) / (double)CLOCKS_PER_SEC;
586  fprintf( stderr, "in %.2lf seconds => %.0lf ms/frame\n", deltaInSecond, deltaInSecond / (double)writtenFrames * 1000.0 );
587  if( writtenFrames < maxNumOutputFrames )
588  {
589    fprintf( stderr, "\nNOTE: less output frames generated than specified!!!\n\n" );
590  }
[340]591  return 0;
592}
Note: See TracBrowser for help on using the repository browser.