PyAV icon indicating copy to clipboard operation
PyAV copied to clipboard

VideoStream.rate and VideoStream.framerate no longer available

Open uvjustin opened this issue 3 years ago • 0 comments

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:

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:

  1. 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
  2. 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?

uvjustin avatar Jul 06 '22 14:07 uvjustin