1.1.0版本
This commit is contained in:
3
UniTAP/libs/__init__.py
Normal file
3
UniTAP/libs/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from UniTAP.libs.lib_helper.lib_os_helpers import OS_Requirements
|
||||
from UniTAP.libs.lib_dscl import *
|
||||
from UniTAP.libs.lib_uicl import *
|
||||
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
|
||||
1
UniTAP/libs/lib_helper/__init__.py
Normal file
1
UniTAP/libs/lib_helper/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .lib_os_helpers import OS_Requirements, lib_method_wrapper
|
||||
131
UniTAP/libs/lib_helper/lib_os_helpers.py
Normal file
131
UniTAP/libs/lib_helper/lib_os_helpers.py
Normal file
@@ -0,0 +1,131 @@
|
||||
import warnings
|
||||
from ctypes import *
|
||||
import os
|
||||
import platform
|
||||
import glob
|
||||
|
||||
LIBS_PATH = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def lib_method_wrapper(named_func_pointer, argtypes, restype):
|
||||
wrapper = named_func_pointer
|
||||
wrapper.argtypes = argtypes
|
||||
wrapper.restype = restype
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class OS_Requirements():
|
||||
|
||||
def __init__(self, lib_type: str, lib_path=""):
|
||||
self.__os_name = platform.system()
|
||||
self.__lib_type = lib_type
|
||||
self.__lib_specific_path = os.path.join(LIBS_PATH, lib_path if lib_path != "" else f"lib_{self.__lib_type.lower()}")
|
||||
|
||||
def __gen_dll_path_for_win(self):
|
||||
dll_path = os.path.join(self.__lib_specific_path, f'{self.__lib_type}.dll')
|
||||
if not os.path.isfile(dll_path):
|
||||
dll_path = f'C:\\Program Files\\Unigraf\\Unigraf UCD Tools\\{self.__lib_type}.dll'
|
||||
|
||||
return dll_path
|
||||
|
||||
def __gen_lib_path_for_osx(self):
|
||||
lib_path = os.path.join(self.__lib_specific_path, f'lib{self.__lib_type}.dylib')
|
||||
return lib_path
|
||||
|
||||
def __get_exe_path_for_win(self):
|
||||
dll_path = os.path.join(self.__lib_specific_path, f'{self.__lib_type}.exe')
|
||||
if not os.path.isfile(dll_path):
|
||||
dll_path = f'C:\\Program Files\\Unigraf\\Unigraf UCD Tools\\{self.__lib_type}.exe'
|
||||
|
||||
return dll_path
|
||||
|
||||
def __gen_lib_path_for_lin(self):
|
||||
full_dll_name = f'lib{self.__lib_type}.so'
|
||||
|
||||
dll_path = os.path.join(self.__lib_specific_path, full_dll_name)
|
||||
if not os.path.isfile(dll_path):
|
||||
dll_path = glob.glob(f'/home/user/Downloads/*/sdk/python/common/tsi/tsi_devices/libs/lib_{self.__lib_type.lower()}/{full_dll_name}')
|
||||
if len(dll_path) > 0:
|
||||
dll_path = dll_path[0]
|
||||
else:
|
||||
dll_path = ""
|
||||
|
||||
return dll_path
|
||||
|
||||
def __gen_exe_path_for_lin_and_mac(self, is_linux):
|
||||
full_dll_name = f'lib{self.__lib_type}.so' if is_linux else f'lib{self.__lib_type}.'
|
||||
|
||||
dll_path = os.path.join(self.__lib_specific_path, full_dll_name)
|
||||
if not os.path.isfile(dll_path):
|
||||
dll_path = glob.glob(f'/home/user/Downloads/*/sdk/python/common/tsi/tsi_devices/libs/lib_{self.__lib_type.lower()}/{full_dll_name}')
|
||||
if len(dll_path) > 0:
|
||||
dll_path = dll_path[0]
|
||||
else:
|
||||
dll_path = ""
|
||||
|
||||
return dll_path
|
||||
|
||||
def __get_lib_for_win(self):
|
||||
if os.path.exists(self.__gen_dll_path_for_win()):
|
||||
return windll.LoadLibrary(self.__gen_dll_path_for_win())
|
||||
else:
|
||||
warnings.warn(f"Failed to find library at {self.__gen_dll_path_for_win()}")
|
||||
|
||||
def __get_lib_for_lin(self):
|
||||
if os.path.exists(self.__gen_lib_path_for_lin()):
|
||||
return cdll.LoadLibrary(self.__gen_lib_path_for_lin())
|
||||
else:
|
||||
warnings.warn(f"Failed to find library at {self.__gen_lib_path_for_lin()}")
|
||||
return None
|
||||
|
||||
def __get_lib_for_osx(self):
|
||||
if os.path.exists(self.__gen_lib_path_for_osx()):
|
||||
return cdll.LoadLibrary(self.__gen_lib_path_for_osx())
|
||||
else:
|
||||
warnings.warn(f"Failed to find library at {self.__gen_lib_path_for_osx()}")
|
||||
return None
|
||||
|
||||
def get_lib(self):
|
||||
if self.__os_name == 'Windows':
|
||||
return self.__get_lib_for_win()
|
||||
elif self.__os_name == 'Linux':
|
||||
return self.__get_lib_for_lin()
|
||||
elif self.__os_name == 'Darwin':
|
||||
return self.__get_lib_for_osx()
|
||||
else:
|
||||
raise Exception('Un-supported OS!')
|
||||
|
||||
def get_additional_file(self):
|
||||
try:
|
||||
if self.__os_name == 'Windows':
|
||||
return self.__get_exe_path_for_win()
|
||||
elif self.__os_name == 'Linux':
|
||||
return self.__gen_exe_path_for_lin_and_mac(True)
|
||||
elif self.__os_name == 'Darwin':
|
||||
return self.__gen_exe_path_for_lin_and_mac(False)
|
||||
else:
|
||||
raise Exception('Un-supported OS!')
|
||||
except OSError:
|
||||
error = get_errno()
|
||||
print(f'Get error = {error} while loading {self.__lib_type} lib for {self.__os_name}!')
|
||||
if error == 193:
|
||||
print('Perhaps you are using a 64-bit python interpreter along with a 32-bit library, or vice versa.'
|
||||
' Need the same.')
|
||||
|
||||
def get_path_to_lib(self):
|
||||
try:
|
||||
if self.__os_name == 'Windows':
|
||||
return self.__gen_dll_path_for_win()
|
||||
elif self.__os_name == 'Linux':
|
||||
return self.__gen_lib_path_for_lin()
|
||||
elif self.__os_name == 'Darwin':
|
||||
return self.__gen_lib_path_for_osx()
|
||||
else:
|
||||
raise Exception('Un-supported OS!')
|
||||
except OSError:
|
||||
error = GetLastError()
|
||||
print(f'Get error = {error} while loading {self.__lib_type} lib for {self.__os_name}!')
|
||||
if error == 193:
|
||||
print('Perhaps you are using a 64-bit python interpreter along with a 32-bit library, or vice versa.'
|
||||
' Need the same.')
|
||||
BIN
UniTAP/libs/lib_pdl/Default_16K.png
Normal file
BIN
UniTAP/libs/lib_pdl/Default_16K.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 606 KiB |
1
UniTAP/libs/lib_pdl/__init__.py
Normal file
1
UniTAP/libs/lib_pdl/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .pdl import generate_pattern_as_vf, PatternType
|
||||
21
UniTAP/libs/lib_pdl/pdl.py
Normal file
21
UniTAP/libs/lib_pdl/pdl.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import os
|
||||
|
||||
from UniTAP.common import VideoFrame, ColorInfo, DataInfo, get_vf_from_image
|
||||
from UniTAP.utils import video_frame_to_ci
|
||||
from .pdl_types import *
|
||||
|
||||
UNIGRAF_IMAGE_PATH = os.path.join(os.path.dirname(__file__), "Default_16K.png")
|
||||
|
||||
|
||||
def generate_pattern_as_vf(pattern_type: PatternType, width: int, height: int,
|
||||
color_info: ColorInfo, data_info: DataInfo) -> VideoFrame:
|
||||
if pattern_type != PatternType.Unigraf:
|
||||
raise NotImplementedError("Generating ColorRamp and ColorSquares not supported yet.")
|
||||
|
||||
if pattern_type == PatternType.Unigraf:
|
||||
if not os.path.exists(UNIGRAF_IMAGE_PATH):
|
||||
raise FileNotFoundError("Unigraf default image not found. Not possible to generate "
|
||||
"Unigraf pattern.")
|
||||
vf = get_vf_from_image(UNIGRAF_IMAGE_PATH, width, height)
|
||||
|
||||
return video_frame_to_ci(vf, color_info, data_info)
|
||||
7
UniTAP/libs/lib_pdl/pdl_types.py
Normal file
7
UniTAP/libs/lib_pdl/pdl_types.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
class PatternType(IntEnum):
|
||||
Unigraf = 0,
|
||||
ColorSquares = 1,
|
||||
ColorRamp = 2
|
||||
BIN
UniTAP/libs/lib_tsi/TSI.dll
Normal file
BIN
UniTAP/libs/lib_tsi/TSI.dll
Normal file
Binary file not shown.
3
UniTAP/libs/lib_tsi/__init__.py
Normal file
3
UniTAP/libs/lib_tsi/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
from UniTAP.libs.lib_tsi.tsi_io import BaseIO, DeviceIO, PortIO
|
||||
624
UniTAP/libs/lib_tsi/tsi.py
Normal file
624
UniTAP/libs/lib_tsi/tsi.py
Normal file
@@ -0,0 +1,624 @@
|
||||
import warnings
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
from UniTAP.libs.lib_helper import OS_Requirements, lib_method_wrapper
|
||||
from ctypes import c_char_p, c_uint32, c_void_p, c_int32, POINTER, create_string_buffer, byref, \
|
||||
sizeof, c_uint64, c_ubyte, c_bool
|
||||
from UniTAP.utils import tsi_logging as logging
|
||||
|
||||
CTYPES_TYPE_LIST = [c_char_p, c_uint32, c_void_p, c_int32, c_uint64, c_ubyte, c_bool]
|
||||
|
||||
|
||||
callback = None
|
||||
|
||||
|
||||
class Singleton(type):
|
||||
_instances = {}
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
if cls not in cls._instances:
|
||||
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||
return cls._instances[cls]
|
||||
|
||||
|
||||
class TSIWrapper(metaclass=Singleton):
|
||||
_TSI_CURRENT_VERSION = 12
|
||||
|
||||
def __init__(self):
|
||||
self._TSI_DEV_SetSearchMask = None
|
||||
self._TSI_GetParsedEventData = None
|
||||
self._TSI_RemoveEventParser = None
|
||||
self._TSI_CreateEventParser = None
|
||||
self._TSIX_STLOG_GetMessageData = None
|
||||
self._TSIX_STLOG_WaitMessage = None
|
||||
self._TSIX_PORT_GetTestInfo = None
|
||||
self._TSIX_PORT_GetTestCount = None
|
||||
self._TSIX_TS_RunTest = None
|
||||
self._TSIX_TS_AbortTests = None
|
||||
self._TSIX_PORT_Deselect = None
|
||||
self._TSIX_PORT_Select = None
|
||||
self._TSI_MISC_GetErrorDescription = None
|
||||
self._TSIX_TS_GetConfigItem = None
|
||||
self._TSI2_TS_GetConfigItem = None
|
||||
self._TSIX_TS_SetConfigItem = None
|
||||
self._TSI2_TS_SetConfigItem = None
|
||||
self._TSIX_DEV_CloseDevice = None
|
||||
self._TSIX_DEV_GetDeviceRoleCount = None
|
||||
self._TSIX_DEV_GetDeviceRoleName = None
|
||||
self._TSIX_DEV_RescanDevices = None
|
||||
self._TSIX_DEV_SelectRole = None
|
||||
self._TSIX_DEV_OpenDevice = None
|
||||
self._TSIX_DEV_GetDeviceName = None
|
||||
self._TSI_DEV_GetDeviceName = None
|
||||
self._TSI_DEV_GetDeviceCount = None
|
||||
self._TSI_Clean = None
|
||||
self._TSIX_Init = None
|
||||
self._TSI_Init = None
|
||||
self.lib = OS_Requirements("TSI").get_lib()
|
||||
self.__setup_callback()
|
||||
|
||||
def __del__(self):
|
||||
self.deinitialize()
|
||||
|
||||
def initialize(self):
|
||||
|
||||
self._TSIX_Init = lib_method_wrapper(self.lib.TSIX_Init, [POINTER(TSI_INIT_CONFIGURATION)],
|
||||
TSI_RESULT)
|
||||
self._TSI_Init = lib_method_wrapper(self.lib.TSI_Init, [c_uint32], TSI_RESULT)
|
||||
self._TSI_Clean = lib_method_wrapper(self.lib.TSI_Clean, [], TSI_RESULT)
|
||||
self._TSI_DEV_GetDeviceCount = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceCount, [],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_GetDeviceName = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceName,
|
||||
[TSI_DEVICE_ID, c_char_p, c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_OpenDevice = lib_method_wrapper(self.lib.TSIX_DEV_OpenDevice,
|
||||
[TSI_DEVICE_ID, POINTER(TSI_RESULT)],
|
||||
TSI_HANDLE)
|
||||
self._TSIX_DEV_SelectRole = lib_method_wrapper(self.lib.TSIX_DEV_SelectRole,
|
||||
[TSI_HANDLE, c_int32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_RescanDevices = lib_method_wrapper(self.lib.TSIX_DEV_RescanDevices,
|
||||
[c_int32, c_int32, c_int32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_GetDeviceRoleName = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceRoleName,
|
||||
[TSI_HANDLE, c_int32, c_char_p,
|
||||
c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_GetDeviceRoleCount = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceRoleCount,
|
||||
[TSI_HANDLE, ],
|
||||
TSI_RESULT)
|
||||
self._TSIX_DEV_CloseDevice = lib_method_wrapper(self.lib.TSIX_DEV_CloseDevice,
|
||||
[TSI_HANDLE, ],
|
||||
TSI_RESULT)
|
||||
self._TSI2_TS_SetConfigItem = lib_method_wrapper(self.lib.TSI2_TS_SetConfigItem,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT,
|
||||
TSI_CONFIG_ID,
|
||||
c_void_p, c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_TS_SetConfigItem = lib_method_wrapper(self.lib.TSIX_TS_SetConfigItem,
|
||||
[TSI_HANDLE, TSI_CONFIG_ID, c_void_p,
|
||||
c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSI2_TS_GetConfigItem = lib_method_wrapper(self.lib.TSI2_TS_GetConfigItem,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT,
|
||||
TSI_CONFIG_ID,
|
||||
c_void_p, c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_TS_GetConfigItem = lib_method_wrapper(self.lib.TSIX_TS_GetConfigItem,
|
||||
[TSI_HANDLE, TSI_CONFIG_ID, c_void_p,
|
||||
c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSI_MISC_GetErrorDescription = lib_method_wrapper(
|
||||
self.lib.TSI_MISC_GetErrorDescription,
|
||||
[TSI_RESULT, c_char_p, c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_PORT_Select = lib_method_wrapper(self.lib.TSIX_PORT_Select,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT],
|
||||
TSI_RESULT)
|
||||
self._TSIX_PORT_Deselect = lib_method_wrapper(self.lib.TSIX_PORT_Deselect,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT],
|
||||
TSI_RESULT)
|
||||
self._TSIX_TS_RunTest = lib_method_wrapper(self.lib.TSIX_TS_RunTest,
|
||||
[TSI_HANDLE, TSI_TEST_ID],
|
||||
TSI_RESULT)
|
||||
self._TSIX_TS_AbortTests = lib_method_wrapper(self.lib.TSIX_TS_AbortTests,
|
||||
[TSI_HANDLE],
|
||||
TSI_RESULT)
|
||||
self._TSIX_PORT_GetTestCount = lib_method_wrapper(self.lib.TSIX_PORT_GetTestCount,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT],
|
||||
TSI_RESULT)
|
||||
self._TSIX_PORT_GetTestInfo = lib_method_wrapper(self.lib.TSIX_PORT_GetTestInfo,
|
||||
[TSI_HANDLE, TSI_LOGICAL_PORT, c_int32,
|
||||
POINTER(TSI_TEST_ID),
|
||||
POINTER(c_int32), c_char_p, c_uint32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_STLOG_WaitMessage = lib_method_wrapper(self.lib.TSIX_STLOG_WaitMessage,
|
||||
[TSI_HANDLE, c_int32],
|
||||
TSI_RESULT)
|
||||
self._TSIX_STLOG_GetMessageData = lib_method_wrapper(self.lib.TSIX_STLOG_GetMessageData,
|
||||
[TSI_HANDLE, c_char_p, c_uint32,
|
||||
POINTER(c_uint32)],
|
||||
TSI_RESULT)
|
||||
self._TSI_CreateEventParser = lib_method_wrapper(self.lib.TSI_CreateEventParser,
|
||||
[POINTER(TSI_RESULT), c_uint32],
|
||||
TSI_PARSER)
|
||||
self._TSI_RemoveEventParser = lib_method_wrapper(self.lib.TSI_RemoveEventParser,
|
||||
[TSI_PARSER, ],
|
||||
TSI_RESULT)
|
||||
self._TSI_GetParsedEventData = lib_method_wrapper(self.lib.TSI_GetParsedEventData,
|
||||
[TSI_PARSER, POINTER(c_ubyte), c_int32,
|
||||
POINTER(c_uint64), c_char_p, c_int32,
|
||||
c_char_p,
|
||||
c_int32, c_char_p, c_int32, c_char_p,
|
||||
c_int32],
|
||||
TSI_RESULT)
|
||||
self._TSI_DEV_SetSearchMask = lib_method_wrapper(self.lib.TSI_DEV_SetSearchMask,
|
||||
[TSI_DEVICE_CAPS, TSI_DEVICE_CAPS],
|
||||
TSI_RESULT)
|
||||
|
||||
return self.__TSIX_Init() if logging.is_enabled() else self.__TSI_Init()
|
||||
|
||||
def deinitialize(self):
|
||||
return self.__TSI_Clean()
|
||||
|
||||
@staticmethod
|
||||
def __setup_callback():
|
||||
global callback
|
||||
|
||||
def ofp_impl(level, message):
|
||||
try:
|
||||
logging.log((level + 1) * 10, message.decode())
|
||||
except Exception as exc:
|
||||
warnings.warn(f"[UniTAP] Logger function receive exception: {exc}")
|
||||
|
||||
callback = TSI_USER_LOG_FUNCTION(ofp_impl)
|
||||
|
||||
def __TSIX_Init(self):
|
||||
global callback
|
||||
|
||||
config = TSI_INIT_CONFIGURATION()
|
||||
config.size = sizeof(config)
|
||||
config.version = self._TSI_CURRENT_VERSION
|
||||
config.function = callback
|
||||
|
||||
return self._TSIX_Init(byref(config))
|
||||
|
||||
def __TSI_Init(self):
|
||||
return self._TSI_Init(self._TSI_CURRENT_VERSION)
|
||||
|
||||
def __TSI_Clean(self):
|
||||
return self._TSI_Clean()
|
||||
|
||||
def TSIX_DEV_GetDeviceCount(self):
|
||||
return self._TSI_DEV_GetDeviceCount()
|
||||
|
||||
def TSIX_DEV_GetDeviceName(self, device_id: int):
|
||||
_device_name = create_string_buffer(TSI_NAME_SIZE)
|
||||
result = self._TSIX_DEV_GetDeviceName(device_id, _device_name, TSI_NAME_SIZE)
|
||||
return result, from_cstr(_device_name)
|
||||
|
||||
def TSIX_DEV_OpenDevice(self, device_id: int):
|
||||
result = c_int32(TSI_SUCCESS)
|
||||
device = self._TSIX_DEV_OpenDevice(c_uint32(device_id), byref(result))
|
||||
return device
|
||||
|
||||
def TSIX_DEV_SelectRole(self, device, role_id: int):
|
||||
return self._TSIX_DEV_SelectRole(device, role_id)
|
||||
|
||||
def TSIX_DEV_RescanDevices(self, search_options=1, required_caps=0, unallowed_caps=0):
|
||||
return self._TSIX_DEV_RescanDevices(search_options, required_caps, unallowed_caps)
|
||||
|
||||
def TSIX_DEV_GetDeviceRoleName(self, device, role_id: int):
|
||||
_log_string_size = c_uint32(65536)
|
||||
_log_string = create_string_buffer(_log_string_size.value)
|
||||
result = self._TSIX_DEV_GetDeviceRoleName(device, role_id, _log_string, _log_string_size)
|
||||
return result, from_cstr(_log_string)
|
||||
|
||||
def TSIX_DEV_GetDeviceRoleCount(self, device):
|
||||
return self._TSIX_DEV_GetDeviceRoleCount(device)
|
||||
|
||||
def TSIX_DEV_CloseDevice(self, device):
|
||||
return self._TSIX_DEV_CloseDevice(device)
|
||||
|
||||
def TSIX_TS_SetPortConfigItem(self, device_handle, port_id, config_id, data, data_type=c_uint32,
|
||||
data_count=1, data_size=0):
|
||||
result = 0
|
||||
if data_size > 0:
|
||||
if type(data) == int or type(data) == bool:
|
||||
_data = data_type(data)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
|
||||
byref(_data),
|
||||
data_size)
|
||||
elif type(data) == str:
|
||||
_data = create_string_buffer(data_count)
|
||||
_data.value = str.encode(data)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
|
||||
byref(_data),
|
||||
data_size)
|
||||
else:
|
||||
if type(data) == int or type(data) == bool or type(data) == float:
|
||||
_data = data_type(data)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
|
||||
byref(_data),
|
||||
sizeof(_data))
|
||||
elif type(data) == list or type(data) == bytearray or type(data) == tuple:
|
||||
_data = (data_type * data_count)(*data)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
|
||||
byref(_data),
|
||||
sizeof(_data))
|
||||
elif type(data) == str:
|
||||
_data = create_string_buffer(data_count)
|
||||
_data.value = str.encode(data)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
|
||||
byref(_data),
|
||||
sizeof(_data))
|
||||
elif str(type(data)).find('WINFUNCTYPE') != -1 or str(type(data)).find(
|
||||
'CFUNCTYPE') != -1:
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id, data,
|
||||
sizeof(data))
|
||||
elif issubclass(type(data), IntEnum):
|
||||
_data = data_type(data.value)
|
||||
result = self._TSI2_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
else:
|
||||
result = TSI_ERROR_NOT_IMPLEMENTED
|
||||
|
||||
return result
|
||||
|
||||
def TSIX_TS_SetConfigItem(self, device_handle, config_id, data, data_type=c_uint32,
|
||||
data_count=1,
|
||||
data_size=0):
|
||||
result = 0
|
||||
if data_size > 0:
|
||||
if type(data) == int or type(data) == bool:
|
||||
_data = data_type(data)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
data_size)
|
||||
elif type(data) == str:
|
||||
_data = create_string_buffer(data_count)
|
||||
_data.value = str.encode(data)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
data_size)
|
||||
else:
|
||||
if type(data) == int or type(data) == bool or type(data) == float:
|
||||
_data = data_type(data)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
elif type(data) == list or type(data) == bytearray:
|
||||
_data = (data_type * data_count)(*data)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
elif type(data) == str:
|
||||
_data = create_string_buffer(data_count)
|
||||
_data.value = str.encode(data)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
elif str(type(data)).find('WINFUNCTYPE') != -1 or str(type(data)).find(
|
||||
'CFUNCTYPE') != -1:
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, data, sizeof(data))
|
||||
elif issubclass(type(data), IntEnum):
|
||||
_data = data_type(data.value)
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
elif issubclass(type(data), Structure):
|
||||
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(data),
|
||||
sizeof(data))
|
||||
else:
|
||||
result = TSI_ERROR_NOT_IMPLEMENTED
|
||||
|
||||
return result
|
||||
|
||||
def TSIX_TS_GetPortConfigItem(self, device_handle, port_id, config_id, data_type, data_count=1):
|
||||
if data_type is None:
|
||||
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, data_type,
|
||||
data_count)
|
||||
result = rv,
|
||||
elif data_count > 1:
|
||||
_data = (data_type * data_count)()
|
||||
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, _data,
|
||||
sizeof(data_type) * data_count)
|
||||
if data_type == c_ubyte:
|
||||
result = rv, bytearray(_data), int(rv / sizeof(data_type))
|
||||
else:
|
||||
result = rv, list(_data), int(rv / sizeof(data_type))
|
||||
|
||||
else:
|
||||
_data = data_type(0)
|
||||
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, byref(_data),
|
||||
sizeof(_data))
|
||||
|
||||
if data_type in CTYPES_TYPE_LIST:
|
||||
result = rv, _data.value
|
||||
else:
|
||||
result = rv, _data
|
||||
|
||||
return result
|
||||
|
||||
def TSIX_TS_GetConfigItem(self, device_handle, config_id, data_type, data_count=1):
|
||||
if data_type is None:
|
||||
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count)
|
||||
result = rv,
|
||||
elif data_count > 1:
|
||||
_data = (data_type * data_count)()
|
||||
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, _data,
|
||||
sizeof(data_type) * data_count)
|
||||
result = rv, _data, data_count
|
||||
else:
|
||||
_data = data_type(0)
|
||||
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, byref(_data), sizeof(_data))
|
||||
|
||||
if data_type in CTYPES_TYPE_LIST:
|
||||
result = rv, _data.value
|
||||
else:
|
||||
result = rv, _data
|
||||
|
||||
return result
|
||||
|
||||
def TSI_MISC_GetErrorDescription(self, error):
|
||||
err_msg_size = 256
|
||||
err_msg = create_string_buffer(err_msg_size)
|
||||
result = self._TSI_MISC_GetErrorDescription(error, err_msg, err_msg_size)
|
||||
|
||||
return result, from_cstr(err_msg)
|
||||
|
||||
def TSIX_PORT_Select(self, device: TSI_HANDLE, port):
|
||||
return self._TSIX_PORT_Select(device, port)
|
||||
|
||||
def TSIX_PORT_Deselect(self, device: TSI_HANDLE, port):
|
||||
return self._TSIX_PORT_Deselect(device, port)
|
||||
|
||||
def TSIX_TS_RunTest(self, device: TSI_HANDLE, test_id: int):
|
||||
return self._TSIX_TS_RunTest(device, c_uint32(test_id))
|
||||
|
||||
def TSIX_TS_AbortTests(self, device: TSI_HANDLE):
|
||||
return self._TSIX_TS_AbortTests(device)
|
||||
|
||||
def TSIX_PORT_GetTestCount(self, device: TSI_HANDLE, port: TSI_LOGICAL_PORT):
|
||||
return self._TSIX_PORT_GetTestCount(device, port)
|
||||
|
||||
def TSIX_PORT_GetTestInfo(self, device: TSI_HANDLE, port: TSI_LOGICAL_PORT, test_index: int):
|
||||
msg_size = c_uint32(1024)
|
||||
test_id = c_uint32(0)
|
||||
msg_buffer = create_string_buffer(msg_size.value)
|
||||
test_flags = c_int32(0)
|
||||
|
||||
self._TSIX_PORT_GetTestInfo(device, port, test_index, byref(test_id), byref(test_flags),
|
||||
msg_buffer, msg_size)
|
||||
return test_id.value, test_flags.value, from_cstr(msg_buffer)
|
||||
|
||||
def TSIX_STLOG_WaitMessage(self, device: TSI_HANDLE, max_wait: int):
|
||||
return self._TSIX_STLOG_WaitMessage(device, c_int32(max_wait))
|
||||
|
||||
def TSIX_STLOG_GetMessageData(self, device: TSI_HANDLE):
|
||||
msg_size = c_uint32(1024)
|
||||
out_size = c_uint32(0)
|
||||
msg_buffer = create_string_buffer(msg_size.value)
|
||||
|
||||
result = self._TSIX_STLOG_GetMessageData(device, msg_buffer, msg_size, byref(out_size))
|
||||
|
||||
return result, from_cstr(msg_buffer), out_size.value
|
||||
|
||||
def TSI_CreateEventParser(self, timestamp_res: int = 100):
|
||||
result = c_int32(TSI_SUCCESS)
|
||||
return self._TSI_CreateEventParser(byref(result), c_uint32(timestamp_res))
|
||||
|
||||
def TSI_RemoveEventParser(self, parser):
|
||||
return self._TSI_RemoveEventParser(parser)
|
||||
|
||||
def TSI_GetParsedEventData(self, parser, data, to_dict=False):
|
||||
event_data = (c_ubyte * (len(data) - 12))(*data[12:])
|
||||
type_str_max_size = 128
|
||||
brief_str_max_size = 256
|
||||
content_str_max_size = 4096
|
||||
event_source_str_max_size = 64
|
||||
|
||||
typeStr = create_string_buffer(type_str_max_size)
|
||||
briefStr = create_string_buffer(brief_str_max_size)
|
||||
contentStr = create_string_buffer(content_str_max_size)
|
||||
eventSourceStr = create_string_buffer(event_source_str_max_size)
|
||||
timestamp = c_uint64(0)
|
||||
|
||||
result = self._TSI_GetParsedEventData(parser, event_data, c_int32(len(data) - 12),
|
||||
byref(timestamp),
|
||||
typeStr,
|
||||
type_str_max_size, briefStr,
|
||||
brief_str_max_size,
|
||||
contentStr, content_str_max_size, eventSourceStr,
|
||||
event_source_str_max_size)
|
||||
|
||||
if to_dict:
|
||||
return result, \
|
||||
{
|
||||
'timestamp': timestamp.value,
|
||||
'type': from_cstr(typeStr),
|
||||
'brief': from_cstr(briefStr),
|
||||
'content': from_cstr(contentStr),
|
||||
'source': from_cstr(eventSourceStr),
|
||||
'data': data[12:]
|
||||
}
|
||||
else:
|
||||
return result, timestamp.value, from_cstr(typeStr), from_cstr(briefStr), from_cstr(
|
||||
contentStr), from_cstr(
|
||||
eventSourceStr), data[12:]
|
||||
|
||||
def TSI_DEV_SetSearchMask(self, required_caps, unallowed_caps):
|
||||
return self._TSI_DEV_SetSearchMask(required_caps, unallowed_caps)
|
||||
|
||||
|
||||
class TSIEventParser:
|
||||
def __init__(self):
|
||||
self.__parser = None
|
||||
self.__parse_function = None
|
||||
|
||||
def __enter__(self):
|
||||
self.__parser = TSIWrapper().TSI_CreateEventParser()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
TSIWrapper().TSI_RemoveEventParser(self.__parser)
|
||||
|
||||
def parse(self, data, to_dict=False):
|
||||
return TSIWrapper().TSI_GetParsedEventData(self.__parser, data, to_dict)
|
||||
|
||||
|
||||
class TSI_INIT_CONFIGURATION(Structure):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.size = 0
|
||||
self.version = 0
|
||||
self.function = TSI_USER_LOG_FUNCTION()
|
||||
|
||||
_fields_ = [
|
||||
("size", c_uint),
|
||||
("version", c_uint),
|
||||
("function", TSI_USER_LOG_FUNCTION),
|
||||
]
|
||||
|
||||
|
||||
def get_config_item_name(config_item) -> str:
|
||||
items = globals().items()
|
||||
variable_name = [k for k, v in items if v == config_item][0]
|
||||
return variable_name
|
||||
|
||||
|
||||
def from_cstr(src_str):
|
||||
try:
|
||||
return src_str.value.decode('cp1252')
|
||||
except BaseException:
|
||||
return src_str.value.decode('utf-8')
|
||||
|
||||
|
||||
def to_cstr(src_str):
|
||||
return c_char_p(src_str.encode('utf-8'))
|
||||
|
||||
|
||||
def show_error(error_code):
|
||||
if error_code >= TSI_SUCCESS:
|
||||
return False
|
||||
result = TSI_MISC_GetErrorDescription(error_code)
|
||||
if result[0] < TSI_SUCCESS:
|
||||
val = f"Error {str(error_code)}: (No description available)\n"
|
||||
else:
|
||||
val = f"Error {str(error_code)}: {str(result[1])}\n"
|
||||
return val
|
||||
|
||||
|
||||
def create_c_array(data, _type, _size):
|
||||
buftype = _type * _size
|
||||
buf = buftype()
|
||||
buf.value = data
|
||||
return buf
|
||||
|
||||
|
||||
def TSIX_Init():
|
||||
return TSIWrapper().initialize()
|
||||
|
||||
|
||||
def TSI_Clean():
|
||||
return TSIWrapper().deinitialize()
|
||||
|
||||
|
||||
def TSIX_DEV_GetDeviceCount():
|
||||
return TSIWrapper().TSIX_DEV_GetDeviceCount()
|
||||
|
||||
|
||||
def TSIX_DEV_GetDeviceName(device_id: int):
|
||||
return TSIWrapper().TSIX_DEV_GetDeviceName(device_id)
|
||||
|
||||
|
||||
def TSIX_DEV_OpenDevice(device_id: int):
|
||||
return TSIWrapper().TSIX_DEV_OpenDevice(device_id)
|
||||
|
||||
|
||||
def TSIX_DEV_SelectRole(device, role_id: int):
|
||||
return TSIWrapper().TSIX_DEV_SelectRole(device, role_id)
|
||||
|
||||
|
||||
def TSIX_DEV_RescanDevices(search_options=1, required_caps=0, unallowed_caps=0):
|
||||
return TSIWrapper().TSIX_DEV_RescanDevices(search_options, required_caps, unallowed_caps)
|
||||
|
||||
|
||||
def TSIX_DEV_GetDeviceRoleName(device, role_id: int):
|
||||
return TSIWrapper().TSIX_DEV_GetDeviceRoleName(device, role_id)
|
||||
|
||||
|
||||
def TSIX_DEV_GetDeviceRoleCount(device):
|
||||
return TSIWrapper().TSIX_DEV_GetDeviceRoleCount(device)
|
||||
|
||||
|
||||
def TSIX_DEV_CloseDevice(device):
|
||||
return TSIWrapper().TSIX_DEV_CloseDevice(device)
|
||||
|
||||
|
||||
def TSIX_TS_SetPortConfigItem(device_handle, port_id, config_id, data, data_type=c_uint32,
|
||||
data_count=1, data_size=0):
|
||||
return TSIWrapper().TSIX_TS_SetPortConfigItem(device_handle, port_id, config_id, data,
|
||||
data_type, data_count, data_size)
|
||||
|
||||
|
||||
def TSIX_TS_SetConfigItem(device_handle, config_id, data, data_type=c_uint32, data_count=1,
|
||||
data_size=0):
|
||||
return TSIWrapper().TSIX_TS_SetConfigItem(device_handle, config_id, data,
|
||||
data_type, data_count, data_size)
|
||||
|
||||
|
||||
def TSIX_TS_GetPortConfigItem(device_handle, port_id, config_id, data_type, data_count=1):
|
||||
return TSIWrapper().TSIX_TS_GetPortConfigItem(device_handle, port_id, config_id, data_type,
|
||||
data_count)
|
||||
|
||||
|
||||
def TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count=1):
|
||||
return TSIWrapper().TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count)
|
||||
|
||||
|
||||
def TSI_MISC_GetErrorDescription(error):
|
||||
return TSIWrapper().TSI_MISC_GetErrorDescription(error)
|
||||
|
||||
|
||||
def TSIX_PORT_Select(device: TSI_HANDLE, port):
|
||||
return TSIWrapper().TSIX_PORT_Select(device, port)
|
||||
|
||||
|
||||
def TSIX_PORT_Deselect(device, port):
|
||||
return TSIWrapper().TSIX_PORT_Deselect(device, port)
|
||||
|
||||
|
||||
def TSIX_TS_RunTest(device: TSI_HANDLE, test_id: int):
|
||||
return TSIWrapper().TSIX_TS_RunTest(device, test_id)
|
||||
|
||||
|
||||
def TSIX_TS_AbortTests(device: TSI_HANDLE):
|
||||
return TSIWrapper().TSIX_TS_AbortTests(device)
|
||||
|
||||
|
||||
def TSIX_PORT_GetTestCount(device: TSI_HANDLE, port: TSI_LOGICAL_PORT):
|
||||
return TSIWrapper().TSIX_PORT_GetTestCount(device, port)
|
||||
|
||||
|
||||
def TSIX_PORT_GetTestInfo(device: TSI_HANDLE, port: TSI_LOGICAL_PORT, test_index: int):
|
||||
return TSIWrapper().TSIX_PORT_GetTestInfo(device, port, test_index)
|
||||
|
||||
|
||||
def TSIX_STLOG_WaitMessage(device: TSI_HANDLE, max_wait: int):
|
||||
return TSIWrapper().TSIX_STLOG_WaitMessage(device, max_wait)
|
||||
|
||||
|
||||
def TSIX_STLOG_GetMessageData(device: TSI_HANDLE):
|
||||
return TSIWrapper().TSIX_STLOG_GetMessageData(device)
|
||||
|
||||
|
||||
def TSI_CreateEventParser(timestamp_res: int = 100):
|
||||
return TSIWrapper().TSI_CreateEventParser(timestamp_res)
|
||||
|
||||
|
||||
def TSI_RemoveEventParser(parser):
|
||||
return TSIWrapper().TSI_RemoveEventParser(parser)
|
||||
|
||||
|
||||
def TSI_GetParsedEventData(parser, data, to_dict=False):
|
||||
return TSIWrapper().TSI_GetParsedEventData(parser, data, to_dict)
|
||||
|
||||
|
||||
def TSI_DEV_SetSearchMask(required_caps, unallowed_caps):
|
||||
return TSIWrapper().TSI_DEV_SetSearchMask(required_caps, unallowed_caps)
|
||||
253
UniTAP/libs/lib_tsi/tsi_io.py
Normal file
253
UniTAP/libs/lib_tsi/tsi_io.py
Normal file
@@ -0,0 +1,253 @@
|
||||
import weakref
|
||||
from ctypes import c_uint32, c_char
|
||||
from typing import Callable, Tuple, List
|
||||
from enum import IntEnum
|
||||
|
||||
from .tsi import (TSI_HANDLE, TSI_LOGICAL_PORT, TSI_SUCCESS, \
|
||||
TSIX_TS_SetConfigItem, TSIX_TS_GetConfigItem, TSIX_TS_SetPortConfigItem, \
|
||||
TSIX_TS_GetPortConfigItem, TSIX_Init, TSI_Clean, TSIX_DEV_RescanDevices, \
|
||||
TSIX_DEV_OpenDevice, TSIX_DEV_GetDeviceName, TSIX_DEV_GetDeviceCount,
|
||||
TSIX_DEV_CloseDevice, \
|
||||
TSIX_DEV_GetDeviceRoleCount, TSIX_DEV_SelectRole, TSIX_DEV_GetDeviceRoleName,
|
||||
TSIX_PORT_Select, \
|
||||
get_config_item_name, TSIX_TS_RunTest, TSIX_STLOG_WaitMessage,
|
||||
TSIX_STLOG_GetMessageData, \
|
||||
TSIX_PORT_GetTestCount, TSIX_PORT_GetTestInfo, TSI_TS_OF_MODE, \
|
||||
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE, TSI_TS_OF_REQ_ID, TSI_TS_OF_CALLBACK,
|
||||
TSI_FW_VERSION_TEXT,
|
||||
Structure, TSI_TEST_STATUS, TSI_DEVICE_INFO_R, TSI_BUNDLE_VERSION_TEXT, \
|
||||
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE_AND_RESULT, TSI_DEV_SetSearchMask,
|
||||
DeviceMaskInternal, \
|
||||
TSI_TEST_LOG_CONFIGURATION, TSI_TEST_ERROR_CODE_R, TSI_TEST_PASSED, TSI_TEST_FAILED,
|
||||
TSI_TEST_NOT_STARTED, TSI_TEST_ABORTED, TSIX_TS_AbortTests, TSI_TEST_DLG_CONFIG)
|
||||
|
||||
from UniTAP.utils import tsi_logging as logging
|
||||
|
||||
|
||||
class PortProtocol(IntEnum):
|
||||
DisplayPort = 0
|
||||
HDMI = 1
|
||||
DisplayPortThrowUSBC = 2
|
||||
|
||||
|
||||
class TestStatus(Structure):
|
||||
_fields_ = [
|
||||
("status", c_uint32, 8),
|
||||
("result", c_uint32, 7),
|
||||
("oper_rq", c_uint32, 1),
|
||||
("error", c_uint32, 7),
|
||||
("log_ovf", c_uint32, 1),
|
||||
("progress", c_uint32, 8),
|
||||
]
|
||||
|
||||
|
||||
class TestDialogConfig(Structure):
|
||||
_fields_ = [
|
||||
("disable_auto_precessing", c_uint32, 1),
|
||||
("reserved", c_uint32, 31)
|
||||
]
|
||||
|
||||
def __init__(self, disable_auto_precessing: bool):
|
||||
super().__init__()
|
||||
self.disable_auto_precessing = disable_auto_precessing
|
||||
|
||||
|
||||
class PortIO:
|
||||
def __init__(self, device: TSI_HANDLE, index: TSI_LOGICAL_PORT, protocol: PortProtocol):
|
||||
logging.info(f"[UniTAP] PortIO.init: {self}")
|
||||
self.__device = device
|
||||
self.__index = index
|
||||
self.__protocol = protocol
|
||||
self.active()
|
||||
|
||||
def __del__(self):
|
||||
logging.info(f"[UniTAP] PortIO.del: {self}")
|
||||
|
||||
def set(self, config_id, data, data_type=c_uint32, data_count=1, data_size=0):
|
||||
result = TSIX_TS_SetPortConfigItem(self.__device, self.__index, config_id, data, data_type,
|
||||
data_count,
|
||||
data_size)
|
||||
if isinstance(data, bytearray):
|
||||
logging.debug(f"[UniTAP] PortIO.set {self} {get_config_item_name(config_id)} "
|
||||
f"with data: {data[:(10 if len(data) > 10 else len(data))]}[{len(data)}] "
|
||||
f"({type(data)}); result: {result}")
|
||||
else:
|
||||
logging.debug(f"[UniTAP] PortIO.set {self} {get_config_item_name(config_id)} "
|
||||
f"with data: {data} ({type(data)}); result: {result}")
|
||||
return result
|
||||
|
||||
def get(self, config_id, data_type=c_uint32, data_count=1):
|
||||
result = TSIX_TS_GetPortConfigItem(self.__device, self.__index, config_id, data_type,
|
||||
data_count)
|
||||
logging.debug(
|
||||
f"PortIO.get {self} {get_config_item_name(config_id)} "
|
||||
f"with type: {data_type}[{data_count}]; result: {result}")
|
||||
|
||||
return result
|
||||
|
||||
def active(self):
|
||||
TSIX_PORT_Select(self.__device, self.__index)
|
||||
|
||||
def get_test_list(self) -> List[Tuple[int, int, str]]:
|
||||
test_list = []
|
||||
for test_id in range(self.__get_test_count()):
|
||||
test_list.append(self.__get_test_info(test_id))
|
||||
|
||||
return test_list
|
||||
|
||||
def protocol(self) -> PortProtocol:
|
||||
return self.__protocol
|
||||
|
||||
def index(self):
|
||||
return self.__index
|
||||
|
||||
def __get_test_count(self) -> int:
|
||||
return TSIX_PORT_GetTestCount(self.__device, self.__index)
|
||||
|
||||
def __get_test_info(self, test_id: int):
|
||||
return TSIX_PORT_GetTestInfo(self.__device, self.__index, test_id)
|
||||
|
||||
|
||||
class DeviceIO:
|
||||
MAX_FW_VERSION_STR_SIZE = 65535
|
||||
|
||||
def __init__(self, index: int):
|
||||
logging.info(f"[UniTAP] DeviceIO.init: {self}")
|
||||
self.__device = TSIX_DEV_OpenDevice(index)
|
||||
self.__port_io_list = [] # type: list[PortIO]
|
||||
self.__current_role = None
|
||||
|
||||
def __del__(self):
|
||||
self.__port_io_list.clear()
|
||||
TSIX_DEV_CloseDevice(self.__device)
|
||||
logging.info(f"[UniTAP] DeviceIO.del: {self}")
|
||||
|
||||
@property
|
||||
def device_handle(self):
|
||||
return self.__device
|
||||
|
||||
def set(self, config_id, data, data_type=c_uint32, data_count=1, data_size=0):
|
||||
return TSIX_TS_SetConfigItem(self.__device, config_id, data, data_type, data_count,
|
||||
data_size)
|
||||
|
||||
def get(self, config_id, data_type=c_uint32, data_count=1):
|
||||
return TSIX_TS_GetConfigItem(self.__device, config_id, data_type, data_count)
|
||||
|
||||
def get_device_role_count(self) -> int:
|
||||
return TSIX_DEV_GetDeviceRoleCount(self.__device)
|
||||
|
||||
def get_device_role_name(self, index) -> str:
|
||||
return TSIX_DEV_GetDeviceRoleName(self.__device, index)[1]
|
||||
|
||||
def select_role(self, index):
|
||||
logging.info(
|
||||
f"[UniTAP] DeviceIO.select_role: {index}")
|
||||
return TSIX_DEV_SelectRole(self.__device, index)
|
||||
|
||||
def create_port_io(self, index, protocol: PortProtocol) -> PortIO:
|
||||
self.__port_io_list.append(PortIO(self.__device, index, protocol))
|
||||
return weakref.proxy(self.__port_io_list[-1])
|
||||
|
||||
def set_opf_callback(self, callback: Callable):
|
||||
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_MODE,
|
||||
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE_AND_RESULT)
|
||||
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_REQ_ID, -1)
|
||||
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_CALLBACK, callback)
|
||||
|
||||
def set_opf_config(self, config: TestDialogConfig):
|
||||
self.set(TSI_TEST_DLG_CONFIG, config)
|
||||
|
||||
def get_test_list(self) -> List[Tuple[int, int, str]]:
|
||||
test_list = []
|
||||
for port in self.__port_io_list:
|
||||
test_list.extend(port.get_test_list())
|
||||
return test_list
|
||||
|
||||
def run_test(self, test_id: int):
|
||||
logging.info(
|
||||
f"[UniTAP] DeviceIO.run_test with id: {hex(test_id)} "
|
||||
f"(group={test_id >> 16 & 0xffff}; test={test_id & 0xffff})")
|
||||
|
||||
result = TSIX_TS_RunTest(self.__device, test_id)
|
||||
|
||||
if result not in [TSI_TEST_PASSED, TSI_TEST_FAILED, TSI_TEST_NOT_STARTED, TSI_TEST_ABORTED]:
|
||||
result = TSI_TEST_FAILED
|
||||
|
||||
return result
|
||||
|
||||
def abort_test(self):
|
||||
logging.info(f"[UniTAP] DeviceIO.abort_test")
|
||||
|
||||
return TSIX_TS_AbortTests(self.__device)
|
||||
|
||||
def set_test_config(self, config: int):
|
||||
if config > 0xffffffff or config < 0:
|
||||
raise ValueError("Test config value must be more than 0 and less than 0xffffffff")
|
||||
TSIX_TS_SetConfigItem(self.__device, TSI_TEST_LOG_CONFIGURATION, config)
|
||||
|
||||
def is_log_message_available(self, max_wait_timeout=5000) -> int:
|
||||
return int(TSIX_STLOG_WaitMessage(self.__device, max_wait_timeout))
|
||||
|
||||
def get_test_log_message(self) -> str:
|
||||
return TSIX_STLOG_GetMessageData(self.__device)
|
||||
|
||||
def get_test_status(self) -> TestStatus:
|
||||
return TSIX_TS_GetConfigItem(self.__device, TSI_TEST_STATUS, TestStatus, 1)[1]
|
||||
|
||||
def get_test_error_code(self) -> int:
|
||||
return TSIX_TS_GetConfigItem(self.__device, TSI_TEST_ERROR_CODE_R, c_uint32, 1)[1]
|
||||
|
||||
def get_fw_version_string(self):
|
||||
return TSIX_TS_GetConfigItem(self.__device, TSI_FW_VERSION_TEXT, c_char,
|
||||
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
|
||||
|
||||
def get_prepared_fw_info(self):
|
||||
return TSIX_TS_GetConfigItem(self.__device, TSI_DEVICE_INFO_R, c_char,
|
||||
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
|
||||
|
||||
def get_bundle_version(self):
|
||||
ver = TSIX_TS_GetConfigItem(self.__device, TSI_BUNDLE_VERSION_TEXT, c_char,
|
||||
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
|
||||
if ver == '':
|
||||
ver = 'not specified (NOT FOR SHARING)'
|
||||
return ver
|
||||
|
||||
def set_role(self, role):
|
||||
self.__current_role = role
|
||||
|
||||
def get_role(self):
|
||||
if self.__current_role is not None:
|
||||
return weakref.proxy(self.__current_role)
|
||||
return None
|
||||
|
||||
|
||||
class BaseIO:
|
||||
def __init__(self):
|
||||
self.__ref_count = TSIX_Init()
|
||||
logging.info(f"[UniTAP] BaseIO.init: {self}; Ref count: {self.__ref_count}")
|
||||
TSIX_DEV_RescanDevices()
|
||||
|
||||
def cleanup(self):
|
||||
self.__ref_count = TSI_Clean()
|
||||
logging.info(f"[UniTAP] BaseIO.del: {self}; Ref count: {self.__ref_count}")
|
||||
|
||||
def get_device_count(self) -> int:
|
||||
if self.__ref_count > 0:
|
||||
return TSIX_DEV_GetDeviceCount()
|
||||
logging.error("[UniTAP] BaseIO.get_device_count call without TSI_Init")
|
||||
|
||||
def get_device_name(self, index) -> str:
|
||||
if self.__ref_count > 0:
|
||||
return TSIX_DEV_GetDeviceName(index)[1]
|
||||
logging.error("[UniTAP] BaseIO.get_device_name call without TSI_Init")
|
||||
|
||||
def get_devices_by_mask(self, require_caps: DeviceMaskInternal,
|
||||
unallowed_caps: DeviceMaskInternal):
|
||||
if self.__ref_count > 0:
|
||||
return TSI_DEV_SetSearchMask(require_caps.value, unallowed_caps.value)
|
||||
logging.error("[UniTAP] BaseIO.get_devices_by_mask call without TSI_Init")
|
||||
|
||||
def create_device_io(self, index: int) -> DeviceIO:
|
||||
if self.__ref_count > 0:
|
||||
return DeviceIO(index)
|
||||
logging.error("[UniTAP] BaseIO.create_device_io call without TSI_Init")
|
||||
140
UniTAP/libs/lib_tsi/tsi_private_types.py
Normal file
140
UniTAP/libs/lib_tsi/tsi_private_types.py
Normal file
@@ -0,0 +1,140 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
|
||||
|
||||
TSI_CAP_OWNER_UNKNOWN = 0x0
|
||||
TSI_CAP_OWNER_NONE = 0x1
|
||||
TSI_CAP_OWNER_TEST_SYSTEM = 0x2
|
||||
TSI_CAP_OWNER_PREVIEW = 0x3
|
||||
TSI_CAP_OWNER = TSI_BASE_LEGACY_CAP(0x1f)
|
||||
|
||||
TSI_SEARCHOPTIONS_FIX_500_IN_UCDCONFIG = 0x80000000
|
||||
|
||||
TSI_VIDCAP_AVAILABLE_FRAME_COUNT_R = TSI_BASE_LEGACY_VIDCAP(0x1d)
|
||||
TSI_VIDCAP_CAPTURE_STATUS_R = TSI_BASE_LEGACY_VIDCAP(0x1e)
|
||||
TSI_VIDCAP_AVAILABLE_FRAME_COUNT = TSI_VIDCAP_AVAILABLE_FRAME_COUNT_R
|
||||
TSI_CRC_MEASUREMENT_DATA_R = TSI_BASE_R_CRC_VIDEO(0x3)
|
||||
|
||||
TSI_AUDCAP_PACKET_HEADER_R = TSI_BASE_LEGACY_AUDCAP(0xe)
|
||||
|
||||
TSI_PG_ADAPTIVE_SYNC_CTRL = 0x733
|
||||
TSI_PG_ADAPTIVE_SYNC_CAPS = 0x734
|
||||
TSI_PG_ADAPTIVE_SYNC_STS = 0x735
|
||||
TSI_PG_CAPS_R = 0x736
|
||||
TSI_PG_PR_CAPS_R = 0x737
|
||||
TSI_PG_PR_CTRL_W = 0x738
|
||||
TSI_PG_PR_STATUS_R = 0x738
|
||||
TSI_PG_PR_CFG = 0x739
|
||||
TSI_DPTX_EVENTS = TSI_BASE_DPTX(0x0e)
|
||||
TSI_DPTX_POST_LT_FEATURES = TSI_BASE_DPTX(0x68)
|
||||
TSI_DPTX_SDP_CTRL = TSI_BASE_DPTX(0x74)
|
||||
TSI_TEST_STATUS = 0x80000019 # Used for reading test status.
|
||||
TSI_DEVICE_INFO_R = 0x80000020 # Used for reading FW version
|
||||
TSI_TEST_ERROR_CODE_R = 0x80000021 # Used for reading test error code
|
||||
TSI_PDC_DPAM_CONFIG_R = TSI_BASE_PDC(0x33)
|
||||
TSI_PDC_HW_CAPS_R = TSI_BASE_PDC(0x00)
|
||||
TSI_PDC_CONTRACT_DATA = TSI_BASE_PDC(0x09)
|
||||
TSI_PDC_TX_ID_VDO_CNT = TSI_BASE_PDC(0x14)
|
||||
TSI_PDC_TX_ID_VDO = TSI_BASE_PDC(0x15)
|
||||
|
||||
TSI_DPTX_OUT_LC = TSI_BASE_DPTX(0x52)
|
||||
TSI_DPTX_OUT_BR = TSI_BASE_DPTX(0x53)
|
||||
TSI_DPTX_OUT_LINK_MODE = TSI_BASE_DPTX(0x54)
|
||||
TSI_DP2TX_OUT_BR = TSI_BASE_DPTX(0x55)
|
||||
TSI_DP2TX_OUT_LC = TSI_BASE_DPTX(0x5A)
|
||||
TSI_DP2TX_OUT_TEST_PATTERN = TSI_BASE_DPTX(0x5B)
|
||||
|
||||
TSI_MLEG_CONTROL = TSI_BASE_MLEG(0x00)
|
||||
TSI_MLEG_SYMBOL_REPLACE_A = TSI_BASE_MLEG(0x01)
|
||||
TSI_MLEG_SYMBOL_REPLACE_MASK_A = TSI_BASE_MLEG(0x02)
|
||||
TSI_MLEG_SYMBOL_REPLACE_B = TSI_BASE_MLEG(0x03)
|
||||
TSI_MLEG_SYMBOL_REPLACE_MASK_B = TSI_BASE_MLEG(0x04)
|
||||
TSI_MLEG_DELAY_COUNTER = TSI_BASE_MLEG(0x0A)
|
||||
TSI_MLEG_LANE0_REPLACE_COUNTERS = TSI_BASE_MLEG(0x05)
|
||||
TSI_MLEG_LANE1_REPLACE_COUNTERS = TSI_BASE_MLEG(0x06)
|
||||
TSI_MLEG_LANE2_REPLACE_COUNTERS = TSI_BASE_MLEG(0x07)
|
||||
TSI_MLEG_LANE3_REPLACE_COUNTERS = TSI_BASE_MLEG(0x08)
|
||||
|
||||
TSI_HDCP_2X_CFG = TSI_BASE_LEGACY_HDCP2(0x2)
|
||||
|
||||
TSI_W_PDC_EPR_MODE_CONTROL = TSI_BASE_PDC(0x04)
|
||||
|
||||
TSI_EVCAP_TIMESTAMP = TSI_BASE_LEGACY_EVCAP(0x8)
|
||||
|
||||
TSI_DPRX_INF_VALID_EX = TSI_BASE_DPRX(0x29)
|
||||
TSI_DPRX_SDP_CRC16_CTRL = TSI_BASE_DPRX(0x98)
|
||||
TSI_DPRX_SDP_CRC16_COUNTERS = TSI_BASE_DPRX(0x99)
|
||||
|
||||
TSI_HDRX_INF_STATUS = TSI_BASE_HDRX(0x0C)
|
||||
TSI_HDRX_INF_VALID = TSI_BASE_HDRX(0x0D)
|
||||
TSI_HDRX_INF_SELECT = TSI_BASE_HDRX(0x0E)
|
||||
TSI_HDRX_INF_DATA = TSI_BASE_HDRX(0x0F)
|
||||
|
||||
MAX_EDID_SIZE = 4096
|
||||
|
||||
TSI_DPRX_DSC_TEST_CRC = TSI_BASE_DPRX(0x43)
|
||||
TSI_DPRX_CRD_FEATURES = TSI_BASE_DPRX(0x63)
|
||||
TSI_DPRX_ALPM_LT_INFO_R = TSI_BASE_DPRX(0x38)
|
||||
|
||||
TSI_DPRX_MSA_INFO_R = TSI_BASE_DPRX(0x48)
|
||||
TSI_DPRX_MST_STATUS_R = TSI_BASE_DPRX(0x49)
|
||||
|
||||
TSI_GENERIC_STATUS = 0x210 # TSI State flags. NOTE: Access mode changes to R+W
|
||||
|
||||
TSI_VIDCAP_HDCP_PROTECTED_R = 0x8000f000
|
||||
TSI_VIDCAP_HDCP_DECRYPTED_R = 0x8000f001
|
||||
TSI_HDCP_COMPLIANT_R = 0x8000f002
|
||||
|
||||
TSI_DSC_BLOCK_NO = 0x80000009 # Used for stating start & end address to DSC PG. Changed 20191202 because not properly reserved.
|
||||
|
||||
TSI_CRC_DEFINITIONS = TSI_BASE_CRC_VIDEO(14) # CRC definitions. Default setting is 0
|
||||
TSI_CRC_WINDOW_0_0 = TSI_BASE_CRC_VIDEO(15) # Left border/window pixel for first window 15..0. Top border/window line for first window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_0_1 = TSI_BASE_CRC_VIDEO(16) # Right border pixel/ window width for first window. 15..0. Bottom border line / window height for first window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_1_0 = TSI_BASE_CRC_VIDEO(17) # Left border/window pixel for second window 15..0. Top border/window line for second window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_1_1 = TSI_BASE_CRC_VIDEO(18) # Right border pixel/ window width for second window. 15..0. Bottom border line / window height for second window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_2_0 = TSI_BASE_CRC_VIDEO(19) # Left border/window pixel for third window 15..0. Top border/window line for third window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_2_1 = TSI_BASE_CRC_VIDEO(20) # Right border pixel/ window width for third window. 15..0. Bottom border line / window height for third window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_3_0 = TSI_BASE_CRC_VIDEO(21) # Left border/window pixel for fourth window 15..0. Top border/window line for fourth window 31..16. Default setting is 0
|
||||
TSI_CRC_WINDOW_3_1 = TSI_BASE_CRC_VIDEO(22) # Right border pixel/ window width for fourth window. 15..0. Bottom border line / window height for fourth window 31..16. Default setting is 0
|
||||
|
||||
TSI_R_LC_COUNT = 0x80000010 # Number of licenses available.
|
||||
TSI_W_LC_SELECT = 0x80000011 # Index from 0 to LC_Count-1: Select which license to access through the CI's below
|
||||
TSI_R_LC_CODE = 0x80000012 # License ID (To identify type of license: "Basic" / "Advanced" / etc...)
|
||||
TSI_R_LC_NAME = 0x80000013 # Human readable name for license.
|
||||
TSI_R_LC_GET_KEY = 0x80000014 # Key string (40 characters, including the terminating NULL)
|
||||
TSI_W_LC_ADD_KEY = 0x80000015 # -> Write license key string. Matching key is validated and added.
|
||||
TSI_W_LC_REMOVE_KEY = 0x80000016 # -> Write license key string. Matching key is deleted.
|
||||
TSI_W_LC_HAS_CODE = 0x80000017 # Check if specified code is available on device.
|
||||
TSI_R_LC_SHA_TYPE = 0x80000018 # Check SHA type used in device.
|
||||
|
||||
TSI_DEVICE_DESCRIPTOR = 0x81000000
|
||||
TSI_DEBUG_INFORMATION = 0x82000000
|
||||
|
||||
TSI_SELECT_SUITE = TSI_BASE_TEST(0x04)
|
||||
TSI_TEST_DLG_CONFIG = TSI_BASE_TEST(0x22)
|
||||
|
||||
TSI_LOGICAL_PORT = c_uint
|
||||
TSI_PORT_FLAGS = c_uint
|
||||
|
||||
TSI_DPRX_ALPM_STATS_CONTROL_W = TSI_BASE_DPRX(0x60)
|
||||
TSI_DPRX_ALPM_STATS_STATUS_R = TSI_BASE_DPRX(0x60)
|
||||
TSI_DPRX_ALPM_STATS_VB_R = TSI_BASE_DPRX(0x61)
|
||||
TSI_DPRX_ALPM_STATS_IFP_R = TSI_BASE_DPRX(0x62)
|
||||
TSI_DPRX_ALPM_STATS_CTRL_W = TSI_DPRX_ALPM_STATS_CONTROL_W
|
||||
TSI_DSC_TX_CRC = TSI_BASE_DSC(0x01)
|
||||
TSI_DSC_MEMORY_BLOCK = TSI_BASE_DSC(0x05)
|
||||
TSI_DSC_DATA_SIZE = TSI_BASE_DSC(0x06)
|
||||
|
||||
TSI_TERMINAL_RW = 0xFFFFFFFE
|
||||
|
||||
TSI_DPTX_CABLE_ATTRIBUTES_R = TSI_BASE_DPTX(0x6E)
|
||||
TSI_DPRX_CABLE_ATTRIBUTES_R = TSI_BASE_DPRX(0x6E)
|
||||
|
||||
TSI_DPRX_LT_INTERNAL_USE = 0x50000000 + 0xFFFFF
|
||||
TSI_DPRX_LT_ROUTE_CREATE = TSI_BASE_LEGACY_DPRX(0x1A + TSI_DPRX_LT_INTERNAL_USE)
|
||||
|
||||
|
||||
class DeviceMaskInternal(IntEnum):
|
||||
Sink = TSI_DEVCAP_SINK
|
||||
Source = TSI_DEVCAP_SOURCE
|
||||
All = TSI_DEVCAP_ALL_CAPS
|
||||
Nothing = 0
|
||||
2414
UniTAP/libs/lib_tsi/tsi_types.py
Normal file
2414
UniTAP/libs/lib_tsi/tsi_types.py
Normal file
File diff suppressed because it is too large
Load Diff
BIN
UniTAP/libs/lib_uicl/UICL.dll
Normal file
BIN
UniTAP/libs/lib_uicl/UICL.dll
Normal file
Binary file not shown.
0
UniTAP/libs/lib_uicl/__init__.py
Normal file
0
UniTAP/libs/lib_uicl/__init__.py
Normal file
73
UniTAP/libs/lib_uicl/uicl.py
Normal file
73
UniTAP/libs/lib_uicl/uicl.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from .uicl_types import *
|
||||
from ..lib_helper import OS_Requirements, lib_method_wrapper
|
||||
|
||||
|
||||
UICL_CURRENT_VERSION = 1
|
||||
UICL = OS_Requirements("UICL").get_lib()
|
||||
|
||||
|
||||
class UICLError(Exception):
|
||||
def __init__(self, message, errors=None):
|
||||
super().__init__(message)
|
||||
self.errors = errors
|
||||
|
||||
|
||||
def UICL_GetRequiredBufferSize(dest_image: UICL_Image):
|
||||
_UICL_GetRequiredBufferSize = lib_method_wrapper(UICL.UICL_GetRequiredBufferSize, [POINTER(UICL_Image)], c_int64)
|
||||
|
||||
return _UICL_GetRequiredBufferSize(byref(dest_image))
|
||||
|
||||
|
||||
def UICL_Convert(src_image: UICL_Image, dest_image: UICL_Image):
|
||||
_UICL_Convert = lib_method_wrapper(UICL.UICL_Convert, [POINTER(UICL_Image), POINTER(UICL_Image)], UICL_RESULT)
|
||||
|
||||
return _UICL_Convert(byref(src_image), byref(dest_image))
|
||||
|
||||
|
||||
def UICL_SaveToFile(src_image: UICL_Image, file_name, image_file_format):
|
||||
_UICL_SaveToFile = lib_method_wrapper(UICL.UICL_SaveToFile, [c_char_p, POINTER(UICL_Image), c_int], UICL_RESULT)
|
||||
|
||||
return _UICL_SaveToFile(c_char_p(file_name.encode('utf-8')), byref(src_image), image_file_format)
|
||||
|
||||
|
||||
def UICL_CalculateCRC16(src_image: UICL_Image, crc: UICL_CRC16):
|
||||
_UICL_CalculateCRC16 = lib_method_wrapper(UICL.UICL_CalculateCRC16, [POINTER(UICL_Image), POINTER(UICL_CRC16)],
|
||||
UICL_RESULT)
|
||||
|
||||
return _UICL_CalculateCRC16(byref(src_image), byref(crc))
|
||||
|
||||
|
||||
def UICL_GeneratePattern(src_image: UICL_Image, pattern_type: int):
|
||||
_UICL_GeneratePattern = lib_method_wrapper(UICL.UICL_GeneratePattern, [POINTER(UICL_Image), c_int],
|
||||
UICL_RESULT)
|
||||
|
||||
return _UICL_GeneratePattern(byref(src_image), pattern_type)
|
||||
|
||||
|
||||
def UICL_GeneratePattern_3Tap(src_image: UICL_Image, pattern_type: int):
|
||||
_UICL_GeneratePattern_3Tap = lib_method_wrapper(UICL.UICL_GeneratePattern_3Tap, [POINTER(UICL_Image), c_int],
|
||||
UICL_RESULT)
|
||||
|
||||
return _UICL_GeneratePattern_3Tap(byref(src_image), pattern_type)
|
||||
|
||||
|
||||
def UICL_FreeImage(src_image: UICL_Image):
|
||||
_UICL_DeleteImage = lib_method_wrapper(UICL.UICL_FreeImage, [ POINTER(UICL_Image) ],
|
||||
UICL_RESULT)
|
||||
|
||||
return _UICL_DeleteImage(byref(src_image))
|
||||
|
||||
|
||||
def UICL_AllocImage(image_params: UICL_ImageParameters) -> UICL_Image:
|
||||
_UICL_AllocateImage = lib_method_wrapper(UICL.UICL_AllocImage,
|
||||
[POINTER(UICL_ImageParameters), POINTER(UICL_Image)],
|
||||
UICL_RESULT)
|
||||
|
||||
image = UICL_Image()
|
||||
|
||||
result = _UICL_AllocateImage(byref(image_params), byref(image))
|
||||
|
||||
if result < UICL_SUCCESS:
|
||||
raise UICLError(f"Cannot allocate image. Error code: {result}")
|
||||
|
||||
return image
|
||||
169
UniTAP/libs/lib_uicl/uicl_types.py
Normal file
169
UniTAP/libs/lib_uicl/uicl_types.py
Normal file
@@ -0,0 +1,169 @@
|
||||
from ctypes import *
|
||||
from enum import IntEnum
|
||||
|
||||
UICL_RESULT = c_int32
|
||||
|
||||
UICL_SUCCESS = 0
|
||||
UICL_ERROR_UNKNOWN = -1
|
||||
UICL_ERROR_NULL_IMAGE = -2
|
||||
UICL_ERROR_INVALID_COLORSPACE = -3
|
||||
UICL_ERROR_CONVERSION_NOT_SUPPORTED = -4
|
||||
|
||||
|
||||
class CtypesEnum(IntEnum):
|
||||
@classmethod
|
||||
def from_param(cls, obj):
|
||||
return int(obj)
|
||||
|
||||
|
||||
class UICL_ImageFileFormat(CtypesEnum):
|
||||
FILE_FORMAT_BMP = 0,
|
||||
FILE_FORMAT_BIN = 1,
|
||||
FILE_FORMAT_PPM = 2,
|
||||
|
||||
|
||||
class UICL_Colorspace(CtypesEnum):
|
||||
Colorspace_Unknown = 0,
|
||||
Colorspace_RGB = 1,
|
||||
Colorspace_YCbCr = 2,
|
||||
Colorspace_Raw = 3,
|
||||
Colorspace_Y = 4,
|
||||
Colorspace_MaxValue = 5
|
||||
|
||||
|
||||
class UICL_Sampling(CtypesEnum):
|
||||
Sampling_Unknown = 0,
|
||||
Sampling_444 = 1,
|
||||
Sampling_422 = 2,
|
||||
Sampling_420 = 3,
|
||||
Sampling_MaxValue = 4
|
||||
|
||||
|
||||
class UICL_Colorimetry(CtypesEnum):
|
||||
Colorimetry_Unknown = 0,
|
||||
Colorimetry_ITU_R_BT601 = 1,
|
||||
Colorimetry_ITU_R_BT709 = 2,
|
||||
Colorimetry_ITU_R_BT2020 = 3,
|
||||
Colorimetry_MaxValue = 4
|
||||
|
||||
|
||||
class UICL_Packing(CtypesEnum):
|
||||
Packing_Unknown = 0,
|
||||
Packing_Planar = 1,
|
||||
Packing_Packed = 2,
|
||||
Packing_DP_1_lane = 3
|
||||
Packing_DP_2_lane = 4
|
||||
Packing_DP_4_lane = 5
|
||||
Packing_MaxValue = 6
|
||||
|
||||
|
||||
class UICL_ComponentOrder(CtypesEnum):
|
||||
Order_Unknown = 0,
|
||||
Order_UCDTX_HI = 1,
|
||||
Order_UCDTX_LO = 2,
|
||||
Order_UCDRX = 3,
|
||||
Order_RGB = 4,
|
||||
Order_RGBA = 5,
|
||||
Order_BGR = 6,
|
||||
Order_BGRA = 7,
|
||||
Order_YCbCr = 8,
|
||||
Order_CbYCr = 9,
|
||||
Order_CbY0CrY1 = 10,
|
||||
Order_PlainRaw = 11,
|
||||
Order_Y = 12,
|
||||
Order_CirdanRaw = 13,
|
||||
Order_MaxValue = 14
|
||||
|
||||
|
||||
class UICL_Alignment(CtypesEnum):
|
||||
Alignment_Unknown = 0,
|
||||
Alignment_MSB = 1,
|
||||
Alignment_LSB = 2,
|
||||
Alignment_MaxValue = 3
|
||||
|
||||
|
||||
class UICL_ImageParameters(Structure):
|
||||
_fields_ = [
|
||||
('Width', c_uint32),
|
||||
('Height', c_uint32),
|
||||
('BitsPerColor', c_uint8),
|
||||
('Colorspace', c_int),
|
||||
('Colorimetry', c_int),
|
||||
('Sampling', c_int),
|
||||
('Packing', c_int),
|
||||
('ComponentOrder', c_int),
|
||||
('Alignment', c_int),
|
||||
('IsFullRange', c_bool),
|
||||
]
|
||||
|
||||
|
||||
class ImageFileFormat(CtypesEnum):
|
||||
FILE_FORMAT_BMP = 0,
|
||||
FILE_FORMAT_BIN = 1
|
||||
FILE_FORMAT_PPM = 2
|
||||
|
||||
|
||||
class UICL_Image(Structure):
|
||||
_fields_ = [
|
||||
('Parameters', UICL_ImageParameters),
|
||||
('DataPtr', POINTER(c_uint8)),
|
||||
('DataSize', c_uint64)
|
||||
]
|
||||
|
||||
|
||||
class UICL_CRC16(Structure):
|
||||
_fields_ = [
|
||||
('R', c_uint16),
|
||||
('G', c_uint16),
|
||||
('B', c_uint16)
|
||||
]
|
||||
|
||||
|
||||
parse_attributes_bpc = [6, 8, 10, 12, 16, 7, 14, 0]
|
||||
|
||||
parse_attributes_packing = [UICL_Packing.Packing_Packed,
|
||||
UICL_Packing.Packing_Packed,
|
||||
UICL_Packing.Packing_Unknown,
|
||||
UICL_Packing.Packing_Unknown]
|
||||
|
||||
parse_attributes_sampling = [UICL_Sampling.Sampling_444,
|
||||
UICL_Sampling.Sampling_422,
|
||||
UICL_Sampling.Sampling_444,
|
||||
UICL_Sampling.Sampling_420,
|
||||
UICL_Sampling.Sampling_444,
|
||||
UICL_Sampling.Sampling_Unknown,
|
||||
UICL_Sampling.Sampling_Unknown,
|
||||
UICL_Sampling.Sampling_Unknown]
|
||||
|
||||
parse_attributes_colorspace = [UICL_Colorspace.Colorspace_RGB,
|
||||
UICL_Colorspace.Colorspace_YCbCr,
|
||||
UICL_Colorspace.Colorspace_YCbCr,
|
||||
UICL_Colorspace.Colorspace_YCbCr,
|
||||
UICL_Colorspace.Colorspace_Y,
|
||||
UICL_Colorspace.Colorspace_Raw,
|
||||
UICL_Colorspace.Colorspace_Unknown,
|
||||
UICL_Colorspace.Colorspace_Unknown]
|
||||
|
||||
parse_attributes_colorimetry = [UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_ITU_R_BT601,
|
||||
UICL_Colorimetry.Colorimetry_ITU_R_BT709,
|
||||
UICL_Colorimetry.Colorimetry_Unknown]
|
||||
|
||||
parse_attributes_ecolorimetry = [UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_Unknown,
|
||||
UICL_Colorimetry.Colorimetry_ITU_R_BT2020,
|
||||
UICL_Colorimetry.Colorimetry_ITU_R_BT2020,
|
||||
UICL_Colorimetry.Colorimetry_ITU_R_BT601]
|
||||
|
||||
dict_colorspace = {0: "Unknown", 1: "RGB", 2: "YCbCr", 3: "Raw", 4: "MaxValue"}
|
||||
dict_sampling = {0: "Unknown", 1: "4:4:4", 2: "4:2:2", 3: "4:2:0"}
|
||||
dict_colorimetry = {0: "Unknown", 1: "RGB", 2: "ITU_R_BT601", 3: "ITU_R_BT709", 4: "ITU_R_BT2020"}
|
||||
dict_packing = {0: "Unknown", 1: "Planar", 2: "SemiPlanar", 3: "Packed", 4: "32bit", 5: "48bit"}
|
||||
dict_component_oreder = {0: "Unknown", 1: "UCDTX_HI", 2: "UCDTX_LO", 3: "UCDRX", 4: "RGB", 5: "RGBA", 6: "BGR",
|
||||
7: "BGRA", 8: "YCbCr", 9: "CbYCr", 10: "CrYCb", 11: "CbY0CrY1", 12: "PlainRaw"}
|
||||
dict_alignment = {0: "Unknown", 1: "MSB", 2: "LSB"}
|
||||
uicl_errors = {-1: "Error unknown", -2: "Error null image", -3: "Invalid colorspace", -4: "Conversion not supported",
|
||||
-5: "Error in conversion", -6: "Unsupported format", -7: "Invalid parameters"}
|
||||
331
UniTAP/libs/lib_uicl/uicl_utils.py
Normal file
331
UniTAP/libs/lib_uicl/uicl_utils.py
Normal file
@@ -0,0 +1,331 @@
|
||||
from UniTAP.common import VideoMode, VideoFrame, ColorInfo, Timing, ImageFileFormat, DataInfo
|
||||
from .uicl_types import UICL_Image, UICL_ImageParameters, UICL_Colorimetry, UICL_Sampling,\
|
||||
UICL_Colorspace, UICL_Packing, UICL_Alignment, UICL_ComponentOrder, UICL_SUCCESS,\
|
||||
UICL_ImageFileFormat
|
||||
from .uicl import UICL_Convert, UICL_GetRequiredBufferSize, UICL_SaveToFile, UICL_CRC16, UICL_CalculateCRC16
|
||||
|
||||
from typing import Tuple
|
||||
from ctypes import c_uint8
|
||||
|
||||
|
||||
def uicl_cf_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Colorspace:
|
||||
if color_format == ColorInfo.ColorFormat.CF_RGB:
|
||||
return UICL_Colorspace.Colorspace_RGB
|
||||
elif color_format in [ColorInfo.ColorFormat.CF_YCbCr_444, ColorInfo.ColorFormat.CF_YCbCr_422,
|
||||
ColorInfo.ColorFormat.CF_YCbCr_420]:
|
||||
return UICL_Colorspace.Colorspace_YCbCr
|
||||
else:
|
||||
return UICL_Colorspace.Colorspace_Unknown
|
||||
|
||||
|
||||
def uicl_sampling_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Sampling:
|
||||
if color_format in [ColorInfo.ColorFormat.CF_RGB, ColorInfo.ColorFormat.CF_YCbCr_444]:
|
||||
return UICL_Sampling.Sampling_444
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
|
||||
return UICL_Sampling.Sampling_422
|
||||
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
|
||||
return UICL_Sampling.Sampling_420
|
||||
else:
|
||||
return UICL_Sampling.Sampling_Unknown
|
||||
|
||||
|
||||
def uicl_colorimetry_from_ci_colorimetry(colorimetry: ColorInfo.Colorimetry) -> UICL_Colorimetry:
|
||||
if colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT601:
|
||||
return UICL_Colorimetry.Colorimetry_ITU_R_BT601
|
||||
elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT709:
|
||||
return UICL_Colorimetry.Colorimetry_ITU_R_BT709
|
||||
elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr:
|
||||
return UICL_Colorimetry.Colorimetry_ITU_R_BT2020
|
||||
else:
|
||||
return UICL_Colorimetry.Colorimetry_Unknown
|
||||
|
||||
|
||||
def uicl_colorimetry_to_ci_colorimetry(colorimetry: UICL_Colorimetry) -> ColorInfo.Colorimetry:
|
||||
if colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT601:
|
||||
return ColorInfo.Colorimetry.CM_ITUR_BT601
|
||||
elif colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT709:
|
||||
return ColorInfo.Colorimetry.CM_ITUR_BT709
|
||||
elif colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT2020:
|
||||
return ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr
|
||||
else:
|
||||
return ColorInfo.Colorimetry.CM_NONE
|
||||
|
||||
|
||||
def uicl_parameters_from_vm(vm: VideoMode) -> UICL_ImageParameters:
|
||||
parameters = UICL_ImageParameters()
|
||||
|
||||
parameters.Width = vm.timing.hactive
|
||||
parameters.Height = vm.timing.vactive
|
||||
parameters.BitsPerColor = vm.color_info.bpc
|
||||
parameters.Colorimetry = uicl_colorimetry_from_ci_colorimetry(vm.color_info.colorimetry)
|
||||
|
||||
if vm.color_info.color_format == ColorInfo.ColorFormat.CF_RGB:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_RGB
|
||||
parameters.ComponentOrder = UICL_ComponentOrder.Order_RGB
|
||||
parameters.Sampling = UICL_Sampling.Sampling_444
|
||||
parameters.Packing = UICL_Packing.Packing_Packed
|
||||
parameters.Alignment = UICL_Alignment.Alignment_LSB
|
||||
parameters.IsFullRange = vm.color_info.DynamicRange == ColorInfo.DynamicRange.DR_VESA
|
||||
|
||||
elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr
|
||||
parameters.Sampling = UICL_Sampling.Sampling_444
|
||||
parameters.Packing = UICL_Packing.Packing_Packed
|
||||
parameters.Alignment = UICL_Alignment.Alignment_LSB
|
||||
parameters.IsFullRange = False
|
||||
|
||||
elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.ComponentOrder = UICL_ComponentOrder.Order_CbY0CrY1
|
||||
parameters.Sampling = UICL_Sampling.Sampling_422
|
||||
parameters.Packing = UICL_Packing.Packing_Packed
|
||||
parameters.Alignment = UICL_Alignment.Alignment_LSB
|
||||
parameters.IsFullRange = False
|
||||
|
||||
elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr
|
||||
parameters.Sampling = UICL_Sampling.Sampling_420
|
||||
parameters.Packing = UICL_Packing.Packing_Planar
|
||||
parameters.Alignment = UICL_Alignment.Alignment_LSB
|
||||
parameters.IsFullRange = False
|
||||
|
||||
return parameters
|
||||
|
||||
|
||||
def uicl_image_from_vm_and_data(video_mode: VideoMode, data: bytearray) -> UICL_Image:
|
||||
image = UICL_Image()
|
||||
|
||||
image.DataPtr = (c_uint8 * len(data))(*data)
|
||||
image.DataSize = len(data)
|
||||
image.Parameters = uicl_parameters_from_vm(video_mode)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def uicl_image_convert_to_vm(src_image: UICL_Image, video_mode: VideoMode) -> bytearray:
|
||||
dest_image = UICL_Image()
|
||||
|
||||
dest_image.Parameters = uicl_parameters_from_vm(video_mode)
|
||||
result = UICL_GetRequiredBufferSize(dest_image)
|
||||
|
||||
assert result >= UICL_SUCCESS, f"Calculation required buffer size failed with error {result}"
|
||||
|
||||
dest_image.DataPtr = (c_uint8 * result)()
|
||||
dest_image.DataSize = result
|
||||
|
||||
result = UICL_Convert(src_image, dest_image)
|
||||
|
||||
assert result == UICL_SUCCESS, f"Image conversion failed with error {result}"
|
||||
|
||||
return bytearray(dest_image.DataPtr[:dest_image.DataSize])
|
||||
|
||||
|
||||
def image_from_vf(video_frame: VideoFrame) -> UICL_Image:
|
||||
image = UICL_Image()
|
||||
|
||||
image.Parameters = image_params_from_size_and_ci(video_frame.width, video_frame.height, video_frame.color_info,
|
||||
video_frame.data_info)
|
||||
image.DataSize = len(video_frame.data)
|
||||
image.DataPtr = (c_uint8 * len(video_frame.data)).from_buffer(video_frame.data)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def image_to_vf(image: UICL_Image) -> VideoFrame:
|
||||
video_frame = VideoFrame()
|
||||
|
||||
video_frame.width, video_frame.height, video_frame.color_info, video_frame.data_info = image_params_to_size_and_ci(image.Parameters)
|
||||
video_frame.data = bytearray(image.DataPtr[:image.DataSize])
|
||||
|
||||
return video_frame
|
||||
|
||||
|
||||
def uicl_image_calculate_crc(src_vf: VideoFrame) -> tuple:
|
||||
crc = UICL_CRC16()
|
||||
|
||||
src_image = image_from_vf(src_vf)
|
||||
|
||||
result = UICL_CalculateCRC16(src_image, crc)
|
||||
|
||||
assert result >= UICL_SUCCESS, f"Calculation CRC failed with error {result}"
|
||||
|
||||
return crc.R, crc.G, crc.B
|
||||
|
||||
|
||||
def image_params_to_vm(image_params: UICL_ImageParameters) -> VideoMode:
|
||||
pass
|
||||
|
||||
|
||||
def image_params_to_size_and_ci(image_params: UICL_ImageParameters) -> Tuple[int, int, ColorInfo, DataInfo]:
|
||||
width = image_params.Width
|
||||
height = image_params.Height
|
||||
color_info = ColorInfo()
|
||||
|
||||
color_info.bpc = image_params.BitsPerColor
|
||||
color_info.colorimetry = uicl_colorimetry_to_ci_colorimetry(image_params.Colorimetry)
|
||||
color_info.dynamic_range = ColorInfo.DynamicRange.DR_VESA if image_params.IsFullRange else ColorInfo.DynamicRange.DR_CTA
|
||||
|
||||
if image_params.Colorspace == UICL_Colorspace.Colorspace_RGB:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_RGB
|
||||
elif image_params.Colorspace == UICL_Colorspace.Colorspace_YCbCr:
|
||||
if image_params.Sampling == UICL_Sampling.Sampling_444:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_444
|
||||
elif image_params.Sampling == UICL_Sampling.Sampling_422:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_422
|
||||
elif image_params.Sampling == UICL_Sampling.Sampling_420:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_420
|
||||
else:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_UNKNOWN
|
||||
elif image_params.Colorspace == UICL_Colorspace.Colorspace_Y:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_Y_ONLY
|
||||
elif image_params.Colorspace == UICL_Colorspace.Colorspace_Raw:
|
||||
color_info.color_format = ColorInfo.ColorFormat.CF_RAW
|
||||
|
||||
data_info = DataInfo()
|
||||
data_info.alignment = uicl_alignment_to_vf_alignment(image_params.Alignment)
|
||||
data_info.component_order = uicl_com_order_to_vf_com_order(image_params.ComponentOrder)
|
||||
data_info.packing = uicl_packing_to_vf_packing(image_params.Packing)
|
||||
|
||||
return width, height, color_info, data_info
|
||||
|
||||
|
||||
def vf_com_order_to_uicl_com_order(component_order: DataInfo.ComponentOrder) -> UICL_ComponentOrder:
|
||||
if component_order == DataInfo.ComponentOrder.CO_UCDRX:
|
||||
return UICL_ComponentOrder.Order_UCDRX
|
||||
elif component_order == DataInfo.ComponentOrder.CO_RGB:
|
||||
return UICL_ComponentOrder.Order_RGB
|
||||
elif component_order == DataInfo.ComponentOrder.CO_RGBA:
|
||||
return UICL_ComponentOrder.Order_RGBA
|
||||
elif component_order == DataInfo.ComponentOrder.CO_BGR:
|
||||
return UICL_ComponentOrder.Order_BGR
|
||||
elif component_order == DataInfo.ComponentOrder.CO_BGRA:
|
||||
return UICL_ComponentOrder.Order_BGRA
|
||||
elif component_order == DataInfo.ComponentOrder.CO_YCbCr:
|
||||
return UICL_ComponentOrder.Order_YCbCr
|
||||
elif component_order == DataInfo.ComponentOrder.CO_CbY0CrY1:
|
||||
return UICL_ComponentOrder.Order_CbY0CrY1
|
||||
else:
|
||||
return UICL_ComponentOrder.Order_Unknown
|
||||
|
||||
|
||||
def uicl_com_order_to_vf_com_order(component_order: UICL_ComponentOrder) -> DataInfo.ComponentOrder:
|
||||
if component_order == UICL_ComponentOrder.Order_UCDRX:
|
||||
return DataInfo.ComponentOrder.CO_UCDRX
|
||||
elif component_order == UICL_ComponentOrder.Order_RGB:
|
||||
return DataInfo.ComponentOrder.CO_RGB
|
||||
elif component_order == UICL_ComponentOrder.Order_RGBA:
|
||||
return DataInfo.ComponentOrder.CO_RGBA
|
||||
elif component_order == UICL_ComponentOrder.Order_BGR:
|
||||
return DataInfo.ComponentOrder.CO_BGR
|
||||
elif component_order == UICL_ComponentOrder.Order_BGRA:
|
||||
return DataInfo.ComponentOrder.CO_BGRA
|
||||
elif component_order == UICL_ComponentOrder.Order_YCbCr:
|
||||
return DataInfo.ComponentOrder.CO_YCbCr
|
||||
elif component_order == UICL_ComponentOrder.Order_CbY0CrY1:
|
||||
return DataInfo.ComponentOrder.CO_CbY0CrY1
|
||||
else:
|
||||
return DataInfo.ComponentOrder.CO_UNKNOWN
|
||||
|
||||
|
||||
def vf_packing_to_uicl_packing(packing: DataInfo.Packing) -> UICL_Packing:
|
||||
if packing == DataInfo.Packing.P_PLANAR:
|
||||
return UICL_Packing.Packing_Planar
|
||||
elif packing == DataInfo.Packing.P_PACKED:
|
||||
return UICL_Packing.Packing_Packed
|
||||
else:
|
||||
return UICL_Packing.Packing_Unknown
|
||||
|
||||
|
||||
def uicl_packing_to_vf_packing(packing: UICL_Packing) -> DataInfo.Packing:
|
||||
if packing == UICL_Packing.Packing_Planar:
|
||||
return DataInfo.Packing.P_PLANAR
|
||||
elif packing == UICL_Packing.Packing_Packed:
|
||||
return DataInfo.Packing.P_PACKED
|
||||
else:
|
||||
return DataInfo.Packing.P_UNKNOWN
|
||||
|
||||
|
||||
def vf_alignment_to_uicl_alignment(alignment: DataInfo.Alignment) -> UICL_Alignment:
|
||||
if alignment == DataInfo.Alignment.A_LSB:
|
||||
return UICL_Alignment.Alignment_LSB
|
||||
elif alignment == DataInfo.Alignment.A_MSB:
|
||||
return UICL_Alignment.Alignment_MSB
|
||||
else:
|
||||
return UICL_Alignment.Alignment_Unknown
|
||||
|
||||
|
||||
def uicl_alignment_to_vf_alignment(alignment: UICL_Alignment) -> DataInfo.Alignment:
|
||||
if alignment == UICL_Alignment.Alignment_LSB:
|
||||
return DataInfo.Alignment.A_LSB
|
||||
elif alignment == UICL_Alignment.Alignment_MSB:
|
||||
return DataInfo.Alignment.A_MSB
|
||||
else:
|
||||
return DataInfo.Alignment.A_UNKNOWN
|
||||
|
||||
|
||||
def image_params_from_vm(video_mode: VideoMode) -> UICL_ImageParameters:
|
||||
pass
|
||||
|
||||
|
||||
def image_params_from_size_and_ci(width: int, height: int, color_info: ColorInfo,
|
||||
data_info: DataInfo) -> UICL_ImageParameters:
|
||||
parameters = UICL_ImageParameters()
|
||||
|
||||
parameters.Width = width
|
||||
parameters.Height = height
|
||||
parameters.BitsPerColor = color_info.bpc
|
||||
parameters.Colorimetry = uicl_colorimetry_from_ci_colorimetry(color_info.colorimetry)
|
||||
parameters.ComponentOrder = vf_com_order_to_uicl_com_order(data_info.component_order)
|
||||
parameters.Packing = vf_packing_to_uicl_packing(data_info.packing)
|
||||
parameters.Alignment = vf_alignment_to_uicl_alignment(data_info.alignment)
|
||||
|
||||
if color_info.color_format == ColorInfo.ColorFormat.CF_RGB:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_RGB
|
||||
parameters.Sampling = UICL_Sampling.Sampling_444
|
||||
parameters.IsFullRange = color_info.DynamicRange == ColorInfo.DynamicRange.DR_VESA
|
||||
|
||||
elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.Sampling = UICL_Sampling.Sampling_444
|
||||
parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False
|
||||
|
||||
elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.Sampling = UICL_Sampling.Sampling_422
|
||||
parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False
|
||||
|
||||
elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
|
||||
parameters.Sampling = UICL_Sampling.Sampling_420
|
||||
parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False
|
||||
|
||||
else:
|
||||
parameters.Colorspace = UICL_Colorspace.Colorspace_Unknown
|
||||
parameters.Sampling = UICL_Sampling.Sampling_Unknown
|
||||
parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False
|
||||
|
||||
return parameters
|
||||
|
||||
|
||||
def image_convert_to_parameters(src_image: UICL_Image, parameters: UICL_ImageParameters) -> UICL_Image:
|
||||
dst_image = UICL_Image()
|
||||
|
||||
dst_image.Parameters = parameters
|
||||
result = UICL_GetRequiredBufferSize(dst_image)
|
||||
|
||||
assert result >= UICL_SUCCESS, f"Calculation required buffer size failed with error {result}"
|
||||
|
||||
dst_image.DataSize = result
|
||||
dst_image.DataPtr = (c_uint8 * result)()
|
||||
|
||||
result = UICL_Convert(src_image, dst_image)
|
||||
|
||||
assert result >= UICL_SUCCESS, f"Image conversion failed with error {result}"
|
||||
|
||||
return dst_image
|
||||
|
||||
|
||||
def image_save_to_file(image: UICL_Image, path: str, image_format: UICL_ImageFileFormat) -> bool:
|
||||
return UICL_SaveToFile(image, path, image_format)
|
||||
Reference in New Issue
Block a user