source: 3DVCSoftware/branches/0.3-nokia/source/Lib/TLibVideoIO/TVideoIOYuv.cpp @ 122

Last change on this file since 122 was 5, checked in by hhi, 13 years ago

Clean version with cfg-files

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