1.1.0版本
This commit is contained in:
1
UniTAP/dev/ports/modules/capturer/video/__init__.py
Normal file
1
UniTAP/dev/ports/modules/capturer/video/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .result_video import PictureFileFormat
|
||||
63
UniTAP/dev/ports/modules/capturer/video/result_video.py
Normal file
63
UniTAP/dev/ports/modules/capturer/video/result_video.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import warnings
|
||||
from UniTAP.dev.modules.capturer.result_object import ResultObject
|
||||
from UniTAP.dev.ports.modules.internal_utils.image_formats import PictureFileFormat, VideoFileFormat
|
||||
from UniTAP.dev.ports.modules.internal_utils.image_utils import save_video_to_bin, save_video_to_mp4
|
||||
from UniTAP.utils.uicl_api import video_frame_save_to_file, ImageFileFormat
|
||||
|
||||
|
||||
class ResultVideoObject(ResultObject):
|
||||
"""
|
||||
Class `ResultVideoObject` inherited from class `ResultObject`.
|
||||
Class `ResultVideoObject` allows saving captured frames to image `save_image_to_file`.
|
||||
Also has all the `ResultObject` functionality.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def save_image_to_file(self, file_format: PictureFileFormat, path: str, index: int):
|
||||
"""
|
||||
|
||||
Saving selected video frame to file. Supported file formats describe in `PictureFileFormat`.
|
||||
|
||||
Args:
|
||||
file_format (`PictureFileFormat`) - file format
|
||||
path (str) - path to save
|
||||
index (int) - number of video frame in list
|
||||
"""
|
||||
if len(self.buffer) > 0:
|
||||
if file_format == PictureFileFormat.BIN:
|
||||
video_frame_save_to_file(video_frame=self.buffer[index], path=path, file_type=ImageFileFormat.IFF_BIN)
|
||||
elif file_format == PictureFileFormat.BMP:
|
||||
video_frame_save_to_file(video_frame=self.buffer[index], path=path, file_type=ImageFileFormat.IFF_BMP)
|
||||
elif file_format == PictureFileFormat.PPM:
|
||||
video_frame_save_to_file(video_frame=self.buffer[index], path=path, file_type=ImageFileFormat.IFF_PPM)
|
||||
elif file_format == PictureFileFormat.DSC:
|
||||
video_frame_save_to_file(video_frame=self.buffer[index], path=path, file_type=ImageFileFormat.IFF_DSC)
|
||||
else:
|
||||
raise ValueError(f"Incorrect image format. Available formats: "
|
||||
f"{PictureFileFormat.BIN.name}, {PictureFileFormat.BMP.name}, "
|
||||
f"{PictureFileFormat.PPM.name}.\n"
|
||||
f"Transferred image format: {file_format.name}")
|
||||
else:
|
||||
warnings.warn("Buffer size is equal 0.")
|
||||
|
||||
def __save_to_video_file(self, file_format: VideoFileFormat, path: str):
|
||||
"""
|
||||
Will be implemented later.
|
||||
"""
|
||||
if len(self.buffer) > 0:
|
||||
if file_format == VideoFileFormat.BIN:
|
||||
save_video_to_bin(path=path, data=self.buffer)
|
||||
elif file_format == VideoFileFormat.MP4:
|
||||
save_video_to_mp4(path=path, data=self.buffer)
|
||||
else:
|
||||
raise ValueError(f"Incorrect video format. Available formats: "
|
||||
f"{VideoFileFormat.BIN.name}, {VideoFileFormat.MP4.name}.\n"
|
||||
f"Transferred video format: {file_format.name}")
|
||||
else:
|
||||
warnings.warn("Buffer size is equal 0.")
|
||||
|
||||
def __str__(self):
|
||||
return f"Start capture time: {self.start_capture_time}\n" \
|
||||
f"End capture time: {self.end_capture_time}\n" \
|
||||
f"Timestamp: {self.timestamp.__str__()}\n"
|
||||
224
UniTAP/dev/ports/modules/capturer/video/video_capturer.py
Normal file
224
UniTAP/dev/ports/modules/capturer/video/video_capturer.py
Normal file
@@ -0,0 +1,224 @@
|
||||
import time
|
||||
import warnings
|
||||
import copy
|
||||
|
||||
from typing import Union, List
|
||||
|
||||
from UniTAP.dev.modules.capturer.capture import Capturer, CaptureConfig
|
||||
from UniTAP.dev.modules.capturer.statuses import VideoCaptureStatus
|
||||
from UniTAP.common import VideoFrame, VideoFrameDSC
|
||||
from .result_video import ResultVideoObject
|
||||
|
||||
|
||||
class VideoCapturer:
|
||||
"""
|
||||
Class `VideoCapturer` allows working with capturing video frames on Sink (RX - receiver) side.
|
||||
You can `start` capturing in several modes, `stop` capturing, getting current `status` and result of
|
||||
capturing `capture_result`.
|
||||
"""
|
||||
|
||||
def __init__(self, capturer: Capturer, max_stream_number: int):
|
||||
self.__capturer = capturer
|
||||
self.__result = ResultVideoObject()
|
||||
self.__max_stream_number = max_stream_number
|
||||
|
||||
@property
|
||||
def status(self) -> VideoCaptureStatus:
|
||||
"""
|
||||
Returns current video capturer status.
|
||||
|
||||
Returns:
|
||||
object of `VideoCaptureStatus` type
|
||||
"""
|
||||
return self.__capturer.video_capturer_status
|
||||
|
||||
@property
|
||||
def capture_result(self) -> ResultVideoObject:
|
||||
"""
|
||||
Returns result of video capturing.
|
||||
|
||||
Returns:
|
||||
object of `ResultVideoObject` type
|
||||
"""
|
||||
return self.__result
|
||||
|
||||
@property
|
||||
def max_stream_number(self) -> int:
|
||||
"""
|
||||
Returns max stream number supported for capturing.
|
||||
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__max_stream_number
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop capture video.
|
||||
"""
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = CaptureConfig.Type.LIVE
|
||||
|
||||
self.__capturer.stop_capture(config)
|
||||
self.__result.end_capture_time = time.time()
|
||||
|
||||
def pop_element(self) -> Union[VideoFrame, VideoFrameDSC]:
|
||||
"""
|
||||
Return first object of `VideoFrame` or `VideoFrameDSC`.
|
||||
|
||||
Returns:
|
||||
object of `VideoFrame` or `VideoFrameDSC` type
|
||||
"""
|
||||
if self.status == VideoCaptureStatus.Idle:
|
||||
warnings.warn("Video capture is not working now. Please, turn it on.")
|
||||
captured_video_frames = self.__capturer.capture_video_by_n_frames(1)
|
||||
self.__result.buffer.extend(copy.deepcopy(captured_video_frames))
|
||||
return captured_video_frames[0]
|
||||
|
||||
def pop_element_as_result_object(self) -> ResultVideoObject:
|
||||
"""
|
||||
Return captured video frame(objects of `VideoFrame` or VideoFrameDSC`) as `ResultVideoObject`.
|
||||
|
||||
Returns:
|
||||
object of `ResultVideoObject` type
|
||||
"""
|
||||
available_frame_count = self.__capturer.get_available_video_frame_count()
|
||||
captured_video_frames = self.__capturer.capture_video_by_n_frames(available_frame_count)
|
||||
|
||||
res = ResultVideoObject()
|
||||
res.buffer.extend(captured_video_frames)
|
||||
return res
|
||||
|
||||
def pop_all_elements(self) -> Union[List[VideoFrame], List[VideoFrameDSC]]:
|
||||
"""
|
||||
Return all captured video frames(objects of `VideoFrame` or `VideoFrameDSC`).
|
||||
|
||||
Returns:
|
||||
object of list[`VideoFrame` or `VideoFrameDSC`] type
|
||||
"""
|
||||
if self.status == VideoCaptureStatus.Idle:
|
||||
warnings.warn("Video capture is not working now. Please, turn it on.")
|
||||
available_frame_count = self.__capturer.get_available_video_frame_count()
|
||||
print(f"Available frames count {available_frame_count}")
|
||||
captured_video_frames = self.__capturer.capture_video_by_n_frames(available_frame_count)
|
||||
self.__result.buffer.extend(copy.deepcopy(captured_video_frames))
|
||||
return captured_video_frames
|
||||
|
||||
def get_crc(self, crc_frame_count: int = 1) -> List[tuple[int, int, int]]:
|
||||
"""
|
||||
Returns captured crc values.
|
||||
|
||||
Returns:
|
||||
list[tuple[int, int, int]]
|
||||
"""
|
||||
return self.__capturer.capture_crc(crc_frame_count)
|
||||
|
||||
|
||||
class VideoCapturerDP(VideoCapturer):
|
||||
"""
|
||||
Class `VideoCapturerDP` inherited from class `VideoCapturer` and also allows working with capturing video frames
|
||||
on DP Sink (RX - receiver) side.
|
||||
You can `start` capturing in several modes, `stop` capturing, getting current `status` and result of
|
||||
capturing `capture_result`.
|
||||
"""
|
||||
|
||||
def __init__(self, capturer: Capturer, max_stream_number: int):
|
||||
super().__init__(capturer, max_stream_number)
|
||||
self.__capturer = capturer
|
||||
|
||||
def start(self, frames_count: int = 0, sec: int = 0, stream_number: int = 0,
|
||||
capture_type: CaptureConfig.Type = CaptureConfig.Type.LIVE):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
- Capture with fixed time (capturing will be continued fixed seconds and capturing will be stopped).
|
||||
- Capture without parameters - Live capturing (for getting frames you need to use functions `pop_element` and
|
||||
`pop_all_elements`)
|
||||
|
||||
All results can be obtained using the function `capture_result`.
|
||||
|
||||
Args:
|
||||
frames_count (int)
|
||||
sec (int)
|
||||
stream_number (int)
|
||||
capture_type (CaptureConfig.Type)
|
||||
"""
|
||||
|
||||
if stream_number >= self.max_stream_number:
|
||||
assert ValueError(f"Incorrect index of stream. Value must be from available options: "
|
||||
f"{', '.join([str(i) for i in range(self.max_stream_number)])}")
|
||||
|
||||
self.__capturer.set_video_stream_number(stream_number)
|
||||
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = capture_type
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.capture_result.clear()
|
||||
self.capture_result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count, capture_type))
|
||||
elif sec > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_sec(sec))
|
||||
|
||||
|
||||
def get_buffer_capacity(self, stream_number: int = 0):
|
||||
return self.__capturer.get_buffer_capacity(stream_number)
|
||||
|
||||
|
||||
class VideoCapturerHDMI(VideoCapturer):
|
||||
"""
|
||||
Class `VideoCapturerHDMI` inherited from class `VideoCapturer` and also allows working with capturing video frames
|
||||
on HDMI Sink (RX - receiver) side.
|
||||
You can `start` capturing in several modes, `stop` capturing, getting current `status` and result of
|
||||
capturing `capture_result`.
|
||||
"""
|
||||
|
||||
def __init__(self, capturer: Capturer, max_stream_number: int):
|
||||
super().__init__(capturer, max_stream_number)
|
||||
self.__capturer = capturer
|
||||
|
||||
def start(self, frames_count: int = 0, sec: int = 0, stream_number: int = 0):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
- Capture with fixed time (capturing will be continued fixed seconds and capturing will be stopped).
|
||||
- Capture without parameters - Live capturing (for getting frames you need to use functions `pop_element` and
|
||||
`pop_all_elements`)
|
||||
|
||||
All results can be obtained using the function `capture_result`.
|
||||
|
||||
Args:
|
||||
frames_count (int)
|
||||
sec (int)
|
||||
stream_number (int)
|
||||
"""
|
||||
|
||||
if stream_number >= self.max_stream_number:
|
||||
assert ValueError(f"Incorrect index of stream. Value must be from available options: "
|
||||
f"{', '.join([str(i) for i in range(self.max_stream_number)])}")
|
||||
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = CaptureConfig.Type.LIVE
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.capture_result.clear()
|
||||
self.capture_result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
if frames_count > 1:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count))
|
||||
else:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count))
|
||||
elif sec > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_sec(sec))
|
||||
|
||||
|
||||
def get_buffer_capacity(self):
|
||||
return self.__capturer.get_buffer_capacity()
|
||||
Reference in New Issue
Block a user