Skip to content

Commit

Permalink
Merge pull request #425 from JeromeMartinez/DPX_Y_12
Browse files Browse the repository at this point in the history
Support of DPX/Y/12-bit/Packed/BE
  • Loading branch information
JeromeMartinez authored Dec 12, 2023
2 parents ec2ddb1 + 4e0b364 commit fce3a36
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 2 deletions.
1 change: 1 addition & 0 deletions Project/GNU/CLI/test/test1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ Formats/DPX/Flavors/Y_10_FilledB_BE/Y_10_FilledB_BE_Modified_8x4.dpx
Formats/DPX/Flavors/Y_10_FilledB_BE/Y_10_FilledB_BE_Modified_8x4_Scanity.dpx
Formats/DPX/Flavors/Y_10_FilledB_BE/Y_10_FilledB_BE_Modified_9x4.dpx
Formats/DPX/Flavors/Y_10_FilledB_BE/Y_10_FilledB_BE_Modified_9x4_Scanity.dpx
Formats/DPX/Flavors/Y_12_Packed_BE/086400.dpx pass
Formats/DPX/Flavors/Y_16_FilledA_BE/0000001.dpx pass
Formats/DPX/Flavors/Y_16_Packed_BE/FFmpeg_gray16be.dpx pass
Formats/DPX/Flavors/Y_16_Packed_LE/FFmpeg_gray16le.dpx pass
Expand Down
1 change: 1 addition & 0 deletions Source/CLI/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ bool parse_info::ParseFile_Input(input_base_uncompressed& SingleFile, input& Inp
{
case dpx::flavor::Raw_Y_10_FilledA_BE: // TODO: remove when we are confident enough, old FFmpeg are not fully compatible and future FFmpeg may change their behavior
case dpx::flavor::Raw_Y_10_FilledB_BE:
case dpx::flavor::Raw_Y_12_Packed_BE:
ForceCheck = true; // TODO: quicker check of FFmpeg support of alternate EOL
break;
default:;
Expand Down
170 changes: 170 additions & 0 deletions Source/Lib/Transform/Transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,175 @@ template <int Offset> class transform_passthrough_dpx_Raw_Y_10_FilledX_BE : publ
#define transform_passthrough_dpx_Raw_Y_10_FilledA_BE transform_passthrough_dpx_Raw_Y_10_FilledX_BE<2>
#define transform_passthrough_dpx_Raw_Y_10_FilledB_BE transform_passthrough_dpx_Raw_Y_10_FilledX_BE<0>

//---------------------------------------------------------------------------
void transform_passthrough_dpx_Raw_Y_12_Packed_BE_Finalize(raw_frame* RawFrame, size_t num_h_slices, size_t /*num_v_slices*/)
{
const auto& Plane = RawFrame->Plane(0);
auto FrameBufferBefore = Plane->Buffer_Extra().Data();
auto Line_SliceCount = Plane->Line_SliceCount();

const auto Width = Plane->Width();
const auto Height = Plane->Height();
size_t Slices_w = Width / num_h_slices;
for (size_t y = 0; y < Height; y++)
{
for (size_t slice_x = 0; slice_x < num_h_slices - 1; slice_x++)
{
auto x = slice_x * Width / num_h_slices;
auto x2 = (slice_x + 1) * Width / num_h_slices;
if (!(x2 % 8))
continue;
auto FrameBuffer = Plane->Buffer_Data(x2, y, true);
auto FrameBuffer_Temp_32 = (uint32_t*)FrameBuffer;
auto FrameBufferBefore_Temp_32 = (uint32_t*)FrameBufferBefore + x / Slices_w;
*FrameBuffer_Temp_32 |= *FrameBufferBefore_Temp_32;
FrameBuffer_Temp_32++;
}
FrameBufferBefore += Line_SliceCount * 4;
}
}

class transform_passthrough_dpx_Raw_Y_12_Packed_BE : public transform_dpx
{
public:
transform_passthrough_dpx_Raw_Y_12_Packed_BE(raw_frame* RawFrame, size_t x_offset, size_t y_offset, size_t w, size_t h) :
transform_dpx(RawFrame, x_offset, y_offset, w, h)
{
const auto& Plane = RawFrame->Plane(0);
auto Width = Plane->Width();
auto PixelsPerBlock = dpx::PixelsPerBlock((dpx::flavor)RawFrame->Flavor_Private);
auto HasBlockSpan = (x_offset % PixelsPerBlock) || ((x_offset + w) % PixelsPerBlock);
bool VFlip = dpx::IsVFlip(RawFrame->Flavor_Private);

if (!HasBlockSpan && !VFlip)
{
FrameBufferBefore = nullptr;
Data_Temp_Pos_Begin = 0;
return;
}

if (HasBlockSpan && !x_offset && !y_offset)
RawFrame->Finalize_Function = transform_passthrough_dpx_Raw_Y_12_Packed_BE_Finalize;

if (VFlip)
{
auto Height = Plane->Height();
y_offset = Height - 1 - y_offset;
}

auto FullLineBitCount = Width * 12;
auto FullLineBlockCount = FullLineBitCount / 32;
if (FullLineBitCount % 32)
FullLineBlockCount++;
auto SliceBeginBitCount = x_offset * 12;
auto SliceBeginBlockCount = SliceBeginBitCount / 32;
auto SliceEndBitCount = (x_offset + w) * 12;
auto SliceEndBlockCount = SliceEndBitCount / 32;

FrameBuffer = Plane->Buffer_Data() + (y_offset * FullLineBlockCount + SliceBeginBlockCount) * 4;
NextLine_Offset = SliceBeginBlockCount - SliceEndBlockCount; // -(SliceEndBlockCount - SliceBeginBlockCount)
if (VFlip)
NextLine_Offset -= FullLineBlockCount;
else
NextLine_Offset += FullLineBlockCount;
NextLine_Offset *= 4;
Data_Temp_Pos_Begin = x_offset % 8;

if (HasBlockSpan && x_offset + w < Width)
{
auto Line_SliceCount = Plane->Line_SliceCount();
FrameBufferBefore = Plane->Buffer_Extra().Data() + (Line_SliceCount * y_offset + (x_offset + 1) * Line_SliceCount / Width) * 4;
FrameBufferBefore_Offset = (uint32_t)(Line_SliceCount * 4);
}
else
FrameBufferBefore = nullptr; // Last block in a line is padded so should be written immediately
}

void From(pixel_t* y, pixel_t*, pixel_t*, pixel_t*)
{
uint32_t Data_Temp = 0;
auto Data_Temp_Pos = Data_Temp_Pos_Begin;
uint32_t* FrameBuffer_Temp_32;
size_t x = 0;

FrameBuffer_Temp_32 = (uint32_t*)FrameBuffer;

for (; x < w; x++)
{
switch (Data_Temp_Pos)
{
case 0:
{
Data_Temp = y[x];
break;
}
case 1:
{
Data_Temp |= y[x] << 12;
break;
}
case 2:
{
*(FrameBuffer_Temp_32++) = htob((uint32_t)((y[x] << 24) | Data_Temp));
Data_Temp = y[x] >> 8;
break;
}
case 3:
{
Data_Temp |= y[x] << 4;
break;
}
case 4:
{
Data_Temp |= y[x] << 16;
break;
}
case 5:
{
*(FrameBuffer_Temp_32++) = htob((uint32_t)((y[x] << 28) | Data_Temp));
Data_Temp = y[x] >> 4;
break;
}
case 6:
{
Data_Temp |= y[x] << 8;
break;
}
default:
{
*(FrameBuffer_Temp_32++) = htob((uint32_t)((y[x] << 20) | Data_Temp));
break;
}
}
Data_Temp_Pos = (Data_Temp_Pos + 1 ) % 8;
}
if (Data_Temp_Pos)
{
if (FrameBufferBefore)
{
auto FrameBufferBefore_Temp_32 = (uint32_t*)FrameBufferBefore;
*FrameBufferBefore_Temp_32 = htob(Data_Temp);
if ((intptr_t)NextLine_Offset < 0)
FrameBufferBefore -= FrameBufferBefore_Offset;
else
FrameBufferBefore += FrameBufferBefore_Offset;
}
else
{
*FrameBuffer_Temp_32 = htob(Data_Temp);
}
}

FrameBuffer = (uint8_t*)FrameBuffer_Temp_32;
Next();
}

protected:
uint8_t* FrameBufferBefore;
uint32_t Data_Temp_Pos_Begin;
uint32_t FrameBufferBefore_Offset;
};

//---------------------------------------------------------------------------
class transform_passthrough_dpx_Raw_Y_16_LE : public transform_dpx
{
Expand Down Expand Up @@ -1119,6 +1288,7 @@ transform_base* Transform_Init(raw_frame* RawFrame, pix_style PixStyle, size_t /
TRANSFORM_CASE(passthrough, dpx, Raw_Y_8)
TRANSFORM_CASE(passthrough, dpx, Raw_Y_10_FilledA_BE)
TRANSFORM_CASE(passthrough, dpx, Raw_Y_10_FilledB_BE)
TRANSFORM_CASE(passthrough, dpx, Raw_Y_12_Packed_BE)
TRANSFORM_CASE(passthrough, dpx, Raw_Y_16_LE)
TRANSFORM_CASE(passthrough, dpx, Raw_Y_16_BE)
TRANSFORM_FLAVOR_END()
Expand Down
5 changes: 3 additions & 2 deletions Source/Lib/Uncompressed/DPX/DPX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ struct dpx_tested_info DPX_Tested[] =
{ { colorspace::Y , 8, endianness::LE, packing::Packed }, { 1, 1, None } }, // 1x1x 8-bit in 1x 8-bit
{ { colorspace::Y , 10, endianness::BE, packing::FilledA}, { 3, 4, BlockSpan | Altern } }, // 1x3x10-bit in 1x32-bit including 1x2-bit padding
{ { colorspace::Y , 10, endianness::BE, packing::FilledB}, { 3, 4, BlockSpan | Altern } }, // 1x3x10-bit in 1x32-bit including 1x2-bit padding
{ { colorspace::Y , 12, endianness::BE, packing::Packed }, { 8, 12, BlockSpan | VFlip } }, // 8x1x12-bit in 3x32-bit
{ { colorspace::Y , 16, endianness::LE, packing::Packed }, { 1, 2, None } }, // 1x1x16-bit in 1x16-bit
{ { colorspace::Y , 16, endianness::BE, packing::Packed }, { 1, 2, None } }, // 1x1x16-bit in 1x16-bit
};
Expand Down Expand Up @@ -523,14 +524,14 @@ void dpx::ParseBuffer()
In[i - OffsetToData] = Buffer[i] & Mask;
}
}
if ((flavor)Flavor == flavor::Raw_RGB_12_Packed_BE)
if ((flavor)Flavor == flavor::Raw_RGB_12_Packed_BE || (flavor)Flavor == flavor::Raw_Y_12_Packed_BE)
{
size_t RemainingPaddingBits = Width % 8;
if (RemainingPaddingBits)
{
RemainingPaddingBits *= 4;
uint32_t Mask = ((uint32_t)-1) << RemainingPaddingBits;
size_t BytesPerLineMinus4 = (Width * 36 / 32) * 4;
size_t BytesPerLineMinus4 = (Width * 12 * Colorspace2Count(DPX_Tested[(uint8_t)Flavor].Test.ColorSpace) / 32) * 4;
size_t i = OffsetToData + BytesPerLineMinus4;
size_t Step = BytesPerLineMinus4 + 4;
for (; i < OffsetAfterData; i += Step)
Expand Down
1 change: 1 addition & 0 deletions Source/Lib/Uncompressed/DPX/DPX.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class dpx : public input_base_uncompressed_video
Raw_Y_8,
Raw_Y_10_FilledA_BE,
Raw_Y_10_FilledB_BE,
Raw_Y_12_Packed_BE,
Raw_Y_16_LE,
Raw_Y_16_BE,
ENUM_END(flavor)
Expand Down

0 comments on commit fce3a36

Please sign in to comment.