public int Encode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { inputFrameBuffer = inFrameBuffer; outputFrameBuffer = outFrameBuffer; FillResidualMatrix(); return ForwardTransform(mResd, mDc, mResd); }
public VideoSequence(YuvFormatType yuvFormatType, Size frameSize ) { this.frameSize = frameSize; currentInputFrame = new YuvFrameBuffer(yuvFormatType, frameSize); currentOutputFrame = new YuvFrameBuffer(yuvFormatType, frameSize); picWidthInMbs = frameSize.Width / MbBlockSize; frameHeightInMbs = frameSize.Height / MbBlockSize; frameSizeInMbs = picWidthInMbs*frameHeightInMbs; lastIdr = 0; pictureIndex = 0; }
protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mp) { var maxW = Macroblock.MbWidth; var maxH = Macroblock.MbHeight; var upAvail = access.IsUpAvailable(maxW); var leftAvail = access.IsLeftAvailable(maxH); var leftUpAvail = access.IsLeftUpAvailable(); if (!upAvail || !leftAvail || !leftUpAvail) // edge return false; var h = 0; var v = 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 7){ (x'+1) * (p[8+x', -1] - p[6-x', -1]) } // V = sum(y' = 0 to 7){ (y'+1) * (p[-1, 8+y'] - p[-1, 6-y']) } for (var i = 1; i < 9; i++) { if (i < 8) { h += i*(codedFrameBuffer.GetY8Bit(pUp.X + 7 + i, pUp.Y)- codedFrameBuffer.GetY8Bit(pUp.X + 7 - i, pUp.Y)); v += i*(codedFrameBuffer.GetY8Bit(pLeft.X, pLeft.Y + 7 + i)- codedFrameBuffer.GetY8Bit(pLeft.X, pLeft.Y + 8 - i)); } else { h += i*(codedFrameBuffer.GetY8Bit(pUp.X + 7 + i, pUp.Y)- codedFrameBuffer.GetY8Bit(pLeftUp.X, pLeftUp.Y)); v += i*(codedFrameBuffer.GetY8Bit(pLeft.X, pLeft.Y + 7 + i)- codedFrameBuffer.GetY8Bit(pLeftUp.X, pLeftUp.Y)); } } var a = 16*(codedFrameBuffer.GetY8Bit(pLeft.X, pLeft.Y + 15) + codedFrameBuffer.GetY8Bit(pUp.X + 15, pUp.Y)); var b = (5*h + 32) >> 6; var c = (5*v + 32) >> 6; // predL[x, y] = Clip1Y((a + b*(x - 7) + c*(y - 7) + 16) >> 5), // with x, y = 0..15 for (var j = 0; j < Macroblock.MbHeight; j++) { for (var i = 0; i < Macroblock.MbWidth; i++) { var value = MathHelper.RshiftRound((a + (i - 7)*b + (j - 7)*c), 5); mp[j][i] = MathHelper.Clip(maxImagePelValue, value); } } return true; }
protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mp) { var p = new Point(); var sumUp = 0; var sumLeft = 0; var maxW = Macroblock.MbWidth; var maxH = Macroblock.MbHeight; var upAvail = access.IsUpAvailable(maxW); var leftAvail = access.IsLeftAvailable(maxH); // sum(x' = 0 to 15) { p[x', -1] } if (upAvail) { for (var i = 0; i < Macroblock.MbWidth; i++) { access.GetNeighbour(i, -1, maxW, maxH, p); sumUp += codedFrameBuffer.GetY8Bit(p.X, p.Y); } } // sum(y' = 0 to 15) { p[-1, y'] } if (leftAvail) { for (var i = 0; i < Macroblock.MbHeight; i++) { access.GetNeighbour(-1, i, maxW, maxH, p); sumLeft += codedFrameBuffer.GetY8Bit(p.X, p.Y); } } // no edge // predL[x, y] = (sumUp + sumLeft + 16) >> 5 , with x, y = 0..15 // upper edge // predL[x, y] = (sumLeft + 8) >> 4, with x, y = 0..15 // left edge // predL[x, y] = (sumUp + 8) >> 4, with x, y = 0..15 // top left corner // predL[x, y] = (1 << (BitDepthY – 1)), with x, y = 0..15 var predL = upAvail && leftAvail ? MathHelper.RshiftRound((sumUp + sumLeft), 5) : (!upAvail && leftAvail ? MathHelper.RshiftRound(sumLeft, 4) : (upAvail ? MathHelper.RshiftRound(sumUp, 4) : 1 << (bitDepthY - 1))); // store DC prediction for (var j = 0; j < Macroblock.MbHeight; j++) for (var i = 0; i < Macroblock.MbWidth; i++) mp[j][i] = predL; return true; }
public int Encode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { const int numberOfCodedMBs = 99; InitSlice(); SetLagrangianMultipliers(); for (var i = 0; i < numberOfCodedMBs; i++) { var mb = new Macroblock(this, i); mb.Encode(inFrameBuffer, outFrameBuffer); macroblocks.Add(mb); } return numberOfCodedMBs; }
protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mp) { var maxW = Macroblock.MbWidth; var maxH = Macroblock.MbHeight; if (!access.IsUpAvailable(maxW)) return false; var p = new Point(); // predL[ x, y ] = p[ x, -1 ], with x, y = 0..15 for (var index0 = 0; index0 < maxW; index0++) { access.GetNeighbour(index0, -1, maxW, maxH, p); for (var index01 = 0; index01 < maxH; index01++) mp[index01][index0] = codedFrameBuffer.GetY8Bit(p.X, p.Y); } return true; }
public override void Reconstruct(YuvFrameBuffer outFrameBuffer) { var x = macroblock.PixelX; var y = macroblock.PixelY; var cx = macroblock.PixelChromaX; var cy = macroblock.PixelChromaY; for (var j = 0; j < Macroblock.MbHeight; j++) for (var i = 0; i < Macroblock.MbWidth; i++) outFrameBuffer.SetY8Bit(i + x, j + y, bufferY[i][j]); for (var j = 0; j < Macroblock.MbChromaHeight; j++) for (var i = 0; i < Macroblock.MbChromaWidth; i++) outFrameBuffer.SetCb8Bit(i + cx, j + cy, bufferU[i][j]); for (var j = 0; j < Macroblock.MbChromaHeight; j++) for (var i = 0; i < Macroblock.MbChromaWidth; i++) outFrameBuffer.SetCr8Bit(i + cx, j + cy, bufferV[i][j]); }
protected override bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mp) { var maxW = Macroblock.MbWidth; var maxH = Macroblock.MbHeight; if (!access.IsLeftAvailable(maxH)) return false; var p = new Point(); // predL[ x, y ] = p[ -1, y ], with x, y = 0..15 for (var i = 0; i < maxH; i++) { access.GetNeighbour(-1, i, maxW, maxH, p); for (var j = 0; j < maxW; j++) mp[i][j] = codedFrameBuffer.GetY8Bit(p.X, p.Y); } return true; }
protected override void DoEncode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer codedFrameBuffer) { var x = macroblock.PixelX; var y = macroblock.PixelY; var cx = macroblock.PixelChromaX; var cy = macroblock.PixelChromaY; // LUMA for (var j = 0; j < Macroblock.MbHeight; j++) for (var i = 0; i < Macroblock.MbWidth; i++) bufferY[i][j] = inputFrameBuffer.GetY8Bit(i + x, j + y); // CHROMA for (var j = 0; j < Macroblock.MbChromaHeight; j++) for (var i = 0; i < Macroblock.MbChromaWidth; i++) { bufferU[i][j] = inputFrameBuffer.GetCb8Bit(i + cx, j + cy); bufferV[i][j] = inputFrameBuffer.GetCr8Bit(i + cx, j + cy); } }
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 abstract bool DoIntraPrediction(YuvFrameBuffer codedFrameBuffer, int[][] mp);
private void FillOriginalMatrix(YuvFrameBuffer origiFrameBuffer) { for (var j = 0; j < mbHeight; j++) { var jj = y + j; for (var i = 0; i < mbWidth; i++) { var ii = x + i; mOrig[j][i] = origiFrameBuffer.GetY8Bit(ii, jj); } } }
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; }
public void Reconstruct(YuvFrameBuffer outFrameBuffer) { const int dqBits = 6; var mrInv = new int[mbHeight][]; for (var i = 0; i < mrInv.Length; i++) mrInv[i] = new int[mbWidth]; InverseTransform(mDc, mResd, mrInv); for (var j = 0; j < mbHeight; j++) { var jj = y + j; for (var i = 0; i < mbWidth; i++) { var ii = x + i; var predicted = mPred[j][i]; // Predicted sample var residualRecons = MathHelper.RshiftRound(mrInv[j][i], dqBits); // Reconstructed residual sample var originalRecons = residualRecons + predicted; // Reconstructed original sample originalRecons = MathHelper.Clip(maxImagePelValue, originalRecons); outFrameBuffer.SetY8Bit(ii, jj, originalRecons); } } }
public bool Predict(YuvFrameBuffer origiFrameBuffer, YuvFrameBuffer codedFrameBuffer) { FillOriginalMatrix(origiFrameBuffer); return DoIntraPrediction(codedFrameBuffer, mPred); }
public abstract void Reconstruct(YuvFrameBuffer outFrameBuffer);
protected abstract void DoEncode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer codedFrameBuffer);
public void Encode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { inputFrameBuffer = inFrameBuffer; outputFrameBuffer = outFrameBuffer; DoEncode(inFrameBuffer, outFrameBuffer); }
public void Encode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { CodePicture(inFrameBuffer, outFrameBuffer); }
public void Encode(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { const int bestDistortion = int.MaxValue; foreach (var mode in encodingModes) { mode.Encode(inFrameBuffer, outFrameBuffer); if (mode.GetDistortion() < bestDistortion) bestMode = mode; } bestMode.Reconstruct(outFrameBuffer); }
protected void CodePicture(YuvFrameBuffer inFrameBuffer, YuvFrameBuffer outFrameBuffer) { var numberOfCodedMBs = 0; // TODO FmoInit() // TODO FmoStartPicture() -> picture level initialization of FMO CalculateQuantParam(); // loop over slices while (numberOfCodedMBs < picSizeInMbs) { slice = new Slice(this, type); numberOfCodedMBs += slice.Encode(inFrameBuffer, outFrameBuffer); } }
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; }