When doing a live broadcast, and the transmission just started, the Dash manifest may have an empty SegmentTimeline (while the first chunk is getting filled). ExoPlayer2 crashes on that moment.
This is the manifest I'm testing:
<?xml version="1.0" encoding="utf-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
profiles="urn:mpeg:dash:profile:isoff-live:2011"
type="dynamic"
minimumUpdatePeriod="PT0S"
suggestedPresentationDelay="PT0S"
publishTime="2016-09-27T16:48:01"
timeShiftBufferDepth="PT0.0S"
minBufferTime="PT0.0S">
<ProgramInformation>
</ProgramInformation>
<Period start="PT0.0S">
<AdaptationSet contentType="video" segmentAlignment="true" bitstreamSwitching="true" frameRate="90000/1">
<Representation id="0" mimeType="video/mp4" codecs="avc1.640034" bandwidth="1000000" width="1280" height="720" frameRate="90000/1">
<SegmentTemplate timescale="90000" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet contentType="audio" segmentAlignment="true" bitstreamSwitching="true">
<Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="128000" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
<SegmentTemplate timescale="44100" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
And here is an example of the stack trace I'm getting:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:411)
at com.google.android.exoplayer2.source.dash.manifest.SegmentBase$MultiSegmentBase.getSegmentTimeUs(SegmentBase.java:190)
at com.google.android.exoplayer2.source.dash.manifest.Representation$MultiSegmentRepresentation.getTimeUs(Representation.java:257)
at com.google.android.exoplayer2.source.dash.DashMediaSource$PeriodSeekInfo.createPeriodSeekInfo(DashMediaSource.java:493)
at com.google.android.exoplayer2.source.dash.DashMediaSource.processManifest(DashMediaSource.java:359)
at com.google.android.exoplayer2.source.dash.DashMediaSource.processManifestAndScheduleRefresh(DashMediaSource.java:341)
at com.google.android.exoplayer2.source.dash.DashMediaSource.onManifestLoadCompleted(DashMediaSource.java:251)
at com.google.android.exoplayer2.source.dash.DashMediaSource$ManifestCallback.onLoadCompleted(DashMediaSource.java:589)
at com.google.android.exoplayer2.source.dash.DashMediaSource$ManifestCallback.onLoadCompleted(DashMediaSource.java:583)
+1 for the issue fix. I've faced it using exo player 2.0.1, but I saw it previously on 1.x too.
manifest:
<?xml version="1.0"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:com:dashif:dash264" minBufferTime="PT10S" type="dynamic" minimumUpdatePeriod="PT2S" availabilityStartTime="2015-01-01T00:00:00Z" publishTime="2016-10-12T12:47:43Z" timeShiftBufferDepth="PT10800S">
<Period id="0" start="PT0S">
<AdaptationSet group="0" segmentAlignment="true" mimeType="video/mp4" minBandwidth="200000" maxBandwidth="5000000" startWithSAP="1" minWidth="480" maxWidth="1280" minHeight="270" maxHeight="720">
<SegmentTemplate timescale="90000" initialization="$RepresentationID$-init" media="$RepresentationID$-$Time$">
<SegmentTimeline/>
</SegmentTemplate>
<Representation id="710848012" bandwidth="200000" codecs="avc3.42E015" width="480" height="270"/>
<Representation id="168120601" bandwidth="600000" codecs="avc3.42E01E" width="640" height="360"/>
<Representation id="1124323237" bandwidth="1500000" codecs="avc3.4D401F" width="960" height="540"/>
<Representation id="1516321653" bandwidth="3000000" codecs="avc3.64001F" width="1280" height="720"/>
<Representation id="1709241829" bandwidth="5000000" codecs="avc3.640020" width="1280" height="720"/>
</AdaptationSet>
<AdaptationSet group="1" segmentAlignment="true" mimeType="audio/mp4" minBandwidth="128000" maxBandwidth="128000" startWithSAP="1" lang="nor">
<SegmentTemplate timescale="90000" initialization="$RepresentationID$-init" media="$RepresentationID$-$Time$">
<SegmentTimeline/>
</SegmentTemplate>
<Representation id="909201945" bandwidth="128000" codecs="mp4a.40.2" audioSamplingRate="48000"/>
</AdaptationSet>
</Period>
</MPD>
logs from the test device:
10-12 15:47:02.839 14091-14091/com.example.devnew D/VideoPlayerManagerImpl: preparePlayer() called, uri: http://nonvalid.mpd?abs_begin=2016-10-12T124900Z
10-12 15:47:02.839 14091-14091/com.example.devnew I/ExoPlayerImpl: Init 2.0.1
10-12 15:47:02.844 14091-14091/com.example.devnew D/PlayerErrorListener: start [0]
10-12 15:47:02.844 14091-14091/com.example.devnew D/VideoPlayerManagerImpl: #preparePlayer()#player.setSurface(..)
10-12 15:47:02.969 14091-14091/com.example.devnew D/EventLogger: droppedFrames [230.15, 2]
10-12 15:47:02.969 14091-14091/com.example.devnew D/EventLogger: videoDisabled [230.15]
10-12 15:47:02.974 14091-14091/com.example.devnew D/EventLogger: audioDisabled [230.15]
10-12 15:47:02.974 14091-14091/com.example.devnew D/VideoPlayerManagerImpl: playWhenReady=false, playbackState=buffering
10-12 15:47:02.974 14091-14091/com.example.devnew D/EventLogger: state [0.13, false, B]
10-12 15:47:02.989 14091-14091/com.example.devnew D/com.example.devnew.player.PlayerWrap: onBufferingStatusChanged, isBuffering = true
10-12 15:47:03.169 14091-14242/com.example.devnew D/dalvikvm: GC_FOR_ALLOC freed 3091K, 13% free 65319K/74900K, paused 56ms, total 57ms
10-12 15:47:03.184 14091-14242/com.example.devnew I/dalvikvm-heap: Grow heap (frag case) to 72.709MB for 8294416-byte allocation
10-12 15:47:03.229 14091-14242/com.example.devnew D/dalvikvm: GC_FOR_ALLOC freed 24552K, 42% free 48867K/83004K, paused 45ms, total 45ms
10-12 15:47:03.419 14091-18104/com.example.devnew E/AndroidRuntime: FATAL EXCEPTION: ExoPlayerImplInternal:Handler
Process: com.example.devnew, PID: 14091
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.google.android.exoplayer2.source.dash.manifest.SegmentBase$MultiSegmentBase.getSegmentTimeUs(SegmentBase.java:190)
at com.google.android.exoplayer2.source.dash.manifest.Representation$MultiSegmentRepresentation.getTimeUs(Representation.java:257)
at com.google.android.exoplayer2.source.dash.DashMediaSource$PeriodSeekInfo.createPeriodSeekInfo(DashMediaSource.java:491)
at com.google.android.exoplayer2.source.dash.DashMediaSource.processManifest(DashMediaSource.java:357)
at com.google.android.exoplayer2.source.dash.DashMediaSource.processManifestAndScheduleRefresh(DashMediaSource.java:339)
at com.google.android.exoplayer2.source.dash.DashMediaSource.onManifestLoadCompleted(DashMediaSource.java:249)
at com.google.android.exoplayer2.source.dash.DashMediaSource$ManifestCallback.onLoadCompleted(DashMediaSource.java:587)
at com.google.android.exoplayer2.source.dash.DashMediaSource$ManifestCallback.onLoadCompleted(DashMediaSource.java:581)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.handleMessage(Loader.java:355)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
+1
I see the issue in the latest 2.0.3 version
I'm thinking how to implement some temporary workaround.
Both MultiSegmentBase and SegmentTemplate should check index before call "segmentTimeline.get(index)", if index is wrong - to work as segmentTimeline is null.
I'll try the approach
well, I've added simple check
xmlSegmentTimelineNodes.item(0).hasChildNodes()
waiting for your fix
+1
I think this should be fixed in dev-v2 now, but please give it a try and verify. Thanks!
Working great for me! The player shows a black screen (state buffering) until segments are available and then it starts playing. 馃憤
Great; thanks for verifying!
Most helpful comment
Working great for me! The player shows a black screen (state buffering) until segments are available and then it starts playing. 馃憤