4d02a2d2c0
* Initial NVDEC and VIC implementation * Update FFmpeg.AutoGen to 4.3.0 * Add nvdec dependencies for Windows * Unify some VP9 structures * Rename VP9 structure fields * Improvements to Video API * XML docs for Common.Memory * Remove now unused or redundant overloads from MemoryAccessor * NVDEC UV surface read/write scalar paths * Add FIXME comments about hacky things/stuff that will need to be fixed in the future * Cleaned up VP9 memory allocation * Remove some debug logs * Rename some VP9 structs * Remove unused struct * No need to compile Ryujinx.Graphics.Host1x with unsafe anymore * Name AsyncWorkQueue threads to make debugging easier * Make Vp9PictureInfo a ref struct * LayoutConverter no longer needs the depth argument (broken by rebase) * Pooling of VP9 buffers, plus fix a memory leak on VP9 * Really wish VS could rename projects properly... * Address feedback * Remove using * Catch OperationCanceledException * Add licensing informations * Add THIRDPARTY.md to release too Co-authored-by: Thog <me@thog.eu>
761 lines
26 KiB
C#
761 lines
26 KiB
C#
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
|
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred;
|
|
|
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
|
{
|
|
internal static class ReconIntra
|
|
{
|
|
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[]
|
|
{
|
|
TxType.DctDct, // DC
|
|
TxType.AdstDct, // V
|
|
TxType.DctAdst, // H
|
|
TxType.DctDct, // D45
|
|
TxType.AdstAdst, // D135
|
|
TxType.AdstDct, // D117
|
|
TxType.DctAdst, // D153
|
|
TxType.DctAdst, // D207
|
|
TxType.AdstDct, // D63
|
|
TxType.AdstAdst // TM
|
|
};
|
|
|
|
private const int NeedLeft = 1 << 1;
|
|
private const int NeedAbove = 1 << 2;
|
|
private const int NeedAboveRight = 1 << 3;
|
|
|
|
private static readonly byte[] ExtendModes = new byte[]
|
|
{
|
|
NeedAbove | NeedLeft, // DC
|
|
NeedAbove, // V
|
|
NeedLeft, // H
|
|
NeedAboveRight, // D45
|
|
NeedLeft | NeedAbove, // D135
|
|
NeedLeft | NeedAbove, // D117
|
|
NeedLeft | NeedAbove, // D153
|
|
NeedLeft, // D207
|
|
NeedAboveRight, // D63
|
|
NeedLeft | NeedAbove, // TM
|
|
};
|
|
|
|
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
|
|
|
private static unsafe IntraPredFn[][] _pred = new IntraPredFn[][]
|
|
{
|
|
new IntraPredFn[]
|
|
{
|
|
null,
|
|
null,
|
|
null,
|
|
null
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
VPredictor4x4,
|
|
VPredictor8x8,
|
|
VPredictor16x16,
|
|
VPredictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
HPredictor4x4,
|
|
HPredictor8x8,
|
|
HPredictor16x16,
|
|
HPredictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D45Predictor4x4,
|
|
D45Predictor8x8,
|
|
D45Predictor16x16,
|
|
D45Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D135Predictor4x4,
|
|
D135Predictor8x8,
|
|
D135Predictor16x16,
|
|
D135Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D117Predictor4x4,
|
|
D117Predictor8x8,
|
|
D117Predictor16x16,
|
|
D117Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D153Predictor4x4,
|
|
D153Predictor8x8,
|
|
D153Predictor16x16,
|
|
D153Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D207Predictor4x4,
|
|
D207Predictor8x8,
|
|
D207Predictor16x16,
|
|
D207Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
D63Predictor4x4,
|
|
D63Predictor8x8,
|
|
D63Predictor16x16,
|
|
D63Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
TMPredictor4x4,
|
|
TMPredictor8x8,
|
|
TMPredictor16x16,
|
|
TMPredictor32x32
|
|
}
|
|
};
|
|
|
|
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][]
|
|
{
|
|
new IntraPredFn[][]
|
|
{
|
|
new IntraPredFn[]
|
|
{
|
|
Dc128Predictor4x4,
|
|
Dc128Predictor8x8,
|
|
Dc128Predictor16x16,
|
|
Dc128Predictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
DcTopPredictor4x4,
|
|
DcTopPredictor8x8,
|
|
DcTopPredictor16x16,
|
|
DcTopPredictor32x32
|
|
}
|
|
},
|
|
new IntraPredFn[][]
|
|
{
|
|
new IntraPredFn[]
|
|
{
|
|
DcLeftPredictor4x4,
|
|
DcLeftPredictor8x8,
|
|
DcLeftPredictor16x16,
|
|
DcLeftPredictor32x32
|
|
},
|
|
new IntraPredFn[]
|
|
{
|
|
DcPredictor4x4,
|
|
DcPredictor8x8,
|
|
DcPredictor16x16,
|
|
DcPredictor32x32
|
|
}
|
|
}
|
|
};
|
|
|
|
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
|
|
|
private static unsafe IntraHighPredFn[][] _predHigh = new IntraHighPredFn[][]
|
|
{
|
|
new IntraHighPredFn[]
|
|
{
|
|
null,
|
|
null,
|
|
null,
|
|
null
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdVPredictor4x4,
|
|
HighbdVPredictor8x8,
|
|
HighbdVPredictor16x16,
|
|
HighbdVPredictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdHPredictor4x4,
|
|
HighbdHPredictor8x8,
|
|
HighbdHPredictor16x16,
|
|
HighbdHPredictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD45Predictor4x4,
|
|
HighbdD45Predictor8x8,
|
|
HighbdD45Predictor16x16,
|
|
HighbdD45Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD135Predictor4x4,
|
|
HighbdD135Predictor8x8,
|
|
HighbdD135Predictor16x16,
|
|
HighbdD135Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD117Predictor4x4,
|
|
HighbdD117Predictor8x8,
|
|
HighbdD117Predictor16x16,
|
|
HighbdD117Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD153Predictor4x4,
|
|
HighbdD153Predictor8x8,
|
|
HighbdD153Predictor16x16,
|
|
HighbdD153Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD207Predictor4x4,
|
|
HighbdD207Predictor8x8,
|
|
HighbdD207Predictor16x16,
|
|
HighbdD207Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdD63Predictor4x4,
|
|
HighbdD63Predictor8x8,
|
|
HighbdD63Predictor16x16,
|
|
HighbdD63Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdTMPredictor4x4,
|
|
HighbdTMPredictor8x8,
|
|
HighbdTMPredictor16x16,
|
|
HighbdTMPredictor32x32
|
|
}
|
|
};
|
|
|
|
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][]
|
|
{
|
|
new IntraHighPredFn[][]
|
|
{
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdDc128Predictor4x4,
|
|
HighbdDc128Predictor8x8,
|
|
HighbdDc128Predictor16x16,
|
|
HighbdDc128Predictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdDcTopPredictor4x4,
|
|
HighbdDcTopPredictor8x8,
|
|
HighbdDcTopPredictor16x16,
|
|
HighbdDcTopPredictor32x32
|
|
}
|
|
},
|
|
new IntraHighPredFn[][]
|
|
{
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdDcLeftPredictor4x4,
|
|
HighbdDcLeftPredictor8x8,
|
|
HighbdDcLeftPredictor16x16,
|
|
HighbdDcLeftPredictor32x32
|
|
},
|
|
new IntraHighPredFn[]
|
|
{
|
|
HighbdDcPredictor4x4,
|
|
HighbdDcPredictor8x8,
|
|
HighbdDcPredictor16x16,
|
|
HighbdDcPredictor32x32
|
|
}
|
|
}
|
|
};
|
|
|
|
private static unsafe void BuildIntraPredictorsHigh(
|
|
ref MacroBlockD xd,
|
|
byte* ref8,
|
|
int refStride,
|
|
byte* dst8,
|
|
int dstStride,
|
|
PredictionMode mode,
|
|
TxSize txSize,
|
|
int upAvailable,
|
|
int leftAvailable,
|
|
int rightAvailable,
|
|
int x,
|
|
int y,
|
|
int plane)
|
|
{
|
|
int i;
|
|
ushort* dst = (ushort*)dst8;
|
|
ushort* refr = (ushort*)ref8;
|
|
ushort* leftCol = stackalloc ushort[32];
|
|
ushort* aboveData = stackalloc ushort[64 + 16];
|
|
ushort* aboveRow = aboveData + 16;
|
|
ushort* constAboveRow = aboveRow;
|
|
int bs = 4 << (int)txSize;
|
|
int frameWidth, frameHeight;
|
|
int x0, y0;
|
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
|
int needLeft = ExtendModes[(int)mode] & NeedLeft;
|
|
int needAbove = ExtendModes[(int)mode] & NeedAbove;
|
|
int needAboveRight = ExtendModes[(int)mode] & NeedAboveRight;
|
|
int baseVal = 128 << (xd.Bd - 8);
|
|
// 127 127 127 .. 127 127 127 127 127 127
|
|
// 129 A B .. Y Z
|
|
// 129 C D .. W X
|
|
// 129 E F .. U V
|
|
// 129 G H .. S T T T T T
|
|
// For 10 bit and 12 bit, 127 and 129 are replaced by base -1 and base + 1.
|
|
|
|
// Get current frame pointer, width and height.
|
|
if (plane == 0)
|
|
{
|
|
frameWidth = xd.CurBuf.Width;
|
|
frameHeight = xd.CurBuf.Height;
|
|
}
|
|
else
|
|
{
|
|
frameWidth = xd.CurBuf.UvWidth;
|
|
frameHeight = xd.CurBuf.UvHeight;
|
|
}
|
|
|
|
// Get block position in current frame.
|
|
x0 = (-xd.MbToLeftEdge >> (3 + pd.SubsamplingX)) + x;
|
|
y0 = (-xd.MbToTopEdge >> (3 + pd.SubsamplingY)) + y;
|
|
|
|
// NEED_LEFT
|
|
if (needLeft != 0)
|
|
{
|
|
if (leftAvailable != 0)
|
|
{
|
|
if (xd.MbToBottomEdge < 0)
|
|
{
|
|
/* slower path if the block needs border extension */
|
|
if (y0 + bs <= frameHeight)
|
|
{
|
|
for (i = 0; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int extendBottom = frameHeight - y0;
|
|
for (i = 0; i < extendBottom; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
|
|
for (; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* faster path if the block does not need extension */
|
|
for (i = 0; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(leftCol, (ushort)(baseVal + 1), bs);
|
|
}
|
|
}
|
|
|
|
// NEED_ABOVE
|
|
if (needAbove != 0)
|
|
{
|
|
if (upAvailable != 0)
|
|
{
|
|
ushort* aboveRef = refr - refStride;
|
|
if (xd.MbToRightEdge < 0)
|
|
{
|
|
/* slower path if the block needs border extension */
|
|
if (x0 + bs <= frameWidth)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
}
|
|
else if (x0 <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + bs - frameWidth);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* faster path if the block does not need extension */
|
|
if (bs == 4 && rightAvailable != 0 && leftAvailable != 0)
|
|
{
|
|
constAboveRow = aboveRef;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
}
|
|
}
|
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow, (ushort)(baseVal - 1), bs);
|
|
aboveRow[-1] = (ushort)(baseVal - 1);
|
|
}
|
|
}
|
|
|
|
// NEED_ABOVERIGHT
|
|
if (needAboveRight != 0)
|
|
{
|
|
if (upAvailable != 0)
|
|
{
|
|
ushort* aboveRef = refr - refStride;
|
|
if (xd.MbToRightEdge < 0)
|
|
{
|
|
/* slower path if the block needs border extension */
|
|
if (x0 + 2 * bs <= frameWidth)
|
|
{
|
|
if (rightAvailable != 0 && bs == 4)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, 2 * bs);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
}
|
|
else if (x0 + bs <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
if (rightAvailable != 0 && bs == 4)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
}
|
|
else if (x0 <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
|
}
|
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
|
}
|
|
else
|
|
{
|
|
/* faster path if the block does not need extension */
|
|
if (bs == 4 && rightAvailable != 0 && leftAvailable != 0)
|
|
{
|
|
constAboveRow = aboveRef;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
if (bs == 4 && rightAvailable != 0)
|
|
{
|
|
MemoryUtil.Copy(aboveRow + bs, aboveRef + bs, bs);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
|
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow, (ushort)(baseVal - 1), bs * 2);
|
|
aboveRow[-1] = (ushort)(baseVal - 1);
|
|
}
|
|
}
|
|
|
|
// Predict
|
|
if (mode == PredictionMode.DcPred)
|
|
{
|
|
_dcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
|
}
|
|
else
|
|
{
|
|
_predHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
|
|
}
|
|
}
|
|
|
|
public static unsafe void BuildIntraPredictors(
|
|
ref MacroBlockD xd,
|
|
byte* refr,
|
|
int refStride,
|
|
byte* dst,
|
|
int dstStride,
|
|
PredictionMode mode,
|
|
TxSize txSize,
|
|
int upAvailable,
|
|
int leftAvailable,
|
|
int rightAvailable,
|
|
int x,
|
|
int y,
|
|
int plane)
|
|
{
|
|
int i;
|
|
byte* leftCol = stackalloc byte[32];
|
|
byte* aboveData = stackalloc byte[64 + 16];
|
|
byte* aboveRow = aboveData + 16;
|
|
byte* constAboveRow = aboveRow;
|
|
int bs = 4 << (int)txSize;
|
|
int frameWidth, frameHeight;
|
|
int x0, y0;
|
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
|
|
|
// 127 127 127 .. 127 127 127 127 127 127
|
|
// 129 A B .. Y Z
|
|
// 129 C D .. W X
|
|
// 129 E F .. U V
|
|
// 129 G H .. S T T T T T
|
|
// ..
|
|
|
|
// Get current frame pointer, width and height.
|
|
if (plane == 0)
|
|
{
|
|
frameWidth = xd.CurBuf.Width;
|
|
frameHeight = xd.CurBuf.Height;
|
|
}
|
|
else
|
|
{
|
|
frameWidth = xd.CurBuf.UvWidth;
|
|
frameHeight = xd.CurBuf.UvHeight;
|
|
}
|
|
|
|
// Get block position in current frame.
|
|
x0 = (-xd.MbToLeftEdge >> (3 + pd.SubsamplingX)) + x;
|
|
y0 = (-xd.MbToTopEdge >> (3 + pd.SubsamplingY)) + y;
|
|
|
|
// NEED_LEFT
|
|
if ((ExtendModes[(int)mode] & NeedLeft) != 0)
|
|
{
|
|
if (leftAvailable != 0)
|
|
{
|
|
if (xd.MbToBottomEdge < 0)
|
|
{
|
|
/* Slower path if the block needs border extension */
|
|
if (y0 + bs <= frameHeight)
|
|
{
|
|
for (i = 0; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int extendBottom = frameHeight - y0;
|
|
for (i = 0; i < extendBottom; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
|
|
for (; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Faster path if the block does not need extension */
|
|
for (i = 0; i < bs; ++i)
|
|
{
|
|
leftCol[i] = refr[i * refStride - 1];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(leftCol, (byte)129, bs);
|
|
}
|
|
}
|
|
|
|
// NEED_ABOVE
|
|
if ((ExtendModes[(int)mode] & NeedAbove) != 0)
|
|
{
|
|
if (upAvailable != 0)
|
|
{
|
|
byte* aboveRef = refr - refStride;
|
|
if (xd.MbToRightEdge < 0)
|
|
{
|
|
/* Slower path if the block needs border extension */
|
|
if (x0 + bs <= frameWidth)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
}
|
|
else if (x0 <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + bs - frameWidth);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Faster path if the block does not need extension */
|
|
if (bs == 4 && rightAvailable != 0 && leftAvailable != 0)
|
|
{
|
|
constAboveRow = aboveRef;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
}
|
|
}
|
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow, (byte)127, bs);
|
|
aboveRow[-1] = 127;
|
|
}
|
|
}
|
|
|
|
// NEED_ABOVERIGHT
|
|
if ((ExtendModes[(int)mode] & NeedAboveRight) != 0)
|
|
{
|
|
if (upAvailable != 0)
|
|
{
|
|
byte* aboveRef = refr - refStride;
|
|
if (xd.MbToRightEdge < 0)
|
|
{
|
|
/* Slower path if the block needs border extension */
|
|
if (x0 + 2 * bs <= frameWidth)
|
|
{
|
|
if (rightAvailable != 0 && bs == 4)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, 2 * bs);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
}
|
|
else if (x0 + bs <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
if (rightAvailable != 0 && bs == 4)
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
}
|
|
else if (x0 <= frameWidth)
|
|
{
|
|
int r = frameWidth - x0;
|
|
MemoryUtil.Copy(aboveRow, aboveRef, r);
|
|
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Faster path if the block does not need extension */
|
|
if (bs == 4 && rightAvailable != 0 && leftAvailable != 0)
|
|
{
|
|
constAboveRow = aboveRef;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
|
if (bs == 4 && rightAvailable != 0)
|
|
{
|
|
MemoryUtil.Copy(aboveRow + bs, aboveRef + bs, bs);
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow + bs, aboveRow[bs - 1], bs);
|
|
}
|
|
}
|
|
}
|
|
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
|
}
|
|
else
|
|
{
|
|
MemoryUtil.Fill(aboveRow, (byte)127, bs * 2);
|
|
aboveRow[-1] = 127;
|
|
}
|
|
}
|
|
|
|
// Predict
|
|
if (mode == PredictionMode.DcPred)
|
|
{
|
|
_dcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
|
}
|
|
else
|
|
{
|
|
_pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
|
|
}
|
|
}
|
|
|
|
public static unsafe void PredictIntraBlock(
|
|
ref MacroBlockD xd,
|
|
int bwlIn,
|
|
TxSize txSize,
|
|
PredictionMode mode,
|
|
byte* refr,
|
|
int refStride,
|
|
byte* dst,
|
|
int dstStride,
|
|
int aoff,
|
|
int loff,
|
|
int plane)
|
|
{
|
|
int bw = 1 << bwlIn;
|
|
int txw = 1 << (int)txSize;
|
|
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
|
|
int haveLeft = aoff != 0 || !xd.LeftMi.IsNull ? 1 : 0;
|
|
int haveRight = (aoff + txw) < bw ? 1 : 0;
|
|
int x = aoff * 4;
|
|
int y = loff * 4;
|
|
|
|
if (xd.CurBuf.HighBd)
|
|
{
|
|
BuildIntraPredictorsHigh(
|
|
ref xd,
|
|
refr,
|
|
refStride,
|
|
dst,
|
|
dstStride,
|
|
mode,
|
|
txSize,
|
|
haveTop,
|
|
haveLeft,
|
|
haveRight,
|
|
x,
|
|
y,
|
|
plane);
|
|
return;
|
|
}
|
|
BuildIntraPredictors(
|
|
ref xd,
|
|
refr,
|
|
refStride,
|
|
dst,
|
|
dstStride,
|
|
mode,
|
|
txSize,
|
|
haveTop,
|
|
haveLeft,
|
|
haveRight,
|
|
x,
|
|
y,
|
|
plane);
|
|
}
|
|
}
|
|
}
|