Changeset 1313 in 3DVCSoftware for trunk/source/Lib/TLibVideoIO/TVideoIOYuv.cpp


Ignore:
Timestamp:
13 Aug 2015, 17:38:13 (9 years ago)
Author:
tech
Message:

Merged 14.1-update-dev1@1312.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/Lib/TLibVideoIO/TVideoIOYuv.cpp

    r1179 r1313  
    22 * License, included below. This software may be subject to other third party
    33 * 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
     4 * granted under this license.
     5 *
     6 * Copyright (c) 2010-2015, ITU/ISO/IEC
    77 * All rights reserved.
    88 *
     
    4242#include <fstream>
    4343#include <iostream>
     44#include <memory.h>
    4445
    4546#include "TLibCommon/TComRom.h"
     
    4849using namespace std;
    4950
    50 /**
    51  * Perform division with rounding of all pixels in img by
    52  * 2<sup>shiftbits</sup>. All pixels are clipped to [minval, maxval]
    53  *
    54  * @param img        pointer to image to be transformed
    55  * @param stride     distance between vertically adjacent pixels of img.
    56  * @param width      width of active area in img.
    57  * @param height     height of active area in img.
    58  * @param shiftbits  number of rounding bits
    59  * @param minval     minimum clipping value
    60  * @param maxval     maximum clipping value
    61  */
    62 static void invScalePlane(Pel* img, UInt stride, UInt width, UInt height,
    63                        UInt shiftbits, Pel minval, Pel maxval)
    64 {
    65   Pel offset = 1 << (shiftbits-1);
    66   for (UInt y = 0; y < height; y++)
    67   {
    68     for (UInt x = 0; x < width; x++)
    69     {
    70       Pel val = (img[x] + offset) >> shiftbits;
    71       img[x] = Clip3(minval, maxval, val);
    72     }
    73     img += stride;
    74   }
    75 }
    76 
    77 /**
    78  * Multiply all pixels in img by 2<sup>shiftbits</sup>.
    79  *
    80  * @param img        pointer to image to be transformed
    81  * @param stride     distance between vertically adjacent pixels of img.
    82  * @param width      width of active area in img.
    83  * @param height     height of active area in img.
    84  * @param shiftbits  number of bits to shift
    85  */
    86 static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
    87                        UInt shiftbits)
    88 {
    89   for (UInt y = 0; y < height; y++)
    90   {
    91     for (UInt x = 0; x < width; x++)
    92     {
    93       img[x] <<= shiftbits;
    94     }
    95     img += stride;
    96   }
    97 }
     51// ====================================================================================================================
     52// Local Functions
     53// ====================================================================================================================
    9854
    9955/**
     
    11268 * @param maxval  maximum clipping value when dividing.
    11369 */
    114 static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
    115                        Int shiftbits, Pel minval, Pel maxval)
    116 {
    117   if (shiftbits == 0)
    118   {
    119     return;
    120   }
    121 
     70static Void scalePlane(Pel* img, const UInt stride, const UInt width, const UInt height, Int shiftbits, Pel minval, Pel maxval)
     71{
    12272  if (shiftbits > 0)
    12373  {
    124     scalePlane(img, stride, width, height, shiftbits);
    125   }
    126   else
    127   {
    128     invScalePlane(img, stride, width, height, -shiftbits, minval, maxval);
     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    }
    12994  }
    13095}
     
    146111 *
    147112 * \param pchFile          file name string
    148  * \param bWriteMode       file open mode: true=read, false=write
    149  * \param fileBitDepthY     bit-depth of input/output file data (luma component).
    150  * \param fileBitDepthC     bit-depth of input/output file data (chroma components).
    151  * \param internalBitDepthY bit-depth to scale image data to/from when reading/writing (luma component).
    152  * \param internalBitDepthC bit-depth to scale image data to/from when reading/writing (chroma components).
     113 * \param bWriteMode       file open mode: true=write, false=read
     114 * \param fileBitDepth     bit-depth array of input/output file data.
     115 * \param MSBExtendedBitDepth
     116 * \param internalBitDepth bit-depth array to scale image data to/from when reading/writing.
    153117 */
    154 Void TVideoIOYuv::open( Char* pchFile, Bool bWriteMode, Int fileBitDepthY, Int fileBitDepthC, Int internalBitDepthY, Int internalBitDepthC)
    155 {
    156   m_bitDepthShiftY = internalBitDepthY - fileBitDepthY;
    157   m_bitDepthShiftC = internalBitDepthC - fileBitDepthC;
    158   m_fileBitDepthY = fileBitDepthY;
    159   m_fileBitDepthC = fileBitDepthC;
     118Void 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  }
    160140
    161141  if ( bWriteMode )
    162142  {
    163143    m_cHandle.open( pchFile, ios::binary | ios::out );
    164    
     144
    165145    if( m_cHandle.fail() )
    166146    {
     
    172152  {
    173153    m_cHandle.open( pchFile, ios::binary | ios::in );
    174    
     154
    175155    if( m_cHandle.fail() )
    176156    {
     
    179159    }
    180160  }
    181  
     161
    182162  return;
    183163}
     
    204184 * seekable, by consuming bytes.
    205185 */
    206 void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height)
     186Void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format)
    207187{
    208188  if (!numFrames)
     189  {
    209190    return;
    210 
    211   const UInt wordsize = (m_fileBitDepthY > 8 || m_fileBitDepthC > 8) ? 2 : 1;
    212   const streamoff framesize = wordsize * width * height * 3 / 2;
    213   const streamoff offset = framesize * numFrames;
     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;
    214210
    215211  /* attempt to seek */
    216212  if (!!m_cHandle.seekg(offset, ios::cur))
     213  {
    217214    return; /* success */
     215  }
    218216  m_cHandle.clear();
    219217
    220218  /* fall back to consuming the input */
    221219  Char buf[512];
    222   const UInt offset_mod_bufsize = offset % sizeof(buf);
     220  const streamoff offset_mod_bufsize = offset % sizeof(buf);
    223221  for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
    224222  {
     
    233231 * either 8bit or 16bit little-endian lsb-aligned words.
    234232 *
    235  * @param dst     destination image
    236  * @param fd      input file stream
    237  * @param is16bit true if input file carries > 8bit data, false otherwise.
    238  * @param stride  distance between vertically adjacent pixels of dst.
    239  * @param width   width of active area in dst.
    240  * @param height  height of active area in dst.
    241  * @param pad_x   length of horizontal padding.
    242  * @param pad_y   length of vertical padding.
     233 * @param dst          destination image plane
     234 * @param fd           input file stream
     235 * @param is16bit      true if input file carries > 8bit data, false otherwise.
     236 * @param stride444    distance between vertically adjacent pixels of dst.
     237 * @param width444     width of active area in dst.
     238 * @param height444    height of active area in dst.
     239 * @param pad_x444     length of horizontal padding.
     240 * @param pad_y444     length of vertical padding.
     241 * @param compID       chroma component
     242 * @param destFormat   chroma format of image
     243 * @param fileFormat   chroma format of file
     244 * @param fileBitDepth component bit depth in file
    243245 * @return true for success, false in case of error
    244246 */
    245 static Bool readPlane(Pel* dst, istream& fd, Bool is16bit,
    246                       UInt stride,
    247                       UInt width, UInt height,
    248                       UInt pad_x, UInt pad_y)
    249 {
    250   Int read_len = width * (is16bit ? 2 : 1);
    251   UChar *buf = new UChar[read_len];
    252   for (Int y = 0; y < height; y++)
    253   {
    254     fd.read(reinterpret_cast<Char*>(buf), read_len);
    255     if (fd.eof() || fd.fail() )
    256     {
    257       delete[] buf;
    258       return false;
    259     }
    260 
    261     if (!is16bit)
    262     {
    263       for (Int x = 0; x < width; x++)
    264       {
    265         dst[x] = buf[x];
    266       }
    267     }
    268     else
    269     {
    270       for (Int x = 0; x < width; x++)
    271       {
    272         dst[x] = (buf[2*x+1] << 8) | buf[2*x];
    273       }
    274     }
    275 
    276     for (Int x = width; x < width + pad_x; x++)
    277     {
    278       dst[x] = dst[width - 1];
    279     }
    280     dst += stride;
    281   }
    282   for (Int y = height; y < height + pad_y; y++)
    283   {
    284     for (Int x = 0; x < width + pad_x; x++)
    285     {
    286       dst[x] = (dst - stride)[x];
    287     }
    288     dst += stride;
     247static 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    }
    289382  }
    290383  delete[] buf;
     
    293386
    294387/**
    295  * Write width*height pixels info fd from src.
    296  *
    297  * @param fd      output file stream
    298  * @param src     source image
    299  * @param is16bit true if input file carries > 8bit data, false otherwise.
    300  * @param stride  distance between vertically adjacent pixels of src.
    301  * @param width   width of active area in src.
    302  * @param height  height of active area in src.
     388 * Write an image plane (width444*height444 pixels) from src into output stream fd.
     389 *
     390 * @param fd         output file stream
     391 * @param src        source image
     392 * @param is16bit    true if input file carries > 8bit data, false otherwise.
     393 * @param stride444  distance between vertically adjacent pixels of src.
     394 * @param width444   width of active area in src.
     395 * @param height444  height of active area in src.
     396 * @param compID       chroma component
     397 * @param srcFormat    chroma format of image
     398 * @param fileFormat   chroma format of file
     399 * @param fileBitDepth component bit depth in file
    303400 * @return true for success, false in case of error
    304401 */
    305402static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
    306                        UInt stride,
    307                        UInt width, UInt height)
    308 {
    309   Int write_len = width * (is16bit ? 2 : 1);
    310   UChar *buf = new UChar[write_len];
    311   for (Int y = 0; y < height; y++)
    312   {
    313     if (!is16bit)
    314     {
    315       for (Int x = 0; x < width; x++)
    316       {
    317         buf[x] = (UChar) src[x];
    318       }
    319     }
    320     else
    321     {
    322       for (Int x = 0; x < width; x++)
    323       {
    324         buf[2*x] = src[x] & 0xff;
    325         buf[2*x+1] = (src[x] >> 8) & 0xff;
    326       }
    327     }
    328 
    329     fd.write(reinterpret_cast<Char*>(buf), write_len);
    330     if (fd.eof() || fd.fail() )
    331     {
    332       delete[] buf;
    333       return false;
    334     }
    335     src += stride;
     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    }
    336522  }
    337523  delete[] buf;
     
    340526
    341527static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit,
    342                        UInt stride,
    343                        UInt width, UInt height, bool isTff)
    344 {
    345   Int write_len = width * (is16bit ? 2 : 1)*2;
    346   UChar *buf = new UChar[write_len];
    347   for (Int y = 0; y < height; y++)
    348   {
    349     if (!is16bit)
    350     {
    351       for (Int x = 0; x < width; x++)
    352       {
    353         buf[x] = isTff ? (UChar) top[x] : (UChar) bottom[x];
    354         buf[width+x] = isTff ? (UChar) bottom[x] : (UChar) top[x];
    355       }
    356     }
    357     else
    358     {
    359       for (Int x = 0; x < width; x++)
    360       {
    361         buf[2*x] = isTff ? top[x] & 0xff : bottom[x] & 0xff;
    362         buf[2*x+1] = isTff ? (top[x] >> 8) & 0xff : (bottom[x] >> 8) & 0xff;
    363        
    364         buf[width+2*x] = isTff ? bottom[x] & 0xff : top[x] & 0xff;
    365         buf[width+2*x+1] = isTff ? (bottom[x] >> 8) & 0xff : (top[x] >> 8) & 0xff;
    366       }
    367     }
    368    
    369     fd.write(reinterpret_cast<Char*>(buf), write_len);
    370     if (fd.eof() || fd.fail() )
    371     {
    372       delete[] buf;
    373       return false;
    374     }
    375     top += stride;
    376     bottom += stride;
     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    }
    377659  }
    378660  delete[] buf;
    379661  return true;
    380662}
     663
    381664/**
    382665 * Read one Y'CbCr frame, performing any required input scaling to change
     
    388671 * file had been provided at the lower-bitdepth compliant to Rec601/709.
    389672 *
    390  * @param pPicYuv      input picture YUV buffer class pointer
    391  * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
     673 * @param pPicYuvUser      input picture YUV buffer class pointer
     674 * @param pPicYuvTrueOrg
     675 * @param ipcsc
     676 * @param aiPad            source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
     677 * @param format           chroma format
    392678 * @return true for success, false in case of error
    393679 */
    394 Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuv, Int aiPad[2] )
     680Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format, const Bool bClipToRec709 )
    395681{
    396682  // check end-of-file
    397   if ( isEof() ) return false;
    398  
    399   Int   iStride = pPicYuv->getStride();
    400  
     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
    401705  // compute actual YUV width & height excluding padding size
    402   UInt pad_h = aiPad[0];
    403   UInt pad_v = aiPad[1];
    404   UInt width_full = pPicYuv->getWidth();
    405   UInt height_full = pPicYuv->getHeight();
    406   UInt width  = width_full - pad_h;
    407   UInt height = height_full - pad_v;
    408   Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
    409 
    410   Int desired_bitdepthY = m_fileBitDepthY + m_bitDepthShiftY;
    411   Int desired_bitdepthC = m_fileBitDepthC + m_bitDepthShiftC;
    412   Pel minvalY = 0;
    413   Pel minvalC = 0;
    414   Pel maxvalY = (1 << desired_bitdepthY) - 1;
    415   Pel maxvalC = (1 << desired_bitdepthC) - 1;
    416 #if CLIP_TO_709_RANGE
    417   if (m_bitdepthShiftY < 0 && desired_bitdepthY >= 8)
    418   {
    419     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    420     minvalY = 1 << (desired_bitdepthY - 8);
    421     maxvalY = (0xff << (desired_bitdepthY - 8)) -1;
    422   }
    423   if (m_bitdepthShiftC < 0 && desired_bitdepthC >= 8)
    424   {
    425     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    426     minvalC = 1 << (desired_bitdepthC - 8);
    427     maxvalC = (0xff << (desired_bitdepthC - 8)) -1;
    428   }
    429 #endif
    430  
    431   if (! readPlane(pPicYuv->getLumaAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
    432     return false;
    433   scalePlane(pPicYuv->getLumaAddr(), iStride, width_full, height_full, m_bitDepthShiftY, minvalY, maxvalY);
    434 
    435   iStride >>= 1;
    436   width_full >>= 1;
    437   height_full >>= 1;
    438   width >>= 1;
    439   height >>= 1;
    440   pad_h >>= 1;
    441   pad_v >>= 1;
    442 
    443   if (! readPlane(pPicYuv->getCbAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
    444     return false;
    445   scalePlane(pPicYuv->getCbAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
    446 
    447   if (! readPlane(pPicYuv->getCrAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
    448     return false;
    449   scalePlane(pPicYuv->getCrAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
     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    const Bool b709Compliance=(bClipToRec709) && (m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
     723    const Pel minval = b709Compliance? ((   1 << (desired_bitdepth - 8))   ) : 0;
     724    const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
     725
     726    if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType]))
     727    {
     728      return false;
     729    }
     730
     731    if (compID < pPicYuv->getNumberValidComponents() )
     732    {
     733      const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat());
     734      const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat());
     735      scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval);
     736    }
     737  }
     738
     739  ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, true);
    450740
    451741  return true;
     
    456746 * assumed to be at TVideoIO::m_fileBitdepth depth.
    457747 *
    458  * @param pPicYuv     input picture YUV buffer class pointer
    459  * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
     748 * @param pPicYuvUser      input picture YUV buffer class pointer
     749 * @param ipCSC
     750 * @param confLeft         conformance window left border
     751 * @param confRight        conformance window right border
     752 * @param confTop          conformance window top border
     753 * @param confBottom       conformance window bottom border
     754 * @param format           chroma format
    460755 * @return true for success, false in case of error
    461756 */
    462 Bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int confLeft, Int confRight, Int confTop, Int confBottom )
    463 {
     757Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool bClipToRec709 )
     758{
     759  TComPicYuv cPicYuvCSCd;
     760  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
     761  {
     762    cPicYuvCSCd.create(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat(), pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), 0, false);
     763    ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, false);
     764  }
     765  TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd;
     766
    464767  // compute actual YUV frame size excluding padding size
    465   Int   iStride = pPicYuv->getStride();
    466   UInt  width  = pPicYuv->getWidth()  - confLeft - confRight;
    467   UInt  height = pPicYuv->getHeight() - confTop  - confBottom;
    468   Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
     768  const Int   iStride444 = pPicYuv->getStride(COMPONENT_Y);
     769  const UInt width444  = pPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight;
     770  const UInt height444 = pPicYuv->getHeight(COMPONENT_Y) -  confTop  - confBottom;
     771  Bool is16bit = false;
     772  Bool nonZeroBitDepthShift=false;
     773
     774  if ((width444 == 0) || (height444 == 0))
     775  {
     776    printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
     777  }
     778
     779  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
     780  {
     781    if (m_fileBitdepth[ch] > 8)
     782    {
     783      is16bit=true;
     784    }
     785    if (m_bitdepthShift[ch] != 0)
     786    {
     787      nonZeroBitDepthShift=true;
     788    }
     789  }
     790
    469791  TComPicYuv *dstPicYuv = NULL;
    470792  Bool retval = true;
    471 
    472   if ((width==0)||(height==0))
    473   {
    474     printf ("\nWarning: writing %d x %d luma sample output picture!", width, height);
    475   }
    476 
    477   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
     793  if (format>=NUM_CHROMA_FORMAT)
     794  {
     795    format=pPicYuv->getChromaFormat();
     796  }
     797
     798  if (nonZeroBitDepthShift)
    478799  {
    479800    dstPicYuv = new TComPicYuv;
    480     dstPicYuv->create( pPicYuv->getWidth(), pPicYuv->getHeight(), 1, 1, 0 );
     801    dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), 0, false );
    481802    pPicYuv->copyToPic(dstPicYuv);
    482803
    483     Pel minvalY = 0;
    484     Pel minvalC = 0;
    485     Pel maxvalY = (1 << m_fileBitDepthY) - 1;
    486     Pel maxvalC = (1 << m_fileBitDepthC) - 1;
    487 #if CLIP_TO_709_RANGE
    488     if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)
    489     {
    490       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    491       minvalY = 1 << (m_fileBitDepthY - 8);
    492       maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;
    493     }
    494     if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)
    495     {
    496       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    497       minvalC = 1 << (m_fileBitDepthC - 8);
    498       maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;
    499     }
     804    for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
     805    {
     806      const ComponentID compID=ComponentID(comp);
     807      const ChannelType ch=toChannelType(compID);
     808      const Bool b709Compliance = bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
     809      const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
     810      const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
     811
     812      scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
     813    }
     814  }
     815  else
     816  {
     817    dstPicYuv = pPicYuv;
     818  }
     819#if NH_3D
     820  for(UInt comp=0; retval && comp< ::getNumberValidComponents(format); comp++)
     821#else
     822  for(UInt comp=0; retval && comp<dstPicYuv->getNumberValidComponents(); comp++)
    500823#endif
    501     scalePlane(dstPicYuv->getLumaAddr(), dstPicYuv->getStride(), dstPicYuv->getWidth(), dstPicYuv->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
    502     scalePlane(dstPicYuv->getCbAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    503     scalePlane(dstPicYuv->getCrAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    504   }
    505   else
    506   {
    507     dstPicYuv = pPicYuv;
    508   }
    509   // location of upper left pel in a plane
    510   Int planeOffset = confLeft + confTop * iStride;
    511  
    512   if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr() + planeOffset, is16bit, iStride, width, height))
    513   {
    514     retval=false;
    515     goto exit;
    516   }
    517 
    518   width >>= 1;
    519   height >>= 1;
    520   iStride >>= 1;
    521   confLeft >>= 1;
    522   confRight >>= 1;
    523   confTop >>= 1;
    524   confBottom >>= 1;
    525 
    526   planeOffset = confLeft + confTop * iStride;
    527 
    528   if (! writePlane(m_cHandle, dstPicYuv->getCbAddr() + planeOffset, is16bit, iStride, width, height))
    529   {
    530     retval=false;
    531     goto exit;
    532   }
    533   if (! writePlane(m_cHandle, dstPicYuv->getCrAddr() + planeOffset, is16bit, iStride, width, height))
    534   {
    535     retval=false;
    536     goto exit;
    537   }
    538  
    539 exit:
    540   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
     824  {
     825    const ComponentID compID = ComponentID(comp);
     826    const ChannelType ch=toChannelType(compID);
     827    const UInt csx = pPicYuv->getComponentScaleX(compID);
     828    const UInt csy = pPicYuv->getComponentScaleY(compID);
     829    const Int planeOffset =  (confLeft>>csx) + (confTop>>csy) * pPicYuv->getStride(compID);
     830    if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, iStride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch]))
     831    {
     832      retval=false;
     833    }
     834  }
     835
     836  if (nonZeroBitDepthShift)
    541837  {
    542838    dstPicYuv->destroy();
    543839    delete dstPicYuv;
    544   } 
     840  }
     841
     842  cPicYuvCSCd.destroy();
     843
    545844  return retval;
    546845}
    547846
    548 
    549 /**
    550  * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is
    551  * assumed to be at TVideoIO::m_fileBitdepth depth.
    552  *
    553  * @param pPicTop     input top field YUV buffer class pointer
    554  * @param pPicBottom  input bottom field YUV buffer class pointer
    555  * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
    556  * @return true for success, false in case of error
    557  */
    558 Bool TVideoIOYuv::write( TComPicYuv* pPicTop, TComPicYuv* pPicBottom, Int cropLeft, Int cropRight, Int cropTop, Int cropBottom , bool isTff)
    559 {
    560   // compute actual YUV frame size excluding padding size
    561   Int   iStride = pPicTop->getStride();
    562   UInt  width  = pPicTop->getWidth()  - cropLeft - cropRight;
    563   UInt  height = pPicTop->getHeight() - cropTop  - cropBottom;
    564   Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
    565  
    566   TComPicYuv *dstPicTop = NULL;
    567   TComPicYuv *dstPicBottom = NULL;
    568  
     847Bool 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 )
     848{
     849
     850  TComPicYuv cPicYuvTopCSCd;
     851  TComPicYuv cPicYuvBottomCSCd;
     852  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
     853  {
     854    cPicYuvTopCSCd   .create(pPicYuvUserTop   ->getWidth(COMPONENT_Y), pPicYuvUserTop   ->getHeight(COMPONENT_Y), pPicYuvUserTop   ->getChromaFormat(), pPicYuvUserTop   ->getWidth(COMPONENT_Y), pPicYuvUserTop   ->getHeight(COMPONENT_Y), 0, false);
     855    cPicYuvBottomCSCd.create(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat(), pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), 0, false);
     856    ColourSpaceConvert(*pPicYuvUserTop,    cPicYuvTopCSCd,    ipCSC, false);
     857    ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, false);
     858  }
     859  TComPicYuv *pPicYuvTop    = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop    : &cPicYuvTopCSCd;
     860  TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd;
     861
     862  Bool is16bit = false;
     863  Bool nonZeroBitDepthShift=false;
     864
     865  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
     866  {
     867    if (m_fileBitdepth[ch] > 8)
     868    {
     869      is16bit=true;
     870    }
     871    if (m_bitdepthShift[ch] != 0)
     872    {
     873      nonZeroBitDepthShift=true;
     874    }
     875  }
     876
     877  TComPicYuv *dstPicYuvTop    = NULL;
     878  TComPicYuv *dstPicYuvBottom = NULL;
     879
     880  for (UInt field = 0; field < 2; field++)
     881  {
     882    TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom;
     883
     884    if (format>=NUM_CHROMA_FORMAT)
     885    {
     886      format=pPicYuv->getChromaFormat();
     887    }
     888
     889    TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom;
     890
     891    if (nonZeroBitDepthShift)
     892    {
     893      dstPicYuv = new TComPicYuv;
     894      dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), 0, false );
     895      pPicYuv->copyToPic(dstPicYuv);
     896
     897      for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
     898      {
     899        const ComponentID compID=ComponentID(comp);
     900        const ChannelType ch=toChannelType(compID);
     901        const Bool b709Compliance=bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
     902        const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
     903        const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
     904
     905        scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
     906      }
     907    }
     908    else
     909    {
     910      dstPicYuv = pPicYuv;
     911    }
     912  }
     913
    569914  Bool retval = true;
    570  
    571   if ((width==0)||(height==0))
    572   {
    573     printf ("\nWarning: writing %d x %d luma sample output picture!", width, height);
    574   }
    575  
    576   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
    577   {
    578     dstPicTop = new TComPicYuv;
    579     dstPicTop->create( pPicTop->getWidth(), pPicTop->getHeight(), 1, 1, 0 );
    580     pPicTop->copyToPic(dstPicTop);
    581    
    582     dstPicBottom = new TComPicYuv;
    583     dstPicBottom->create( pPicBottom->getWidth(), pPicBottom->getHeight(), 1, 1, 0 );
    584     pPicBottom->copyToPic(dstPicBottom);
    585    
    586     Pel minvalY = 0;
    587     Pel minvalC = 0;
    588     Pel maxvalY = (1 << m_fileBitDepthY) - 1;
    589     Pel maxvalC = (1 << m_fileBitDepthC) - 1;
    590 #if CLIP_TO_709_RANGE
    591     if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)
    592     {
    593       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    594       minvalY = 1 << (m_fileBitDepthY - 8);
    595       maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;
    596     }
    597     if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)
    598     {
    599       /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
    600       minvalC = 1 << (m_fileBitDepthC - 8);
    601       maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;
    602     }
    603 #endif
    604     scalePlane(dstPicTop->getLumaAddr(), dstPicTop->getStride(), dstPicTop->getWidth(), dstPicTop->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
    605     scalePlane(dstPicTop->getCbAddr(), dstPicTop->getCStride(), dstPicTop->getWidth()>>1, dstPicTop->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    606     scalePlane(dstPicTop->getCrAddr(), dstPicTop->getCStride(), dstPicTop->getWidth()>>1, dstPicTop->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    607    
    608     scalePlane(dstPicBottom->getLumaAddr(), dstPicBottom->getStride(), dstPicBottom->getWidth(), dstPicBottom->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
    609     scalePlane(dstPicBottom->getCbAddr(), dstPicBottom->getCStride(), dstPicBottom->getWidth()>>1, dstPicBottom->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    610     scalePlane(dstPicBottom->getCrAddr(), dstPicBottom->getCStride(), dstPicBottom->getWidth()>>1, dstPicBottom->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
    611   }
    612   else
    613   {
    614     dstPicTop = pPicTop;
    615     dstPicBottom = pPicBottom;
    616   }
    617   // location of upper left pel in a plane
    618   Int planeOffset = 0; //cropLeft + cropTop * iStride;
    619   //Write luma
    620   if (! writeField(m_cHandle, dstPicTop->getLumaAddr() + planeOffset,  dstPicBottom->getLumaAddr() + planeOffset, is16bit, iStride, width, height, isTff))
    621   {
    622     retval=false;
    623     goto exit;
    624   }
    625  
    626   width >>= 1;
    627   height >>= 1;
    628   iStride >>= 1;
    629   cropLeft >>= 1;
    630   cropRight >>= 1;
    631  
    632   planeOffset = 0; // cropLeft + cropTop * iStride;
    633  
    634   //Write chroma U
    635   if (! writeField(m_cHandle, dstPicTop->getCbAddr() + planeOffset, dstPicBottom->getCbAddr() + planeOffset, is16bit, iStride, width, height, isTff))
    636   {
    637     retval=false;
    638     goto exit;
    639   }
    640  
    641   //Write chroma V
    642   if (! writeField(m_cHandle, dstPicTop->getCrAddr() + planeOffset, dstPicBottom->getCrAddr() + planeOffset, is16bit, iStride, width, height, isTff))
    643    
    644   {
    645     retval=false;
    646     goto exit;
    647   }
    648  
    649 exit:
    650   if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
    651   {
    652     dstPicTop->destroy();
    653     delete dstPicTop;
    654     dstPicBottom->destroy();
    655     delete dstPicBottom;
    656   } 
     915
     916  assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents());
     917  assert(dstPicYuvTop->getChromaFormat()          == dstPicYuvBottom->getChromaFormat()         );
     918  assert(dstPicYuvTop->getWidth(COMPONENT_Y)      == dstPicYuvBottom->getWidth(COMPONENT_Y)    );
     919  assert(dstPicYuvTop->getHeight(COMPONENT_Y)     == dstPicYuvBottom->getHeight(COMPONENT_Y)    );
     920  assert(dstPicYuvTop->getStride(COMPONENT_Y)     == dstPicYuvBottom->getStride(COMPONENT_Y)    );
     921
     922  for(UInt comp=0; retval && comp<dstPicYuvTop->getNumberValidComponents(); comp++)
     923  {
     924    const ComponentID compID = ComponentID(comp);
     925    const ChannelType ch=toChannelType(compID);
     926
     927    assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID));
     928    assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID));
     929    assert(dstPicYuvTop->getStride         (compID) == dstPicYuvBottom->getStride         (compID));
     930
     931    const UInt width444   = dstPicYuvTop->getWidth(COMPONENT_Y)  - (confLeft + confRight);
     932    const UInt height444  = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom);
     933
     934    if ((width444 == 0) || (height444 == 0))
     935    {
     936      printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
     937    }
     938
     939    const UInt csx = dstPicYuvTop->getComponentScaleX(compID);
     940    const UInt csy = dstPicYuvTop->getComponentScaleY(compID);
     941    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
     942
     943    if (! writeField(m_cHandle,
     944                     (dstPicYuvTop   ->getAddr(compID) + planeOffset),
     945                     (dstPicYuvBottom->getAddr(compID) + planeOffset),
     946                     is16bit,
     947                     dstPicYuvTop->getStride(COMPONENT_Y),
     948                     width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff))
     949    {
     950      retval=false;
     951    }
     952  }
     953
     954  if (nonZeroBitDepthShift)
     955  {
     956    dstPicYuvTop->destroy();
     957    dstPicYuvBottom->destroy();
     958    delete dstPicYuvTop;
     959    delete dstPicYuvBottom;
     960  }
     961
     962  cPicYuvTopCSCd.destroy();
     963  cPicYuvBottomCSCd.destroy();
     964
    657965  return retval;
    658966}
     967
     968static Void
     969copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
     970{
     971  const UInt width=src.getWidth(srcPlane);
     972  const UInt height=src.getHeight(srcPlane);
     973  assert(dest.getWidth(destPlane) == width);
     974  assert(dest.getHeight(destPlane) == height);
     975  const Pel *pSrc=src.getAddr(srcPlane);
     976  Pel *pDest=dest.getAddr(destPlane);
     977  const UInt strideSrc=src.getStride(srcPlane);
     978  const UInt strideDest=dest.getStride(destPlane);
     979  for(UInt y=0; y<height; y++, pSrc+=strideSrc, pDest+=strideDest)
     980  {
     981    memcpy(pDest, pSrc, width*sizeof(Pel));
     982  }
     983}
     984
     985// static member
     986Void TVideoIOYuv::ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, Bool bIsForwards)
     987{
     988  const ChromaFormat  format=src.getChromaFormat();
     989  const UInt          numValidComp=src.getNumberValidComponents();
     990
     991  switch (conversion)
     992  {
     993    case IPCOLOURSPACE_YCbCrtoYYY:
     994      if (format!=CHROMA_444)
     995      {
     996        // only 444 is handled.
     997        assert(format==CHROMA_444);
     998        exit(1);
     999      }
     1000
     1001      {
     1002        for(UInt comp=0; comp<numValidComp; comp++)
     1003        {
     1004          copyPlane(src, ComponentID(bIsForwards?0:comp), dest, ComponentID(comp));
     1005        }
     1006      }
     1007      break;
     1008    case IPCOLOURSPACE_YCbCrtoYCrCb:
     1009      {
     1010        for(UInt comp=0; comp<numValidComp; comp++)
     1011        {
     1012          copyPlane(src, ComponentID(comp), dest, ComponentID((numValidComp-comp)%numValidComp));
     1013        }
     1014      }
     1015      break;
     1016
     1017    case IPCOLOURSPACE_RGBtoGBR:
     1018      {
     1019        if (format!=CHROMA_444)
     1020        {
     1021          // only 444 is handled.
     1022          assert(format==CHROMA_444);
     1023          exit(1);
     1024        }
     1025
     1026        // channel re-mapping
     1027        for(UInt comp=0; comp<numValidComp; comp++)
     1028        {
     1029          const ComponentID compIDsrc=ComponentID((comp+1)%numValidComp);
     1030          const ComponentID compIDdst=ComponentID(comp);
     1031          copyPlane(src, bIsForwards?compIDsrc:compIDdst, dest, bIsForwards?compIDdst:compIDsrc);
     1032        }
     1033      }
     1034      break;
     1035
     1036    case IPCOLOURSPACE_UNCHANGED:
     1037    default:
     1038      {
     1039        for(UInt comp=0; comp<numValidComp; comp++)
     1040        {
     1041          copyPlane(src, ComponentID(comp), dest, ComponentID(comp));
     1042        }
     1043      }
     1044      break;
     1045  }
     1046}
Note: See TracChangeset for help on using the changeset viewer.