source: SHVCSoftware/branches/SHM-dev/source/App/TAppDownConvert/TAppDownConvert.cpp @ 1598

Last change on this file since 1598 was 1587, checked in by interdigital, 8 years ago

JCTVC-Y0028 was adopted to support 10bit down conversion

File size: 25.8 KB
Line 
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-2016, 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
38#include <cmath>
39#include <cstdio>
40#include <cstdlib>
41#include <cstring>
42#include <ctime>
43
44#include "DownConvert.h"
45
46typedef struct
47{
48  int            stride;
49  int            lines;
50  short* data;
51  short* data2;
52} ColorComponent;
53
54typedef struct
55{
56  int inputBitDepth;
57  int outputBitDepth;
58  ColorComponent y;
59  ColorComponent u;
60  ColorComponent v;
61} YuvFrame;
62
63
64void
65  createColorComponent( ColorComponent& c, int maxwidth, int maxheight )
66{
67  maxwidth  = ( ( maxwidth  + 15 ) >> 4 ) << 4;
68  maxheight = ( ( maxheight + 15 ) >> 4 ) << 4;
69  int size  = maxwidth * maxheight;
70  c.stride  = maxwidth;
71  c.lines   = maxheight;
72  c.data    = new short [ size ];
73  c.data2   = new short [ size ];
74
75  if( ! c.data || ! c.data2 )
76  {
77    fprintf(stderr, "\nERROR: memory allocation failed!\n\n");
78    exit(1);
79  }
80}
81
82void
83  deleteColorComponent( ColorComponent& c )
84{
85  delete[] c.data;
86  delete[] c.data2;
87  c.stride  = 0;
88  c.lines   = 0;
89  c.data    = 0;
90  c.data2   = 0;
91}
92
93int
94  readColorComponent( ColorComponent& c, FILE* file, int width, int height, int inputBitDepth, bool second )
95{
96  assert( width  <= c.stride );
97  assert( height <= c.lines  );
98  unsigned char *temp=NULL;
99 
100  int iMaxPadWidth  = gMin( c.stride, ( ( width  + 15 ) >> 4 ) << 4 );
101  int iMaxPadHeight = gMin( c.lines,  ( ( height + 31 ) >> 5 ) << 5 );
102
103  for( int i = 0; i < height; i++ )
104  {
105    short* buffer = ( second ? c.data2 : c.data ) + i * c.stride;
106    int            rsize;
107   
108    if (inputBitDepth == 10)
109    {
110       rsize = (int)fread( buffer, sizeof(short), width, file );
111    }
112    else
113    {
114       if (temp == NULL)
115         temp = (unsigned char * )calloc(width, sizeof(unsigned char));
116       rsize = (int)fread( temp, sizeof(unsigned char), width, file );
117       for (int j = 0; j < width; j++)
118         buffer[j] = (short) temp[j];
119    }
120    if( rsize != width )
121    {
122      return 1;
123    }
124    for( int xp = width; xp < iMaxPadWidth; xp++ )
125    {
126      buffer[xp] = buffer[xp-1];
127    }
128  }
129  for( int yp = height; yp < iMaxPadHeight; yp++ )
130  {
131    short* buffer  = ( second ? c.data2 : c.data ) + yp * c.stride;
132    short* bufferX = buffer - c.stride;
133    for( int xp = 0; xp < c.stride; xp++ )
134    {
135      buffer[xp] = bufferX[xp];
136    }
137  }
138  if (temp!=NULL)
139    free(temp);
140  return 0;
141}
142
143void
144  duplicateColorComponent( ColorComponent& c )
145{
146  memcpy( c.data2, c.data, c.stride * c.lines * sizeof(short) );
147}
148
149void
150  combineTopAndBottomInColorComponent( ColorComponent& c, Bool bBotField )
151{
152  int            offs = ( bBotField ? c.stride : 0 );
153  short* pDes = c.data  + offs;
154  short* pSrc = c.data2 + offs;
155  for( int i = 0; i < c.lines / 2; i++, pDes += 2*c.stride, pSrc += 2*c.stride )
156  {
157    memcpy( pDes, pSrc, c.stride * sizeof(short) );
158  }
159}
160
161void
162  writeColorComponent( ColorComponent& c, FILE* file, int width, int height, int outputBitDepth, bool second )
163{
164  assert( width  <= c.stride );
165  assert( height <= c.lines  );
166  unsigned char* temp = NULL;
167       
168  for( int i = 0; i < height; i++ )
169  {
170    short* buffer = ( second ? c.data2 : c.data ) + i * c.stride;
171    int            wsize;
172   
173    if ( outputBitDepth == 8 )
174    {
175      if (temp == NULL)
176        temp = (unsigned char * )calloc(width, sizeof(unsigned char));
177      for (int j = 0; j < width; j ++)
178        temp[j] = (unsigned char)buffer[j];
179      wsize = (int)fwrite( temp, sizeof(unsigned char), width, file );
180    }
181    else
182    {
183      wsize = (int)fwrite( buffer, sizeof(short), width, file );
184    }
185
186    if( wsize != width )
187    {
188      fprintf(stderr, "\nERROR: while writing to output file!\n\n");
189      exit(1);
190    }
191  }
192}
193
194
195void
196  createFrame( YuvFrame& f, int width, int height, int inputBitDepth, int outputBitDepth )
197{
198  f.inputBitDepth = inputBitDepth;
199  f.outputBitDepth = outputBitDepth;
200  createColorComponent( f.y, width,      height      );
201  createColorComponent( f.u, width >> 1, height >> 1 );
202  createColorComponent( f.v, width >> 1, height >> 1 );
203}
204
205void
206  deleteFrame( YuvFrame& f )
207{
208  deleteColorComponent( f.y );
209  deleteColorComponent( f.u );
210  deleteColorComponent( f.v );
211}
212
213int
214  readFrame( YuvFrame& f, FILE* file, int width, int height, bool second = false )
215{
216  ROTRS( readColorComponent( f.y, file, width,      height,      f.inputBitDepth, second ), 1 );
217  ROTRS( readColorComponent( f.u, file, width >> 1, height >> 1, f.inputBitDepth, second ), 1 );
218  ROTRS( readColorComponent( f.v, file, width >> 1, height >> 1, f.inputBitDepth, second ), 1 );
219  return 0;
220}
221
222void
223  duplicateFrame( YuvFrame& f )
224{
225  duplicateColorComponent( f.y );
226  duplicateColorComponent( f.u );
227  duplicateColorComponent( f.v );
228}
229
230void
231  combineTopAndBottomInFrame( YuvFrame& f, Bool botField )
232{
233  combineTopAndBottomInColorComponent( f.y, botField );
234  combineTopAndBottomInColorComponent( f.u, botField );
235  combineTopAndBottomInColorComponent( f.v, botField );
236}
237
238void
239  writeFrame( YuvFrame& f, FILE* file, int width, int height, bool both = false )
240{
241  writeColorComponent( f.y, file, width,      height,      f.outputBitDepth, false );
242  writeColorComponent( f.u, file, width >> 1, height >> 1, f.outputBitDepth, false );
243  writeColorComponent( f.v, file, width >> 1, height >> 1, f.outputBitDepth, false );
244
245  if( both )
246  {
247    writeColorComponent( f.y, file, width,      height,      f.outputBitDepth, true );
248    writeColorComponent( f.u, file, width >> 1, height >> 1, f.outputBitDepth, true );
249    writeColorComponent( f.v, file, width >> 1, height >> 1, f.outputBitDepth, true );
250  }
251}
252
253
254void
255  print_usage_and_exit( int test, const char* name, const char* message = 0 )
256{
257  if( test )
258  {
259    if( message )
260    {
261      fprintf ( stderr, "\nERROR: %s\n", message );
262    }
263    fprintf (   stderr, "\nUsage: %s <win> <hin> <in> <wout> <hout> <out> [<bin> <bout> <method> <t> [<skip> [<frms>]]] [[-phase <args>] ]\n\n", name );
264    fprintf (   stderr, "  win     : input width  (luma samples)\n" );
265    fprintf (   stderr, "  hin     : input height (luma samples)\n" );
266    fprintf (   stderr, "  in      : input file\n" );
267    fprintf (   stderr, "  wout    : output width  (luma samples)\n" );
268    fprintf (   stderr, "  hout    : output height (luma samples)\n" );
269    fprintf (   stderr, "  out     : output file\n" );
270    fprintf (   stderr, "\n--------------------------- OPTIONAL ---------------------------\n\n" );
271    fprintf (   stderr, "  bin     : input bit depth (8 or 10) (default: 8)\n" );
272    fprintf (   stderr, "  bout    : output bit depth (8 or 10) (default: 8)\n" );
273    fprintf (   stderr, "  method  : sampling method (0, 1, 2, 3, 4) (default: 0)\n" );
274    fprintf (   stderr, "  t       : number of temporal downsampling stages (default: 0)\n" );
275    fprintf (   stderr, "  skip    : number of frames to skip at start (default: 0)\n" );
276    fprintf (   stderr, "  frms    : number of frames wanted in output file (default: max)\n" );
277    fprintf (   stderr, "\n-------------------------- OVERLOADED --------------------------\n\n" );
278    fprintf (   stderr, " -phase <in_uv_ph_x> <in_uv_ph_y> <out_uv_ph_x> <out_uv_ph_y>\n");
279    fprintf (   stderr, "   in_uv_ph_x : input  chroma phase shift in horizontal direction (default:-1)\n" );
280    fprintf (   stderr, "   in_uv_ph_y : input  chroma phase shift in vertical   direction (default: 0)\n" );
281    fprintf (   stderr, "   out_uv_ph_x: output chroma phase shift in horizontal direction (default:-1)\n" );
282    fprintf (   stderr, "   out_uv_ph_y: output chroma phase shift in vertical   direction (default: 0)\n" );
283    fprintf (   stderr, "\n-------------------------- EXAMPLE --------------------------\n\n" );
284    fprintf (   stderr, "\nUsage: %s 4096 2048 input_video_4096x2048_10bits.yuv 2048 1024 output_video_2048x1024_8bits.yuv 10 8\n\n", name );
285    fprintf (   stderr, "\n\n");
286    exit    (   1 );
287  }
288}
289
290
291void
292  updateCropParametersFromFile( ResizeParameters& cRP, FILE* cropFile, int resamplingMethod, char* name )
293{
294  int crop_x0 = 0;
295  int crop_y0 = 0;
296  int crop_w  = 0;
297  int crop_h  = 0;
298  if( fscanf( cropFile, "%d,%d,%d,%d\n", &crop_x0, &crop_y0, &crop_w, &crop_h ) == 4 )
299  {
300    cRP.m_iLeftFrmOffset      = crop_x0;
301    cRP.m_iTopFrmOffset       = crop_y0;
302    cRP.m_iScaledRefFrmWidth  = crop_w;
303    cRP.m_iScaledRefFrmHeight = crop_h;
304  }
305  print_usage_and_exit( cRP.m_iLeftFrmOffset     & 1 || cRP.m_iTopFrmOffset       & 1,                                              name, "cropping parameters must be even values" );
306  print_usage_and_exit( cRP.m_iScaledRefFrmWidth & 1 || cRP.m_iScaledRefFrmHeight & 1,                                              name, "cropping parameters must be even values" );
307  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" );
308  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" );
309  print_usage_and_exit( cRP.m_iScaledRefFrmWidth  > gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),                            name, "wrong crop window size" );
310  print_usage_and_exit( cRP.m_iScaledRefFrmHeight > gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),                            name, "wrong crop window size" );
311  print_usage_and_exit( cRP.m_iScaledRefFrmWidth  < gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),                            name, "wrong crop window size" );
312  print_usage_and_exit( cRP.m_iScaledRefFrmHeight < gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),                            name, "wrong crop window size" );
313  print_usage_and_exit( cRP.m_iLeftFrmOffset + cRP.m_iScaledRefFrmWidth  > gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ),     name, "wrong crop window size and origin" );
314  print_usage_and_exit( cRP.m_iTopFrmOffset  + cRP.m_iScaledRefFrmHeight > gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight ),     name, "wrong crop window size and origin" );
315}
316
317
318void
319  resampleFrame( YuvFrame&          rcFrame,
320  DownConvert&       rcDownConvert,
321  ResizeParameters&  rcRP,
322  int                resamplingMethod,
323  int                resamplingMode,
324  bool               resampling,
325  bool               upsampling,
326  bool               bSecondInputFrame )
327{
328  assert( upsampling == 0 );
329
330  //===== downsampling =====
331  ResizeParameters cRP = rcRP;
332  {
333    Int iRefVerMbShift        = ( cRP.m_bRefLayerFrameMbsOnlyFlag ? 4 : 5 );
334    Int iScaledVerShift       = ( cRP.m_bFrameMbsOnlyFlag         ? 1 : 2 );
335    Int iHorDiv               = ( cRP.m_iFrameWidth    <<               1 );
336    Int iVerDiv               = ( cRP.m_iFrameHeight   << iScaledVerShift );
337    Int iRefFrmW              = ( ( cRP.m_iFrameWidth   + ( 1 <<               4 ) - 1 ) >>               4 ) <<               4;        // round to next multiple of 16
338    Int iRefFrmH              = ( ( cRP.m_iFrameHeight  + ( 1 <<  iRefVerMbShift ) - 1 ) >>  iRefVerMbShift ) <<  iRefVerMbShift;        // round to next multiple of 16 or 32 (for interlaced)
339    Int iScaledRefFrmW        = ( ( cRP.m_iScaledRefFrmWidth  * iRefFrmW + ( iHorDiv >> 1 ) ) / iHorDiv ) <<               1;  // scale and round to next multiple of  2
340    Int iScaledRefFrmH        = ( ( cRP.m_iScaledRefFrmHeight * iRefFrmH + ( iVerDiv >> 1 ) ) / iVerDiv ) << iScaledVerShift;  // scale and round to next multiple of  2 or  4 (for interlaced)
341    cRP.m_iFrameWidth         = iRefFrmW;
342    cRP.m_iFrameHeight        = iRefFrmH;
343    cRP.m_iScaledRefFrmWidth  = iScaledRefFrmW;
344    cRP.m_iScaledRefFrmHeight = iScaledRefFrmH;
345    cRP.inputBitDepth         = rcFrame.inputBitDepth;
346    cRP.outputBitDepth        = rcFrame.outputBitDepth;
347  }
348  assert( resamplingMethod == 0 );
349  if( resamplingMode < 4 )
350  {
351    rcDownConvert.downsamplingSVC       ( rcFrame.y.data,  rcFrame.y.stride, rcFrame.u.data,  rcFrame.u.stride, rcFrame.v.data,  rcFrame.v.stride, &cRP, resamplingMode == 3 );
352    return;
353  }
354}
355
356
357
358int
359  main( int argc, char *argv[] )
360{
361  //===== set standard resize parameters =====
362  ResizeParameters cRP;
363  cRP.m_bRefLayerFrameMbsOnlyFlag   = true;
364  cRP.m_bFrameMbsOnlyFlag           = true;
365  cRP.m_bRefLayerFieldPicFlag       = false;
366  cRP.m_bFieldPicFlag               = false;
367  cRP.m_bRefLayerBotFieldFlag       = false;
368  cRP.m_bBotFieldFlag               = false;
369  cRP.m_bRefLayerIsMbAffFrame       = false;
370  cRP.m_bIsMbAffFrame               = false;
371#if ZERO_PHASE
372  cRP.m_iRefLayerChromaPhaseX       = 0;
373  cRP.m_iRefLayerChromaPhaseY       = 1;
374  cRP.m_iChromaPhaseX               = 0;
375  cRP.m_iChromaPhaseY               = 1;
376#else
377  cRP.m_iRefLayerChromaPhaseX       = -1;
378  cRP.m_iRefLayerChromaPhaseY       = 0;
379  cRP.m_iChromaPhaseX               = -1;
380  cRP.m_iChromaPhaseY               = 0;
381#endif
382  cRP.m_iRefLayerFrmWidth           = 0;
383  cRP.m_iRefLayerFrmHeight          = 0;
384  cRP.m_iScaledRefFrmWidth          = 0;
385  cRP.m_iScaledRefFrmHeight         = 0;
386  cRP.m_iFrameWidth                 = 0;
387  cRP.m_iFrameHeight                = 0;
388  cRP.m_iLeftFrmOffset              = 0;
389  cRP.m_iTopFrmOffset               = 0;
390  //cRP.m_iExtendedSpatialScalability = 0;
391  cRP.m_iLevelIdc                   = 0;
392
393  //===== init parameters =====
394  FILE* inputFile                   = 0;
395  FILE* outputFile                  = 0;
396  FILE* croppingParametersFile      = 0;
397  int   inputBitDepth               = 8;
398  int   outputBitDepth              = 8;
399  int   resamplingMethod            = 0;
400  int   resamplingMode              = 0;
401  bool  croppingInitialized         = false;
402  bool  phaseInitialized            = false;
403  bool  methodInitialized           = false;
404  bool  resampling                  = false;
405  bool  upsampling                  = false;
406  int   numSpatialDyadicStages      = 0;
407  int   skipBetween                 = 0;
408  int   skipAtStart                 = 0;
409  int   maxNumOutputFrames          = 0;
410
411
412  //===== read input parameters =====
413  print_usage_and_exit( ( argc < 7 || argc > 24 ), argv[0], "wrong number of arguments" );
414  cRP.m_iRefLayerFrmWidth   = atoi  ( argv[1] );
415  cRP.m_iRefLayerFrmHeight  = atoi  ( argv[2] );
416  inputFile                 = fopen ( argv[3], "rb" );
417  cRP.m_iFrameWidth         = atoi  ( argv[4] );
418  cRP.m_iFrameHeight        = atoi  ( argv[5] );
419  outputFile                = fopen ( argv[6], "wb" );
420  print_usage_and_exit( ! inputFile,  argv[0], "failed to open input file" );
421  print_usage_and_exit( ! outputFile, argv[0], "failed to open input file" );
422  print_usage_and_exit( cRP.m_iRefLayerFrmWidth > cRP.m_iFrameWidth && cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight, argv[0], "mixed upsampling and downsampling not supported" );
423  print_usage_and_exit( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth && cRP.m_iRefLayerFrmHeight > cRP.m_iFrameHeight, argv[0], "mixed upsampling and downsampling not supported" );
424  for( int i = 7; i < argc; )
425  {
426    if( ! strcmp( argv[i], "-phase" ) )
427    {
428      print_usage_and_exit( resamplingMethod != 0,          argv[0], "phases only supported in normative resampling" );
429      print_usage_and_exit( phaseInitialized || argc < i+5, argv[0], "wrong number of phase parameters" );
430      phaseInitialized = true;
431      i++;
432      cRP.m_iRefLayerChromaPhaseX = atoi( argv[i++] );
433      cRP.m_iRefLayerChromaPhaseY = atoi( argv[i++] );
434      cRP.m_iChromaPhaseX         = atoi( argv[i++] );
435      cRP.m_iChromaPhaseY         = atoi( argv[i++] );
436      print_usage_and_exit( cRP.m_iRefLayerChromaPhaseX > 0 || cRP.m_iRefLayerChromaPhaseX < -1, argv[0], "wrong phase x parameters (range : [-1, 0])");
437      print_usage_and_exit( cRP.m_iRefLayerChromaPhaseY > 1 || cRP.m_iRefLayerChromaPhaseY < -1, argv[0], "wrong phase x parameters (range : [-1, 1])");
438      print_usage_and_exit( cRP.m_iChromaPhaseX         > 0 || cRP.m_iChromaPhaseX         < -1, argv[0], "wrong phase x parameters (range : [-1, 0])");
439      print_usage_and_exit( cRP.m_iChromaPhaseY         > 1 || cRP.m_iChromaPhaseY         < -1, argv[0], "wrong phase x parameters (range : [-1, 1])");
440    }
441    else if (i == 7) // input bit depth
442    {
443      inputBitDepth = atoi( argv[i++] );
444      print_usage_and_exit( inputBitDepth != 8 && inputBitDepth != 10, argv[0], "wrong input bit depth (8 bit or 10 bit)");
445    }
446    else if (i == 8) // output bit depth
447    {
448      outputBitDepth = atoi( argv[i++] );
449      print_usage_and_exit( outputBitDepth != 8 && outputBitDepth != 10, argv[0], "wrong output bit depth (8 bit or 10 bit)");
450    }
451    else if (i == 9) // downsampling methods
452    {
453      methodInitialized = true;
454      resamplingMethod  = atoi( argv[i++] );
455      print_usage_and_exit( resamplingMethod < 0 || resamplingMethod > 4, argv[0], "unsupported method" );
456      if( resamplingMethod > 2 )
457      {
458        print_usage_and_exit( cRP.m_iRefLayerFrmWidth  > cRP.m_iFrameWidth,  argv[0], "method 3 and 4 are not supported for downsampling" );
459        print_usage_and_exit( cRP.m_iRefLayerFrmHeight > cRP.m_iFrameHeight, argv[0], "method 3 and 4 are not supported for downsampling" );
460      }
461      if( resamplingMethod != 2 )
462      {
463        resampling  = true;
464        upsampling  = ( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth ) || ( cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight );
465      }
466      if( resamplingMethod == 1 )
467      {
468        if( upsampling )
469        {
470          int      div  = cRP.m_iFrameWidth / cRP.m_iRefLayerFrmWidth;
471          if     ( div == 1) numSpatialDyadicStages =  0;
472          else if( div == 2) numSpatialDyadicStages =  1;
473          else if( div == 4) numSpatialDyadicStages =  2;
474          else if( div == 8) numSpatialDyadicStages =  3;
475          else               numSpatialDyadicStages = -1;
476          print_usage_and_exit( numSpatialDyadicStages < 0,                           argv[0], "ratio not supported for dyadic upsampling method" );
477          print_usage_and_exit( div * cRP.m_iRefLayerFrmWidth  != cRP.m_iFrameWidth,  argv[0], "ratio is not dyadic in dyadic mode" );
478          print_usage_and_exit( div * cRP.m_iRefLayerFrmHeight != cRP.m_iFrameHeight, argv[0], "different horizontal and vertical ratio in dyadic mode" );
479        }
480        else
481        {
482          int      div  = cRP.m_iRefLayerFrmWidth / cRP.m_iFrameWidth;
483          if     ( div == 1) numSpatialDyadicStages =  0;
484          else if( div == 2) numSpatialDyadicStages =  1;
485          else if( div == 4) numSpatialDyadicStages =  2;
486          else if( div == 8) numSpatialDyadicStages =  3;
487          else               numSpatialDyadicStages = -1;
488          print_usage_and_exit( numSpatialDyadicStages < 0,                           argv[0], "ratio not supported for dyadic downsampling method" );
489          print_usage_and_exit( div * cRP.m_iFrameWidth  != cRP.m_iRefLayerFrmWidth,  argv[0], "ratio is not dyadic in dyadic mode" );
490          print_usage_and_exit( div * cRP.m_iFrameHeight != cRP.m_iRefLayerFrmHeight, argv[0], "different horizontal and vertical ratio in dyadic mode" );
491        }
492      }
493    }
494    else if( i == 10 ) // temporal stages
495    {
496      int TStages = atoi( argv[i++] );
497      skipBetween = ( 1 << TStages ) - 1;
498      print_usage_and_exit( TStages < 0,              argv[0], "negative number of temporal stages" );
499    }
500    else if( i == 11 ) // skipped frames
501    {
502      skipAtStart = atoi( argv[i++] );
503      print_usage_and_exit( skipAtStart < 0,          argv[0], "negative number of skipped frames at start" );
504    }
505    else if( i == 12 ) // output frames
506    {
507      maxNumOutputFrames = atoi( argv[i++] );
508      print_usage_and_exit( maxNumOutputFrames < 0 ,  argv[0], "negative number of output frames" );
509    }
510    else
511    {
512      print_usage_and_exit( true, argv[0], "error in command line parameters" );
513    }
514  }
515  if( ! methodInitialized )
516  {
517    resampling  = true;
518    upsampling  = ( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth ) || ( cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight );
519  }
520  if( ! croppingInitialized )
521  {
522    if( resamplingMethod == 2 )
523    {
524      cRP.m_iScaledRefFrmWidth  = gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
525      cRP.m_iScaledRefFrmHeight = gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
526    }
527    else
528    {
529      cRP.m_iScaledRefFrmWidth  = gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
530      cRP.m_iScaledRefFrmHeight = gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
531    }
532  }
533
534  //===== set basic parameters for resampling control =====
535  if( resamplingMethod == 0 )
536  {
537    if( resamplingMode == 1 )
538    {
539      cRP.m_bRefLayerFrameMbsOnlyFlag = false;
540      cRP.m_bFrameMbsOnlyFlag         = false;
541    }
542    else if( resamplingMode == 2 || resamplingMode == 3 )
543    {
544      cRP.m_bFrameMbsOnlyFlag     = false;
545      if( ! upsampling )
546      {
547        cRP.m_bFieldPicFlag       = true;
548        cRP.m_bBotFieldFlag       = ( resamplingMode == 3 );
549      }
550    }
551    else if( resamplingMode == 4 || resamplingMode == 5 )
552    {
553      cRP.m_bRefLayerFrameMbsOnlyFlag = false;
554      cRP.m_bRefLayerFieldPicFlag     = true;
555    }
556  }
557
558  //===== initialize classes =====
559  YuvFrame    cFrame;
560  DownConvert cDownConvert;
561  {
562    int maxWidth  = gMax( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
563    int maxHeight = gMax( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
564    int minWidth  = gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  );
565    int minHeight = gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight );
566    int minWRnd16 = ( ( minWidth  + 15 ) >> 4 ) << 4;
567    int minHRnd32 = ( ( minHeight + 31 ) >> 5 ) << 5;
568    maxWidth      = ( ( maxWidth  * minWRnd16 + ( minWidth  << 4 ) - 1 ) / ( minWidth  << 4 ) ) << 4;
569    maxHeight     = ( ( maxHeight * minHRnd32 + ( minHeight << 4 ) - 1 ) / ( minHeight << 4 ) ) << 4;
570    createFrame( cFrame, maxWidth, maxHeight, inputBitDepth, outputBitDepth );
571    cDownConvert.init(   maxWidth, maxHeight );
572  }
573
574  printf("Resampler\n\n");
575
576  //===== loop over frames =====
577  int   skip              = skipAtStart;
578  int   writtenFrames     = 0;
579  int   numInputFrames    = ( resamplingMode >= 4 && ! upsampling ? 2 : 1 );
580  int   numOutputFrames   = ( resamplingMode >= 4 &&   upsampling ? 2 : 1 );
581  bool  bFinished         = false;
582  long  startTime         = clock();
583  while( ! bFinished )
584  {
585    for( int inputFrame = 0; inputFrame < numInputFrames && ! bFinished; inputFrame++ )
586    {
587      //===== read input frame =====
588      for( int numToRead = skip + 1; numToRead > 0 && ! bFinished; numToRead-- )
589      {
590        bFinished = ( readFrame( cFrame, inputFile, cRP.m_iRefLayerFrmWidth, cRP.m_iRefLayerFrmHeight, inputFrame != 0 ) != 0 );
591      }
592      skip = skipBetween;
593      if( cRP.m_iExtendedSpatialScalability == 2 && ! bFinished )
594      {
595        updateCropParametersFromFile( cRP, croppingParametersFile, resamplingMethod, argv[0] );
596      }
597
598      //===== set resampling parameter =====
599      if( resamplingMethod != 0 &&
600        cRP.m_iScaledRefFrmWidth  == gMin( cRP.m_iRefLayerFrmWidth,  cRP.m_iFrameWidth  ) &&
601        cRP.m_iScaledRefFrmHeight == gMin( cRP.m_iRefLayerFrmHeight, cRP.m_iFrameHeight )   )
602      {
603        resampling = false;
604      }
605      else
606      {
607        resampling = true;
608      }
609
610      //===== resample input frame =====
611      if( ! bFinished )
612      {
613        resampleFrame( cFrame, cDownConvert, cRP, resamplingMethod, resamplingMode, resampling, upsampling, inputFrame != 0 );
614      }
615    }
616
617    //===== write output frame =====
618    if( ! bFinished )
619    {
620      Bool bWriteTwoFrames = ( numOutputFrames == 2 && ( maxNumOutputFrames == 0 || writtenFrames + 1 < maxNumOutputFrames ) );
621      writeFrame( cFrame, outputFile, cRP.m_iFrameWidth, cRP.m_iFrameHeight, bWriteTwoFrames );
622      writtenFrames += ( bWriteTwoFrames ? 2 : 1 );
623      bFinished      = ( maxNumOutputFrames != 0 && writtenFrames == maxNumOutputFrames );
624      fprintf( stderr, "\r%6d frames converted", writtenFrames );
625    }
626  }
627  long  endTime           = clock();
628
629  deleteFrame( cFrame );
630  fclose     ( inputFile );
631  fclose     ( outputFile );
632  if( croppingParametersFile )
633  {
634    fclose   ( croppingParametersFile );
635  }
636
637  fprintf( stderr, "\n" );
638  double deltaInSecond = (double)( endTime - startTime) / (double)CLOCKS_PER_SEC;
639  fprintf( stderr, "in %.2lf seconds => %.0lf ms/frame\n", deltaInSecond, deltaInSecond / (double)writtenFrames * 1000.0 );
640  if( writtenFrames < maxNumOutputFrames )
641  {
642    fprintf( stderr, "\nNOTE: less output frames generated than specified!!!\n\n" );
643  }
644  return 0;
645}
Note: See TracBrowser for help on using the repository browser.