VideoStream.rate and VideoStream.framerate no longer available
Created by: uvjustin
Overview
After #910 was merged, VideoStream.rate and VideoStream.framerate are no longer populated from an InputContainer.
Expected behavior
These fields should be populated.
Investigation
Using the below test_streams.py file (augment the current test_streams.py with 2 additional lines), the test case now fails. Pre #910 it succeeded.
import av
from .common import TestCase, fate_suite
class TestStreams(TestCase):
def test_stream_tuples(self):
for fate_name in ("h264/interlaced_crop.mp4",):
container = av.open(fate_suite(fate_name))
video_streams = tuple([s for s in container.streams if s.type == "video"])
self.assertEqual(video_streams, container.streams.video)
audio_streams = tuple([s for s in container.streams if s.type == "audio"])
self.assertEqual(audio_streams, container.streams.audio)
def test_selection(self):
container = av.open(fate_suite("h264/interlaced_crop.mp4"))
video = container.streams.video[0]
# audio_stream = container.streams.audio[0]
# audio_streams = list(container.streams.audio[0:2])
self.assertEqual([video], container.streams.get(video=0))
self.assertEqual([video], container.streams.get(video=(0,)))
self.assertIsNotNone(video.rate)
self.assertIsNotNone(video.framerate)
# TODO: Find something in the fate suite with video, audio, and subtitles.
Actual behavior
fails
Research
I have done the following:
-
Checked the PyAV documentation -
Searched on Google -
Searched on Stack Overflow -
Looked through old GitHub issues -
Asked on PyAV Gitter -
... and waited 72 hours for a response.
Additional context
This is because the InputContainer's cinit was changed to initialize a separate AVCodecContext, and the parameters are copied over from the stream's AVCodecParameters using lib.avcodec_parameters_to_context(). However, AVCodecParameters does not include a video framerate, so the AVCodecContext never has the framerate field initialized for video streams. Note that AudioStream does not have this issue as the sample_rate field gets copied properly. As mentioned on #910, we can either solve this by:
- Copying the stream's avg_frame_rate into codec_context's framerate during InputContainer cinit, continuing to rely on passthrough into the codec_context when the properties are acccessed, or
- Adding the rate/framerate properties directly to VideoStream (pointing them to the AVStream's avg_frame_rate). There's a broader architectural theme here - continue relying on passthrough attribute access or not?