satdump/src-core/libs/bpe/PatternCoding.c

583 lines
26 KiB
C
Raw Permalink Normal View History

2026-05-22 17:54:17 +02:00
#include <stdlib.h>
#include "bpe_internal.h"
const int bit2_pattern[] = {0, 2, 1, 3};
const int bit3_pattern[] = {1, 4, 0, 5, 2, 6, 3, 7};
const int bit3_pattern_TranD[] = {0, 3, 0, 4, 1, 5, 2, 6};
const int bit4_pattern_TypeCi[] = {10, 1, 3, 6, 2, 5, 9, 12, 0, 8, 7, 13, 4, 14, 11, 15};
const int bit4_pattern_TypeHij_TranHi[] = {0, 1, 3, 6, 2, 5, 9, 11, 0, 8, 7, 12, 4, 13, 10, 14};
extern void StagesEnCodingGaggles1(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8[], BOOL[]);
extern void StagesEnCodingGaggles2(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8[], BOOL[]);
extern void StagesEnCodingGaggles3(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8[], BOOL[]);
extern void StagesDeCodingGaggles1(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8 *, BOOL *);
extern void StagesDeCodingGaggles2(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8 *, BOOL *);
extern void StagesDeCodingGaggles3(StructCodingPara *, BitPlaneBits *,
UCHAR8, UCHAR8 *, BOOL *);
void PatternMapping(StrSymbolDetails *StrSymbol)
{
switch (StrSymbol->sym_len) {
case 0: return;
case 1: StrSymbol->sym_mapped_pattern = StrSymbol->sym_val; break;
case 2: StrSymbol->sym_mapped_pattern = bit2_pattern[StrSymbol->sym_val]; break;
case 3:
if (StrSymbol->type == ENUM_TRAN_D)
StrSymbol->sym_mapped_pattern = bit3_pattern_TranD[StrSymbol->sym_val];
else
StrSymbol->sym_mapped_pattern = bit3_pattern[StrSymbol->sym_val];
break;
case 4:
if (StrSymbol->type == ENUM_TYPE_CI)
StrSymbol->sym_mapped_pattern = bit4_pattern_TypeCi[StrSymbol->sym_val];
else if (StrSymbol->type == ENUM_TRAN_HI || StrSymbol->type == ENUM_TYPE_HIJ)
StrSymbol->sym_mapped_pattern = bit4_pattern_TypeHij_TranHi[StrSymbol->sym_val];
break;
default:
ErrorMsg(BPE_PATTERNING_CODING_ERROR);
}
}
void DeMappingPattern(StrSymbolDetails *StrSymbol)
{
UCHAR8 i;
switch (StrSymbol->sym_len) {
case 1:
StrSymbol->sym_val = StrSymbol->sym_mapped_pattern;
break;
case 2:
for (i = 0; i < 4; i++) {
if (StrSymbol->sym_mapped_pattern == bit2_pattern[i]) {
StrSymbol->sym_val = i;
break;
}
}
break;
case 3:
if (StrSymbol->type == ENUM_TRAN_D) {
for (i = 1; i < 8; i++) {
if (StrSymbol->sym_mapped_pattern == bit3_pattern_TranD[i]) {
StrSymbol->sym_val = i;
break;
}
}
} else {
for (i = 0; i < 8; i++) {
if (StrSymbol->sym_mapped_pattern == bit3_pattern[i]) {
StrSymbol->sym_val = i;
break;
}
}
}
break;
case 4:
if (StrSymbol->type == ENUM_TYPE_CI) {
for (i = 0; i < 16; i++) {
if (StrSymbol->sym_mapped_pattern == bit4_pattern_TypeCi[i]) {
StrSymbol->sym_val = i;
break;
}
}
} else if (StrSymbol->type == ENUM_TRAN_HI || StrSymbol->type == ENUM_TYPE_HIJ) {
for (i = 1; i < 16; i++) {
if (StrSymbol->sym_mapped_pattern == bit4_pattern_TypeHij_TranHi[i]) {
StrSymbol->sym_val = i;
break;
}
}
}
break;
default:
ErrorMsg(BPE_PATTERNING_CODING_ERROR);
}
}
void BitPlaneSymbolReset(StrSymbolDetails *SymbolStr)
{
SymbolStr->sign = 0;
SymbolStr->sym_len = 0;
SymbolStr->sym_mapped_pattern = 0;
SymbolStr->sym_val = 0;
SymbolStr->type = 0;
}
void CodingOptions(StructCodingPara *PtrCoding,
BitPlaneBits *BlockInfo,
UINT32 BlocksInGaggle,
UCHAR8 Option[])
{
DWORD32 BlockSeq = 0;
DWORD32 bitsCounter_2Bits[2] = {0};
DWORD32 bitsCounter_3Bits[3] = {0};
DWORD32 bitsCounter_4Bits[4] = {0};
for (BlockSeq = 0; BlockSeq < BlocksInGaggle; BlockSeq++) {
UCHAR8 SymbolIndex = 0;
if (BlockInfo[BlockSeq].BitMaxAC < PtrCoding->BitPlane)
continue;
for (SymbolIndex = 0; SymbolIndex < MAX_SYMBOLS_IN_BLOCK; SymbolIndex++) {
if (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].type == ENUM_NONE)
continue;
else if (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_len == 1) {
PatternMapping(&BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex]);
continue;
}
PatternMapping(&BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex]);
if (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_len == 2) {
switch (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_mapped_pattern) {
case 0: bitsCounter_2Bits[0] += 1; break;
case 1: bitsCounter_2Bits[0] += 2; break;
case 2: bitsCounter_2Bits[0] += 3; break;
case 3: bitsCounter_2Bits[0] += 3; break;
default: ErrorMsg(BPE_PATTERNING_CODING_ERROR);
}
bitsCounter_2Bits[1] += 2;
} else if (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_len == 3) {
UCHAR8 p = BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_mapped_pattern;
if (p <= 2) bitsCounter_3Bits[0] += p + 1;
else if (p <= 5) bitsCounter_3Bits[0] += 5;
else if (p <= 7) bitsCounter_3Bits[0] += 6;
else ErrorMsg(BPE_PATTERNING_CODING_ERROR);
if (p <= 1) bitsCounter_3Bits[1] += 2;
else if (p <= 3) bitsCounter_3Bits[1] += 3;
else if (p <= 7) bitsCounter_3Bits[1] += 4;
else ErrorMsg(BPE_PATTERNING_CODING_ERROR);
bitsCounter_3Bits[2] += 3;
} else if (BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_len == 4) {
UCHAR8 p = BlockInfo[BlockSeq].SymbolsBlock[SymbolIndex].sym_mapped_pattern;
if (p <= 3) bitsCounter_4Bits[0] += p + 1;
else if (p <= 7) bitsCounter_4Bits[0] += 7;
else if (p <= 15) bitsCounter_4Bits[0] += 8;
else ErrorMsg(BPE_PATTERNING_CODING_ERROR);
if (p <= 1) bitsCounter_4Bits[1] += 2;
else if (p <= 3) bitsCounter_4Bits[1] += 3;
else if (p <= 5) bitsCounter_4Bits[1] += 4;
else if (p <= 11) bitsCounter_4Bits[1] += 6;
else if (p <= 15) bitsCounter_4Bits[1] += 7;
else ErrorMsg(BPE_PATTERNING_CODING_ERROR);
if (p <= 3) bitsCounter_4Bits[2] += 3;
else if (p <= 7) bitsCounter_4Bits[2] += 4;
else if (p <= 15) bitsCounter_4Bits[2] += 5;
else ErrorMsg(BPE_PATTERNING_CODING_ERROR);
bitsCounter_4Bits[3] += 4;
}
}
}
Option[0] = (bitsCounter_2Bits[0] < bitsCounter_2Bits[1]) ? 0 : 1;
if (bitsCounter_3Bits[2] <= bitsCounter_3Bits[0] &&
bitsCounter_3Bits[2] <= bitsCounter_3Bits[1])
Option[1] = 3;
else if (bitsCounter_3Bits[0] <= bitsCounter_3Bits[1] &&
bitsCounter_3Bits[0] <= bitsCounter_3Bits[2])
Option[1] = 0;
else
Option[1] = 1;
if (bitsCounter_4Bits[3] <= bitsCounter_4Bits[0] &&
bitsCounter_4Bits[3] <= bitsCounter_4Bits[1] &&
bitsCounter_4Bits[3] <= bitsCounter_4Bits[2])
Option[2] = 3;
else if (bitsCounter_4Bits[0] <= bitsCounter_4Bits[1] &&
bitsCounter_4Bits[0] <= bitsCounter_4Bits[2] &&
bitsCounter_4Bits[0] <= bitsCounter_4Bits[3])
Option[2] = 0;
else if (bitsCounter_4Bits[1] <= bitsCounter_4Bits[0] &&
bitsCounter_4Bits[1] <= bitsCounter_4Bits[2] &&
bitsCounter_4Bits[1] <= bitsCounter_4Bits[3])
Option[2] = 1;
else
Option[2] = 2;
}
void RefBitsDe(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo)
{
UINT32 BlockSeq;
UCHAR8 i, j, k, p;
DWORD32 TempWord;
long **block;
UCHAR8 BitPlane = PtrCoding->BitPlane;
if (PtrCoding->PtrHeader->Header.Part2.StageStop_2Bits < 3 &&
(PtrCoding->PtrHeader->Header.Part2.BitPlaneStop_5Bits == BitPlane - 1 ||
PtrCoding->altStrageStop))
return;
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = 0;
for (BlockSeq = 0; BlockSeq < PtrCoding->PtrHeader->Header.Part3.S_20Bits; BlockSeq++) {
if (BlockInfo[BlockSeq].BitMaxAC < BitPlane)
continue;
block = BlockInfo[BlockSeq].PtrBlockAddress;
if (BlockInfo[BlockSeq].RefineBits.RefineParent.ParentSymbolLength > 0) {
if (PtrCoding->SegmentFull == TRUE || PtrCoding->RateReached == TRUE)
return;
for (i = 0; i < 3; i++) {
UCHAR8 temp_x = 0, temp_y = 0;
if ((BlockInfo[BlockSeq].RefineBits.RefineParent.ParentRefSymbol & (1 << (2 - i))) > 0) {
UCHAR8 code = 0;
BitsRead(PtrCoding, &TempWord, 1);
code = (UCHAR8)TempWord;
BlockInfo[BlockSeq].RefineBits.RefineParent.ParentSymbolLength--;
temp_x = (i >= 1 ? 1 : 0);
temp_y = (i != 1 ? 1 : 0);
if (code > 0) {
if (block[temp_x][temp_y] > 0)
block[temp_x][temp_y] += (1 << (BitPlane - 1));
else
block[temp_x][temp_y] -= (1 << (BitPlane - 1));
}
}
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE &&
!PtrCoding->DecodingStopLocations.LocationFind) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = BlockSeq;
PtrCoding->DecodingStopLocations.X_LocationStopDecoding = temp_x;
PtrCoding->DecodingStopLocations.Y_LocationStopDecoding = temp_y;
PtrCoding->DecodingStopLocations.LocationFind = TRUE;
return;
}
}
BlockInfo[BlockSeq].RefineBits.RefineParent.ParentRefSymbol = 0;
BlockInfo[BlockSeq].RefineBits.RefineParent.ParentSymbolLength = 0;
}
if (BlockInfo[BlockSeq].RefineBits.RefineChildren.ChildrenSymbolLength > 0) {
if (PtrCoding->SegmentFull == TRUE || PtrCoding->RateReached == TRUE)
break;
for (k = 0; k < 3; k++) {
UCHAR8 counter = 3;
UCHAR8 temp_x = (UCHAR8)((k >= 1 ? 1 : 0) * 2);
UCHAR8 temp_y = (UCHAR8)((k != 1 ? 1 : 0) * 2);
for (i = temp_x; i < temp_x + 2; i++)
for (j = temp_y; j < temp_y + 2; j++) {
if ((BlockInfo[BlockSeq].RefineBits.RefineChildren.ChildrenRefSymbol &
(1 << (8 - k * 4 + counter))) > 0) {
UCHAR8 code = 0;
BitsRead(PtrCoding, &TempWord, 1);
code = (UCHAR8)TempWord;
BlockInfo[BlockSeq].RefineBits.RefineChildren.ChildrenSymbolLength--;
if (code > 0) {
if (block[i][j] > 0)
block[i][j] += (1 << (BitPlane - 1));
else
block[i][j] -= (1 << (BitPlane - 1));
}
}
counter--;
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE &&
!PtrCoding->DecodingStopLocations.LocationFind) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = BlockSeq;
PtrCoding->DecodingStopLocations.X_LocationStopDecoding = i;
PtrCoding->DecodingStopLocations.Y_LocationStopDecoding = j;
PtrCoding->DecodingStopLocations.LocationFind = TRUE;
return;
}
}
}
BlockInfo[BlockSeq].RefineBits.RefineChildren.ChildrenRefSymbol = 0;
BlockInfo[BlockSeq].RefineBits.RefineChildren.ChildrenSymbolLength = 0;
}
for (i = 0; i < 3; i++) {
if (BlockInfo[BlockSeq].RefineBits.RefineGrandChildren[i].GrandChildrenSymbolLength > 0) {
if (PtrCoding->SegmentFull == TRUE || PtrCoding->RateReached == TRUE)
break;
for (j = 0; j < 4; j++) {
UCHAR8 counter = 3;
UCHAR8 temp_x = (UCHAR8)((i >= 1 ? 1 : 0) * 4 + (j >= 2 ? 1 : 0) * 2);
UCHAR8 temp_y = (UCHAR8)((i != 1 ? 1 : 0) * 4 + (j % 2) * 2);
for (k = temp_x; k < temp_x + 2; k++)
for (p = temp_y; p < temp_y + 2; p++) {
if ((BlockInfo[BlockSeq].RefineBits.RefineGrandChildren[i].GrandChildrenRefSymbol &
(1 << (12 - j * 4 + counter))) > 0) {
UCHAR8 code = 0;
BitsRead(PtrCoding, &TempWord, 1);
code = (UCHAR8)TempWord;
BlockInfo[BlockSeq].RefineBits.RefineGrandChildren[i].GrandChildrenSymbolLength--;
if (code > 0) {
if (block[k][p] > 0)
block[k][p] += (1 << (BitPlane - 1));
else
block[k][p] -= (1 << (BitPlane - 1));
}
}
counter--;
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE &&
!PtrCoding->DecodingStopLocations.LocationFind) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = BlockSeq;
PtrCoding->DecodingStopLocations.X_LocationStopDecoding = k;
PtrCoding->DecodingStopLocations.Y_LocationStopDecoding = p;
PtrCoding->DecodingStopLocations.LocationFind = TRUE;
return;
}
}
}
}
BlockInfo[BlockSeq].RefineBits.RefineGrandChildren[i].GrandChildrenRefSymbol = 0;
BlockInfo[BlockSeq].RefineBits.RefineGrandChildren[i].GrandChildrenSymbolLength = 0;
}
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE)
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = BlockSeq;
}
}
void RefBitsEn(BitPlaneBits *BlockInfo, StructCodingPara *PtrCoding)
{
UINT32 i;
UCHAR8 j;
if (PtrCoding->PtrHeader->Header.Part2.StageStop_2Bits < 3 &&
(PtrCoding->PtrHeader->Header.Part2.BitPlaneStop_5Bits == PtrCoding->BitPlane - 1 ||
PtrCoding->altStrageStop))
return;
for (i = 0; i < PtrCoding->PtrHeader->Header.Part3.S_20Bits; i++) {
if (BlockInfo[i].RefineBits.RefineParent.ParentSymbolLength > 0) {
BitsOutput(PtrCoding,
BlockInfo[i].RefineBits.RefineParent.ParentRefSymbol,
BlockInfo[i].RefineBits.RefineParent.ParentSymbolLength);
BlockInfo[i].RefineBits.RefineParent.ParentRefSymbol = 0;
BlockInfo[i].RefineBits.RefineParent.ParentSymbolLength = 0;
}
if (BlockInfo[i].RefineBits.RefineChildren.ChildrenSymbolLength > 0) {
BitsOutput(PtrCoding,
BlockInfo[i].RefineBits.RefineChildren.ChildrenRefSymbol,
BlockInfo[i].RefineBits.RefineChildren.ChildrenSymbolLength);
BlockInfo[i].RefineBits.RefineChildren.ChildrenRefSymbol = 0;
BlockInfo[i].RefineBits.RefineChildren.ChildrenSymbolLength = 0;
}
for (j = 0; j < 3; j++) {
if (BlockInfo[i].RefineBits.RefineGrandChildren[j].GrandChildrenSymbolLength > 0)
BitsOutput(PtrCoding,
BlockInfo[i].RefineBits.RefineGrandChildren[j].GrandChildrenRefSymbol,
BlockInfo[i].RefineBits.RefineGrandChildren[j].GrandChildrenSymbolLength);
BlockInfo[i].RefineBits.RefineGrandChildren[j].GrandChildrenRefSymbol = 0;
BlockInfo[i].RefineBits.RefineGrandChildren[j].GrandChildrenSymbolLength = 0;
}
}
}
void StagesEnCoding(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo)
{
UCHAR8 BlocksInLastGaggle = 0;
DWORD32 TotalGaggles;
DWORD32 GaggleIndex = 0;
UCHAR8 **CodeOptionsAllGaggles;
UCHAR8 BlocksInGaggle = 0;
UINT32 BlockStartIndex = 0;
BOOL **OptionHitFlag;
UINT32 SymbolIndex;
BlocksInLastGaggle = (UCHAR8)(PtrCoding->PtrHeader->Header.Part3.S_20Bits % GAGGLE_SIZE);
TotalGaggles = PtrCoding->PtrHeader->Header.Part3.S_20Bits / GAGGLE_SIZE;
if (BlocksInLastGaggle != 0) TotalGaggles++;
CodeOptionsAllGaggles = (UCHAR8 **)calloc(TotalGaggles, sizeof(UCHAR8 *));
OptionHitFlag = (BOOL **) calloc(TotalGaggles, sizeof(BOOL *));
if (!CodeOptionsAllGaggles || !OptionHitFlag) {
free(CodeOptionsAllGaggles);
free(OptionHitFlag);
ErrorMsg(BPE_MEM_ERROR);
}
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
CodeOptionsAllGaggles[GaggleIndex] = (UCHAR8 *)calloc(3, sizeof(UCHAR8));
OptionHitFlag[GaggleIndex] = (BOOL *) calloc(3, sizeof(BOOL));
if (!CodeOptionsAllGaggles[GaggleIndex] || !OptionHitFlag[GaggleIndex])
goto en_cleanup;
OptionHitFlag[GaggleIndex][0] = FALSE;
OptionHitFlag[GaggleIndex][1] = FALSE;
OptionHitFlag[GaggleIndex][2] = FALSE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
CodingOptions(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex]);
StagesEnCodingGaggles1(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
}
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
StagesEnCodingGaggles2(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
}
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
StagesEnCodingGaggles3(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
}
RefBitsEn(BlockInfo, PtrCoding);
for (BlockStartIndex = 0;
BlockStartIndex < PtrCoding->PtrHeader->Header.Part3.S_20Bits;
BlockStartIndex++) {
int j;
for (SymbolIndex = 0; SymbolIndex < MAX_SYMBOLS_IN_BLOCK; SymbolIndex++)
BitPlaneSymbolReset(&BlockInfo[BlockStartIndex].SymbolsBlock[SymbolIndex]);
BlockInfo[BlockStartIndex].RefineBits.RefineParent.ParentRefSymbol = 0;
BlockInfo[BlockStartIndex].RefineBits.RefineParent.ParentSymbolLength = 0;
BlockInfo[BlockStartIndex].RefineBits.RefineChildren.ChildrenRefSymbol = 0;
BlockInfo[BlockStartIndex].RefineBits.RefineChildren.ChildrenSymbolLength = 0;
for (j = 0; j < 3; j++) {
BlockInfo[BlockStartIndex].RefineBits.RefineGrandChildren[j].GrandChildrenRefSymbol = 0;
BlockInfo[BlockStartIndex].RefineBits.RefineGrandChildren[j].GrandChildrenSymbolLength = 0;
}
}
en_cleanup:
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
free(CodeOptionsAllGaggles[GaggleIndex]);
free(OptionHitFlag[GaggleIndex]);
}
free(CodeOptionsAllGaggles);
free(OptionHitFlag);
}
void StagesDeCoding(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo)
{
UCHAR8 BlocksInLastGaggle = 0;
DWORD32 TotalGaggles;
DWORD32 GaggleIndex = 0;
UCHAR8 **CodeOptionsAllGaggles;
UCHAR8 BlocksInGaggle = 0;
UINT32 BlockStartIndex = 0;
BOOL **OptionHitFlag;
BlocksInLastGaggle = (UCHAR8)(PtrCoding->PtrHeader->Header.Part3.S_20Bits % GAGGLE_SIZE);
TotalGaggles = PtrCoding->PtrHeader->Header.Part3.S_20Bits / GAGGLE_SIZE;
if (BlocksInLastGaggle != 0) TotalGaggles++;
CodeOptionsAllGaggles = (UCHAR8 **)calloc(TotalGaggles, sizeof(UCHAR8 *));
OptionHitFlag = (BOOL **) calloc(TotalGaggles, sizeof(BOOL *));
if (!CodeOptionsAllGaggles || !OptionHitFlag) {
free(CodeOptionsAllGaggles);
free(OptionHitFlag);
ErrorMsg(BPE_MEM_ERROR);
}
PtrCoding->DecodingStopLocations.BlockNoStopDecoding = 0;
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
CodeOptionsAllGaggles[GaggleIndex] = (UCHAR8 *)calloc(3, sizeof(UCHAR8));
OptionHitFlag[GaggleIndex] = (BOOL *) calloc(3, sizeof(BOOL));
if (!CodeOptionsAllGaggles[GaggleIndex] || !OptionHitFlag[GaggleIndex])
goto cleanup;
OptionHitFlag[GaggleIndex][0] = FALSE;
OptionHitFlag[GaggleIndex][1] = FALSE;
OptionHitFlag[GaggleIndex][2] = FALSE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
StagesDeCodingGaggles1(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding += GaggleIndex * 16;
PtrCoding->DecodingStopLocations.stoppedstage = 1;
goto cleanup;
}
}
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
StagesDeCodingGaggles2(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding += GaggleIndex * 16;
PtrCoding->DecodingStopLocations.stoppedstage = 2;
goto cleanup;
}
}
if (PtrCoding->RateReached == TRUE) {
PtrCoding->DecodingStopLocations.stoppedstage = 2;
goto cleanup;
}
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
BlockStartIndex = GaggleIndex * GAGGLE_SIZE;
BlocksInGaggle = (UCHAR8)((BlockStartIndex + GAGGLE_SIZE <
PtrCoding->PtrHeader->Header.Part3.S_20Bits)
? GAGGLE_SIZE
: (PtrCoding->PtrHeader->Header.Part3.S_20Bits - BlockStartIndex));
StagesDeCodingGaggles3(PtrCoding, &BlockInfo[BlockStartIndex],
BlocksInGaggle, CodeOptionsAllGaggles[GaggleIndex],
OptionHitFlag[GaggleIndex]);
if ((PtrCoding->DecodingStopLocations.BitPlaneStopDecoding != -1) &&
PtrCoding->RateReached == TRUE) {
PtrCoding->DecodingStopLocations.BlockNoStopDecoding += GaggleIndex * 16;
PtrCoding->DecodingStopLocations.stoppedstage = 3;
goto cleanup;
}
}
if (PtrCoding->RateReached == TRUE) {
PtrCoding->DecodingStopLocations.stoppedstage = 3;
goto cleanup;
}
RefBitsDe(PtrCoding, BlockInfo);
if (PtrCoding->RateReached == TRUE)
PtrCoding->DecodingStopLocations.stoppedstage = 4;
cleanup:
/* Free the per-gaggle arrays */
for (GaggleIndex = 0; GaggleIndex < TotalGaggles; GaggleIndex++) {
free(CodeOptionsAllGaggles[GaggleIndex]); /* free(NULL) is safe for unallocated entries */
free(OptionHitFlag[GaggleIndex]);
}
free(CodeOptionsAllGaggles);
free(OptionHitFlag);
}