Skip to content

Commit 15311a0

Browse files
committed
More tests after seek
1 parent 6919cf4 commit 15311a0

1 file changed

Lines changed: 43 additions & 4 deletions

File tree

test/test_decoders.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5062,9 +5062,12 @@ def test_audio_demuxer_seek(self):
50625062
# ===== Audio decoding: RawAudioSamples =====
50635063

50645064
@staticmethod
5065-
def _decode_audio(asset, stream_index=None):
5065+
def _decode_audio(asset, stream_index=None, seek_seconds=None):
50665066
demuxer = AudioDemuxer(asset.path, stream_index=stream_index)
50675067
decoder = AudioPacketDecoder(demuxer)
5068+
if seek_seconds is not None:
5069+
demuxer.seek(seek_seconds)
5070+
decoder.reset()
50685071
chunks = []
50695072
for packet in demuxer:
50705073
chunks += decoder.decode(packet)
@@ -5117,11 +5120,39 @@ def test_audio_raw_samples_dtype_and_shape(self, asset, sample_format, dtype):
51175120
NASA_AUDIO,
51185121
),
51195122
)
5120-
def test_audio_raw_samples_match_audio_decoder(self, asset):
5123+
@pytest.mark.parametrize("seek_fraction", (None, 1 / 3, 2 / 3))
5124+
def test_audio_raw_samples_match_audio_decoder(self, asset, seek_fraction):
51215125
# We hand out the true source samples: normalizing them the way FFmpeg
51225126
# does reproduces AudioDecoder's output bit for bit. This is also what
51235127
# pins the de-interleaving, most visibly on the 16-channel asset.
5124-
raw = torch.cat([chunk.data for chunk in self._decode_audio(asset)], dim=1)
5128+
#
5129+
# It holds after a seek too, but only once the caller has done the
5130+
# pre-roll these blocks don't do: a lossy codec decodes its first frames
5131+
# after a seek from a flushed state, so they come out subtly wrong -
5132+
# plausible, but not what whole-file decoding gives - until it
5133+
# re-primes. Dropping those frames is exactly what pre-rolling means,
5134+
# and everything from there on is bit exact again. Without the drop,
5135+
# mp3 and aac diverge over their first ~1000-1600 samples and match
5136+
# perfectly after that.
5137+
if seek_fraction is not None and asset is SINE_STEREO_MP2_MPEG_PS:
5138+
pytest.skip(
5139+
"MPEG-PS resync after a seek is unreliable for both the blocks "
5140+
"and AudioDecoder (which raises seeking this file to 2.8s), so "
5141+
"it can't tell us anything here. See "
5142+
"test_audio_decoder_mpeg_ps_resync_after_seek."
5143+
)
5144+
5145+
seek_seconds = (
5146+
None if seek_fraction is None else asset.duration_seconds * seek_fraction
5147+
)
5148+
chunks = self._decode_audio(asset, seek_seconds=seek_seconds)
5149+
if seek_seconds is not None:
5150+
# Same number of frames SingleStreamDecoder pre-rolls by, see
5151+
# Note [Audio pre-roll and post-roll].
5152+
chunks = chunks[4:]
5153+
assert len(chunks) > 0
5154+
5155+
raw = torch.cat([chunk.data for chunk in chunks], dim=1)
51255156

51265157
if raw.dtype == torch.uint8:
51275158
got = (raw.to(torch.float32) - 128) / 128
@@ -5130,7 +5161,15 @@ def test_audio_raw_samples_match_audio_decoder(self, asset):
51305161
else:
51315162
got = raw.to(torch.float32)
51325163

5133-
expected = AudioDecoder(asset.path).get_all_samples().data
5164+
decoder = AudioDecoder(asset.path)
5165+
if seek_seconds is None:
5166+
expected = decoder.get_all_samples().data
5167+
else:
5168+
# Re-anchor on the first frame we kept, so both sides start on the
5169+
# same sample.
5170+
expected = decoder.get_samples_played_in_range(
5171+
start_seconds=chunks[0].pts_seconds
5172+
).data
51345173
torch.testing.assert_close(got, expected, atol=0, rtol=0)
51355174

51365175
def test_audio_raw_samples_pts(self):

0 commit comments

Comments
 (0)