Source code for QVideo.dvr.QHDF5Writer
'''HDF5 video writer with per-frame timestamps.'''
from QVideo.lib import QVideoWriter
from QVideo.lib.videotypes import Image
try:
import h5py
except (ImportError, ModuleNotFoundError):
h5py = None
from time import time
import logging
__all__ = ['QHDF5Writer']
logger = logging.getLogger(__name__)
[docs]
class QHDF5Writer(QVideoWriter):
'''Video writer for HDF5 files.
Writes frames to an HDF5 file as a group of timestamped datasets.
Each frame is stored under a key equal to its elapsed time in
seconds since recording began. A ``Timestamp`` attribute on the
file records the absolute start time (UNIX epoch).
The file is created on the first frame and closed explicitly by
:meth:`close`. If the file cannot be created, :meth:`open`
returns ``False`` and no data are written.
Parameters
----------
filename : str
Path to the output HDF5 file.
*args :
Forwarded to :class:`~QVideo.lib.QVideoWriter`.
**kwargs :
Forwarded to :class:`~QVideo.lib.QVideoWriter`.
'''
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._file = None
self._writer = None
self._start = None
[docs]
def open(self, frame: Image) -> bool:
'''Open the HDF5 file for writing.
Called automatically by :meth:`~QVideo.lib.QVideoWriter.write`
on the first frame.
Parameters
----------
frame : Image
The first video frame (used only to trigger file creation;
dimensions are not required in advance for HDF5).
Returns
-------
bool
``True`` if the file was opened successfully; ``False`` if
the file could not be created.
'''
try:
self._file = h5py.File(self.filename, 'w',
libver='latest',
track_order=True)
except OSError:
logger.warning(f'Could not open {self.filename!r} for writing')
return False
self._start = time()
self._file.attrs['Timestamp'] = self._start
self._writer = self._file.create_group('images')
return True
[docs]
def isOpen(self) -> bool:
'''Return ``True`` if the HDF5 file is currently open.'''
return self._file is not None and bool(self._file)
def _write(self, frame: Image) -> None:
'''Write *frame* as a dataset keyed by elapsed time in seconds.'''
now = time() - self._start
self._writer.create_dataset(f'{now:.9f}', data=frame)
[docs]
def close(self) -> None:
'''Close the HDF5 file and reset internal state.'''
if self.isOpen():
self._file.close()
self._file = None
self._writer = None
self._start = None