blob: dc209b43fbb414be4638dfcc19d79235ba7c5fff [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry.internal.image_processing import frame_generator
from telemetry.internal.util import external_modules
cv2 = external_modules.ImportRequiredModule('cv2')
class VideoFileFrameGenerator(frame_generator.FrameGenerator):
"""Provides a Frame Generator for a video file.
Sample Usage:
generator = VideoFileFrameGenerator(sys.argv[1]).GetGenerator()
for frame in generator:
# Do something
Attributes:
_capture: The openCV video capture.
_frame_count: The number of frames in the video capture.
_frame_index: The frame number of the current frame.
_timestamp: The timestamp of the current frame.
_dimensions: The dimensions of the video capture."""
def __init__(self, video_filename, start_frame_index=0):
"""Initializes the VideoFileFrameGenerator object.
Args:
video_filename: str, The path to the video file.
start_frame_index: int, The number of frames to skip at the start of the
file.
Raises:
FrameReadError: A read error occurred during initialization."""
self._capture = cv2.VideoCapture(video_filename)
self._frame_count = int(self._capture.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
self._frame_index = -1
self._timestamp = 0
width = self._capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)
height = self._capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)
self._dimensions = (int(width), int(height))
if self._frame_count <= start_frame_index:
raise frame_generator.FrameReadError('Not enough frames in capture.')
while self._frame_index < start_frame_index - 1:
self._ReadFrame(True)
super(self.__class__, self).__init__()
def _ReadFrame(self, skip_decode=False):
"""Reads the next frame, updates attributes.
Args:
skip_decode: Whether or not to skip decoding. Useful for seeking.
Returns:
The frame if not EOF, 'None' if EOF.
Raises:
FrameReadError: Unexpectedly failed to read a frame from the capture."""
if self._frame_index >= self._frame_count - 1:
return None
self._timestamp = self._capture.get(cv2.cv.CV_CAP_PROP_POS_MSEC)
if skip_decode:
ret = self._capture.grab()
frame = None
else:
ret, frame = self._capture.read()
if not ret:
raise frame_generator.FrameReadError(
'Failed to read frame from capture.')
self._frame_index += 1
return frame
# OVERRIDE
def _CreateGenerator(self):
while True:
frame = self._ReadFrame()
if frame is None:
break
yield frame
# OVERRIDE
@property
def CurrentTimestamp(self):
return self._timestamp
# OVERRIDE
@property
def CurrentFrameNumber(self):
return self._frame_index
# OVERRIDE
@property
def Dimensions(self):
return self._dimensions