Changeset 517 in SHVCSoftware for branches/SHM-4.1-dev/source


Ignore:
Timestamp:
17 Dec 2013, 20:25:51 (11 years ago)
Author:
qualcomm
Message:

JSVM based down-sampler

Location:
branches/SHM-4.1-dev/source/App/TAppDownConvert
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • branches/SHM-4.1-dev/source/App/TAppDownConvert/TAppDownConvert.cpp

    r442 r517  
    3535    \brief    Down convert application main
    3636*/
    37 #include <stdio.h>
    38 #include <stdlib.h>
    39 #include <string.h>
    40 #include <math.h>
    41 
    42 //! \ingroup TAppDecoder
    43 //! \{
    44 
    45 #define pi 3.1415926
    46 
    47 int get_mem2DPelWithPad(unsigned char ***array2D, int dim0, int dim1, int iPadY, int iPadX)
    48 {
    49   int i;
    50   unsigned char *curr = NULL;
    51   int iHeight, iWidth;
    52 
    53   iHeight = dim0+2*iPadY;
    54   iWidth = dim1+2*iPadX;
    55   (*array2D) = (unsigned char**)malloc(iHeight*sizeof(unsigned char*));
    56   *(*array2D) = (unsigned char* )calloc(iHeight * iWidth, sizeof(unsigned char ));
    57 
    58   (*array2D)[0] += iPadX;
    59   curr = (*array2D)[0];
    60   for(i = 1 ; i < iHeight; i++)
    61   {
    62     curr += iWidth;
    63     (*array2D)[i] = curr;
    64   }
    65   (*array2D) = &((*array2D)[iPadY]);
    66 
     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  unsigned char* data;
     51  unsigned char* data2;
     52} ColorComponent;
     53
     54typedef struct
     55{
     56  ColorComponent y;
     57  ColorComponent u;
     58  ColorComponent v;
     59} YuvFrame;
     60
     61
     62void
     63  createColorComponent( ColorComponent& c, int maxwidth, int maxheight )
     64{
     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 ];
     72
     73  if( ! c.data || ! c.data2 )
     74  {
     75    fprintf(stderr, "\nERROR: memory allocation failed!\n\n");
     76    exit(1);
     77  }
     78}
     79
     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;
     89}
     90
     91int
     92  readColorComponent( ColorComponent& c, FILE* file, int width, int height, bool second )
     93{
     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++ )
     101  {
     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 )
     105    {
     106      return 1;
     107    }
     108    for( int xp = width; xp < iMaxPadWidth; xp++ )
     109    {
     110      buffer[xp] = buffer[xp-1];
     111    }
     112  }
     113  for( int yp = height; yp < iMaxPadHeight; yp++ )
     114  {
     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++ )
     118    {
     119      buffer[xp] = bufferX[xp];
     120    }
     121  }
    67122  return 0;
    68123}
    69124
    70 int get_mem2DintWithPad(int ***array2D, int dim0, int dim1, int iPadY, int iPadX)
    71 {
    72   int i;
    73   int *curr = NULL;
    74   int iHeight, iWidth;
    75 
    76   iHeight = dim0+2*iPadY;
    77   iWidth = dim1+2*iPadX;
    78   (*array2D) = (int**)malloc(iHeight*sizeof(int*));
    79   *(*array2D) = (int* )calloc(iHeight * iWidth, sizeof(int ));
    80 
    81   (*array2D)[0] += iPadX;
    82   curr = (*array2D)[0];
    83   for(i = 1 ; i < iHeight; i++)
    84   {
    85     curr += iWidth;
    86     (*array2D)[i] = curr;
    87   }
    88   (*array2D) = &((*array2D)[iPadY]);
    89 
     125void
     126  duplicateColorComponent( ColorComponent& c )
     127{
     128  memcpy( c.data2, c.data, c.stride * c.lines * sizeof(unsigned char) );
     129}
     130
     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) );
     140  }
     141}
     142
     143void
     144  writeColorComponent( ColorComponent& c, FILE* file, int width, int height, bool second )
     145{
     146  assert( width  <= c.stride );
     147  assert( height <= c.lines  );
     148
     149  for( int i = 0; i < height; i++ )
     150  {
     151    unsigned char* buffer = ( second ? c.data2 : c.data ) + i * c.stride;
     152    int            wsize  = (int)fwrite( buffer, sizeof(unsigned char), width, file );
     153
     154    if( wsize != width )
     155    {
     156      fprintf(stderr, "\nERROR: while writing to output file!\n\n");
     157      exit(1);
     158    }
     159  }
     160}
     161
     162
     163void
     164  createFrame( YuvFrame& f, int width, int height )
     165{
     166  createColorComponent( f.y, width,      height      );
     167  createColorComponent( f.u, width >> 1, height >> 1 );
     168  createColorComponent( f.v, width >> 1, height >> 1 );
     169}
     170
     171void
     172  deleteFrame( YuvFrame& f )
     173{
     174  deleteColorComponent( f.y );
     175  deleteColorComponent( f.u );
     176  deleteColorComponent( f.v );
     177}
     178
     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 );
    90185  return 0;
    91186}
    92187
    93 void free_mem2DPelWithPad(unsigned char **array2D, int iPadY, int iPadX)
    94 {
    95   if (array2D)
    96   {
    97     if (*array2D)
    98     {
    99       free (array2D[-iPadY]-iPadX);
    100     }
    101     else
    102     {
    103       printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n");
    104     }
    105 
    106     free (&array2D[-iPadY]);
    107   }
    108   else
    109   {
    110     printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n");
    111   }
    112 }
    113 
    114 void free_mem2DintWithPad(int **array2D, int iPadY, int iPadX)
    115 {
    116   if (array2D)
    117   {
    118     if (*array2D)
    119     {
    120       free (array2D[-iPadY]-iPadX);
    121     }
    122     else
    123     {
    124       printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n");
    125     }
    126 
    127     free (&array2D[-iPadY]);
    128   }
    129   else
    130   {
    131     printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n");
    132   }
    133 }
    134 
    135 void PadImgHorizontal(unsigned char **src, unsigned char **dst, int height, int width, int pad_h)
    136 {
    137   int i, j;
    138   unsigned char *BufSrc, *BufDst;
    139 
    140   for (j=0;j<height;j++)
    141   {   
    142     BufDst = &(dst[j][-pad_h] );
    143     BufSrc = src[j];
    144     for (i=0;i<pad_h;i++)
    145     {
    146       *(BufDst++) = BufSrc[0];
    147     }
    148     memcpy(BufDst, BufSrc, width*sizeof(unsigned char));
    149     BufDst += width;
    150     for (i=0;i<pad_h;i++)
    151     {
    152       *(BufDst++) = BufSrc[width-1];
    153     }
    154   }
    155 }
    156 
    157 void FilterImg( unsigned char **src,
    158                 int           **temp,
    159                 unsigned char **dst,
    160                 int           height1, 
    161                 int           width1, 
    162                 int           M,
    163                 int           N,
    164                 int           **phase_filter,
    165                 int           length,
    166                 int           shift,
    167                 int           plane)
    168 {
    169   int height2,width2;
    170   int k,iSum;
    171   int i0, div_i0, i1;
    172   int j0, div_j0, j1;
    173   int *p_filter;
    174   unsigned char *p_src, *p_dst;
    175   int **p_temp, *p_tmp;
    176   int shift2 = (2*shift);
    177   int shift_round = (1 << (2 * shift - 1));
    178 
    179   height2 = (height1 * M) / N;
    180   width2  = (width1  * M) / N;
    181 
    182   // horizontal filtering
    183   for(j1 = 0; j1 < height1; j1++)
    184   {
    185     i0=-N;
    186     p_tmp = temp[j1];
    187     for(i1 = 0; i1 < width2; i1++)
    188     {
    189       i0      += N;
    190       div_i0   = (i0 / M);
    191       p_src    = &src[j1][ div_i0 - (length >> 1)];
    192       p_filter = phase_filter[i0 - div_i0 * M];
    193       iSum     = 0;
    194       for(k = 0; k < length; k++)
    195       {
    196         iSum += (*p_src++) * (*p_filter++);
    197       }
    198       *p_tmp++ = iSum;
    199     }
    200   }
    201 
    202   // pad temp (vertical)
    203   for (k=-(length>>1);k<0;k++)
    204     memcpy(temp[k], temp[0], width2*sizeof(int));
    205   for (k=height1;k<(height1+(length>>1));k++)
    206     memcpy(temp[k], temp[k-1], (width2)* sizeof(int));
    207 
    208   // vertical filtering
    209   j0 = (plane == 0) ? -N : -(N-1);
    210  
    211   for(j1 = 0; j1 < height2; j1++)
    212   {
    213     j0      += N;
    214     div_j0   = (j0 / M);
    215     p_dst    = dst[j1];
    216     p_temp   = &temp[div_j0 - (length>>1)];
    217     p_filter = phase_filter[j0 - div_j0 * M];
    218     for(i1 = 0; i1 < width2;i1++)
    219     {
    220       iSum=0;
    221       for(k = 0; k < length; k++)
    222       {
    223         iSum += p_temp[k][i1] * p_filter[k];
    224       }
    225       iSum=((iSum + shift_round) >> shift2);
    226       *p_dst++ = (unsigned char)(iSum > 255 ? 255 : iSum < 0 ? 0 : iSum);
    227     }
    228   }
    229 }
    230 
    231 // ====================================================================================================================
    232 // Main function
    233 // ====================================================================================================================
    234 
    235 int main(int argc, char *argv[])
    236 {
    237   const int phase_filter_0[4][13]={
    238     {0,  2,  -3,  -9,   6,  39,  58,  39,   6,  -9,  -3,  2,  0}, 
    239     {0,  1,  -1,  -8,  -1,  31,  57,  47,  13,  -7,  -5,  1,  0}, 
    240     {0,  1,   0,  -7,  -5,  22,  53,  53,  22,  -5,  -7,  0,  1}, 
    241     {0,  0,   1,  -5,  -7,  13,  47,  57,  31,  -1,  -8,-1,  1} 
    242   };
    243 
    244   const int phase_filter_1[8][13]={
    245     {0,   0,  5,  -6,  -10,  37,  76,  37,-10,   -6, 5,  0,   0},   
    246     {0,  -1,  5,  -3,  -12,  29,  75,  45,  -7,   -8, 5,  0,   0},   
    247     {0,  -1,  4,  -1,  -13,  22,  73,  52,  -3,  -10, 4,  1,   0},   
    248     {0,  -1,  4,   1,  -13,  14,  70,  59,   2,  -12, 3,  2,  -1}, 
    249     {0,  -1,  3,   2,  -13,   8,  65,  65,   8,  -13, 2,  3,  -1},   
    250     {0,  -1,  2,   3,  -12,   2,  59,  70,  14,  -13, 1,  4,  -1},   
    251     {0,   0,  1,   4,  -10,  -3,  52,  73,  22,  -13,-1,  4,  -1},   
    252     {0,   0,  0,   5,   -8,  -7,  45,  75,  29,  -12,-3,  5,  -1}   
    253   };
    254 
    255   int i,j;
    256 
    257   int width_org,  width_org_c,  width_sampled,  width_sampled_c;
    258   int height_org, height_org_c, height_sampled, height_sampled_c;
    259   int size_org,   size_org_c,   size_sampled,   size_sampled_c;
    260 
    261   unsigned char **Y1,    **U1,    **V1;
    262   unsigned char **Y2,    **U2,    **V2;
    263   unsigned char **temp_luma,    **temp_chroma;
    264   int           **tempY, **tempU, **tempV;
    265 
    266   int **phase_filter;
    267   int log2_scaling_factor=7;
    268 
    269   FILE * infile;
    270   FILE * outfile;
    271 
    272   int M = -1 ,N = -1;
    273   int ratio = -1;
    274   int Frames=0;
    275   int totalFrames=0;
    276   int StartFrame=0;
    277   int Tap=13;
    278 
    279   if (argc < 6)
    280   {
    281     printf("\nIncorrect number of arguments!!!\n\n");
    282     printf("Syntax: \n");
    283     printf("%s <input width> <input height> <input file> <output file> <downsampling method> [frames_to_process] [start_frame]\n\n", argv[0]);
    284     printf("<downsampling method> 0: 2x downsampling, 1: 1.5x downsampling. \n");
    285     printf("Examples: \n");
    286     printf("%s 1920 1080 input_1920x1080_24p.yuv output_960x540_24p.yuv 0 \n", argv[0]);
    287     printf("%s 1920 1080 input_1920x1080_24p.yuv output_1280x720_24p.yuv 1 \n", argv[0]);
    288     return -1;
    289   }
    290 
    291   width_org  = atoi  (argv[1]);
    292   height_org = atoi  (argv[2]);
    293   infile     = fopen (argv[3], "rb");
    294   outfile    = fopen (argv[4], "wb");
    295   ratio      = atoi  (argv[5]);
    296 
    297   for(i=7; i<= argc; i++)
    298   {
    299     switch(i)
    300     {
    301     case 7:
    302       Frames = atoi(argv[6]);
    303       break;
    304     case 8:
    305       StartFrame = atoi(argv[7]);
    306       break;
    307     default:
    308       printf("Too many input arguments");
    309       break;
    310     }
    311   }
    312 
    313   if( width_org < 4 || height_org < 4 )
    314   {
    315     printf("\ninput resolution is too small, exit\n");
    316     return -1;
    317   }
    318   if ( infile == NULL || outfile == NULL )
    319   {
    320     printf("\ninput or output file is invalid, exit\n");
    321     return -1;
    322   }
    323   if ((argc > 6) && (Frames < 1 || StartFrame < 0))
    324   {
    325     printf("input frame parameter error\n");
    326     return -1;
    327   }
    328 
    329   switch( ratio )
    330   {
    331   default:
    332     printf("\ndown sampling parameter %d is not supported (0: 2x downsampling, 1: 1.5x downsampling)\n", ratio);
    333     return -1;
    334   case 0:
    335     M=4;
    336     N=8;
    337     break;
    338   case 1:
    339     M=8;
    340     N=12;
    341     break;
    342   }
    343 
    344   width_org_c      = width_org  >> 1;
    345   height_org_c     = height_org >> 1;
    346   width_sampled    = (width_org  * M) / N;
    347   height_sampled   = (height_org * M) / N;
    348   width_sampled_c  = width_sampled  >> 1;
    349   height_sampled_c = height_sampled >> 1;
    350   size_org         = height_org * width_org;
    351   size_org_c       = height_org_c * width_org_c;
    352   size_sampled     = height_sampled * width_sampled;
    353   size_sampled_c   = height_sampled_c * width_sampled_c;
    354 
    355   printf("\n=============================================================\n");
    356   printf("\n Input  = %s", argv[3]);
    357   printf("\n Output = %s", argv[4]);
    358   printf("\n Rescaling input from (%d,%d) to (%d,%d) resolution\n", width_org, height_org, width_sampled, height_sampled);
    359   printf("\n=============================================================\n\n"); 
    360 
    361   // construct phase filters
    362   get_mem2DintWithPad (&phase_filter, M, Tap, 0, 0);
    363 
    364   for (j=0;j<M;j++)
    365     for (i=0;i<Tap;i++)
    366       phase_filter[j][i]= ratio==0 ? phase_filter_0[j][i] :  phase_filter_1[j][i];
    367 
    368   get_mem2DPelWithPad (&Y1, height_org,   width_org,   0, Tap>>1);
    369   get_mem2DPelWithPad (&U1, height_org_c, width_org_c, 0, Tap>>1);
    370   get_mem2DPelWithPad (&V1, height_org_c, width_org_c, 0, Tap>>1);
    371 
    372   get_mem2DintWithPad (&tempY, height_org,   width_sampled,   Tap>>1, 0);
    373   get_mem2DintWithPad (&tempU, height_org_c, width_sampled_c, Tap>>1, 0);
    374   get_mem2DintWithPad (&tempV, height_org_c, width_sampled_c, Tap>>1, 0);
    375 
    376   get_mem2DPelWithPad (&Y2, height_sampled,   width_sampled,  0,0);
    377   get_mem2DPelWithPad (&U2, height_sampled_c, width_sampled_c,0,0);
    378   get_mem2DPelWithPad (&V2, height_sampled_c, width_sampled_c,0,0);
    379 
    380   get_mem2DPelWithPad (&temp_luma,   height_org,   width_org,  0,0);
    381   get_mem2DPelWithPad (&temp_chroma, height_org_c, width_org_c,0,0);
    382 
    383   if(StartFrame!=0)
    384   {
    385     for (i = 0; i < StartFrame; i ++)
    386     {
    387       fread(temp_luma[0], sizeof(unsigned char), size_org,     infile);
    388       fread(temp_chroma[0], sizeof(unsigned char), size_org_c, infile);
    389       fread(temp_chroma[0], sizeof(unsigned char), size_org_c, infile);
    390       if (feof(infile))
    391       {
    392         printf("\nThe start frame number exceeds the file size\n");
    393         return -1;
    394       }
    395     }
    396     //fseek64(infile, (size_org * StartFrame * 3) >> 1,SEEK_SET);
    397   }
    398 
    399   if (Frames)
    400   {
    401     totalFrames = Frames;
    402   }
    403   else
    404   {
    405     totalFrames = 0x7FFF;
    406   }
    407 
    408   i = 0;
    409   while(totalFrames)
    410   {
    411    
    412     // read and pad Y
    413     fread(temp_luma[0], sizeof(unsigned char), size_org,     infile);
    414     PadImgHorizontal(temp_luma, Y1, height_org, width_org, Tap>>1);
    415 
    416     // read and pad U
    417     fread(temp_chroma[0], sizeof(unsigned char), size_org_c, infile);
    418     PadImgHorizontal(temp_chroma, U1, height_org_c, width_org_c, Tap>>1);
    419 
    420     // read and pad V
    421     fread(temp_chroma[0], sizeof(unsigned char), size_org_c, infile);
    422     PadImgHorizontal(temp_chroma, V1, height_org_c, width_org_c, Tap>>1);
    423 
    424     if (feof(infile))
    425     {
    426       break;
    427     }
    428 
    429     fprintf(stdout,"Rescaling %dth frame\r", i);
    430     fflush(stdout);
    431 
    432     i ++;
    433     totalFrames --;
    434 
    435     FilterImg(Y1,tempY,Y2,height_org,  width_org,  M, N, phase_filter,Tap,log2_scaling_factor,0);
    436     FilterImg(U1,tempU,U2,height_org_c,width_org_c,M, N, phase_filter,Tap,log2_scaling_factor,1);
    437     FilterImg(V1,tempV,V2,height_org_c,width_org_c,M, N, phase_filter,Tap,log2_scaling_factor,2);
    438 
    439     // write a sampled frame
    440     fwrite(Y2[0], sizeof(unsigned char), size_sampled,     outfile);
    441     fwrite(U2[0], sizeof(unsigned char), size_sampled_c, outfile);
    442     fwrite(V2[0], sizeof(unsigned char), size_sampled_c, outfile);
    443 
    444   }
    445 
    446   printf("\nEnd of rescaling process.\n");
    447 
    448   free_mem2DintWithPad (phase_filter, 0, 0);
    449 
    450   free_mem2DPelWithPad (Y1, 0, Tap>>1);
    451   free_mem2DPelWithPad (U1, 0, Tap>>1);
    452   free_mem2DPelWithPad (V1, 0, Tap>>1);
    453 
    454   free_mem2DintWithPad (tempY, Tap>>1, 0);
    455   free_mem2DintWithPad (tempU, Tap>>1, 0);
    456   free_mem2DintWithPad (tempV, Tap>>1, 0);
    457 
    458   free_mem2DPelWithPad (Y2,0,0);
    459   free_mem2DPelWithPad (U2,0,0);
    460   free_mem2DPelWithPad (V2,0,0);
    461 
    462   free_mem2DPelWithPad (temp_luma,  0,0);
    463   free_mem2DPelWithPad (temp_chroma,0,0);
    464 
    465   fclose(infile);
    466   fclose(outfile);
    467 
     188void
     189  duplicateFrame( YuvFrame& f )
     190{
     191  duplicateColorComponent( f.y );
     192  duplicateColorComponent( f.u );
     193  duplicateColorComponent( f.v );
     194}
     195
     196void
     197  combineTopAndBottomInFrame( YuvFrame& f, Bool botField )
     198{
     199  combineTopAndBottomInColorComponent( f.y, botField );
     200  combineTopAndBottomInColorComponent( f.u, botField );
     201  combineTopAndBottomInColorComponent( f.v, botField );
     202}
     203
     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 );
     210
     211  if( both )
     212  {
     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 );
     216  }
     217}
     218
     219
     220void
     221  print_usage_and_exit( int test, const char* name, const char* message = 0 )
     222{
     223  if( test )
     224  {
     225    if( message )
     226    {
     227      fprintf ( stderr, "\nERROR: %s\n", message );
     228    }
     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 );
     248  }
     249}
     250
     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 )
     260  {
     261    cRP.m_iLeftFrmOffset      = crop_x0;
     262    cRP.m_iTopFrmOffset       = crop_y0;
     263    cRP.m_iScaledRefFrmWidth  = crop_w;
     264    cRP.m_iScaledRefFrmHeight = crop_h;
     265  }
     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;
     293  {
     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;
     306  }
     307  assert( resamplingMethod == 0 );
     308  if( resamplingMode < 4 )
     309  {
     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;
     312  }
     313}
     314
     315
     316
     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;
     351
     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;
     367
     368
     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; )
     382  {
     383    if( ! strcmp( argv[i], "-phase" ) )
     384    {
     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 )
     404      {
     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" );
     407      }
     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      }
     440    }
     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    }
     461  }
     462  if( ! methodInitialized )
     463  {
     464    resampling  = true;
     465    upsampling  = ( cRP.m_iRefLayerFrmWidth < cRP.m_iFrameWidth ) || ( cRP.m_iRefLayerFrmHeight < cRP.m_iFrameHeight );
     466  }
     467  if( ! croppingInitialized )
     468  {
     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    }
     479  }
     480
     481  //===== set basic parameters for resampling control =====
     482  if( resamplingMethod == 0 )
     483  {
     484    if( resamplingMode == 1 )
     485    {
     486      cRP.m_bRefLayerFrameMbsOnlyFlag = false;
     487      cRP.m_bFrameMbsOnlyFlag         = false;
     488    }
     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  }
     504
     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 );
     519  }
     520
     521  printf("Resampler\n\n");
     522
     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      }
     544
     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      }
     556
     557      //===== resample input frame =====
     558      if( ! bFinished )
     559      {
     560        resampleFrame( cFrame, cDownConvert, cRP, resamplingMethod, resamplingMode, resampling, upsampling, inputFrame != 0 );
     561      }
     562    }
     563
     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();
     575
     576  deleteFrame( cFrame );
     577  fclose     ( inputFile );
     578  fclose     ( outputFile );
     579  if( croppingParametersFile )
     580  {
     581    fclose   ( croppingParametersFile );
     582  }
     583
     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  }
    468591  return 0;
    469592}
    470 
    471 //! \}
Note: See TracChangeset for help on using the changeset viewer.