media icon indicating copy to clipboard operation
media copied to clipboard

period@start time is missing in presentationTimesUs calculation of EventStream

Open akhilesh-dubey opened this issue 11 months ago • 6 comments

Version

Media3 main branch

More version details

We have encountered with an issue with the Event@presentationTime calculation in Exo Player. Based on the Exo Player logic, the event’s presentation time is calculated as: Event@presentationTime - EventStream@presentationTimeOffset

Here is the manifest for reference:

<Period id="173" start="PT14H17M58S">
  <EventStream schemeIdUri="metadata-update" timescale="1000" presentationTimeOffset="51478000">
    <Event presentationTime="11211" id="2054">...</Event>
...

This results in a presentation time of -51466789, which is way before the Period's start time and this appears incorrect.

Referencing the MPD events timing model in the DASH spec, The formula for the event start:

The ST of an MPD event, relative to period start time of Period containing the Event, can be calculated using values in its EventStream and Event elements: ST = PST + (PT - PTO)/TS where: — PST is the Period start time of the Period containing the event stream. — PTO is the presentation time offset of the Event Stream provided by EventStream@presentationTimeoffset. — TS is the value of EventStream@timescale. — PT is the value of EventStream@presentationTime.

Which is: PST = PT14H17M58S = 51478S PT = 11211 PTO = 51478000 TS = 1000 Based on the given formula: ST = PST + (PT - PTO) / TS The calculated Event Start Time is 11.211 seconds.

However, ExoPlayer provides a presentation time of -51466789, which indicates that ExoPlayer does not appear to follow the latest DASH specification (Edition 5).

Dash Spec: https://standards.iso.org/ittf/PubliclyAvailableStandards/c083314_ISO_IEC%2023009-1_2022(en).zip

I checked the Exo Player code and found that parseEvent() API of DashManifestParser, It calculates the presentationTime time as below:

    long presentationTimesUs =
        Util.scaleLargeTimestamp(
            presentationTime - presentationTimeOffset, C.MICROS_PER_SECOND, timescale);

Which does not follows the latest Dash Spec(Edition 5).

Reference: Image

Devices that reproduce the issue

Any Android Device

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

Play a live event which has the EventStream with EventStream@presentationTimeOffset and EventStream@presentationTime. When we get the EventStream.presentationTimesUs it returns the incorrect PT time.

Expected result

While creating the EventStream instance, We should also add the period@start time in presentationTimesUs to follow the DASH specification.

Actual result

While creating the EventStream instance, We are not adding the period@start time in presentationTimesUs.

Media

NA

Bug Report

  • [x] You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

akhilesh-dubey avatar Feb 04 '25 11:02 akhilesh-dubey

Thanks for your report and the detailed explanation!

Your reasoning assumes that the value calculated in parseEvent is the ST from above, which I'm not convinced this is true. Instead this simply calculates the presentation time of the event within the period which is the right part of the equation above:

PT - PTO /  TS

This is parsed and then set into the Pair<Long, Event> that is returned by parseEvent. My interpretation is that the calculated value presentationTimeUs is the start time of the event within the period (relative to the period start) and a period in ExoPlayer always starts at position 0.

I think that the terms period start time in Figure A3 from above, refers to the start time of the period within the stream. Whereas the start of the period in ExoPlayer is always 0.

This kind of simplifies the equation from above because in the sense of PST=0.

When looking into MetadatRenderer I mean that the code seconds my reasoning from above:

In MetadataRenderer.getPresentationTimeUs, the actual presentation time relative to the period start is calculated by subtracting outputStreamOffsetUs from positionUs. positionUs is the current render position.

positionUs - outputStreamOffsetUs

The render position of the period start is set when MetadataRenderer.onStreamChanged is called and offsetUs is passed in that then is assigned to outputStreamOffsetUs used by getPresentationTimeUs(positionUs).

Further, from the equation above and the manifest values presentationTimeOffset="51478000" and presentationTime="11211" (as in 'offset larger than pt') the start of the event always lands at a time that is before the start of the period which sounds a bit odd.

From this theoretical reasoning I think the calculation in DashManfiestParser is correct within the ExoPlayer logic.

However, besides theory: Do you see any problems with such a Dash live stream and events emitted by ExoPlayer that differs to the behavior of another dash player like [1]?

[1] https://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html

marcbaechinger avatar Feb 04 '25 14:02 marcbaechinger

Further, from the equation above and the manifest values presentationTimeOffset="51478000" and presentationTime="11211" (as in 'offset larger than pt') the start of the event always lands at a time that is before the start of the period which sounds a bit odd.

From this theoretical reasoning I think the calculation in DashManfiestParser is correct within the ExoPlayer logic.

@marcbaechinger while I cannot speak to the reference anchor points that Exo uses to perform calculations I wanted to add some additional information regarding the DASH spec itself and why this sort of data may occur.

  1. From DASH-IF Part 10: Events and Timed Metadata:
7.2.4 Repeating events

7.2.4.1 Repeating event instances in one Period

Events in the same Period should not be repeated. Since the player sees all events of a Period, there is no benefit for
repeating events in that Period.

7.2.4.2 Repeating the event cross Period

Events of the previous Period that continue into the next Period (i.e. are still active) should be repeated at the next
Period. The next Period should include a corresponding EventStream and Event elements. The EventStream element of
an event continuation should include an @presentationTimeOffset attribute.

7.2.5 Event timing considerations

The considerations are as follows:
1. An EventStream element may have an @presentationTimeOffset, an Event with a presentation time
matching the value of the @presentationTimeOffset will align to the Period@start. By setting an
event’s presentation time to a value smaller than the @presentationTimeOffset, an event that starts
before Period start time can be signalled.
2. In some common cases, the @presentationTimeOffset of an EventStream Element matches the
@presentationTimeOffset of the Adaptation Sets the events apply to (after timescale conversion). It is
recommended to use such common timeline for events 

Notably: "By setting an event’s presentation time to a value smaller than the @presentationTimeOffset, an event that starts before Period start time can be signalled."

A specific application of this occurs in the SCTE-214 specification:

3. EventStream@presentationTimeOffset should be present. When EventStream@presentationTimeOffset
is present and its value should be set such thatEvent@presentationTime of an event starting before the
start of the current period would still be a non-negative number.

Note 1: the above allows expressing events happening in the past without keeping periods for this
purpose. As a result, the receiver may receive the same SCTE DASH Event element twice, in different
periods, and is expected to handle this.
Note 2: It is possible to do “epoch locking” and start the event timing from the POSIX Epoch time,
January 1, 1970 00:00.00Z.
This implies that EventStream@presentationTimeOffset set to the number of ticks since the Epoch
till the start of the period, and EventStream@presentationTime is set to the number of ticks from the
Epoch till the event start as calculated from the SCTE 35 cue message. Note that the condition
EventStream@presentationTimeOffset > Event@presentationTime
is legal and indicates an event starting prior to the start of the current period.

The key quote being: "Note that the condition EventStream@presentationTimeOffset > Event@presentationTime is legal and indicates an event starting prior to the start of the current period."

marcind avatar Feb 04 '25 22:02 marcind

However, besides theory: Do you see any problems with such a Dash live stream and events emitted by ExoPlayer that differs to the behavior of another dash player like [1]?

[1] https://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html

Speaking of dash.js, this is the logic they implement for handling Event/EventStream attributes to calculate the event time: https://github.com/Dash-Industry-Forum/dash.js/blob/9cddbe588f982b905a4caede615a7e2cac7fec85/src/dash/models/DashManifestModel.js#L1110-L1111, which conforms to the formula mentioned in the issue description.

marcind avatar Feb 04 '25 23:02 marcind

Adding a reference to dash.js: https://github.com/Dash-Industry-Forum/dash.js/blob/9cddbe588f982b905a4caede615a7e2cac7fec85/src/dash/DashAdapter.js#L493

At line no. 493: It adds the periodStart time to calculate the final PT.

            // The PTO in voRepresentation is already specified in seconds
            const presentationTimeOffset = !isNaN(voRepresentation.presentationTimeOffset) ? voRepresentation.presentationTimeOffset : !isNaN(eventStream.presentationTimeOffset) ? eventStream.presentationTimeOffset : 0;
            // In case of version 1 events the presentation_time is parsed as presentation_time_delta
            let presentationTimeDelta = eventBox.presentation_time_delta / timescale;
            let calculatedPresentationTime;

            if (eventBox.version === 0) {
                calculatedPresentationTime = periodStart + mediaStartTime - presentationTimeOffset + presentationTimeDelta;
            } else {
                calculatedPresentationTime = periodStart  + presentationTimeDelta - presentationTimeOffset;
            }
...
...
            event.calculatedPresentationTime = calculatedPresentationTime;

akhilesh-dubey avatar Feb 05 '25 05:02 akhilesh-dubey

Given PTO = 51478000 and PT = 11211, when we add PST = PT14H17M58S = 51478 seconds to it, the calculated presentation time (PS) would be 11.211 seconds, as expected.

akhilesh-dubey avatar Feb 05 '25 05:02 akhilesh-dubey

Thanks everyone.

Can you please provide me with a test fixture that exhibits a problem with events being emitted wrongly or not emitted and describe the malfunctioning so we can look into this.

marcbaechinger avatar Feb 05 '25 09:02 marcbaechinger