📄 aiccabac.pas
字号:
unit AICCabac;
{ Advanced Image Coding (AIC)
===========================
Base class for Context Adaptive Binary Arithmetic Coding.
Parts of the code in this unit are based on the H.264 reference software.
See JM.txt for license details. }
interface
uses
AICCommon, Classes;
type
PCabacContext = ^TCabacContext;
TCabacContext = record
{ Represents a context by a state (0..63) and Most Probable Symbol (0/1) }
State: Cardinal;
MPS : Cardinal;
end;
const
CabacCodeStreamSize = 8192;
{ The Cabac codec reads or writes 8192 bytes at a time }
CabacBits = 10;
{ Precision of Cabac values in bits }
CabacOne = 1 shl CabacBits;
{ The value 1 expressed as an integer with a precision of CabacBits bits }
CabacHalf = 1 shl (CabacBits - 1);
{ The value 0.5 expressed as an integer with a precision of CabacBits bits }
CabacQuarter = 1 shl (CabacBits - 2);
{ The value 0.25 expressed as an integer with a precision of CabacBits bits }
CabacExpStart = 13;
{ A threshold used to encode or decode exponential Golomb codes }
type
TAICCabac = class
{ Base class for Context Adaptive Binary Arithmetic Coding (as used by the
H.264 video coding standard) }
private
FQuality: TAICQuality;
{ The quality level of the image. Used to initialize the contexts with
appropriate values for this setting }
FStream: TStream;
{ The stream used for reading and writing Cabac codes }
procedure InitializeContexts;
{ Initializes all contexts with appropriate values for Quality }
procedure InitializeContext(out Context: TCabacContext; const M, N: Integer);
{ Used by InitializeContexts }
procedure InitializeContext1D(const InitData; out Contexts;
const Count: Integer);
{ Used by InitializeContexts }
procedure InitializeContext2D(const InitData; out Contexts;
const Count: Integer);
{ Used by InitializeContexts }
protected
BitsToGo: Integer;
{ The number of bits left in the current byte (Buffer) }
Buffer: Cardinal;
{ The current byte containing encoded/decoded bits }
Range: Cardinal;
{ The current range representing the probabilities of recent symbols }
Low: Cardinal;
{ The current lower value representing the probabilities of recent symbols }
CodeStream: array [0..CabacCodeStreamSize - 1] of Byte;
{ A buffer used for speeding up reading to and writing from files }
CodeStreamLen: Integer;
{ The length of the CodeStream }
CtxPredictionMode: array [0..1] of TCabacContext;
{ The contexts used to encode/decode the prediction mode.
Context 0 is used to code a boolean specifying if the predicted prediction
mode is used.
Context 1 is used when the actual prediction mode differs from the
predicted one. This context is used to encode the actual prediction mode }
CtxCoefficientMap: array [TAICChannelType,0..62] of TCabacContext;
{ The contexts used to encode/decode boolean values indicating if the
coefficients at position 0..62 in the zig zag array are
significant (<> 0). }
CtxLastCoefficient: array [TAICChannelType,0..62] of TCabacContext;
{ The contexts used to encode/decode boolean values indicating if the
coefficient at position 0..62 in the zig zag array is the last
significant coefficient. }
CtxCoefGreaterOne: array [TAICChannelType,0..4] of TCabacContext;
{ The contexts used to encode/decode if a the absolute value of a
coefficient is greater than 1 }
CtxCoefAbsolute: array [TAICChannelType,0..4] of TCabacContext;
{ The contexts used to encode/decode the absolute value of a coefficient
when it is greater than 1 }
CtxCodedBlock: TCabacContext;
{ The context used to encode/decode if a block of coefficients contains
non-zero values }
property Stream: TStream read FStream;
{ The stream used for reading and writing Cabac codes }
public
constructor Create(const AQuality: TAICQuality; const AStream: TStream);
end;
const
CabacRLPSTable: array [0..63,0..3] of Byte = (
( 128, 176, 208, 240),
( 128, 167, 197, 227),
( 128, 158, 187, 216),
( 123, 150, 178, 205),
( 116, 142, 169, 195),
( 111, 135, 160, 185),
( 105, 128, 152, 175),
( 100, 122, 144, 166),
( 95, 116, 137, 158),
( 90, 110, 130, 150),
( 85, 104, 123, 142),
( 81, 99, 117, 135),
( 77, 94, 111, 128),
( 73, 89, 105, 122),
( 69, 85, 100, 116),
( 66, 80, 95, 110),
( 62, 76, 90, 104),
( 59, 72, 86, 99),
( 56, 69, 81, 94),
( 53, 65, 77, 89),
( 51, 62, 73, 85),
( 48, 59, 69, 80),
( 46, 56, 66, 76),
( 43, 53, 63, 72),
( 41, 50, 59, 69),
( 39, 48, 56, 65),
( 37, 45, 54, 62),
( 35, 43, 51, 59),
( 33, 41, 48, 56),
( 32, 39, 46, 53),
( 30, 37, 43, 50),
( 29, 35, 41, 48),
( 27, 33, 39, 45),
( 26, 31, 37, 43),
( 24, 30, 35, 41),
( 23, 28, 33, 39),
( 22, 27, 32, 37),
( 21, 26, 30, 35),
( 20, 24, 29, 33),
( 19, 23, 27, 31),
( 18, 22, 26, 30),
( 17, 21, 25, 28),
( 16, 20, 23, 27),
( 15, 19, 22, 25),
( 14, 18, 21, 24),
( 14, 17, 20, 23),
( 13, 16, 19, 22),
( 12, 15, 18, 21),
( 12, 14, 17, 20),
( 11, 14, 16, 19),
( 11, 13, 15, 18),
( 10, 12, 15, 17),
( 10, 12, 14, 16),
( 9, 11, 13, 15),
( 9, 11, 12, 14),
( 8, 10, 12, 14),
( 8, 9, 11, 13),
( 7, 9, 11, 12),
( 7, 9, 10, 12),
( 7, 8, 10, 11),
( 6, 8, 9, 11),
( 6, 7, 9, 10),
( 6, 7, 8, 9),
( 2, 2, 2, 2));
const
CabacACNextStateMPS: array [0..63] of Byte = (
1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,
51,52,53,54,55,56,57,58,59,60,
61,62,62,63);
const
CabacACNextStateLPS: array [0..63] of Byte = (
0, 0, 1, 2, 2, 4, 4, 5, 6, 7,
8, 9, 9,11,11,12,13,13,15,15,
16,16,18,18,19,19,21,21,22,22,
23,24,24,25,26,26,27,27,28,29,
29,30,30,30,31,32,32,33,33,33,
34,34,35,35,35,36,36,36,37,37,
37,38,38,63);
implementation
uses
Math;
type
TInitData = array [0..62,0..1] of Integer;
TContexts = array [0..999] of TCabacContext;
const
InitPredictionMode: array [0..1,0..1] of Integer = (
( 2, 48),( 4, 67));
InitCoefficientMap: array [0..62,0..1] of Integer = (
( 7, 67),( 8, 61),( 8, 60),( 10, 40),( 8, 59),( 2, 64),( 4, 54),
( 3, 61),( 9, 50),( 11, 35),( 31,-22),( 10, 34),( 5, 52),( 0, 62),
( 0, 59),( 3, 54),( 2, 58),( 1, 59),( 7, 45),( 14, 27),( 28,-15),
( 41,-56),( 31,-27),( 29,-15),( 3, 51),( 2, 58),( 0, 59),( 1, 56),
( 10, 28),( 4, 51),( -1, 61),( -2, 61),( 0, 52),( 7, 24),( 26,-24),
( 24,-13),( 53,-88),( 44,-61),( 5, 36),( 1, 50),( -3, 58),( -2, 61),
( 6, 46),( 1, 52),( -5, 64),( -6, 60),( 1, 48),( 4, 38),( 35,-41),
( 34,-39),( 6, 46),( -3, 56),( -1, 55),( -2, 63),( -7, 62),( -2, 62),
( -3, 61),( -1, 59),( -3, 60),( -2, 61),( -1, 70),( -4, 71),( 2, 69));
InitLastCoefficient: array [0..62,0..1] of Integer = (
(-29, 66),(-25, 65),(-28, 70),(-22, 39),(-28, 72),(-23, 61),(-22, 54),
(-21, 60),(-22, 64),(-25, 60),(-20, 37),(-15, 39),(-20, 56),(-19, 54),
(-25, 67),(-22, 59),(-20, 57),(-25, 65),(-26, 70),(-19, 52),(-22, 56),
(-23, 60),(-17, 41),(-19, 51),(-24, 61),(-20, 54),(-27, 62),(-25, 77),
(-21, 78),(-26, 71),(-18, 68),(-22, 63),(-27, 72),(-24, 71),(-22, 65),
(-22, 70),(-23, 72),(-21, 64),(-24, 64),(-24, 74),(-24, 75),(-24, 80),
(-22, 81),(-20, 74),(-20, 71),(-25, 78),(-20, 78),(-20, 78),( -5, 55),
(-14, 63),(-21, 74),(-16, 77),(-16, 70),( -7, 63),(-12, 70),(-12, 71),
( -4, 60),( 5, 49),( 1, 50),( 7, 46),( 5, 55),( 15, 41),( 25, 30));
InitCoefGreaterOne: array [0..4,0..1] of Integer = (
( 5, 57),(181,-493),(129,-330),(-7,32),( -2, 45));
InitCoefAbsolute: array [0..4,0..1] of Integer = (
( 7, 28),( 2, 48),( 0, 57),( 1, 59),( 11, 55));
InitCodedBlock: array [0..0,0..1] of Integer = (
( 31, 40));
{ TAICCabac }
constructor TAICCabac.Create(const AQuality: TAICQuality;
const AStream: TStream);
begin
inherited Create;
FQuality := AQuality;
FStream := AStream;
InitializeContexts;
end;
procedure TAICCabac.InitializeContext(out Context: TCabacContext; const M,
N: Integer);
var
State: Integer;
begin
State := ((M * FQuality) div 32) + N;
State := EnsureRange(State,1,126);
if State >= 64 then begin
Context.State := State - 64;
Context.MPS := 1;
end else begin
Context.State := 63 - State;
Context.MPS := 0;
end;
end;
procedure TAICCabac.InitializeContext1D(const InitData; out Contexts;
const Count: Integer);
var
D: TInitData absolute InitData;
C: TContexts absolute Contexts;
J: Integer;
begin
for J := 0 to Count - 1 do
InitializeContext(C[J],D[J,0],D[J,1]);
end;
procedure TAICCabac.InitializeContext2D(const InitData; out Contexts;
const Count: Integer);
var
D: TInitData absolute InitData;
C: TContexts absolute Contexts;
CT: TAICChannelType;
J: Integer;
begin
for CT := System.Low(TAICChannelType) to High(TAICChannelType) do
for J := 0 to Count - 1 do
InitializeContext(C[Ord(CT) * Count + J],D[J,0],D[J,1]);
end;
procedure TAICCabac.InitializeContexts;
begin
InitializeContext1D(InitPredictionMode,CtxPredictionMode,2);
InitializeContext2D(InitPredictionMode,CtxPredictionMode,63);
InitializeContext2D(InitLastCoefficient,CtxLastCoefficient,63);
InitializeContext2D(InitCoefGreaterOne,CtxCoefGreaterOne,5);
InitializeContext2D(InitCoefAbsolute,CtxCoefAbsolute,5);
InitializeContext1D(InitCodedBlock,CtxCodedBlock,1);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -