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

Last change on this file since 851 was 442, checked in by seregin, 11 years ago

reintegrate SHM-3.1-dev branch

File size: 13.9 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-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#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
47int 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
67  return 0;
68}
69
70int 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
90  return 0;
91}
92
93void 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
114void 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
135void 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
157void 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
235int 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
468  return 0;
469}
470
471//! \}
Note: See TracBrowser for help on using the repository browser.