Fix timestamp comparison for seeks in fMP4

When seeking in fMP4, we try to extract as little samples as possible
by only starting at the preceding sync frame. This comparison should
use <= to allow sync frames at exactly the seek position.

Issue: google/ExoPlayer#10941

#minor-release

PiperOrigin-RevId: 505098172
This commit is contained in:
tonihei 2023-01-27 14:01:47 +00:00 committed by christosts
parent 3d82846074
commit 00436a04a4
6 changed files with 73 additions and 86 deletions

View File

@ -20,9 +20,12 @@
for seeking. for seeking.
* Use theme when loading drawables on API 21+ * Use theme when loading drawables on API 21+
([#220](https://github.com/androidx/media/issues/220)). ([#220](https://github.com/androidx/media/issues/220)).
* Extractors:
* Throw a ParserException instead of a NullPointerException if the sample * Throw a ParserException instead of a NullPointerException if the sample
table (stbl) is missing a required sample description (stsd) when table (stbl) is missing a required sample description (stsd) when
parsing trak atoms. parsing trak atoms.
* Correctly skip samples when seeking directly to a sync frame in fMP4
([#10941](https://github.com/google/ExoPlayer/issues/10941)).
* Audio: * Audio:
* Use the compressed audio format bitrate to calculate the min buffer size * Use the compressed audio format bitrate to calculate the min buffer size
for `AudioTrack` in direct playbacks (passthrough). for `AudioTrack` in direct playbacks (passthrough).

View File

@ -1675,15 +1675,15 @@ public class FragmentedMp4Extractor implements Extractor {
} }
/** /**
* Advances {@link #firstSampleToOutputIndex} to point to the sync sample before the specified * Advances {@link #firstSampleToOutputIndex} to point to the sync sample at or before the
* seek time in the current fragment. * specified seek time in the current fragment.
* *
* @param timeUs The seek time, in microseconds. * @param timeUs The seek time, in microseconds.
*/ */
public void seek(long timeUs) { public void seek(long timeUs) {
int searchIndex = currentSampleIndex; int searchIndex = currentSampleIndex;
while (searchIndex < fragment.sampleCount while (searchIndex < fragment.sampleCount
&& fragment.getSamplePresentationTimeUs(searchIndex) < timeUs) { && fragment.getSamplePresentationTimeUs(searchIndex) <= timeUs) {
if (fragment.sampleIsSyncFrameTable[searchIndex]) { if (fragment.sampleIsSyncFrameTable[searchIndex]) {
firstSampleToOutputIndex = searchIndex; firstSampleToOutputIndex = searchIndex;
} }

View File

@ -7,8 +7,8 @@ seekMap:
getPosition(288000) = [[timeUs=0, position=636]] getPosition(288000) = [[timeUs=0, position=636]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
total output bytes = 10752 total output bytes = 9216
sample count = 7 sample count = 6
format 0: format 0:
averageBitrate = 384000 averageBitrate = 384000
peakBitrate = 384000 peakBitrate = 384000
@ -18,30 +18,26 @@ track 0:
sampleRate = 48000 sampleRate = 48000
language = und language = und
sample 0: sample 0:
time = 64000
flags = 1
data = length 1536, hash 5D09685
sample 1:
time = 96000 time = 96000
flags = 1 flags = 1
data = length 1536, hash A9A24E44 data = length 1536, hash A9A24E44
sample 2: sample 1:
time = 128000 time = 128000
flags = 1 flags = 1
data = length 1536, hash 6F856273 data = length 1536, hash 6F856273
sample 3: sample 2:
time = 160000 time = 160000
flags = 1 flags = 1
data = length 1536, hash B1737D3C data = length 1536, hash B1737D3C
sample 4: sample 3:
time = 192000 time = 192000
flags = 1 flags = 1
data = length 1536, hash 98FDEB9D data = length 1536, hash 98FDEB9D
sample 5: sample 4:
time = 224000 time = 224000
flags = 1 flags = 1
data = length 1536, hash 99B9B943 data = length 1536, hash 99B9B943
sample 6: sample 5:
time = 256000 time = 256000
flags = 1 flags = 1
data = length 1536, hash AAD9FCD2 data = length 1536, hash AAD9FCD2

View File

@ -7,8 +7,8 @@ seekMap:
getPosition(288000) = [[timeUs=0, position=636]] getPosition(288000) = [[timeUs=0, position=636]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
total output bytes = 6144 total output bytes = 4608
sample count = 4 sample count = 3
format 0: format 0:
averageBitrate = 384000 averageBitrate = 384000
peakBitrate = 384000 peakBitrate = 384000
@ -18,18 +18,14 @@ track 0:
sampleRate = 48000 sampleRate = 48000
language = und language = und
sample 0: sample 0:
time = 160000
flags = 1
data = length 1536, hash B1737D3C
sample 1:
time = 192000 time = 192000
flags = 1 flags = 1
data = length 1536, hash 98FDEB9D data = length 1536, hash 98FDEB9D
sample 2: sample 1:
time = 224000 time = 224000
flags = 1 flags = 1
data = length 1536, hash 99B9B943 data = length 1536, hash 99B9B943
sample 3: sample 2:
time = 256000 time = 256000
flags = 1 flags = 1
data = length 1536, hash AAD9FCD2 data = length 1536, hash AAD9FCD2

View File

@ -7,8 +7,8 @@ seekMap:
getPosition(1728000) = [[timeUs=0, position=638]] getPosition(1728000) = [[timeUs=0, position=638]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
total output bytes = 148000 total output bytes = 144000
sample count = 37 sample count = 36
format 0: format 0:
peakBitrate = 1000000 peakBitrate = 1000000
id = 1 id = 1
@ -17,150 +17,146 @@ track 0:
sampleRate = 48000 sampleRate = 48000
language = und language = und
sample 0: sample 0:
time = 544000
flags = 1
data = length 4000, hash 27F20D29
sample 1:
time = 576000 time = 576000
flags = 1 flags = 1
data = length 4000, hash 6F565894 data = length 4000, hash 6F565894
sample 2: sample 1:
time = 608000 time = 608000
flags = 1 flags = 1
data = length 4000, hash A6F07C4A data = length 4000, hash A6F07C4A
sample 3: sample 2:
time = 640000 time = 640000
flags = 1 flags = 1
data = length 4000, hash 3A0CA15C data = length 4000, hash 3A0CA15C
sample 4: sample 3:
time = 672000 time = 672000
flags = 1 flags = 1
data = length 4000, hash DB365414 data = length 4000, hash DB365414
sample 5: sample 4:
time = 704000 time = 704000
flags = 1 flags = 1
data = length 4000, hash 31E08469 data = length 4000, hash 31E08469
sample 6: sample 5:
time = 736000 time = 736000
flags = 1 flags = 1
data = length 4000, hash 315F5C28 data = length 4000, hash 315F5C28
sample 7: sample 6:
time = 768000 time = 768000
flags = 1 flags = 1
data = length 4000, hash CC65DF80 data = length 4000, hash CC65DF80
sample 8: sample 7:
time = 800000 time = 800000
flags = 1 flags = 1
data = length 4000, hash 503FB64C data = length 4000, hash 503FB64C
sample 9: sample 8:
time = 832000 time = 832000
flags = 1 flags = 1
data = length 4000, hash 817CF735 data = length 4000, hash 817CF735
sample 10: sample 9:
time = 864000 time = 864000
flags = 1 flags = 1
data = length 4000, hash 37391ADA data = length 4000, hash 37391ADA
sample 11: sample 10:
time = 896000 time = 896000
flags = 1 flags = 1
data = length 4000, hash 37391ADA data = length 4000, hash 37391ADA
sample 12: sample 11:
time = 928000 time = 928000
flags = 1 flags = 1
data = length 4000, hash 64DBF751 data = length 4000, hash 64DBF751
sample 13: sample 12:
time = 960000 time = 960000
flags = 1 flags = 1
data = length 4000, hash 81AE828E data = length 4000, hash 81AE828E
sample 14: sample 13:
time = 992000 time = 992000
flags = 1 flags = 1
data = length 4000, hash 767D6C98 data = length 4000, hash 767D6C98
sample 15: sample 14:
time = 1024000 time = 1024000
flags = 1 flags = 1
data = length 4000, hash A5F6D4E data = length 4000, hash A5F6D4E
sample 16: sample 15:
time = 1056000 time = 1056000
flags = 1 flags = 1
data = length 4000, hash EABC6B0D data = length 4000, hash EABC6B0D
sample 17: sample 16:
time = 1088000 time = 1088000
flags = 1 flags = 1
data = length 4000, hash F47EF742 data = length 4000, hash F47EF742
sample 18: sample 17:
time = 1120000 time = 1120000
flags = 1 flags = 1
data = length 4000, hash 9B2549DA data = length 4000, hash 9B2549DA
sample 19: sample 18:
time = 1152000 time = 1152000
flags = 1 flags = 1
data = length 4000, hash A12733C9 data = length 4000, hash A12733C9
sample 20: sample 19:
time = 1184000 time = 1184000
flags = 1 flags = 1
data = length 4000, hash 95F62E99 data = length 4000, hash 95F62E99
sample 21: sample 20:
time = 1216000 time = 1216000
flags = 1 flags = 1
data = length 4000, hash A4D858 data = length 4000, hash A4D858
sample 22: sample 21:
time = 1248000 time = 1248000
flags = 1 flags = 1
data = length 4000, hash A4D858 data = length 4000, hash A4D858
sample 23: sample 22:
time = 1280000 time = 1280000
flags = 1 flags = 1
data = length 4000, hash 22C1A129 data = length 4000, hash 22C1A129
sample 24: sample 23:
time = 1312000 time = 1312000
flags = 1 flags = 1
data = length 4000, hash 2C51E4A1 data = length 4000, hash 2C51E4A1
sample 25: sample 24:
time = 1344000 time = 1344000
flags = 1 flags = 1
data = length 4000, hash 3782E8BB data = length 4000, hash 3782E8BB
sample 26: sample 25:
time = 1376000 time = 1376000
flags = 1 flags = 1
data = length 4000, hash 2C51E4A1 data = length 4000, hash 2C51E4A1
sample 27: sample 26:
time = 1408000 time = 1408000
flags = 1 flags = 1
data = length 4000, hash BDB3D129 data = length 4000, hash BDB3D129
sample 28: sample 27:
time = 1440000 time = 1440000
flags = 1 flags = 1
data = length 4000, hash F642A55 data = length 4000, hash F642A55
sample 29: sample 28:
time = 1472000 time = 1472000
flags = 1 flags = 1
data = length 4000, hash 32F259F4 data = length 4000, hash 32F259F4
sample 30: sample 29:
time = 1504000 time = 1504000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 31: sample 30:
time = 1536000 time = 1536000
flags = 1 flags = 1
data = length 4000, hash 57C98E1C data = length 4000, hash 57C98E1C
sample 32: sample 31:
time = 1568000 time = 1568000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 33: sample 32:
time = 1600000 time = 1600000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 34: sample 33:
time = 1632000 time = 1632000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 35: sample 34:
time = 1664000 time = 1664000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 36: sample 35:
time = 1696000 time = 1696000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C

View File

@ -7,8 +7,8 @@ seekMap:
getPosition(1728000) = [[timeUs=0, position=638]] getPosition(1728000) = [[timeUs=0, position=638]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
total output bytes = 76000 total output bytes = 72000
sample count = 19 sample count = 18
format 0: format 0:
peakBitrate = 1000000 peakBitrate = 1000000
id = 1 id = 1
@ -17,78 +17,74 @@ track 0:
sampleRate = 48000 sampleRate = 48000
language = und language = und
sample 0: sample 0:
time = 1120000
flags = 1
data = length 4000, hash 9B2549DA
sample 1:
time = 1152000 time = 1152000
flags = 1 flags = 1
data = length 4000, hash A12733C9 data = length 4000, hash A12733C9
sample 2: sample 1:
time = 1184000 time = 1184000
flags = 1 flags = 1
data = length 4000, hash 95F62E99 data = length 4000, hash 95F62E99
sample 3: sample 2:
time = 1216000 time = 1216000
flags = 1 flags = 1
data = length 4000, hash A4D858 data = length 4000, hash A4D858
sample 4: sample 3:
time = 1248000 time = 1248000
flags = 1 flags = 1
data = length 4000, hash A4D858 data = length 4000, hash A4D858
sample 5: sample 4:
time = 1280000 time = 1280000
flags = 1 flags = 1
data = length 4000, hash 22C1A129 data = length 4000, hash 22C1A129
sample 6: sample 5:
time = 1312000 time = 1312000
flags = 1 flags = 1
data = length 4000, hash 2C51E4A1 data = length 4000, hash 2C51E4A1
sample 7: sample 6:
time = 1344000 time = 1344000
flags = 1 flags = 1
data = length 4000, hash 3782E8BB data = length 4000, hash 3782E8BB
sample 8: sample 7:
time = 1376000 time = 1376000
flags = 1 flags = 1
data = length 4000, hash 2C51E4A1 data = length 4000, hash 2C51E4A1
sample 9: sample 8:
time = 1408000 time = 1408000
flags = 1 flags = 1
data = length 4000, hash BDB3D129 data = length 4000, hash BDB3D129
sample 10: sample 9:
time = 1440000 time = 1440000
flags = 1 flags = 1
data = length 4000, hash F642A55 data = length 4000, hash F642A55
sample 11: sample 10:
time = 1472000 time = 1472000
flags = 1 flags = 1
data = length 4000, hash 32F259F4 data = length 4000, hash 32F259F4
sample 12: sample 11:
time = 1504000 time = 1504000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 13: sample 12:
time = 1536000 time = 1536000
flags = 1 flags = 1
data = length 4000, hash 57C98E1C data = length 4000, hash 57C98E1C
sample 14: sample 13:
time = 1568000 time = 1568000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 15: sample 14:
time = 1600000 time = 1600000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 16: sample 15:
time = 1632000 time = 1632000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 17: sample 16:
time = 1664000 time = 1664000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C
sample 18: sample 17:
time = 1696000 time = 1696000
flags = 1 flags = 1
data = length 4000, hash 4C987B7C data = length 4000, hash 4C987B7C