@@ -119,6 +119,7 @@ export default class BaseStreamController
119119 protected retryDate : number = 0 ;
120120 protected levels : Array < Level > | null = null ;
121121 protected fragmentLoader : FragmentLoader ;
122+ protected initFragmentLoader : FragmentLoader ;
122123 protected keyLoader : KeyLoader ;
123124 protected levelLastLoaded : Level | null = null ;
124125 protected startFragRequested : boolean = false ;
@@ -139,6 +140,7 @@ export default class BaseStreamController
139140 this . playlistType = playlistType ;
140141 this . hls = hls ;
141142 this . fragmentLoader = new FragmentLoader ( hls . config ) ;
143+ this . initFragmentLoader = new FragmentLoader ( hls . config ) ;
142144 this . keyLoader = keyLoader ;
143145 this . fragmentTracker = fragmentTracker ;
144146 this . config = hls . config ;
@@ -176,6 +178,7 @@ export default class BaseStreamController
176178 return ;
177179 }
178180 this . fragmentLoader . abort ( ) ;
181+ this . initFragmentLoader . abort ( ) ;
179182 this . keyLoader . abort ( this . playlistType ) ;
180183 const frag = this . fragCurrent ;
181184 if ( frag ?. loader ) {
@@ -511,6 +514,9 @@ export default class BaseStreamController
511514 if ( this . fragmentLoader ) {
512515 this . fragmentLoader . destroy ( ) ;
513516 }
517+ if ( this . initFragmentLoader ) {
518+ this . initFragmentLoader . destroy ( ) ;
519+ }
514520 if ( this . keyLoader ) {
515521 this . keyLoader . destroy ( ) ;
516522 }
@@ -521,7 +527,8 @@ export default class BaseStreamController
521527 //@ts -ignore
522528 this . hls = this . decrypter = this . keyLoader = null ;
523529 //@ts -ignore
524- this . fragmentLoader = this . fragmentTracker = null ;
530+ this . fragmentLoader = this . initFragmentLoader = this . fragmentTracker = null ;
531+
525532 super . onHandlerDestroyed ( ) ;
526533 }
527534
@@ -698,18 +705,24 @@ export default class BaseStreamController
698705 this . hls . trigger ( Events . BUFFER_FLUSHING , flushScope ) ;
699706 }
700707
701- protected _loadInitSegment ( fragment : Fragment , level : Level ) {
702- this . _doFragLoad ( fragment , level )
708+ protected _loadInitSegment ( initFrag : Fragment ) : Promise < void > {
709+ const { hls } = this ;
710+ this . initFragmentLoader . abort ( ) ;
711+ hls . trigger ( Events . FRAG_LOADING , { frag : initFrag , targetBufferTime : 0 } ) ;
712+ return this . initFragmentLoader
713+ . load ( initFrag )
703714 . then ( ( data ) => {
704715 const frag = data ?. frag ;
705- if ( ! frag || this . fragContextChanged ( frag ) || ! this . levels ) {
716+ if (
717+ ! frag ||
718+ ! fragmentsAreEqual ( frag , this . fragCurrent ?. initSegment ) ||
719+ ! this . levels
720+ ) {
706721 throw new Error ( 'init load aborted' ) ;
707722 }
708-
709723 return data ;
710724 } )
711725 . then ( ( data : FragLoadedData ) => {
712- const { hls } = this ;
713726 const { frag, payload } = data ;
714727 const decryptData = frag . decryptdata ;
715728
@@ -744,6 +757,7 @@ export default class BaseStreamController
744757 reason : err . message ,
745758 frag,
746759 } ) ;
760+ this . fragmentLoader . abort ( ) ;
747761 throw err ;
748762 } )
749763 . then ( ( decryptedData ) => {
@@ -761,29 +775,47 @@ export default class BaseStreamController
761775 } ) ;
762776 }
763777 return this . completeInitSegmentLoad ( data ) ;
764- } )
765- . catch ( ( reason ) => {
766- if ( this . state === State . STOPPED || this . state === State . ERROR ) {
767- return ;
768- }
769- this . warn ( reason ) ;
770- this . resetFragmentLoading ( fragment ) ;
771778 } ) ;
772779 }
773780
774781 private completeInitSegmentLoad ( data : FragLoadedData ) {
775- const { levels } = this ;
776- if ( ! levels ) {
777- throw new Error ( 'init load aborted, missing levels' ) ;
778- }
779782 const stats = data . frag . stats ;
780- if ( this . state !== State . STOPPED ) {
781- this . state = State . IDLE ;
782- }
783783 data . frag . data = new Uint8Array ( data . payload ) ;
784784 stats . parsing . start = stats . buffering . start = self . performance . now ( ) ;
785785 stats . parsing . end = stats . buffering . end = self . performance . now ( ) ;
786- this . tick ( ) ;
786+ }
787+
788+ private loadInitSegmentIfNeeded (
789+ mediaFrag : Fragment ,
790+ ) : Promise < void > | undefined {
791+ const { initSegment } = mediaFrag ;
792+ if (
793+ ! this . bitrateTest &&
794+ isMediaFragment ( mediaFrag ) &&
795+ initSegment &&
796+ ! initSegment . data
797+ ) {
798+ const initPromise =
799+ initSegment . encrypted && ! initSegment . decryptdata ?. key
800+ ? this . keyLoader
801+ . load ( initSegment )
802+ . then ( ( ) => this . _loadInitSegment ( initSegment ) )
803+ : this . _loadInitSegment ( initSegment ) ;
804+
805+ return initPromise . catch ( ( reason : LoadError | Error ) => {
806+ if ( this . state === State . STOPPED || this . state === State . ERROR ) {
807+ throw reason ;
808+ }
809+ if ( 'data' in reason ) {
810+ reason . data . frag = mediaFrag ;
811+ this . fragmentLoader . abort ( ) ;
812+ this . handleFragLoadError ( reason ) ;
813+ }
814+ this . warn ( reason ) ;
815+ this . resetFragmentLoading ( mediaFrag ) ;
816+ throw reason ;
817+ } ) ;
818+ }
787819 }
788820
789821 protected unhandledEncryptionError (
@@ -983,12 +1015,15 @@ export default class BaseStreamController
9831015 this . nextLoadPosition = part . start + part . duration ;
9841016 this . state = State . FRAG_LOADING ;
9851017 let result : Promise < PartsLoadedData | FragLoadedData | null > ;
986- if ( keyLoadingPromise ) {
987- result = keyLoadingPromise
988- . then ( ( keyLoadedData ) => {
1018+ const initDataPromise = this . loadInitSegmentIfNeeded ( frag ) ;
1019+ if ( keyLoadingPromise || initDataPromise ) {
1020+ const useKeyLoader = ! ! keyLoadingPromise ;
1021+ result = Promise . all ( [ keyLoadingPromise , initDataPromise ] )
1022+ . then ( ( [ keyLoadedData ] ) => {
9891023 if (
990- ! keyLoadedData ||
991- this . fragContextChanged ( keyLoadedData . frag )
1024+ useKeyLoader &&
1025+ ( ! keyLoadedData ||
1026+ this . fragContextChanged ( keyLoadedData . frag ) )
9921027 ) {
9931028 return null ;
9941029 }
@@ -1057,6 +1092,9 @@ export default class BaseStreamController
10571092 // Load key before streaming fragment data
10581093 const dataOnProgress =
10591094 this . config . progressive && frag . type !== PlaylistLevelType . SUBTITLE ;
1095+
1096+ const initDataPromise = this . loadInitSegmentIfNeeded ( frag ) ;
1097+
10601098 let result : Promise < PartsLoadedData | FragLoadedData | null > ;
10611099 if ( dataOnProgress && keyLoadingPromise ) {
10621100 result = keyLoadingPromise
@@ -1068,6 +1106,7 @@ export default class BaseStreamController
10681106 frag ,
10691107 this . iframesOnly ,
10701108 progressCallback ,
1109+ initDataPromise ,
10711110 ) ;
10721111 } )
10731112 . catch ( ( error ) => this . handleFragLoadError ( error ) ) ;
@@ -1079,8 +1118,10 @@ export default class BaseStreamController
10791118 frag ,
10801119 this . iframesOnly ,
10811120 dataOnProgress ? progressCallback : undefined ,
1121+ dataOnProgress ? initDataPromise : undefined ,
10821122 ) ,
10831123 keyLoadingPromise ,
1124+ initDataPromise ,
10841125 ] )
10851126 . then ( ( [ fragLoadedData ] ) => {
10861127 if ( ! dataOnProgress && progressCallback ) {
@@ -1096,7 +1137,10 @@ export default class BaseStreamController
10961137 new Error ( `frag load aborted, context changed in FRAG_LOADING` ) ,
10971138 ) ;
10981139 }
1099- return result ;
1140+
1141+ return Promise . all ( [ result , initDataPromise ] ) . then (
1142+ ( [ fragData ] ) => fragData ,
1143+ ) ;
11001144 }
11011145
11021146 private doFragPartsLoad (
@@ -1431,7 +1475,7 @@ export default class BaseStreamController
14311475 protected getNextFragment (
14321476 pos : number ,
14331477 levelDetails : LevelDetails ,
1434- ) : Fragment | null {
1478+ ) : MediaFragment | null {
14351479 const fragments = levelDetails . fragments ;
14361480 const fragLen = fragments . length ;
14371481
@@ -1523,7 +1567,7 @@ export default class BaseStreamController
15231567 levelDetails ,
15241568 ) ;
15251569 }
1526- return this . mapToInitFragWhenRequired ( programFrag ) ;
1570+ return programFrag ;
15271571 }
15281572
15291573 protected isLoopLoading ( frag : Fragment , targetBufferTime : number ) : boolean {
@@ -1546,13 +1590,13 @@ export default class BaseStreamController
15461590 }
15471591
15481592 protected getNextFragmentLoopLoading (
1549- frag : Fragment ,
1593+ frag : MediaFragment ,
15501594 levelDetails : LevelDetails ,
15511595 bufferInfo : BufferInfo ,
15521596 playlistType : PlaylistLevelType ,
15531597 maxBufLen : number ,
1554- ) : Fragment | null {
1555- let nextFragment : Fragment | null = null ;
1598+ ) : MediaFragment | null {
1599+ let nextFragment : MediaFragment | null = null ;
15561600 if ( frag . gap ) {
15571601 nextFragment = this . getNextFragment ( this . nextLoadPosition , levelDetails ) ;
15581602 if ( nextFragment && ! nextFragment . gap && bufferInfo . nextStart ) {
@@ -1656,17 +1700,6 @@ export default class BaseStreamController
16561700 return frag ;
16571701 }
16581702
1659- protected mapToInitFragWhenRequired < T extends Fragment | null > (
1660- frag : T ,
1661- ) : T | Fragment {
1662- // If an initSegment is present, it must be buffered first
1663- if ( frag ?. initSegment && ! frag . initSegment . data && ! this . bitrateTest ) {
1664- return frag . initSegment ;
1665- }
1666-
1667- return frag ;
1668- }
1669-
16701703 getNextPart (
16711704 partList : Part [ ] ,
16721705 frag : Fragment ,
0 commit comments