google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.74k stars 6.03k forks source link

Live DASH playback fails if Period@start changes #3457

Closed noamtamim closed 6 years ago

noamtamim commented 7 years ago

Issue description

A DASH live stream fails to play in ExoPlayer due to what seems like timing issues. The log is shown below.

The first frame is shown, but playback does not continue.

For reference, it also doesn't work in ShakaPlayer, but it does work in bitmovin and dash.js web players.

Reproduction steps

Add the URL to media.exolist.json in ExoPlayer's demo app. No DRM setup is required.

Link to test content

Will be sent in email.

Version of ExoPlayer being used

r2.5.4 (with gradle changes to support Android Studio 3.0.0).

Device(s) and version(s) of Android being used

Nexus 5X, Android 8.0.0.

A full bug report captured from the device

I don't think the full ADB bugreport is relevant, but here's the logcat:

11-14 14:08:10.870 2163-2163/com.google.android.exoplayer2.demo I/ExoPlayerImpl: Init bbc4cad [ExoPlayerLib/2.5.4] [bullhead, Nexus 5X, LGE, 26]
11-14 14:08:10.873 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: state [0.00, true, I]
11-14 14:08:10.884 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: state [0.02, true, B]
11-14 14:08:10.973 2163-2191/com.google.android.exoplayer2.demo D/OpenGLRenderer: endAllActiveAnimators on 0x791622cc00 (ExpandableListView) with handle 0x792d8e67a0
11-14 14:08:11.307 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:11.307 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:11.308 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.98, true, true]
11-14 14:08:11.308 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:11.315 2163-2168/com.google.android.exoplayer2.demo I/zygote64: Do full code cache collection, code=251KB, data=192KB
11-14 14:08:11.316 2163-2168/com.google.android.exoplayer2.demo I/zygote64: After code cache collection, code=249KB, data=154KB
11-14 14:08:11.323 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: loading [true]
11-14 14:08:11.335 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: Tracks [
11-14 14:08:11.335 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   Renderer:0 [
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     Group:0, adaptive_supported=YES [
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [X] Track:0, id=v0_273, mimeType=video/avc, bitrate=1600000, res=960x540, fps=25.0, supported=YES
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [X] Track:1, id=v1_273, mimeType=video/avc, bitrate=1100000, res=854x480, fps=25.0, supported=YES
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [X] Track:2, id=v2_273, mimeType=video/avc, bitrate=600000, res=640x360, fps=25.0, supported=YES
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [X] Track:3, id=v3_273, mimeType=video/avc, bitrate=300000, res=480x270, fps=25.0, supported=YES
11-14 14:08:11.336 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     ]
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   ]
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   Renderer:1 [
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     Group:0, adaptive_supported=N/A [
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [X] Track:0, id=v3_546, mimeType=audio/mp4a-latm, bitrate=64000, channels=2, sample_rate=24000, language=rus, supported=YES
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     ]
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     Group:1, adaptive_supported=N/A [
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:       [ ] Track:0, id=v3_819, mimeType=audio/mp4a-latm, bitrate=32000, channels=2, sample_rate=24000, language=rus, supported=YES
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:     ]
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   ]
11-14 14:08:11.337 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:11.339 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: videoEnabled [0.47]
11-14 14:08:11.339 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: audioEnabled [0.47]
11-14 14:08:11.919 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: audioDecoderInitialized [1.05, OMX.google.aac.decoder]
11-14 14:08:11.921 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: audioFormatChanged [1.05, id=v3_546, mimeType=audio/mp4a-latm, bitrate=64000, channels=2, sample_rate=24000, language=und]
11-14 14:08:12.054 2163-2295/com.google.android.exoplayer2.demo D/SurfaceUtils: connecting to surface 0x7912a17010, reason connectToSurface
11-14 14:08:12.054 2163-2295/com.google.android.exoplayer2.demo I/MediaCodec: [OMX.qcom.video.decoder.avc] setting surface generation to 2214914
11-14 14:08:12.055 2163-2295/com.google.android.exoplayer2.demo D/SurfaceUtils: disconnecting from surface 0x7912a17010, reason connectToSurface(reconnect)
11-14 14:08:12.055 2163-2295/com.google.android.exoplayer2.demo D/SurfaceUtils: connecting to surface 0x7912a17010, reason connectToSurface(reconnect)
11-14 14:08:12.091 2163-2296/com.google.android.exoplayer2.demo D/SurfaceUtils: set up nativeWindow 0x7912a17010 for 640x360, color 0x7fa30c04, rotation 0, usage 0x42002900
11-14 14:08:12.102 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: videoDecoderInitialized [1.23, OMX.qcom.video.decoder.avc]
11-14 14:08:12.103 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: videoFormatChanged [1.23, id=v2_273, mimeType=video/avc, bitrate=600000, res=640x360, fps=25.0]
11-14 14:08:12.128 2163-2296/com.google.android.exoplayer2.demo D/SurfaceUtils: set up nativeWindow 0x7912a17010 for 640x368, color 0x7fa30c04, rotation 0, usage 0x42002900
11-14 14:08:12.186 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: videoSizeChanged [640, 360]
11-14 14:08:12.187 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: renderedFirstFrame [Surface(name=null)/@0x6007bcf]
11-14 14:08:12.570 2163-2287/com.google.android.exoplayer2.demo D/AudioTrack: Client defaulted notificationFrames to 6000 for frameCount 12000
11-14 14:08:12.575 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: audioSessionId [1393]
11-14 14:08:13.166 2163-2168/com.google.android.exoplayer2.demo I/zygote64: Do partial code cache collection, code=251KB, data=165KB
11-14 14:08:13.167 2163-2168/com.google.android.exoplayer2.demo I/zygote64: After code cache collection, code=251KB, data=165KB
11-14 14:08:13.167 2163-2168/com.google.android.exoplayer2.demo I/zygote64: Increasing code cache capacity to 1024KB
11-14 14:08:13.205 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: state [2.34, true, R]
11-14 14:08:13.295 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:13.295 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:13.296 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.97, true, true]
11-14 14:08:13.296 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:13.313 2163-2295/com.google.android.exoplayer2.demo D/SurfaceUtils: disconnecting from surface 0x7912a17010, reason disconnectFromSurface
11-14 14:08:13.315 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: state [2.45, true, E]
11-14 14:08:13.327 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: videoDisabled [2.46]
11-14 14:08:13.331 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: audioDisabled [2.46]
11-14 14:08:13.332 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: loading [false]
11-14 14:08:15.309 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:15.310 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:15.311 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.97, true, true]
11-14 14:08:15.311 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:17.157 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:17.157 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:17.158 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.96, true, true]
11-14 14:08:17.159 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:19.301 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:19.301 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:19.302 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.03, true, true]
11-14 14:08:19.302 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:21.264 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: state [10.40, false, E]
11-14 14:08:21.433 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:21.434 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:21.434 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.00, true, true]
11-14 14:08:21.434 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:23.301 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:23.301 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:23.302 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.99, true, true]
11-14 14:08:23.302 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:25.137 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:25.138 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:25.139 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [29.99, true, true]
11-14 14:08:25.139 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:27.279 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:27.279 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:27.280 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.01, true, true]
11-14 14:08:27.280 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:29.443 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:29.443 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:29.445 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.02, true, true]
11-14 14:08:29.445 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:31.292 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:31.292 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:31.293 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.02, true, true]
11-14 14:08:31.293 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:33.429 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:33.429 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:33.430 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.03, true, true]
11-14 14:08:33.430 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:35.281 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:35.282 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:35.283 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.04, true, true]
11-14 14:08:35.283 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:37.121 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:37.121 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:37.122 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.04, true, true]
11-14 14:08:37.122 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:39.274 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:39.274 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:39.275 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.00, true, true]
11-14 14:08:39.275 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
11-14 14:08:41.427 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: sourceInfo [periodCount=1, windowCount=1
11-14 14:08:41.427 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   period [?]
11-14 14:08:41.428 2163-2163/com.google.android.exoplayer2.demo D/EventLogger:   window [28.01, true, true]
11-14 14:08:41.428 2163-2163/com.google.android.exoplayer2.demo D/EventLogger: ]
ojw28 commented 7 years ago

The media does not seem to be spec compliant. In particular, I think that:

  1. The "start" attribute of the period should not be increasing each time the manifest is refreshed. The fact that not all of the media from the period is available any more does not change when the period started.
  2. The "presentationTimeOffset" attributes should not be increasing each time the manifest is refreshed either. This is likely being done to compensate for the initial error of increasing the "start" attribute.

Fixing these issues should allow the content to play successfully across all players.

itaykinnrot commented 7 years ago

thanks @ojw28 we'll check it!

noamtamim commented 7 years ago

Hi @ojw28 We looked at the standard: http://dashif.org/w/2015/04/DASH-IF-IOP-v3.0.pdf

It says: “In order to make the MPD joining friendly and to remove data that is available in the past, any segments that have fallen out of the time shift buffer may no longer be announced in the MPD. In this case, the Period start may be moved by changing one or both, MPD@availabilityStartTime and Period@start. However, this requires that the @startNumber, @presentationTimeOffset and S values need to be updated such that the Segment Information according to section 4.3.2.2.6 is not modified over an MPD update.”

Please check this again.

ojw28 commented 7 years ago

Thanks for the reference. I think we might need to discuss this with the DASH-IF authors. I can't think of a good reason for needing to change Period@start, and if there isn't a good reason then I don't see why it should be allowed as an optional thing. It would just be one more thing for clients to have to deal with for no benefit. It's also quite confusing. Note that it's not required to adjust Period@start to remove data or make the MPD joining friendly.

In the meantime, I would still advise changing the way your manifests update to be as I described above. It would be inline with how manifest updates occur in most of the other live streams I've seen, I think, and I suspect it will make your streams compatible with a wider range of clients.

sandersaares commented 7 years ago

In this case, the Period start may be moved by changing one or both, MPD@availabilityStartTime and Period@start

It appears to me that the first part of the statement directly contradicts DASH 8.4.2 which says:

When the MPD is updated, the value of MPD@availabilityStartTime shall be the same in the original and the updated MPD

While AST does not appear to be relevant in case of the content in question here, it does serve as additional evidence that this part of the guidelines might deserve a review.

ojw28 commented 7 years ago
ojw28 commented 7 years ago

DASH-IF question filed here: https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/160

sandersaares commented 6 years ago

note that Period@id is optional in the DASH spec, and so cannot be relied upon to identify that the period is the same

Based on my reading, this attribute is only optional for static manifests, so it could actually be used to determine period identity in case of dynamic manifests.

Here's the relevant snippet from DASH spec:

If the MPD@type is "dynamic", then this attribute shall be present and shall not change in case the MPD is updated.

ojw28 commented 6 years ago

Ah, thanks, that's good to know!

ojw28 commented 6 years ago

Marking as wontfix for now on the assumption that the DASH-IF guidelines will be amended.

ojw28 commented 6 years ago

DASH IF guidelines v4.2 has been amended to prevent the type of manifest update described here. In 4.4.3.3:

MPD@availabilityStartTime and Period@start shall not be changed over MPD updates.

Closing this. Thanks!