Commit 6bd38512 authored by moto's avatar moto Committed by Facebook GitHub Bot
Browse files

Fix decimal FPS handling StreamWriter (#2831)

Summary:
StreamWriter assumed that frame rate is always expressed as 1/something, which is a reasonable assumption.

This commit fixes it by properly computing time_base from frame rate.

Address https://github.com/pytorch/audio/issues/2830

Pull Request resolved: https://github.com/pytorch/audio/pull/2831

Reviewed By: carolineechen

Differential Revision: D41036084

Pulled By: mthrok

fbshipit-source-id: 805881d4cb221ab2c002563aefb986e30fb91609
parent 7a1d5317
...@@ -327,3 +327,28 @@ class StreamWriterInterfaceTest(_MediaSourceMixin, TempDirMixin, TorchaudioTestC ...@@ -327,3 +327,28 @@ class StreamWriterInterfaceTest(_MediaSourceMixin, TempDirMixin, TorchaudioTestC
assert saved.shape == chunk.shape assert saved.shape == chunk.shape
if format in ["wav", "flac"]: if format in ["wav", "flac"]:
self.assertEqual(saved, chunk) self.assertEqual(saved, chunk)
def test_preserve_fps(self):
"""Decimal point frame rate is properly saved
https://github.com/pytorch/audio/issues/2830
"""
ext = "mp4"
filename = f"test.{ext}"
frame_rate = 5000 / 167
width, height = 96, 128
# Write data
dst = self.get_dst(filename)
writer = torchaudio.io.StreamWriter(dst=dst, format=ext)
writer.add_video_stream(frame_rate=frame_rate, width=width, height=height)
video = torch.randint(256, (90, 3, height, width), dtype=torch.uint8)
with writer.open():
writer.write_video_chunk(0, video)
if self.test_fileobj:
dst.flush()
# Load data
reader = torchaudio.io.StreamReader(src=self.get_temp_path(filename))
assert reader.get_src_stream_info(0).frame_rate == frame_rate
...@@ -111,7 +111,7 @@ void configure_audio_codec( ...@@ -111,7 +111,7 @@ void configure_audio_codec(
". Supported sample rates are: ", ". Supported sample rates are: ",
c10::Join(", ", rates)); c10::Join(", ", rates));
}(); }();
ctx->time_base = AVRational{1, static_cast<int>(sample_rate)}; ctx->time_base = av_inv_q(av_d2q(sample_rate, 1 << 24));
ctx->sample_fmt = [&]() { ctx->sample_fmt = [&]() {
// Use default // Use default
if (!format) { if (!format) {
...@@ -177,7 +177,7 @@ void configure_video_codec( ...@@ -177,7 +177,7 @@ void configure_video_codec(
ctx->width = static_cast<int>(width); ctx->width = static_cast<int>(width);
ctx->height = static_cast<int>(height); ctx->height = static_cast<int>(height);
ctx->time_base = [&]() { ctx->time_base = [&]() {
AVRational ret = AVRational{1, static_cast<int>(frame_rate)}; AVRational ret = av_inv_q(av_d2q(frame_rate, 1 << 24));
auto rates = get_supported_frame_rates(ctx->codec); auto rates = get_supported_frame_rates(ctx->codec);
// Codec does not have constraint on frame rate // Codec does not have constraint on frame rate
if (rates.empty()) { if (rates.empty()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment