# Source code for picamera.frames

# vim: set et sw=4 sts=4 fileencoding=utf-8:
#
# Python camera library for the Rasperry-Pi camera module
# Copyright (c) 2013-2015 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,
)

[docs]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.

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.

"""
frame = 0
key_frame = 1
motion_data = 3

[docs]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 which picamera represents as None. If you are
querying this property you will need to check the value is not
None before using it. 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(
'PiVideoFrame.keyframe is deprecated; please check '
'PiVideoFrame.frame_type for equality with '
return self.frame_type == PiVideoFrameType.key_frame

@property
"""
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(