diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a3cb9c0370..1b4899aa5e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,6 +14,9 @@ `MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory, boolean)` to specify whether the renderer will output metadata early or in sync with the player position. +* DASH: + * Parse `EventStream.presentationTimeOffset` from manifests + ([#10460](https://github.com/google/ExoPlayer/issues/10460)). * UI: * Use current overrides of the player as preset in `TrackSelectionDialogBuilder` diff --git a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java index 6c4e9bee10..c5006ad7b7 100644 --- a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java +++ b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java @@ -1105,13 +1105,15 @@ protected EventStream parseEventStream(XmlPullParser xpp) String schemeIdUri = parseString(xpp, "schemeIdUri", ""); String value = parseString(xpp, "value", ""); long timescale = parseLong(xpp, "timescale", 1); + long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", 0); List> eventMessages = new ArrayList<>(); ByteArrayOutputStream scratchOutputStream = new ByteArrayOutputStream(512); do { xpp.next(); if (XmlPullParserUtil.isStartTag(xpp, "Event")) { Pair event = - parseEvent(xpp, schemeIdUri, value, timescale, scratchOutputStream); + parseEvent( + xpp, schemeIdUri, value, timescale, presentationTimeOffset, scratchOutputStream); eventMessages.add(event); } else { maybeSkipTag(xpp); @@ -1144,6 +1146,7 @@ protected EventStream buildEventStream( * @param schemeIdUri The schemeIdUri of the parent EventStream. * @param value The schemeIdUri of the parent EventStream. * @param timescale The timescale of the parent EventStream. + * @param presentationTimeOffset The unscaled presentation time offset of the parent EventStream. * @param scratchOutputStream A {@link ByteArrayOutputStream} that is used when parsing event * objects. * @return A pair containing the node's presentation timestamp in microseconds and the parsed @@ -1156,6 +1159,7 @@ protected Pair parseEvent( String schemeIdUri, String value, long timescale, + long presentationTimeOffset, ByteArrayOutputStream scratchOutputStream) throws IOException, XmlPullParserException { long id = parseLong(xpp, "id", 0); @@ -1163,7 +1167,8 @@ protected Pair parseEvent( long presentationTime = parseLong(xpp, "presentationTime", 0); long durationMs = Util.scaleLargeTimestamp(duration, C.MILLIS_PER_SECOND, timescale); long presentationTimesUs = - Util.scaleLargeTimestamp(presentationTime, C.MICROS_PER_SECOND, timescale); + Util.scaleLargeTimestamp( + presentationTime - presentationTimeOffset, C.MICROS_PER_SECOND, timescale); String messageData = parseString(xpp, "messageData", null); byte[] eventObject = parseEventObject(xpp, scratchOutputStream); return Pair.create( diff --git a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/manifest/DashManifestParserTest.java b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/manifest/DashManifestParserTest.java index 7619322769..04d53b1841 100644 --- a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/manifest/DashManifestParserTest.java +++ b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/manifest/DashManifestParserTest.java @@ -139,7 +139,7 @@ public void parseMediaPresentationDescription_eventStream() throws IOException { ApplicationProvider.getApplicationContext(), SAMPLE_MPD_EVENT_STREAM)); Period period = manifest.getPeriod(0); - assertThat(period.eventStreams).hasSize(3); + assertThat(period.eventStreams).hasSize(4); // assert text-only event stream EventStream eventStream1 = period.eventStreams.get(0); @@ -150,10 +150,18 @@ public void parseMediaPresentationDescription_eventStream() throws IOException { assertThat(eventStream1.events[0]).isEqualTo(expectedEvent1); assertThat(eventStream1.presentationTimesUs[0]).isEqualTo(0); - // assert CData-structured event stream + // assert event stream with presentationTimeOffset EventStream eventStream2 = period.eventStreams.get(1); assertThat(eventStream2.events.length).isEqualTo(1); EventMessage expectedEvent2 = + new EventMessage("urn:uuid:with-pto", "pto-4s", 10000, 0, "pt=1s".getBytes(Charsets.UTF_8)); + assertThat(eventStream2.events[0]).isEqualTo(expectedEvent2); + assertThat(eventStream2.presentationTimesUs[0]).isEqualTo(1000000); + + // assert CData-structured event stream + EventStream eventStream3 = period.eventStreams.get(2); + assertThat(eventStream3.events.length).isEqualTo(1); + EventMessage expectedEvent3 = new EventMessage( "urn:dvb:iptv:cpm:2014", "", @@ -173,13 +181,13 @@ public void parseMediaPresentationDescription_eventStream() throws IOException { + " \n" + " ]]>")); - assertThat(eventStream2.events[0]).isEqualTo(expectedEvent2); - assertThat(eventStream2.presentationTimesUs[0]).isEqualTo(300000000); + assertThat(eventStream3.events[0]).isEqualTo(expectedEvent3); + assertThat(eventStream3.presentationTimesUs[0]).isEqualTo(300000000); // assert xml-structured event stream - EventStream eventStream3 = period.eventStreams.get(2); - assertThat(eventStream3.events.length).isEqualTo(1); - EventMessage expectedEvent3 = + EventStream eventStream4 = period.eventStreams.get(3); + assertThat(eventStream4.events.length).isEqualTo(1); + EventMessage expectedEvent4 = new EventMessage( "urn:scte:scte35:2014:xml+bin", "", @@ -191,8 +199,8 @@ public void parseMediaPresentationDescription_eventStream() throws IOException { + " /DAIAAAAAAAAAAAQAAZ/I0VniQAQAgBDVUVJQAAAAH+cAAAAAA==\n" + " \n" + " ")); - assertThat(eventStream3.events[0]).isEqualTo(expectedEvent3); - assertThat(eventStream3.presentationTimesUs[0]).isEqualTo(1000000000); + assertThat(eventStream4.events[0]).isEqualTo(expectedEvent4); + assertThat(eventStream4.presentationTimesUs[0]).isEqualTo(1000000000); } @Test diff --git a/libraries/test_data/src/test/assets/media/mpd/sample_mpd_event_stream b/libraries/test_data/src/test/assets/media/mpd/sample_mpd_event_stream index 15e3e07b89..8ad7ed4cd0 100644 --- a/libraries/test_data/src/test/assets/media/mpd/sample_mpd_event_stream +++ b/libraries/test_data/src/test/assets/media/mpd/sample_mpd_event_stream @@ -4,6 +4,9 @@ + + +