mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 22:27:35 +00:00
LibVideo: Implement CICP color space conversion
This adds a struct called CodingIndependentCodePoints and related enums that are used by video codecs to define its color space that frames must be converted from when displaying a video. Pre-multiplied matrices and lookup tables are stored to avoid most of the floating point division and exponentiation in the conversion.
This commit is contained in:
parent
ba79de0439
commit
cd127b65c3
15 changed files with 935 additions and 18 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <AK/IntegralMath.h>
|
||||
#include <LibGfx/Size.h>
|
||||
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
||||
|
||||
#include "Decoder.h"
|
||||
#include "Utilities.h"
|
||||
|
@ -149,6 +150,70 @@ bool Decoder::get_uv_subsampling_x()
|
|||
return m_parser->m_subsampling_x;
|
||||
}
|
||||
|
||||
CodingIndependentCodePoints Decoder::get_cicp_color_space()
|
||||
{
|
||||
ColorPrimaries color_primaries;
|
||||
TransferCharacteristics transfer_characteristics;
|
||||
MatrixCoefficients matrix_coefficients;
|
||||
|
||||
switch (m_parser->m_color_space) {
|
||||
case ColorSpace::Unknown:
|
||||
color_primaries = ColorPrimaries::Unspecified;
|
||||
transfer_characteristics = TransferCharacteristics::Unspecified;
|
||||
matrix_coefficients = MatrixCoefficients::Unspecified;
|
||||
break;
|
||||
case ColorSpace::Bt601:
|
||||
color_primaries = ColorPrimaries::BT601;
|
||||
transfer_characteristics = TransferCharacteristics::BT601;
|
||||
matrix_coefficients = MatrixCoefficients::BT601;
|
||||
break;
|
||||
case ColorSpace::Bt709:
|
||||
color_primaries = ColorPrimaries::BT709;
|
||||
transfer_characteristics = TransferCharacteristics::BT709;
|
||||
matrix_coefficients = MatrixCoefficients::BT709;
|
||||
break;
|
||||
case ColorSpace::Smpte170:
|
||||
// https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/pixfmt-007.html#colorspace-smpte-170m-v4l2-colorspace-smpte170m
|
||||
color_primaries = ColorPrimaries::BT601;
|
||||
transfer_characteristics = TransferCharacteristics::BT709;
|
||||
matrix_coefficients = MatrixCoefficients::BT601;
|
||||
break;
|
||||
case ColorSpace::Smpte240:
|
||||
color_primaries = ColorPrimaries::SMPTE240;
|
||||
transfer_characteristics = TransferCharacteristics::SMPTE240;
|
||||
matrix_coefficients = MatrixCoefficients::SMPTE240;
|
||||
break;
|
||||
case ColorSpace::Bt2020:
|
||||
color_primaries = ColorPrimaries::BT2020;
|
||||
// Bit depth doesn't actually matter to our transfer functions since we
|
||||
// convert in floats of range 0-1 (for now?), but just for correctness set
|
||||
// the TC to match the bit depth here.
|
||||
if (m_parser->m_bit_depth == 12)
|
||||
transfer_characteristics = TransferCharacteristics::BT2020BitDepth12;
|
||||
else if (m_parser->m_bit_depth == 10)
|
||||
transfer_characteristics = TransferCharacteristics::BT2020BitDepth10;
|
||||
else
|
||||
transfer_characteristics = TransferCharacteristics::BT709;
|
||||
matrix_coefficients = MatrixCoefficients::BT2020NonConstantLuminance;
|
||||
break;
|
||||
case ColorSpace::RGB:
|
||||
color_primaries = ColorPrimaries::BT709;
|
||||
transfer_characteristics = TransferCharacteristics::Linear;
|
||||
matrix_coefficients = MatrixCoefficients::Identity;
|
||||
break;
|
||||
case ColorSpace::Reserved:
|
||||
VERIFY_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
|
||||
return { color_primaries, transfer_characteristics, matrix_coefficients, m_parser->m_color_range };
|
||||
}
|
||||
|
||||
u8 Decoder::get_bit_depth()
|
||||
{
|
||||
return m_parser->m_bit_depth;
|
||||
}
|
||||
|
||||
u8 Decoder::merge_prob(u8 pre_prob, u8 count_0, u8 count_1, u8 count_sat, u8 max_update_factor)
|
||||
{
|
||||
auto total_decode_count = count_0 + count_1;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Span.h>
|
||||
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
||||
#include <LibVideo/DecoderError.h>
|
||||
|
||||
#include "Parser.h"
|
||||
|
@ -32,6 +33,8 @@ public:
|
|||
Gfx::Size<size_t> get_y_plane_size();
|
||||
bool get_uv_subsampling_y();
|
||||
bool get_uv_subsampling_x();
|
||||
CodingIndependentCodePoints get_cicp_color_space();
|
||||
u8 get_bit_depth();
|
||||
|
||||
private:
|
||||
typedef i32 Intermediate;
|
||||
|
|
|
@ -27,11 +27,6 @@ enum ColorSpace : u8 {
|
|||
RGB = 7
|
||||
};
|
||||
|
||||
enum ColorRange {
|
||||
StudioSwing,
|
||||
FullSwing
|
||||
};
|
||||
|
||||
enum InterpolationFilter : u8 {
|
||||
EightTap = 0,
|
||||
EightTapSmooth = 1,
|
||||
|
|
|
@ -136,8 +136,8 @@ DecoderErrorOr<FrameType> Parser::read_frame_type()
|
|||
DecoderErrorOr<ColorRange> Parser::read_color_range()
|
||||
{
|
||||
if (TRY_READ(m_bit_stream->read_bit()))
|
||||
return FullSwing;
|
||||
return StudioSwing;
|
||||
return ColorRange::Full;
|
||||
return ColorRange::Studio;
|
||||
}
|
||||
|
||||
/* (6.2) */
|
||||
|
@ -273,7 +273,7 @@ DecoderErrorOr<void> Parser::color_config()
|
|||
m_subsampling_y = true;
|
||||
}
|
||||
} else {
|
||||
m_color_range = FullSwing;
|
||||
m_color_range = ColorRange::Full;
|
||||
if (m_profile == 1 || m_profile == 3) {
|
||||
m_subsampling_x = false;
|
||||
m_subsampling_y = false;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <AK/Span.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibVideo/Color/CodingIndependentCodePoints.h>
|
||||
#include <LibVideo/DecoderError.h>
|
||||
|
||||
#include "BitStream.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue