protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mpCb, int[][] mpCr)
        {
            var maxW = Macroblock.MbChromaWidth;
            var maxH = Macroblock.MbChromaHeight;

            if (!access.IsLeftAvailable(maxH)) return false;
            var p = new Point();

            // predC[ x, y ] = p[ -1, y ],
            // with x = 0..MbWidthC - 1 and y = 0..MbHeightC - 1
            for (var i = 0; i < maxH; i++)
            {
                access.GetNeighbour(-1, i, maxW, maxH, p);
                for (var j = 0; j < maxW; j++)
                {
                    mpCb[i][j] = codedFrameBuffer.GetCb8Bit(p.X, p.Y);
                    mpCr[i][j] = codedFrameBuffer.GetCr8Bit(p.X, p.Y);
                }
            }

            return true;
        }
        protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mpCb, int[][] mpCr)
        {
            var p = new Point();
            var maxW = Macroblock.MbChromaWidth;
            var maxH = Macroblock.MbChromaHeight;
            var upAvail = access.IsUpAvailable(maxW);
            var leftAvail = access.IsLeftAvailable(maxH);

            // For each chroma block of 4x4 samples indexed by
            // chroma4x4BlkIdx = 0..( 1 << ( ChromaArrayType + 1 ) ) – 1
            for (var chroma4X4BlkIdx = 0; chroma4X4BlkIdx < 4; chroma4X4BlkIdx++)
            {
                var predCb = 0;
                var predCr = 0;
                var sumUpCb = 0;
                var sumUpCr = 0;
                var sumLeftCb = 0;
                var sumLeftCr = 0;

                var xO = PosX(chroma4X4BlkIdx);
                var yO = PosY(chroma4X4BlkIdx);

                // sum(x' = 0 to 3) { p[x' + xO, -1] }
                if (upAvail)
                {
                    for (var i = 0; i < ChromaBlkWidth; i++)
                    {
                        access.GetNeighbour(i, -1, maxW, maxH, p);
                        sumUpCb += codedFrameBuffer.GetCb8Bit(p.X + xO, p.Y);
                        sumUpCr += codedFrameBuffer.GetCr8Bit(p.X + xO, p.Y);
                    }
                }
                // sum(y' = 0 to 3) { p[-1, y' + yO] }
                if (leftAvail)
                {
                    for (var i = 0; i < ChromaBlkHeight; i++)
                    {
                        access.GetNeighbour(-1, i, maxW, maxH, p);
                        sumLeftCb += codedFrameBuffer.GetCb8Bit(p.X, p.Y + yO);
                        sumLeftCr += codedFrameBuffer.GetCr8Bit(p.X, p.Y + yO);
                    }
                }

                // TOP-LEFT and BOTTOM-RIGHT
                if (((xO == 0) && (yO == 0)) || ((xO > 0) && (yO > 0)))
                {
                    if (upAvail && leftAvail)
                    {
                        // predC[x+xO, y+yO] = (sumUp + sumLeft + 4) >> 3
                        predCb = (sumUpCb + sumLeftCb + 4) >> 3;
                        predCr = (sumUpCr + sumLeftCr + 4) >> 3;
                    }
                    else if (leftAvail)
                    {
                        // predC[x+xO, y+yO] = (sumLeft + 2) >> 2
                        predCb = (sumLeftCb + 2) >> 2;
                        predCr = (sumLeftCr + 2) >> 2;
                    }
                    else if (upAvail)
                    {
                        // predC[x+xO, y+yO] = (sumUp + 2) >> 2
                        predCb = (sumUpCb + 2) >> 2;
                        predCr = (sumUpCr + 2) >> 2;
                    }
                    else
                    {
                        // predC[x+xO, y+yO] = (1 << ( BitDepthC – 1 ))
                        predCb = 1 << (bitDepthC - 1);
                        predCr = 1 << (bitDepthC - 1);
                    }
                } // TOP-RIGHT
                else if ((xO > 0) && (yO == 0))
                {
                    if (upAvail)
                    {
                        // predC[x+xO, y+yO] = (sumUp + 2) >> 2
                        predCb = (sumUpCb + 2) >> 2;
                        predCr = (sumUpCr + 2) >> 2;
                    }
                    else if (leftAvail)
                    {
                        // predC[x+xO, y+yO] = (sumLeft + 2) >> 2
                        predCb = (sumLeftCb + 2) >> 2;
                        predCr = (sumLeftCr + 2) >> 2;
                    }
                    else
                    {
                        // predC[x+xO, y+yO] = (1 << ( BitDepthC – 1 ))
                        predCb = 1 << (bitDepthC - 1);
                        predCr = 1 << (bitDepthC - 1);
                    }
                } // BOTTOM-LEFT
                else if ((xO == 0) && (yO > 0))
                {
                    if (leftAvail)
                    {
                        // predC[x+xO, y+yO] = (sumLeft + 2) >> 2
                        predCb = (sumLeftCb + 2) >> 2;
                        predCr = (sumLeftCr + 2) >> 2;
                    }
                    else if (upAvail)
                    {
                        // predC[x+xO, y+yO] = (sumUp + 2) >> 2
                        predCb = (sumUpCb + 2) >> 2;
                        predCr = (sumUpCr + 2) >> 2;
                    }
                    else
                    {
                        // predC[x+xO, y+yO] = (1 << ( BitDepthC – 1 ))
                        predCb = 1 << (bitDepthC - 1);
                        predCr = 1 << (bitDepthC - 1);
                    }
                }

                // store DC prediction
                for (var j = yO; j < ChromaBlkHeight + yO; j++)
                {
                    for (var i = xO; i < ChromaBlkWidth + xO; i++)
                    {
                        mpCb[j][i] = predCb;
                        mpCr[j][i] = predCr;
                    }
                }
            }

            return true;
        }
        protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mpCb, int[][] mpCr)
        {
            var maxW = Macroblock.MbChromaWidth;
            var maxH = Macroblock.MbChromaHeight;
            var upAvail = access.IsUpAvailable(maxW);
            var leftAvail = access.IsLeftAvailable(maxH);
            var leftUpAvail = access.IsLeftUpAvailable();
            if (!upAvail || !leftAvail || !leftUpAvail)
                return false;

            // Note: used (chroma_block_width >> 1) instead of (xCF + 4)
            // Note: used (chroma_block_height >> 1) instead of (yCF + 4)

            var hCb = 0;
            var vCb = 0;
            var hCr = 0;
            var vCr = 0;
            var pUp = new Point();
            var pLeft = new Point();
            var pLeftUp = new Point();

            access.GetNeighbour(0, -1, maxW, maxH, pUp);
            access.GetNeighbour(-1, 0, maxW, maxH, pLeft);
            access.GetNeighbour(-1, -1, maxW, maxH, pLeftUp);

            // H = sum(x' = 0 to (3 + xCF)){ (x'+1) * (p[4 + xCF + x', -1] - p[2 + xCF -x', -1]) }
            for (var i = 1; i <= (maxW >> 1); i++)
            {
                var x = i - 1; // x'
                hCb += i*(codedFrameBuffer.GetCb8Bit(pUp.X + (maxW >> 1) + x, pUp.Y) - codedFrameBuffer.GetCb8Bit(pUp.X + (maxW >> 1) - 2 - x, pUp.Y));
                hCr += i*(codedFrameBuffer.GetCr8Bit(pUp.X + (maxW >> 1) + x, pUp.Y) - codedFrameBuffer.GetCr8Bit(pUp.X + (maxW >> 1) - 2 - x, pUp.Y));
            }
            // V = sum(y' = 0 to (3 + yCF)){ (y'+1) * (p[-1, 4 + yCF + y'] - p[-1, 2 + yCF - y']) }
            for (var i = 1; i <= (maxH >> 1); i++)
            {
                var y = i - 1; // y'
                vCb += i*(codedFrameBuffer.GetCb8Bit(pLeft.X, pLeft.Y + (maxH >> 1) + y) - codedFrameBuffer.GetCb8Bit(pLeft.X, pLeft.Y + (maxH >> 1) - 2 - y));
                vCr += i*(codedFrameBuffer.GetCr8Bit(pLeft.X, pLeft.Y + (maxH >> 1) + y) - codedFrameBuffer.GetCr8Bit(pLeft.X, pLeft.Y + (maxH >> 1) - 2 - y));
            }
            // a = 16 * ( p[ -1, MbHeightC - 1 ] + p[ MbWidthC - 1, -1 ] )
            var aCb = 16*(codedFrameBuffer.GetCb8Bit(pLeft.X, pLeft.Y + maxH - 1) + codedFrameBuffer.GetCb8Bit(pUp.X + maxH - 1, pUp.Y));
            var aCr = 16*(codedFrameBuffer.GetCr8Bit(pLeft.X, pLeft.Y + maxH - 1) + codedFrameBuffer.GetCr8Bit(pUp.X + maxH - 1, pUp.Y));

            // b = ( ( 34 – 29 * ( ChromaArrayType == 3 ) ) * H + 32 ) >> 6
            var bCb = ((maxW == 8 ? 17 : 5)*hCb + 2*maxW) >> (maxW == 8 ? 5 : 6);
            var bCr = ((maxW == 8 ? 17 : 5)*hCr + 2*maxW) >> (maxW == 8 ? 5 : 6);

            // c = ( ( 34 – 29 * ( ChromaArrayType != 1 ) ) * V + 32 ) >> 6
            var cCb = ((maxH == 8 ? 17 : 5)*vCb + 2*maxH) >> (maxH == 8 ? 5 : 6);
            var cCr = ((maxH == 8 ? 17 : 5)*vCr + 2*maxH) >> (maxH == 8 ? 5 : 6);

            // predC[ x, y ] = Clip1C( ( a + b * ( x – 3 – xCF ) + c * ( y – 3 – yCF ) + 16 ) >> 5 ),
            // with x = 0..MbWidthC - 1 and y = 0..MbHeightC - 1
            for (var j = 0; j < maxH; j++)
            {
                for (var i = 0; i < maxW; i++)
                {
                    var predCb = (aCb + (i - (maxW >> 1) + 1)*bCb + (j - (maxH >> 1) + 1)*cCb + 16) >> 5;
                    var predCr = (aCr + (i - (maxW >> 1) + 1)*bCr + (j - (maxH >> 1) + 1)*cCr + 16) >> 5;
                    mpCb[j][i] = MathHelper.Clip(maxImagePelValue, predCb);
                    mpCr[j][i] = MathHelper.Clip(maxImagePelValue, predCr);
                }
            }
            return true;
        }