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

Last change on this file since 189 was 56, checked in by hschwarz, 12 years ago

updated trunk (move to HM6.1)

  • Property svn:eol-style set to native
File size: 15.4 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-2012, 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, unsigned int stride, unsigned int width, unsigned int height,
63                       unsigned int shiftbits, Pel minval, Pel maxval)
64{
65  Pel offset = 1 << (shiftbits-1);
66  for (unsigned int y = 0; y < height; y++)
67  {
68    for (unsigned int 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, unsigned int stride, unsigned int width, unsigned int height,
87                       unsigned int shiftbits)
88{
89  for (unsigned int y = 0; y < height; y++)
90  {
91    for (unsigned int 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, unsigned int stride, unsigned int width, unsigned int 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 fileBitDepth     bit-depth of input/output file data.
150 * \param internalBitDepth bit-depth to scale image data to/from when reading/writing.
151 */
152Void TVideoIOYuv::open( char* pchFile, Bool bWriteMode, unsigned int fileBitDepth, unsigned int internalBitDepth )
153{
154  m_bitdepthShift = internalBitDepth - fileBitDepth;
155  m_fileBitdepth = fileBitDepth;
156
157  if ( bWriteMode )
158  {
159    m_cHandle.open( pchFile, ios::binary | ios::out );
160   
161    if( m_cHandle.fail() )
162    {
163      printf("\nfailed to write reconstructed YUV file\n");
164      exit(0);
165    }
166  }
167  else
168  {
169    m_cHandle.open( pchFile, ios::binary | ios::in );
170   
171    if( m_cHandle.fail() )
172    {
173      printf("\nfailed to open Input YUV file\n");
174      exit(0);
175    }
176  }
177 
178  return;
179}
180
181Void TVideoIOYuv::close()
182{
183  m_cHandle.close();
184}
185
186Bool TVideoIOYuv::isEof()
187{
188  return m_cHandle.eof();
189}
190
191Bool TVideoIOYuv::isFail()
192{
193  return m_cHandle.fail();
194}
195
196/**
197 * Skip numFrames in input.
198 *
199 * This function correctly handles cases where the input file is not
200 * seekable, by consuming bytes.
201 */
202void TVideoIOYuv::skipFrames(unsigned int numFrames, unsigned int width, unsigned int height)
203{
204  if (!numFrames)
205    return;
206
207  const unsigned int wordsize = m_fileBitdepth > 8 ? 2 : 1;
208  const streamoff framesize = wordsize * width * height * 3 / 2;
209  const streamoff offset = framesize * numFrames;
210
211  /* attempt to seek */
212  if (!!m_cHandle.seekg(offset, ios::cur))
213    return; /* success */
214  m_cHandle.clear();
215
216  /* fall back to consuming the input */
217  char buf[512];
218  const unsigned offset_mod_bufsize = offset % sizeof(buf);
219  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
220  {
221    m_cHandle.read(buf, sizeof(buf));
222  }
223  m_cHandle.read(buf, offset_mod_bufsize);
224}
225
226/**
227 * Read width*height pixels from fd into dst, optionally
228 * padding the left and right edges by edge-extension.  Input may be
229 * either 8bit or 16bit little-endian lsb-aligned words.
230 *
231 * @param dst     destination image
232 * @param fd      input file stream
233 * @param is16bit true if input file carries > 8bit data, false otherwise.
234 * @param stride  distance between vertically adjacent pixels of dst.
235 * @param width   width of active area in dst.
236 * @param height  height of active area in dst.
237 * @param pad_x   length of horizontal padding.
238 * @param pad_y   length of vertical padding.
239 * @return true for success, false in case of error
240 */
241static bool readPlane(Pel* dst, istream& fd, bool is16bit,
242                      unsigned int stride,
243                      unsigned int width, unsigned int height,
244                      unsigned int pad_x, unsigned int pad_y)
245{
246  int read_len = width * (is16bit ? 2 : 1);
247  unsigned char *buf = new unsigned char[read_len];
248  for (int y = 0; y < height; y++)
249  {
250    fd.read(reinterpret_cast<char*>(buf), read_len);
251    if (fd.eof() || fd.fail() )
252    {
253      delete[] buf;
254      return false;
255    }
256
257    if (!is16bit)
258    {
259      for (int x = 0; x < width; x++)
260      {
261        dst[x] = buf[x];
262      }
263    }
264    else
265    {
266      for (int x = 0; x < width; x++)
267      {
268        dst[x] = (buf[2*x+1] << 8) | buf[2*x];
269      }
270    }
271
272    for (int x = width; x < width + pad_x; x++)
273    {
274      dst[x] = dst[width - 1];
275    }
276    dst += stride;
277  }
278  for (int y = height; y < height + pad_y; y++)
279  {
280    for (int x = 0; x < width + pad_x; x++)
281    {
282      dst[x] = (dst - stride)[x];
283    }
284    dst += stride;
285  }
286  delete[] buf;
287  return true;
288}
289
290/**
291 * Write width*height pixels info fd from src.
292 *
293 * @param fd      output file stream
294 * @param src     source image
295 * @param is16bit true if input file carries > 8bit data, false otherwise.
296 * @param stride  distance between vertically adjacent pixels of src.
297 * @param width   width of active area in src.
298 * @param height  height of active area in src.
299 * @return true for success, false in case of error
300 */
301static bool writePlane(ostream& fd, Pel* src, bool is16bit,
302                       unsigned int stride,
303                       unsigned int width, unsigned int height)
304{
305  int write_len = width * (is16bit ? 2 : 1);
306  unsigned char *buf = new unsigned char[write_len];
307  for (int y = 0; y < height; y++)
308  {
309    if (!is16bit) 
310    {
311      for (int x = 0; x < width; x++) 
312      {
313        buf[x] = (unsigned char) src[x];
314      }
315    }
316    else 
317    {
318      for (int x = 0; x < width; x++) 
319      {
320        buf[2*x] = src[x] & 0xff;
321        buf[2*x+1] = (src[x] >> 8) & 0xff;
322      }
323    }
324
325    fd.write(reinterpret_cast<char*>(buf), write_len);
326    if (fd.eof() || fd.fail() )
327    {
328      delete[] buf;
329      return false;
330    }
331    src += stride;
332  }
333  delete[] buf;
334  return true;
335}
336
337/**
338 * Read one Y'CbCr frame, performing any required input scaling to change
339 * from the bitdepth of the input file to the internal bit-depth.
340 *
341 * If a bit-depth reduction is required, and internalBitdepth >= 8, then
342 * the input file is assumed to be ITU-R BT.601/709 compliant, and the
343 * resulting data is clipped to the appropriate legal range, as if the
344 * file had been provided at the lower-bitdepth compliant to Rec601/709.
345 *
346 * @param pPicYuv      input picture YUV buffer class pointer
347 * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
348 * @return true for success, false in case of error
349 */
350bool TVideoIOYuv::read ( TComPicYuv*  pPicYuv, Int aiPad[2], Bool bRewind )
351{
352  // check end-of-file
353  if ( isEof() ) return false;
354 
355  Int   iStride = pPicYuv->getStride();
356 
357  // compute actual YUV width & height excluding padding size
358  unsigned int pad_h = aiPad[0];
359  unsigned int pad_v = aiPad[1];
360  unsigned int width_full = pPicYuv->getWidth();
361  unsigned int height_full = pPicYuv->getHeight();
362  unsigned int width  = width_full - pad_h;
363  unsigned int height = height_full - pad_v;
364  bool is16bit = m_fileBitdepth > 8;
365
366  int desired_bitdepth = m_fileBitdepth + m_bitdepthShift;
367  Pel minval = 0;
368  Pel maxval = (1 << desired_bitdepth) - 1;
369#if CLIP_TO_709_RANGE
370  if (m_bitdepthShift < 0 && desired_bitdepth >= 8)
371  {
372    /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
373    minval = 1 << (desired_bitdepth - 8);
374    maxval = (0xff << (desired_bitdepth - 8)) -1;
375  }
376#endif
377 
378  if (! readPlane(pPicYuv->getLumaAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
379    return false;
380  scalePlane(pPicYuv->getLumaAddr(), iStride, width_full, height_full, m_bitdepthShift, minval, maxval);
381
382  iStride >>= 1;
383  width_full >>= 1;
384  height_full >>= 1;
385  width >>= 1;
386  height >>= 1;
387  pad_h >>= 1;
388  pad_v >>= 1;
389
390  if (! readPlane(pPicYuv->getCbAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
391    return false;
392  scalePlane(pPicYuv->getCbAddr(), iStride, width_full, height_full, m_bitdepthShift, minval, maxval);
393
394  if (! readPlane(pPicYuv->getCrAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
395    return false;
396  scalePlane(pPicYuv->getCrAddr(), iStride, width_full, height_full, m_bitdepthShift, minval, maxval);
397
398  if( bRewind )
399  {
400    Int iFrameSize = ( is16bit ? 2 : 1 ) * 6 * width * height;
401    m_cHandle.seekg( -iFrameSize, std::ios_base::cur );
402  }
403
404  return true;
405}
406
407/**
408 * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is
409 * assumed to be at TVideoIO::m_fileBitdepth depth.
410 *
411 * @param pPicYuv     input picture YUV buffer class pointer
412 * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
413 * @return true for success, false in case of error
414 */
415#if PIC_CROPPING
416Bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int cropLeft, Int cropRight, Int cropTop, Int cropBottom )
417#else
418bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int aiPad[2] )
419#endif
420{
421  // compute actual YUV frame size excluding padding size
422  Int   iStride = pPicYuv->getStride();
423#if PIC_CROPPING
424  UInt  width  = pPicYuv->getWidth()  - cropLeft - cropRight;
425  UInt  height = pPicYuv->getHeight() - cropTop  - cropBottom;
426#else
427  unsigned int width  = pPicYuv->getWidth() - aiPad[0];
428  unsigned int height = pPicYuv->getHeight() - aiPad[1];
429#endif
430  bool is16bit = m_fileBitdepth > 8;
431  TComPicYuv *dstPicYuv = NULL;
432  bool retval = true;
433
434  if (m_bitdepthShift != 0)
435  {
436    dstPicYuv = new TComPicYuv;
437    dstPicYuv->create( pPicYuv->getWidth(), pPicYuv->getHeight(), 1, 1, 0 );
438    pPicYuv->copyToPic(dstPicYuv);
439
440    Pel minval = 0;
441    Pel maxval = (1 << m_fileBitdepth) - 1;
442#if CLIP_TO_709_RANGE
443    if (-m_bitdepthShift < 0 && m_fileBitdepth >= 8)
444    {
445      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
446      minval = 1 << (m_fileBitdepth - 8);
447      maxval = (0xff << (m_fileBitdepth - 8)) -1;
448    }
449#endif
450    scalePlane(dstPicYuv->getLumaAddr(), dstPicYuv->getStride(), dstPicYuv->getWidth(), dstPicYuv->getHeight(), -m_bitdepthShift, minval, maxval);
451    scalePlane(dstPicYuv->getCbAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitdepthShift, minval, maxval);
452    scalePlane(dstPicYuv->getCrAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitdepthShift, minval, maxval);
453  }
454  else
455  {
456    dstPicYuv = pPicYuv;
457  }
458#if PIC_CROPPING
459  // location of upper left pel in a plane
460  Int planeOffset = 0; //cropLeft + cropTop * iStride;
461 
462  if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr() + planeOffset, is16bit, iStride, width, height))
463#else
464  if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr(), is16bit, iStride, width, height))
465#endif
466  {
467    retval=false; 
468    goto exit;
469  }
470
471  width >>= 1;
472  height >>= 1;
473  iStride >>= 1;
474#if PIC_CROPPING
475  cropLeft >>= 1;
476  cropRight >>= 1;
477
478  planeOffset = 0; // cropLeft + cropTop * iStride;
479
480  if (! writePlane(m_cHandle, dstPicYuv->getCbAddr() + planeOffset, is16bit, iStride, width, height))
481#else
482  if (! writePlane(m_cHandle, dstPicYuv->getCbAddr(), is16bit, iStride, width, height))
483#endif
484  {
485    retval=false; 
486    goto exit;
487  }
488#if PIC_CROPPING
489  if (! writePlane(m_cHandle, dstPicYuv->getCrAddr() + planeOffset, is16bit, iStride, width, height))
490#else
491  if (! writePlane(m_cHandle, dstPicYuv->getCrAddr(), is16bit, iStride, width, height))
492#endif
493  {
494    retval=false; 
495    goto exit;
496  }
497 
498exit:
499  if (m_bitdepthShift != 0)
500  {
501    dstPicYuv->destroy();
502    delete dstPicYuv;
503  } 
504  return retval;
505}
506
Note: See TracBrowser for help on using the repository browser.