Switching quality/bitrate of video and seeking to different position immediately causing green artifacts
Created by: iamprem
Environment
- [] The MPD passes the DASH-IF Conformance Tool on https://conformance.dashif.org/
-
The stream has correct Access-Control-Allow-Origin headers (CORS) -
There are no network errors such as 404s in the browser console when trying to play the stream -
The issue observed is not mentioned on https://github.com/Dash-Industry-Forum/dash.js/wiki/FAQ - [] The issue occurs in the latest reference client on http://reference.dashif.org/dash.js/ and not just on my page
- Link to playable MPD file: Due to content encryption and custom widevine server, not able to provide an publicly playable DASH file.
- Dash.js version: 2.9.2
- Browser name/version: Chrome 73.0.3683.86
- OS name/version: Mac 10.13.6 Note: This issue happens regardless of the browser (observed both in Firefox and Chrome, because we use Widevine DRM) and OS.
Steps to reproduce
Note: This issue is little hard to reproduce because the nature of the events that triggers this issue.
-
You need the ability to switch quality in the player (Currently I have a UI element that allow me to switch bitrate, you can also do it programmatically using the setQualityFor API but you need to seek to a different position as fast as possible after changing quality)
-
Play the video with whatever initial quality that it choose to start with.
-
Switch the quality and immediately seek to different position in the video.
-
Three things could happen, 4.a. (Happy Case) The quality switch initiated the init request and completed appending to the buffer and then seek request loads further fragments. 4.b.(Happy Case) The quality switch haven't initiated the init request but the seek request is handled first without aborting any inflight requests and then the quality switch is handled. 4.c. (Failure Case) Quality switch is handled first where it issued init segment request, while it is being loaded, the seek request is handled and to support faster seeking it aborts in-flight requests. This results in incompatible init segment to decode the seeked fragments.
-
This bug is intermittent as i described above and i didn't succeeded in reproducing this issue using the 2.9.2 reference player. But i've attached the happy case logs and error case log from my application for your reference and to give better understanding of this issue.
Observed behaviour
The player is failing to decode the video fragments from seeked position and starting to produce weird green artifacts when the quality switch happens.
Console output
After looking at the logs produced, it looks like the onPlaybackSeeking method in ScheduleController is aborting the Init Fragment request made by the quality switch request when the two events happen very quickly in order to support faster seek response.
You can see on line 36857 it is loading video_5 and later on line 36862 the quality change is triggered to load video_4 fragment url. But if you look even further on line 37013 the init fragment request for video_4 is aborted to support faster seek.
Debug.js:98 [36745][AbrController] AbrController (video) switch from 4 to 3/7 (buffer: 7.147) .
Debug.js:98 [36857][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_5.mp4 , Range: 47795811-47954319
Debug.js:98 [36859][BufferController][video] Buffered Range for type: video : 622.622 - 632.631999 currentTime = 623.483259
Debug.js:98 [36862][ScheduleController][video] Quality has changed, get init request for representationid = video_eng=450000
Debug.js:98 [36862][ScheduleController][video] isFragmentProcessingInProgress is already equal to true
Debug.js:98 [36913][AbrController] AbrController (audio) stay on 0/0 (buffer: 6.533)
Debug.js:98 [36913][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 630 was changed to 630.015999
Debug.js:98 [36914][DashHandler] Getting the request for audio time : 630.015999
Debug.js:98 [36914][DashHandler] Index for audio time 630.015999 is 314
Debug.js:98 [36914][DashHandler] SegmentList: 628 / 1195.861334
Debug.js:98 [36915][DashHandler] Getting the next request at index: 315, type: audio
Debug.js:98 [36915][DashHandler] SegmentList: 630 / 1195.861334
Debug.js:98 [36916][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [37011][PlaybackController] Seeking to: 998.254617
Debug.js:98 [37012][BufferController][video] getAllRangesWithSafetyFactor for video - No request found in current time position, removing full buffer 0 - 633.131999
Debug.js:98 [37012][BufferController][video] Removing video buffer from: 0 to 633.131999
Debug.js:98 [37013][ScheduleController][video] onPlaybackSeeking for video, call fragmentModel.abortRequests in order to seek quicker
Debug.js:98 [37014][ScheduleController][video] onFragmentLoadingAbandoned for video, request: https://example.com/dash_video_4.mp4 has been aborted
Debug.js:98 [37015][ScheduleController][video] onFragmentLoadingAbandoned for video, request: https://example.com/dash_video_4.mp4 has been aborted
Debug.js:98 [37015][ScheduleController][video] isFragmentProcessingInProgress is already equal to false
Debug.js:98 [37016][BufferController][audio] getAllRangesWithSafetyFactor for audio - No request found in current time position, removing full buffer 0 - 630.515999
Debug.js:98 [37017][BufferController][audio] Removing audio buffer from: 0 to 630.515999
Debug.js:98 [37017][ScheduleController][audio] onPlaybackSeeking for audio, call fragmentModel.abortRequests in order to seek quicker
Debug.js:98 [37018][ScheduleController][audio] onFragmentLoadingAbandoned for audio, request: https://example.com/dash_audio_3.mp4 has been aborted
Debug.js:98 [37019][ScheduleController][audio] onFragmentLoadingAbandoned for audio, request: https://example.com/dash_audio_3.mp4 has been aborted
Debug.js:98 [37019][ScheduleController][audio] isFragmentProcessingInProgress is already equal to false
Debug.js:98 [37022][BufferController][video] onRemoved buffer from: 0 to 633.131999
Debug.js:98 [37024][BufferController][video] onRemoved : call updateBufferLevel
Debug.js:98 [37025][BufferController][audio] onRemoved buffer from: 0 to 630.515999
Debug.js:98 [37026][BufferController][audio] onRemoved : call updateBufferLevel
Debug.js:98 [37032][AbrController] AbrController (audio) stay on 0/0 (buffer: 6.533)
Debug.js:98 [37033][DashHandler] Getting the request for audio time : 998.254617
Debug.js:98 [37034][DashHandler] Index for audio time 998.254617 is 499
Debug.js:98 [37035][DashHandler] SegmentList: 998 / 1195.861334
Debug.js:98 [37036][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [37331][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 15897380-15928973
Debug.js:98 [37333][BufferController][audio] Buffered Range for type: audio : 998.016 - 999.999999 currentTime = 998.254617
Debug.js:98 [37335][AbrController] AbrController (audio) stay on 0/0 (buffer: 1.745)
Debug.js:98 [37335][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1000 was changed to 999.999999
Debug.js:98 [37335][DashHandler] Getting the request for audio time : 999.999999
Debug.js:98 [37336][DashHandler] Index for audio time 999.999999 is 499
Debug.js:98 [37336][DashHandler] SegmentList: 998 / 1195.861334
Debug.js:98 [37337][DashHandler] Getting the next request at index: 500, type: audio
Debug.js:98 [37337][DashHandler] SegmentList: 1000 / 1195.861334
Debug.js:98 [37338][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [37523][DashHandler] Getting the request for video time : 998.254617
Debug.js:98 [37524][DashHandler] Index for video time 998.254617 is 498
Debug.js:98 [37524][DashHandler] SegmentList: 996.996 / 1195.861334
Debug.js:98 [37525][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [37628][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 15928974-15960868
Debug.js:98 [37630][BufferController][audio] Buffered Range for type: audio : 998.016 - 1002.005333 currentTime = 998.254617
Debug.js:98 [38179][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 56774647-56881567
Debug.js:98 [38181][BufferController][video] Buffered Range for type: video : 996.996 - 998.997999 currentTime = 998.254617
Debug.js:98 [38184][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 998.9979999999999 was changed to 998.997999
Debug.js:98 [38184][DashHandler] Getting the request for video time : 998.997999
Debug.js:98 [38184][DashHandler] Index for video time 998.997999 is 498
Debug.js:98 [38185][DashHandler] SegmentList: 996.996 / 1195.861334
Debug.js:98 [38185][DashHandler] Getting the next request at index: 499, type: video
Debug.js:98 [38186][DashHandler] SegmentList: 998.998 / 1195.861334
Debug.js:98 [38186][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [38231][PlaybackController] Native video element event: seeked
Debug.js:98 [38604][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 56881568-56987813
Debug.js:98 [38607][BufferController][video] Buffered Range for type: video : 996.996 - 1000.999999 currentTime = 998.254617
Debug.js:98 [38609][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 1001 was changed to 1000.999999
Debug.js:98 [38609][DashHandler] Getting the request for video time : 1000.999999
Debug.js:98 [38610][DashHandler] Index for video time 1000.999999 is 499
Debug.js:98 [38610][DashHandler] SegmentList: 998.998 / 1195.861334
Debug.js:98 [38611][DashHandler] Getting the next request at index: 500, type: video
Debug.js:98 [38611][DashHandler] SegmentList: 1001 / 1195.861334
Debug.js:98 [38612][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [39032][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 56987814-57101481
Debug.js:98 [39033][BufferController][video] Buffered Range for type: video : 996.996 - 1003.001999 currentTime = 998.254617
Debug.js:98 [39035][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 1003.002 was changed to 1003.001999
Debug.js:98 [39036][DashHandler] Getting the request for video time : 1003.001999
Debug.js:98 [39036][DashHandler] Index for video time 1003.001999 is 500
Debug.js:98 [39036][DashHandler] SegmentList: 1001 / 1195.861334
Debug.js:98 [39037][DashHandler] Getting the next request at index: 501, type: video
Debug.js:98 [39038][DashHandler] SegmentList: 1003.002 / 1195.861334
Debug.js:98 [39039][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [39134][AbrController] AbrController (audio) stay on 0/0 (buffer: 3.751)
Debug.js:98 [39135][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1002 was changed to 1002.005333
Debug.js:98 [39136][DashHandler] Getting the request for audio time : 1002.005333
Debug.js:98 [39137][DashHandler] Index for audio time 1002.005333 is 500
Debug.js:98 [39137][DashHandler] SegmentList: 1000 / 1195.861334
Debug.js:98 [39138][DashHandler] Getting the next request at index: 501, type: audio
Debug.js:98 [39139][DashHandler] SegmentList: 1002 / 1195.861334
Debug.js:98 [39140][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [39455][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 57101482-57217549
Debug.js:98 [39457][BufferController][video] Buffered Range for type: video : 996.996 - 1005.003999 currentTime = 998.254617
Debug.js:98 [39459][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 1005.0039999999999 was changed to 1005.003999
Debug.js:98 [39460][DashHandler] Getting the request for video time : 1005.003999
Debug.js:98 [39460][DashHandler] Index for video time 1005.003999 is 501
Debug.js:98 [39461][DashHandler] SegmentList: 1003.002 / 1195.861334
Debug.js:98 [39462][DashHandler] Getting the next request at index: 502, type: video
Debug.js:98 [39464][DashHandler] SegmentList: 1005.004 / 1195.861334
Debug.js:98 [39466][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [39584][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 15960869-15992817
Debug.js:98 [39585][BufferController][audio] Buffered Range for type: audio : 998.016 - 1004.010666 currentTime = 998.254617
Debug.js:98 [39588][AbrController] AbrController (audio) stay on 0/0 (buffer: 5.756)
Debug.js:98 [39589][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1004 was changed to 1004.010666
Debug.js:98 [39589][DashHandler] Getting the request for audio time : 1004.010666
Debug.js:98 [39590][DashHandler] Index for audio time 1004.010666 is 501
Debug.js:98 [39590][DashHandler] SegmentList: 1002 / 1195.861334
Debug.js:98 [39591][DashHandler] Getting the next request at index: 502, type: audio
Debug.js:98 [39591][DashHandler] SegmentList: 1004 / 1195.861334
Debug.js:98 [39591][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [39760][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 57217550-57335087
Debug.js:98 [39761][BufferController][video] Buffered Range for type: video : 996.996 - 1007.005999 currentTime = 998.254617
Debug.js:98 [39763][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 1007.006 was changed to 1007.005999
Debug.js:98 [39764][DashHandler] Getting the request for video time : 1007.005999
Debug.js:98 [39764][DashHandler] Index for video time 1007.005999 is 502
Debug.js:98 [39764][DashHandler] SegmentList: 1005.004 / 1195.861334
Debug.js:98 [39765][DashHandler] Getting the next request at index: 503, type: video
Debug.js:98 [39765][DashHandler] SegmentList: 1007.006 / 1195.861334
Debug.js:98 [39766][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [39886][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 15992818-16024697
Debug.js:98 [39887][BufferController][audio] Buffered Range for type: audio : 998.016 - 1006.015999 currentTime = 998.254617
Debug.js:98 [39890][AbrController] AbrController (audio) stay on 0/0 (buffer: 7.761)
Debug.js:98 [39890][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1006 was changed to 1006.015999
Debug.js:98 [39890][DashHandler] Getting the request for audio time : 1006.015999
Debug.js:98 [39891][DashHandler] Index for audio time 1006.015999 is 502
Debug.js:98 [39891][DashHandler] SegmentList: 1004 / 1195.861334
Debug.js:98 [39892][DashHandler] Getting the next request at index: 503, type: audio
Debug.js:98 [39892][DashHandler] SegmentList: 1006 / 1195.861334
Debug.js:98 [39892][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [40060][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 57335088-57448002
Debug.js:98 [40062][BufferController][video] Buffered Range for type: video : 996.996 - 1009.007999 currentTime = 998.254617
Debug.js:98 [40064][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for video . 1009.0079999999999 was changed to 1009.007999
Debug.js:98 [40064][DashHandler] Getting the request for video time : 1009.007999
Debug.js:98 [40064][DashHandler] Index for video time 1009.007999 is 503
Debug.js:98 [40065][DashHandler] SegmentList: 1007.006 / 1195.861334
Debug.js:98 [40065][DashHandler] Getting the next request at index: 504, type: video
Debug.js:98 [40065][DashHandler] SegmentList: 1009.008 / 1195.861334
Debug.js:98 [40066][ScheduleController][video] Next fragment request url is https://example.com/dash_video_4.mp4
Debug.js:98 [40185][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 16024698-16056328
Debug.js:98 [40186][BufferController][audio] Buffered Range for type: audio : 998.016 - 1007.999999 currentTime = 998.254617
Debug.js:98 [40188][AbrController] AbrController (audio) stay on 0/0 (buffer: 9.745)
Debug.js:98 [40188][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1008 was changed to 1007.999999
Debug.js:98 [40189][DashHandler] Getting the request for audio time : 1007.999999
Debug.js:98 [40189][DashHandler] Index for audio time 1007.999999 is 503
Debug.js:98 [40189][DashHandler] SegmentList: 1006 / 1195.861334
Debug.js:98 [40190][DashHandler] Getting the next request at index: 504, type: audio
Debug.js:98 [40190][DashHandler] SegmentList: 1008 / 1195.861334
Debug.js:98 [40191][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [40355][ScheduleController][video] OnFragmentLoadingCompleted - Url: https://example.com/dash_video_4.mp4 , Range: 57448003-57561904
Debug.js:98 [40357][BufferController][video] Buffered Range for type: video : 996.996 - 1011.009999 currentTime = 998.254617
Debug.js:98 [40357][AbrController] AbrController (video) switching from throughput to buffer occupancy ABR rule (buffer: 12.755).
Debug.js:98 [40358][BufferController][video] Got enough buffer to start for video
Debug.js:98 [40484][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 16056329-16088258
Debug.js:98 [40486][BufferController][audio] Buffered Range for type: audio : 998.016 - 1010.005333 currentTime = 998.254617
Debug.js:98 [40488][AbrController] AbrController (audio) stay on 0/0 (buffer: 11.751)
Debug.js:98 [40489][NextFragmentRequestRule] Prior to making a request for time, NextFragmentRequestRule is aligning index handler's currentTime with bufferedRange.end for audio . 1010 was changed to 1010.005333
Debug.js:98 [40489][DashHandler] Getting the request for audio time : 1010.005333
Debug.js:98 [40489][DashHandler] Index for audio time 1010.005333 is 504
Debug.js:98 [40490][DashHandler] SegmentList: 1008 / 1195.861334
Debug.js:98 [40490][DashHandler] Getting the next request at index: 505, type: audio
Debug.js:98 [40491][DashHandler] SegmentList: 1010 / 1195.861334
Debug.js:98 [40491][ScheduleController][audio] Next fragment request url is https://example.com/dash_audio_3.mp4
Debug.js:98 [40790][ScheduleController][audio] OnFragmentLoadingCompleted - Url: https://example.com/dash_audio_3.mp4 , Range: 16088259-16120146
Debug.js:98 [40791][BufferController][audio] Buffered Range for type: audio : 998.016 - 1012.010666 currentTime = 998.254617
Debug.js:98 [40792][AbrController] AbrController (audio) switching from throughput to buffer occupancy ABR rule (buffer: 13.756).
Debug.js:98 [40792][BufferController][audio] Got enough buffer to start for audio