Из буфера памяти на диск как можно быстрееPython

Программы на Python
Ответить
Anonymous
 Из буфера памяти на диск как можно быстрее

Сообщение Anonymous »

Я хотел бы представить сценарий и обсудить подходящие шаблоны проектирования для его решения.
Рассмотрим простую ситуацию: камера записывает в буфер памяти в течение десяти секунд, прежде чем остановиться. После завершения записи открывается дескриптор двоичного файла, и данные передаются на диск.
Основным ограничением этого подхода является то, что запись ограничивается доступным размером оперативной памяти. Однако потеря кадров может и не быть проблемой.
Чтобы смягчить эту проблему, одним из возможных решений является использование выделенного потока или процесса для записи на диск. В этой настройке буфер памяти производителя используется совместно между основным потоком/процессом и записывающим потоком. Однако при этом возникает новая проблема: когда поток записи блокирует буфер, камера может оказаться неспособной разместить новые кадры, что может привести к потере кадров.
Вопрос >
Существует ли шаблон проектирования, который решает проблему, описанную во втором сценарии?
Ниже приведены примеры кода для двух сценариев на Python.
Первый сценарий на Python:
import io
from picamera2 import Picamera2
from picamera2.encoders import Encoder as NullEncoder
from picamera2.outputs import FileOutput

# Init camera
cam = Picamera2()

# Init memory buffer
mem_buff = io.BytesIO()
mem_out = FileOutput(mem_buff)

# Open camera
cam.start()

# Just writes frames without encoding i.e.: BGR888
encoder = NullEncoder()

# Recording time
to_record = 10
print(f"Start recording for {to_record} seconds")
cam.start_recording(encoder, mem_out)
time.sleep(to_record)
cam.stop_recording()
print("Finish recording")
cam.close()

# Begin data transfer to disk
out_fpath = "video.bin"
disk_transfer_start = time.perf_counter()
with open(out_fpath, "wb") as fd:
fd.write(mem_buff.getvalue())
disk_transfer_el = time.perf_counter() - disk_transfer_start
print(f"Data transfer took {disk_transfer_el} sec")

# Get a sense of how many frames are missing
totbytes = os.path.getsize(out_fpath)
byteel = 2304*1296*3 # (frame_width * frame_height * num_channels)
num_frames = totbytes / byteel
print(f"Video has {num_frames} frames")

Возможная реализация второго сценария на Python:
import io
from threading import Thread, Event, Lock
from picamera2 import Picamera2
from picamera2.encoders import Encoder as NullEncoder
from picamera2.outputs import FileOutput

def disk_writer(mem_buff: io.BytesIO, bin_fd, write_interval: int, stop_event: Event, lock: Lock):
while not stop_event.is_set():
start_loop = time.perf_counter()
lock.acquire()
curr_buff_pos = mem_buff.tell()
lock.release()
if curr_buff_pos > 0:
lock.acquire()
bin_fd.write(mem_buff.getvalue())
mem_buff.seek(0)
mem_buff.truncate(0)
lock.release()
elapsed = time.perf_counter() - start_loop
if elapsed < write_interval:
time.sleep(write_interval - elapsed)
if mem_buff.tell() > 0:
bin_fd.write(mem_buff.getvalue())
mem_buff.seek(0)
mem_buff.truncate(0)

# Init camera
cam = Picamera2()

# Init memory buffer
mem_buff = io.BytesIO()
mem_out = FileOutput(mem_buff)

# Get output file descriptor
bin_fd = open("video.bin", "wb")

# Open camera
cam.start()

# Create writing thread and start
stop_event = Event()
lock = Lock()
write_interval = 5
writer_thread = Thread(target=disk_writer, args=(mem_buff, bin_fd, write_interval, stop_event, lock))
writer_thread.start()

# Just writes frames without encoding i.e.: BGR888
encoder = NullEncoder()

# Recording time
to_record = 10
print(f"Start recording for {to_record} seconds")
cam.start_recording(encoder, mem_out)
time.sleep(to_record)
cam.stop_recording()
print("Finish recording")
stop_event.set()
writer_thread.join()
cam.close()
bin_fd.close()

# Get a sense of how many frames are missing
totbytes = os.path.getsize(out_fpath)
byteel = 2304*1296*3 # (frame_width * frame_height * num_channels)
num_frames = totbytes / byteel
print(f"Video has {num_frames} frames")


Подробнее здесь: https://stackoverflow.com/questions/791 ... s-possible
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»