Index: branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.cpp
===================================================================
--- branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.cpp	(revision 1199)
+++ branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.cpp	(revision 1200)
@@ -2,7 +2,7 @@
  * License, included below. This software may be subject to other third party
  * and contributor rights, including patent rights, and no such rights are
- * granted under this license.  
- *
-* Copyright (c) 2010-2015, ITU/ISO/IEC
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2015, ITU/ISO/IEC
  * All rights reserved.
  *
@@ -42,4 +42,5 @@
 #include <fstream>
 #include <iostream>
+#include <memory.h>
 
 #include "TLibCommon/TComRom.h"
@@ -48,52 +49,7 @@
 using namespace std;
 
-/**
- * Perform division with rounding of all pixels in img by
- * 2<sup>shiftbits</sup>. All pixels are clipped to [minval, maxval]
- *
- * @param img        pointer to image to be transformed
- * @param stride     distance between vertically adjacent pixels of img.
- * @param width      width of active area in img.
- * @param height     height of active area in img.
- * @param shiftbits  number of rounding bits
- * @param minval     minimum clipping value
- * @param maxval     maximum clipping value
- */
-static void invScalePlane(Pel* img, UInt stride, UInt width, UInt height,
-                       UInt shiftbits, Pel minval, Pel maxval)
-{
-  Pel offset = 1 << (shiftbits-1);
-  for (UInt y = 0; y < height; y++)
-  {
-    for (UInt x = 0; x < width; x++)
-    {
-      Pel val = (img[x] + offset) >> shiftbits;
-      img[x] = Clip3(minval, maxval, val);
-    }
-    img += stride;
-  }
-}
-
-/**
- * Multiply all pixels in img by 2<sup>shiftbits</sup>.
- *
- * @param img        pointer to image to be transformed
- * @param stride     distance between vertically adjacent pixels of img.
- * @param width      width of active area in img.
- * @param height     height of active area in img.
- * @param shiftbits  number of bits to shift
- */
-static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
-                       UInt shiftbits)
-{
-  for (UInt y = 0; y < height; y++)
-  {
-    for (UInt x = 0; x < width; x++)
-    {
-      img[x] <<= shiftbits;
-    }
-    img += stride;
-  }
-}
+// ====================================================================================================================
+// Local Functions
+// ====================================================================================================================
 
 /**
@@ -112,19 +68,28 @@
  * @param maxval  maximum clipping value when dividing.
  */
-static void scalePlane(Pel* img, UInt stride, UInt width, UInt height,
-                       Int shiftbits, Pel minval, Pel maxval)
-{
-  if (shiftbits == 0)
-  {
-    return;
-  }
-
+static Void scalePlane(Pel* img, const UInt stride, const UInt width, const UInt height, Int shiftbits, Pel minval, Pel maxval)
+{
   if (shiftbits > 0)
   {
-    scalePlane(img, stride, width, height, shiftbits);
-  }
-  else
-  {
-    invScalePlane(img, stride, width, height, -shiftbits, minval, maxval);
+    for (UInt y = 0; y < height; y++, img+=stride)
+    {
+      for (UInt x = 0; x < width; x++)
+      {
+        img[x] <<= shiftbits;
+      }
+    }
+  }
+  else if (shiftbits < 0)
+  {
+    shiftbits=-shiftbits;
+
+    Pel rounding = 1 << (shiftbits-1);
+    for (UInt y = 0; y < height; y++, img+=stride)
+    {
+      for (UInt x = 0; x < width; x++)
+      {
+        img[x] = Clip3(minval, maxval, Pel((img[x] + rounding) >> shiftbits));
+      }
+    }
   }
 }
@@ -146,21 +111,36 @@
  *
  * \param pchFile          file name string
- * \param bWriteMode       file open mode: true=read, false=write
- * \param fileBitDepthY     bit-depth of input/output file data (luma component).
- * \param fileBitDepthC     bit-depth of input/output file data (chroma components).
- * \param internalBitDepthY bit-depth to scale image data to/from when reading/writing (luma component).
- * \param internalBitDepthC bit-depth to scale image data to/from when reading/writing (chroma components).
+ * \param bWriteMode       file open mode: true=write, false=read
+ * \param fileBitDepth     bit-depth array of input/output file data.
+ * \param MSBExtendedBitDepth
+ * \param internalBitDepth bit-depth array to scale image data to/from when reading/writing.
  */
-Void TVideoIOYuv::open( Char* pchFile, Bool bWriteMode, Int fileBitDepthY, Int fileBitDepthC, Int internalBitDepthY, Int internalBitDepthC)
-{
-  m_bitDepthShiftY = internalBitDepthY - fileBitDepthY;
-  m_bitDepthShiftC = internalBitDepthC - fileBitDepthC;
-  m_fileBitDepthY = fileBitDepthY;
-  m_fileBitDepthC = fileBitDepthC;
+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] )
+{
+  //NOTE: files cannot have bit depth greater than 16
+  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
+  {
+    m_fileBitdepth       [ch] = std::min<UInt>(fileBitDepth[ch], 16);
+    m_MSBExtendedBitDepth[ch] = MSBExtendedBitDepth[ch];
+    m_bitdepthShift      [ch] = internalBitDepth[ch] - m_MSBExtendedBitDepth[ch];
+
+    if (m_fileBitdepth[ch] > 16)
+    {
+      if (bWriteMode)
+      {
+        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;
+      }
+      else
+      {
+        std::cerr << "\nERROR: Cannot read a yuv file of bit depth greater than 16\n" << std::endl;
+        exit(0);
+      }
+    }
+  }
 
   if ( bWriteMode )
   {
     m_cHandle.open( pchFile, ios::binary | ios::out );
-    
+
     if( m_cHandle.fail() )
     {
@@ -172,5 +152,5 @@
   {
     m_cHandle.open( pchFile, ios::binary | ios::in );
-    
+
     if( m_cHandle.fail() )
     {
@@ -179,5 +159,5 @@
     }
   }
-  
+
   return;
 }
@@ -204,21 +184,39 @@
  * seekable, by consuming bytes.
  */
-void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height)
+Void TVideoIOYuv::skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format)
 {
   if (!numFrames)
+  {
     return;
-
-  const UInt wordsize = (m_fileBitDepthY > 8 || m_fileBitDepthC > 8) ? 2 : 1;
-  const streamoff framesize = wordsize * width * height * 3 / 2;
-  const streamoff offset = framesize * numFrames;
+  }
+
+  //------------------
+  //set the frame size according to the chroma format
+  streamoff frameSize = 0;
+  UInt wordsize=1; // default to 8-bit, unless a channel with more than 8-bits is detected.
+  for (UInt component = 0; component < getNumberValidComponents(format); component++)
+  {
+    ComponentID compID=ComponentID(component);
+    frameSize += (width >> getComponentScaleX(compID, format)) * (height >> getComponentScaleY(compID, format));
+    if (m_fileBitdepth[toChannelType(compID)] > 8)
+    {
+      wordsize=2;
+    }
+  }
+  frameSize *= wordsize;
+  //------------------
+
+  const streamoff offset = frameSize * numFrames;
 
   /* attempt to seek */
   if (!!m_cHandle.seekg(offset, ios::cur))
+  {
     return; /* success */
+  }
   m_cHandle.clear();
 
   /* fall back to consuming the input */
   Char buf[512];
-  const UInt offset_mod_bufsize = offset % sizeof(buf);
+  const streamoff offset_mod_bufsize = offset % sizeof(buf);
   for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf))
   {
@@ -233,58 +231,153 @@
  * either 8bit or 16bit little-endian lsb-aligned words.
  *
- * @param dst     destination image
- * @param fd      input file stream
- * @param is16bit true if input file carries > 8bit data, false otherwise.
- * @param stride  distance between vertically adjacent pixels of dst.
- * @param width   width of active area in dst.
- * @param height  height of active area in dst.
- * @param pad_x   length of horizontal padding.
- * @param pad_y   length of vertical padding.
+ * @param dst          destination image plane
+ * @param fd           input file stream
+ * @param is16bit      true if input file carries > 8bit data, false otherwise.
+ * @param stride444    distance between vertically adjacent pixels of dst.
+ * @param width444     width of active area in dst.
+ * @param height444    height of active area in dst.
+ * @param pad_x444     length of horizontal padding.
+ * @param pad_y444     length of vertical padding.
+ * @param compID       chroma component
+ * @param destFormat   chroma format of image
+ * @param fileFormat   chroma format of file
+ * @param fileBitDepth component bit depth in file
  * @return true for success, false in case of error
  */
-static Bool readPlane(Pel* dst, istream& fd, Bool is16bit,
-                      UInt stride,
-                      UInt width, UInt height,
-                      UInt pad_x, UInt pad_y)
-{
-  Int read_len = width * (is16bit ? 2 : 1);
-  UChar *buf = new UChar[read_len];
-  for (Int y = 0; y < height; y++)
-  {
-    fd.read(reinterpret_cast<Char*>(buf), read_len);
-    if (fd.eof() || fd.fail() )
-    {
-      delete[] buf;
-      return false;
-    }
-
-    if (!is16bit)
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        dst[x] = buf[x];
-      }
-    }
-    else
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        dst[x] = (buf[2*x+1] << 8) | buf[2*x];
-      }
-    }
-
-    for (Int x = width; x < width + pad_x; x++)
-    {
-      dst[x] = dst[width - 1];
-    }
-    dst += stride;
-  }
-  for (Int y = height; y < height + pad_y; y++)
-  {
-    for (Int x = 0; x < width + pad_x; x++)
-    {
-      dst[x] = (dst - stride)[x];
-    }
-    dst += stride;
+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)
+{
+  const UInt csx_file =getComponentScaleX(compID, fileFormat);
+  const UInt csy_file =getComponentScaleY(compID, fileFormat);
+  const UInt csx_dest =getComponentScaleX(compID, destFormat);
+  const UInt csy_dest =getComponentScaleY(compID, destFormat);
+
+  const UInt width_dest       = width444 >>csx_dest;
+  const UInt height_dest      = height444>>csy_dest;
+  const UInt pad_x_dest       = pad_x444>>csx_dest;
+  const UInt pad_y_dest       = pad_y444>>csy_dest;
+  const UInt stride_dest      = stride444>>csx_dest;
+
+  const UInt full_width_dest  = width_dest+pad_x_dest;
+  const UInt full_height_dest = height_dest+pad_y_dest;
+
+  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
+
+  UChar  *buf   = new UChar[stride_file];
+
+  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || destFormat==CHROMA_400))
+  {
+    if (destFormat!=CHROMA_400)
+    {
+      // set chrominance data to mid-range: (1<<(fileBitDepth-1))
+      const Pel value=Pel(1<<(fileBitDepth-1));
+      for (UInt y = 0; y < full_height_dest; y++, dst+=stride_dest)
+      {
+        for (UInt x = 0; x < full_width_dest; x++)
+        {
+          dst[x] = value;
+        }
+      }
+    }
+
+    if (fileFormat!=CHROMA_400)
+    {
+      const UInt height_file      = height444>>csy_file;
+      fd.seekg(height_file*stride_file, ios::cur);
+      if (fd.eof() || fd.fail() )
+      {
+        delete[] buf;
+        return false;
+      }
+    }
+  }
+  else
+  {
+    const UInt mask_y_file=(1<<csy_file)-1;
+    const UInt mask_y_dest=(1<<csy_dest)-1;
+    for(UInt y444=0; y444<height444; y444++)
+    {
+      if ((y444&mask_y_file)==0)
+      {
+        // read a new line
+        fd.read(reinterpret_cast<Char*>(buf), stride_file);
+        if (fd.eof() || fd.fail() )
+        {
+          delete[] buf;
+          return false;
+        }
+      }
+
+      if ((y444&mask_y_dest)==0)
+      {
+        // process current destination line
+        if (csx_file < csx_dest)
+        {
+          // eg file is 444, dest is 422.
+          const UInt sx=csx_dest-csx_file;
+          if (!is16bit)
+          {
+            for (UInt x = 0; x < width_dest; x++)
+            {
+              dst[x] = buf[x<<sx];
+            }
+          }
+          else
+          {
+            for (UInt x = 0; x < width_dest; x++)
+            {
+              dst[x] = Pel(buf[(x<<sx)*2+0]) | (Pel(buf[(x<<sx)*2+1])<<8);
+            }
+          }
+        }
+        else
+        {
+          // eg file is 422, dest is 444.
+          const UInt sx=csx_file-csx_dest;
+          if (!is16bit)
+          {
+            for (UInt x = 0; x < width_dest; x++)
+            {
+              dst[x] = buf[x>>sx];
+            }
+          }
+          else
+          {
+            for (UInt x = 0; x < width_dest; x++)
+            {
+              dst[x] = Pel(buf[(x>>sx)*2+0]) | (Pel(buf[(x>>sx)*2+1])<<8);
+            }
+          }
+        }
+
+        // process right hand side padding
+        const Pel val=dst[width_dest-1];
+        for (UInt x = width_dest; x < full_width_dest; x++)
+        {
+          dst[x] = val;
+        }
+
+        dst += stride_dest;
+      }
+    }
+
+    // process lower padding
+    for (UInt y = height_dest; y < full_height_dest; y++, dst+=stride_dest)
+    {
+      for (UInt x = 0; x < full_width_dest; x++)
+      {
+        dst[x] = (dst - stride_dest)[x];
+      }
+    }
   }
   delete[] buf;
@@ -293,45 +386,138 @@
 
 /**
- * Write width*height pixels info fd from src.
- *
- * @param fd      output file stream
- * @param src     source image
- * @param is16bit true if input file carries > 8bit data, false otherwise.
- * @param stride  distance between vertically adjacent pixels of src.
- * @param width   width of active area in src.
- * @param height  height of active area in src.
+ * Write an image plane (width444*height444 pixels) from src into output stream fd.
+ *
+ * @param fd         output file stream
+ * @param src        source image
+ * @param is16bit    true if input file carries > 8bit data, false otherwise.
+ * @param stride444  distance between vertically adjacent pixels of src.
+ * @param width444   width of active area in src.
+ * @param height444  height of active area in src.
+ * @param compID       chroma component
+ * @param srcFormat    chroma format of image
+ * @param fileFormat   chroma format of file
+ * @param fileBitDepth component bit depth in file
  * @return true for success, false in case of error
  */
 static Bool writePlane(ostream& fd, Pel* src, Bool is16bit,
-                       UInt stride,
-                       UInt width, UInt height)
-{
-  Int write_len = width * (is16bit ? 2 : 1);
-  UChar *buf = new UChar[write_len];
-  for (Int y = 0; y < height; y++)
-  {
-    if (!is16bit) 
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        buf[x] = (UChar) src[x];
-      }
-    }
-    else 
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        buf[2*x] = src[x] & 0xff;
-        buf[2*x+1] = (src[x] >> 8) & 0xff;
-      }
-    }
-
-    fd.write(reinterpret_cast<Char*>(buf), write_len);
-    if (fd.eof() || fd.fail() )
-    {
-      delete[] buf;
-      return false;
-    }
-    src += stride;
+                       UInt stride444,
+                       UInt width444, UInt height444,
+                       const ComponentID compID,
+                       const ChromaFormat srcFormat,
+                       const ChromaFormat fileFormat,
+                       const UInt fileBitDepth)
+{
+  const UInt csx_file =getComponentScaleX(compID, fileFormat);
+  const UInt csy_file =getComponentScaleY(compID, fileFormat);
+  const UInt csx_src  =getComponentScaleX(compID, srcFormat);
+  const UInt csy_src  =getComponentScaleY(compID, srcFormat);
+
+  const UInt stride_src      = stride444>>csx_src;
+
+  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
+  const UInt width_file       = width444 >>csx_file;
+  const UInt height_file      = height444>>csy_file;
+
+  UChar  *buf   = new UChar[stride_file];
+
+  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
+  {
+    if (fileFormat!=CHROMA_400)
+    {
+      const UInt value=1<<(fileBitDepth-1);
+
+      for(UInt y=0; y< height_file; y++)
+      {
+        if (!is16bit)
+        {
+          UChar val(value);
+          for (UInt x = 0; x < width_file; x++)
+          {
+            buf[x]=val;
+          }
+        }
+        else
+        {
+          UShort val(value);
+          for (UInt x = 0; x < width_file; x++)
+          {
+            buf[2*x+0]= (val>>0) & 0xff;
+            buf[2*x+1]= (val>>8) & 0xff;
+          }
+        }
+
+        fd.write(reinterpret_cast<Char*>(buf), stride_file);
+        if (fd.eof() || fd.fail() )
+        {
+          delete[] buf;
+          return false;
+        }
+      }
+    }
+  }
+  else
+  {
+    const UInt mask_y_file=(1<<csy_file)-1;
+    const UInt mask_y_src =(1<<csy_src )-1;
+    for(UInt y444=0; y444<height444; y444++)
+    {
+      if ((y444&mask_y_file)==0)
+      {
+        // write a new line
+        if (csx_file < csx_src)
+        {
+          // eg file is 444, source is 422.
+          const UInt sx=csx_src-csx_file;
+          if (!is16bit)
+          {
+            for (UInt x = 0; x < width_file; x++)
+            {
+              buf[x] = (UChar)(src[x>>sx]);
+            }
+          }
+          else
+          {
+            for (UInt x = 0; x < width_file; x++)
+            {
+              buf[2*x  ] = (src[x>>sx]>>0) & 0xff;
+              buf[2*x+1] = (src[x>>sx]>>8) & 0xff;
+            }
+          }
+        }
+        else
+        {
+          // eg file is 422, src is 444.
+          const UInt sx=csx_file-csx_src;
+          if (!is16bit)
+          {
+            for (UInt x = 0; x < width_file; x++)
+            {
+              buf[x] = (UChar)(src[x<<sx]);
+            }
+          }
+          else
+          {
+            for (UInt x = 0; x < width_file; x++)
+            {
+              buf[2*x  ] = (src[x<<sx]>>0) & 0xff;
+              buf[2*x+1] = (src[x<<sx]>>8) & 0xff;
+            }
+          }
+        }
+
+        fd.write(reinterpret_cast<Char*>(buf), stride_file);
+        if (fd.eof() || fd.fail() )
+        {
+          delete[] buf;
+          return false;
+        }
+      }
+
+      if ((y444&mask_y_src)==0)
+      {
+        src += stride_src;
+      }
+
+    }
   }
   delete[] buf;
@@ -340,43 +526,140 @@
 
 static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit,
-                       UInt stride,
-                       UInt width, UInt height, bool isTff)
-{
-  Int write_len = width * (is16bit ? 2 : 1)*2;
-  UChar *buf = new UChar[write_len];
-  for (Int y = 0; y < height; y++)
-  {
-    if (!is16bit)
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        buf[x] = isTff ? (UChar) top[x] : (UChar) bottom[x];
-        buf[width+x] = isTff ? (UChar) bottom[x] : (UChar) top[x];
-      }
-    }
-    else
-    {
-      for (Int x = 0; x < width; x++)
-      {
-        buf[2*x] = isTff ? top[x] & 0xff : bottom[x] & 0xff;
-        buf[2*x+1] = isTff ? (top[x] >> 8) & 0xff : (bottom[x] >> 8) & 0xff;
-        
-        buf[width+2*x] = isTff ? bottom[x] & 0xff : top[x] & 0xff;
-        buf[width+2*x+1] = isTff ? (bottom[x] >> 8) & 0xff : (top[x] >> 8) & 0xff;
-      }
-    }
-    
-    fd.write(reinterpret_cast<Char*>(buf), write_len);
-    if (fd.eof() || fd.fail() )
-    {
-      delete[] buf;
-      return false;
-    }
-    top += stride;
-    bottom += stride;
+                       UInt stride444,
+                       UInt width444, UInt height444,
+                       const ComponentID compID,
+                       const ChromaFormat srcFormat,
+                       const ChromaFormat fileFormat,
+                       const UInt fileBitDepth, const Bool isTff)
+{
+  const UInt csx_file =getComponentScaleX(compID, fileFormat);
+  const UInt csy_file =getComponentScaleY(compID, fileFormat);
+  const UInt csx_src  =getComponentScaleX(compID, srcFormat);
+  const UInt csy_src  =getComponentScaleY(compID, srcFormat);
+
+  const UInt stride_src      = stride444>>csx_src;
+
+  const UInt stride_file      = (width444 * (is16bit ? 2 : 1)) >> csx_file;
+  const UInt width_file       = width444 >>csx_file;
+  const UInt height_file      = height444>>csy_file;
+
+  UChar  *buf   = new UChar[stride_file * 2];
+
+  if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400))
+  {
+    if (fileFormat!=CHROMA_400)
+    {
+      const UInt value=1<<(fileBitDepth-1);
+
+      for(UInt y=0; y< height_file; y++)
+      {
+        for (UInt field = 0; field < 2; field++)
+        {
+          UChar *fieldBuffer = buf + (field * stride_file);
+
+          if (!is16bit)
+          {
+            UChar val(value);
+            for (UInt x = 0; x < width_file; x++)
+            {
+              fieldBuffer[x]=val;
+            }
+          }
+          else
+          {
+            UShort val(value);
+            for (UInt x = 0; x < width_file; x++)
+            {
+              fieldBuffer[2*x+0]= (val>>0) & 0xff;
+              fieldBuffer[2*x+1]= (val>>8) & 0xff;
+            }
+          }
+        }
+
+        fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
+        if (fd.eof() || fd.fail() )
+        {
+          delete[] buf;
+          return false;
+        }
+      }
+    }
+  }
+  else
+  {
+    const UInt mask_y_file=(1<<csy_file)-1;
+    const UInt mask_y_src =(1<<csy_src )-1;
+    for(UInt y444=0; y444<height444; y444++)
+    {
+      if ((y444&mask_y_file)==0)
+      {
+        for (UInt field = 0; field < 2; field++)
+        {
+          UChar *fieldBuffer = buf + (field * stride_file);
+          Pel   *src         = (((field == 0) && isTff) || ((field == 1) && (!isTff))) ? top : bottom;
+
+          // write a new line
+          if (csx_file < csx_src)
+          {
+            // eg file is 444, source is 422.
+            const UInt sx=csx_src-csx_file;
+            if (!is16bit)
+            {
+              for (UInt x = 0; x < width_file; x++)
+              {
+                fieldBuffer[x] = (UChar)(src[x>>sx]);
+              }
+            }
+            else
+            {
+              for (UInt x = 0; x < width_file; x++)
+              {
+                fieldBuffer[2*x  ] = (src[x>>sx]>>0) & 0xff;
+                fieldBuffer[2*x+1] = (src[x>>sx]>>8) & 0xff;
+              }
+            }
+          }
+          else
+          {
+            // eg file is 422, src is 444.
+            const UInt sx=csx_file-csx_src;
+            if (!is16bit)
+            {
+              for (UInt x = 0; x < width_file; x++)
+              {
+                fieldBuffer[x] = (UChar)(src[x<<sx]);
+              }
+            }
+            else
+            {
+              for (UInt x = 0; x < width_file; x++)
+              {
+                fieldBuffer[2*x  ] = (src[x<<sx]>>0) & 0xff;
+                fieldBuffer[2*x+1] = (src[x<<sx]>>8) & 0xff;
+              }
+            }
+          }
+        }
+
+        fd.write(reinterpret_cast<Char*>(buf), (stride_file * 2));
+        if (fd.eof() || fd.fail() )
+        {
+          delete[] buf;
+          return false;
+        }
+      }
+
+      if ((y444&mask_y_src)==0)
+      {
+        top    += stride_src;
+        bottom += stride_src;
+      }
+
+    }
   }
   delete[] buf;
   return true;
 }
+
 /**
  * Read one Y'CbCr frame, performing any required input scaling to change
@@ -388,64 +671,71 @@
  * file had been provided at the lower-bitdepth compliant to Rec601/709.
  *
- * @param pPicYuv      input picture YUV buffer class pointer
- * @param aiPad        source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
+ * @param pPicYuvUser      input picture YUV buffer class pointer
+ * @param pPicYuvTrueOrg
+ * @param ipcsc
+ * @param aiPad            source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
+ * @param format           chroma format
  * @return true for success, false in case of error
  */
-Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuv, Int aiPad[2] )
+Bool TVideoIOYuv::read ( TComPicYuv*  pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format, const Bool bClipToRec709 )
 {
   // check end-of-file
-  if ( isEof() ) return false;
-  
-  Int   iStride = pPicYuv->getStride();
-  
+  if ( isEof() )
+  {
+    return false;
+  }
+  TComPicYuv *pPicYuv=pPicYuvTrueOrg;
+  if (format>=NUM_CHROMA_FORMAT)
+  {
+    format=pPicYuv->getChromaFormat();
+  }
+
+  Bool is16bit = false;
+
+  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
+  {
+    if (m_fileBitdepth[ch] > 8)
+    {
+      is16bit=true;
+    }
+  }
+
+  const UInt stride444      = pPicYuv->getStride(COMPONENT_Y);
+
   // compute actual YUV width & height excluding padding size
-  UInt pad_h = aiPad[0];
-  UInt pad_v = aiPad[1];
-  UInt width_full = pPicYuv->getWidth();
-  UInt height_full = pPicYuv->getHeight();
-  UInt width  = width_full - pad_h;
-  UInt height = height_full - pad_v;
-  Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
-
-  Int desired_bitdepthY = m_fileBitDepthY + m_bitDepthShiftY;
-  Int desired_bitdepthC = m_fileBitDepthC + m_bitDepthShiftC;
-  Pel minvalY = 0;
-  Pel minvalC = 0;
-  Pel maxvalY = (1 << desired_bitdepthY) - 1;
-  Pel maxvalC = (1 << desired_bitdepthC) - 1;
-#if CLIP_TO_709_RANGE
-  if (m_bitdepthShiftY < 0 && desired_bitdepthY >= 8)
-  {
-    /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-    minvalY = 1 << (desired_bitdepthY - 8);
-    maxvalY = (0xff << (desired_bitdepthY - 8)) -1;
-  }
-  if (m_bitdepthShiftC < 0 && desired_bitdepthC >= 8)
-  {
-    /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-    minvalC = 1 << (desired_bitdepthC - 8);
-    maxvalC = (0xff << (desired_bitdepthC - 8)) -1;
-  }
-#endif
-  
-  if (! readPlane(pPicYuv->getLumaAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
-    return false;
-  scalePlane(pPicYuv->getLumaAddr(), iStride, width_full, height_full, m_bitDepthShiftY, minvalY, maxvalY);
-
-  iStride >>= 1;
-  width_full >>= 1;
-  height_full >>= 1;
-  width >>= 1;
-  height >>= 1;
-  pad_h >>= 1;
-  pad_v >>= 1;
-
-  if (! readPlane(pPicYuv->getCbAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
-    return false;
-  scalePlane(pPicYuv->getCbAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
-
-  if (! readPlane(pPicYuv->getCrAddr(), m_cHandle, is16bit, iStride, width, height, pad_h, pad_v))
-    return false;
-  scalePlane(pPicYuv->getCrAddr(), iStride, width_full, height_full, m_bitDepthShiftC, minvalC, maxvalC);
+  const UInt pad_h444       = aiPad[0];
+  const UInt pad_v444       = aiPad[1];
+
+  const UInt width_full444  = pPicYuv->getWidth(COMPONENT_Y);
+  const UInt height_full444 = pPicYuv->getHeight(COMPONENT_Y);
+
+  const UInt width444       = width_full444 - pad_h444;
+  const UInt height444      = height_full444 - pad_v444;
+
+  for(UInt comp=0; comp<MAX_NUM_COMPONENT; comp++)
+  {
+    const ComponentID compID = ComponentID(comp);
+    const ChannelType chType=toChannelType(compID);
+
+    const Int desired_bitdepth = m_MSBExtendedBitDepth[chType] + m_bitdepthShift[chType];
+
+    const Bool b709Compliance=(bClipToRec709) && (m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
+    const Pel minval = b709Compliance? ((   1 << (desired_bitdepth - 8))   ) : 0;
+    const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
+
+    if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType]))
+    {
+      return false;
+    }
+
+    if (compID < pPicYuv->getNumberValidComponents() )
+    {
+      const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat());
+      const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat());
+      scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval);
+    }
+  }
+
+  ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, true);
 
   return true;
@@ -456,203 +746,301 @@
  * assumed to be at TVideoIO::m_fileBitdepth depth.
  *
- * @param pPicYuv     input picture YUV buffer class pointer
- * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
+ * @param pPicYuvUser      input picture YUV buffer class pointer
+ * @param ipCSC
+ * @param confLeft         conformance window left border
+ * @param confRight        conformance window right border
+ * @param confTop          conformance window top border
+ * @param confBottom       conformance window bottom border
+ * @param format           chroma format
  * @return true for success, false in case of error
  */
-Bool TVideoIOYuv::write( TComPicYuv* pPicYuv, Int confLeft, Int confRight, Int confTop, Int confBottom )
-{
+Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool bClipToRec709 )
+{
+  TComPicYuv cPicYuvCSCd;
+  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
+  {
+    cPicYuvCSCd.create(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat(), pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), 0, false);
+    ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, false);
+  }
+  TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd;
+
   // compute actual YUV frame size excluding padding size
-  Int   iStride = pPicYuv->getStride();
-  UInt  width  = pPicYuv->getWidth()  - confLeft - confRight;
-  UInt  height = pPicYuv->getHeight() - confTop  - confBottom;
-  Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
+  const Int   iStride444 = pPicYuv->getStride(COMPONENT_Y);
+  const UInt width444  = pPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight;
+  const UInt height444 = pPicYuv->getHeight(COMPONENT_Y) -  confTop  - confBottom;
+  Bool is16bit = false;
+  Bool nonZeroBitDepthShift=false;
+
+  if ((width444 == 0) || (height444 == 0))
+  {
+    printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
+  }
+
+  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
+  {
+    if (m_fileBitdepth[ch] > 8)
+    {
+      is16bit=true;
+    }
+    if (m_bitdepthShift[ch] != 0)
+    {
+      nonZeroBitDepthShift=true;
+    }
+  }
+
   TComPicYuv *dstPicYuv = NULL;
   Bool retval = true;
-
-  if ((width==0)||(height==0))
-  {
-    printf ("\nWarning: writing %d x %d luma sample output picture!", width, height);
-  }
-
-  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
+  if (format>=NUM_CHROMA_FORMAT)
+  {
+    format=pPicYuv->getChromaFormat();
+  }
+
+  if (nonZeroBitDepthShift)
   {
     dstPicYuv = new TComPicYuv;
-    dstPicYuv->create( pPicYuv->getWidth(), pPicYuv->getHeight(), 1, 1, 0 );
+    dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), 0, false );
     pPicYuv->copyToPic(dstPicYuv);
 
-    Pel minvalY = 0;
-    Pel minvalC = 0;
-    Pel maxvalY = (1 << m_fileBitDepthY) - 1;
-    Pel maxvalC = (1 << m_fileBitDepthC) - 1;
-#if CLIP_TO_709_RANGE
-    if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)
-    {
-      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-      minvalY = 1 << (m_fileBitDepthY - 8);
-      maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;
-    }
-    if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)
-    {
-      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-      minvalC = 1 << (m_fileBitDepthC - 8);
-      maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;
-    }
+    for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
+    {
+      const ComponentID compID=ComponentID(comp);
+      const ChannelType ch=toChannelType(compID);
+      const Bool b709Compliance = bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
+      const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
+      const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
+
+      scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
+    }
+  }
+  else
+  {
+    dstPicYuv = pPicYuv;
+  }
+#if NH_3D
+  for(UInt comp=0; retval && comp< ::getNumberValidComponents(format); comp++)
+#else
+  for(UInt comp=0; retval && comp<dstPicYuv->getNumberValidComponents(); comp++)
 #endif
-    scalePlane(dstPicYuv->getLumaAddr(), dstPicYuv->getStride(), dstPicYuv->getWidth(), dstPicYuv->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
-    scalePlane(dstPicYuv->getCbAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-    scalePlane(dstPicYuv->getCrAddr(), dstPicYuv->getCStride(), dstPicYuv->getWidth()>>1, dstPicYuv->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-  }
-  else
-  {
-    dstPicYuv = pPicYuv;
-  }
-  // location of upper left pel in a plane
-  Int planeOffset = confLeft + confTop * iStride;
-  
-  if (! writePlane(m_cHandle, dstPicYuv->getLumaAddr() + planeOffset, is16bit, iStride, width, height))
-  {
-    retval=false; 
-    goto exit;
-  }
-
-  width >>= 1;
-  height >>= 1;
-  iStride >>= 1;
-  confLeft >>= 1;
-  confRight >>= 1;
-  confTop >>= 1;
-  confBottom >>= 1;
-
-  planeOffset = confLeft + confTop * iStride;
-
-  if (! writePlane(m_cHandle, dstPicYuv->getCbAddr() + planeOffset, is16bit, iStride, width, height))
-  {
-    retval=false; 
-    goto exit;
-  }
-  if (! writePlane(m_cHandle, dstPicYuv->getCrAddr() + planeOffset, is16bit, iStride, width, height))
-  {
-    retval=false; 
-    goto exit;
-  }
-  
-exit:
-  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
+  {
+    const ComponentID compID = ComponentID(comp);
+    const ChannelType ch=toChannelType(compID);
+    const UInt csx = pPicYuv->getComponentScaleX(compID);
+    const UInt csy = pPicYuv->getComponentScaleY(compID);
+    const Int planeOffset =  (confLeft>>csx) + (confTop>>csy) * pPicYuv->getStride(compID);
+    if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, iStride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch]))
+    {
+      retval=false;
+    }
+  }
+
+  if (nonZeroBitDepthShift)
   {
     dstPicYuv->destroy();
     delete dstPicYuv;
-  }  
+  }
+
+  cPicYuvCSCd.destroy();
+
   return retval;
 }
 
-
-/**
- * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is
- * assumed to be at TVideoIO::m_fileBitdepth depth.
- *
- * @param pPicTop     input top field YUV buffer class pointer
- * @param pPicBottom  input bottom field YUV buffer class pointer
- * @param aiPad       source padding size, aiPad[0] = horizontal, aiPad[1] = vertical
- * @return true for success, false in case of error
- */
-Bool TVideoIOYuv::write( TComPicYuv* pPicTop, TComPicYuv* pPicBottom, Int cropLeft, Int cropRight, Int cropTop, Int cropBottom , bool isTff)
-{
-  // compute actual YUV frame size excluding padding size
-  Int   iStride = pPicTop->getStride();
-  UInt  width  = pPicTop->getWidth()  - cropLeft - cropRight;
-  UInt  height = pPicTop->getHeight() - cropTop  - cropBottom;
-  Bool is16bit = m_fileBitDepthY > 8 || m_fileBitDepthC > 8;
-  
-  TComPicYuv *dstPicTop = NULL;
-  TComPicYuv *dstPicBottom = NULL;
-  
+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 )
+{
+
+  TComPicYuv cPicYuvTopCSCd;
+  TComPicYuv cPicYuvBottomCSCd;
+  if (ipCSC!=IPCOLOURSPACE_UNCHANGED)
+  {
+    cPicYuvTopCSCd   .create(pPicYuvUserTop   ->getWidth(COMPONENT_Y), pPicYuvUserTop   ->getHeight(COMPONENT_Y), pPicYuvUserTop   ->getChromaFormat(), pPicYuvUserTop   ->getWidth(COMPONENT_Y), pPicYuvUserTop   ->getHeight(COMPONENT_Y), 0, false);
+    cPicYuvBottomCSCd.create(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat(), pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), 0, false);
+    ColourSpaceConvert(*pPicYuvUserTop,    cPicYuvTopCSCd,    ipCSC, false);
+    ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, false);
+  }
+  TComPicYuv *pPicYuvTop    = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop    : &cPicYuvTopCSCd;
+  TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd;
+
+  Bool is16bit = false;
+  Bool nonZeroBitDepthShift=false;
+
+  for(UInt ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
+  {
+    if (m_fileBitdepth[ch] > 8)
+    {
+      is16bit=true;
+    }
+    if (m_bitdepthShift[ch] != 0)
+    {
+      nonZeroBitDepthShift=true;
+    }
+  }
+
+  TComPicYuv *dstPicYuvTop    = NULL;
+  TComPicYuv *dstPicYuvBottom = NULL;
+
+  for (UInt field = 0; field < 2; field++)
+  {
+    TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom;
+
+    if (format>=NUM_CHROMA_FORMAT)
+    {
+      format=pPicYuv->getChromaFormat();
+    }
+
+    TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom;
+
+    if (nonZeroBitDepthShift)
+    {
+      dstPicYuv = new TComPicYuv;
+      dstPicYuv->create( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat(), pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), 0, false );
+      pPicYuv->copyToPic(dstPicYuv);
+
+      for(UInt comp=0; comp<dstPicYuv->getNumberValidComponents(); comp++)
+      {
+        const ComponentID compID=ComponentID(comp);
+        const ChannelType ch=toChannelType(compID);
+        const Bool b709Compliance=bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
+        const Pel minval = b709Compliance? ((   1 << (m_MSBExtendedBitDepth[ch] - 8))   ) : 0;
+        const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1;
+
+        scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval);
+      }
+    }
+    else
+    {
+      dstPicYuv = pPicYuv;
+    }
+  }
+
   Bool retval = true;
-  
-  if ((width==0)||(height==0))
-  {
-    printf ("\nWarning: writing %d x %d luma sample output picture!", width, height);
-  }
-  
-  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
-  {
-    dstPicTop = new TComPicYuv;
-    dstPicTop->create( pPicTop->getWidth(), pPicTop->getHeight(), 1, 1, 0 );
-    pPicTop->copyToPic(dstPicTop);
-    
-    dstPicBottom = new TComPicYuv;
-    dstPicBottom->create( pPicBottom->getWidth(), pPicBottom->getHeight(), 1, 1, 0 );
-    pPicBottom->copyToPic(dstPicBottom);
-    
-    Pel minvalY = 0;
-    Pel minvalC = 0;
-    Pel maxvalY = (1 << m_fileBitDepthY) - 1;
-    Pel maxvalC = (1 << m_fileBitDepthC) - 1;
-#if CLIP_TO_709_RANGE
-    if (-m_bitDepthShiftY < 0 && m_fileBitDepthY >= 8)
-    {
-      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-      minvalY = 1 << (m_fileBitDepthY - 8);
-      maxvalY = (0xff << (m_fileBitDepthY - 8)) -1;
-    }
-    if (-m_bitDepthShiftC < 0 && m_fileBitDepthC >= 8)
-    {
-      /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
-      minvalC = 1 << (m_fileBitDepthC - 8);
-      maxvalC = (0xff << (m_fileBitDepthC - 8)) -1;
-    }
-#endif
-    scalePlane(dstPicTop->getLumaAddr(), dstPicTop->getStride(), dstPicTop->getWidth(), dstPicTop->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
-    scalePlane(dstPicTop->getCbAddr(), dstPicTop->getCStride(), dstPicTop->getWidth()>>1, dstPicTop->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-    scalePlane(dstPicTop->getCrAddr(), dstPicTop->getCStride(), dstPicTop->getWidth()>>1, dstPicTop->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-    
-    scalePlane(dstPicBottom->getLumaAddr(), dstPicBottom->getStride(), dstPicBottom->getWidth(), dstPicBottom->getHeight(), -m_bitDepthShiftY, minvalY, maxvalY);
-    scalePlane(dstPicBottom->getCbAddr(), dstPicBottom->getCStride(), dstPicBottom->getWidth()>>1, dstPicBottom->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-    scalePlane(dstPicBottom->getCrAddr(), dstPicBottom->getCStride(), dstPicBottom->getWidth()>>1, dstPicBottom->getHeight()>>1, -m_bitDepthShiftC, minvalC, maxvalC);
-  }
-  else
-  {
-    dstPicTop = pPicTop;
-    dstPicBottom = pPicBottom;
-  }
-  // location of upper left pel in a plane
-  Int planeOffset = 0; //cropLeft + cropTop * iStride;
-  //Write luma
-  if (! writeField(m_cHandle, dstPicTop->getLumaAddr() + planeOffset,  dstPicBottom->getLumaAddr() + planeOffset, is16bit, iStride, width, height, isTff))
-  {
-    retval=false;
-    goto exit;
-  }
-  
-  width >>= 1;
-  height >>= 1;
-  iStride >>= 1;
-  cropLeft >>= 1;
-  cropRight >>= 1;
-  
-  planeOffset = 0; // cropLeft + cropTop * iStride;
-  
-  //Write chroma U
-  if (! writeField(m_cHandle, dstPicTop->getCbAddr() + planeOffset, dstPicBottom->getCbAddr() + planeOffset, is16bit, iStride, width, height, isTff))
-  {
-    retval=false;
-    goto exit;
-  }
-  
-  //Write chroma V
-  if (! writeField(m_cHandle, dstPicTop->getCrAddr() + planeOffset, dstPicBottom->getCrAddr() + planeOffset, is16bit, iStride, width, height, isTff))
-    
-  {
-    retval=false;
-    goto exit;
-  }
-  
-exit:
-  if (m_bitDepthShiftY != 0 || m_bitDepthShiftC != 0)
-  {
-    dstPicTop->destroy();
-    delete dstPicTop;
-    dstPicBottom->destroy();
-    delete dstPicBottom;
-  }  
+
+  assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents());
+  assert(dstPicYuvTop->getChromaFormat()          == dstPicYuvBottom->getChromaFormat()         );
+  assert(dstPicYuvTop->getWidth(COMPONENT_Y)      == dstPicYuvBottom->getWidth(COMPONENT_Y)    );
+  assert(dstPicYuvTop->getHeight(COMPONENT_Y)     == dstPicYuvBottom->getHeight(COMPONENT_Y)    );
+  assert(dstPicYuvTop->getStride(COMPONENT_Y)     == dstPicYuvBottom->getStride(COMPONENT_Y)    );
+
+  for(UInt comp=0; retval && comp<dstPicYuvTop->getNumberValidComponents(); comp++)
+  {
+    const ComponentID compID = ComponentID(comp);
+    const ChannelType ch=toChannelType(compID);
+
+    assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID));
+    assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID));
+    assert(dstPicYuvTop->getStride         (compID) == dstPicYuvBottom->getStride         (compID));
+
+    const UInt width444   = dstPicYuvTop->getWidth(COMPONENT_Y)  - (confLeft + confRight);
+    const UInt height444  = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom);
+
+    if ((width444 == 0) || (height444 == 0))
+    {
+      printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444);
+    }
+
+    const UInt csx = dstPicYuvTop->getComponentScaleX(compID);
+    const UInt csy = dstPicYuvTop->getComponentScaleY(compID);
+    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
+
+    if (! writeField(m_cHandle,
+                     (dstPicYuvTop   ->getAddr(compID) + planeOffset),
+                     (dstPicYuvBottom->getAddr(compID) + planeOffset),
+                     is16bit,
+                     dstPicYuvTop->getStride(COMPONENT_Y),
+                     width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff))
+    {
+      retval=false;
+    }
+  }
+
+  if (nonZeroBitDepthShift)
+  {
+    dstPicYuvTop->destroy();
+    dstPicYuvBottom->destroy();
+    delete dstPicYuvTop;
+    delete dstPicYuvBottom;
+  }
+
+  cPicYuvTopCSCd.destroy();
+  cPicYuvBottomCSCd.destroy();
+
   return retval;
 }
+
+static Void
+copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane)
+{
+  const UInt width=src.getWidth(srcPlane);
+  const UInt height=src.getHeight(srcPlane);
+  assert(dest.getWidth(destPlane) == width);
+  assert(dest.getHeight(destPlane) == height);
+  const Pel *pSrc=src.getAddr(srcPlane);
+  Pel *pDest=dest.getAddr(destPlane);
+  const UInt strideSrc=src.getStride(srcPlane);
+  const UInt strideDest=dest.getStride(destPlane);
+  for(UInt y=0; y<height; y++, pSrc+=strideSrc, pDest+=strideDest)
+  {
+    memcpy(pDest, pSrc, width*sizeof(Pel));
+  }
+}
+
+// static member
+Void TVideoIOYuv::ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, Bool bIsForwards)
+{
+  const ChromaFormat  format=src.getChromaFormat();
+  const UInt          numValidComp=src.getNumberValidComponents();
+
+  switch (conversion)
+  {
+    case IPCOLOURSPACE_YCbCrtoYYY:
+      if (format!=CHROMA_444)
+      {
+        // only 444 is handled.
+        assert(format==CHROMA_444);
+        exit(1);
+      }
+
+      {
+        for(UInt comp=0; comp<numValidComp; comp++)
+        {
+          copyPlane(src, ComponentID(bIsForwards?0:comp), dest, ComponentID(comp));
+        }
+      }
+      break;
+    case IPCOLOURSPACE_YCbCrtoYCrCb:
+      {
+        for(UInt comp=0; comp<numValidComp; comp++)
+        {
+          copyPlane(src, ComponentID(comp), dest, ComponentID((numValidComp-comp)%numValidComp));
+        }
+      }
+      break;
+
+    case IPCOLOURSPACE_RGBtoGBR:
+      {
+        if (format!=CHROMA_444)
+        {
+          // only 444 is handled.
+          assert(format==CHROMA_444);
+          exit(1);
+        }
+
+        // channel re-mapping
+        for(UInt comp=0; comp<numValidComp; comp++)
+        {
+          const ComponentID compIDsrc=ComponentID((comp+1)%numValidComp);
+          const ComponentID compIDdst=ComponentID(comp);
+          copyPlane(src, bIsForwards?compIDsrc:compIDdst, dest, bIsForwards?compIDdst:compIDsrc);
+        }
+      }
+      break;
+
+    case IPCOLOURSPACE_UNCHANGED:
+    default:
+      {
+        for(UInt comp=0; comp<numValidComp; comp++)
+        {
+          copyPlane(src, ComponentID(comp), dest, ComponentID(comp));
+        }
+      }
+      break;
+  }
+}
Index: branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.h
===================================================================
--- branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.h	(revision 1199)
+++ branches/HTM-14.1-update-dev0/source/Lib/TLibVideoIO/TVideoIOYuv.h	(revision 1200)
@@ -2,7 +2,7 @@
  * License, included below. This software may be subject to other third party
  * and contributor rights, including patent rights, and no such rights are
- * granted under this license.  
+ * granted under this license.
  *
-* Copyright (c) 2010-2015, ITU/ISO/IEC
+ * Copyright (c) 2010-2015, ITU/ISO/IEC
  * All rights reserved.
  *
@@ -56,25 +56,34 @@
 private:
   fstream   m_cHandle;                                      ///< file handle
-  Int m_fileBitDepthY; ///< bitdepth of input/output video file luma component
-  Int m_fileBitDepthC; ///< bitdepth of input/output video file chroma component
-  Int m_bitDepthShiftY;  ///< number of bits to increase or decrease luma by before/after write/read
-  Int m_bitDepthShiftC;  ///< number of bits to increase or decrease chroma by before/after write/read
-  
+  Int       m_fileBitdepth[MAX_NUM_CHANNEL_TYPE]; ///< bitdepth of input/output video file
+  Int       m_MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE];  ///< bitdepth after addition of MSBs (with value 0)
+  Int       m_bitdepthShift[MAX_NUM_CHANNEL_TYPE];  ///< number of bits to increase or decrease image by before/after write/read
+
 public:
   TVideoIOYuv()           {}
   virtual ~TVideoIOYuv()  {}
-  
-  Void  open  ( Char* pchFile, Bool bWriteMode, Int fileBitDepthY, Int fileBitDepthC, Int internalBitDepthY, Int internalBitDepthC ); ///< open or create file
+
+  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
   Void  close ();                                           ///< close file
 
-  void skipFrames(UInt numFrames, UInt width, UInt height);
-  
-  Bool  read  ( TComPicYuv*   pPicYuv, Int aiPad[2] );     ///< read  one YUV frame with padding parameter
-  Bool  write( TComPicYuv*    pPicYuv, Int confLeft=0, Int confRight=0, Int confTop=0, Int confBottom=0 );
-  Bool  write( TComPicYuv*    pPicYuv, TComPicYuv*    pPicYuv2, Int confLeft=0, Int confRight=0, Int confTop=0, Int confBottom=0  , bool isTff=false); 
-  
+  Void skipFrames(UInt numFrames, UInt width, UInt height, ChromaFormat format);
+
+  // if fileFormat<NUM_CHROMA_FORMAT, the format of the file is that format specified, else it is the format of the TComPicYuv.
+
+
+  // If fileFormat=NUM_CHROMA_FORMAT, use the format defined by pPicYuvTrueOrg
+  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
+
+  // If fileFormat=NUM_CHROMA_FORMAT, use the format defined by pPicYuv
+  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
+
+  // If fileFormat=NUM_CHROMA_FORMAT, use the format defined by pPicYuvTop and pPicYuvBottom
+  Bool  write ( TComPicYuv* pPicYuvTop, TComPicYuv* pPicYuvBottom, const InputColourSpaceConversion ipCSC, Int confLeft=0, Int confRight=0, Int confTop=0, Int confBottom=0, ChromaFormat fileFormat=NUM_CHROMA_FORMAT, const Bool isTff=false, const Bool bClipToRec709=false);
+  static Void ColourSpaceConvert(const TComPicYuv &src, TComPicYuv &dest, const InputColourSpaceConversion conversion, Bool bIsForwards);
+
   Bool  isEof ();                                           ///< check for end-of-file
   Bool  isFail();                                           ///< check for failure
-  
+
+
 };
 
