source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibVideoIO/TVideoIOYuv.cpp @ 1236

Last change on this file since 1236 was 1077, checked in by seregin, 10 years ago

update the older Visual Studio project files and some fixes to avoid implicit cast warnings, patch was provided by Karsten Sühring <karsten.suehring@…>

  • Property svn:eol-style set to native
File size: 32.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-2014, 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#include <memory.h>
45
46#include "TLibCommon/TComRom.h"
47#include "TVideoIOYuv.h"
48
49using namespace std;
50
51// ====================================================================================================================
52// Local Functions
53// ====================================================================================================================
54
55/**
56 * Scale all pixels in img depending upon sign of shiftbits by a factor of
57 * 2<sup>shiftbits</sup>.
58 *
59 * @param img        pointer to image to be transformed
60 * @param stride  distance between vertically adjacent pixels of img.
61 * @param width   width of active area in img.
62 * @param height  height of active area in img.
63 * @param shiftbits if zero, no operation performed
64 *                  if > 0, multiply by 2<sup>shiftbits</sup>, see scalePlane()
65 *                  if < 0, divide and round by 2<sup>shiftbits</sup> and clip,
66 *                          see invScalePlane().
67 * @param minval  minimum clipping value when dividing.
68 * @param maxval  maximum clipping value when dividing.
69 */
70static Void scalePlane(Pel* img, const UInt stride, const UInt width, const UInt height, Int shiftbits, Pel minval, Pel maxval)
71{
72  if (shiftbits > 0)
73  {
74    for (UInt y = 0; y < height; y++, img+=stride)
75      for (UInt x = 0; x < width; x++)
76        img[x] <<= shiftbits;
77  }
78  else if (shiftbits < 0)
79  {
80    shiftbits=-shiftbits;
81
82    Pel rounding = 1 << (shiftbits-1);
83    for (UInt y = 0; y < height; y++, img+=stride)
84      for (UInt x = 0; x < width; x++)
85        img[x] = Clip3(minval, maxval, Pel((img[x] + rounding) >> shiftbits));
86  }
87}
88
89
90// ====================================================================================================================
91// Public member functions
92// ====================================================================================================================
93
94/**
95 * Open file for reading/writing Y'CbCr frames.
96 *
97 * Frames read/written have bitdepth fileBitDepth, and are automatically
98 * formatted as 8 or 16 bit word values (see TVideoIOYuv::write()).
99 *
100 * Image data read or written is converted to/from internalBitDepth
101 * (See scalePlane(), TVideoIOYuv::read() and TVideoIOYuv::write() for
102 * further details).
103 *
104 * \param pchFile          file name string
105 * \param bWriteMode       file open mode: true=read, false=write
106 * \param fileBitDepth     bit-depth array of input/output file data.
107 * \param internalBitDepth bit-depth array to scale image data to/from when reading/writing.
108 */
109Void TVideoIOYuv::open( Char* pchFile, Bool bWriteMode, const Int fileBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int internalBitDepth[MAX_NUM_CHANNEL_TYPE] )
110{
111  //NOTE: files cannot have bit depth greater than 16
112  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
113  {
114    m_fileBitdepth       [ch] = std::min<UInt>(fileBitDepth[ch], 16);
115    m_MSBExtendedBitDepth[ch] = MSBExtendedBitDepth[ch];
116    m_bitdepthShift      [ch] = internalBitDepth[ch] - m_MSBExtendedBitDepth[ch];
117
118    if (m_fileBitdepth[ch] > 16)
119    {
120      if (bWriteMode)
121      {
122        std::cerr << "\nWARNING: Cannot write a yuv file of bit depth greater than 16 - output will be right-shifted down to 16-bit precision\n" << std::endl;
123      }
124      else
125      {
126        std::cerr << "\nERROR: Cannot read a yuv file of bit depth greater than 16\n" << std::endl;
127        exit(0);
128      }
129    }
130  }
131
132  if ( bWriteMode )
133  {
134    m_cHandle.open( pchFile, ios::binary | ios::out );
135
136    if( m_cHandle.fail() )
137    {
138      printf("\nfailed to write reconstructed YUV file\n");
139      exit(0);
140    }
141  }
142  else
143  {
144    m_cHandle.open( pchFile, ios::binary | ios::in );
145
146    if( m_cHandle.fail() )
147    {
148      printf("\nfailed to open Input YUV file\n");
149      exit(0);
150    }
151  }
152
153  return;
154}
155
156Void TVideoIOYuv::close()
157{
158  m_cHandle.close();
159}
160
161Bool TVideoIOYuv::isEof()
162{
163  return m_cHandle.eof();
164}
165
166Bool TVideoIOYuv::isFail()
167{
168  return m_cHandle.fail();
169}
170
171/**
172 * Skip numFrames in input.
173 *
174 * This function correctly handles cases where the input file is not
175 * seekable, by consuming bytes.
176 */
177Void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format)
178{
179  if (!numFrames)
180    return;
181
182  //------------------
183  //set the frame size according to the chroma format
184  streamoff frameSize = 0;
185  UInt wordsize=1; // default to 8-bit, unless a channel with more than 8-bits is detected.
186  for (UInt component = 0; component < getNumberValidComponents(format); component++)
187  {
188    ComponentID compID=ComponentID(component);
189    frameSize += (width >> getComponentScaleX(compID, format)) * (height >> getComponentScaleY(compID, format));
190    if (m_fileBitdepth[toChannelType(compID)] > 8) wordsize=2;
191  }
192  frameSize *= wordsize;
193  //------------------
194
195  const streamoff offset = frameSize * numFrames;
196
197  /* attempt to seek */
198  if (!!m_cHandle.seekg(offset, ios::cur))
199    return; /* success */
200  m_cHandle.clear();
201
202  /* fall back to consuming the input */
203  Char buf[512];
204  const streamoff offset_mod_bufsize = offset % sizeof(buf);
205  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
206  {
207    m_cHandle.read(buf, sizeof(buf));
208  }
209  m_cHandle.read(buf, offset_mod_bufsize);
210}
211
212/**
213 * Read width*height pixels from fd into dst, optionally
214 * padding the left and right edges by edge-extension.  Input may be
215 * either 8bit or 16bit little-endian lsb-aligned words.
216 *
217 * @param dst     destination image
218 * @param fd      input file stream
219 * @param is16bit true if input file carries > 8bit data, false otherwise.
220 * @param stride  distance between vertically adjacent pixels of dst.
221 * @param width   width of active area in dst.
222 * @param height  height of active area in dst.
223 * @param pad_x   length of horizontal padding.
224 * @param pad_y   length of vertical padding.
225 * @return true for success, false in case of error
226 */
227static Bool readPlane(Pel* dst,
228                      istream& fd,
229                      Bool is16bit,
230                      UInt stride444,
231                      UInt width444,
232                      UInt height444,
233                      UInt pad_x444,
234                      UInt pad_y444,
235                      const ComponentID compID,
236                      const ChromaFormat destFormat,
237                      const ChromaFormat fileFormat,
238                      const UInt fileBitDepth)
239{
240  const UInt csx_file =getComponentScaleX(compID, fileFormat);
241  const UInt csy_file =getComponentScaleY(compID, fileFormat);
242  const UInt csx_dest =getComponentScaleX(compID, destFormat);
243  const UInt csy_dest =getComponentScaleY(compID, destFormat);
244
245  const UInt width_dest       = width444 >>csx_dest;
246  const UInt height_dest      = height444>>csy_dest;
247  const UInt pad_x_dest       = pad_x444>>csx_dest;
248  const UInt pad_y_dest       = pad_y444>>csy_dest;
249  const UInt stride_dest      = stride444>>csx_dest;
250
251  const UInt full_width_dest  = width_dest+pad_x_dest;
252  const UInt full_height_dest = height_dest+pad_y_dest;
253
254  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
255
256  UChar  *buf   = new UChar[stride_file];
257
258  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || destFormat==CHROMA_400))
259  {
260    if (destFormat!=CHROMA_400)
261    {
262      // set chrominance data to mid-range: (1<<(fileBitDepth-1))
263      const Pel value=Pel(1<<(fileBitDepth-1));
264      for (UInt y = 0; y < full_height_dest; y++, dst+=stride_dest)
265        for (UInt x = 0; x < full_width_dest; x++)
266          dst[x] = value;
267    }
268
269    if (fileFormat!=CHROMA_400)
270    {
271      const UInt height_file      = height444>>csy_file;
272      fd.seekg(height_file*stride_file, ios::cur);
273      if (fd.eof() || fd.fail() )
274      {
275        delete[] buf;
276        return false;
277      }
278    }
279  }
280  else
281  {
282    const UInt mask_y_file=(1<<csy_file)-1;
283    const UInt mask_y_dest=(1<<csy_dest)-1;
284    for(UInt y444=0; y444<height444; y444++)
285    {
286      if ((y444&mask_y_file)==0)
287      {
288        // read a new line
289        fd.read(reinterpret_cast<Char*>(buf), stride_file);
290        if (fd.eof() || fd.fail() )
291        {
292          delete[] buf;
293          return false;
294        }
295      }
296
297      if ((y444&mask_y_dest)==0)
298      {
299        // process current destination line
300        if (csx_file < csx_dest)
301        {
302          // eg file is 444, dest is 422.
303          const UInt sx=csx_dest-csx_file;
304          if (!is16bit)
305          {
306            for (UInt x = 0; x < width_dest; x++)
307              dst[x] = buf[x<<sx];
308          }
309          else
310          {
311            for (UInt x = 0; x < width_dest; x++)
312            {
313              dst[x] = Pel(buf[(x<<sx)*2+0]) | (Pel(buf[(x<<sx)*2+1])<<8);
314            }
315          }
316        }
317        else
318        {
319          // eg file is 422, dest is 444.
320          const UInt sx=csx_file-csx_dest;
321          if (!is16bit)
322          {
323            for (UInt x = 0; x < width_dest; x++)
324              dst[x] = buf[x>>sx];
325          }
326          else
327          {
328            for (UInt x = 0; x < width_dest; x++)
329              dst[x] = Pel(buf[(x>>sx)*2+0]) | (Pel(buf[(x>>sx)*2+1])<<8);
330          }
331        }
332
333        // process right hand side padding
334        const Pel val=dst[width_dest-1];
335        for (UInt x = width_dest; x < full_width_dest; x++)
336          dst[x] = val;
337
338        dst += stride_dest;
339      }
340    }
341
342    // process lower padding
343    for (UInt y = height_dest; y < full_height_dest; y++, dst+=stride_dest)
344      for (UInt x = 0; x < full_width_dest; x++)
345        dst[x] = (dst - stride_dest)[x];
346  }
347  delete[] buf;
348  return true;
349}
350
351/**
352 * Write width*height pixels info fd from src.
353 *
354 * @param fd      output file stream
355 * @param src     source image
356 * @param is16bit true if input file carries > 8bit data, false otherwise.
357 * @param stride  distance between vertically adjacent pixels of src.
358 * @param width   width of active area in src.
359 * @param height  height of active area in src.
360 * @return true for success, false in case of error
361 */
362static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
363                       UInt stride444,
364                       UInt width444, UInt height444,
365                       const ComponentID compID,
366                       const ChromaFormat srcFormat,
367                       const ChromaFormat fileFormat,
368                       const UInt fileBitDepth)
369{
370  const UInt csx_file =getComponentScaleX(compID, fileFormat);
371  const UInt csy_file =getComponentScaleY(compID, fileFormat);
372  const UInt csx_src  =getComponentScaleX(compID, srcFormat);
373  const UInt csy_src  =getComponentScaleY(compID, srcFormat);
374
375  const UInt stride_src      = stride444>>csx_src;
376
377  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
378  const UInt width_file       = width444 >>csx_file;
379  const UInt height_file      = height444>>csy_file;
380
381  UChar  *buf   = new UChar[stride_file];
382
383  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
384  {
385    if (fileFormat!=CHROMA_400)
386    {
387      const UInt value=1<<(fileBitDepth-1);
388
389      for(UInt y=0; y< height_file; y++)
390      {
391        if (!is16bit)
392        {
393          UChar val(value);
394          for (UInt x = 0; x < width_file; x++)
395            buf[x]=val;
396        }
397        else
398        {
399          UShort val(value);
400          for (UInt x = 0; x < width_file; x++)
401          {
402            buf[2*x+0]= (val>>0) & 0xff;
403            buf[2*x+1]= (val>>8) & 0xff;
404          }
405        }
406
407        fd.write(reinterpret_cast<Char*>(buf), stride_file);
408        if (fd.eof() || fd.fail() )
409        {
410          delete[] buf;
411          return false;
412        }
413      }
414    }
415  }
416  else
417  {
418    const UInt mask_y_file=(1<<csy_file)-1;
419    const UInt mask_y_src =(1<<csy_src )-1;
420    for(UInt y444=0; y444<height444; y444++)
421    {
422      if ((y444&mask_y_file)==0)
423      {
424        // write a new line
425        if (csx_file < csx_src)
426        {
427          // eg file is 444, source is 422.
428          const UInt sx=csx_src-csx_file;
429          if (!is16bit)
430          {
431            for (UInt x = 0; x < width_file; x++)
432            {
433              buf[x] = (UChar)(src[x>>sx]);
434            }
435          }
436          else
437          {
438            for (UInt x = 0; x < width_file; x++)
439            {
440              buf[2*] = (src[x>>sx]>>0) & 0xff;
441              buf[2*x+1] = (src[x>>sx]>>8) & 0xff;
442            }
443          }
444        }
445        else
446        {
447          // eg file is 422, src is 444.
448          const UInt sx=csx_file-csx_src;
449          if (!is16bit)
450          {
451            for (UInt x = 0; x < width_file; x++)
452            {
453              buf[x] = (UChar)(src[x<<sx]);
454            }
455          }
456          else
457          {
458            for (UInt x = 0; x < width_file; x++)
459            {
460              buf[2*] = (src[x<<sx]>>0) & 0xff;
461              buf[2*x+1] = (src[x<<sx]>>8) & 0xff;
462            }
463          }
464        }
465
466        fd.write(reinterpret_cast<Char*>(buf), stride_file);
467        if (fd.eof() || fd.fail() )
468        {
469          delete[] buf;
470          return false;
471        }
472      }
473
474      if ((y444&mask_y_src)==0)
475      {
476        src += stride_src;
477      }
478
479    }
480  }
481  delete[] buf;
482  return true;
483}
484
485static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit,
486                       UInt stride444,
487                       UInt width444, UInt height444,
488                       const ComponentID compID,
489                       const ChromaFormat srcFormat,
490                       const ChromaFormat fileFormat,
491                       const UInt fileBitDepth, const Bool isTff)
492{
493  const UInt csx_file =getComponentScaleX(compID, fileFormat);
494  const UInt csy_file =getComponentScaleY(compID, fileFormat);
495  const UInt csx_src  =getComponentScaleX(compID, srcFormat);
496  const UInt csy_src  =getComponentScaleY(compID, srcFormat);
497
498  const UInt stride_src      = stride444>>csx_src;
499
500  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
501  const UInt width_file       = width444 >>csx_file;
502  const UInt height_file      = height444>>csy_file;
503
504  UChar  *buf   = new UChar[stride_file * 2];
505
506  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
507  {
508    if (fileFormat!=CHROMA_400)
509    {
510      const UInt value=1<<(fileBitDepth-1);
511
512      for(UInt y=0; y< height_file; y++)
513      {
514        for (UInt field = 0; field < 2; field++)
515        {
516          UChar *fieldBuffer = buf + (field * stride_file);
517
518          if (!is16bit)
519          {
520            UChar val(value);
521            for (UInt x = 0; x < width_file; x++)
522              fieldBuffer[x]=val;
523          }
524          else
525          {
526            UShort val(value);
527            for (UInt x = 0; x < width_file; x++)
528            {
529              fieldBuffer[2*x+0]= (val>>0) & 0xff;
530              fieldBuffer[2*x+1]= (val>>8) & 0xff;
531            }
532          }
533        }
534
535        fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
536        if (fd.eof() || fd.fail() )
537        {
538          delete[] buf;
539          return false;
540        }
541      }
542    }
543  }
544  else
545  {
546    const UInt mask_y_file=(1<<csy_file)-1;
547    const UInt mask_y_src =(1<<csy_src )-1;
548    for(UInt y444=0; y444<height444; y444++)
549    {
550      if ((y444&mask_y_file)==0)
551      {
552        for (UInt field = 0; field < 2; field++)
553        {
554          UChar *fieldBuffer = buf + (field * stride_file);
555          Pel   *src         = (((field == 0) && isTff) || ((field == 1) && (!isTff))) ? top : bottom;
556
557          // write a new line
558          if (csx_file < csx_src)
559          {
560            // eg file is 444, source is 422.
561            const UInt sx=csx_src-csx_file;
562            if (!is16bit)
563            {
564              for (UInt x = 0; x < width_file; x++)
565              {
566                fieldBuffer[x] = (UChar)(src[x>>sx]);
567              }
568            }
569            else
570            {
571              for (UInt x = 0; x < width_file; x++)
572              {
573                fieldBuffer[2*] = (src[x>>sx]>>0) & 0xff;
574                fieldBuffer[2*x+1] = (src[x>>sx]>>8) & 0xff;
575              }
576            }
577          }
578          else
579          {
580            // eg file is 422, src is 444.
581            const UInt sx=csx_file-csx_src;
582            if (!is16bit)
583            {
584              for (UInt x = 0; x < width_file; x++)
585              {
586                fieldBuffer[x] = (UChar)(src[x<<sx]);
587              }
588            }
589            else
590            {
591              for (UInt x = 0; x < width_file; x++)
592              {
593                fieldBuffer[2*] = (src[x<<sx]>>0) & 0xff;
594                fieldBuffer[2*x+1] = (src[x<<sx]>>8) & 0xff;
595              }
596            }
597          }
598        }
599
600        fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
601        if (fd.eof() || fd.fail() )
602        {
603          delete[] buf;
604          return false;
605        }
606      }
607
608      if ((y444&mask_y_src)==0)
609      {
610        top    += stride_src;
611        bottom += stride_src;
612      }
613
614    }
615  }
616  delete[] buf;
617  return true;
618}
619
620/**
621 * Read one Y'CbCr frame, performing any required input scaling to change
622 * from the bitdepth of the input file to the internal bit-depth.
623 *
624 * If a bit-depth reduction is required, and internalBitdepth >= 8, then
625 * the input file is assumed to be ITU-R BT.601/709 compliant, and the
626 * resulting data is clipped to the appropriate legal range, as if the
627 * file had been provided at the lower-bitdepth compliant to Rec601/709.
628 *
629 * @param pPicYuv      input picture YUV buffer class pointer
630 * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
631 * @return true for success, false in case of error
632 */
633Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format )
634{
635  // check end-of-file
636  if ( isEof() ) return false;
637  TComPicYuv *pPicYuv=pPicYuvTrueOrg;
638  if (format>=NUM_CHROMA_FORMAT) format=pPicYuv->getChromaFormat();
639
640  Bool is16bit = false;
641
642  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
643  {
644    if (m_fileBitdepth[ch] > 8) is16bit=true;
645  }
646
647  const UInt stride444      = pPicYuv->getStride(COMPONENT_Y);
648
649  // compute actual YUV width & height excluding padding size
650  const UInt pad_h444       = aiPad[0];
651  const UInt pad_v444       = aiPad[1];
652
653  const UInt width_full444  = pPicYuv->getWidth(COMPONENT_Y);
654  const UInt height_full444 = pPicYuv->getHeight(COMPONENT_Y);
655
656  const UInt width444       = width_full444 - pad_h444;
657  const UInt height444      = height_full444 - pad_v444;
658
659  for(UInt comp=0; comp<MAX_NUM_COMPONENT; comp++)
660  {
661    const ComponentID compID = ComponentID(comp);
662    const ChannelType chType=toChannelType(compID);
663
664    const Int desired_bitdepth = m_MSBExtendedBitDepth[chType] + m_bitdepthShift[chType];
665
666#if !CLIP_TO_709_RANGE
667    const Pel minval = 0;
668    const Pel maxval = (1 << desired_bitdepth) - 1;
669#else
670    const Bool b709Compliance=(m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
671    const Pel minval = b709Compliance? ((   1 << (desired_bitdepth - 8))   ) : 0;
672    const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
673#endif
674
675    if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType]))
676    {
677      return false;
678    }
679
680    if (compID < pPicYuv->getNumberValidComponents() )
681    {
682      const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat());
683      const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat());
684      scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval);
685    }
686  }
687
688  Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
689  for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
690  {
691    internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
692  }
693  ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, internalBitDepth, true);
694
695  return true;
696}
697
698/**
699 * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is
700 * assumed to be at TVideoIO::m_fileBitdepth depth.
701 *
702 * @param pPicYuv     input picture YUV buffer class pointer
703 * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
704 * @return true for success, false in case of error
705 */
706Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format )
707{
708  TComPicYuv cPicYuvCSCd;
709  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
710  {
711    cPicYuvCSCd.create(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
712    Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
713    for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
714    {
715      internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
716    }
717    ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, internalBitDepth, false);
718  }
719  TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd;
720
721  // compute actual YUV frame size excluding padding size
722  const Int   iStride444 = pPicYuv->getStride(COMPONENT_Y);
723  const UInt width444  = pPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight;
724  const UInt height444 = pPicYuv->getHeight(COMPONENT_Y) -  confTop  - confBottom;
725  Bool is16bit = false;
726  Bool nonZeroBitDepthShift=false;
727
728  if ((width444 == 0) || (height444 == 0))
729  {
730    printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
731  }
732
733  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
734  {
735    if (m_fileBitdepth[ch] > 8) is16bit=true;
736    if (m_bitdepthShift[ch] != 0) nonZeroBitDepthShift=true;
737  }
738
739  TComPicYuv *dstPicYuv = NULL;
740  Bool retval = true;
741  if (format>=NUM_CHROMA_FORMAT) format=pPicYuv->getChromaFormat();
742
743  if (nonZeroBitDepthShift)
744  {
745    dstPicYuv = new TComPicYuv;
746    dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), 1, 1, 0 );
747    pPicYuv->copyToPic(dstPicYuv);
748
749    for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
750    {
751      const ComponentID compID=ComponentID(comp);
752      const ChannelType ch=toChannelType(compID);
753#if !CLIP_TO_709_RANGE
754      const Pel minval = 0;
755      const Pel maxval = (1 << m_MSBExtendedBitDepth[ch]) - 1;
756#else
757      const Bool b709Compliance=(-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
758      const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
759      const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
760#endif
761
762      scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
763    }
764  }
765  else
766  {
767    dstPicYuv = pPicYuv;
768  }
769
770  for(UInt comp=0; retval && comp<dstPicYuv->getNumberValidComponents(); comp++)
771  {
772    const ComponentID compID = ComponentID(comp);
773    const ChannelType ch=toChannelType(compID);
774    const UInt csx = pPicYuv->getComponentScaleX(compID);
775    const UInt csy = pPicYuv->getComponentScaleY(compID);
776    const Int planeOffset =  (confLeft>>csx) + (confTop>>csy) * pPicYuv->getStride(compID);
777    if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, iStride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch]))
778    {
779      retval=false;
780    }
781  }
782
783  if (nonZeroBitDepthShift)
784  {
785    dstPicYuv->destroy();
786    delete dstPicYuv;
787  }
788
789  cPicYuvCSCd.destroy();
790
791  return retval;
792}
793
794Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUserTop, TComPicYuv* pPicYuvUserBottom, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool isTff )
795{
796
797  TComPicYuv cPicYuvTopCSCd;
798  TComPicYuv cPicYuvBottomCSCd;
799  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
800  {
801    cPicYuvTopCSCd   .create(pPicYuvUserTop   ->getWidth(COMPONENT_Y), pPicYuvUserTop   ->getHeight(COMPONENT_Y), pPicYuvUserTop   ->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
802    cPicYuvBottomCSCd.create(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
803    Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
804    for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
805    {
806      internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
807    }
808    ColourSpaceConvert(*pPicYuvUserTop,    cPicYuvTopCSCd,    ipCSC, internalBitDepth, false);
809    ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, internalBitDepth, false);
810  }
811  TComPicYuv *pPicYuvTop    = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop    : &cPicYuvTopCSCd;
812  TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd;
813
814  Bool is16bit = false;
815  Bool nonZeroBitDepthShift=false;
816
817  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
818  {
819    if (m_fileBitdepth[ch] > 8) is16bit=true;
820    if (m_bitdepthShift[ch] != 0) nonZeroBitDepthShift=true;
821  }
822
823  TComPicYuv *dstPicYuvTop    = NULL;
824  TComPicYuv *dstPicYuvBottom = NULL;
825
826  for (UInt field = 0; field < 2; field++)
827  {
828    TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom;
829
830    if (format>=NUM_CHROMA_FORMAT) format=pPicYuv->getChromaFormat();
831
832    TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom;
833
834    if (nonZeroBitDepthShift)
835    {
836      dstPicYuv = new TComPicYuv;
837      dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), 1, 1, 0 );
838      pPicYuv->copyToPic(dstPicYuv);
839
840      for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
841      {
842        const ComponentID compID=ComponentID(comp);
843        const ChannelType ch=toChannelType(compID);
844#if !CLIP_TO_709_RANGE
845        const Pel minval = 0;
846        const Pel maxval = (1 << m_MSBExtendedBitDepth[ch]) - 1;
847#else
848        const Bool b709Compliance=(-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
849        const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
850        const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
851#endif
852
853        scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
854      }
855    }
856    else
857    {
858      dstPicYuv = pPicYuv;
859    }
860  }
861
862  Bool retval = true;
863
864  assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents());
865  assert(dstPicYuvTop->getChromaFormat()          == dstPicYuvBottom->getChromaFormat()         );
866  assert(dstPicYuvTop->getWidth(COMPONENT_Y)      == dstPicYuvBottom->getWidth(COMPONENT_Y)    );
867  assert(dstPicYuvTop->getHeight(COMPONENT_Y)     == dstPicYuvBottom->getHeight(COMPONENT_Y)    );
868  assert(dstPicYuvTop->getStride(COMPONENT_Y)     == dstPicYuvBottom->getStride(COMPONENT_Y)    );
869
870  for(UInt comp=0; retval && comp<dstPicYuvTop->getNumberValidComponents(); comp++)
871  {
872    const ComponentID compID = ComponentID(comp);
873    const ChannelType ch=toChannelType(compID);
874
875    assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID));
876    assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID));
877    assert(dstPicYuvTop->getStride         (compID) == dstPicYuvBottom->getStride         (compID));
878
879    const UInt width444   = dstPicYuvTop->getWidth(COMPONENT_Y)  - (confLeft + confRight);
880    const UInt height444  = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom);
881
882    if ((width444 == 0) || (height444 == 0))
883    {
884      printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
885    }
886
887    const UInt csx = dstPicYuvTop->getComponentScaleX(compID);
888    const UInt csy = dstPicYuvTop->getComponentScaleY(compID);
889    const Int planeOffset  = (confLeft>>csx) + ( confTop>>csy) * dstPicYuvTop->getStride(compID); //offset is for entire frame - round up for top field and down for bottom field
890
891    if (! writeField(m_cHandle,
892                     (dstPicYuvTop   ->getAddr(compID) + planeOffset),
893                     (dstPicYuvBottom->getAddr(compID) + planeOffset),
894                     is16bit,
895                     dstPicYuvTop->getStride(COMPONENT_Y),
896                     width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff))
897    {
898      retval=false;
899    }
900  }
901
902  if (nonZeroBitDepthShift)
903  {
904    dstPicYuvTop->destroy();
905    dstPicYuvBottom->destroy();
906    delete dstPicYuvTop;
907    delete dstPicYuvBottom;
908  }
909
910  cPicYuvTopCSCd.destroy();
911  cPicYuvBottomCSCd.destroy();
912
913  return retval;
914}
915
916static Void
917copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
918{
919  const UInt width=src.getWidth(srcPlane);
920  const UInt height=src.getHeight(srcPlane);
921  assert(dest.getWidth(destPlane) == width);
922  assert(dest.getHeight(destPlane) == height);
923  const Pel *pSrc=src.getAddr(srcPlane);
924  Pel *pDest=dest.getAddr(destPlane);
925  const UInt strideSrc=src.getStride(srcPlane);
926  const UInt strideDest=dest.getStride(destPlane);
927  for(UInt y=0; y<height; y++, pSrc+=strideSrc, pDest+=strideDest)
928  {
929    memcpy(pDest, pSrc, width*sizeof(Pel));
930  }
931}
932
933// static member
934Void TVideoIOYuv::ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, const Int bitDepths[MAX_NUM_CHANNEL_TYPE], Bool bIsForwards)
935{
936  const ChromaFormat  format=src.getChromaFormat();
937  const UInt          numValidComp=src.getNumberValidComponents();
938
939  switch (conversion)
940  {
941    case IPCOLOURSPACE_YCbCrtoYYY:
942      if (format!=CHROMA_444)
943      {
944        // only 444 is handled.
945        assert(format==CHROMA_444);
946        exit(1);
947      }
948
949      {
950        for(UInt comp=0; comp<numValidComp; comp++)
951          copyPlane(src, ComponentID(bIsForwards?0:comp), dest, ComponentID(comp));
952      }
953      break;
954    case IPCOLOURSPACE_YCbCrtoYCrCb:
955      {
956        for(UInt comp=0; comp<numValidComp; comp++)
957          copyPlane(src, ComponentID(comp), dest, ComponentID((numValidComp-comp)%numValidComp));
958      }
959      break;
960
961    case IPCOLOURSPACE_RGBtoGBR:
962      {
963        if (format!=CHROMA_444)
964        {
965          // only 444 is handled.
966          assert(format==CHROMA_444);
967          exit(1);
968        }
969
970        // channel re-mapping
971        for(UInt comp=0; comp<numValidComp; comp++)
972        {
973          const ComponentID compIDsrc=ComponentID((comp+1)%numValidComp);
974          const ComponentID compIDdst=ComponentID(comp);
975          copyPlane(src, bIsForwards?compIDsrc:compIDdst, dest, bIsForwards?compIDdst:compIDsrc);
976        }
977      }
978      break;
979
980    case IPCOLOURSPACE_UNCHANGED:
981    default:
982      {
983        for(UInt comp=0; comp<numValidComp; comp++)
984          copyPlane(src, ComponentID(comp), dest, ComponentID(comp));
985      }
986      break;
987  }
988}
Note: See TracBrowser for help on using the repository browser.