HEVC Test Model (HM)  HM-16.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-2017, 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 static Void
98 copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane);
99 
100 // ====================================================================================================================
101 // Public member functions
102 // ====================================================================================================================
103 
120 Void TVideoIOYuv::open( const std::string &fileName, Bool bWriteMode, const Int fileBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int internalBitDepth[MAX_NUM_CHANNEL_TYPE] )
121 {
122  //NOTE: files cannot have bit depth greater than 16
123  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
124  {
125  m_fileBitdepth [ch] = std::min<UInt>(fileBitDepth[ch], 16);
126  m_MSBExtendedBitDepth[ch] = MSBExtendedBitDepth[ch];
127  m_bitdepthShift [ch] = internalBitDepth[ch] - m_MSBExtendedBitDepth[ch];
128 
129  if (m_fileBitdepth[ch] > 16)
130  {
131  if (bWriteMode)
132  {
133  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;
134  }
135  else
136  {
137  std::cerr << "\nERROR: Cannot read a yuv file of bit depth greater than 16\n" << std::endl;
138  exit(0);
139  }
140  }
141  }
142 
143  if ( bWriteMode )
144  {
145  m_cHandle.open( fileName.c_str(), ios::binary | ios::out );
146 
147  if( m_cHandle.fail() )
148  {
149  printf("\nfailed to write reconstructed YUV file\n");
150  exit(0);
151  }
152  }
153  else
154  {
155  m_cHandle.open( fileName.c_str(), ios::binary | ios::in );
156 
157  if( m_cHandle.fail() )
158  {
159  printf("\nfailed to open Input YUV file\n");
160  exit(0);
161  }
162  }
163 
164  return;
165 }
166 
168 {
169  m_cHandle.close();
170 }
171 
173 {
174  return m_cHandle.eof();
175 }
176 
178 {
179  return m_cHandle.fail();
180 }
181 
188 Void TVideoIOYuv::skipFrames(Int numFrames, UInt width, UInt height, ChromaFormat format)
189 {
190  if (numFrames==0)
191  {
192  return;
193  }
194 
195  //------------------
196  //set the frame size according to the chroma format
197  streamoff frameSize = 0;
198  UInt wordsize=1; // default to 8-bit, unless a channel with more than 8-bits is detected.
199  for (UInt component = 0; component < getNumberValidComponents(format); component++)
200  {
201  ComponentID compID=ComponentID(component);
202  frameSize += (width >> getComponentScaleX(compID, format)) * (height >> getComponentScaleY(compID, format));
203  if (m_fileBitdepth[toChannelType(compID)] > 8)
204  {
205  wordsize=2;
206  }
207  }
208  frameSize *= wordsize;
209  //------------------
210 
211  const streamoff offset = frameSize * numFrames;
212 
213  /* attempt to seek */
214  if (!!m_cHandle.seekg(offset, ios::cur))
215  {
216  return; /* success */
217  }
218  m_cHandle.clear();
219 
220  /* fall back to consuming the input */
221  TChar buf[512];
222  const streamoff offset_mod_bufsize = offset % sizeof(buf);
223  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
224  {
225  m_cHandle.read(buf, sizeof(buf));
226  }
227  m_cHandle.read(buf, offset_mod_bufsize);
228 }
229 
249 static Bool readPlane(Pel* dst,
250  istream& fd,
251  Bool is16bit,
252  UInt stride444,
253  UInt width444,
254  UInt height444,
255  UInt pad_x444,
256  UInt pad_y444,
257  const ComponentID compID,
258  const ChromaFormat destFormat,
259  const ChromaFormat fileFormat,
260  const UInt fileBitDepth)
261 {
262  const UInt csx_file =getComponentScaleX(compID, fileFormat);
263  const UInt csy_file =getComponentScaleY(compID, fileFormat);
264  const UInt csx_dest =getComponentScaleX(compID, destFormat);
265  const UInt csy_dest =getComponentScaleY(compID, destFormat);
266 
267  const UInt width_dest = width444 >>csx_dest;
268  const UInt height_dest = height444>>csy_dest;
269  const UInt pad_x_dest = pad_x444>>csx_dest;
270  const UInt pad_y_dest = pad_y444>>csy_dest;
271  const UInt stride_dest = stride444>>csx_dest;
272 
273  const UInt full_width_dest = width_dest+pad_x_dest;
274  const UInt full_height_dest = height_dest+pad_y_dest;
275 
276  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
277  std::vector<UChar> bufVec(stride_file);
278  UChar *buf=&(bufVec[0]);
279 
280  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || destFormat==CHROMA_400))
281  {
282  if (destFormat!=CHROMA_400)
283  {
284  // set chrominance data to mid-range: (1<<(fileBitDepth-1))
285  const Pel value=Pel(1<<(fileBitDepth-1));
286  for (UInt y = 0; y < full_height_dest; y++, dst+=stride_dest)
287  {
288  for (UInt x = 0; x < full_width_dest; x++)
289  {
290  dst[x] = value;
291  }
292  }
293  }
294 
295  if (fileFormat!=CHROMA_400)
296  {
297  const UInt height_file = height444>>csy_file;
298  fd.seekg(height_file*stride_file, ios::cur);
299  if (fd.eof() || fd.fail() )
300  {
301  return false;
302  }
303  }
304  }
305  else
306  {
307  const UInt mask_y_file=(1<<csy_file)-1;
308  const UInt mask_y_dest=(1<<csy_dest)-1;
309  for(UInt y444=0; y444<height444; y444++)
310  {
311  if ((y444&mask_y_file)==0)
312  {
313  // read a new line
314  fd.read(reinterpret_cast<TChar*>(buf), stride_file);
315  if (fd.eof() || fd.fail() )
316  {
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  return true;
384 }
385 
401 static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
402  UInt stride444,
403  UInt width444, UInt height444,
404  const ComponentID compID,
405  const ChromaFormat srcFormat,
406  const ChromaFormat fileFormat,
407  const UInt fileBitDepth)
408 {
409  const UInt csx_file =getComponentScaleX(compID, fileFormat);
410  const UInt csy_file =getComponentScaleY(compID, fileFormat);
411  const UInt csx_src =getComponentScaleX(compID, srcFormat);
412  const UInt csy_src =getComponentScaleY(compID, srcFormat);
413 
414  const UInt stride_src = stride444>>csx_src;
415 
416  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
417  const UInt width_file = width444 >>csx_file;
418  const UInt height_file = height444>>csy_file;
419 
420  std::vector<UChar> bufVec(stride_file);
421  UChar *buf=&(bufVec[0]);
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<const TChar*>(buf), stride_file);
450  if (fd.eof() || fd.fail() )
451  {
452  return false;
453  }
454  }
455  }
456  }
457  else
458  {
459  const UInt mask_y_file=(1<<csy_file)-1;
460  const UInt mask_y_src =(1<<csy_src )-1;
461  for(UInt y444=0; y444<height444; y444++)
462  {
463  if ((y444&mask_y_file)==0)
464  {
465  // write a new line
466  if (csx_file < csx_src)
467  {
468  // eg file is 444, source is 422.
469  const UInt sx=csx_src-csx_file;
470  if (!is16bit)
471  {
472  for (UInt x = 0; x < width_file; x++)
473  {
474  buf[x] = (UChar)(src[x>>sx]);
475  }
476  }
477  else
478  {
479  for (UInt x = 0; x < width_file; x++)
480  {
481  buf[2*x ] = (src[x>>sx]>>0) & 0xff;
482  buf[2*x+1] = (src[x>>sx]>>8) & 0xff;
483  }
484  }
485  }
486  else
487  {
488  // eg file is 422, src is 444.
489  const UInt sx=csx_file-csx_src;
490  if (!is16bit)
491  {
492  for (UInt x = 0; x < width_file; x++)
493  {
494  buf[x] = (UChar)(src[x<<sx]);
495  }
496  }
497  else
498  {
499  for (UInt x = 0; x < width_file; x++)
500  {
501  buf[2*x ] = (src[x<<sx]>>0) & 0xff;
502  buf[2*x+1] = (src[x<<sx]>>8) & 0xff;
503  }
504  }
505  }
506 
507  fd.write(reinterpret_cast<const TChar*>(buf), stride_file);
508  if (fd.eof() || fd.fail() )
509  {
510  return false;
511  }
512  }
513 
514  if ((y444&mask_y_src)==0)
515  {
516  src += stride_src;
517  }
518 
519  }
520  }
521  return true;
522 }
523 
524 static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit,
525  UInt stride444,
526  UInt width444, UInt height444,
527  const ComponentID compID,
528  const ChromaFormat srcFormat,
529  const ChromaFormat fileFormat,
530  const UInt fileBitDepth, const Bool isTff)
531 {
532  const UInt csx_file =getComponentScaleX(compID, fileFormat);
533  const UInt csy_file =getComponentScaleY(compID, fileFormat);
534  const UInt csx_src =getComponentScaleX(compID, srcFormat);
535  const UInt csy_src =getComponentScaleY(compID, srcFormat);
536 
537  const UInt stride_src = stride444>>csx_src;
538 
539  const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file;
540  const UInt width_file = width444 >>csx_file;
541  const UInt height_file = height444>>csy_file;
542 
543  std::vector<UChar> bufVec(stride_file * 2);
544  UChar *buf=&(bufVec[0]);
545 
546  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
547  {
548  if (fileFormat!=CHROMA_400)
549  {
550  const UInt value=1<<(fileBitDepth-1);
551 
552  for(UInt y=0; y< height_file; y++)
553  {
554  for (UInt field = 0; field < 2; field++)
555  {
556  UChar *fieldBuffer = buf + (field * stride_file);
557 
558  if (!is16bit)
559  {
560  UChar val(value);
561  for (UInt x = 0; x < width_file; x++)
562  {
563  fieldBuffer[x]=val;
564  }
565  }
566  else
567  {
568  UShort val(value);
569  for (UInt x = 0; x < width_file; x++)
570  {
571  fieldBuffer[2*x+0]= (val>>0) & 0xff;
572  fieldBuffer[2*x+1]= (val>>8) & 0xff;
573  }
574  }
575  }
576 
577  fd.write(reinterpret_cast<const TChar*>(buf), (stride_file * 2));
578  if (fd.eof() || fd.fail() )
579  {
580  return false;
581  }
582  }
583  }
584  }
585  else
586  {
587  const UInt mask_y_file=(1<<csy_file)-1;
588  const UInt mask_y_src =(1<<csy_src )-1;
589  for(UInt y444=0; y444<height444; y444++)
590  {
591  if ((y444&mask_y_file)==0)
592  {
593  for (UInt field = 0; field < 2; field++)
594  {
595  UChar *fieldBuffer = buf + (field * stride_file);
596  Pel *src = (((field == 0) && isTff) || ((field == 1) && (!isTff))) ? top : bottom;
597 
598  // write a new line
599  if (csx_file < csx_src)
600  {
601  // eg file is 444, source is 422.
602  const UInt sx=csx_src-csx_file;
603  if (!is16bit)
604  {
605  for (UInt x = 0; x < width_file; x++)
606  {
607  fieldBuffer[x] = (UChar)(src[x>>sx]);
608  }
609  }
610  else
611  {
612  for (UInt x = 0; x < width_file; x++)
613  {
614  fieldBuffer[2*x ] = (src[x>>sx]>>0) & 0xff;
615  fieldBuffer[2*x+1] = (src[x>>sx]>>8) & 0xff;
616  }
617  }
618  }
619  else
620  {
621  // eg file is 422, src is 444.
622  const UInt sx=csx_file-csx_src;
623  if (!is16bit)
624  {
625  for (UInt x = 0; x < width_file; x++)
626  {
627  fieldBuffer[x] = (UChar)(src[x<<sx]);
628  }
629  }
630  else
631  {
632  for (UInt x = 0; x < width_file; x++)
633  {
634  fieldBuffer[2*x ] = (src[x<<sx]>>0) & 0xff;
635  fieldBuffer[2*x+1] = (src[x<<sx]>>8) & 0xff;
636  }
637  }
638  }
639  }
640 
641  fd.write(reinterpret_cast<const TChar*>(buf), (stride_file * 2));
642  if (fd.eof() || fd.fail() )
643  {
644  return false;
645  }
646  }
647 
648  if ((y444&mask_y_src)==0)
649  {
650  top += stride_src;
651  bottom += stride_src;
652  }
653 
654  }
655  }
656  return true;
657 }
658 
675 Bool TVideoIOYuv::read ( TComPicYuv* pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format, const Bool bClipToRec709 )
676 {
677  // check end-of-file
678  if ( isEof() )
679  {
680  return false;
681  }
682  TComPicYuv *pPicYuv=pPicYuvTrueOrg;
683  if (format>=NUM_CHROMA_FORMAT)
684  {
685  format=pPicYuv->getChromaFormat();
686  }
687 
688  Bool is16bit = false;
689 
690  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
691  {
692  if (m_fileBitdepth[ch] > 8)
693  {
694  is16bit=true;
695  }
696  }
697 
698  const UInt stride444 = pPicYuv->getStride(COMPONENT_Y);
699 
700  // compute actual YUV width & height excluding padding size
701  const UInt pad_h444 = aiPad[0];
702  const UInt pad_v444 = aiPad[1];
703 
704  const UInt width_full444 = pPicYuv->getWidth(COMPONENT_Y);
705  const UInt height_full444 = pPicYuv->getHeight(COMPONENT_Y);
706 
707  const UInt width444 = width_full444 - pad_h444;
708  const UInt height444 = height_full444 - pad_v444;
709 
710  for(UInt comp=0; comp<MAX_NUM_COMPONENT; comp++)
711  {
712  const ComponentID compID = ComponentID(comp);
713  const ChannelType chType=toChannelType(compID);
714 
715  const Int desired_bitdepth = m_MSBExtendedBitDepth[chType] + m_bitdepthShift[chType];
716 
717  const Bool b709Compliance=(bClipToRec709) && (m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
718  const Pel minval = b709Compliance? (( 1 << (desired_bitdepth - 8)) ) : 0;
719  const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
720 
721  if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType]))
722  {
723  return false;
724  }
725 
726  if (compID < pPicYuv->getNumberValidComponents() )
727  {
728  const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat());
729  const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat());
730  scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval);
731  }
732  }
733 
734  if(pPicYuvUser)
735  {
736  ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, true);
737  }
738 
739  return true;
740 }
741 
755 Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool bClipToRec709 )
756 {
757  TComPicYuv cPicYuvCSCd;
758  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
759  {
760  cPicYuvCSCd.createWithoutCUInfo(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat() );
761  ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, false);
762  }
763  TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd;
764 
765  // compute actual YUV frame size excluding padding size
766  Bool is16bit = false;
767  Bool nonZeroBitDepthShift=false;
768 
769  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
770  {
771  if (m_fileBitdepth[ch] > 8)
772  {
773  is16bit=true;
774  }
775  if (m_bitdepthShift[ch] != 0)
776  {
777  nonZeroBitDepthShift=true;
778  }
779  }
780 
781  TComPicYuv *dstPicYuv = NULL;
782  Bool retval = true;
783  if (format>=NUM_CHROMA_FORMAT)
784  {
785  format=pPicYuv->getChromaFormat();
786  }
787 
788  if (nonZeroBitDepthShift)
789  {
790  dstPicYuv = new TComPicYuv;
791  dstPicYuv->createWithoutCUInfo( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat() );
792 
793  for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
794  {
795  const ComponentID compID=ComponentID(comp);
796  const ChannelType ch=toChannelType(compID);
797  const Bool b709Compliance = bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
798  const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0;
799  const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
800 
801  copyPlane(*pPicYuv, compID, *dstPicYuv, compID);
802  scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
803  }
804  }
805  else
806  {
807  dstPicYuv = pPicYuv;
808  }
809 
810  const Int stride444 = dstPicYuv->getStride(COMPONENT_Y);
811  const UInt width444 = dstPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight;
812  const UInt height444 = dstPicYuv->getHeight(COMPONENT_Y) - confTop - confBottom;
813 
814  if ((width444 == 0) || (height444 == 0))
815  {
816  printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
817  }
818 
819  for(UInt comp=0; retval && comp<dstPicYuv->getNumberValidComponents(); comp++)
820  {
821  const ComponentID compID = ComponentID(comp);
822  const ChannelType ch=toChannelType(compID);
823  const UInt csx = dstPicYuv->getComponentScaleX(compID);
824  const UInt csy = dstPicYuv->getComponentScaleY(compID);
825  const Int planeOffset = (confLeft>>csx) + (confTop>>csy) * dstPicYuv->getStride(compID);
826  if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, stride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch]))
827  {
828  retval=false;
829  }
830  }
831 
832  if (nonZeroBitDepthShift)
833  {
834  dstPicYuv->destroy();
835  delete dstPicYuv;
836  }
837 
838  cPicYuvCSCd.destroy();
839 
840  return retval;
841 }
842 
843 Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUserTop, TComPicYuv* pPicYuvUserBottom, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool isTff, const Bool bClipToRec709 )
844 {
845 
846  TComPicYuv cPicYuvTopCSCd;
847  TComPicYuv cPicYuvBottomCSCd;
848  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
849  {
850  cPicYuvTopCSCd .createWithoutCUInfo(pPicYuvUserTop ->getWidth(COMPONENT_Y), pPicYuvUserTop ->getHeight(COMPONENT_Y), pPicYuvUserTop ->getChromaFormat() );
851  cPicYuvBottomCSCd.createWithoutCUInfo(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat() );
852  ColourSpaceConvert(*pPicYuvUserTop, cPicYuvTopCSCd, ipCSC, false);
853  ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, false);
854  }
855  TComPicYuv *pPicYuvTop = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop : &cPicYuvTopCSCd;
856  TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd;
857 
858  Bool is16bit = false;
859  Bool nonZeroBitDepthShift=false;
860 
861  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
862  {
863  if (m_fileBitdepth[ch] > 8)
864  {
865  is16bit=true;
866  }
867  if (m_bitdepthShift[ch] != 0)
868  {
869  nonZeroBitDepthShift=true;
870  }
871  }
872 
873  TComPicYuv *dstPicYuvTop = NULL;
874  TComPicYuv *dstPicYuvBottom = NULL;
875 
876  for (UInt field = 0; field < 2; field++)
877  {
878  TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom;
879 
880  if (format>=NUM_CHROMA_FORMAT)
881  {
882  format=pPicYuv->getChromaFormat();
883  }
884 
885  TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom;
886 
887  if (nonZeroBitDepthShift)
888  {
889  dstPicYuv = new TComPicYuv;
890  dstPicYuv->createWithoutCUInfo( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat() );
891 
892  for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
893  {
894  const ComponentID compID=ComponentID(comp);
895  const ChannelType ch=toChannelType(compID);
896  const Bool b709Compliance=bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
897  const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0;
898  const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
899 
900  copyPlane(*pPicYuv, compID, *dstPicYuv, compID);
901  scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
902  }
903  }
904  else
905  {
906  dstPicYuv = pPicYuv;
907  }
908  }
909 
910  Bool retval = true;
911 
912  assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents());
913  assert(dstPicYuvTop->getChromaFormat() == dstPicYuvBottom->getChromaFormat() );
914 
915  for(UInt comp=0; retval && comp<dstPicYuvTop->getNumberValidComponents(); comp++)
916  {
917  const ComponentID compID = ComponentID(comp);
918  const ChannelType ch=toChannelType(compID);
919 
920  assert(dstPicYuvTop->getWidth (compID) == dstPicYuvBottom->getWidth (compID));
921  assert(dstPicYuvTop->getHeight (compID) == dstPicYuvBottom->getHeight (compID));
922  assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID));
923  assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID));
924  assert(dstPicYuvTop->getStride (compID) == dstPicYuvBottom->getStride (compID));
925 
926  const UInt width444 = dstPicYuvTop->getWidth(COMPONENT_Y) - (confLeft + confRight);
927  const UInt height444 = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom);
928 
929  if ((width444 == 0) || (height444 == 0))
930  {
931  printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
932  }
933 
934  const UInt csx = dstPicYuvTop->getComponentScaleX(compID);
935  const UInt csy = dstPicYuvTop->getComponentScaleY(compID);
936  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
937 
938  if (! writeField(m_cHandle,
939  (dstPicYuvTop ->getAddr(compID) + planeOffset),
940  (dstPicYuvBottom->getAddr(compID) + planeOffset),
941  is16bit,
942  dstPicYuvTop->getStride(COMPONENT_Y),
943  width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff))
944  {
945  retval=false;
946  }
947  }
948 
949  if (nonZeroBitDepthShift)
950  {
951  dstPicYuvTop->destroy();
952  dstPicYuvBottom->destroy();
953  delete dstPicYuvTop;
954  delete dstPicYuvBottom;
955  }
956 
957  cPicYuvTopCSCd.destroy();
958  cPicYuvBottomCSCd.destroy();
959 
960  return retval;
961 }
962 
963 static Void
964 copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
965 {
966  const UInt width=src.getWidth(srcPlane);
967  const UInt height=src.getHeight(srcPlane);
968  assert(dest.getWidth(destPlane) == width);
969  assert(dest.getHeight(destPlane) == height);
970  const Pel *pSrc=src.getAddr(srcPlane);
971  Pel *pDest=dest.getAddr(destPlane);
972  const UInt strideSrc=src.getStride(srcPlane);
973  const UInt strideDest=dest.getStride(destPlane);
974  for(UInt y=0; y<height; y++, pSrc+=strideSrc, pDest+=strideDest)
975  {
976  memcpy(pDest, pSrc, width*sizeof(Pel));
977  }
978 }
979 
980 // static member
982 {
983  const ChromaFormat format=src.getChromaFormat();
984  const UInt numValidComp=src.getNumberValidComponents();
985 
986  switch (conversion)
987  {
989  if (format!=CHROMA_444)
990  {
991  // only 444 is handled.
992  assert(format==CHROMA_444);
993  exit(1);
994  }
995 
996  {
997  for(UInt comp=0; comp<numValidComp; comp++)
998  {
999  copyPlane(src, ComponentID(bIsForwards?0:comp), dest, ComponentID(comp));
1000  }
1001  }
1002  break;
1004  {
1005  for(UInt comp=0; comp<numValidComp; comp++)
1006  {
1007  copyPlane(src, ComponentID(comp), dest, ComponentID((numValidComp-comp)%numValidComp));
1008  }
1009  }
1010  break;
1011 
1013  {
1014  if (format!=CHROMA_444)
1015  {
1016  // only 444 is handled.
1017  assert(format==CHROMA_444);
1018  exit(1);
1019  }
1020 
1021  // channel re-mapping
1022  for(UInt comp=0; comp<numValidComp; comp++)
1023  {
1024  const ComponentID compIDsrc=ComponentID((comp+1)%numValidComp);
1025  const ComponentID compIDdst=ComponentID(comp);
1026  copyPlane(src, bIsForwards?compIDsrc:compIDdst, dest, bIsForwards?compIDdst:compIDsrc);
1027  }
1028  }
1029  break;
1030 
1032  default:
1033  {
1034  for(UInt comp=0; comp<numValidComp; comp++)
1035  {
1036  copyPlane(src, ComponentID(comp), dest, ComponentID(comp));
1037  }
1038  }
1039  break;
1040  }
1041 }
unsigned short UShort
Definition: TypeDef.h:210
Bool write(TComPicYuv *pPicYuv, const InputColourSpaceConversion ipCSC, Int confLeft=0, Int confRight=0, Int confTop=0, Int confBottom=0, ChromaFormat fileFormat=NUM_CHROMA_FORMAT, const Bool bClipToRec709=false)
write one YUV frame with padding parameter
picture YUV buffer class
Definition: TComPicYuv.h:55
ChannelType
Definition: TypeDef.h:301
static Void copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
void Void
Definition: TypeDef.h:203
Int getStride(const ComponentID id) const
Definition: TComPicYuv.h:121
global variables &amp; functions (header)
static Void ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, Bool bIsForwards)
Void open(const std::string &fileName, 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
#define NULL
Definition: CommonDef.h:107
Void createWithoutCUInfo(const Int picWidth, const Int picHeight, const ChromaFormat chromaFormatIDC, const Bool bUseMargin=false, const UInt maxCUWidth=0, const UInt maxCUHeight=0)
used for margin only
Definition: TComPicYuv.cpp:81
Int getHeight(const ComponentID id) const
Definition: TComPicYuv.h:117
static UInt getComponentScaleY(const ComponentID id, const ChromaFormat fmt)
unsigned int UInt
Definition: TypeDef.h:212
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:249
Bool isEof()
check for end-of-file
char TChar
Definition: TypeDef.h:206
YUV file I/O class (header)
Int getWidth(const ComponentID id) const
Definition: TComPicYuv.h:116
UInt getComponentScaleY(const ComponentID id) const
Definition: TComPicYuv.h:151
UInt getComponentScaleX(const ComponentID id) const
Definition: TComPicYuv.h:150
bool Bool
Definition: TypeDef.h:204
Bool isFail()
check for failure
static ChannelType toChannelType(const ComponentID id)
T Clip3(const T minVal, const T maxVal, const T a)
general min/max clip
Definition: CommonDef.h:252
Void close()
close file
ChromaFormat
chroma formats (according to semantics of chroma_format_idc)
Definition: TypeDef.h:292
unsigned char UChar
Definition: TypeDef.h:208
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:119
InputColourSpaceConversion
Definition: TypeDef.h:316
Bool read(TComPicYuv *pPicYuv, TComPicYuv *pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat fileFormat=NUM_CHROMA_FORMAT, const Bool bClipToRec709=false)
read one frame with padding parameter
Pel * getAddr(const ComponentID ch)
Definition: TComPicYuv.h:139
int Int
Definition: TypeDef.h:211
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:308
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)
Void skipFrames(Int numFrames, UInt width, UInt height, ChromaFormat format)
static UInt getNumberValidComponents(const ChromaFormat fmt)
Void destroy()
Definition: TComPicYuv.cpp:168
ChromaFormat getChromaFormat() const
Definition: TComPicYuv.h:118