Skip to content

Commit

Permalink
v1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
Lijun-Yu committed Jul 30, 2020
1 parent 23ed86a commit f781626
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ for frame in video:
image = frame.numpy()
# image is an uint8 array in a shape of (height, width, channel[BGR])
# ... Do something with the image
video.close() # Release internal buffers
```

### Replace `cv2.VideoCapture`
Expand All @@ -56,6 +57,7 @@ cap = AVIReader(video_path)
```

`AVIReader.read` follows the schema of `cv2.VideoCapture.read` but automatically inserts the missing frames while reading the video.
`AVIReader.release` also follows `cv2.VideoCapture.release`.

### Random Access

Expand Down
44 changes: 32 additions & 12 deletions avi_r/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(self, video_path: str, parent_dir: str = '',
'%s@%s' % (__name__, self.path), logging.INFO)
av.logging.set_level(av.logging.INFO)
self._assert_msg = 'Please open an issue with your video file at ' \
'https://github.com/Lijun-Yu/avi-r.'
'https://github.com/CMU-INF-DIVA/avi-r.'
self.fix_missing = fix_missing
if not self.fix_missing:
self._logger.warning('NOT fixing missing frames.')
Expand Down Expand Up @@ -211,18 +211,36 @@ def get_at(self, frame_id):
def reset(self):
"""Reset the internal states to load the video from the beginning.
"""
if hasattr(self, '_container'):
self._container.close()
self._del()
self._init()

def close(self):
"""Close the reader and delete internal buffers.
"""
self._del()

def release(self):
"""Following the API of cv2.VideoCapture.release() for consistency
in old codes.
"""
self.close()

def __del__(self):
if hasattr(self, '_container'):
self._container.close()
self._del()

def _init(self, video_stream_id=0):
self._container = av.open(self.path)
self._stream = self._container.streams.video[video_stream_id]
self._frame_gen = self._get_frame_gen()
self.reorder_buffer = []

def _del(self):
self._container.close()
del self._container
del self._stream
del self._frame_gen
del self.reorder_buffer

def _get_frame_gen(self, start_frame_id=0, retry=5, retry_step=120):
seek_frame_id = start_frame_id
Expand Down Expand Up @@ -298,18 +316,20 @@ def _fix_missing_one(self, start_frame_id, end_frame_id, src_frame):
start_frame_id, end_frame_id)

def _reorder(self):
buffer = []
self.reorder_buffer = []
for frame in self._decode():
if frame.key_frame:
for reordered_frame in sorted(buffer, key=lambda f: f.frame_id):
for reordered_frame in sorted(
self.reorder_buffer, key=lambda f: f.frame_id):
yield reordered_frame
buffer = [frame]
self.reorder_buffer = [frame]
else:
buffer.append(frame)
assert buffer[0].frame.key_frame
if len(buffer) > 0:
buffer = sorted(buffer, key=lambda f: f.frame_id)
for f in buffer:
self.reorder_buffer.append(frame)
assert self.reorder_buffer[0].frame.key_frame
if len(self.reorder_buffer) > 0:
self.reorder_buffer = sorted(
self.reorder_buffer, key=lambda f: f.frame_id)
for f in self.reorder_buffer:
yield f

def _decode(self):
Expand Down
4 changes: 4 additions & 0 deletions docs/version.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Version History

## AVI-R v1.3

* Fix memory leak with explicit `close` method.

## AVI-R v1.2.1

* Update video properties.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setuptools.setup(
name='avi-r',
version='1.2.1',
version='1.3',
author='Lijun Yu',
author_email='lijun@lj-y.com',
description='A robust reader for avi videos.',
Expand Down

0 comments on commit f781626

Please sign in to comment.