source: 3DVCSoftware/trunk/source/Lib/TLibVideoIO/TVideoIOYuv.cpp @ 608

Last change on this file since 608 was 608, checked in by tech, 11 years ago

Merged DEV-2.0-dev0@604.

  • Property svn:eol-style set to native
File size: 15.6 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     TVideoIOYuv.cpp
35    \brief    YUV file I/O class
36*/
37
38#include <cstdlib>
39#include <fcntl.h>
40#include <assert.h>
41#include <sys/stat.h>
42#include <fstream>
43#include <iostream>
44
45#include "TLibCommon/TComRom.h"
46#include "TVideoIOYuv.h"
47
48using namespace std;
49
50/**
51 * Perform division with rounding of all pixels in img by
52 * 2<sup>shiftbits</sup>. All pixels are clipped to [minval, maxval]
53 *
54 * @param img        pointer to image to be transformed
55 * @param stride     distance between vertically adjacent pixels of img.
56 * @param width      width of active area in img.
57 * @param height     height of active area in img.
58 * @param shiftbits  number of rounding bits
59 * @param minval     minimum clipping value
60 * @param maxval     maximum clipping value
61 */
62static void invScalePlane(Pel* img, UInt stride, UInt width, UInt height,
63                       UInt shiftbits, Pel minval, Pel maxval)
64{
65  Pel offset = 1 << (shiftbits-1);
66  for (UInt y = 0; y < height; y++)
67  {
68    for (UInt x = 0; x < width; x++)
69    {
70      Pel val = (img[x] + offset) >> shiftbits;
71      img[x] = Clip3(minval, maxval, val);
72    }
73    img += stride;
74  }
75}
76
77/**
78 * Multiply all pixels in img by 2<sup>shiftbits</sup>.
79 *
80 * @param img        pointer to image to be transformed
81 * @param stride     distance between vertically adjacent pixels of img.
82 * @param width      width of active area in img.
83 * @param height     height of active area in img.
84 * @param shiftbits  number of bits to shift
85 */
86static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
87                       UInt shiftbits)
88{
89  for (UInt y = 0; y < height; y++)
90  {
91    for (UInt x = 0; x < width; x++)
92    {
93      img[x] <<= shiftbits;
94    }
95    img += stride;
96  }
97}
98
99/**
100 * Scale all pixels in img depending upon sign of shiftbits by a factor of
101 * 2<sup>shiftbits</sup>.
102 *
103 * @param img        pointer to image to be transformed
104 * @param stride  distance between vertically adjacent pixels of img.
105 * @param width   width of active area in img.
106 * @param height  height of active area in img.
107 * @param shiftbits if zero, no operation performed
108 *                  if > 0, multiply by 2<sup>shiftbits</sup>, see scalePlane()
109 *                  if < 0, divide and round by 2<sup>shiftbits</sup> and clip,
110 *                          see invScalePlane().
111 * @param minval  minimum clipping value when dividing.
112 * @param maxval  maximum clipping value when dividing.
113 */
114static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
115                       Int shiftbits, Pel minval, Pel maxval)
116{
117  if (shiftbits == 0)
118  {
119    return;
120  }
121
122  if (shiftbits > 0)
123  {
124    scalePlane(img, stride, width, height, shiftbits);
125  }
126  else
127  {
128    invScalePlane(img, stride, width, height, -shiftbits, minval, maxval);
129  }
130}
131
132
133// ====================================================================================================================
134// Public member functions
135// ====================================================================================================================
136
137/**
138 * Open file for reading/writing Y'CbCr frames.
139 *
140 * Frames read/written have bitdepth fileBitDepth, and are automatically
141 * formatted as 8 or 16 bit word values (see TVideoIOYuv::write()).
142 *
143 * Image data read or written is converted to/from internalBitDepth
144 * (See scalePlane(), TVideoIOYuv::read() and TVideoIOYuv::write() for
145 * further details).
146 *
147 * \param pchFile          file name string
148 * \param bWriteMode       file open mode: true=read, false=write
149 * \param fileBitDepthY     bit-depth of input/output file data (luma component).
150 * \param fileBitDepthC     bit-depth of input/output file data (chroma components).
151 * \param internalBitDepthY bit-depth to scale image data to/from when reading/writing (luma component).
152 * \param internalBitDepthC bit-depth to scale image data to/from when reading/writing (chroma components).
153 */
154Void TVideoIOYuv::open( Char* pchFile, Bool bWriteMode, Int fileBitDepthY, Int fileBitDepthC, Int internalBitDepthY, Int internalBitDepthC)
155{
156  m_bitDepthShiftY = internalBitDepthY - fileBitDepthY;
157  m_bitDepthShiftC = internalBitDepthC - fileBitDepthC;
158  m_fileBitDepthY = fileBitDepthY;
159  m_fileBitDepthC = fileBitDepthC;
160
161  if ( bWriteMode )
162  {
163    m_cHandle.open( pchFile, ios::binary | ios::out );
164   
165    if( m_cHandle.fail() )
166    {
167      printf("\nfailed to write reconstructed YUV file\n");
168      exit(0);
169    }
170  }
171  else
172  {
173    m_cHandle.open( pchFile, ios::binary | ios::in );
174   
175    if( m_cHandle.fail() )
176    {
177      printf("\nfailed to open Input YUV file\n");
178      exit(0);
179    }
180  }
181 
182  return;
183}
184
185Void TVideoIOYuv::close()
186{
187  m_cHandle.close();
188}
189
190Bool TVideoIOYuv::isEof()
191{
192  return m_cHandle.eof();
193}
194
195Bool TVideoIOYuv::isFail()
196{
197  return m_cHandle.fail();
198}
199
200/**
201 * Skip numFrames in input.
202 *
203 * This function correctly handles cases where the input file is not
204 * seekable, by consuming bytes.
205 */
206void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height)
207{
208  if (!numFrames)
209    return;
210
211  const UInt wordsize = (m_fileBitDepthY > 8 || m_fileBitDepthC > 8) ? 2 : 1;
212  const streamoff framesize = wordsize * width * height * 3 / 2;
213  const streamoff offset = framesize * numFrames;
214
215  /* attempt to seek */
216  if (!!m_cHandle.seekg(offset, ios::cur))
217    return; /* success */
218  m_cHandle.clear();
219
220  /* fall back to consuming the input */
221  Char buf[512];
222  const UInt offset_mod_bufsize = offset % sizeof(buf);
223  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
224  {
225    m_cHandle.read(buf, sizeof(buf));
226  }
227  m_cHandle.read(buf, offset_mod_bufsize);
228}
229
230/**
231 * Read width*height pixels from fd into dst, optionally
232 * padding the left and right edges by edge-extension.  Input may be
233 * either 8bit or 16bit little-endian lsb-aligned words.
234 *
235 * @param dst     destination image
236 * @param fd      input file stream
237 * @param is16bit true if input file carries > 8bit data, false otherwise.
238 * @param stride  distance between vertically adjacent pixels of dst.
239 * @param width   width of active area in dst.
240 * @param height  height of active area in dst.
241 * @param pad_x   length of horizontal padding.
242 * @param pad_y   length of vertical padding.
243 * @return true for success, false in case of error
244 */
245static Bool readPlane(Pel* dst, istream& fd, Bool is16bit,
246                      UInt stride,
247                      UInt width, UInt height,
248                      UInt pad_x, UInt pad_y)
249{
250  Int read_len = width * (is16bit ? 2 : 1);
251  UChar *buf = new UChar[read_len];
252  for (Int y = 0; y < height; y++)
253  {
254    fd.read(reinterpret_cast<Char*>(buf), read_len);
255    if (fd.eof() || fd.fail() )
256    {
257      delete[] buf;
258      return false;
259    }
260
261    if (!is16bit)
262    {
263      for (Int x = 0; x < width; x++)
264      {
265        dst[x] = buf[x];
266      }
267    }
268    else
269    {
270      for (Int x = 0; x < width; x++)
271      {
272        dst[x] = (buf[2*x+1] << 8) | buf[2*x];
273      }
274    }
275
276    for (Int x = width; x < width + pad_x; x++)
277    {
278      dst[x] = dst[width - 1];
279    }
280    dst += stride;
281  }
282  for (Int y = height; y < height + pad_y; y++)
283  {
284    for (Int x = 0; x < width + pad_x; x++)
285    {
286      dst[x] = (dst - stride)[x];
287    }
288    dst += stride;
289  }
290  delete[] buf;
291  return true;
292}
293
294/**
295 * Write width*height pixels info fd from src.
296 *
297 * @param fd      output file stream
298 * @param src     source image
299 * @param is16bit true if input file carries > 8bit data, false otherwise.
300 * @param stride  distance between vertically adjacent pixels of src.
301 * @param width   width of active area in src.
302 * @param height  height of active area in src.
303 * @return true for success, false in case of error
304 */
305static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
306                       UInt stride,
307                       UInt width, UInt height)
308{
309  Int write_len = width * (is16bit ? 2 : 1);
310  UChar *buf = new UChar[write_len];
311  for (Int y = 0; y < height; y++)
312  {
313    if (!is16bit) 
314    {
315      for (Int x = 0; x < width; x++)
316      {
317        buf[x] = (UChar) src[x];
318      }
319    }
320    else 
321    {
322      for (Int x = 0; x < width; x++)
323      {
324        buf[2*x] = src[x] & 0xff;
325        buf[2*x+1] = (src[x] >> 8) & 0xff;
326      }
327    }
328
329    fd.write(reinterpret_cast<Char*>(buf), write_len);
330    if (fd.eof() || fd.fail() )
331    {
332      delete[] buf;
333      return false;
334    }
335    src += stride;
336  }
337  delete[] buf;
338  return true;
339}
340
341/**
342 * Read one Y'CbCr frame, performing any required input scaling to change
343 * from the bitdepth of the input file to the internal bit-depth.
344 *
345 * If a bit-depth reduction is required, and internalBitdepth >= 8, then
346 * the input file is assumed to be ITU-R BT.601/709 compliant, and the
347 * resulting data is clipped to the appropriate legal range, as if the
348 * file had been provided at the lower-bitdepth compliant to Rec601/709.
349 *
350 * @param pPicYuv      input picture YUV buffer class pointer
351 * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
352 * @return true for success, false in case of error
353 */
354Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuv, Int aiPad[2] )
355{
356  // check end-of-file
357  if ( isEof() ) return false;
358 
359  Int   iStride = pPicYuv->getStride();
360 
361  // compute actual YUV width & height excluding padding size
362  UInt pad_h = aiPad[0];
363  UInt pad_v = aiPad[1];
364  UInt width_full = pPicYuv->getWidth();
365  UInt height_full = pPicYuv->getHeight();
366  UInt width  = width_full - pad_h;
367  UInt height = height_full - pad_v;
368  Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
369
370  Int desired_bitdepthY = m_fileBitDepthY + m_bitDepthShiftY;
371  Int desired_bitdepthC = m_fileBitDepthC + m_bitDepthShiftC;
372  Pel minvalY = 0;
373  Pel minvalC = 0;
374  Pel maxvalY = (1 << desired_bitdepthY) - 1;
375  Pel maxvalC = (1 << desired_bitdepthC) - 1;
376#if CLIP_TO_709_RANGE
377  if (m_bitdepthShiftY < 0 && desired_bitdepthY >= 8)
378  {
379    /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
380    minvalY = 1 << (desired_bitdepthY - 8);
381    maxvalY = (0xff << (desired_bitdepthY - 8)) -1;
382  }
383  if (m_bitdepthShiftC < 0 && desired_bitdepthC >= 8)
384  {
385    /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
386    minvalC = 1 << (desired_bitdepthC - 8);
387    maxvalC = (0xff << (desired_bitdepthC - 8)) -1;
388  }
389#endif
390 
391  if (! readPlane(pPicYuv->getLumaAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
392    return false;
393  scalePlane(pPicYuv->getLumaAddr(), iStride, width_full, height_full, m_bitDepthShiftY, minvalY, maxvalY);
394
395  iStride >>= 1;
396  width_full >>= 1;
397  height_full >>= 1;
398  width >>= 1;
399  height >>= 1;
400  pad_h >>= 1;
401  pad_v >>= 1;
402
403  if (! readPlane(pPicYuv->getCbAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
404    return false;
405  scalePlane(pPicYuv->getCbAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
406
407  if (! readPlane(pPicYuv->getCrAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
408    return false;
409  scalePlane(pPicYuv->getCrAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
410
411  return true;
412}
413
414/**
415 * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is
416 * assumed to be at TVideoIO::m_fileBitdepth depth.
417 *
418 * @param pPicYuv     input picture YUV buffer class pointer
419 * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
420 * @return true for success, false in case of error
421 */
422Bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int confLeft, Int confRight, Int confTop, Int confBottom )
423{
424  // compute actual YUV frame size excluding padding size
425  Int   iStride = pPicYuv->getStride();
426  UInt  width  = pPicYuv->getWidth()  - confLeft - confRight;
427  UInt  height = pPicYuv->getHeight() - confTop  - confBottom;
428  Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
429  TComPicYuv *dstPicYuv = NULL;
430  Bool retval = true;
431
432  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
433  {
434    dstPicYuv = new TComPicYuv;
435    dstPicYuv->create( pPicYuv->getWidth(), pPicYuv->getHeight(), 1, 1, 0 );
436    pPicYuv->copyToPic(dstPicYuv);
437
438    Pel minvalY = 0;
439    Pel minvalC = 0;
440    Pel maxvalY = (1 << m_fileBitDepthY) - 1;
441    Pel maxvalC = (1 << m_fileBitDepthC) - 1;
442#if CLIP_TO_709_RANGE
443    if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)
444    {
445      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
446      minvalY = 1 << (m_fileBitDepthY - 8);
447      maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;
448    }
449    if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)
450    {
451      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
452      minvalC = 1 << (m_fileBitDepthC - 8);
453      maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;
454    }
455#endif
456    scalePlane(dstPicYuv->getLumaAddr(), dstPicYuv->getStride(), dstPicYuv->getWidth(), dstPicYuv->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
457    scalePlane(dstPicYuv->getCbAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
458    scalePlane(dstPicYuv->getCrAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
459  }
460  else
461  {
462    dstPicYuv = pPicYuv;
463  }
464  // location of upper left pel in a plane
465  Int planeOffset = confLeft + confTop * iStride;
466 
467  if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr() + planeOffset, is16bit, iStride, width, height))
468  {
469    retval=false; 
470    goto exit;
471  }
472
473  width >>= 1;
474  height >>= 1;
475  iStride >>= 1;
476  confLeft >>= 1;
477  confRight >>= 1;
478  confTop >>= 1;
479  confBottom >>= 1;
480
481  planeOffset = confLeft + confTop * iStride;
482
483  if (! writePlane(m_cHandle, dstPicYuv->getCbAddr() + planeOffset, is16bit, iStride, width, height))
484  {
485    retval=false; 
486    goto exit;
487  }
488  if (! writePlane(m_cHandle, dstPicYuv->getCrAddr() + planeOffset, is16bit, iStride, width, height))
489  {
490    retval=false; 
491    goto exit;
492  }
493 
494exit:
495  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
496  {
497    dstPicYuv->destroy();
498    delete dstPicYuv;
499  } 
500  return retval;
501}
502
Note: See TracBrowser for help on using the repository browser.