HEVC Test Model (HM)  HM-16.3
TVideoIOYuv.cpp
Go to the documentation of this file.
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-2015, 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 
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 
49 using namespace std;
50 
51 // ====================================================================================================================
52 // Local Functions
53 // ====================================================================================================================
54 
70 static 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  {
76  for (UInt x = 0; x < width; x++)
77  {
78  img[x] <<= shiftbits;
79  }
80  }
81  }
82  else if (shiftbits < 0)
83  {
84  shiftbits=-shiftbits;
85 
86  Pel rounding = 1 << (shiftbits-1);
87  for (UInt y = 0; y < height; y++, img+=stride)
88  {
89  for (UInt x = 0; x < width; x++)
90  {
91  img[x] = Clip3(minval, maxval, Pel((img[x] + rounding) >> shiftbits));
92  }
93  }
94  }
95 }
96 
97 
98 // ====================================================================================================================
99 // Public member functions
100 // ====================================================================================================================
101 
118 Void 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] )
119 {
120  //NOTE: files cannot have bit depth greater than 16
121  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
122  {
123  m_fileBitdepth [ch] = std::min<UInt>(fileBitDepth[ch], 16);
124  m_MSBExtendedBitDepth[ch] = MSBExtendedBitDepth[ch];
125  m_bitdepthShift [ch] = internalBitDepth[ch] - m_MSBExtendedBitDepth[ch];
126 
127  if (m_fileBitdepth[ch] > 16)
128  {
129  if (bWriteMode)
130  {
131  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;
132  }
133  else
134  {
135  std::cerr << "\nERROR: Cannot read a yuv file of bit depth greater than 16\n" << std::endl;
136  exit(0);
137  }
138  }
139  }
140 
141  if ( bWriteMode )
142  {
143  m_cHandle.open( pchFile, ios::binary | ios::out );
144 
145  if( m_cHandle.fail() )
146  {
147  printf("\nfailed to write reconstructed YUV file\n");
148  exit(0);
149  }
150  }
151  else
152  {
153  m_cHandle.open( pchFile, ios::binary | ios::in );
154 
155  if( m_cHandle.fail() )
156  {
157  printf("\nfailed to open Input YUV file\n");
158  exit(0);
159  }
160  }
161 
162  return;
163 }
164 
166 {
167  m_cHandle.close();
168 }
169 
171 {
172  return m_cHandle.eof();
173 }
174 
176 {
177  return m_cHandle.fail();
178 }
179 
186 Void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format)
187 {
188  if (!numFrames)
189  {
190  return;
191  }
192 
193  //------------------
194  //set the frame size according to the chroma format
195  streamoff frameSize = 0;
196  UInt wordsize=1; // default to 8-bit, unless a channel with more than 8-bits is detected.
197  for (UInt component = 0; component < getNumberValidComponents(format); component++)
198  {
199  ComponentID compID=ComponentID(component);
200  frameSize += (width >> getComponentScaleX(compID, format)) * (height >> getComponentScaleY(compID, format));
201  if (m_fileBitdepth[toChannelType(compID)] > 8)
202  {
203  wordsize=2;
204  }
205  }
206  frameSize *= wordsize;
207  //------------------
208 
209  const streamoff offset = frameSize * numFrames;
210 
211  /* attempt to seek */
212  if (!!m_cHandle.seekg(offset, ios::cur))
213  {
214  return; /* success */
215  }
216  m_cHandle.clear();
217 
218  /* fall back to consuming the input */
219  Char buf[512];
220  const UInt offset_mod_bufsize = offset % sizeof(buf);
221  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
222  {
223  m_cHandle.read(buf, sizeof(buf));
224  }
225  m_cHandle.read(buf, offset_mod_bufsize);
226 }
227 
247 static Bool readPlane(Pel* dst,
248  istream& fd,
249  Bool is16bit,
250  UInt stride444,
251  UInt width444,
252  UInt height444,
253  UInt pad_x444,
254  UInt pad_y444,
255  const ComponentID compID,
256  const ChromaFormat destFormat,
257  const ChromaFormat fileFormat,
258  const UInt fileBitDepth)
259 {
260  const UInt csx_file =getComponentScaleX(compID, fileFormat);
261  const UInt csy_file =getComponentScaleY(compID, fileFormat);
262  const UInt csx_dest =getComponentScaleX(compID, destFormat);
263  const UInt csy_dest =getComponentScaleY(compID, destFormat);
264 
265  const UInt width_dest = width444 >>csx_dest;
266  const UInt height_dest = height444>>csy_dest;
267  const UInt pad_x_dest = pad_x444>>csx_dest;
268  const UInt pad_y_dest = pad_y444>>csy_dest;
269  const UInt stride_dest = stride444>>csx_dest;
270 
271  const UInt full_width_dest = width_dest+pad_x_dest;
272  const UInt full_height_dest = height_dest+pad_y_dest;
273 
274  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
275 
276  UChar *buf = new UChar[stride_file];
277 
278  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || destFormat==CHROMA_400))
279  {
280  if (destFormat!=CHROMA_400)
281  {
282  // set chrominance data to mid-range: (1<<(fileBitDepth-1))
283  const Pel value=Pel(1<<(fileBitDepth-1));
284  for (UInt y = 0; y < full_height_dest; y++, dst+=stride_dest)
285  {
286  for (UInt x = 0; x < full_width_dest; x++)
287  {
288  dst[x] = value;
289  }
290  }
291  }
292 
293  if (fileFormat!=CHROMA_400)
294  {
295  const UInt height_file = height444>>csy_file;
296  fd.seekg(height_file*stride_file, ios::cur);
297  if (fd.eof() || fd.fail() )
298  {
299  delete[] buf;
300  return false;
301  }
302  }
303  }
304  else
305  {
306  const UInt mask_y_file=(1<<csy_file)-1;
307  const UInt mask_y_dest=(1<<csy_dest)-1;
308  for(UInt y444=0; y444<height444; y444++)
309  {
310  if ((y444&mask_y_file)==0)
311  {
312  // read a new line
313  fd.read(reinterpret_cast<Char*>(buf), stride_file);
314  if (fd.eof() || fd.fail() )
315  {
316  delete[] buf;
317  return false;
318  }
319  }
320 
321  if ((y444&mask_y_dest)==0)
322  {
323  // process current destination line
324  if (csx_file < csx_dest)
325  {
326  // eg file is 444, dest is 422.
327  const UInt sx=csx_dest-csx_file;
328  if (!is16bit)
329  {
330  for (UInt x = 0; x < width_dest; x++)
331  {
332  dst[x] = buf[x<<sx];
333  }
334  }
335  else
336  {
337  for (UInt x = 0; x < width_dest; x++)
338  {
339  dst[x] = Pel(buf[(x<<sx)*2+0]) | (Pel(buf[(x<<sx)*2+1])<<8);
340  }
341  }
342  }
343  else
344  {
345  // eg file is 422, dest is 444.
346  const UInt sx=csx_file-csx_dest;
347  if (!is16bit)
348  {
349  for (UInt x = 0; x < width_dest; x++)
350  {
351  dst[x] = buf[x>>sx];
352  }
353  }
354  else
355  {
356  for (UInt x = 0; x < width_dest; x++)
357  {
358  dst[x] = Pel(buf[(x>>sx)*2+0]) | (Pel(buf[(x>>sx)*2+1])<<8);
359  }
360  }
361  }
362 
363  // process right hand side padding
364  const Pel val=dst[width_dest-1];
365  for (UInt x = width_dest; x < full_width_dest; x++)
366  {
367  dst[x] = val;
368  }
369 
370  dst += stride_dest;
371  }
372  }
373 
374  // process lower padding
375  for (UInt y = height_dest; y < full_height_dest; y++, dst+=stride_dest)
376  {
377  for (UInt x = 0; x < full_width_dest; x++)
378  {
379  dst[x] = (dst - stride_dest)[x];
380  }
381  }
382  }
383  delete[] buf;
384  return true;
385 }
386 
402 static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
403  UInt stride444,
404  UInt width444, UInt height444,
405  const ComponentID compID,
406  const ChromaFormat srcFormat,
407  const ChromaFormat fileFormat,
408  const UInt fileBitDepth)
409 {
410  const UInt csx_file =getComponentScaleX(compID, fileFormat);
411  const UInt csy_file =getComponentScaleY(compID, fileFormat);
412  const UInt csx_src =getComponentScaleX(compID, srcFormat);
413  const UInt csy_src =getComponentScaleY(compID, srcFormat);
414 
415  const UInt stride_src = stride444>>csx_src;
416 
417  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
418  const UInt width_file = width444 >>csx_file;
419  const UInt height_file = height444>>csy_file;
420 
421  UChar *buf = new UChar[stride_file];
422 
423  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
424  {
425  if (fileFormat!=CHROMA_400)
426  {
427  const UInt value=1<<(fileBitDepth-1);
428 
429  for(UInt y=0; y< height_file; y++)
430  {
431  if (!is16bit)
432  {
433  UChar val(value);
434  for (UInt x = 0; x < width_file; x++)
435  {
436  buf[x]=val;
437  }
438  }
439  else
440  {
441  UShort val(value);
442  for (UInt x = 0; x < width_file; x++)
443  {
444  buf[2*x+0]= (val>>0) & 0xff;
445  buf[2*x+1]= (val>>8) & 0xff;
446  }
447  }
448 
449  fd.write(reinterpret_cast<Char*>(buf), stride_file);
450  if (fd.eof() || fd.fail() )
451  {
452  delete[] buf;
453  return false;
454  }
455  }
456  }
457  }
458  else
459  {
460  const UInt mask_y_file=(1<<csy_file)-1;
461  const UInt mask_y_src =(1<<csy_src )-1;
462  for(UInt y444=0; y444<height444; y444++)
463  {
464  if ((y444&mask_y_file)==0)
465  {
466  // write a new line
467  if (csx_file < csx_src)
468  {
469  // eg file is 444, source is 422.
470  const UInt sx=csx_src-csx_file;
471  if (!is16bit)
472  {
473  for (UInt x = 0; x < width_file; x++)
474  {
475  buf[x] = (UChar)(src[x>>sx]);
476  }
477  }
478  else
479  {
480  for (UInt x = 0; x < width_file; x++)
481  {
482  buf[2*x ] = (src[x>>sx]>>0) & 0xff;
483  buf[2*x+1] = (src[x>>sx]>>8) & 0xff;
484  }
485  }
486  }
487  else
488  {
489  // eg file is 422, src is 444.
490  const UInt sx=csx_file-csx_src;
491  if (!is16bit)
492  {
493  for (UInt x = 0; x < width_file; x++)
494  {
495  buf[x] = (UChar)(src[x<<sx]);
496  }
497  }
498  else
499  {
500  for (UInt x = 0; x < width_file; x++)
501  {
502  buf[2*x ] = (src[x<<sx]>>0) & 0xff;
503  buf[2*x+1] = (src[x<<sx]>>8) & 0xff;
504  }
505  }
506  }
507 
508  fd.write(reinterpret_cast<Char*>(buf), stride_file);
509  if (fd.eof() || fd.fail() )
510  {
511  delete[] buf;
512  return false;
513  }
514  }
515 
516  if ((y444&mask_y_src)==0)
517  {
518  src += stride_src;
519  }
520 
521  }
522  }
523  delete[] buf;
524  return true;
525 }
526 
527 static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit,
528  UInt stride444,
529  UInt width444, UInt height444,
530  const ComponentID compID,
531  const ChromaFormat srcFormat,
532  const ChromaFormat fileFormat,
533  const UInt fileBitDepth, const Bool isTff)
534 {
535  const UInt csx_file =getComponentScaleX(compID, fileFormat);
536  const UInt csy_file =getComponentScaleY(compID, fileFormat);
537  const UInt csx_src =getComponentScaleX(compID, srcFormat);
538  const UInt csy_src =getComponentScaleY(compID, srcFormat);
539 
540  const UInt stride_src = stride444>>csx_src;
541 
542  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
543  const UInt width_file = width444 >>csx_file;
544  const UInt height_file = height444>>csy_file;
545 
546  UChar *buf = new UChar[stride_file * 2];
547 
548  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
549  {
550  if (fileFormat!=CHROMA_400)
551  {
552  const UInt value=1<<(fileBitDepth-1);
553 
554  for(UInt y=0; y< height_file; y++)
555  {
556  for (UInt field = 0; field < 2; field++)
557  {
558  UChar *fieldBuffer = buf + (field * stride_file);
559 
560  if (!is16bit)
561  {
562  UChar val(value);
563  for (UInt x = 0; x < width_file; x++)
564  {
565  fieldBuffer[x]=val;
566  }
567  }
568  else
569  {
570  UShort val(value);
571  for (UInt x = 0; x < width_file; x++)
572  {
573  fieldBuffer[2*x+0]= (val>>0) & 0xff;
574  fieldBuffer[2*x+1]= (val>>8) & 0xff;
575  }
576  }
577  }
578 
579  fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
580  if (fd.eof() || fd.fail() )
581  {
582  delete[] buf;
583  return false;
584  }
585  }
586  }
587  }
588  else
589  {
590  const UInt mask_y_file=(1<<csy_file)-1;
591  const UInt mask_y_src =(1<<csy_src )-1;
592  for(UInt y444=0; y444<height444; y444++)
593  {
594  if ((y444&mask_y_file)==0)
595  {
596  for (UInt field = 0; field < 2; field++)
597  {
598  UChar *fieldBuffer = buf + (field * stride_file);
599  Pel *src = (((field == 0) && isTff) || ((field == 1) && (!isTff))) ? top : bottom;
600 
601  // write a new line
602  if (csx_file < csx_src)
603  {
604  // eg file is 444, source is 422.
605  const UInt sx=csx_src-csx_file;
606  if (!is16bit)
607  {
608  for (UInt x = 0; x < width_file; x++)
609  {
610  fieldBuffer[x] = (UChar)(src[x>>sx]);
611  }
612  }
613  else
614  {
615  for (UInt x = 0; x < width_file; x++)
616  {
617  fieldBuffer[2*x ] = (src[x>>sx]>>0) & 0xff;
618  fieldBuffer[2*x+1] = (src[x>>sx]>>8) & 0xff;
619  }
620  }
621  }
622  else
623  {
624  // eg file is 422, src is 444.
625  const UInt sx=csx_file-csx_src;
626  if (!is16bit)
627  {
628  for (UInt x = 0; x < width_file; x++)
629  {
630  fieldBuffer[x] = (UChar)(src[x<<sx]);
631  }
632  }
633  else
634  {
635  for (UInt x = 0; x < width_file; x++)
636  {
637  fieldBuffer[2*x ] = (src[x<<sx]>>0) & 0xff;
638  fieldBuffer[2*x+1] = (src[x<<sx]>>8) & 0xff;
639  }
640  }
641  }
642  }
643 
644  fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
645  if (fd.eof() || fd.fail() )
646  {
647  delete[] buf;
648  return false;
649  }
650  }
651 
652  if ((y444&mask_y_src)==0)
653  {
654  top += stride_src;
655  bottom += stride_src;
656  }
657 
658  }
659  }
660  delete[] buf;
661  return true;
662 }
663 
680 Bool TVideoIOYuv::read ( TComPicYuv* pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format )
681 {
682  // check end-of-file
683  if ( isEof() )
684  {
685  return false;
686  }
687  TComPicYuv *pPicYuv=pPicYuvTrueOrg;
688  if (format>=NUM_CHROMA_FORMAT)
689  {
690  format=pPicYuv->getChromaFormat();
691  }
692 
693  Bool is16bit = false;
694 
695  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
696  {
697  if (m_fileBitdepth[ch] > 8)
698  {
699  is16bit=true;
700  }
701  }
702 
703  const UInt stride444 = pPicYuv->getStride(COMPONENT_Y);
704 
705  // compute actual YUV width & height excluding padding size
706  const UInt pad_h444 = aiPad[0];
707  const UInt pad_v444 = aiPad[1];
708 
709  const UInt width_full444 = pPicYuv->getWidth(COMPONENT_Y);
710  const UInt height_full444 = pPicYuv->getHeight(COMPONENT_Y);
711 
712  const UInt width444 = width_full444 - pad_h444;
713  const UInt height444 = height_full444 - pad_v444;
714 
715  for(UInt comp=0; comp<MAX_NUM_COMPONENT; comp++)
716  {
717  const ComponentID compID = ComponentID(comp);
718  const ChannelType chType=toChannelType(compID);
719 
720  const Int desired_bitdepth = m_MSBExtendedBitDepth[chType] + m_bitdepthShift[chType];
721 
722 #if !CLIP_TO_709_RANGE
723  const Pel minval = 0;
724  const Pel maxval = (1 << desired_bitdepth) - 1;
725 #else
726  const Bool b709Compliance=(m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
727  const Pel minval = b709Compliance? (( 1 << (desired_bitdepth - 8)) ) : 0;
728  const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
729 #endif
730 
731  if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType]))
732  {
733  return false;
734  }
735 
736  if (compID < pPicYuv->getNumberValidComponents() )
737  {
738  const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat());
739  const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat());
740  scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval);
741  }
742  }
743 
744  Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
745  for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
746  {
747  internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
748  }
749  ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, internalBitDepth, true);
750 
751  return true;
752 }
753 
767 Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format )
768 {
769  TComPicYuv cPicYuvCSCd;
770  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
771  {
772  cPicYuvCSCd.create(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
773  Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
774  for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
775  {
776  internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
777  }
778  ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, internalBitDepth, false);
779  }
780  TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd;
781 
782  // compute actual YUV frame size excluding padding size
783  const Int iStride444 = pPicYuv->getStride(COMPONENT_Y);
784  const UInt width444 = pPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight;
785  const UInt height444 = pPicYuv->getHeight(COMPONENT_Y) - confTop - confBottom;
786  Bool is16bit = false;
787  Bool nonZeroBitDepthShift=false;
788 
789  if ((width444 == 0) || (height444 == 0))
790  {
791  printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
792  }
793 
794  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
795  {
796  if (m_fileBitdepth[ch] > 8)
797  {
798  is16bit=true;
799  }
800  if (m_bitdepthShift[ch] != 0)
801  {
802  nonZeroBitDepthShift=true;
803  }
804  }
805 
806  TComPicYuv *dstPicYuv = NULL;
807  Bool retval = true;
808  if (format>=NUM_CHROMA_FORMAT)
809  {
810  format=pPicYuv->getChromaFormat();
811  }
812 
813  if (nonZeroBitDepthShift)
814  {
815  dstPicYuv = new TComPicYuv;
816  dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), 1, 1, 0 );
817  pPicYuv->copyToPic(dstPicYuv);
818 
819  for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
820  {
821  const ComponentID compID=ComponentID(comp);
822  const ChannelType ch=toChannelType(compID);
823 #if !CLIP_TO_709_RANGE
824  const Pel minval = 0;
825  const Pel maxval = (1 << m_MSBExtendedBitDepth[ch]) - 1;
826 #else
827  const Bool b709Compliance=(-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
828  const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0;
829  const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
830 #endif
831 
832  scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
833  }
834  }
835  else
836  {
837  dstPicYuv = pPicYuv;
838  }
839 
840  for(UInt comp=0; retval && comp<dstPicYuv->getNumberValidComponents(); comp++)
841  {
842  const ComponentID compID = ComponentID(comp);
843  const ChannelType ch=toChannelType(compID);
844  const UInt csx = pPicYuv->getComponentScaleX(compID);
845  const UInt csy = pPicYuv->getComponentScaleY(compID);
846  const Int planeOffset = (confLeft>>csx) + (confTop>>csy) * pPicYuv->getStride(compID);
847  if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, iStride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch]))
848  {
849  retval=false;
850  }
851  }
852 
853  if (nonZeroBitDepthShift)
854  {
855  dstPicYuv->destroy();
856  delete dstPicYuv;
857  }
858 
859  cPicYuvCSCd.destroy();
860 
861  return retval;
862 }
863 
864 Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUserTop, TComPicYuv* pPicYuvUserBottom, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool isTff )
865 {
866 
867  TComPicYuv cPicYuvTopCSCd;
868  TComPicYuv cPicYuvBottomCSCd;
869  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
870  {
871  cPicYuvTopCSCd .create(pPicYuvUserTop ->getWidth(COMPONENT_Y), pPicYuvUserTop ->getHeight(COMPONENT_Y), pPicYuvUserTop ->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
872  cPicYuvBottomCSCd.create(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
873  Int internalBitDepth[MAX_NUM_CHANNEL_TYPE];
874  for(UInt chType=0; chType<MAX_NUM_CHANNEL_TYPE; chType++)
875  {
876  internalBitDepth[chType] = m_bitdepthShift[chType] + m_MSBExtendedBitDepth[chType];
877  }
878  ColourSpaceConvert(*pPicYuvUserTop, cPicYuvTopCSCd, ipCSC, internalBitDepth, false);
879  ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, internalBitDepth, false);
880  }
881  TComPicYuv *pPicYuvTop = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop : &cPicYuvTopCSCd;
882  TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd;
883 
884  Bool is16bit = false;
885  Bool nonZeroBitDepthShift=false;
886 
887  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
888  {
889  if (m_fileBitdepth[ch] > 8)
890  {
891  is16bit=true;
892  }
893  if (m_bitdepthShift[ch] != 0)
894  {
895  nonZeroBitDepthShift=true;
896  }
897  }
898 
899  TComPicYuv *dstPicYuvTop = NULL;
900  TComPicYuv *dstPicYuvBottom = NULL;
901 
902  for (UInt field = 0; field < 2; field++)
903  {
904  TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom;
905 
906  if (format>=NUM_CHROMA_FORMAT)
907  {
908  format=pPicYuv->getChromaFormat();
909  }
910 
911  TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom;
912 
913  if (nonZeroBitDepthShift)
914  {
915  dstPicYuv = new TComPicYuv;
916  dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), 1, 1, 0 );
917  pPicYuv->copyToPic(dstPicYuv);
918 
919  for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
920  {
921  const ComponentID compID=ComponentID(comp);
922  const ChannelType ch=toChannelType(compID);
923 #if !CLIP_TO_709_RANGE
924  const Pel minval = 0;
925  const Pel maxval = (1 << m_MSBExtendedBitDepth[ch]) - 1;
926 #else
927  const Bool b709Compliance=(-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
928  const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0;
929  const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
930 #endif
931 
932  scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
933  }
934  }
935  else
936  {
937  dstPicYuv = pPicYuv;
938  }
939  }
940 
941  Bool retval = true;
942 
943  assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents());
944  assert(dstPicYuvTop->getChromaFormat() == dstPicYuvBottom->getChromaFormat() );
945  assert(dstPicYuvTop->getWidth(COMPONENT_Y) == dstPicYuvBottom->getWidth(COMPONENT_Y) );
946  assert(dstPicYuvTop->getHeight(COMPONENT_Y) == dstPicYuvBottom->getHeight(COMPONENT_Y) );
947  assert(dstPicYuvTop->getStride(COMPONENT_Y) == dstPicYuvBottom->getStride(COMPONENT_Y) );
948 
949  for(UInt comp=0; retval && comp<dstPicYuvTop->getNumberValidComponents(); comp++)
950  {
951  const ComponentID compID = ComponentID(comp);
952  const ChannelType ch=toChannelType(compID);
953 
954  assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID));
955  assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID));
956  assert(dstPicYuvTop->getStride (compID) == dstPicYuvBottom->getStride (compID));
957 
958  const UInt width444 = dstPicYuvTop->getWidth(COMPONENT_Y) - (confLeft + confRight);
959  const UInt height444 = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom);
960 
961  if ((width444 == 0) || (height444 == 0))
962  {
963  printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
964  }
965 
966  const UInt csx = dstPicYuvTop->getComponentScaleX(compID);
967  const UInt csy = dstPicYuvTop->getComponentScaleY(compID);
968  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
969 
970  if (! writeField(m_cHandle,
971  (dstPicYuvTop ->getAddr(compID) + planeOffset),
972  (dstPicYuvBottom->getAddr(compID) + planeOffset),
973  is16bit,
974  dstPicYuvTop->getStride(COMPONENT_Y),
975  width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff))
976  {
977  retval=false;
978  }
979  }
980 
981  if (nonZeroBitDepthShift)
982  {
983  dstPicYuvTop->destroy();
984  dstPicYuvBottom->destroy();
985  delete dstPicYuvTop;
986  delete dstPicYuvBottom;
987  }
988 
989  cPicYuvTopCSCd.destroy();
990  cPicYuvBottomCSCd.destroy();
991 
992  return retval;
993 }
994 
995 static Void
996 copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
997 {
998  const UInt width=src.getWidth(srcPlane);
999  const UInt height=src.getHeight(srcPlane);
1000  assert(dest.getWidth(destPlane) == width);
1001  assert(dest.getHeight(destPlane) == height);
1002  const Pel *pSrc=src.getAddr(srcPlane);
1003  Pel *pDest=dest.getAddr(destPlane);
1004  const UInt strideSrc=src.getStride(srcPlane);
1005  const UInt strideDest=dest.getStride(destPlane);
1006  for(UInt y=0; y<height; y++, pSrc+=strideSrc, pDest+=strideDest)
1007  {
1008  memcpy(pDest, pSrc, width*sizeof(Pel));
1009  }
1010 }
1011 
1012 // static member
1013 Void TVideoIOYuv::ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, const Int bitDepths[MAX_NUM_CHANNEL_TYPE], Bool bIsForwards)
1014 {
1015  const ChromaFormat format=src.getChromaFormat();
1016  const UInt numValidComp=src.getNumberValidComponents();
1017 
1018  switch (conversion)
1019  {
1021  if (format!=CHROMA_444)
1022  {
1023  // only 444 is handled.
1024  assert(format==CHROMA_444);
1025  exit(1);
1026  }
1027 
1028  {
1029  for(UInt comp=0; comp<numValidComp; comp++)
1030  {
1031  copyPlane(src, ComponentID(bIsForwards?0:comp), dest, ComponentID(comp));
1032  }
1033  }
1034  break;
1036  {
1037  for(UInt comp=0; comp<numValidComp; comp++)
1038  {
1039  copyPlane(src, ComponentID(comp), dest, ComponentID((numValidComp-comp)%numValidComp));
1040  }
1041  }
1042  break;
1043 
1045  {
1046  if (format!=CHROMA_444)
1047  {
1048  // only 444 is handled.
1049  assert(format==CHROMA_444);
1050  exit(1);
1051  }
1052 
1053  // channel re-mapping
1054  for(UInt comp=0; comp<numValidComp; comp++)
1055  {
1056  const ComponentID compIDsrc=ComponentID((comp+1)%numValidComp);
1057  const ComponentID compIDdst=ComponentID(comp);
1058  copyPlane(src, bIsForwards?compIDsrc:compIDdst, dest, bIsForwards?compIDdst:compIDsrc);
1059  }
1060  }
1061  break;
1062 
1064  default:
1065  {
1066  for(UInt comp=0; comp<numValidComp; comp++)
1067  {
1068  copyPlane(src, ComponentID(comp), dest, ComponentID(comp));
1069  }
1070  }
1071  break;
1072  }
1073 }
static Void ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, const Int bitDepths[MAX_NUM_CHANNEL_TYPE], Bool bIsForwards)
UInt g_uiMaxCUDepth
Definition: TComRom.cpp:253
unsigned short UShort
Definition: TypeDef.h:295
Void create(const Int iPicWidth, const Int iPicHeight, const ChromaFormat chromaFormatIDC, const UInt uiMaxCUWidth, const UInt uiMaxCUHeight, const UInt uiMaxCUDepth)
Definition: TComPicYuv.cpp:81
picture YUV buffer class
Definition: TComPicYuv.h:55
Void 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])
open or create file
ChannelType
Definition: TypeDef.h:361
Bool read(TComPicYuv *pPicYuv, TComPicYuv *pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat fileFormat=NUM_CHROMA_FORMAT)
read one frame with padding parameter
static Void copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
void Void
Definition: TypeDef.h:285
Int getStride(const ComponentID id) const
Definition: TComPicYuv.h:113
global variables & functions (header)
#define NULL
Definition: CommonDef.h:100
Int getHeight(const ComponentID id) const
Definition: TComPicYuv.h:109
static UInt getComponentScaleY(const ComponentID id, const ChromaFormat fmt)
char Char
Definition: TypeDef.h:291
unsigned int UInt
Definition: TypeDef.h:297
static UInt getComponentScaleX(const ComponentID id, const ChromaFormat fmt)
static Void scalePlane(Pel *img, const UInt stride, const UInt width, const UInt height, Int shiftbits, Pel minval, Pel maxval)
Definition: TVideoIOYuv.cpp:70
Short Pel
pixel type
Definition: TypeDef.h:692
STL namespace.
Bool isEof()
check for end-of-file
YUV file I/O class (header)
Int getWidth(const ComponentID id) const
Definition: TComPicYuv.h:108
UInt getComponentScaleY(const ComponentID id) const
Definition: TComPicYuv.h:139
UInt getComponentScaleX(const ComponentID id) const
Definition: TComPicYuv.h:138
Bool write(TComPicYuv *pPicYuv, const InputColourSpaceConversion ipCSC, Int confLeft=0, Int confRight=0, Int confTop=0, Int confBottom=0, ChromaFormat fileFormat=NUM_CHROMA_FORMAT)
write one YUV frame with padding parameter
bool Bool
Definition: TypeDef.h:286
Bool isFail()
check for failure
UInt g_uiMaxCUHeight
Definition: TComRom.cpp:252
UInt g_uiMaxCUWidth
Definition: TComRom.cpp:251
Void copyToPic(TComPicYuv *pcPicYuvDst) const
Definition: TComPicYuv.cpp:176
static ChannelType toChannelType(const ComponentID id)
T Clip3(const T minVal, const T maxVal, const T a)
general min/max clip
Definition: CommonDef.h:137
Void skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format)
Void close()
close file
ChromaFormat
chroma formats (according to semantics of chroma_format_idc)
Definition: TypeDef.h:352
unsigned char UChar
Definition: TypeDef.h:293
static Bool writePlane(ostream &fd, Pel *src, Bool is16bit, UInt stride444, UInt width444, UInt height444, const ComponentID compID, const ChromaFormat srcFormat, const ChromaFormat fileFormat, const UInt fileBitDepth)
UInt getNumberValidComponents() const
Definition: TComPicYuv.h:111
InputColourSpaceConversion
Definition: TypeDef.h:376
Pel * getAddr(const ComponentID ch)
Definition: TComPicYuv.h:127
int Int
Definition: TypeDef.h:296
static Bool writeField(ostream &fd, Pel *top, Pel *bottom, Bool is16bit, UInt stride444, UInt width444, UInt height444, const ComponentID compID, const ChromaFormat srcFormat, const ChromaFormat fileFormat, const UInt fileBitDepth, const Bool isTff)
ComponentID
Definition: TypeDef.h:368
static Bool readPlane(Pel *dst, istream &fd, Bool is16bit, UInt stride444, UInt width444, UInt height444, UInt pad_x444, UInt pad_y444, const ComponentID compID, const ChromaFormat destFormat, const ChromaFormat fileFormat, const UInt fileBitDepth)
static UInt getNumberValidComponents(const ChromaFormat fmt)
Void destroy()
Definition: TComPicYuv.cpp:146
ChromaFormat getChromaFormat() const
Definition: TComPicYuv.h:110