1.1.0版本
This commit is contained in:
BIN
UniTAP/libs/lib_dscl/DSCL.dll
Normal file
BIN
UniTAP/libs/lib_dscl/DSCL.dll
Normal file
Binary file not shown.
BIN
UniTAP/libs/lib_dscl/Dsc.exe
Normal file
BIN
UniTAP/libs/lib_dscl/Dsc.exe
Normal file
Binary file not shown.
3
UniTAP/libs/lib_dscl/__init__.py
Normal file
3
UniTAP/libs/lib_dscl/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .dsc_info import DscParameters
|
||||
from .dscl_utils import (dscl_cf_from_dsc_cf, dscl_cf_to_dsc_cf, image_from_dsc_vf,
|
||||
dscl_image_calculate_crc, calculate_slice_size)
|
||||
156
UniTAP/libs/lib_dscl/dsc_info.py
Normal file
156
UniTAP/libs/lib_dscl/dsc_info.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from UniTAP.common.color_info import ColorInfo
|
||||
|
||||
|
||||
class DscParameters:
|
||||
"""
|
||||
Class `DscParameters` describes all parameters necessary for formatting input image to DSC image.
|
||||
- Width of image `width`.
|
||||
- Height of image `height`.
|
||||
- Color format of image `color_format` type `ColorInfo.ColorFormat`.
|
||||
- BPC `bpc`.
|
||||
- BPP `bpp`.
|
||||
- Flag of is block prediction enabled `is_block_prediction_enabled`.
|
||||
- Horizontal slice number `horizontal_slice_number`.
|
||||
- Number of buffer bit depth `buffer_bit_depth`.
|
||||
- Vertical slice number `vertical_slice_number`.
|
||||
- Vertical slice size `vertical_slice_size`.
|
||||
- DSC major version `version_major`.
|
||||
- DSC minor version `version_minor`.
|
||||
"""
|
||||
def __init__(self, width: int = 1920, height: int = 1080,
|
||||
color_format: ColorInfo.ColorFormat = ColorInfo.ColorFormat.CF_RGB, bpc: int = 8, bpp: int = 128,
|
||||
is_block_prediction_enabled: bool = False, horizontal_slice_number: int = 8, buffer_bit_depth: int = 8,
|
||||
vertical_slice_number: int = 8, vertical_slice_size: int = 1, version_major: int = 1,
|
||||
version_minor: int = 2):
|
||||
self.__width = width
|
||||
self.__height = height
|
||||
self.__color_format = color_format
|
||||
self.__bpc = bpc
|
||||
self.__bpp = bpp
|
||||
self.__is_block_prediction_enabled = is_block_prediction_enabled
|
||||
self.__horizontal_slice_number = horizontal_slice_number
|
||||
self.__buffer_bit_depth = buffer_bit_depth
|
||||
self.__vertical_slice_number = vertical_slice_number
|
||||
self.__vertical_slice_size = vertical_slice_size
|
||||
self.__version_major = version_major
|
||||
self.__version_minor = version_minor
|
||||
|
||||
@property
|
||||
def width(self) -> int:
|
||||
return self.__width
|
||||
|
||||
@width.setter
|
||||
def width(self, width: int = 1920):
|
||||
if width <= 0:
|
||||
raise ValueError(f"Incorrect width of image. Must be more, than 0. Current value: {width}")
|
||||
self.__width = width
|
||||
|
||||
@property
|
||||
def height(self) -> int:
|
||||
return self.__height
|
||||
|
||||
@height.setter
|
||||
def height(self, height: int = 1080):
|
||||
if height <= 0:
|
||||
raise ValueError(f"Incorrect height of image. Must be more, than 0. Current value: {height}")
|
||||
self.__height = height
|
||||
|
||||
@property
|
||||
def color_format(self) -> ColorInfo.ColorFormat:
|
||||
return self.__color_format
|
||||
|
||||
@color_format.setter
|
||||
def color_format(self, color_format: ColorInfo.ColorFormat.CF_RGB):
|
||||
self.__color_format = color_format
|
||||
|
||||
@property
|
||||
def bpc(self) -> int:
|
||||
return self.__bpc
|
||||
|
||||
@bpc.setter
|
||||
def bpc(self, bpc: int = 8):
|
||||
if bpc <= 5:
|
||||
raise ValueError(f"Incorrect bpc of image. Must be more, than 5. Current value: {bpc}")
|
||||
self.__bpc = bpc
|
||||
|
||||
@property
|
||||
def bpp(self) -> int:
|
||||
return self.__bpp
|
||||
|
||||
@bpp.setter
|
||||
def bpp(self, bpp: int = 10):
|
||||
if bpp <= 0:
|
||||
raise ValueError(f"Incorrect bpp of image. Must be more, than 0. Current value: {bpp}")
|
||||
self.__bpp = bpp
|
||||
|
||||
@property
|
||||
def is_block_prediction_enabled(self) -> bool:
|
||||
return self.__is_block_prediction_enabled
|
||||
|
||||
@width.setter
|
||||
def width(self, is_block_prediction_enabled: bool = False):
|
||||
self.__is_block_prediction_enabled = is_block_prediction_enabled
|
||||
|
||||
@property
|
||||
def horizontal_slice_number(self) -> int:
|
||||
return self.__horizontal_slice_number
|
||||
|
||||
@horizontal_slice_number.setter
|
||||
def horizontal_slice_number(self, horizontal_slice_number: int = 1920):
|
||||
if horizontal_slice_number <= 0:
|
||||
raise ValueError(f"Incorrect horizontal_slice_number of image. Must be more, than 0. "
|
||||
f"Current value: {horizontal_slice_number}")
|
||||
self.__horizontal_slice_number = horizontal_slice_number
|
||||
|
||||
@property
|
||||
def buffer_bit_depth(self) -> int:
|
||||
return self.__buffer_bit_depth
|
||||
|
||||
@buffer_bit_depth.setter
|
||||
def buffer_bit_depth(self, buffer_bit_depth: int = 8):
|
||||
if buffer_bit_depth <= 0:
|
||||
raise ValueError(f"Incorrect buffer_bit_depth of image. Must be more, than 0. "
|
||||
f"Current value: {buffer_bit_depth}")
|
||||
self.__buffer_bit_depth = buffer_bit_depth
|
||||
|
||||
@property
|
||||
def vertical_slice_number(self) -> int:
|
||||
return self.__vertical_slice_number
|
||||
|
||||
@vertical_slice_number.setter
|
||||
def vertical_slice_number(self, vertical_slice_number: int = 8):
|
||||
if vertical_slice_number <= 0:
|
||||
raise ValueError(f"Incorrect vertical_slice_number of image. Must be more, than 0. "
|
||||
f"Current value: {vertical_slice_number}")
|
||||
self.__vertical_slice_number = vertical_slice_number
|
||||
|
||||
@property
|
||||
def vertical_slice_size(self) -> int:
|
||||
return self.__vertical_slice_size
|
||||
|
||||
@vertical_slice_size.setter
|
||||
def vertical_slice_size(self, vertical_slice_size: int = 1):
|
||||
if vertical_slice_size <= 0:
|
||||
raise ValueError(f"Incorrect vertical_slice_size of image. Must be more, than 0. "
|
||||
f"Current value: {vertical_slice_size}")
|
||||
self.__vertical_slice_size = vertical_slice_size
|
||||
|
||||
@property
|
||||
def version_major(self) -> int:
|
||||
return self.__version_major
|
||||
|
||||
@version_major.setter
|
||||
def version_major(self, version_major: int = 1):
|
||||
if version_major <= 0:
|
||||
raise ValueError(f"Incorrect version_major of image. Must be more, than 0. Current value: {version_major}")
|
||||
self.__version_major = version_major
|
||||
|
||||
@property
|
||||
def version_minor(self) -> int:
|
||||
return self.__version_minor
|
||||
|
||||
@version_minor.setter
|
||||
def version_minor(self, version_minor: int = 2):
|
||||
if version_minor <= 0:
|
||||
raise ValueError(f"Incorrect version_minor of image. Must be more, than 0. Current value: {version_minor}")
|
||||
self.__version_minor = version_minor
|
||||
194
UniTAP/libs/lib_dscl/dscl.py
Normal file
194
UniTAP/libs/lib_dscl/dscl.py
Normal file
@@ -0,0 +1,194 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from .dscl_types import *
|
||||
from UniTAP.libs.lib_uicl.uicl_types import UICL_Image, UICL_ImageParameters
|
||||
from UniTAP.libs.lib_helper import OS_Requirements, lib_method_wrapper
|
||||
|
||||
DSCL_CURRENT_VERSION = 1
|
||||
DSCL = OS_Requirements("DSCL").get_lib()
|
||||
DSCL_PATH = OS_Requirements("DSCL").get_path_to_lib()
|
||||
DSC_TOOLS_FOLDER = os.path.dirname(DSCL_PATH)
|
||||
|
||||
|
||||
def from_cstr(src_str):
|
||||
try:
|
||||
return src_str.value.decode('cp1252')
|
||||
except BaseException:
|
||||
return src_str.value.decode('utf-8')
|
||||
|
||||
|
||||
class DSCLError(Exception):
|
||||
def __init__(self, message, errors=None):
|
||||
super().__init__(message)
|
||||
self.errors = errors
|
||||
|
||||
|
||||
def DSCL_GetRequiredBufferSize(image_to_encode: DSCL_Image):
|
||||
_DSCL_GetRequiredBufferSize = lib_method_wrapper(DSCL.DSCL_GetRequiredBufferSize,
|
||||
[POINTER(DSCL_Image)],
|
||||
c_uint64)
|
||||
|
||||
return _DSCL_GetRequiredBufferSize(byref(image_to_encode))
|
||||
|
||||
|
||||
def DSCL_GetRequiredBufferSizeFromPPS(pps: DSCL_PPS):
|
||||
_DSCL_GetRequiredBufferSizeFromPPS = lib_method_wrapper(DSCL.DSCL_GetRequiredBufferSizeFromPPS,
|
||||
[POINTER(DSCL_PPS)],
|
||||
c_uint64)
|
||||
|
||||
return _DSCL_GetRequiredBufferSizeFromPPS(byref(pps))
|
||||
|
||||
|
||||
def DSCL_Encode(image: UICL_Image, pps: DSCL_PPS) -> DSCL_Image:
|
||||
_DSCL_Encode = lib_method_wrapper(DSCL.DSCL_Encode,
|
||||
[POINTER(UICL_Image), POINTER(DSCL_PPS), POINTER(DSCL_Image),
|
||||
POINTER(DSCL_EncoderConfig), c_char_p, c_int],
|
||||
DSCL_RESULT)
|
||||
|
||||
max_enc_image_size = DSCL_GetRequiredBufferSizeFromPPS(pps)
|
||||
|
||||
if max_enc_image_size <= 132:
|
||||
raise DSCLError("Failed to calculate buffer size for DSC encoding!")
|
||||
|
||||
encoded_image = DSCL_Image()
|
||||
encoded_image.DataPtr = (c_uint8 * max_enc_image_size)()
|
||||
encoded_image.DataSize = max_enc_image_size
|
||||
|
||||
_log_struct = DSCL_EncoderConfig()
|
||||
_log_string_size = 65536
|
||||
_log_string = create_string_buffer(_log_string_size)
|
||||
|
||||
result = _DSCL_Encode(byref(image), byref(pps), byref(encoded_image), byref(_log_struct),
|
||||
_log_string, _log_string_size)
|
||||
|
||||
log = str(from_cstr(_log_string))
|
||||
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Encoding finished with error: {result}. Error log: {log}", result)
|
||||
|
||||
return encoded_image
|
||||
|
||||
|
||||
def DSCL_Decode(encoded_image: DSCL_Image, decode_simple422_to_444: Optional[bool] = False) -> UICL_Image:
|
||||
_DSCL_Decode = lib_method_wrapper(DSCL.DSCL_Decode,
|
||||
[POINTER(DSCL_Image), POINTER(UICL_Image),
|
||||
POINTER(DSCL_DecoderConfig)],
|
||||
DSCL_RESULT)
|
||||
|
||||
decoded_image = UICL_Image()
|
||||
decoded_image.Parameters = UICL_ImageParameters()
|
||||
decoded_image.DataPtr = POINTER(c_uint8)()
|
||||
decoded_image.DataSize = 0
|
||||
|
||||
decoder_config = DSCL_DecoderConfig()
|
||||
decoder_config.decodeSimple422to444 = False if decode_simple422_to_444 is None else decode_simple422_to_444
|
||||
|
||||
result = _DSCL_Decode(byref(encoded_image), byref(decoded_image), byref(decoder_config))
|
||||
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Decoding failed with error code: {result}", result)
|
||||
|
||||
return decoded_image
|
||||
|
||||
|
||||
def DSCL_ResultToString(result):
|
||||
_DSCL_ResultToString = lib_method_wrapper(DSCL.DSCL_ResultToString,
|
||||
[DSCL_RESULT, c_char_p, c_uint64],
|
||||
c_uint64)
|
||||
|
||||
_error_string = create_string_buffer(1024)
|
||||
_DSCL_ResultToString(result, _error_string, 1024)
|
||||
return from_cstr(_error_string)
|
||||
|
||||
|
||||
def DSCL_CalculateDSCCRC(image: DSCL_Image):
|
||||
_DSCL_CalculateDSCCRC = lib_method_wrapper(DSCL.DSCL_CalculateDSCCRC,
|
||||
[POINTER(DSCL_Image), POINTER(DSCL_CRC16)],
|
||||
c_uint64)
|
||||
crc_value = DSCL_CRC16()
|
||||
result = _DSCL_CalculateDSCCRC(byref(image), byref(crc_value))
|
||||
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Calculate DSC CRC: Failed to calculate CRC", result)
|
||||
|
||||
return crc_value
|
||||
|
||||
|
||||
def DSCL_ExtractPPSFromData(data):
|
||||
_DSCL_ExtractPPSFromData = lib_method_wrapper(DSCL.DSCL_ExtractPPSFromData,
|
||||
[POINTER(c_uint8), c_uint64, POINTER(DSCL_PPS)],
|
||||
c_uint64)
|
||||
_pps = DSCL_PPS()
|
||||
_size = len(data)
|
||||
_data = (c_uint8 * _size)(*data)
|
||||
result = _DSCL_ExtractPPSFromData(_data, _size, byref(_pps))
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Cannot extract PPS from data. Code: {result}")
|
||||
|
||||
return _pps
|
||||
|
||||
|
||||
def DSCL_ExtractPPS(image: DSCL_Image):
|
||||
_DSCL_ExtractPPS = lib_method_wrapper(DSCL.DSCL_ExtractPPS,
|
||||
[POINTER(DSCL_Image), POINTER(DSCL_PPS)],
|
||||
c_uint64)
|
||||
_pps = DSCL_PPS()
|
||||
result = _DSCL_ExtractPPS(byref(image), byref(_pps))
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Cannot extract PPS from DSCL Image. Code: {result}")
|
||||
|
||||
return _pps
|
||||
|
||||
|
||||
def DSCL_VerifyPPS(image: DSCL_Image):
|
||||
_DSCL_VerifyPPS = lib_method_wrapper(DSCL.DSCL_VerifyPPS,
|
||||
[POINTER(DSCL_Image), c_char_p, c_uint64],
|
||||
c_bool)
|
||||
|
||||
_error_string = create_string_buffer(1024)
|
||||
return _DSCL_VerifyPPS(byref(image), _error_string, 1024)
|
||||
|
||||
|
||||
def DSCL_GeneratePPS(decoded_image_parameters: UICL_ImageParameters,
|
||||
is_simple_422: bool, is_block_prediction_enabled: bool, bits_per_pixel: int,
|
||||
horizontal_slice_count: int, vertical_slice_count: int, buffer_bit_depth: int,
|
||||
dsc_version: DSCL_DscVersion) -> DSCL_PPS:
|
||||
_DSCL_GeneratePPS = lib_method_wrapper(DSCL.DSCL_GeneratePPS,
|
||||
[POINTER(DSCL_PPS), POINTER(UICL_ImageParameters), c_bool, c_bool,
|
||||
c_uint16, c_uint16, c_uint16, c_uint8, DSCL_DscVersion],
|
||||
c_bool)
|
||||
_pps = DSCL_PPS()
|
||||
result = _DSCL_GeneratePPS(byref(_pps), byref(decoded_image_parameters), is_simple_422,
|
||||
is_block_prediction_enabled, bits_per_pixel, horizontal_slice_count,
|
||||
vertical_slice_count, buffer_bit_depth, dsc_version)
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Cannot generate PPS. Error code {result}")
|
||||
|
||||
return _pps
|
||||
|
||||
|
||||
def DSCL_LoadFromFile(file_name: str) -> DSCL_RESULT:
|
||||
_DSCL_LoadFromFile = lib_method_wrapper(DSCL.DSCL_LoadFromFile,
|
||||
[c_char_p, POINTER(DSCL_Image)],
|
||||
DSCL_Image)
|
||||
image = DSCL_Image()
|
||||
image.DataPtr = POINTER(c_uint8)()
|
||||
image.DataSize = 0
|
||||
|
||||
result = _DSCL_LoadFromFile(c_char_p(file_name.encode('utf-8')), byref(image))
|
||||
|
||||
if result < DSCL_SUCCESS:
|
||||
raise DSCLError(f"Cannot load image from file. Error code {result}.")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def DSCL_FreeImage(image: DSCL_Image) -> DSCL_RESULT:
|
||||
_DSCL_FreeImage = lib_method_wrapper(DSCL.DSCL_FreeImage,
|
||||
[POINTER(POINTER(DSCL_Image))],
|
||||
c_uint64)
|
||||
|
||||
result = _DSCL_FreeImage(byref(byref(image)))
|
||||
|
||||
return result
|
||||
206
UniTAP/libs/lib_dscl/dscl_types.py
Normal file
206
UniTAP/libs/lib_dscl/dscl_types.py
Normal file
@@ -0,0 +1,206 @@
|
||||
from ctypes import *
|
||||
from enum import IntEnum
|
||||
|
||||
DSCL_RESULT = c_int32
|
||||
|
||||
DSCL_SUCCESS = 0
|
||||
DSCL_INTERNAL_ERROR = -1
|
||||
DSCL_ERROR_NULL_IMAGE = -2
|
||||
DSCL_NOT_ENOUGH_SPACE_FOR_ENCODED_IMAGE = -3
|
||||
DSCL_COMPRESSION_FAILED = -4
|
||||
DSCL_DECOMPRESSION_FAILED = -5
|
||||
DSCL_DSC_EXE_NOT_FOUND = -6
|
||||
DSCL_DP_CRC_EXE_NOT_FOUND = -7
|
||||
DSCL_PB_EXE_NOT_FOUND = -8
|
||||
DSCL_CFG_NOT_CREATED = -9
|
||||
DSCL_CFG_NOT_FOUND = -10
|
||||
DSCL_FAIL_TO_CREATE_TMP_FOLDER = -11
|
||||
DSCL_FAIL_TO_CREATE_TMP_FILE = -12
|
||||
|
||||
RC_BUF_THRESH_SIZE = 14
|
||||
RC_RANGE_PARAMETERS_SIZE = 30
|
||||
RC_RANGE_PARAMETERS_COUNT = int(RC_RANGE_PARAMETERS_SIZE / 2)
|
||||
|
||||
|
||||
class CtypesEnum(IntEnum):
|
||||
@classmethod
|
||||
def from_param(cls, obj):
|
||||
return int(obj)
|
||||
|
||||
|
||||
class DSCL_Colorformat(CtypesEnum):
|
||||
Colorformat_RGB = 0,
|
||||
Colorformat_YCbCr422 = 1,
|
||||
Colorformat_YCbCr444 = 2,
|
||||
Colorformat_YCbCr420 = 3,
|
||||
Colorformat_Simple422 = 4,
|
||||
Colorformat_MaxValue = 5
|
||||
|
||||
|
||||
class DSCL_DscVersion(Structure):
|
||||
_fields_ = [
|
||||
('major', c_uint8),
|
||||
('minor', c_uint8),
|
||||
]
|
||||
|
||||
|
||||
DSCL_ColorformatStr = ["RGB",
|
||||
"YCbCr 4:2:2",
|
||||
"YCbCr 4:4:4",
|
||||
"YCbCr 4:2:0",
|
||||
"Simple 4:2:2"]
|
||||
|
||||
class DSCL_Image(Structure):
|
||||
_fields_ = [
|
||||
('DataPtr', POINTER(c_uint8)),
|
||||
('DataSize', c_uint64),
|
||||
]
|
||||
|
||||
|
||||
class DSCL_Compression(Structure):
|
||||
_fields_ = [
|
||||
('bitsPerPixel', c_uint32),
|
||||
('bitsPerComponent', c_uint32),
|
||||
('is422', c_bool),
|
||||
('is420', c_bool),
|
||||
]
|
||||
|
||||
|
||||
class DSCL_CRC16(Structure):
|
||||
_fields_ = [
|
||||
('eng0', c_uint16),
|
||||
('eng1', c_uint16),
|
||||
('eng2', c_uint16)
|
||||
]
|
||||
|
||||
|
||||
class DSCL_PPS(Structure):
|
||||
_fields_ = [
|
||||
('dsc_version_minor', c_uint8, 4),
|
||||
('dsc_version_major', c_uint8, 4),
|
||||
('pps_identifier', c_uint8, 8),
|
||||
('', c_uint8, 8),
|
||||
('linebuf_depth', c_uint8, 4),
|
||||
('bits_per_component', c_uint8, 4),
|
||||
('bits_per_pixel_high', c_uint8, 2),
|
||||
('vbr_enable', c_uint8, 1),
|
||||
('simple_422', c_uint8, 1),
|
||||
('convert_rgb', c_uint8, 1),
|
||||
('block_pred_enable', c_uint8, 1),
|
||||
('', c_uint8, 2),
|
||||
('bits_per_pixel_low', c_uint8, 8),
|
||||
('pic_height_high', c_uint8, 8),
|
||||
('pic_height_low', c_uint8, 8),
|
||||
('pic_width_high', c_uint8, 8),
|
||||
('pic_width_low', c_uint8, 8),
|
||||
('slice_height_high', c_uint8, 8),
|
||||
('slice_height_low', c_uint8, 8),
|
||||
('slice_width_high', c_uint8, 8),
|
||||
('slice_width_low', c_uint8, 8),
|
||||
('chunk_size_high', c_uint8, 8),
|
||||
('chunk_size_low', c_uint8, 8),
|
||||
('initial_xmit_delay_high', c_uint8, 2),
|
||||
('', c_uint8, 6),
|
||||
('initial_xmit_delay_low', c_uint8, 8),
|
||||
('initial_dec_delay_high', c_uint8, 8),
|
||||
('initial_dec_delay_low', c_uint8, 8),
|
||||
('', c_uint8, 8),
|
||||
('initial_scale_value', c_uint8, 6),
|
||||
('', c_uint8, 2),
|
||||
('scale_increment_interval_high', c_uint8, 8),
|
||||
('scale_increment_interval_low', c_uint8, 8),
|
||||
('scale_decrement_interval_high', c_uint8, 4),
|
||||
('', c_uint8, 4),
|
||||
('scale_decrement_interval_low', c_uint8, 8),
|
||||
('', c_uint8, 8),
|
||||
('first_line_bpg_offset', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('nfl_bpg_offset_high', c_uint8, 8),
|
||||
('nfl_bpg_offset_low', c_uint8, 8),
|
||||
('slice_bpg_offset_high', c_uint8, 8),
|
||||
('slice_bpg_offset_low', c_uint8, 8),
|
||||
('initial_offset_high', c_uint8, 8),
|
||||
('initial_offset_low', c_uint8, 8),
|
||||
('final_offset_high', c_uint8, 8),
|
||||
('final_offset_low', c_uint8, 8),
|
||||
('flatness_min_qp', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('flatness_min_qp', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('rc_model_size_high', c_uint8, 8),
|
||||
('rc_model_size_low', c_uint8, 8),
|
||||
('rc_edge_factor', c_uint8, 4),
|
||||
('', c_uint8, 4),
|
||||
('rc_quant_incr_limit0', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('rc_quant_incr_limit1', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('rc_tgt_offset_lo', c_uint8, 4),
|
||||
('rc_tgt_offset_hi', c_uint8, 4),
|
||||
('rc_buf_thresh', c_uint8 * RC_BUF_THRESH_SIZE),
|
||||
('rc_range_parameters', c_uint8 * RC_RANGE_PARAMETERS_SIZE),
|
||||
('native_422', c_uint8, 1),
|
||||
('native_420', c_uint8, 1),
|
||||
('', c_uint8, 6),
|
||||
('second_line_bpg_offset', c_uint8, 5),
|
||||
('', c_uint8, 3),
|
||||
('nsl_bpg_offset_high', c_uint8, 8),
|
||||
('nsl_bpg_offset_low', c_uint8, 8),
|
||||
('second_line_offset_adj_high', c_uint8, 8),
|
||||
('second_line_offset_adj_low', c_uint8, 8),
|
||||
('', c_uint8 * 34)
|
||||
]
|
||||
|
||||
def width(self) -> int:
|
||||
return (self.pic_width_high << 8) | self.pic_width_low
|
||||
|
||||
def height(self) -> int:
|
||||
return (self.pic_height_high << 8) | self.pic_height_low
|
||||
|
||||
def is_yuv(self) -> bool:
|
||||
return self.convert_rgb == 0
|
||||
|
||||
def bpp(self) -> int:
|
||||
if self.native_422 == 1 or self.native_420 == 1:
|
||||
return int((((self.bits_per_pixel_high & 0x3) << 8) | self.bits_per_pixel_low) / 2)
|
||||
else:
|
||||
return ((self.bits_per_pixel_high & 0x3) << 8) | self.bits_per_pixel_low
|
||||
|
||||
def bpc(self) -> int:
|
||||
return self.bits_per_component & 0x0F
|
||||
|
||||
def is_422(self) -> bool:
|
||||
return self.native_422 != 0
|
||||
|
||||
def is_420(self) -> bool:
|
||||
return self.native_420 != 0
|
||||
|
||||
def is_simple_422(self) -> bool:
|
||||
return self.simple_422 != 0
|
||||
|
||||
def v_slice(self) -> int:
|
||||
return (self.slice_height_high << 8) | self.slice_height_low
|
||||
|
||||
def h_slice(self) -> int:
|
||||
return (self.slice_width_high << 8) | self.slice_width_low
|
||||
|
||||
def buffer_bit_depth(self) -> int:
|
||||
return self.linebuf_depth
|
||||
|
||||
def is_block_prediction_enabled(self) -> bool:
|
||||
return self.block_pred_enable != 0
|
||||
|
||||
def dsc_version(self) -> tuple:
|
||||
return self.dsc_version_major, self.dsc_version_minor
|
||||
|
||||
|
||||
class DSCL_EncoderConfig(Structure):
|
||||
_fields_ = [
|
||||
# ('log_buffer', c_char * 2048),
|
||||
]
|
||||
|
||||
|
||||
class DSCL_DecoderConfig(Structure):
|
||||
_fields_ = [
|
||||
('decodeSimple422to444', c_bool),
|
||||
]
|
||||
219
UniTAP/libs/lib_dscl/dscl_utils.py
Normal file
219
UniTAP/libs/lib_dscl/dscl_utils.py
Normal file
@@ -0,0 +1,219 @@
|
||||
from UniTAP.libs.lib_dscl.dscl_types import *
|
||||
from UniTAP.libs.lib_dscl.dscl import (DSCL_Encode, DSCL_Decode, DSCL_CalculateDSCCRC, DSCL_ExtractPPSFromData,
|
||||
DSCL_GeneratePPS)
|
||||
from UniTAP.common import VideoFrameDSC, CompressionInfo
|
||||
from UniTAP.libs.lib_uicl.uicl_utils import *
|
||||
|
||||
|
||||
def dscl_cf_from_dsc_cf(color_format: CompressionInfo.DscColorFormat) -> DSCL_Colorformat:
|
||||
assert isinstance(color_format, CompressionInfo.DscColorFormat)
|
||||
if color_format == CompressionInfo.DscColorFormat.CF_RGB:
|
||||
return DSCL_Colorformat.Colorformat_RGB
|
||||
elif color_format == CompressionInfo.DscColorFormat.CF_YCbCr_444:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr444
|
||||
elif color_format == CompressionInfo.DscColorFormat.CF_YCbCr_422:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr422
|
||||
elif color_format == CompressionInfo.DscColorFormat.CF_YCbCr_420:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr420
|
||||
elif color_format == CompressionInfo.DscColorFormat.CF_Simple_422:
|
||||
return DSCL_Colorformat.Colorformat_Simple422
|
||||
else:
|
||||
return DSCL_Colorformat.Colorformat_MaxValue
|
||||
|
||||
|
||||
def dscl_cf_to_dsc_cf(color_format: DSCL_Colorformat) -> CompressionInfo.DscColorFormat:
|
||||
if color_format == DSCL_Colorformat.Colorformat_RGB:
|
||||
return CompressionInfo.DscColorFormat.CF_RGB
|
||||
elif color_format == DSCL_Colorformat.Colorformat_YCbCr444:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_444
|
||||
elif color_format == DSCL_Colorformat.Colorformat_YCbCr422:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_422
|
||||
elif color_format == DSCL_Colorformat.Colorformat_YCbCr420:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_420
|
||||
elif color_format == DSCL_Colorformat.Colorformat_Simple422:
|
||||
return CompressionInfo.DscColorFormat.CF_Simple_422
|
||||
else:
|
||||
return CompressionInfo.DscColorFormat.CF_NONE
|
||||
|
||||
|
||||
def vm_cf_to_dscl_cf(color_format: ColorInfo.ColorFormat) -> DSCL_Colorformat:
|
||||
if color_format == ColorInfo.ColorFormat.CF_RGB:
|
||||
return DSCL_Colorformat.Colorformat_RGB
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr444
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr422
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
|
||||
return DSCL_Colorformat.Colorformat_YCbCr420
|
||||
else:
|
||||
return DSCL_Colorformat.Colorformat_MaxValue
|
||||
|
||||
|
||||
def vm_cf_to_dsc_cf(color_format: ColorInfo.ColorFormat) -> CompressionInfo.DscColorFormat:
|
||||
if color_format == ColorInfo.ColorFormat.CF_RGB:
|
||||
return CompressionInfo.DscColorFormat.CF_RGB
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_444
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_422
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_420
|
||||
else:
|
||||
return CompressionInfo.DscColorFormat.CF_NONE
|
||||
|
||||
|
||||
def dscl_pps_cf_to_compression_info_cf(dscl_pps: DSCL_PPS) -> CompressionInfo.DscColorFormat:
|
||||
if dscl_pps.convert_rgb:
|
||||
return CompressionInfo.DscColorFormat.CF_RGB
|
||||
elif dscl_pps.native_422:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_422
|
||||
elif dscl_pps.native_420:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_420
|
||||
elif dscl_pps.simple_422:
|
||||
return CompressionInfo.DscColorFormat.CF_Simple_422
|
||||
else:
|
||||
return CompressionInfo.DscColorFormat.CF_YCbCr_444
|
||||
|
||||
|
||||
def is_simple_as_444(dscl_pps: DSCL_PPS) -> bool:
|
||||
return dscl_pps_cf_to_compression_info_cf(dscl_pps) == CompressionInfo.DscColorFormat.CF_YCbCr_444
|
||||
|
||||
|
||||
def dscl_pps_to_compression_info(dscl_pps: DSCL_PPS) -> CompressionInfo:
|
||||
compression_info = CompressionInfo()
|
||||
|
||||
compression_info.color_format = dscl_pps_cf_to_compression_info_cf(dscl_pps)
|
||||
compression_info.bpp = ((dscl_pps.bits_per_pixel_high << 8) | dscl_pps.bits_per_pixel_low)
|
||||
compression_info.is_block_prediction_enabled = dscl_pps.block_pred_enable
|
||||
compression_info.h_slice_size = ((dscl_pps.slice_height_high << 8) | dscl_pps.slice_height_low)
|
||||
compression_info.v_slice_size = ((dscl_pps.slice_width_high << 8) | dscl_pps.slice_width_low)
|
||||
compression_info.buffer_bit_depth = dscl_pps.linebuf_depth
|
||||
compression_info.version = (dscl_pps.dsc_version_major, dscl_pps.dsc_version_minor)
|
||||
compression_info.is_simple_as_444 = is_simple_as_444(dscl_pps)
|
||||
|
||||
return compression_info
|
||||
|
||||
|
||||
def image_from_dsc_vf(video_frame: VideoFrameDSC) -> DSCL_Image:
|
||||
image = DSCL_Image()
|
||||
image.DataSize = len(video_frame.data)
|
||||
|
||||
if isinstance(video_frame.data, bytearray):
|
||||
image.DataPtr = (c_uint8 * image.DataSize)(*video_frame.data)
|
||||
elif isinstance(video_frame.data, bytes):
|
||||
image.DataPtr = (c_uint8 * image.DataSize)(*bytearray(video_frame.data))
|
||||
else:
|
||||
image.DataPtr = video_frame.data
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def dscl_image_from_vf(video_frame: VideoFrame, parameters: CompressionInfo) -> DSCL_Image:
|
||||
image = DSCL_Image()
|
||||
image.DataSize = len(video_frame.data)
|
||||
|
||||
if isinstance(video_frame.data, bytearray):
|
||||
image.DataPtr = (c_uint8 * image.DataSize).from_buffer(video_frame.data)
|
||||
elif isinstance(video_frame.data, bytes):
|
||||
image.DataPtr = (c_uint8 * image.DataSize).from_buffer(bytearray(video_frame.data))
|
||||
else:
|
||||
image.DataPtr = video_frame.data
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def dscl_image_to_dsc_vf(image: DSCL_Image, width: int = 0, height: int = 0, bpc: int = 0) -> VideoFrameDSC:
|
||||
video_frame = VideoFrameDSC()
|
||||
|
||||
video_frame.data = bytearray(image.DataPtr[:image.DataSize])
|
||||
video_frame.width = width
|
||||
video_frame.height = height
|
||||
video_frame.color_info.bpc = bpc
|
||||
video_frame.color_info.color_format = ColorInfo.ColorFormat.CF_DSC
|
||||
|
||||
return video_frame
|
||||
|
||||
|
||||
def encode_vf(video_frame: VideoFrame, parameters: CompressionInfo) -> VideoFrameDSC:
|
||||
if video_frame.color_info.color_format == ColorInfo.ColorFormat.CF_DSC:
|
||||
raise AssertionError(f"Image must not have color format DSC. Current format: "
|
||||
f"{video_frame.color_info.color_format.name}")
|
||||
|
||||
uicl_image = image_from_vf(video_frame)
|
||||
|
||||
width, height, color_info, data_info = image_params_to_size_and_ci(uicl_image.Parameters)
|
||||
horizontal_slice_count = calculate_slice_number(width, parameters.h_slice_size, color_info.color_format)
|
||||
vertical_slice_count = calculate_slice_number(height, parameters.v_slice_size, color_info.color_format)
|
||||
dsc_version = DSCL_DscVersion()
|
||||
dsc_version.major = parameters.version[0]
|
||||
dsc_version.minor = parameters.version[1]
|
||||
target_pps = DSCL_GeneratePPS(decoded_image_parameters=uicl_image.Parameters,
|
||||
is_simple_422=parameters.color_format == CompressionInfo.DscColorFormat.CF_Simple_422,
|
||||
is_block_prediction_enabled=parameters.is_block_prediction_enabled,
|
||||
bits_per_pixel=parameters.bpp,
|
||||
horizontal_slice_count=horizontal_slice_count,
|
||||
vertical_slice_count=vertical_slice_count,
|
||||
buffer_bit_depth=parameters.buffer_bit_depth,
|
||||
dsc_version=dsc_version)
|
||||
encoded_image = DSCL_Encode(uicl_image, target_pps)
|
||||
encoded_vf = dscl_image_to_dsc_vf(encoded_image, width, height, color_info.bpc)
|
||||
encoded_vf.compression_info = parameters
|
||||
|
||||
return encoded_vf
|
||||
|
||||
|
||||
def decode_vf(video_frame: VideoFrameDSC) -> VideoFrame:
|
||||
if bytearray("DSCF".encode()) not in video_frame.data:
|
||||
video_frame.data = bytearray("DSCF".encode()) + video_frame.data
|
||||
encoded_image = image_from_dsc_vf(video_frame)
|
||||
decoded_image = DSCL_Decode(encoded_image, decode_simple422_to_444=video_frame.compression_info.is_simple_as_444)
|
||||
decoded_vf = image_to_vf(decoded_image)
|
||||
|
||||
return decoded_vf
|
||||
|
||||
|
||||
def dscl_image_calculate_crc(video_frame: VideoFrameDSC):
|
||||
image = DSCL_Image()
|
||||
image.DataSize = len(video_frame.data)
|
||||
|
||||
if isinstance(video_frame.data, bytearray):
|
||||
image.DataPtr = (c_uint8 * image.DataSize)(*video_frame.data)
|
||||
elif isinstance(video_frame.data, bytes):
|
||||
image.DataPtr = (c_uint8 * image.DataSize)(*bytearray(video_frame.data))
|
||||
else:
|
||||
image.DataPtr = video_frame.data
|
||||
crc = DSCL_CalculateDSCCRC(image)
|
||||
return crc.eng0, crc.eng1, crc.eng2
|
||||
|
||||
|
||||
def dscl_data_processing(data: bytearray) -> VideoFrameDSC:
|
||||
vf = VideoFrameDSC()
|
||||
pps_data = DSCL_ExtractPPSFromData(data)
|
||||
vf.compression_info = dscl_pps_to_compression_info(pps_data)
|
||||
vf.height = ((pps_data.pic_height_high << 8) | pps_data.pic_height_low)
|
||||
vf.width = ((pps_data.pic_width_high << 8) | pps_data.pic_width_low)
|
||||
vf.color_info.bpc = pps_data.bits_per_component
|
||||
vf.color_info.color_format = ColorInfo.ColorFormat.CF_DSC
|
||||
vf.data = data
|
||||
return vf
|
||||
|
||||
|
||||
def calculate_slice_size(value: int, slice_number: int,
|
||||
color_format: ColorInfo.ColorFormat = ColorInfo.ColorFormat.CF_RGB):
|
||||
slice_size = value / slice_number + (1 if value % slice_number else 0)
|
||||
|
||||
if color_format in [ColorInfo.ColorFormat.CF_YCbCr_422, ColorInfo.ColorFormat.CF_YCbCr_420,
|
||||
ColorInfo.ColorFormat.CF_Y_ONLY]:
|
||||
slice_size += (1 if slice_size % 2 else 0)
|
||||
|
||||
return slice_size
|
||||
|
||||
|
||||
def calculate_slice_number(value: int, slice_size: int,
|
||||
color_format: ColorInfo.ColorFormat = ColorInfo.ColorFormat.CF_RGB):
|
||||
if color_format in [ColorInfo.ColorFormat.CF_YCbCr_422, ColorInfo.ColorFormat.CF_YCbCr_420,
|
||||
ColorInfo.ColorFormat.CF_Y_ONLY]:
|
||||
slice_size -= (1 if slice_size % 2 else 0)
|
||||
|
||||
slice_number = (value + slice_size - 1) // slice_size
|
||||
return slice_number
|
||||
Reference in New Issue
Block a user