215 lines
8.2 KiB
Python
215 lines
8.2 KiB
Python
# vim: set et sw=4 sts=4 fileencoding=utf-8:
|
|
#
|
|
# Python camera library for the Rasperry-Pi camera module
|
|
# Copyright (c) 2013-2017 Dave Jones <dave@waveform.org.uk>
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# * Neither the name of the copyright holder nor the
|
|
# names of its contributors may be used to endorse or promote products
|
|
# derived from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
from __future__ import (
|
|
unicode_literals,
|
|
print_function,
|
|
division,
|
|
absolute_import,
|
|
)
|
|
|
|
# Make Py2's str and range equivalent to Py3's
|
|
str = type('')
|
|
|
|
import warnings
|
|
from collections import namedtuple
|
|
|
|
from picamera.exc import (
|
|
mmal_check,
|
|
PiCameraError,
|
|
PiCameraMMALError,
|
|
PiCameraValueError,
|
|
PiCameraRuntimeError,
|
|
PiCameraDeprecated,
|
|
)
|
|
|
|
|
|
class PiVideoFrameType(object):
|
|
"""
|
|
This class simply defines constants used to represent the type of a frame
|
|
in :attr:`PiVideoFrame.frame_type`. Effectively it is a namespace for an
|
|
enum.
|
|
|
|
.. attribute:: frame
|
|
|
|
Indicates a predicted frame (P-frame). This is the most common frame
|
|
type.
|
|
|
|
.. attribute:: key_frame
|
|
|
|
Indicates an intra-frame (I-frame) also known as a key frame.
|
|
|
|
.. attribute:: sps_header
|
|
|
|
Indicates an inline SPS/PPS header (rather than picture data) which is
|
|
typically used as a split point.
|
|
|
|
.. attribute:: motion_data
|
|
|
|
Indicates the frame is inline motion vector data, rather than picture
|
|
data.
|
|
|
|
.. versionadded:: 1.5
|
|
"""
|
|
frame = 0
|
|
key_frame = 1
|
|
sps_header = 2
|
|
motion_data = 3
|
|
|
|
|
|
class PiVideoFrame(namedtuple('PiVideoFrame', (
|
|
'index', # the frame number, where the first frame is 0
|
|
'frame_type', # a constant indicating the frame type (see PiVideoFrameType)
|
|
'frame_size', # the size (in bytes) of the frame's data
|
|
'video_size', # the size (in bytes) of the video so far
|
|
'split_size', # the size (in bytes) of the video since the last split
|
|
'timestamp', # the presentation timestamp (PTS) of the frame
|
|
'complete', # whether the frame is complete or not
|
|
))):
|
|
"""
|
|
This class is a :func:`~collections.namedtuple` derivative used to store
|
|
information about a video frame. It is recommended that you access the
|
|
information stored by this class by attribute name rather than position
|
|
(for example: ``frame.index`` rather than ``frame[0]``).
|
|
|
|
.. attribute:: index
|
|
|
|
Returns the zero-based number of the frame. This is a monotonic counter
|
|
that is simply incremented every time the camera starts outputting a
|
|
new frame. As a consequence, this attribute cannot be used to detect
|
|
dropped frames. Nor does it necessarily represent actual frames; it
|
|
will be incremented for SPS headers and motion data buffers too.
|
|
|
|
.. attribute:: frame_type
|
|
|
|
Returns a constant indicating the kind of data that the frame contains
|
|
(see :class:`PiVideoFrameType`). Please note that certain frame types
|
|
contain no image data at all.
|
|
|
|
.. attribute:: frame_size
|
|
|
|
Returns the size in bytes of the current frame. If a frame is written
|
|
in multiple chunks, this value will increment while :attr:`index`
|
|
remains static. Query :attr:`complete` to determine whether the frame
|
|
has been completely output yet.
|
|
|
|
.. attribute:: video_size
|
|
|
|
Returns the size in bytes of the entire video up to this frame. Note
|
|
that this is unlikely to match the size of the actual file/stream
|
|
written so far. This is because a stream may utilize buffering which
|
|
will cause the actual amount written (e.g. to disk) to lag behind the
|
|
value reported by this attribute.
|
|
|
|
.. attribute:: split_size
|
|
|
|
Returns the size in bytes of the video recorded since the last call to
|
|
either :meth:`~PiCamera.start_recording` or
|
|
:meth:`~PiCamera.split_recording`. For the reasons explained above,
|
|
this may differ from the size of the actual file/stream written so far.
|
|
|
|
.. attribute:: timestamp
|
|
|
|
Returns the presentation timestamp (PTS) of the frame. This represents
|
|
the point in time that the Pi received the first line of the frame from
|
|
the camera.
|
|
|
|
The timestamp is measured in microseconds (millionths of a second).
|
|
When the camera's clock mode is ``'reset'`` (the default), the
|
|
timestamp is relative to the start of the video recording. When the
|
|
camera's :attr:`~PiCamera.clock_mode` is ``'raw'``, it is relative to
|
|
the last system reboot. See :attr:`~PiCamera.timestamp` for more
|
|
information.
|
|
|
|
.. warning::
|
|
|
|
Currently, the camera occasionally returns "time unknown" values in
|
|
this field. In this case, picamera will simply re-use the timestamp
|
|
of the previous frame (under the assumption that time never goes
|
|
backwards). This happens for SPS header "frames", for example.
|
|
|
|
.. attribute:: complete
|
|
|
|
Returns a bool indicating whether the current frame is complete or not.
|
|
If the frame is complete then :attr:`frame_size` will not increment
|
|
any further, and will reset for the next frame.
|
|
|
|
.. versionchanged:: 1.5
|
|
Deprecated :attr:`header` and :attr:`keyframe` attributes and added the
|
|
new :attr:`frame_type` attribute instead.
|
|
|
|
.. versionchanged:: 1.9
|
|
Added the :attr:`complete` attribute.
|
|
"""
|
|
|
|
__slots__ = () # workaround python issue #24931
|
|
|
|
@property
|
|
def position(self):
|
|
"""
|
|
Returns the zero-based position of the frame in the stream containing
|
|
it.
|
|
"""
|
|
return self.split_size - self.frame_size
|
|
|
|
@property
|
|
def keyframe(self):
|
|
"""
|
|
Returns a bool indicating whether the current frame is a keyframe (an
|
|
intra-frame, or I-frame in MPEG parlance).
|
|
|
|
.. deprecated:: 1.5
|
|
Please compare :attr:`frame_type` to
|
|
:attr:`PiVideoFrameType.key_frame` instead.
|
|
"""
|
|
warnings.warn(
|
|
PiCameraDeprecated(
|
|
'PiVideoFrame.keyframe is deprecated; please check '
|
|
'PiVideoFrame.frame_type for equality with '
|
|
'PiVideoFrameType.key_frame instead'))
|
|
return self.frame_type == PiVideoFrameType.key_frame
|
|
|
|
@property
|
|
def header(self):
|
|
"""
|
|
Contains a bool indicating whether the current frame is actually an
|
|
SPS/PPS header. Typically it is best to split an H.264 stream so that
|
|
it starts with an SPS/PPS header.
|
|
|
|
.. deprecated:: 1.5
|
|
Please compare :attr:`frame_type` to
|
|
:attr:`PiVideoFrameType.sps_header` instead.
|
|
"""
|
|
warnings.warn(
|
|
PiCameraDeprecated(
|
|
'PiVideoFrame.header is deprecated; please check '
|
|
'PiVideoFrame.frame_type for equality with '
|
|
'PiVideoFrameType.sps_header instead'))
|
|
return self.frame_type == PiVideoFrameType.sps_header
|