Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public static ImmutableList<String> mediaSamples() {
"sample_with_overlapping_srt.mkv",
"sample_with_vtt_subtitles.mkv",
"sample_with_null_terminated_vtt_subtitles.mkv",
"sample_with_vobsub.mkv");
"sample_with_vobsub.mkv",
"sample_recursive_seekhead.mkv");
}

@ParameterizedRobolectricTestRunner.Parameter public String inputFile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,9 @@ public static ExtractorsFactory newFactory(SubtitleParser.Factory subtitleParser

// Cue related elements.
private boolean seekForCues;
private boolean seekForSeekContent;
private long seekPositionAfterSeekingForHead = C.INDEX_UNSET;
private long seekHeadContentPosition = C.INDEX_UNSET;
private long cuesContentPosition = C.INDEX_UNSET;
private long seekPositionAfterBuildingCues = C.INDEX_UNSET;
private long clusterTimecodeUs = C.TIME_UNSET;
Expand Down Expand Up @@ -764,6 +767,10 @@ protected void startMasterElement(int id, long contentPosition, long contentSize
if (seekForCuesEnabled && cuesContentPosition != C.INDEX_UNSET) {
// We know where the Cues element is located. Seek to request it.
seekForCues = true;
} else if (seekForCuesEnabled && seekHeadContentPosition != C.INDEX_UNSET) {
// We do not know where the cues are located, however we have a seek-head entry
// we have not yet visited
seekForSeekContent = true;
} else {
// We don't know where the Cues element is located. It's most likely omitted. Allow
// playback, but disable seeking.
Expand Down Expand Up @@ -816,9 +823,16 @@ protected void endMasterElement(int id) throws ParserException {
if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.INDEX_UNSET) {
throw ParserException.createForMalformedContainer(
"Mandatory element SeekID or SeekPosition not found", /* cause= */ null);
}
if (seekEntryId == ID_CUES) {
} else if (seekEntryId == ID_SEEK_HEAD) {
seekHeadContentPosition = seekEntryPosition;
} else if (seekEntryId == ID_CUES) {
cuesContentPosition = seekEntryPosition;

// We are currently seeking from the seek-head, so we seek again to get to the cues
// instead of waiting for the cluster
if (seekForCuesEnabled && seekPositionAfterSeekingForHead != C.INDEX_UNSET) {
seekForCues = true;
}
}
break;
case ID_CUES:
Expand Down Expand Up @@ -1936,6 +1950,13 @@ private SeekMap buildSeekMap(
* @return Whether the seek position was updated.
*/
private boolean maybeSeekForCues(PositionHolder seekPosition, long currentPosition) {
if (seekForSeekContent) {
seekPositionAfterSeekingForHead = currentPosition;
seekPosition.position = seekHeadContentPosition;
seekForSeekContent = false;
return true;
}

if (seekForCues) {
seekPositionAfterBuildingCues = currentPosition;
seekPosition.position = cuesContentPosition;
Expand All @@ -1949,6 +1970,16 @@ private boolean maybeSeekForCues(PositionHolder seekPosition, long currentPositi
seekPositionAfterBuildingCues = C.INDEX_UNSET;
return true;
}

// After we have seeked back from seekPositionAfterBuildingCues seek back again to parse the
// rest of the file. This ends the double jump that is preformed when the beginning metadata
// only contains a ID_SEEK_HEAD without a ID_CUES.
if (sentSeekMap && seekPositionAfterSeekingForHead != C.INDEX_UNSET) {
seekPosition.position = seekPositionAfterSeekingForHead;
seekPositionAfterSeekingForHead = C.INDEX_UNSET;
return true;
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ public void mkvSample_withNullTerminatedVttSubtitles() throws Exception {
simulationConfig);
}

// https://github.com/androidx/media/issues/1143
@Test
public void mkvSample_withRecursiveSeekHead() throws Exception {
ExtractorAsserts.assertBehavior(
getExtractorFactory(subtitlesParsedDuringExtraction),
"media/mkv/sample_recursive_seekhead.mkv",
getAssertionConfigWithPrefix(
"media/mkv/sample_recursive_seekhead.mkv", subtitlesParsedDuringExtraction),
simulationConfig);
}

@Test
public void mkvSample_withVorbisAudio() throws Exception {
ExtractorAsserts.assertBehavior(
Expand Down
Binary file not shown.
Loading