<div dir="ltr"><div>Thanks, Steve. I have this monochrome patch from Fabrice, an SEI update from Luca of libav, and numerous asm patches from the dev team waiting to be pushed in. <br><br></div>Once the scenecut bug is solved, I plan to tag 1.8 - and push these in. 1.9 should probably be tagged in another 3-4 weeks, since there are many features which will not make it into 1.8. <br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 10:20 PM, Steve Borho <span dir="ltr"><<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Steve Borho <<a href="mailto:steve@borho.org">steve@borho.org</a>><br>
# Date 1442853618 18000<br>
#      Mon Sep 21 11:40:18 2015 -0500<br>
# Node ID 5602b4bc1fec175e7c5bf14ef18978a50e3bc07f<br>
# Parent  f8b8ebdc54578e6735216d8b9abce5ba80c05bd8<br>
add support for Monochrome color space (X265_CSP_I400)<br>
<br>
This patch was extracted from changes made by Fabrice Bellard for BPG<br>
<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/deblock.cpp<br>
--- a/source/common/deblock.cpp Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/deblock.cpp Mon Sep 21 11:40:18 2015 -0500<br>
@@ -109,7 +109,7 @@<br>
     for (uint32_t e = 0; e < numUnits; e += partIdxIncr)<br>
     {<br>
         edgeFilterLuma(cu, absPartIdx, depth, dir, e, blockStrength);<br>
-        if (!((e0 + e) & chromaMask))<br>
+        if (cu->m_chromaFormat != X265_CSP_I400 && !((e0 + e) & chromaMask))<br>
             edgeFilterChroma(cu, absPartIdx, depth, dir, e, blockStrength);<br>
     }<br>
 }<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/frame.cpp<br>
--- a/source/common/frame.cpp   Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/frame.cpp   Mon Sep 21 11:40:18 2015 -0500<br>
@@ -73,14 +73,20 @@<br>
          * end of the picture accessing uninitialized pixels */<br>
         int maxHeight = sps.numCuInHeight * g_maxCUSize;<br>
         memset(m_reconPic->m_picOrg[0], 0, sizeof(pixel) * m_reconPic->m_stride * maxHeight);<br>
-        memset(m_reconPic->m_picOrg[1], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>
-        memset(m_reconPic->m_picOrg[2], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>
+        if (m_reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            memset(m_reconPic->m_picOrg[1], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>
+            memset(m_reconPic->m_picOrg[2], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>
+        }<br>
<br>
         /* use pre-calculated cu/pu offsets cached in the SPS structure */<br>
-        m_reconPic->m_cuOffsetC = sps.cuOffsetC;<br>
         m_reconPic->m_cuOffsetY = sps.cuOffsetY;<br>
-        m_reconPic->m_buOffsetC = sps.buOffsetC;<br>
         m_reconPic->m_buOffsetY = sps.buOffsetY;<br>
+        if (m_reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            m_reconPic->m_cuOffsetC = sps.cuOffsetC;<br>
+            m_reconPic->m_buOffsetC = sps.buOffsetC;<br>
+        }<br>
     }<br>
     return ok;<br>
 }<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/param.cpp<br>
--- a/source/common/param.cpp   Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/param.cpp   Mon Sep 21 11:40:18 2015 -0500<br>
@@ -1069,7 +1069,7 @@<br>
<br>
     CHECK(param->sourceWidth < (int)param->maxCUSize || param->sourceHeight < (int)param->maxCUSize,<br>
           "Picture size must be at least one CTU");<br>
-    CHECK(param->internalCsp < X265_CSP_I420 || X265_CSP_I444 < param->internalCsp,<br>
+    CHECK(param->internalCsp < X265_CSP_I400 || X265_CSP_I444 < param->internalCsp,<br>
           "Color space must be i420, i422, or i444");<br>
     CHECK(param->sourceWidth & !!CHROMA_H_SHIFT(param->internalCsp),<br>
           "Picture width must be an integer multiple of the specified chroma subsampling");<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/picyuv.cpp<br>
--- a/source/common/picyuv.cpp  Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/picyuv.cpp  Mon Sep 21 11:40:18 2015 -0500<br>
@@ -70,12 +70,16 @@<br>
     int maxHeight = numCuInHeight * g_maxCUSize;<br>
<br>
     CHECKED_MALLOC(m_picBuf[0], pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));<br>
-    CHECKED_MALLOC(m_picBuf[1], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));<br>
-    CHECKED_MALLOC(m_picBuf[2], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));<br>
+    m_picOrg[0] = m_picBuf[0] + m_lumaMarginY   * m_stride  + m_lumaMarginX;<br>
<br>
-    m_picOrg[0] = m_picBuf[0] + m_lumaMarginY   * m_stride  + m_lumaMarginX;<br>
-    m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;<br>
-    m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;<br>
+    if (m_picCsp != X265_CSP_I400)<br>
+    {<br>
+        CHECKED_MALLOC(m_picBuf[1], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));<br>
+        CHECKED_MALLOC(m_picBuf[2], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));<br>
+<br>
+        m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;<br>
+        m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;<br>
+    }<br>
<br>
     return true;<br>
<br>
@@ -90,24 +94,32 @@<br>
 {<br>
     uint32_t numPartitions = 1 << (g_unitSizeDepth * 2);<br>
     CHECKED_MALLOC(m_cuOffsetY, intptr_t, sps.numCuInWidth * sps.numCuInHeight);<br>
-    CHECKED_MALLOC(m_cuOffsetC, intptr_t, sps.numCuInWidth * sps.numCuInHeight);<br>
+    if (m_picCsp != X265_CSP_I400)<br>
+    {<br>
+        CHECKED_MALLOC(m_cuOffsetC, intptr_t, sps.numCuInWidth * sps.numCuInHeight);<br>
+    }<br>
     for (uint32_t cuRow = 0; cuRow < sps.numCuInHeight; cuRow++)<br>
     {<br>
         for (uint32_t cuCol = 0; cuCol < sps.numCuInWidth; cuCol++)<br>
         {<br>
             m_cuOffsetY[cuRow * sps.numCuInWidth + cuCol] = m_stride * cuRow * g_maxCUSize + cuCol * g_maxCUSize;<br>
-            m_cuOffsetC[cuRow * sps.numCuInWidth + cuCol] = m_strideC * cuRow * (g_maxCUSize >> m_vChromaShift) + cuCol * (g_maxCUSize >> m_hChromaShift);<br>
+            if (m_picCsp != X265_CSP_I400)<br>
+                m_cuOffsetC[cuRow * sps.numCuInWidth + cuCol] = m_strideC * cuRow * (g_maxCUSize >> m_vChromaShift) + cuCol * (g_maxCUSize >> m_hChromaShift);<br>
         }<br>
     }<br>
<br>
     CHECKED_MALLOC(m_buOffsetY, intptr_t, (size_t)numPartitions);<br>
-    CHECKED_MALLOC(m_buOffsetC, intptr_t, (size_t)numPartitions);<br>
+    if (m_picCsp != X265_CSP_I400)<br>
+    {<br>
+        CHECKED_MALLOC(m_buOffsetC, intptr_t, (size_t)numPartitions);<br>
+    }<br>
     for (uint32_t idx = 0; idx < numPartitions; ++idx)<br>
     {<br>
         intptr_t x = g_zscanToPelX[idx];<br>
         intptr_t y = g_zscanToPelY[idx];<br>
         m_buOffsetY[idx] = m_stride * y + x;<br>
-        m_buOffsetC[idx] = m_strideC * (y >> m_vChromaShift) + (x >> m_hChromaShift);<br>
+        if (m_picCsp != X265_CSP_I400)<br>
+            m_buOffsetC[idx] = m_strideC * (y >> m_vChromaShift) + (x >> m_hChromaShift);<br>
     }<br>
<br>
     return true;<br>
@@ -168,8 +180,11 @@<br>
             int shift = (X265_DEPTH - 8);<br>
<br>
             primitives.planecopy_cp(yChar, pic.stride[0] / sizeof(*yChar), yPixel, m_stride, width, height, shift);<br>
-            primitives.planecopy_cp(uChar, pic.stride[1] / sizeof(*uChar), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);<br>
-            primitives.planecopy_cp(vChar, pic.stride[2] / sizeof(*vChar), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);<br>
+            if (m_picCsp != X265_CSP_I400)<br>
+            {<br>
+                primitives.planecopy_cp(uChar, pic.stride[1] / sizeof(*uChar), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);<br>
+                primitives.planecopy_cp(vChar, pic.stride[2] / sizeof(*vChar), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift);<br>
+            }<br>
         }<br>
 #else /* Case for (X265_DEPTH == 8) */<br>
         // TODO: Does we need this path? may merge into above in future<br>
@@ -190,15 +205,18 @@<br>
                 yChar += pic.stride[0] / sizeof(*yChar);<br>
             }<br>
<br>
-            for (int r = 0; r < height >> m_vChromaShift; r++)<br>
+            if (m_picCsp != X265_CSP_I400)<br>
             {<br>
-                memcpy(uPixel, uChar, (width >> m_hChromaShift) * sizeof(pixel));<br>
-                memcpy(vPixel, vChar, (width >> m_hChromaShift) * sizeof(pixel));<br>
+                for (int r = 0; r < height >> m_vChromaShift; r++)<br>
+                {<br>
+                    memcpy(uPixel, uChar, (width >> m_hChromaShift) * sizeof(pixel));<br>
+                    memcpy(vPixel, vChar, (width >> m_hChromaShift) * sizeof(pixel));<br>
<br>
-                uPixel += m_strideC;<br>
-                vPixel += m_strideC;<br>
-                uChar += pic.stride[1] / sizeof(*uChar);<br>
-                vChar += pic.stride[2] / sizeof(*vChar);<br>
+                    uPixel += m_strideC;<br>
+                    vPixel += m_strideC;<br>
+                    uChar += pic.stride[1] / sizeof(*uChar);<br>
+                    vChar += pic.stride[2] / sizeof(*vChar);<br>
+                }<br>
             }<br>
         }<br>
 #endif /* (X265_DEPTH > 8) */<br>
@@ -220,15 +238,21 @@<br>
         {<br>
             /* shift right and mask pixels to final size */<br>
             primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>
-            primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
-            primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+            if (m_picCsp != X265_CSP_I400)<br>
+            {<br>
+                primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+                primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+            }<br>
         }<br>
         else /* Case for (pic.bitDepth <= X265_DEPTH) */<br>
         {<br>
             /* shift left and mask pixels to final size */<br>
             primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>
-            primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
-            primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+            if (m_picCsp != X265_CSP_I400)<br>
+            {<br>
+                primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+                primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>
+            }<br>
         }<br>
     }<br>
<br>
@@ -250,30 +274,36 @@<br>
         Y += m_stride;<br>
     }<br>
<br>
-    for (int r = 0; r < height >> m_vChromaShift; r++)<br>
+    if (m_picCsp != X265_CSP_I400)<br>
     {<br>
-        for (int x = 0; x < padx >> m_hChromaShift; x++)<br>
+        for (int r = 0; r < height >> m_vChromaShift; r++)<br>
         {<br>
-            U[(width >> m_hChromaShift) + x] = U[(width >> m_hChromaShift) - 1];<br>
-            V[(width >> m_hChromaShift) + x] = V[(width >> m_hChromaShift) - 1];<br>
+            for (int x = 0; x < padx >> m_hChromaShift; x++)<br>
+            {<br>
+                U[(width >> m_hChromaShift) + x] = U[(width >> m_hChromaShift) - 1];<br>
+                V[(width >> m_hChromaShift) + x] = V[(width >> m_hChromaShift) - 1];<br>
+            }<br>
+<br>
+            U += m_strideC;<br>
+            V += m_strideC;<br>
         }<br>
-<br>
-        U += m_strideC;<br>
-        V += m_strideC;<br>
     }<br>
<br>
     /* extend the bottom if height was not multiple of the minimum CU size */<br>
     Y = m_picOrg[0] + (height - 1) * m_stride;<br>
-    U = m_picOrg[1] + ((height >> m_vChromaShift) - 1) * m_strideC;<br>
-    V = m_picOrg[2] + ((height >> m_vChromaShift) - 1) * m_strideC;<br>
<br>
     for (int i = 1; i <= pady; i++)<br>
         memcpy(Y + i * m_stride, Y, (width + padx) * sizeof(pixel));<br>
<br>
-    for (int j = 1; j <= pady >> m_vChromaShift; j++)<br>
+    if (m_picCsp != X265_CSP_I400)<br>
     {<br>
-        memcpy(U + j * m_strideC, U, ((width + padx) >> m_hChromaShift) * sizeof(pixel));<br>
-        memcpy(V + j * m_strideC, V, ((width + padx) >> m_hChromaShift) * sizeof(pixel));<br>
+        U = m_picOrg[1] + ((height >> m_vChromaShift) - 1) * m_strideC;<br>
+        V = m_picOrg[2] + ((height >> m_vChromaShift) - 1) * m_strideC;<br>
+        for (int j = 1; j <= pady >> m_vChromaShift; j++)<br>
+        {<br>
+            memcpy(U + j * m_strideC, U, ((width + padx) >> m_hChromaShift) * sizeof(pixel));<br>
+            memcpy(V + j * m_strideC, V, ((width + padx) >> m_hChromaShift) * sizeof(pixel));<br>
+        }<br>
     }<br>
 }<br>
<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/predict.cpp<br>
--- a/source/common/predict.cpp Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/predict.cpp Mon Sep 21 11:40:18 2015 -0500<br>
@@ -85,6 +85,14 @@<br>
     int refIdx0 = cu.m_refIdx[0][pu.puAbsPartIdx];<br>
     int refIdx1 = cu.m_refIdx[1][pu.puAbsPartIdx];<br>
<br>
+    /* XXX: disable chroma at a higher level ? */<br>
+    if (cu.m_chromaFormat == X265_CSP_I400)<br>
+    {<br>
+        bChroma = false;<br>
+        if (!bLuma)<br>
+            return;<br>
+    }<br>
+<br>
     if (cu.m_slice->isInterP())<br>
     {<br>
         /* P Slice */<br>
@@ -99,7 +107,8 @@<br>
<br>
         if (cu.m_slice->m_pps->bUseWeightPred && wp0->bPresentFlag)<br>
         {<br>
-            for (int plane = 0; plane < 3; plane++)<br>
+            int numPlanes = cu.m_chromaFormat == X265_CSP_I400 ? 1 : 3;<br>
+            for (int plane = 0; plane < numPlanes; plane++)<br>
             {<br>
                 wv0[plane].w      = wp0[plane].inputWeight;<br>
                 wv0[plane].offset = wp0[plane].inputOffset * (1 << (X265_DEPTH - 8));<br>
@@ -136,13 +145,14 @@<br>
<br>
         if (cu.m_slice->m_pps->bUseWeightedBiPred)<br>
         {<br>
+            int numPlanes = cu.m_chromaFormat == X265_CSP_I400 ? 1 : 3;<br>
+<br>
             pwp0 = refIdx0 >= 0 ? cu.m_slice->m_weightPredTable[0][refIdx0] : NULL;<br>
             pwp1 = refIdx1 >= 0 ? cu.m_slice->m_weightPredTable[1][refIdx1] : NULL;<br>
-<br>
             if (pwp0 && pwp1 && (pwp0->bPresentFlag || pwp1->bPresentFlag))<br>
             {<br>
                 /* biprediction weighting */<br>
-                for (int plane = 0; plane < 3; plane++)<br>
+                for (int plane = 0; plane < numPlanes; plane++)<br>
                 {<br>
                     wv0[plane].w = pwp0[plane].inputWeight;<br>
                     wv0[plane].o = pwp0[plane].inputOffset * (1 << (X265_DEPTH - 8));<br>
@@ -159,7 +169,7 @@<br>
             {<br>
                 /* uniprediction weighting, always outputs to wv0 */<br>
                 const WeightParam* pwp = (refIdx0 >= 0) ? pwp0 : pwp1;<br>
-                for (int plane = 0; plane < 3; plane++)<br>
+                for (int plane = 0; plane < numPlanes; plane++)<br>
                 {<br>
                     wv0[plane].w = pwp[plane].inputWeight;<br>
                     wv0[plane].offset = pwp[plane].inputOffset * (1 << (X265_DEPTH - 8));<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/shortyuv.cpp<br>
--- a/source/common/shortyuv.cpp        Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/shortyuv.cpp        Mon Sep 21 11:40:18 2015 -0500<br>
@@ -40,19 +40,26 @@<br>
 bool ShortYuv::create(uint32_t size, int csp)<br>
 {<br>
     m_csp = csp;<br>
-    m_hChromaShift = CHROMA_H_SHIFT(csp);<br>
-    m_vChromaShift = CHROMA_V_SHIFT(csp);<br>
-<br>
     m_size = size;<br>
-    m_csize = size >> m_hChromaShift;<br>
<br>
     size_t sizeL = size * size;<br>
-    size_t sizeC = sizeL >> (m_hChromaShift + m_vChromaShift);<br>
-    X265_CHECK((sizeC & 15) == 0, "invalid size");<br>
-<br>
-    CHECKED_MALLOC(m_buf[0], int16_t, sizeL + sizeC * 2);<br>
-    m_buf[1] = m_buf[0] + sizeL;<br>
-    m_buf[2] = m_buf[0] + sizeL + sizeC;<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        m_hChromaShift = CHROMA_H_SHIFT(csp);<br>
+        m_vChromaShift = CHROMA_V_SHIFT(csp);<br>
+        m_csize = size >> m_hChromaShift;<br>
+        size_t sizeC = sizeL >> (m_hChromaShift + m_vChromaShift);<br>
+        X265_CHECK((sizeC & 15) == 0, "invalid size");<br>
+        CHECKED_MALLOC(m_buf[0], int16_t, sizeL + sizeC * 2);<br>
+        m_buf[1] = m_buf[0] + sizeL;<br>
+        m_buf[2] = m_buf[0] + sizeL + sizeC;<br>
+    }<br>
+    else<br>
+    {<br>
+        m_csize = 0;<br>
+        CHECKED_MALLOC(m_buf[0], int16_t, sizeL);<br>
+    }<br>
+<br>
     return true;<br>
<br>
 fail:<br>
@@ -67,16 +74,22 @@<br>
 void ShortYuv::clear()<br>
 {<br>
     memset(m_buf[0], 0, (m_size  * m_size) *  sizeof(int16_t));<br>
-    memset(m_buf[1], 0, (m_csize * m_csize) * sizeof(int16_t));<br>
-    memset(m_buf[2], 0, (m_csize * m_csize) * sizeof(int16_t));<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        memset(m_buf[1], 0, (m_csize * m_csize) * sizeof(int16_t));<br>
+        memset(m_buf[2], 0, (m_csize * m_csize) * sizeof(int16_t));<br>
+    }<br>
 }<br>
<br>
 void ShortYuv::subtract(const Yuv& srcYuv0, const Yuv& srcYuv1, uint32_t log2Size)<br>
 {<br>
     const int sizeIdx = log2Size - 2;<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[sizeIdx].sub_ps(m_buf[0], m_size, srcYuv0.m_buf[0], srcYuv1.m_buf[0], srcYuv0.m_size, srcYuv1.m_size);<br>
-    primitives.chroma[m_csp].cu[sizeIdx].sub_ps(m_buf[1], m_csize, srcYuv0.m_buf[1], srcYuv1.m_buf[1], srcYuv0.m_csize, srcYuv1.m_csize);<br>
-    primitives.chroma[m_csp].cu[sizeIdx].sub_ps(m_buf[2], m_csize, srcYuv0.m_buf[2], srcYuv1.m_buf[2], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        primitives.chroma[m_csp].cu[sizeIdx].sub_ps(m_buf[1], m_csize, srcYuv0.m_buf[1], srcYuv1.m_buf[1], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+        primitives.chroma[m_csp].cu[sizeIdx].sub_ps(m_buf[2], m_csize, srcYuv0.m_buf[2], srcYuv1.m_buf[2], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+    }<br>
 }<br>
<br>
 void ShortYuv::copyPartToPartLuma(ShortYuv& dstYuv, uint32_t absPartIdx, uint32_t log2Size) const<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/common/yuv.cpp<br>
--- a/source/common/yuv.cpp     Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/common/yuv.cpp     Mon Sep 21 11:40:18 2015 -0500<br>
@@ -84,10 +84,13 @@<br>
     pixel* dstY = dstPic.getLumaAddr(cuAddr, absPartIdx);<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[m_part].copy_pp(dstY, dstPic.m_stride, m_buf[0], m_size);<br>
<br>
-    pixel* dstU = dstPic.getCbAddr(cuAddr, absPartIdx);<br>
-    pixel* dstV = dstPic.getCrAddr(cuAddr, absPartIdx);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(dstU, dstPic.m_strideC, m_buf[1], m_csize);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(dstV, dstPic.m_strideC, m_buf[2], m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        pixel* dstU = dstPic.getCbAddr(cuAddr, absPartIdx);<br>
+        pixel* dstV = dstPic.getCrAddr(cuAddr, absPartIdx);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(dstU, dstPic.m_strideC, m_buf[1], m_csize);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(dstV, dstPic.m_strideC, m_buf[2], m_csize);<br>
+    }<br>
 }<br>
<br>
 void Yuv::copyFromPicYuv(const PicYuv& srcPic, uint32_t cuAddr, uint32_t absPartIdx)<br>
@@ -95,10 +98,13 @@<br>
     const pixel* srcY = srcPic.getLumaAddr(cuAddr, absPartIdx);<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[m_part].copy_pp(m_buf[0], m_size, srcY, srcPic.m_stride);<br>
<br>
-    const pixel* srcU = srcPic.getCbAddr(cuAddr, absPartIdx);<br>
-    const pixel* srcV = srcPic.getCrAddr(cuAddr, absPartIdx);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[1], m_csize, srcU, srcPic.m_strideC);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[2], m_csize, srcV, srcPic.m_strideC);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        const pixel* srcU = srcPic.getCbAddr(cuAddr, absPartIdx);<br>
+        const pixel* srcV = srcPic.getCrAddr(cuAddr, absPartIdx);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[1], m_csize, srcU, srcPic.m_strideC);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[2], m_csize, srcV, srcPic.m_strideC);<br>
+    }<br>
 }<br>
<br>
 void Yuv::copyFromYuv(const Yuv& srcYuv)<br>
@@ -106,8 +112,11 @@<br>
     X265_CHECK(m_size >= srcYuv.m_size, "invalid size\n");<br>
<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[m_part].copy_pp(m_buf[0], m_size, srcYuv.m_buf[0], srcYuv.m_size);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[1], m_csize, srcYuv.m_buf[1], srcYuv.m_csize);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[2], m_csize, srcYuv.m_buf[2], srcYuv.m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[1], m_csize, srcYuv.m_buf[1], srcYuv.m_csize);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(m_buf[2], m_csize, srcYuv.m_buf[2], srcYuv.m_csize);<br>
+    }<br>
 }<br>
<br>
 /* This version is intended for use by ME, which required FENC_STRIDE for luma fenc pixels */<br>
@@ -132,10 +141,13 @@<br>
     pixel* dstY = dstYuv.getLumaAddr(absPartIdx);<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[m_part].copy_pp(dstY, dstYuv.m_size, m_buf[0], m_size);<br>
<br>
-    pixel* dstU = dstYuv.getCbAddr(absPartIdx);<br>
-    pixel* dstV = dstYuv.getCrAddr(absPartIdx);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(dstU, dstYuv.m_csize, m_buf[1], m_csize);<br>
-    primitives.chroma[m_csp].cu[m_part].copy_pp(dstV, dstYuv.m_csize, m_buf[2], m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        pixel* dstU = dstYuv.getCbAddr(absPartIdx);<br>
+        pixel* dstV = dstYuv.getCrAddr(absPartIdx);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(dstU, dstYuv.m_csize, m_buf[1], m_csize);<br>
+        primitives.chroma[m_csp].cu[m_part].copy_pp(dstV, dstYuv.m_csize, m_buf[2], m_csize);<br>
+    }<br>
 }<br>
<br>
 void Yuv::copyPartToYuv(Yuv& dstYuv, uint32_t absPartIdx) const<br>
@@ -144,19 +156,25 @@<br>
     pixel* dstY = dstYuv.m_buf[0];<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[dstYuv.m_part].copy_pp(dstY, dstYuv.m_size, srcY, m_size);<br>
<br>
-    pixel* srcU = m_buf[1] + getChromaAddrOffset(absPartIdx);<br>
-    pixel* srcV = m_buf[2] + getChromaAddrOffset(absPartIdx);<br>
-    pixel* dstU = dstYuv.m_buf[1];<br>
-    pixel* dstV = dstYuv.m_buf[2];<br>
-    primitives.chroma[m_csp].cu[dstYuv.m_part].copy_pp(dstU, dstYuv.m_csize, srcU, m_csize);<br>
-    primitives.chroma[m_csp].cu[dstYuv.m_part].copy_pp(dstV, dstYuv.m_csize, srcV, m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        pixel* srcU = m_buf[1] + getChromaAddrOffset(absPartIdx);<br>
+        pixel* srcV = m_buf[2] + getChromaAddrOffset(absPartIdx);<br>
+        pixel* dstU = dstYuv.m_buf[1];<br>
+        pixel* dstV = dstYuv.m_buf[2];<br>
+        primitives.chroma[m_csp].cu[dstYuv.m_part].copy_pp(dstU, dstYuv.m_csize, srcU, m_csize);<br>
+        primitives.chroma[m_csp].cu[dstYuv.m_part].copy_pp(dstV, dstYuv.m_csize, srcV, m_csize);<br>
+    }<br>
 }<br>
<br>
 void Yuv::addClip(const Yuv& srcYuv0, const ShortYuv& srcYuv1, uint32_t log2SizeL)<br>
 {<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[log2SizeL - 2].add_ps(m_buf[0], m_size, srcYuv0.m_buf[0], srcYuv1.m_buf[0], srcYuv0.m_size, srcYuv1.m_size);<br>
-    primitives.chroma[m_csp].cu[log2SizeL - 2].add_ps(m_buf[1], m_csize, srcYuv0.m_buf[1], srcYuv1.m_buf[1], srcYuv0.m_csize, srcYuv1.m_csize);<br>
-    primitives.chroma[m_csp].cu[log2SizeL - 2].add_ps(m_buf[2], m_csize, srcYuv0.m_buf[2], srcYuv1.m_buf[2], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        primitives.chroma[m_csp].cu[log2SizeL - 2].add_ps(m_buf[1], m_csize, srcYuv0.m_buf[1], srcYuv1.m_buf[1], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+        primitives.chroma[m_csp].cu[log2SizeL - 2].add_ps(m_buf[2], m_csize, srcYuv0.m_buf[2], srcYuv1.m_buf[2], srcYuv0.m_csize, srcYuv1.m_csize);<br>
+    }<br>
 }<br>
<br>
 void Yuv::addAvg(const ShortYuv& srcYuv0, const ShortYuv& srcYuv1, uint32_t absPartIdx, uint32_t width, uint32_t height, bool bLuma, bool bChroma)<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/entropy.cpp<br>
--- a/source/encoder/entropy.cpp        Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/entropy.cpp        Mon Sep 21 11:40:18 2015 -0500<br>
@@ -430,7 +430,8 @@<br>
     if (slice.m_sps->bUseSAO)<br>
     {<br>
         WRITE_FLAG(saoParam->bSaoFlag[0], "slice_sao_luma_flag");<br>
-        WRITE_FLAG(saoParam->bSaoFlag[1], "slice_sao_chroma_flag");<br>
+        if (slice.m_sps->chromaFormatIdc != X265_CSP_I400)<br>
+            WRITE_FLAG(saoParam->bSaoFlag[1], "slice_sao_chroma_flag");<br>
     }<br>
<br>
     // check if numRefIdx match the defaults (1, hard-coded in PPS). If not, override<br>
@@ -723,19 +724,23 @@<br>
     uint32_t hChromaShift = cu.m_hChromaShift;<br>
     uint32_t vChromaShift = cu.m_vChromaShift;<br>
     bool bSmallChroma = (log2CurSize - hChromaShift) < 2;<br>
-    if (!curDepth || !bSmallChroma)<br>
+<br>
+    if (cu.m_chromaFormat != X265_CSP_I400)<br>
     {<br>
-        if (!curDepth || cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth - 1))<br>
-            codeQtCbfChroma(cu, absPartIdx, TEXT_CHROMA_U, curDepth, !subdiv);<br>
-        if (!curDepth || cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth - 1))<br>
-            codeQtCbfChroma(cu, absPartIdx, TEXT_CHROMA_V, curDepth, !subdiv);<br>
+        if (!curDepth || !bSmallChroma)<br>
+        {<br>
+            if (!curDepth || cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth - 1))<br>
+                codeQtCbfChroma(cu, absPartIdx, TEXT_CHROMA_U, curDepth, !subdiv);<br>
+            if (!curDepth || cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth - 1))<br>
+                codeQtCbfChroma(cu, absPartIdx, TEXT_CHROMA_V, curDepth, !subdiv);<br>
+        }<br>
+        else<br>
+        {<br>
+            X265_CHECK(cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth) == cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth - 1), "chroma xform size match failure\n");<br>
+            X265_CHECK(cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth) == cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth - 1), "chroma xform size match failure\n");<br>
+        }<br>
     }<br>
-    else<br>
-    {<br>
-        X265_CHECK(cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth) == cu.getCbf(absPartIdx, TEXT_CHROMA_U, curDepth - 1), "chroma xform size match failure\n");<br>
-        X265_CHECK(cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth) == cu.getCbf(absPartIdx, TEXT_CHROMA_V, curDepth - 1), "chroma xform size match failure\n");<br>
-    }<br>
-<br>
+<br>
     if (subdiv)<br>
     {<br>
         --log2CurSize;<br>
@@ -782,6 +787,9 @@<br>
             return;<br>
     }<br>
<br>
+    if (cu.m_chromaFormat == X265_CSP_I400)<br>
+        return;<br>
+<br>
     if (bSmallChroma)<br>
     {<br>
         if ((absPartIdx & 3) != 3)<br>
@@ -1011,7 +1019,7 @@<br>
 void Entropy::codePredWeightTable(const Slice& slice)<br>
 {<br>
     const WeightParam *wp;<br>
-    bool            bChroma      = true; // 4:0:0 not yet supported<br>
+    bool            bChroma      = (slice.m_sps->chromaFormatIdc != X265_CSP_I400);<br>
     bool            bDenomCoded  = false;<br>
     int             numRefDirs   = slice.m_sliceType == B_SLICE ? 2 : 1;<br>
     uint32_t        totalSignalledWeightFlags = 0;<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/framefilter.cpp<br>
--- a/source/encoder/framefilter.cpp    Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/framefilter.cpp    Mon Sep 21 11:40:18 2015 -0500<br>
@@ -167,25 +167,31 @@<br>
<br>
     // Border extend Left and Right<br>
     primitives.extendRowBorder(reconPic->getLumaAddr(lineStartCUAddr), reconPic->m_stride, reconPic->m_picWidth, realH, reconPic->m_lumaMarginX);<br>
-    primitives.extendRowBorder(reconPic->getCbAddr(lineStartCUAddr), reconPic->m_strideC, reconPic->m_picWidth >> m_hChromaShift, realH >> m_vChromaShift, reconPic->m_chromaMarginX);<br>
-    primitives.extendRowBorder(reconPic->getCrAddr(lineStartCUAddr), reconPic->m_strideC, reconPic->m_picWidth >> m_hChromaShift, realH >> m_vChromaShift, reconPic->m_chromaMarginX);<br>
+    if (reconPic->m_picCsp != X265_CSP_I400)<br>
+    {<br>
+        primitives.extendRowBorder(reconPic->getCbAddr(lineStartCUAddr), reconPic->m_strideC, reconPic->m_picWidth >> m_hChromaShift, realH >> m_vChromaShift, reconPic->m_chromaMarginX);<br>
+        primitives.extendRowBorder(reconPic->getCrAddr(lineStartCUAddr), reconPic->m_strideC, reconPic->m_picWidth >> m_hChromaShift, realH >> m_vChromaShift, reconPic->m_chromaMarginX);<br>
+    }<br>
<br>
     // Border extend Top<br>
     if (!row)<br>
     {<br>
         const intptr_t stride = reconPic->m_stride;<br>
-        const intptr_t strideC = reconPic->m_strideC;<br>
         pixel *pixY = reconPic->getLumaAddr(lineStartCUAddr) - reconPic->m_lumaMarginX;<br>
-        pixel *pixU = reconPic->getCbAddr(lineStartCUAddr) - reconPic->m_chromaMarginX;<br>
-        pixel *pixV = reconPic->getCrAddr(lineStartCUAddr) - reconPic->m_chromaMarginX;<br>
<br>
         for (uint32_t y = 0; y < reconPic->m_lumaMarginY; y++)<br>
             memcpy(pixY - (y + 1) * stride, pixY, stride * sizeof(pixel));<br>
<br>
-        for (uint32_t y = 0; y < reconPic->m_chromaMarginY; y++)<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
         {<br>
-            memcpy(pixU - (y + 1) * strideC, pixU, strideC * sizeof(pixel));<br>
-            memcpy(pixV - (y + 1) * strideC, pixV, strideC * sizeof(pixel));<br>
+            const intptr_t strideC = reconPic->m_strideC;<br>
+            pixel *pixU = reconPic->getCbAddr(lineStartCUAddr) - reconPic->m_chromaMarginX;<br>
+            pixel *pixV = reconPic->getCrAddr(lineStartCUAddr) - reconPic->m_chromaMarginX;<br>
+            for (uint32_t y = 0; y < reconPic->m_chromaMarginY; y++)<br>
+            {<br>
+                memcpy(pixU - (y + 1) * strideC, pixU, strideC * sizeof(pixel));<br>
+                memcpy(pixV - (y + 1) * strideC, pixV, strideC * sizeof(pixel));<br>
+            }<br>
         }<br>
     }<br>
<br>
@@ -193,17 +199,20 @@<br>
     if (row == m_numRows - 1)<br>
     {<br>
         const intptr_t stride = reconPic->m_stride;<br>
-        const intptr_t strideC = reconPic->m_strideC;<br>
         pixel *pixY = reconPic->getLumaAddr(lineStartCUAddr) - reconPic->m_lumaMarginX + (realH - 1) * stride;<br>
-        pixel *pixU = reconPic->getCbAddr(lineStartCUAddr) - reconPic->m_chromaMarginX + ((realH >> m_vChromaShift) - 1) * strideC;<br>
-        pixel *pixV = reconPic->getCrAddr(lineStartCUAddr) - reconPic->m_chromaMarginX + ((realH >> m_vChromaShift) - 1) * strideC;<br>
         for (uint32_t y = 0; y < reconPic->m_lumaMarginY; y++)<br>
             memcpy(pixY + (y + 1) * stride, pixY, stride * sizeof(pixel));<br>
<br>
-        for (uint32_t y = 0; y < reconPic->m_chromaMarginY; y++)<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
         {<br>
-            memcpy(pixU + (y + 1) * strideC, pixU, strideC * sizeof(pixel));<br>
-            memcpy(pixV + (y + 1) * strideC, pixV, strideC * sizeof(pixel));<br>
+            const intptr_t strideC = reconPic->m_strideC;<br>
+            pixel *pixU = reconPic->getCbAddr(lineStartCUAddr) - reconPic->m_chromaMarginX + ((realH >> m_vChromaShift) - 1) * strideC;<br>
+            pixel *pixV = reconPic->getCrAddr(lineStartCUAddr) - reconPic->m_chromaMarginX + ((realH >> m_vChromaShift) - 1) * strideC;<br>
+            for (uint32_t y = 0; y < reconPic->m_chromaMarginY; y++)<br>
+            {<br>
+                memcpy(pixU + (y + 1) * strideC, pixU, strideC * sizeof(pixel));<br>
+                memcpy(pixV + (y + 1) * strideC, pixV, strideC * sizeof(pixel));<br>
+            }<br>
         }<br>
     }<br>
<br>
@@ -220,16 +229,19 @@<br>
         uint32_t height = getCUHeight(row);<br>
<br>
         uint64_t ssdY = computeSSD(fencPic->getLumaAddr(cuAddr), reconPic->getLumaAddr(cuAddr), stride, width, height);<br>
-        height >>= m_vChromaShift;<br>
-        width  >>= m_hChromaShift;<br>
-        stride = reconPic->m_strideC;<br>
+        m_frameEncoder->m_SSDY += ssdY;<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            height >>= m_vChromaShift;<br>
+            width  >>= m_hChromaShift;<br>
+            stride = reconPic->m_strideC;<br>
+<br>
+            uint64_t ssdU = computeSSD(fencPic->getCbAddr(cuAddr), reconPic->getCbAddr(cuAddr), stride, width, height);<br>
+            uint64_t ssdV = computeSSD(fencPic->getCrAddr(cuAddr), reconPic->getCrAddr(cuAddr), stride, width, height);<br>
<br>
-        uint64_t ssdU = computeSSD(fencPic->getCbAddr(cuAddr), reconPic->getCbAddr(cuAddr), stride, width, height);<br>
-        uint64_t ssdV = computeSSD(fencPic->getCrAddr(cuAddr), reconPic->getCrAddr(cuAddr), stride, width, height);<br>
-<br>
-        m_frameEncoder->m_SSDY += ssdY;<br>
-        m_frameEncoder->m_SSDU += ssdU;<br>
-        m_frameEncoder->m_SSDV += ssdV;<br>
+            m_frameEncoder->m_SSDU += ssdU;<br>
+            m_frameEncoder->m_SSDV += ssdV;<br>
+        }<br>
     }<br>
     if (m_param->bEnableSsim && m_ssimBuf)<br>
     {<br>
@@ -264,12 +276,15 @@<br>
         }<br>
<br>
         updateMD5Plane(m_frameEncoder->m_state[0], reconPic->getLumaAddr(cuAddr), width, height, stride);<br>
-        width  >>= m_hChromaShift;<br>
-        height >>= m_vChromaShift;<br>
-        stride = reconPic->m_strideC;<br>
-<br>
-        updateMD5Plane(m_frameEncoder->m_state[1], reconPic->getCbAddr(cuAddr), width, height, stride);<br>
-        updateMD5Plane(m_frameEncoder->m_state[2], reconPic->getCrAddr(cuAddr), width, height, stride);<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            width  >>= m_hChromaShift;<br>
+            height >>= m_vChromaShift;<br>
+            stride = reconPic->m_strideC;<br>
+<br>
+            updateMD5Plane(m_frameEncoder->m_state[1], reconPic->getCbAddr(cuAddr), width, height, stride);<br>
+            updateMD5Plane(m_frameEncoder->m_state[2], reconPic->getCrAddr(cuAddr), width, height, stride);<br>
+        }<br>
     }<br>
     else if (m_param->decodedPictureHashSEI == 2)<br>
     {<br>
@@ -279,12 +294,15 @@<br>
         if (!row)<br>
             m_frameEncoder->m_crc[0] = m_frameEncoder->m_crc[1] = m_frameEncoder->m_crc[2] = 0xffff;<br>
         updateCRC(reconPic->getLumaAddr(cuAddr), m_frameEncoder->m_crc[0], height, width, stride);<br>
-        width  >>= m_hChromaShift;<br>
-        height >>= m_vChromaShift;<br>
-        stride = reconPic->m_strideC;<br>
-<br>
-        updateCRC(reconPic->getCbAddr(cuAddr), m_frameEncoder->m_crc[1], height, width, stride);<br>
-        updateCRC(reconPic->getCrAddr(cuAddr), m_frameEncoder->m_crc[2], height, width, stride);<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            width  >>= m_hChromaShift;<br>
+            height >>= m_vChromaShift;<br>
+            stride = reconPic->m_strideC;<br>
+<br>
+            updateCRC(reconPic->getCbAddr(cuAddr), m_frameEncoder->m_crc[1], height, width, stride);<br>
+            updateCRC(reconPic->getCrAddr(cuAddr), m_frameEncoder->m_crc[2], height, width, stride);<br>
+        }<br>
     }<br>
     else if (m_param->decodedPictureHashSEI == 3)<br>
     {<br>
@@ -295,13 +313,16 @@<br>
         if (!row)<br>
             m_frameEncoder->m_checksum[0] = m_frameEncoder->m_checksum[1] = m_frameEncoder->m_checksum[2] = 0;<br>
         updateChecksum(reconPic->m_picOrg[0], m_frameEncoder->m_checksum[0], height, width, stride, row, cuHeight);<br>
-        width  >>= m_hChromaShift;<br>
-        height >>= m_vChromaShift;<br>
-        stride = reconPic->m_strideC;<br>
-        cuHeight >>= m_vChromaShift;<br>
-<br>
-        updateChecksum(reconPic->m_picOrg[1], m_frameEncoder->m_checksum[1], height, width, stride, row, cuHeight);<br>
-        updateChecksum(reconPic->m_picOrg[2], m_frameEncoder->m_checksum[2], height, width, stride, row, cuHeight);<br>
+        if (reconPic->m_picCsp != X265_CSP_I400)<br>
+        {<br>
+            width  >>= m_hChromaShift;<br>
+            height >>= m_vChromaShift;<br>
+            stride = reconPic->m_strideC;<br>
+            cuHeight >>= m_vChromaShift;<br>
+<br>
+            updateChecksum(reconPic->m_picOrg[1], m_frameEncoder->m_checksum[1], height, width, stride, row, cuHeight);<br>
+            updateChecksum(reconPic->m_picOrg[2], m_frameEncoder->m_checksum[2], height, width, stride, row, cuHeight);<br>
+        }<br>
     }<br>
<br>
     if (ATOMIC_INC(&m_frameEncoder->m_completionCount) == 2 * (int)m_frameEncoder->m_numRows)<br>
@@ -415,15 +436,18 @@<br>
<br>
     <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[size].copy_pp(dst, reconPic->m_stride, src, fencPic->m_stride);<br>
<br>
-    pixel* dstCb = reconPic->getCbAddr(cuAddr, absPartIdx);<br>
-    pixel* srcCb = fencPic->getCbAddr(cuAddr, absPartIdx);<br>
+    int csp = fencPic->m_picCsp;<br>
+    if (csp != X265_CSP_I400)<br>
+    {<br>
+        pixel* dstCb = reconPic->getCbAddr(cuAddr, absPartIdx);<br>
+        pixel* srcCb = fencPic->getCbAddr(cuAddr, absPartIdx);<br>
<br>
-    pixel* dstCr = reconPic->getCrAddr(cuAddr, absPartIdx);<br>
-    pixel* srcCr = fencPic->getCrAddr(cuAddr, absPartIdx);<br>
+        pixel* dstCr = reconPic->getCrAddr(cuAddr, absPartIdx);<br>
+        pixel* srcCr = fencPic->getCrAddr(cuAddr, absPartIdx);<br>
<br>
-    int csp = fencPic->m_picCsp;<br>
-    primitives.chroma[csp].cu[size].copy_pp(dstCb, reconPic->m_strideC, srcCb, fencPic->m_strideC);<br>
-    primitives.chroma[csp].cu[size].copy_pp(dstCr, reconPic->m_strideC, srcCr, fencPic->m_strideC);<br>
+        primitives.chroma[csp].cu[size].copy_pp(dstCb, reconPic->m_strideC, srcCb, fencPic->m_strideC);<br>
+        primitives.chroma[csp].cu[size].copy_pp(dstCr, reconPic->m_strideC, srcCr, fencPic->m_strideC);<br>
+    }<br>
 }<br>
<br>
 /* Original YUV restoration for CU in lossless coding */<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/sao.cpp<br>
--- a/source/encoder/sao.cpp    Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/sao.cpp    Mon Sep 21 11:40:18 2015 -0500<br>
@@ -106,9 +106,15 @@<br>
 bool SAO::create(x265_param* param)<br>
 {<br>
     m_param = param;<br>
-    m_hChromaShift = CHROMA_H_SHIFT(param->internalCsp);<br>
-    m_vChromaShift = CHROMA_V_SHIFT(param->internalCsp);<br>
-<br>
+    if (param->internalCsp != X265_CSP_I400)<br>
+    {<br>
+        m_hChromaShift = CHROMA_H_SHIFT(param->internalCsp);<br>
+        m_vChromaShift = CHROMA_V_SHIFT(param->internalCsp);<br>
+        m_numPlanes = 3;<br>
+    }<br>
+    else<br>
+        m_numPlanes = 1;<br>
+<br>
     m_numCuInWidth =  (m_param->sourceWidth + g_maxCUSize - 1) / g_maxCUSize;<br>
     m_numCuInHeight = (m_param->sourceHeight + g_maxCUSize - 1) / g_maxCUSize;<br>
<br>
@@ -224,7 +230,7 @@<br>
     }<br>
<br>
     saoParam->bSaoFlag[0] = true;<br>
-    saoParam->bSaoFlag[1] = true;<br>
+    saoParam->bSaoFlag[1] = (m_numPlanes > 1);<br>
<br>
     m_numNoSao[0] = 0; // Luma<br>
     m_numNoSao[1] = 0; // Chroma<br>
@@ -1132,7 +1138,7 @@<br>
             m_entropyCoder.codeSaoMerge(0);<br>
         m_entropyCoder.store(m_rdContexts.temp);<br>
         // reset stats Y, Cb, Cr<br>
-        for (int plane = 0; plane < 3; plane++)<br>
+        for (int plane = 0; plane < m_numPlanes; plane++)<br>
         {<br>
             for (int j = 0; j < MAX_NUM_SAO_TYPE; j++)<br>
             {<br>
@@ -1161,7 +1167,8 @@<br>
<br>
         saoComponentParamDist(saoParam, addr, addrUp, addrLeft, &mergeSaoParam[0][0], mergeDist);<br>
<br>
-        sao2ChromaParamDist(saoParam, addr, addrUp, addrLeft, mergeSaoParam, mergeDist);<br>
+        if (m_numPlanes > 1)<br>
+            sao2ChromaParamDist(saoParam, addr, addrUp, addrLeft, mergeSaoParam, mergeDist);<br>
<br>
         if (saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1])<br>
         {<br>
@@ -1172,7 +1179,7 @@<br>
                 m_entropyCoder.codeSaoMerge(0);<br>
             if (allowMerge[1])<br>
                 m_entropyCoder.codeSaoMerge(0);<br>
-            for (int plane = 0; plane < 3; plane++)<br>
+            for (int plane = 0; plane < m_numPlanes; plane++)<br>
             {<br>
                 if (saoParam->bSaoFlag[plane > 0])<br>
                     m_entropyCoder.codeSaoOffset(saoParam->ctuParam[plane][addr], plane);<br>
@@ -1202,7 +1209,7 @@<br>
                     SaoMergeMode mergeMode = mergeIdx ? SAO_MERGE_UP : SAO_MERGE_LEFT;<br>
                     bestCost = mergeCost;<br>
                     m_entropyCoder.store(m_rdContexts.temp);<br>
-                    for (int plane = 0; plane < 3; plane++)<br>
+                    for (int plane = 0; plane < m_numPlanes; plane++)<br>
                     {<br>
                         mergeSaoParam[plane][mergeIdx].mergeMode = mergeMode;<br>
                         if (saoParam->bSaoFlag[plane > 0])<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/sao.h<br>
--- a/source/encoder/sao.h      Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/sao.h      Mon Sep 21 11:40:18 2015 -0500<br>
@@ -85,6 +85,7 @@<br>
<br>
     int         m_numCuInWidth;<br>
     int         m_numCuInHeight;<br>
+    int         m_numPlanes;<br>
     int         m_hChromaShift;<br>
     int         m_vChromaShift;<br>
<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/search.cpp<br>
--- a/source/encoder/search.cpp Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/search.cpp Mon Sep 21 11:40:18 2015 -0500<br>
@@ -1169,7 +1169,8 @@<br>
<br>
     intraMode.initCosts();<br>
     intraMode.lumaDistortion += estIntraPredQT(intraMode, cuGeom, tuDepthRange, sharedModes);<br>
-    intraMode.chromaDistortion += estIntraPredChromaQT(intraMode, cuGeom, sharedChromaModes);<br>
+    if (m_csp != X265_CSP_I400)<br>
+        intraMode.chromaDistortion += estIntraPredChromaQT(intraMode, cuGeom, sharedChromaModes);<br>
     intraMode.distortion += intraMode.lumaDistortion + intraMode.chromaDistortion;<br>
<br>
     m_entropyCoder.resetBits();<br>
@@ -2499,9 +2500,14 @@<br>
     // Luma<br>
     int part = partitionFromLog2Size(cu.m_log2CUSize[0]);<br>
     interMode.lumaDistortion = <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[part].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);<br>
-    // Chroma<br>
-    interMode.chromaDistortion = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));<br>
-    interMode.chromaDistortion += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        // Chroma<br>
+        interMode.chromaDistortion = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));<br>
+        interMode.chromaDistortion += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));<br>
+    }<br>
+    else<br>
+        interMode.chromaDistortion = 0;<br>
     interMode.distortion = interMode.lumaDistortion + interMode.chromaDistortion;<br>
<br>
     m_entropyCoder.load(m_rqt[depth].cur);<br>
@@ -2553,9 +2559,12 @@<br>
     if (!tqBypass)<br>
     {<br>
         sse_ret_t cbf0Dist = <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);<br>
-        cbf0Dist += m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], predYuv->m_csize, predYuv->m_buf[1], predYuv->m_csize));<br>
-        cbf0Dist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], predYuv->m_csize, predYuv->m_buf[2], predYuv->m_csize));<br>
-<br>
+        if (m_csp != X265_CSP_I400)<br>
+        {<br>
+            cbf0Dist += m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], predYuv->m_csize, predYuv->m_buf[1], predYuv->m_csize));<br>
+            cbf0Dist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], predYuv->m_csize, predYuv->m_buf[2], predYuv->m_csize));<br>
+        }<br>
+<br>
         /* Consider the RD cost of not signaling any residual */<br>
         m_entropyCoder.load(m_rqt[depth].cur);<br>
         m_entropyCoder.resetBits();<br>
@@ -2624,8 +2633,14 @@<br>
<br>
     // update with clipped distortion and cost (qp estimation loop uses unclipped values)<br>
     sse_ret_t bestLumaDist = <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);<br>
-    sse_ret_t bestChromaDist = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));<br>
-    bestChromaDist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));<br>
+    sse_ret_t bestChromaDist;<br>
+    if (m_csp != X265_CSP_I400)<br>
+    {<br>
+        bestChromaDist = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));<br>
+        bestChromaDist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));<br>
+    }<br>
+    else<br>
+        bestChromaDist = 0;<br>
     if (m_rdCost.m_psyRd)<br>
         interMode.psyEnergy = m_rdCost.psyCost(sizeIdx, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);<br>
     interMode.resEnergy = <a href="http://primitives.cu" rel="noreferrer" target="_blank">primitives.cu</a>[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);<br>
@@ -2798,15 +2813,22 @@<br>
     X265_CHECK(bCheckFull || bCheckSplit, "check-full or check-split must be set\n");<br>
<br>
     uint32_t log2TrSizeC = log2TrSize - m_hChromaShift;<br>
-    bool bCodeChroma = true;<br>
+    bool bCodeChroma;<br>
     uint32_t tuDepthC = tuDepth;<br>
-    if (log2TrSizeC < 2)<br>
+<br>
+    if (m_csp != X265_CSP_I400)<br>
     {<br>
-        X265_CHECK(log2TrSize == 2 && m_csp != X265_CSP_I444 && tuDepth, "invalid tuDepth\n");<br>
-        log2TrSizeC = 2;<br>
-        tuDepthC--;<br>
-        bCodeChroma = !(absPartIdx & 3);<br>
+        bCodeChroma = true;<br>
+        if (log2TrSizeC < 2)<br>
+        {<br>
+            X265_CHECK(log2TrSize == 2 && m_csp != X265_CSP_I444 && tuDepth, "invalid tuDepth\n");<br>
+            log2TrSizeC = 2;<br>
+            tuDepthC--;<br>
+            bCodeChroma = !(absPartIdx & 3);<br>
+        }<br>
     }<br>
+    else<br>
+        bCodeChroma = false;<br>
<br>
     // code full block<br>
     Cost fullCost;<br>
@@ -3383,15 +3405,22 @@<br>
     const uint32_t qtLayer = log2TrSize - 2;<br>
<br>
     uint32_t log2TrSizeC = log2TrSize - m_hChromaShift;<br>
-    bool bCodeChroma = true;<br>
+    bool bCodeChroma;<br>
     uint32_t tuDepthC = tuDepth;<br>
-    if (log2TrSizeC < 2)<br>
+<br>
+    if (m_csp != X265_CSP_I400)<br>
     {<br>
-        X265_CHECK(log2TrSize == 2 && m_csp != X265_CSP_I444 && tuDepth, "invalid tuDepth\n");<br>
-        log2TrSizeC = 2;<br>
-        tuDepthC--;<br>
-        bCodeChroma = !(absPartIdx & 3);<br>
+        bCodeChroma = true;<br>
+        if (log2TrSizeC < 2)<br>
+        {<br>
+            X265_CHECK(log2TrSize == 2 && m_csp != X265_CSP_I444 && tuDepth, "invalid tuDepth\n");<br>
+            log2TrSizeC = 2;<br>
+            tuDepthC--;<br>
+            bCodeChroma = !(absPartIdx & 3);<br>
+        }<br>
     }<br>
+    else<br>
+        bCodeChroma = false;<br>
<br>
     m_rqt[qtLayer].resiQtYuv.copyPartToPartLuma(resiYuv, absPartIdx, log2TrSize);<br>
<br>
diff -r f8b8ebdc5457 -r 5602b4bc1fec source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp      Mon Sep 28 14:34:41 2015 +0530<br>
+++ b/source/encoder/slicetype.cpp      Mon Sep 21 11:40:18 2015 -0500<br>
@@ -74,17 +74,18 @@<br>
 uint32_t LookaheadTLD::acEnergyCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, int csp)<br>
 {<br>
     intptr_t stride = curFrame->m_fencPic->m_stride;<br>
-    intptr_t cStride = curFrame->m_fencPic->m_strideC;<br>
     intptr_t blockOffsetLuma = blockX + (blockY * stride);<br>
-    int hShift = CHROMA_H_SHIFT(csp);<br>
-    int vShift = CHROMA_V_SHIFT(csp);<br>
-    intptr_t blockOffsetChroma = (blockX >> hShift) + ((blockY >> vShift) * cStride);<br>
<br>
-    uint32_t var;<br>
-<br>
-    var  = acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[0] + blockOffsetLuma, stride, 0, csp);<br>
-    var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[1] + blockOffsetChroma, cStride, 1, csp);<br>
-    var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[2] + blockOffsetChroma, cStride, 2, csp);<br>
+    uint32_t var = acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[0] + blockOffsetLuma, stride, 0, csp);<br>
+    if (csp != X265_CSP_I400)<br>
+    {<br>
+        intptr_t cStride = curFrame->m_fencPic->m_strideC;<br>
+        int hShift = CHROMA_H_SHIFT(csp);<br>
+        int vShift = CHROMA_V_SHIFT(csp);<br>
+        intptr_t blockOffsetChroma = (blockX >> hShift) + ((blockY >> vShift) * cStride);<br>
+        var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[1] + blockOffsetChroma, cStride, 1, csp);<br>
+        var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[2] + blockOffsetChroma, cStride, 2, csp);<br>
+    }<br>
     x265_emms();<br>
     return var;<br>
 }<br>
<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<br>
</blockquote></div><br></div>