{"version":3,"sources":["webpack:///./node_modules/@videojs/http-streaming/node_modules/mux.js/lib/utils/numbers.js","webpack:///./node_modules/@videojs/http-streaming/node_modules/mux.js/lib/utils/clock.js","webpack:///./node_modules/@videojs/http-streaming/dist/videojs-http-streaming.es.js","webpack:///./node_modules/@videojs/http-streaming/node_modules/mux.js/lib/tools/parse-sidx.js","webpack:///./node_modules/@videojs/vhs-utils/es/media-groups.js","webpack:///./node_modules/@videojs/http-streaming/node_modules/mpd-parser/dist/mpd-parser.es.js"],"names":["MAX_UINT32","Math","pow","getUint64","uint8","value","dv","DataView","buffer","byteOffset","byteLength","getBigUint64","Number","MAX_SAFE_INTEGER","getUint32","module","exports","secondsToVideoTs","secondsToAudioTs","videoTsToSeconds","audioTsToSeconds","audioTsToVideoTs","videoTsToAudioTs","metadataTsToSeconds","ONE_SECOND_IN_TS","seconds","sampleRate","timestamp","timelineStartPts","keepOriginalTimestamps","resolveUrl","resolveManifestRedirect","handleManifestRedirect","url","req","responseURL","logger","source","log","debug","bind","TIME_FUDGE_FACTOR","SAFE_TIME_DELTA","filterRanges","timeRanges","predicate","i","results","length","start","end","push","createTimeRanges","findRange","buffered","time","findNextRange","findGaps","ranges","bufferIntersection","bufferA","bufferB","arity","extents","createTimeRange","count","type","sort","a","b","printableRange","range","strArr","join","timeUntilRebuffer","currentTime","playbackRate","bufferedEnd","timeRangesToArray","timeRangesList","isRangeDifferent","lastBufferedEnd","timeAheadOf","startTime","segmentDurationWithParts","playlist","segment","preload","duration","result","parts","forEach","p","preloadHints","partTargetDuration","getPartsAndSegments","segments","reduce","acc","si","part","pi","segmentIndex","partIndex","getLastParts","media","lastSegment","getKnownPartCount","_ref","preloadSegment","partCount","hint","liveEdgeDelay","master","endList","suggestedPresentationDelay","hasParts","serverControl","partHoldBack","holdBack","targetDuration","backwardDuration","endSequence","mediaSequence","precise","forwardDuration","intervalDuration","expired","backward","forward","totalDuration","Infinity","sumDurations","_ref2","defaultDuration","durationList","startIndex","endIndex","durations","_ref3","min","_i","playlistEnd","useSafeLiveEnd","liveEdgePadding","lastSegmentEndTime","max","seekable","seekableStart","seekableEnd","getMediaInfoForTime","_ref4","startingSegmentIndex","startingPartIndex","experimentalExactManifestTimings","partsAndSegments","partAndSegment","_i2","_partAndSegment","_i3","_i4","_partAndSegment2","isBlacklisted","excludeUntil","Date","now","isIncompatible","isEnabled","blacklisted","disabled","isDisabled","isAes","key","hasAttribute","attr","attributes","estimateSegmentRequestTime","segmentDuration","bandwidth","bytesReceived","NaN","size","BANDWIDTH","isLowestEnabledRendition","playlists","currentBandwidth","MAX_VALUE","filter","playlistMatch","id","resolvedUri","uri","someAudioVariant","callback","AUDIO","mediaGroups","found","groupName","label","isAudioOnly","variant","_loop","CODECS","split","every","c","v","_ret","Playlist","createPlaylistID","index","parseManifest","onwarn","oninfo","manifestString","_ref$customTagParsers","customTagParsers","_ref$customTagMappers","customTagMappers","experimentalLLHLS","parser","on","customParser","addParser","mapper","addTagMapper","manifest","k","hasOwnProperty","s","error","forEachMediaGroup","mediaType","groupKey","labelKey","mediaProperties","setupMediaPlaylist","playlistErrors_","setupMediaPlaylists","warn","resolveMediaGroupUris","properties","masterForMedia","location","href","addPropertiesToMaster","phonyUri","audioOnlyMaster","groupId","mergeOptions$2","mergeOptions","EventTarget$1","EventTarget","addLLHLSQueryDirectives","parameters","canBlockReload","nextMSN","nextPart","_HLS_part","_HLS_msn","canSkipUntil","_HLS_skip","canSkipDateranges","Object","keys","parsedUri","URL","name","searchParams","set","toString","updateSegment","skipped","updateSegments","original","update","offset","oldSegments","slice","newSegments","currentMap","newIndex","oldSegment","newSegment","map","resolveSegmentUris","baseUri","getAllSegments","isPlaylistUnchanged","updateMaster$1","newMedia","unchangedCheck","oldMedia","mergedPlaylist","skip","skippedSegments","unshift","refreshDelay","lastPart","lastDuration","PlaylistLoader","_EventTarget","src","vhs","options","_this","call","this","Error","logger_","_options","_options$withCredenti","withCredentials","_options$handleManife","handleManifestRedirects","vhs_","vhsOptions","options_","browser","IE_VERSION","state","handleMediaupdatetimeout_","_proto","prototype","_this2","request","xhr","playlistRequestError","haveMetadata","playlistString","responseText","startingState","status","message","code","trigger","parseManifest_","_this3","playlistObject","lastRequest","pendingMedia_","media_","updateMediaUpdateTimeout_","dispose","stopRequest","clearTimeout","mediaUpdateTimeout","finalRenditionTimeout","off","oldRequest","onreadystatechange","abort","shouldDelay","_this4","delay","setTimeout","mediaChange","masterPlaylistRef","pause","started","load","_this5","_this6","_this7","setupInitialPlaylist","srcUri","videojsXHR","mergeOptions$1","callbackWrapper","response","reqResponse","responseType","responseTime","roundTripTime","requestTime","floor","headers","responseHeaders","timedout","aborted","statusCode","xhrFactory","XhrFunction","timeout","beforeRequest","Vhs","newOptions","xhrMethod","originalAbort","apply","arguments","byterangeStr","byterange","byterangeEnd","byterangeStart","BigInt","segmentXhrHeaders","Range","textRange","formatHexString","e","substring","formatAsciiString","String","fromCharCode","createTransferableMessage","transferable","ArrayBuffer","isView","bytes","initSegmentId","initSegment","segmentKeyId","hexDump","data","hex","ascii","Array","step","j","tagDump","textRanges","utils","freeze","__proto__","SEGMENT_END_FUDGE_PERCENT","playerTimeToProgramTime","playerTime","dateTimeObject","transmuxerPrependedSeconds","videoTimingInfo","transmuxedStart","transmuxedPresentationStart","startOfSegment","offsetFromSegmentStart","getTime","originalSegmentVideoDuration","transmuxedPresentationEnd","findSegmentForProgramTime","programTime","nextSegmentStart","lastSegmentStart","lastSegmentDuration","lastSegmentEnd","estimatedStart","indexOf","findSegmentForPlayerTime","segmentEnd","getOffsetFromTimestamp","comparisonTimeStamp","segmentDateTime","programDateTime","segmentTimeEpoch","programTimeEpoch","verifyProgramDateTimeTags","getProgramTime","_ref$time","undefined","matchedSegment","seekTime","programTimeObject","mediaSeconds","toISOString","seekToProgramTime","_ref2$retryCount","retryCount","seekTo","_ref2$pauseAfterSeek","pauseAfterSeek","tech","hasStarted_","mediaOffset","one","seekToTime","seekedCallback","callbackOnCompleted","cb","readyState","containerRequest","id3Offset","finished","endRequestAndCallback","err","_bytes","progressListener","newPart","beforeSend","overrideMimeType","addEventListener","total","loaded","dashPlaylistUnchanged","sidx","aSegment","bSegment","aByterange","bByterange","parseMasterXml","masterXml","srcUrl","clientOffset","sidxMapping","previousManifest","manifestUri","updateMaster","oldMaster","newMaster","noChanges","minimumUpdatePeriod","timelineStarts","sidxKey","playlistUpdate","group","_playlistUpdate","equivalentSidx","neitherMap","Boolean","equivalentMap","compareSidxEntry","oldSidxMapping","newSidxMapping","currentSidxInfo","savedSidxInfo","sidxInfo","filterChangedSidxMappings","videoSidx","mediaGroupSidx","DashPlaylistLoader","srcUrlOrPlaylist","masterPlaylistLoader","masterPlaylistLoader_","isMaster_","refreshXml_","refreshMedia_","loadedPlaylists_","sidxMapping_","childPlaylist_","requestErrored_","addSidxSegments_","fin","subarray","container","internal","blacklistDuration","_playlist$sidx$bytera","mediaRequest_","minimumUpdatePeriodTimeout_","createMupOnMedia_","hasPendingRequest","sidxChanged","isFinalRendition","updateMinimumUpdatePeriodTimeout_","requestMaster_","masterChanged","haveMaster_","masterXml_","date","masterLoaded_","parse","handleMaster_","syncClientServerClock_","done","utcTiming","clientOffset_","method","serverTime","locations","mpl","mup","createMUPTimeout_","_this8","mediaID","_this9","mediaChanged","createMediaUpdateTimeout","Config","GOAL_BUFFER_LENGTH","MAX_GOAL_BUFFER_LENGTH","BACK_BUFFER_LENGTH","GOAL_BUFFER_LENGTH_RATE","INITIAL_BANDWIDTH","BANDWIDTH_VARIANCE","BUFFER_LOW_WATER_LINE","MAX_BUFFER_LOW_WATER_LINE","EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE","BUFFER_LOW_WATER_LINE_RATE","BUFFER_HIGH_WATER_LINE","stringToArrayBuffer","string","view","Uint8Array","charCodeAt","browserWorkerPolyFill","workerObj","removeEventListener","createObjectURL","str","Blob","blob","BlobBuilder","append","getBlob","factory","objectUrl","worker","Worker","objURL","terminate","revokeObjectURL","transform","getWorkerString","fn","replace","workerCode$1","Stream","init","listeners","listener","concat","splice","callbacks","args","pipe","destination","flushSource","flush","partialFlush","endTimeline","reset","box","dinf","esds","ftyp","mdat","mfhd","minf","moof","moov","mvex","mvhd","trak","tkhd","mdia","mdhd","hdlr","sdtp","stbl","stsd","traf","trex","trun$1","types","MAJOR_BRAND","MINOR_VERSION","AVC1_BRAND","VIDEO_HDLR","AUDIO_HDLR","HDLR_TYPES","VMHD","SMHD","DREF","STCO","STSC","STSZ","STTS","stream","MAX_UINT32$1","getUint64$2","numbers","avc1","avcC","btrt","dref","mp4a","pasp","smhd","stco","stsc","stsz","stts","styp","tfdt","tfhd","trun","vmhd","video","audio","payload","setUint32","track","audioobjecttype","samplingfrequencyindex","channelcount","samplerate","sequenceNumber","tracks","trackFragments","boxes","flags","samples","dependsOn","isDependedOn","hasRedundancy","videoSample","audioSample","avc1Box","sps","pps","sequenceParameterSets","pictureParameterSets","width","height","profileIdc","profileCompatibility","levelIdc","sarRatio","hSpacing","vSpacing","samplesize","trackFragmentHeader","trackFragmentDecodeTime","trackFragmentRun","sampleDependencyTable","dataOffset","upperWordBaseMediaDecodeTime","lowerWordBaseMediaDecodeTime","baseMediaDecodeTime","audioTrun","videoTrun","trunHeader","durationPresent","sizePresent","flagsPresent","compositionTimeOffset","bytesOffest","header","sample","isLeading","paddingValue","isNonSyncSample","degradationPriority","silence","mp4Generator","fileType","movie","groupNalsIntoFrames","nalUnits","currentNal","currentFrame","frames","nalCount","nalUnitType","dts","pts","keyFrame","groupFramesIntoGops","currentGop","gops","extendFirstKeyFrame","shift","createDefaultSample","sampleForFrame","frame","generateSampleTable$1","baseDataOffset","h","concatenateNalData","nalsByteLength","numberOfNals","totalByteLength","generateSampleTableForFrame","concatenateNalDataForFrame","frameUtils","generateSampleTable","highPrefix","lowPrefix","zeroFill","makeTable","metaTable","obj","arr","silence_1","coneOfSilence","96000","88200","64000","48000","44100","32000","24000","16000","12000","11025","8000","ONE_SECOND_IN_TS$4","clock","sumFrameByteLengths","array","currentObj","sum","prefixWithSilence","audioAppendStartTs","videoBaseMediaDecodeTime","baseMediaDecodeTimeTs","silentFrame","firstFrame","frameDuration","audioGapDuration","audioFillFrameCount","audioFillDuration","ceil","trimAdtsFramesByEarliestDts","adtsFrames","earliestAllowedDts","minSegmentDts","minSegmentPts","concatenateFrameData","audioFrameUtils","ONE_SECOND_IN_TS$3","collectDtsInfo","timelineStartInfo","maxSegmentPts","maxSegmentDts","clearDtsInfo","calculateTrackBaseMediaDecodeTime","scale","trackDecodeInfo","USER_DATA_REGISTERED_ITU_T_T35","RBSP_TRAILING_BITS","parseSei","payloadType","payloadSize","userIdentifier","parseUserData","sei","parseCaptionPackets","userData","ccData","discardEmulationPreventionBytes$1","newLength","newData","emulationPreventionBytesPositions","sourceIndex","captionPacketParser","discardEmulationPreventionBytes","CaptionStream$1","CaptionStream","parse708captions_","parse708captions","captionPackets_","ccStreams_","Cea608Stream","cc708Stream_","Cea708Stream","captionServices","cc","event","newCaptionPackets","escapedRBSP","latestDts_","ignoreNextEqualDts_","numSameDts_","flushCCStreams","flushType","flushStream","elem","idx","presortIndex","packet","dispatchCea608Packet","dispatchCea708Packet","activeCea608Channel_","ccStream","setsTextOrXDSActive","setsChannel1Active","setsChannel2Active","CHARACTER_TRANSLATION_708","get708CharFromCode","newCode","within708TextBlock","Cea708Window","windowNum","clearText","pendingNewLine","winAttr","penAttr","penLoc","penColor","visible","rowLock","columnLock","priority","relativePositioning","anchorVertical","anchorHorizontal","anchorPoint","rowCount","virtualRowCount","columnCount","windowStyle","penStyle","getText","rows","rowIdx","newLine","beforeRowOverflow","isEmpty","addText","text","backspace","row","substr","Cea708Service","serviceNum","encoding","currentWindow","windows","createTextDecoder","startPts","win","setCurrentWindow","TextDecoder","level","textDecoder_","serviceProps","self","captionServiceEncodings","serviceName","test","serviceEncodings","current708Packet","services","new708Packet","add708Bytes","push708Packet","ptsVals","byte0","byte1","packet708","packetData","blockSize","seq","sizeCode","pushServiceBlock","service","initService","handleText","multiByteCharacter","extendedCommands","defineWindow","clearWindows","deleteWindows","displayWindows","hideWindows","toggleWindows","setWindowAttributes","setPenAttributes","setPenColor","setPenLocation","isExtended","getPts","byteIndex","flushDisplayed","char","charCodeArray","isMultiByte","extended","currentByte","nextByte","decode","firstByte","secondByte","fillOpacity","fillRed","fillGreen","fillBlue","borderType","borderRed","borderGreen","borderBlue","wordWrap","printDirection","scrollDirection","justify","effectSpeed","effectDirection","displayEffect","displayedText","winId","endPts","pushCaption","textTag","penSize","italics","underline","edgeType","fontStyle","fgOpacity","fgRed","fgGreen","fgBlue","bgOpacity","bgRed","bgGreen","bgBlue","edgeRed","edgeGreen","edgeBlue","column","CHARACTER_TRANSLATION","getCharFromCode","BOTTOM_ROW","ROWS","createDisplayBuffer","field","dataChannel","field_","dataChannel_","name_","setConstants","swap","char0","char1","lastControlCode_","PADDING_","RESUME_CAPTION_LOADING_","mode_","END_OF_CAPTION_","clearFormatting","displayed_","nonDisplayed_","startPts_","ROLL_UP_2_ROWS_","rollUpRows_","setRollUp","ROLL_UP_3_ROWS_","ROLL_UP_4_ROWS_","CARRIAGE_RETURN_","shiftRowsUp_","BACKSPACE_","row_","ERASE_DISPLAYED_MEMORY_","ERASE_NON_DISPLAYED_MEMORY_","RESUME_DIRECT_CAPTIONING_","isSpecialCharacter","column_","isExtCharacter","isMidRowCode","addFormatting","isOffsetControlCode","isPAC","formatting_","isColorPAC","isNormalChar","content","trim","topRow_","BASE_","EXT_","CONTROL_","OFFSET_","newBaseRow","format","reverse","popOn","baseRow","rollUp","paintOn","captionStream","streamTypes","H264_STREAM_TYPE","ADTS_STREAM_TYPE","METADATA_STREAM_TYPE","MAX_TS","RO_THRESH","TYPE_SHARED","handleRollover$1","reference","direction","abs","TimestampRolloverStream$1","TimestampRolloverStream","lastDTS","referenceDTS","type_","discontinuity","_MetadataStream","timestampRolloverStream","handleRollover","percentEncode$1","parseUtf8","decodeURIComponent","parseIso88591$1","unescape","parseSyncSafeInteger$1","tagParsers","TXXX","tag","description","WXXX","PRIV","owner","privateData","settings","descriptor","tagSize","bufferSize","dispatchType","chunk","frameStart","frameSize","frameHeader","dataAlignmentIndicator","d","timeStamp","_TransportPacketStream","_TransportParseStream","_ElementaryStream","metadataStream","MP2T_PACKET_LENGTH$1","SYNC_BYTE$1","bytesInBuffer","everything","parsePsi","parsePat","parsePmt","packetsWaitingForPmt","programMapTable","psi","payloadUnitStartIndicator","pat","section_number","last_section_number","pmtPid","pmt","sectionLength","tableEnd","programInfoLength","streamType","pid","processPes_","STREAM_TYPES","h264","adts","segmentHadPmt","timedMetadata","parsePes","pes","ptsDtsFlags","startPrefix","packetLength","forceFlush","fragment","packetFlushable","trackId","codec","flushStreams_","m2ts","PAT_PID","MP2T_PACKET_LENGTH","TransportPacketStream","TransportParseStream","ElementaryStream","MetadataStream","_AdtsStream","m2ts_1","ONE_SECOND_IN_TS$2","ADTS_SAMPLING_FREQUENCIES$1","handlePartialSegments","frameNum","skipWarn_","frameLength","protectionSkipBytes","oldBuffer","sampleCount","adtsFrameDuration","ExpGolomb","workingData","workingBytesAvailable","workingWord","workingBitsAvailable","bitsAvailable","loadWord","position","workingBytes","availableBytes","skipBits","skipBytes","readBits","bits","valu","skipLeadingZeros","leadingZeroCount","skipUnsignedExpGolomb","skipExpGolomb","readUnsignedExpGolomb","clz","readExpGolomb","readBoolean","readUnsignedByte","_H264Stream","_NalByteStream","PROFILES_WITH_OPTIONAL_SPS_DATA","expGolomb","syncPoint","swapBuffer","len","100","110","122","244","44","83","86","118","128","138","139","134","currentPts","currentDts","readSequenceParameterSet","skipScalingList","nalByteStream","nalUnitTypeCode","config","expGolombDecoder","deltaScale","lastScale","nextScale","chromaFormatIdc","picOrderCntType","numRefFramesInPicOrderCntCycle","picWidthInMbsMinus1","picHeightInMapUnitsMinus1","frameMbsOnlyFlag","scalingListCount","aspectRatioIdc","frameCropLeftOffset","frameCropRightOffset","frameCropTopOffset","frameCropBottomOffset","_AacStream","H264Stream","NalByteStream","ADTS_SAMPLING_FREQUENCIES","parseId3TagSize","returnSize","footerPresent","getId3Offset","isLikelyAacData$1","parseSyncSafeInteger","percentEncode","parseIso88591","parseAdtsSize","lowThree","middle","highTwo","parseType$2","parseSampleRate","parseAacTimestamp","isLikelyAacData","parseType","setTimestamp","bytesLeft","tempLength","_VideoSegmentStream","_AudioSegmentStream","_Transmuxer","_CoalesceStream","aac","AUDIO_PROPERTIES","audioProperties","VIDEO_PROPERTIES","videoProperties","ONE_SECOND_IN_TS$1","retriggerForStream","addPipelineLogRetriggers","transmuxer","pipeline","arrayEquals","generateSegmentTimingInfo","startDts","endDts","prependedContentDuration","ptsOffsetFromDts","decodeDuration","presentationDuration","firstSequenceNumber","prop","setEarliestDts","earliestDts","setVideoBaseMediaDecodeTime","setAudioAppendStart","videoClockCyclesOfSilencePrefixed","gopsToAlignWith","minPTS","gopCache_","nalUnit","gopForFusion","firstGop","lastGop","resetStream_","getGopForFusion_","alignedGops","alignGopsAtEnd","alignGopsAtEnd_","alignGopsAtStart_","gop","pop","dtsDistance","nearestGopObj","currentGopObj","halfSecond","allowableOverlap","nearestDistance","alignIndex","gopIndex","align","alignEndIndex","matchFound","trimIndex","metadata","alignGopsWith","newGopsToAlignWith","numberOfTracks","remux","remuxTracks","pendingTracks","videoTrack","pendingBoxes","pendingCaptions","pendingMetadata","pendingBytes","emittedTracks","output","audioTrack","caption","id3","captions","captionStreams","info","endTime","cueTime","setRemux","val","hasFlushed","transmuxPipeline_","setupAacPipeline","aacStream","audioTimestampRolloverStream","timedMetadataTimestampRolloverStream","adtsStream","coalesceStream","headOfPipeline","audioSegmentStream","getLogTrigger_","hasAudio","hasVideo","setupTsPipeline","packetStream","parseStream","elementaryStream","h264Stream","videoSegmentStream","id3Frame","setBaseMediaDecodeTime","isAac","resetCaptions","Transmuxer","VideoSegmentStream","AudioSegmentStream","toUnsigned$3","toHexString$1","bin","toUnsigned","toHexString","parseType$1","parseType_1","toUnsigned$2","findBox","path","subresults","findBox_1","toUnsigned$1","getUint64$1","version","parseTfdt","parseSampleFlags","parseSampleFlags_1","dataOffsetPresent","firstSampleFlagsPresent","sampleDurationPresent","sampleSizePresent","sampleFlagsPresent","sampleCompositionTimeOffsetPresent","getInt32","parseTrun","baseDataOffsetPresent","sampleDescriptionIndexPresent","defaultSampleDurationPresent","defaultSampleSizePresent","defaultSampleFlagsPresent","durationIsEmpty","defaultBaseIsMoof","sampleDescriptionIndex","defaultSampleDuration","defaultSampleSize","defaultSampleFlags","baseDataOffsetIsMoof","parseTfhd","commonjsGlobal","globalThis","window","global","timescale","compositionStartTime","getVideoTrackIds","getTracks","getTimescaleFromMediaHeader","window_1","mapToSample","approximateOffset","findSeiNals","avcStream","seiNal","lastMatchedSample","avcView","logs","seiNals","matchingSample","parseSamples","truns","allSamples","trackRun","parseCaptionNals","videoTrackId","trafs","mdats","captionNals","mdatTrafPairs","matchingTraf","pair","headerInfo","parseEmbeddedCaptions","trackNals","CaptionParser","segmentCache","parsedCaptions","parsingPartial","isInitialized","isPartial","isNewInit","videoTrackIds","timescales","parsedData","cachedSegment","pushNals","nals","nal","clearParsedCaptions","resetCaptionStream","clearAllCaptions","captionParser","traks","lowestTime","baseTime","isNaN","isFinite","trafBoxes","parsedTfhd","parsedTfdt","parsedTrun","hdlrs","tkhds","handlerType","getUint8","tkhdVersion","sampleDescriptions","codecConfig","codecConfigType","codecBox","toLowerCase","probe$2","parsePid","parsePayloadUnitStartIndicator","parseAdaptionField","pusi","payloadOffset","parsePesType","parsePesTime","parseNalUnitType","videoPacketContainsKeyFrame","nalType","frameBuffer","frameI","frameSyncPoint","foundKeyFrame","probe$1","probe","ts","SYNC_BYTE","parsePsi_","table","parseAudioPes_","pesType","parsed","endLoop","parseVideoPes_","firstKeyFrame","console","adjustTimestamp_","segmentInfo","baseTimestamp","audioBaseTimestamp","dtsTime","ptsTime","videoBaseTimestamp","inspectAac_","audioCount","audioTimescale","inspectTs_","inspect","isAacData","tsInspector","wireTransmuxerEvents","initArray","typedArray","postMessage","action","gopInfo","timingInfo","videoSegmentTimingInfo","presentation","audioSegmentTimingInfo","trackInfo","audioTimingInfo","MessageHandlers","pushMp4Captions","trackIds","probeMp4StartTime","probeMp4Tracks","probeTs","baseStartTime","tsStartTime","timeInfo","videoStart","audioStart","clearAllMp4Captions","clearParsedMp4Captions","setTimestampOffset","timestampOffset","round","appendStart","onmessage","messageHandlers","TransmuxWorker","handleData_","transmuxedData","_event$data$segment","videoFrameDtsTime","videoFramePtsTime","handleDone_","handleGopInfo_","processTransmux","audioAppendStart","onData","onTrackInfo","onAudioTimingInfo","onVideoTimingInfo","onVideoSegmentTimingInfo","onAudioSegmentTimingInfo","onId3","onCaptions","onDone","onEndedTimeline","onTransmuxerLog","isEndOfTimeline","waitForEndedTimelineEvent","handleMessage","currentTransmux","dequeue","isArray","transmuxQueue","processAction","enqueueAction","transmux","createTransmuxer","term","segmentTransmuxer","workerCallback","endAction","listenForEndEvent","isArrayBuffer","transfers","REQUEST_ERRORS","FAILURE","TIMEOUT","ABORTED","abortAll","activeXhrs","getRequestStats","getProgressStats","progressEvent","target","stats","handleErrors","handleKeyResponse","objects","finishProcessingFn","errorObj","Uint32Array","parseInitSegment","_callback","handleInitSegmentResponse","encryptedBytes","parseError","handleSegmentResponse","newBytes","lastReachedChar","transmuxAndNotify","trackInfoFn","timingInfoFn","videoSegmentTimingInfoFn","audioSegmentTimingInfoFn","id3Fn","captionsFn","endedTimelineFn","dataFn","doneFn","fmp4Tracks","isMuxed","audioStartFn","audioEndFn","videoStartFn","videoEndFn","finish","id3Frames","probeResult","handleSegmentBytes","_ref5","bytesAsUint8Array","isFmp4","audioCodec","videoCodec","finishLoading","_ref6","decrypt","_ref7","keyBytes","decryptionWorker","decryptionHandler","decrypted","encrypted","iv","decryptSegment","_ref8","requestId","decryptedBytes","waitForCompletion","_ref9","didError","segmentFinish","endOfAllRequests","handleLoadEnd","_ref10","loadendState","abortFn","calledAbortFn","handleProgress","_ref11","progressFn","firstBytesReceivedAt","mediaSegmentRequest","_ref12","xhrOptions","keyRequestOptions","keyRequestCallback","keyXhr","differentMapKey","mapKeyRequestOptions","mapKeyRequestCallback","mapKeyXhr","initSegmentOptions","initSegmentRequestCallback","initSegmentXhr","segmentRequestOptions","segmentRequestCallback","segmentXhr","activeXhr","logFn$1","getCodecs","mediaAttributes","isMaat","audioGroup","unwrapCodecList","codecList","codecs","details","codecCount","codecObj","codecsForPlaylist","codecInfo","defaultCodecs","logFn","representationToString","representation","JSON","stringify","safeGetComputedStyle","el","property","getComputedStyle","stableSort","sortFn","newArray","left","right","cmp","comparePlaylistBandwidth","leftBandwidth","rightBandwidth","comparePlaylistResolution","leftWidth","rightWidth","RESOLUTION","simpleSelector","playerBandwidth","playerWidth","playerHeight","limitRenditionByPlayerDimensions","masterPlaylistController","getAudioTrackPlaylists_","audioOnly","sortedPlaylistReps","rep","enabledPlaylistReps","bandwidthPlaylistReps","highestRemainingBandwidthRep","bandwidthBestRep","_chosenRep","haveResolution","resolutionBestRepList","resolutionPlusOneList","resolutionPlusOneSmallest","resolutionPlusOneRep","leastPixelDiffRep","resolutionBestRep","experimentalLeastPixelDiffSelector","leastPixelDiffList","pixelDiff","chosenRep","_type","lastBandwidthSelector","pixelRatio","useDevicePixelRatio","devicePixelRatio","systemBandwidth","parseInt","tech_","masterPlaylistController_","movingAverageBandwidthSelector","decay","average","lastSystemBandwidth","minRebufferMaxBandwidthSelector","currentTimeline","syncController","compatiblePlaylists","enabledPlaylists","bandwidthPlaylists","rebufferingEstimates","getSyncPoint","numRequests","requestTimeEstimate","rebufferingImpact","noRebufferingPlaylists","estimate","lowestBitrateCompatibleVariantSelector","playlistsWithVideo","concatSegments","segmentObj","tempBuffer","createCaptionsTrackIfNotExists","inbandTextTracks","instreamId","textTracks","getTrackById","language","def","captionService","default","addRemoteTextTrack","kind","addCaptionData","captionArray","Cue","WebKitDataCue","VTTCue","addCue","deprecateOldCue","cue","defineProperties","get","addMetadata","metadataArray","videoDuration","metadataTrack","metadataTrack_","cues","cuesArray","cuesGroupedByStartTime","timeSlot","sortedStartTimes","cueGroup","nextTime","createMetadataTrackIfNotExists","inBandMetadataTrackDispatchType","removeCuesFromTrack","removeCue","removeDuplicateCuesFromTrack","duplicates","occurrences","dupe","gopsSafeToAlignWith","mapping","currentTimePts","updateGopBuffer","removeGopBuffer","updatedBuffer","shallowEqual","akeys","bkeys","QUOTA_EXCEEDED_ERR","getSyncSegmentCandidate","targetTime","timelineSegments","timeline","MIN_BACK_BUFFER","CHECK_BUFFER_DELAY","finite","num","MIN_SEGMENT_DURATION_TO_SAVE_STATS","illegalMediaSwitch","loaderType","startingMedia","safeBackBufferTrimTime","trimTime","maxTrimTime","segmentInfoString","_segmentInfo$playlist","_segmentInfo$playlist2","mediaIndex","segmentLen","selection","isSyncRequest","independent","hasPartIndex","zeroBasedPartCount","timingInfoPropertyForMedia","timestampOffsetForSegment","segmentTimeline","overrideCheck","shouldWaitForTimelineChange","timelineChangeController","audioDisabled","lastMainTimelineChange","lastTimelineChange","to","pendingAudioTimelineChange","pendingTimelineChange","mediaDuration","timingInfos","maxDuration","typeTimingInfo","segmentTooLong","getTroublesomeSegmentDurationMessage","sourceType","isSegmentWayTooLong","isSegmentSlightlyTooLong","segmentTooLongMessage","severity","SegmentLoader","_videojs$EventTarget","TypeError","mediaSource","throughput","rate","roundTrip","resetStats_","hasPlayed_","hasPlayed","currentTime_","seekable_","seeking_","seeking","duration_","mediaSource_","loaderType_","currentMediaInfo_","startingMediaInfo_","segmentMetadataTrack_","segmentMetadataTrack","goalBufferLength_","goalBufferLength","sourceType_","sourceUpdater_","sourceUpdater","inbandTextTracks_","state_","timelineChangeController_","shouldSaveSegmentTimingInfo_","captionServices_","checkBufferTimeout_","error_","currentTimeline_","pendingSegment_","xhrOptions_","pendingSegments_","audioDisabled_","isPendingTimestampOffset_","gopBuffer_","timeMapping_","safeAppend_","appendInitSegment_","playlistOfLastInitSegment_","callQueue_","loadQueue_","metadataQueue_","waitingOnRemove_","quotaExceededErrorRetryTimeout_","activeInitSegmentId_","initSegments_","cacheEncryptionKeys_","cacheEncryptionKeys","keyCache_","decrypter_","decrypter","syncController_","syncPoint_","transmuxer_","createTransmuxer_","triggerSyncInfoUpdate_","isEndOfStream_","ended_","fetchAtBuffer_","defineProperty","newState","hasEnoughInfoToAppend_","processCallQueue_","hasEnoughInfoToLoad_","processLoadQueue_","mediaBytesTransferred","mediaRequests","mediaRequestsAborted","mediaRequestsTimedout","mediaRequestsErrored","mediaTransferDuration","mediaSecondsLoaded","mediaAppends","abort_","setAudio","enable","removeAudio","paused","monitorBuffer_","abortRequests","clearPendingTimelineChange","checkForAbort_","_error","endOfStream","buffered_","getMediaInfo_","videoBuffered","audioBuffered","initSegmentForMap","storedMap","segmentKey","storedKey","couldBeginLoading_","playlist_","init_","resetEverything","newPlaylist","oldPlaylist","syncInfo","setDateTimeMappingForStart","oldId","resyncLoader","resetLoader","mediaSequenceDiff","saveExpiredSegmentInfo","remove","force","removesRemaining","removeFinished","removeVideo","monitorBufferTick_","fillBuffer_","updating","chooseNextRequest_","from","loadSegment_","appendedLastSegment","appendedLastPart","bufferedTime","preloaded","haveEnoughBuffer","next","_Playlist$getMediaInf","_partIndex","nextSegment","lastSegmentLastPart","ended","generateSegmentInfo_","forceTimestampOffset","random","timestampOffsetForSegment_","audioBufferedEnd","audioTimestampOffset","videoTimestampOffset","earlyAbortWhenNeeded_","measuredBandwidth","requestTimeRemaining","timeUntilRebuffer$1","switchCandidate","timeSavedBySwitching","minimumTimeSaving","handleAbort_","handleProgress_","simpleSegment","handleTrackInfo_","checkForIllegalMediaSwitch","handleTimingInfo_","timeType","timingInfoProperty","handleCaptions_","captionData","hasAppendedData_","captionTracks","captionTrack","trackName","_captionTracks$trackN","handleId3_","processMetadataQueue_","callQueue","fun","loadQueue","getCurrentMediaInfo_","ready","setTimeMapping_","updateMediaSecondsLoaded_","firstVideoFrameTimeForData","useVideoTimingInfo","trueSegmentStart_","currentStart","currentVideoTimestampOffset","updateAppendInitSegmentStatus","updateSourceBufferTimestampOffset_","updateTimingInfoEnd_","saveSegmentTimingInfo","shouldSaveTimelineMapping","appendData_","changedTimestampOffset","getInitSegmentAndUpdateState_","handleQuotaExceededError_","audioBufferStart","audioBufferEnd","videoBufferStart","videoBufferEnd","appendToSourceBuffer_","timeToRemoveUntil","handleAppendError_","appendBuffer","handleSegmentTimingInfo_","segmentTimingInfo","transmuxedDecodeStart","transmuxedDecodeEnd","trimBackBuffer_","updateTransmuxerAndRequestSegment_","shouldUpdateTransmuxerTimestampOffset_","createSimplifiedSegmentObj_","isEndOfStream","isWalkingForward","isDiscontinuity","segmentRequestFinished_","removeToTime","previousSegment","saveTransferStats_","saveBandwidthRelatedStats_","handleTimeout_","waitForAppendsToComplete_","timelineMapping","mappingForTimeline","waitForVideo","waitForAudio","waitingOnAppends","checkAppendsDone_","videoQueueCallback","audioQueueCallback","handleAppendsDone_","illegalMediaSwitchError","didChange","prioritizedTimingInfo","segmentDurationMessage","recordThroughput_","addSegmentMetadataCue_","badSegmentGuess","badPartGuess","segmentProcessingTime","segmentProcessingThroughput","custom","dateTimeString","resolution","noop","Vhs$1","toTitleCase","w","toUpperCase","bufferTypes","_updating","sourceBuffer","queuePending","nextQueueIndexOfType","queue","queueEntry","shiftQueue","queueIndex","cleanupBuffer","titleType","inSourceBuffers","sourceBuffers","actions","onError","_duration","addSourceBuffer","mime","removeSourceBuffer","changeType","pushQueue","onUpdateend","SourceUpdater","sourceopenListener_","audioTimestampOffset_","videoTimestampOffset_","delayedAudioAppendQueue_","videoAppendQueued_","onVideoUpdateEnd_","onAudioUpdateEnd_","onVideoError_","videoError_","onAudioError_","audioError_","createdSourceBuffers_","initializedEme_","triggeredReady_","initializedEme","triggerReady","hasCreatedSourceBuffers","hasInitializedAnyEme","createSourceBuffers","addOrChangeSourceBuffers","canRemoveSourceBuffer","IS_FIREFOX","MediaSource","canChangeType","SourceBuffer","constructor","processedAppend_","videoBuffer","que","audioBuffer","setDuration","uint8ToUtf8","uintArray","escape","VTT_LINE_TERMINATORS","VTTSegmentLoader","_SegmentLoader","subtitlesTrack_","featuresNativeTextTracks_","featuresNativeTextTracks","combinedByteLength","combinedSegment","_track","timestampOffsetForTimeline","checkTimestampOffset","skipEmptySegments_","empty","stopForError","WebVTT","loadHandler","errorHandler","requested","parseVTTCues_","updateTimeMapping_","timelines","decoder","decodeBytesToString","StringDecoder","Parser","vttjs","timestampmap","MPEGTS","LOCAL","oncue","ontimestampmap","onparsingerror","mapData","segmentData","mappingObj","diff","firstStart","lastStart","findAdCue","mediaTime","adStartTime","adEndTime","updateAdCues","cueOut","parseFloat","_segment$cueOutCont$s","cueOutCont","adOffset","adTotal","MAX_MEDIA_SEQUENCE_DIFF_FOR_SYNC","syncPointStrategies","run","timelineToDatetimeMappings","lastDistance","datetimeMapping","segmentTime","z","distance","discontinuityStarts","discontinuitySequence","discontinuitySync","discontinuities","SyncController","syncPoints","runStrategies_","selectSyncPoint_","getExpiredTime","strategy","bestSyncPoint","bestDistance","bestStrategy","newDistance","lastRemovedSegment","firstSegment","playlistTimestamp","didCalculateSegmentTimeMapping","calculateSegmentTimeMapping_","saveDiscontinuitySyncInfo_","dateTime","accuracy","mediaIndexDiff","TimelineChangeController","pendingTimelineChanges_","lastTimelineChanges_","workerCode","createCommonjsModule","basedir","require","base","commonjsRequire","createClass","_defineProperties","props","enumerable","configurable","writable","_createClass","Constructor","protoProps","staticProps","__esModule","setPrototypeOf","_setPrototypeOf","o","inheritsLoose","_inheritsLoose","subClass","superClass","create","_length","unpad","padded","precompute","x","xInv","x2","x4","x8","tEnc","tDec","tables","encTable","decTable","sbox","sboxInv","th","aesTables","AES","tmp","_tables","keyLen","rcon","encKey","decKey","_key","encrypted0","encrypted1","encrypted2","encrypted3","out","a2","b2","c2","nInnerRounds","kIndex","table0","table1","table2","table3","AsyncStream","_Stream","jobs","timeout_","processJob_","job","ntoh","word","initVector","init0","init1","init2","init3","wordIx","encrypted32","Int32Array","decipher","decrypted32","Decrypter","STEP","asyncStream_","decryptChunk_","audioTrackKind_","characteristics","stopLoaders","segmentLoader","activePlaylistLoader","startLoaders","playlistLoader","onGroupChanged","_settings$segmentLoad","segmentLoaders","mainSegmentLoader","main","mediaTypes","activeTrack","activeGroup","getActiveGroup","previousActiveLoader","lastGroup","lastGroup_","lastTrack_","isMasterPlaylist","onGroupChanging","onTrackChanged","_settings$segmentLoad2","lastTrack","mpc","selectPlaylist","fastQualityChange_","blacklistCurrentPlaylist","defaultTrack","enabled","SUBTITLES","mode","setupListeners","requestOptions","initialize","_settings$mediaTypes$","groups","variantLabel","AudioTrack","_settings$mediaTypes$2","forced","autoselect","_settings$mediaTypes$3","newProps","groupMatch","list","variants","groupKeys","groupPropertyList","activeTrack_","setupMediaGroups","_settings$segmentLoad3","audioSegmentLoader","activeAudioGroup","onAudioTrackChanged","audioTracks","remoteTextTracks","clearTracks","addTrack","createMediaTypes","ABORT_EARLY_BLACKLIST_SECONDS","loaderStats","sumLoaderStat","stat","audioSegmentLoader_","mainSegmentLoader_","shouldSwitchToMedia","currentPlaylist","nextPlaylist","bufferLowWaterLine","bufferHighWaterLine","experimentalBufferBasedABR","sharedLogLine","isBuffered","forwardBuffer","maxBufferLowWaterLine","nextBandwidth","currBandwidth","logLine","_logLine","MasterPlaylistController","externVhs","useCueTags","enableLowInitialPlaylist","maxPlaylistRetries","useCueTags_","cueTagsTrack_","addTextTrack","requestOptions_","pauseLoading","mediaTypes_","handleDurationChange_","handleSourceOpen_","handleSourceEnded_","segmentLoaderSettings","setupMasterPlaylistLoaderListeners_","subtitleSegmentLoader_","setupSegmentLoaderListeners_","startABRTimer_","stopABRTimer_","triggeredFmp4Usage","loadOnPlay_","timeToLoadedData__","mainAppendsToLoadedData__","audioAppendsToLoadedData__","timeToLoadedDataStart","mainAppendsToLoadedData_","audioAppendsToLoadedData_","appendsToLoadedData_","timeToLoadedData_","checkABR_","shouldSwitchToMedia_","switchMedia_","cause","newId","abrTimer_","setInterval","scrubbing","clearInterval","defaultPlaylists","defaultGroup","requestTimeout","triggerPresenceUsage_","setupFirstPlay","updatedPlaylist","selectedMedia","excludeUnsupportedVariants_","selectInitialPlaylist","initialMedia_","haveJsonSource","handleUpdatedMediaPlaylist","bubbles","lastExcludeReason_","playlistOutdated","stuckAtPlaylistEnd_","reason","updateAdCues_","updateDuration","defaultDemuxed","audioGroupKeys","mediaGroup","onSyncInfoUpdate_","onEndOfStream","delegateLoaders_","updateCodecs","tryToCreateSourceBuffers_","getCodecsOrExclude_","mediaSecondsLoaded_","smoothQualityChange_","IS_EDGE","setCurrentTime","play","autoplay","playPromise","then","mainMediaInfo","absolutePlaylistEnd","reincluded","errorMessage","delayDuration","fnNames","loaders","dontFilterPlaylist","loader","fnName","audioSeekable","mainSeekable","oldEnd","oldStart","isLive","updateDuration_","areMediaTypesKnown_","usingAudioLoader","hasMainMediaInfo","hasAudioMediaInfo","playlistCodecs","unsupportedAudio","supportFunction","unsupportedCodecs","supporter","variantAudioGroup","switchMessages","newCodec","oldCodec","codecString","excludeIncompatibleVariants_","_this10","ids","unsupported","_this11","codecCount_","videoDetails","audioDetails","blacklistReasons","variantCodecs","variantCodecCount","variantVideoDetails","variantAudioDetails","initial","newMax","enableFunction","playlistID","changePlaylistFn","incompatible","currentlyEnabled","Representation","vhsHandler","smoothQualityChange","qualityChangeFunction","renditionSelectionMixin","representations","timerCancelEvents","PlaybackWatcher","allowSeeksWithinUnsafeLiveWindow","liveRangeSafeTimeDelta","consecutiveUpdates","lastRecordedTime","timer_","checkCurrentTimeTimeout_","playHandler","monitorCurrentTime_","canPlayHandler","waitingHandler","techWaiting_","cancelTimerHandler","cancelTimer_","loaderTypes","loaderChecks","resetSegmentDownloads_","updateend","checkSegmentDownloads_","setSeekingHandlers","seekingAppendCheck_","fixesBadSeeks_","clearSeekingAppendCheck_","watchForBadSeeking_","checkCurrentTime_","isBufferedDifferent","playlistId","waiting_","isAfterSeekableRange","afterSeekableWindow_","beforeSeekableWindow_","minAppendedDuration","bufferedToCheck","timeAhead","nextRange","currentRange","livePoint","videoUnderflow","videoUnderflow_","difference","skipTheGap_","allowedEnd","gap","lastVideoRange","videoRange","audioRange","gapFromVideoUnderflow_","scheduledCurrentTime","gaps","defaultOptions","errorInterval","getSource","IWillNotUseThisInPlugins","sourceObj","currentSource_","currentSource","initPlugin","player","lastCalled","localOptions","loadedMetadataHandler","setSource","cleanupEvents","reinitPlugin","reloadSourceOnError","version$4","version$3","version$2","version$1","STANDARD_PLAYLIST_SELECTOR","INITIAL_PLAYLIST_SELECTOR","LOCAL_STORAGE_KEY","handleVhsMediaChange","qualityLevels","selectedIndex","selectedIndex_","handleVhsLoadedMetadata","addQualityLevel","canPlaySource","emeKeySystems","keySystemOptions","mainPlaylist","audioPlaylist","videoContentType","audioContentType","keySystemContentTypes","keySystem","contentProtection","pssh","getAllPsshKeySystemsOptions","keySystems","keySystemsArr","keySystemsOptions","keySystemsObj","waitForKeySessionCreation","sourceKeySystems","audioMedia","mainPlaylists","eme","initializeMediaKeys","Promise","resolve","keySystemsOptionsArr","initializationFinishedPromises","keySessionCreatedPromises","reject","race","all","setupEmeOptions","sourceOptions","getVhsLocalStorage","localStorage","storedObject","getItem","updateVhsLocalStorage","objectToStore","setItem","expandDataUri","dataUri","supportsNativeHls","createElement","getTech","isSupported","canPlay","some","canItPlay","canPlayType","supportsNativeDash","supportsTypeNatively","Component","getComponent","VhsHandler","_Component","hls","initialBandwidth","playerId","_player","player_","source_","ignoreNextSeekingEvent_","setOptions_","overrideNative","overrideNativeAudioTracks","overrideNativeVideoTracks","featuresNativeVideoTracks","featuresNativeAudioTracks","fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement","contains","useBandwidthFromLocalStorage","useNetworkInformationApi","option","_src","playbackWatcherOptions","playbackWatcher_","players","defaultSelector","playerBandwidthEst","networkInformation","navigator","connection","mozConnection","webkitConnection","tenMbpsAsBitsPerSecond","networkInfoBandwidthEstBitsPerSec","downlink","invThroughput","invBandwidth","systemBitrate","mediaRequests_","mediaRequestsAborted_","mediaRequestsTimedout_","mediaRequestsErrored_","mediaTransferDuration_","mediaBytesTransferred_","mediaAppends_","mainAppendsToLoadedData","audioAppendsToLoadedData","appendsToLoadedData","timeToLoadedData","currentTech","playerDimensions","currentDimensions","videoPlaybackQuality","getVideoPlaybackQuality","setupEme_","setupQualityLevels_","mediaSourceUrl_","createKeySessions_","audioPlaylistLoader","catch","handleWaitingForKey_","didSetupEmeOptions","qualityLevels_","dash","convertToProgramTime","VhsSourceHandler","VERSION","canHandleSource","srcObj","handleSource","_videojs$mergeOptions","_videojs$mergeOptions2","_videojs$mergeOptions3","IS_ANY_SAFARI","_videojs$mergeOptions4","_videojs$mergeOptions5","legacyOverrideNative","supportedType","canUseMsePlayback","supportsNativeMediaSources","registerSourceHandler","use","registerComponent","getPlugin","registerPlugin","plugin","parseSidx","references","referenceId","earliestPresentationTime","firstOffset","referenceCount","getUint16","referenceType","referencedSize","subsegmentDuration","startsWithSap","sapType","sapDeltaTime","isObject","merge","_len","values","flatten","lists","y","findIndexes","l","findIndex","matchingFunction","union","keyFunction","errors","INVALID_NUMBER_OF_PERIOD","DASH_EMPTY_MANIFEST","DASH_INVALID_XML","NO_BASE_URL","MISSING_SEGMENT_INFORMATION","SEGMENT_TIME_UNSPECIFIED","UNSUPPORTED_UTC_TIMING_SCHEME","_ref$baseUrl","baseUrl","_ref$source","_ref$range","_ref$indexRange","indexRange","rangeStr","startRange","endRange","parseEndNumber","endNumber","segmentRange","static","_attributes$timescale","sourceDuration","periodDuration","dynamic","NOW","availabilityStartTime","_attributes$timescale2","_attributes$periodSta","periodStart","_attributes$minimumUp","_attributes$timeShift","timeShiftBufferDepth","periodStartWC","periodEndWC","segmentCount","availableStart","availableEnd","toSegments","number","_attributes$timescale3","_attributes$startNumb","startNumber","parseByDuration","_attributes$timescale4","_segmentRange$type","sectionDuration","segmentsFromBase","_attributes$initializ","initialization","_attributes$indexRang","presentationTime","_attributes$number","sourceURL","segmentTimeInfo","addSidxSegmentsToPlaylist$1","sidxByteRange","sidxEnd","mediaReferences","r","SUPPORTED_MEDIA_TYPES","TIME_FUDGE","getUniqueTimelineStarts","findPlaylistWithName","NAME","mediaGroupPlaylists","updateMediaSequenceForPlaylist","updateSequenceNumbers","oldPlaylists","newPlaylists","firstNewSegment","oldMatchingSegmentIndex","oldMatchingSegment","positionManifestOnTimeline","oldManifest","newManifest","generateSidxKey","mergeDiscontiguousPlaylists","mergedPlaylists","lang","_acc$name$segments","sidxMatch","addSidxSegmentsToPlaylists","formatAudioPlaylist","_attributes","formatVttPlaylist","_m3u8Attributes","m3u8Attributes","organizeAudioPlaylists","formattedPlaylists","role","roleLabel","formatted","firstLabel","organizeVttPlaylists","organizeCaptionServices","svcObj","svc","channel","aspectRatio","easyReader","formatVideoPlaylist","_attributes2","videoOnly","mimeType","contentType","vttOnly","addMediaSequenceValues","flattenMediaGroupPlaylists","mediaGroupObject","labelContents","toM3u8","_mediaGroups","dashPlaylists","_ref8$sidxMapping","_dashPlaylists$0$attr","videoPlaylists","audioPlaylists","vttPlaylists","allowCache","VIDEO","organizedAudioGroup","organizedVttGroup","playlistTimelineStarts","subs","getLiveRValue","parseByTimeline","_attributes$minimumUp2","_attributes$media","sIndex","S","repeat","t","nextS","identifierPattern","identifierReplacement","match","identifier","constructTemplateUrl","parseTemplateInfo","templateValues","RepresentationID","Bandwidth","mapSegment","Time","presentationTimeOffset","SegmentURLToSegmentObject","segmentUrl","mediaRange","segmentsFromList","_attributes$segmentUr","segmentUrls","segmentUrlMap","segmentUrlObject","generateSegments","segmentAttributes","segmentsFn","template","segmentsInfo","_segmentAttributes","_segmentAttributes$ti","toPlaylists","findChildren","element","childNodes","tagName","getContent","textContent","parseDuration","SECONDS_IN_YEAR","SECONDS_IN_MONTH","SECONDS_IN_DAY","SECONDS_IN_HOUR","SECONDS_IN_MIN","durationRegex","exec","_match$slice","year","month","day","hour","minute","second","parseDate","dateRegex","parsers","mediaPresentationDuration","parsedValue","DEFAULT","parseAttributes","parseFn","keySystemsMap","referenceUrls","baseUrlElements","baseUrlElement","getSegmentInformation","adaptationSet","segmentTemplate","segmentList","segmentBase","segmentTimelineParentNode","segmentInitializationParentNode","segmentInitialization","inheritBaseUrls","adaptationSetAttributes","adaptationSetBaseUrls","adaptationSetSegmentInfo","repBaseUrlElements","repBaseUrls","representationSegmentInfo","contentProtectionNodes","node","schemeIdUri","psshNode","psshBuffer","parseCaptionServiceMetadata","_value$split","_values","_value$split2","_value$split2$","opts","opt","_opt$split","toRepresentations","periodAttributes","periodBaseUrls","periodSegmentInfo","roleAttributes","attrs","accessibility","labelVal","nodeValue","toAdaptationSets","mpdAttributes","mpdBaseUrls","period","adaptationSets","getPeriodStart","priorPeriodAttributes","mpdType","inheritAttributes","mpd","_options$manifestUri","_options$NOW","_options$clientOffset","periodNodes","periods","priorPeriod","representationInfo","xml","parseFromString","documentElement","getElementsByTagName","parseUTCTimingScheme","UTCTimingNode","parsedManifestInfo","parseUTCTiming"],"mappings":"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","file":"js/chunk-00d919a8.6710b35e.js","sourcesContent":["var MAX_UINT32 = Math.pow(2, 32);\n\nvar getUint64 = function(uint8) {\n var dv = new DataView(uint8.buffer, uint8.byteOffset, uint8.byteLength);\n var value;\n\n if (dv.getBigUint64) {\n value = dv.getBigUint64(0);\n\n if (value < Number.MAX_SAFE_INTEGER) {\n return Number(value);\n }\n\n return value;\n }\n\n return (dv.getUint32(0) * MAX_UINT32) + dv.getUint32(4);\n};\n\nmodule.exports = {\n getUint64: getUint64,\n MAX_UINT32: MAX_UINT32\n};\n","/**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\nvar\n ONE_SECOND_IN_TS = 90000, // 90kHz clock\n secondsToVideoTs,\n secondsToAudioTs,\n videoTsToSeconds,\n audioTsToSeconds,\n audioTsToVideoTs,\n videoTsToAudioTs,\n metadataTsToSeconds;\n\nsecondsToVideoTs = function(seconds) {\n return seconds * ONE_SECOND_IN_TS;\n};\n\nsecondsToAudioTs = function(seconds, sampleRate) {\n return seconds * sampleRate;\n};\n\nvideoTsToSeconds = function(timestamp) {\n return timestamp / ONE_SECOND_IN_TS;\n};\n\naudioTsToSeconds = function(timestamp, sampleRate) {\n return timestamp / sampleRate;\n};\n\naudioTsToVideoTs = function(timestamp, sampleRate) {\n return secondsToVideoTs(audioTsToSeconds(timestamp, sampleRate));\n};\n\nvideoTsToAudioTs = function(timestamp, sampleRate) {\n return secondsToAudioTs(videoTsToSeconds(timestamp), sampleRate);\n};\n\n/**\n * Adjust ID3 tag or caption timing information by the timeline pts values\n * (if keepOriginalTimestamps is false) and convert to seconds\n */\nmetadataTsToSeconds = function(timestamp, timelineStartPts, keepOriginalTimestamps) {\n return videoTsToSeconds(keepOriginalTimestamps ? timestamp : timestamp - timelineStartPts);\n};\n\nmodule.exports = {\n ONE_SECOND_IN_TS: ONE_SECOND_IN_TS,\n secondsToVideoTs: secondsToVideoTs,\n secondsToAudioTs: secondsToAudioTs,\n videoTsToSeconds: videoTsToSeconds,\n audioTsToSeconds: audioTsToSeconds,\n audioTsToVideoTs: audioTsToVideoTs,\n videoTsToAudioTs: videoTsToAudioTs,\n metadataTsToSeconds: metadataTsToSeconds\n};\n","/*! @name @videojs/http-streaming @version 2.13.1 @license Apache-2.0 */\nimport _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';\nimport _inheritsLoose from '@babel/runtime/helpers/inheritsLoose';\nimport document from 'global/document';\nimport window$1 from 'global/window';\nimport _resolveUrl from '@videojs/vhs-utils/es/resolve-url.js';\nimport videojs from 'video.js';\nimport _extends from '@babel/runtime/helpers/extends';\nimport { Parser } from 'm3u8-parser';\nimport { isAudioCodec, translateLegacyCodec, codecsFromDefault, parseCodecs, getMimeForCodec, DEFAULT_VIDEO_CODEC, DEFAULT_AUDIO_CODEC, browserSupportsCodec, muxerSupportsCodec } from '@videojs/vhs-utils/es/codecs.js';\nimport { simpleTypeFromSourceType } from '@videojs/vhs-utils/es/media-types.js';\nexport { simpleTypeFromSourceType } from '@videojs/vhs-utils/es/media-types.js';\nimport { generateSidxKey, parseUTCTiming, parse, addSidxSegmentsToPlaylist } from 'mpd-parser';\nimport parseSidx from 'mux.js/lib/tools/parse-sidx';\nimport { getId3Offset } from '@videojs/vhs-utils/es/id3-helpers';\nimport { detectContainerForBytes, isLikelyFmp4MediaSegment } from '@videojs/vhs-utils/es/containers';\nimport { concatTypedArrays, stringToBytes, toUint8 } from '@videojs/vhs-utils/es/byte-helpers';\nimport { ONE_SECOND_IN_TS } from 'mux.js/lib/utils/clock';\n\n/**\n * @file resolve-url.js - Handling how URLs are resolved and manipulated\n */\nvar resolveUrl = _resolveUrl;\n/**\n * Checks whether xhr request was redirected and returns correct url depending\n * on `handleManifestRedirects` option\n *\n * @api private\n *\n * @param {string} url - an url being requested\n * @param {XMLHttpRequest} req - xhr request result\n *\n * @return {string}\n */\n\nvar resolveManifestRedirect = function resolveManifestRedirect(handleManifestRedirect, url, req) {\n // To understand how the responseURL below is set and generated:\n // - https://fetch.spec.whatwg.org/#concept-response-url\n // - https://fetch.spec.whatwg.org/#atomic-http-redirect-handling\n if (handleManifestRedirect && req && req.responseURL && url !== req.responseURL) {\n return req.responseURL;\n }\n\n return url;\n};\n\nvar logger = function logger(source) {\n if (videojs.log.debug) {\n return videojs.log.debug.bind(videojs, 'VHS:', source + \" >\");\n }\n\n return function () {};\n};\n\n/**\n * ranges\n *\n * Utilities for working with TimeRanges.\n *\n */\n\nvar TIME_FUDGE_FACTOR = 1 / 30; // Comparisons between time values such as current time and the end of the buffered range\n// can be misleading because of precision differences or when the current media has poorly\n// aligned audio and video, which can cause values to be slightly off from what you would\n// expect. This value is what we consider to be safe to use in such comparisons to account\n// for these scenarios.\n\nvar SAFE_TIME_DELTA = TIME_FUDGE_FACTOR * 3;\n\nvar filterRanges = function filterRanges(timeRanges, predicate) {\n var results = [];\n var i;\n\n if (timeRanges && timeRanges.length) {\n // Search for ranges that match the predicate\n for (i = 0; i < timeRanges.length; i++) {\n if (predicate(timeRanges.start(i), timeRanges.end(i))) {\n results.push([timeRanges.start(i), timeRanges.end(i)]);\n }\n }\n }\n\n return videojs.createTimeRanges(results);\n};\n/**\n * Attempts to find the buffered TimeRange that contains the specified\n * time.\n *\n * @param {TimeRanges} buffered - the TimeRanges object to query\n * @param {number} time - the time to filter on.\n * @return {TimeRanges} a new TimeRanges object\n */\n\n\nvar findRange = function findRange(buffered, time) {\n return filterRanges(buffered, function (start, end) {\n return start - SAFE_TIME_DELTA <= time && end + SAFE_TIME_DELTA >= time;\n });\n};\n/**\n * Returns the TimeRanges that begin later than the specified time.\n *\n * @param {TimeRanges} timeRanges - the TimeRanges object to query\n * @param {number} time - the time to filter on.\n * @return {TimeRanges} a new TimeRanges object.\n */\n\nvar findNextRange = function findNextRange(timeRanges, time) {\n return filterRanges(timeRanges, function (start) {\n return start - TIME_FUDGE_FACTOR >= time;\n });\n};\n/**\n * Returns gaps within a list of TimeRanges\n *\n * @param {TimeRanges} buffered - the TimeRanges object\n * @return {TimeRanges} a TimeRanges object of gaps\n */\n\nvar findGaps = function findGaps(buffered) {\n if (buffered.length < 2) {\n return videojs.createTimeRanges();\n }\n\n var ranges = [];\n\n for (var i = 1; i < buffered.length; i++) {\n var start = buffered.end(i - 1);\n var end = buffered.start(i);\n ranges.push([start, end]);\n }\n\n return videojs.createTimeRanges(ranges);\n};\n/**\n * Calculate the intersection of two TimeRanges\n *\n * @param {TimeRanges} bufferA\n * @param {TimeRanges} bufferB\n * @return {TimeRanges} The interesection of `bufferA` with `bufferB`\n */\n\nvar bufferIntersection = function bufferIntersection(bufferA, bufferB) {\n var start = null;\n var end = null;\n var arity = 0;\n var extents = [];\n var ranges = [];\n\n if (!bufferA || !bufferA.length || !bufferB || !bufferB.length) {\n return videojs.createTimeRange();\n } // Handle the case where we have both buffers and create an\n // intersection of the two\n\n\n var count = bufferA.length; // A) Gather up all start and end times\n\n while (count--) {\n extents.push({\n time: bufferA.start(count),\n type: 'start'\n });\n extents.push({\n time: bufferA.end(count),\n type: 'end'\n });\n }\n\n count = bufferB.length;\n\n while (count--) {\n extents.push({\n time: bufferB.start(count),\n type: 'start'\n });\n extents.push({\n time: bufferB.end(count),\n type: 'end'\n });\n } // B) Sort them by time\n\n\n extents.sort(function (a, b) {\n return a.time - b.time;\n }); // C) Go along one by one incrementing arity for start and decrementing\n // arity for ends\n\n for (count = 0; count < extents.length; count++) {\n if (extents[count].type === 'start') {\n arity++; // D) If arity is ever incremented to 2 we are entering an\n // overlapping range\n\n if (arity === 2) {\n start = extents[count].time;\n }\n } else if (extents[count].type === 'end') {\n arity--; // E) If arity is ever decremented to 1 we leaving an\n // overlapping range\n\n if (arity === 1) {\n end = extents[count].time;\n }\n } // F) Record overlapping ranges\n\n\n if (start !== null && end !== null) {\n ranges.push([start, end]);\n start = null;\n end = null;\n }\n }\n\n return videojs.createTimeRanges(ranges);\n};\n/**\n * Gets a human readable string for a TimeRange\n *\n * @param {TimeRange} range\n * @return {string} a human readable string\n */\n\nvar printableRange = function printableRange(range) {\n var strArr = [];\n\n if (!range || !range.length) {\n return '';\n }\n\n for (var i = 0; i < range.length; i++) {\n strArr.push(range.start(i) + ' => ' + range.end(i));\n }\n\n return strArr.join(', ');\n};\n/**\n * Calculates the amount of time left in seconds until the player hits the end of the\n * buffer and causes a rebuffer\n *\n * @param {TimeRange} buffered\n * The state of the buffer\n * @param {Numnber} currentTime\n * The current time of the player\n * @param {number} playbackRate\n * The current playback rate of the player. Defaults to 1.\n * @return {number}\n * Time until the player has to start rebuffering in seconds.\n * @function timeUntilRebuffer\n */\n\nvar timeUntilRebuffer = function timeUntilRebuffer(buffered, currentTime, playbackRate) {\n if (playbackRate === void 0) {\n playbackRate = 1;\n }\n\n var bufferedEnd = buffered.length ? buffered.end(buffered.length - 1) : 0;\n return (bufferedEnd - currentTime) / playbackRate;\n};\n/**\n * Converts a TimeRanges object into an array representation\n *\n * @param {TimeRanges} timeRanges\n * @return {Array}\n */\n\nvar timeRangesToArray = function timeRangesToArray(timeRanges) {\n var timeRangesList = [];\n\n for (var i = 0; i < timeRanges.length; i++) {\n timeRangesList.push({\n start: timeRanges.start(i),\n end: timeRanges.end(i)\n });\n }\n\n return timeRangesList;\n};\n/**\n * Determines if two time range objects are different.\n *\n * @param {TimeRange} a\n * the first time range object to check\n *\n * @param {TimeRange} b\n * the second time range object to check\n *\n * @return {Boolean}\n * Whether the time range objects differ\n */\n\nvar isRangeDifferent = function isRangeDifferent(a, b) {\n // same object\n if (a === b) {\n return false;\n } // one or the other is undefined\n\n\n if (!a && b || !b && a) {\n return true;\n } // length is different\n\n\n if (a.length !== b.length) {\n return true;\n } // see if any start/end pair is different\n\n\n for (var i = 0; i < a.length; i++) {\n if (a.start(i) !== b.start(i) || a.end(i) !== b.end(i)) {\n return true;\n }\n } // if the length and every pair is the same\n // this is the same time range\n\n\n return false;\n};\nvar lastBufferedEnd = function lastBufferedEnd(a) {\n if (!a || !a.length || !a.end) {\n return;\n }\n\n return a.end(a.length - 1);\n};\n/**\n * A utility function to add up the amount of time in a timeRange\n * after a specified startTime.\n * ie:[[0, 10], [20, 40], [50, 60]] with a startTime 0\n * would return 40 as there are 40s seconds after 0 in the timeRange\n *\n * @param {TimeRange} range\n * The range to check against\n * @param {number} startTime\n * The time in the time range that you should start counting from\n *\n * @return {number}\n * The number of seconds in the buffer passed the specified time.\n */\n\nvar timeAheadOf = function timeAheadOf(range, startTime) {\n var time = 0;\n\n if (!range || !range.length) {\n return time;\n }\n\n for (var i = 0; i < range.length; i++) {\n var start = range.start(i);\n var end = range.end(i); // startTime is after this range entirely\n\n if (startTime > end) {\n continue;\n } // startTime is within this range\n\n\n if (startTime > start && startTime <= end) {\n time += end - startTime;\n continue;\n } // startTime is before this range.\n\n\n time += end - start;\n }\n\n return time;\n};\n\n/**\n * @file playlist.js\n *\n * Playlist related utilities.\n */\nvar createTimeRange = videojs.createTimeRange;\n/**\n * Get the duration of a segment, with special cases for\n * llhls segments that do not have a duration yet.\n *\n * @param {Object} playlist\n * the playlist that the segment belongs to.\n * @param {Object} segment\n * the segment to get a duration for.\n *\n * @return {number}\n * the segment duration\n */\n\nvar segmentDurationWithParts = function segmentDurationWithParts(playlist, segment) {\n // if this isn't a preload segment\n // then we will have a segment duration that is accurate.\n if (!segment.preload) {\n return segment.duration;\n } // otherwise we have to add up parts and preload hints\n // to get an up to date duration.\n\n\n var result = 0;\n (segment.parts || []).forEach(function (p) {\n result += p.duration;\n }); // for preload hints we have to use partTargetDuration\n // as they won't even have a duration yet.\n\n (segment.preloadHints || []).forEach(function (p) {\n if (p.type === 'PART') {\n result += playlist.partTargetDuration;\n }\n });\n return result;\n};\n/**\n * A function to get a combined list of parts and segments with durations\n * and indexes.\n *\n * @param {Playlist} playlist the playlist to get the list for.\n *\n * @return {Array} The part/segment list.\n */\n\nvar getPartsAndSegments = function getPartsAndSegments(playlist) {\n return (playlist.segments || []).reduce(function (acc, segment, si) {\n if (segment.parts) {\n segment.parts.forEach(function (part, pi) {\n acc.push({\n duration: part.duration,\n segmentIndex: si,\n partIndex: pi,\n part: part,\n segment: segment\n });\n });\n } else {\n acc.push({\n duration: segment.duration,\n segmentIndex: si,\n partIndex: null,\n segment: segment,\n part: null\n });\n }\n\n return acc;\n }, []);\n};\nvar getLastParts = function getLastParts(media) {\n var lastSegment = media.segments && media.segments.length && media.segments[media.segments.length - 1];\n return lastSegment && lastSegment.parts || [];\n};\nvar getKnownPartCount = function getKnownPartCount(_ref) {\n var preloadSegment = _ref.preloadSegment;\n\n if (!preloadSegment) {\n return;\n }\n\n var parts = preloadSegment.parts,\n preloadHints = preloadSegment.preloadHints;\n var partCount = (preloadHints || []).reduce(function (count, hint) {\n return count + (hint.type === 'PART' ? 1 : 0);\n }, 0);\n partCount += parts && parts.length ? parts.length : 0;\n return partCount;\n};\n/**\n * Get the number of seconds to delay from the end of a\n * live playlist.\n *\n * @param {Playlist} master the master playlist\n * @param {Playlist} media the media playlist\n * @return {number} the hold back in seconds.\n */\n\nvar liveEdgeDelay = function liveEdgeDelay(master, media) {\n if (media.endList) {\n return 0;\n } // dash suggestedPresentationDelay trumps everything\n\n\n if (master && master.suggestedPresentationDelay) {\n return master.suggestedPresentationDelay;\n }\n\n var hasParts = getLastParts(media).length > 0; // look for \"part\" delays from ll-hls first\n\n if (hasParts && media.serverControl && media.serverControl.partHoldBack) {\n return media.serverControl.partHoldBack;\n } else if (hasParts && media.partTargetDuration) {\n return media.partTargetDuration * 3; // finally look for full segment delays\n } else if (media.serverControl && media.serverControl.holdBack) {\n return media.serverControl.holdBack;\n } else if (media.targetDuration) {\n return media.targetDuration * 3;\n }\n\n return 0;\n};\n/**\n * walk backward until we find a duration we can use\n * or return a failure\n *\n * @param {Playlist} playlist the playlist to walk through\n * @param {Number} endSequence the mediaSequence to stop walking on\n */\n\nvar backwardDuration = function backwardDuration(playlist, endSequence) {\n var result = 0;\n var i = endSequence - playlist.mediaSequence; // if a start time is available for segment immediately following\n // the interval, use it\n\n var segment = playlist.segments[i]; // Walk backward until we find the latest segment with timeline\n // information that is earlier than endSequence\n\n if (segment) {\n if (typeof segment.start !== 'undefined') {\n return {\n result: segment.start,\n precise: true\n };\n }\n\n if (typeof segment.end !== 'undefined') {\n return {\n result: segment.end - segment.duration,\n precise: true\n };\n }\n }\n\n while (i--) {\n segment = playlist.segments[i];\n\n if (typeof segment.end !== 'undefined') {\n return {\n result: result + segment.end,\n precise: true\n };\n }\n\n result += segmentDurationWithParts(playlist, segment);\n\n if (typeof segment.start !== 'undefined') {\n return {\n result: result + segment.start,\n precise: true\n };\n }\n }\n\n return {\n result: result,\n precise: false\n };\n};\n/**\n * walk forward until we find a duration we can use\n * or return a failure\n *\n * @param {Playlist} playlist the playlist to walk through\n * @param {number} endSequence the mediaSequence to stop walking on\n */\n\n\nvar forwardDuration = function forwardDuration(playlist, endSequence) {\n var result = 0;\n var segment;\n var i = endSequence - playlist.mediaSequence; // Walk forward until we find the earliest segment with timeline\n // information\n\n for (; i < playlist.segments.length; i++) {\n segment = playlist.segments[i];\n\n if (typeof segment.start !== 'undefined') {\n return {\n result: segment.start - result,\n precise: true\n };\n }\n\n result += segmentDurationWithParts(playlist, segment);\n\n if (typeof segment.end !== 'undefined') {\n return {\n result: segment.end - result,\n precise: true\n };\n }\n } // indicate we didn't find a useful duration estimate\n\n\n return {\n result: -1,\n precise: false\n };\n};\n/**\n * Calculate the media duration from the segments associated with a\n * playlist. The duration of a subinterval of the available segments\n * may be calculated by specifying an end index.\n *\n * @param {Object} playlist a media playlist object\n * @param {number=} endSequence an exclusive upper boundary\n * for the playlist. Defaults to playlist length.\n * @param {number} expired the amount of time that has dropped\n * off the front of the playlist in a live scenario\n * @return {number} the duration between the first available segment\n * and end index.\n */\n\n\nvar intervalDuration = function intervalDuration(playlist, endSequence, expired) {\n if (typeof endSequence === 'undefined') {\n endSequence = playlist.mediaSequence + playlist.segments.length;\n }\n\n if (endSequence < playlist.mediaSequence) {\n return 0;\n } // do a backward walk to estimate the duration\n\n\n var backward = backwardDuration(playlist, endSequence);\n\n if (backward.precise) {\n // if we were able to base our duration estimate on timing\n // information provided directly from the Media Source, return\n // it\n return backward.result;\n } // walk forward to see if a precise duration estimate can be made\n // that way\n\n\n var forward = forwardDuration(playlist, endSequence);\n\n if (forward.precise) {\n // we found a segment that has been buffered and so it's\n // position is known precisely\n return forward.result;\n } // return the less-precise, playlist-based duration estimate\n\n\n return backward.result + expired;\n};\n/**\n * Calculates the duration of a playlist. If a start and end index\n * are specified, the duration will be for the subset of the media\n * timeline between those two indices. The total duration for live\n * playlists is always Infinity.\n *\n * @param {Object} playlist a media playlist object\n * @param {number=} endSequence an exclusive upper\n * boundary for the playlist. Defaults to the playlist media\n * sequence number plus its length.\n * @param {number=} expired the amount of time that has\n * dropped off the front of the playlist in a live scenario\n * @return {number} the duration between the start index and end\n * index.\n */\n\n\nvar duration = function duration(playlist, endSequence, expired) {\n if (!playlist) {\n return 0;\n }\n\n if (typeof expired !== 'number') {\n expired = 0;\n } // if a slice of the total duration is not requested, use\n // playlist-level duration indicators when they're present\n\n\n if (typeof endSequence === 'undefined') {\n // if present, use the duration specified in the playlist\n if (playlist.totalDuration) {\n return playlist.totalDuration;\n } // duration should be Infinity for live playlists\n\n\n if (!playlist.endList) {\n return window$1.Infinity;\n }\n } // calculate the total duration based on the segment durations\n\n\n return intervalDuration(playlist, endSequence, expired);\n};\n/**\n * Calculate the time between two indexes in the current playlist\n * neight the start- nor the end-index need to be within the current\n * playlist in which case, the targetDuration of the playlist is used\n * to approximate the durations of the segments\n *\n * @param {Array} options.durationList list to iterate over for durations.\n * @param {number} options.defaultDuration duration to use for elements before or after the durationList\n * @param {number} options.startIndex partsAndSegments index to start\n * @param {number} options.endIndex partsAndSegments index to end.\n * @return {number} the number of seconds between startIndex and endIndex\n */\n\nvar sumDurations = function sumDurations(_ref2) {\n var defaultDuration = _ref2.defaultDuration,\n durationList = _ref2.durationList,\n startIndex = _ref2.startIndex,\n endIndex = _ref2.endIndex;\n var durations = 0;\n\n if (startIndex > endIndex) {\n var _ref3 = [endIndex, startIndex];\n startIndex = _ref3[0];\n endIndex = _ref3[1];\n }\n\n if (startIndex < 0) {\n for (var i = startIndex; i < Math.min(0, endIndex); i++) {\n durations += defaultDuration;\n }\n\n startIndex = 0;\n }\n\n for (var _i = startIndex; _i < endIndex; _i++) {\n durations += durationList[_i].duration;\n }\n\n return durations;\n};\n/**\n * Calculates the playlist end time\n *\n * @param {Object} playlist a media playlist object\n * @param {number=} expired the amount of time that has\n * dropped off the front of the playlist in a live scenario\n * @param {boolean|false} useSafeLiveEnd a boolean value indicating whether or not the\n * playlist end calculation should consider the safe live end\n * (truncate the playlist end by three segments). This is normally\n * used for calculating the end of the playlist's seekable range.\n * This takes into account the value of liveEdgePadding.\n * Setting liveEdgePadding to 0 is equivalent to setting this to false.\n * @param {number} liveEdgePadding a number indicating how far from the end of the playlist we should be in seconds.\n * If this is provided, it is used in the safe live end calculation.\n * Setting useSafeLiveEnd=false or liveEdgePadding=0 are equivalent.\n * Corresponds to suggestedPresentationDelay in DASH manifests.\n * @return {number} the end time of playlist\n * @function playlistEnd\n */\n\nvar playlistEnd = function playlistEnd(playlist, expired, useSafeLiveEnd, liveEdgePadding) {\n if (!playlist || !playlist.segments) {\n return null;\n }\n\n if (playlist.endList) {\n return duration(playlist);\n }\n\n if (expired === null) {\n return null;\n }\n\n expired = expired || 0;\n var lastSegmentEndTime = intervalDuration(playlist, playlist.mediaSequence + playlist.segments.length, expired);\n\n if (useSafeLiveEnd) {\n liveEdgePadding = typeof liveEdgePadding === 'number' ? liveEdgePadding : liveEdgeDelay(null, playlist);\n lastSegmentEndTime -= liveEdgePadding;\n } // don't return a time less than zero\n\n\n return Math.max(0, lastSegmentEndTime);\n};\n/**\n * Calculates the interval of time that is currently seekable in a\n * playlist. The returned time ranges are relative to the earliest\n * moment in the specified playlist that is still available. A full\n * seekable implementation for live streams would need to offset\n * these values by the duration of content that has expired from the\n * stream.\n *\n * @param {Object} playlist a media playlist object\n * dropped off the front of the playlist in a live scenario\n * @param {number=} expired the amount of time that has\n * dropped off the front of the playlist in a live scenario\n * @param {number} liveEdgePadding how far from the end of the playlist we should be in seconds.\n * Corresponds to suggestedPresentationDelay in DASH manifests.\n * @return {TimeRanges} the periods of time that are valid targets\n * for seeking\n */\n\nvar seekable = function seekable(playlist, expired, liveEdgePadding) {\n var useSafeLiveEnd = true;\n var seekableStart = expired || 0;\n var seekableEnd = playlistEnd(playlist, expired, useSafeLiveEnd, liveEdgePadding);\n\n if (seekableEnd === null) {\n return createTimeRange();\n }\n\n return createTimeRange(seekableStart, seekableEnd);\n};\n/**\n * Determine the index and estimated starting time of the segment that\n * contains a specified playback position in a media playlist.\n *\n * @param {Object} options.playlist the media playlist to query\n * @param {number} options.currentTime The number of seconds since the earliest\n * possible position to determine the containing segment for\n * @param {number} options.startTime the time when the segment/part starts\n * @param {number} options.startingSegmentIndex the segment index to start looking at.\n * @param {number?} [options.startingPartIndex] the part index to look at within the segment.\n *\n * @return {Object} an object with partIndex, segmentIndex, and startTime.\n */\n\nvar getMediaInfoForTime = function getMediaInfoForTime(_ref4) {\n var playlist = _ref4.playlist,\n currentTime = _ref4.currentTime,\n startingSegmentIndex = _ref4.startingSegmentIndex,\n startingPartIndex = _ref4.startingPartIndex,\n startTime = _ref4.startTime,\n experimentalExactManifestTimings = _ref4.experimentalExactManifestTimings;\n var time = currentTime - startTime;\n var partsAndSegments = getPartsAndSegments(playlist);\n var startIndex = 0;\n\n for (var i = 0; i < partsAndSegments.length; i++) {\n var partAndSegment = partsAndSegments[i];\n\n if (startingSegmentIndex !== partAndSegment.segmentIndex) {\n continue;\n } // skip this if part index does not match.\n\n\n if (typeof startingPartIndex === 'number' && typeof partAndSegment.partIndex === 'number' && startingPartIndex !== partAndSegment.partIndex) {\n continue;\n }\n\n startIndex = i;\n break;\n }\n\n if (time < 0) {\n // Walk backward from startIndex in the playlist, adding durations\n // until we find a segment that contains `time` and return it\n if (startIndex > 0) {\n for (var _i2 = startIndex - 1; _i2 >= 0; _i2--) {\n var _partAndSegment = partsAndSegments[_i2];\n time += _partAndSegment.duration;\n\n if (experimentalExactManifestTimings) {\n if (time < 0) {\n continue;\n }\n } else if (time + TIME_FUDGE_FACTOR <= 0) {\n continue;\n }\n\n return {\n partIndex: _partAndSegment.partIndex,\n segmentIndex: _partAndSegment.segmentIndex,\n startTime: startTime - sumDurations({\n defaultDuration: playlist.targetDuration,\n durationList: partsAndSegments,\n startIndex: startIndex,\n endIndex: _i2\n })\n };\n }\n } // We were unable to find a good segment within the playlist\n // so select the first segment\n\n\n return {\n partIndex: partsAndSegments[0] && partsAndSegments[0].partIndex || null,\n segmentIndex: partsAndSegments[0] && partsAndSegments[0].segmentIndex || 0,\n startTime: currentTime\n };\n } // When startIndex is negative, we first walk forward to first segment\n // adding target durations. If we \"run out of time\" before getting to\n // the first segment, return the first segment\n\n\n if (startIndex < 0) {\n for (var _i3 = startIndex; _i3 < 0; _i3++) {\n time -= playlist.targetDuration;\n\n if (time < 0) {\n return {\n partIndex: partsAndSegments[0] && partsAndSegments[0].partIndex || null,\n segmentIndex: partsAndSegments[0] && partsAndSegments[0].segmentIndex || 0,\n startTime: currentTime\n };\n }\n }\n\n startIndex = 0;\n } // Walk forward from startIndex in the playlist, subtracting durations\n // until we find a segment that contains `time` and return it\n\n\n for (var _i4 = startIndex; _i4 < partsAndSegments.length; _i4++) {\n var _partAndSegment2 = partsAndSegments[_i4];\n time -= _partAndSegment2.duration;\n\n if (experimentalExactManifestTimings) {\n if (time > 0) {\n continue;\n }\n } else if (time - TIME_FUDGE_FACTOR >= 0) {\n continue;\n }\n\n return {\n partIndex: _partAndSegment2.partIndex,\n segmentIndex: _partAndSegment2.segmentIndex,\n startTime: startTime + sumDurations({\n defaultDuration: playlist.targetDuration,\n durationList: partsAndSegments,\n startIndex: startIndex,\n endIndex: _i4\n })\n };\n } // We are out of possible candidates so load the last one...\n\n\n return {\n segmentIndex: partsAndSegments[partsAndSegments.length - 1].segmentIndex,\n partIndex: partsAndSegments[partsAndSegments.length - 1].partIndex,\n startTime: currentTime\n };\n};\n/**\n * Check whether the playlist is blacklisted or not.\n *\n * @param {Object} playlist the media playlist object\n * @return {boolean} whether the playlist is blacklisted or not\n * @function isBlacklisted\n */\n\nvar isBlacklisted = function isBlacklisted(playlist) {\n return playlist.excludeUntil && playlist.excludeUntil > Date.now();\n};\n/**\n * Check whether the playlist is compatible with current playback configuration or has\n * been blacklisted permanently for being incompatible.\n *\n * @param {Object} playlist the media playlist object\n * @return {boolean} whether the playlist is incompatible or not\n * @function isIncompatible\n */\n\nvar isIncompatible = function isIncompatible(playlist) {\n return playlist.excludeUntil && playlist.excludeUntil === Infinity;\n};\n/**\n * Check whether the playlist is enabled or not.\n *\n * @param {Object} playlist the media playlist object\n * @return {boolean} whether the playlist is enabled or not\n * @function isEnabled\n */\n\nvar isEnabled = function isEnabled(playlist) {\n var blacklisted = isBlacklisted(playlist);\n return !playlist.disabled && !blacklisted;\n};\n/**\n * Check whether the playlist has been manually disabled through the representations api.\n *\n * @param {Object} playlist the media playlist object\n * @return {boolean} whether the playlist is disabled manually or not\n * @function isDisabled\n */\n\nvar isDisabled = function isDisabled(playlist) {\n return playlist.disabled;\n};\n/**\n * Returns whether the current playlist is an AES encrypted HLS stream\n *\n * @return {boolean} true if it's an AES encrypted HLS stream\n */\n\nvar isAes = function isAes(media) {\n for (var i = 0; i < media.segments.length; i++) {\n if (media.segments[i].key) {\n return true;\n }\n }\n\n return false;\n};\n/**\n * Checks if the playlist has a value for the specified attribute\n *\n * @param {string} attr\n * Attribute to check for\n * @param {Object} playlist\n * The media playlist object\n * @return {boolean}\n * Whether the playlist contains a value for the attribute or not\n * @function hasAttribute\n */\n\nvar hasAttribute = function hasAttribute(attr, playlist) {\n return playlist.attributes && playlist.attributes[attr];\n};\n/**\n * Estimates the time required to complete a segment download from the specified playlist\n *\n * @param {number} segmentDuration\n * Duration of requested segment\n * @param {number} bandwidth\n * Current measured bandwidth of the player\n * @param {Object} playlist\n * The media playlist object\n * @param {number=} bytesReceived\n * Number of bytes already received for the request. Defaults to 0\n * @return {number|NaN}\n * The estimated time to request the segment. NaN if bandwidth information for\n * the given playlist is unavailable\n * @function estimateSegmentRequestTime\n */\n\nvar estimateSegmentRequestTime = function estimateSegmentRequestTime(segmentDuration, bandwidth, playlist, bytesReceived) {\n if (bytesReceived === void 0) {\n bytesReceived = 0;\n }\n\n if (!hasAttribute('BANDWIDTH', playlist)) {\n return NaN;\n }\n\n var size = segmentDuration * playlist.attributes.BANDWIDTH;\n return (size - bytesReceived * 8) / bandwidth;\n};\n/*\n * Returns whether the current playlist is the lowest rendition\n *\n * @return {Boolean} true if on lowest rendition\n */\n\nvar isLowestEnabledRendition = function isLowestEnabledRendition(master, media) {\n if (master.playlists.length === 1) {\n return true;\n }\n\n var currentBandwidth = media.attributes.BANDWIDTH || Number.MAX_VALUE;\n return master.playlists.filter(function (playlist) {\n if (!isEnabled(playlist)) {\n return false;\n }\n\n return (playlist.attributes.BANDWIDTH || 0) < currentBandwidth;\n }).length === 0;\n};\nvar playlistMatch = function playlistMatch(a, b) {\n // both playlits are null\n // or only one playlist is non-null\n // no match\n if (!a && !b || !a && b || a && !b) {\n return false;\n } // playlist objects are the same, match\n\n\n if (a === b) {\n return true;\n } // first try to use id as it should be the most\n // accurate\n\n\n if (a.id && b.id && a.id === b.id) {\n return true;\n } // next try to use reslovedUri as it should be the\n // second most accurate.\n\n\n if (a.resolvedUri && b.resolvedUri && a.resolvedUri === b.resolvedUri) {\n return true;\n } // finally try to use uri as it should be accurate\n // but might miss a few cases for relative uris\n\n\n if (a.uri && b.uri && a.uri === b.uri) {\n return true;\n }\n\n return false;\n};\n\nvar someAudioVariant = function someAudioVariant(master, callback) {\n var AUDIO = master && master.mediaGroups && master.mediaGroups.AUDIO || {};\n var found = false;\n\n for (var groupName in AUDIO) {\n for (var label in AUDIO[groupName]) {\n found = callback(AUDIO[groupName][label]);\n\n if (found) {\n break;\n }\n }\n\n if (found) {\n break;\n }\n }\n\n return !!found;\n};\n\nvar isAudioOnly = function isAudioOnly(master) {\n // we are audio only if we have no main playlists but do\n // have media group playlists.\n if (!master || !master.playlists || !master.playlists.length) {\n // without audio variants or playlists this\n // is not an audio only master.\n var found = someAudioVariant(master, function (variant) {\n return variant.playlists && variant.playlists.length || variant.uri;\n });\n return found;\n } // if every playlist has only an audio codec it is audio only\n\n\n var _loop = function _loop(i) {\n var playlist = master.playlists[i];\n var CODECS = playlist.attributes && playlist.attributes.CODECS; // all codecs are audio, this is an audio playlist.\n\n if (CODECS && CODECS.split(',').every(function (c) {\n return isAudioCodec(c);\n })) {\n return \"continue\";\n } // playlist is in an audio group it is audio only\n\n\n var found = someAudioVariant(master, function (variant) {\n return playlistMatch(playlist, variant);\n });\n\n if (found) {\n return \"continue\";\n } // if we make it here this playlist isn't audio and we\n // are not audio only\n\n\n return {\n v: false\n };\n };\n\n for (var i = 0; i < master.playlists.length; i++) {\n var _ret = _loop(i);\n\n if (_ret === \"continue\") continue;\n if (typeof _ret === \"object\") return _ret.v;\n } // if we make it past every playlist without returning, then\n // this is an audio only playlist.\n\n\n return true;\n}; // exports\n\nvar Playlist = {\n liveEdgeDelay: liveEdgeDelay,\n duration: duration,\n seekable: seekable,\n getMediaInfoForTime: getMediaInfoForTime,\n isEnabled: isEnabled,\n isDisabled: isDisabled,\n isBlacklisted: isBlacklisted,\n isIncompatible: isIncompatible,\n playlistEnd: playlistEnd,\n isAes: isAes,\n hasAttribute: hasAttribute,\n estimateSegmentRequestTime: estimateSegmentRequestTime,\n isLowestEnabledRendition: isLowestEnabledRendition,\n isAudioOnly: isAudioOnly,\n playlistMatch: playlistMatch,\n segmentDurationWithParts: segmentDurationWithParts\n};\n\nvar log = videojs.log;\nvar createPlaylistID = function createPlaylistID(index, uri) {\n return index + \"-\" + uri;\n};\n/**\n * Parses a given m3u8 playlist\n *\n * @param {Function} [onwarn]\n * a function to call when the parser triggers a warning event.\n * @param {Function} [oninfo]\n * a function to call when the parser triggers an info event.\n * @param {string} manifestString\n * The downloaded manifest string\n * @param {Object[]} [customTagParsers]\n * An array of custom tag parsers for the m3u8-parser instance\n * @param {Object[]} [customTagMappers]\n * An array of custom tag mappers for the m3u8-parser instance\n * @param {boolean} [experimentalLLHLS=false]\n * Whether to keep ll-hls features in the manifest after parsing.\n * @return {Object}\n * The manifest object\n */\n\nvar parseManifest = function parseManifest(_ref) {\n var onwarn = _ref.onwarn,\n oninfo = _ref.oninfo,\n manifestString = _ref.manifestString,\n _ref$customTagParsers = _ref.customTagParsers,\n customTagParsers = _ref$customTagParsers === void 0 ? [] : _ref$customTagParsers,\n _ref$customTagMappers = _ref.customTagMappers,\n customTagMappers = _ref$customTagMappers === void 0 ? [] : _ref$customTagMappers,\n experimentalLLHLS = _ref.experimentalLLHLS;\n var parser = new Parser();\n\n if (onwarn) {\n parser.on('warn', onwarn);\n }\n\n if (oninfo) {\n parser.on('info', oninfo);\n }\n\n customTagParsers.forEach(function (customParser) {\n return parser.addParser(customParser);\n });\n customTagMappers.forEach(function (mapper) {\n return parser.addTagMapper(mapper);\n });\n parser.push(manifestString);\n parser.end();\n var manifest = parser.manifest; // remove llhls features from the parsed manifest\n // if we don't want llhls support.\n\n if (!experimentalLLHLS) {\n ['preloadSegment', 'skip', 'serverControl', 'renditionReports', 'partInf', 'partTargetDuration'].forEach(function (k) {\n if (manifest.hasOwnProperty(k)) {\n delete manifest[k];\n }\n });\n\n if (manifest.segments) {\n manifest.segments.forEach(function (segment) {\n ['parts', 'preloadHints'].forEach(function (k) {\n if (segment.hasOwnProperty(k)) {\n delete segment[k];\n }\n });\n });\n }\n }\n\n if (!manifest.targetDuration) {\n var targetDuration = 10;\n\n if (manifest.segments && manifest.segments.length) {\n targetDuration = manifest.segments.reduce(function (acc, s) {\n return Math.max(acc, s.duration);\n }, 0);\n }\n\n if (onwarn) {\n onwarn(\"manifest has no targetDuration defaulting to \" + targetDuration);\n }\n\n manifest.targetDuration = targetDuration;\n }\n\n var parts = getLastParts(manifest);\n\n if (parts.length && !manifest.partTargetDuration) {\n var partTargetDuration = parts.reduce(function (acc, p) {\n return Math.max(acc, p.duration);\n }, 0);\n\n if (onwarn) {\n onwarn(\"manifest has no partTargetDuration defaulting to \" + partTargetDuration);\n log.error('LL-HLS manifest has parts but lacks required #EXT-X-PART-INF:PART-TARGET value. See https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-09#section-4.4.3.7. Playback is not guaranteed.');\n }\n\n manifest.partTargetDuration = partTargetDuration;\n }\n\n return manifest;\n};\n/**\n * Loops through all supported media groups in master and calls the provided\n * callback for each group\n *\n * @param {Object} master\n * The parsed master manifest object\n * @param {Function} callback\n * Callback to call for each media group\n */\n\nvar forEachMediaGroup = function forEachMediaGroup(master, callback) {\n if (!master.mediaGroups) {\n return;\n }\n\n ['AUDIO', 'SUBTITLES'].forEach(function (mediaType) {\n if (!master.mediaGroups[mediaType]) {\n return;\n }\n\n for (var groupKey in master.mediaGroups[mediaType]) {\n for (var labelKey in master.mediaGroups[mediaType][groupKey]) {\n var mediaProperties = master.mediaGroups[mediaType][groupKey][labelKey];\n callback(mediaProperties, mediaType, groupKey, labelKey);\n }\n }\n });\n};\n/**\n * Adds properties and attributes to the playlist to keep consistent functionality for\n * playlists throughout VHS.\n *\n * @param {Object} config\n * Arguments object\n * @param {Object} config.playlist\n * The media playlist\n * @param {string} [config.uri]\n * The uri to the media playlist (if media playlist is not from within a master\n * playlist)\n * @param {string} id\n * ID to use for the playlist\n */\n\nvar setupMediaPlaylist = function setupMediaPlaylist(_ref2) {\n var playlist = _ref2.playlist,\n uri = _ref2.uri,\n id = _ref2.id;\n playlist.id = id;\n playlist.playlistErrors_ = 0;\n\n if (uri) {\n // For media playlists, m3u8-parser does not have access to a URI, as HLS media\n // playlists do not contain their own source URI, but one is needed for consistency in\n // VHS.\n playlist.uri = uri;\n } // For HLS master playlists, even though certain attributes MUST be defined, the\n // stream may still be played without them.\n // For HLS media playlists, m3u8-parser does not attach an attributes object to the\n // manifest.\n //\n // To avoid undefined reference errors through the project, and make the code easier\n // to write/read, add an empty attributes object for these cases.\n\n\n playlist.attributes = playlist.attributes || {};\n};\n/**\n * Adds ID, resolvedUri, and attributes properties to each playlist of the master, where\n * necessary. In addition, creates playlist IDs for each playlist and adds playlist ID to\n * playlist references to the playlists array.\n *\n * @param {Object} master\n * The master playlist\n */\n\nvar setupMediaPlaylists = function setupMediaPlaylists(master) {\n var i = master.playlists.length;\n\n while (i--) {\n var playlist = master.playlists[i];\n setupMediaPlaylist({\n playlist: playlist,\n id: createPlaylistID(i, playlist.uri)\n });\n playlist.resolvedUri = resolveUrl(master.uri, playlist.uri);\n master.playlists[playlist.id] = playlist; // URI reference added for backwards compatibility\n\n master.playlists[playlist.uri] = playlist; // Although the spec states an #EXT-X-STREAM-INF tag MUST have a BANDWIDTH attribute,\n // the stream can be played without it. Although an attributes property may have been\n // added to the playlist to prevent undefined references, issue a warning to fix the\n // manifest.\n\n if (!playlist.attributes.BANDWIDTH) {\n log.warn('Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.');\n }\n }\n};\n/**\n * Adds resolvedUri properties to each media group.\n *\n * @param {Object} master\n * The master playlist\n */\n\nvar resolveMediaGroupUris = function resolveMediaGroupUris(master) {\n forEachMediaGroup(master, function (properties) {\n if (properties.uri) {\n properties.resolvedUri = resolveUrl(master.uri, properties.uri);\n }\n });\n};\n/**\n * Creates a master playlist wrapper to insert a sole media playlist into.\n *\n * @param {Object} media\n * Media playlist\n * @param {string} uri\n * The media URI\n *\n * @return {Object}\n * Master playlist\n */\n\nvar masterForMedia = function masterForMedia(media, uri) {\n var id = createPlaylistID(0, uri);\n var master = {\n mediaGroups: {\n 'AUDIO': {},\n 'VIDEO': {},\n 'CLOSED-CAPTIONS': {},\n 'SUBTITLES': {}\n },\n uri: window$1.location.href,\n resolvedUri: window$1.location.href,\n playlists: [{\n uri: uri,\n id: id,\n resolvedUri: uri,\n // m3u8-parser does not attach an attributes property to media playlists so make\n // sure that the property is attached to avoid undefined reference errors\n attributes: {}\n }]\n }; // set up ID reference\n\n master.playlists[id] = master.playlists[0]; // URI reference added for backwards compatibility\n\n master.playlists[uri] = master.playlists[0];\n return master;\n};\n/**\n * Does an in-place update of the master manifest to add updated playlist URI references\n * as well as other properties needed by VHS that aren't included by the parser.\n *\n * @param {Object} master\n * Master manifest object\n * @param {string} uri\n * The source URI\n */\n\nvar addPropertiesToMaster = function addPropertiesToMaster(master, uri) {\n master.uri = uri;\n\n for (var i = 0; i < master.playlists.length; i++) {\n if (!master.playlists[i].uri) {\n // Set up phony URIs for the playlists since playlists are referenced by their URIs\n // throughout VHS, but some formats (e.g., DASH) don't have external URIs\n // TODO: consider adding dummy URIs in mpd-parser\n var phonyUri = \"placeholder-uri-\" + i;\n master.playlists[i].uri = phonyUri;\n }\n }\n\n var audioOnlyMaster = isAudioOnly(master);\n forEachMediaGroup(master, function (properties, mediaType, groupKey, labelKey) {\n var groupId = \"placeholder-uri-\" + mediaType + \"-\" + groupKey + \"-\" + labelKey; // add a playlist array under properties\n\n if (!properties.playlists || !properties.playlists.length) {\n // If the manifest is audio only and this media group does not have a uri, check\n // if the media group is located in the main list of playlists. If it is, don't add\n // placeholder properties as it shouldn't be considered an alternate audio track.\n if (audioOnlyMaster && mediaType === 'AUDIO' && !properties.uri) {\n for (var _i = 0; _i < master.playlists.length; _i++) {\n var p = master.playlists[_i];\n\n if (p.attributes && p.attributes.AUDIO && p.attributes.AUDIO === groupKey) {\n return;\n }\n }\n }\n\n properties.playlists = [_extends({}, properties)];\n }\n\n properties.playlists.forEach(function (p, i) {\n var id = createPlaylistID(i, groupId);\n\n if (p.uri) {\n p.resolvedUri = p.resolvedUri || resolveUrl(master.uri, p.uri);\n } else {\n // DEPRECATED, this has been added to prevent a breaking change.\n // previously we only ever had a single media group playlist, so\n // we mark the first playlist uri without prepending the index as we used to\n // ideally we would do all of the playlists the same way.\n p.uri = i === 0 ? groupId : id; // don't resolve a placeholder uri to an absolute url, just use\n // the placeholder again\n\n p.resolvedUri = p.uri;\n }\n\n p.id = p.id || id; // add an empty attributes object, all playlists are\n // expected to have this.\n\n p.attributes = p.attributes || {}; // setup ID and URI references (URI for backwards compatibility)\n\n master.playlists[p.id] = p;\n master.playlists[p.uri] = p;\n });\n });\n setupMediaPlaylists(master);\n resolveMediaGroupUris(master);\n};\n\nvar mergeOptions$2 = videojs.mergeOptions,\n EventTarget$1 = videojs.EventTarget;\n\nvar addLLHLSQueryDirectives = function addLLHLSQueryDirectives(uri, media) {\n if (media.endList || !media.serverControl) {\n return uri;\n }\n\n var parameters = {};\n\n if (media.serverControl.canBlockReload) {\n var preloadSegment = media.preloadSegment; // next msn is a zero based value, length is not.\n\n var nextMSN = media.mediaSequence + media.segments.length; // If preload segment has parts then it is likely\n // that we are going to request a part of that preload segment.\n // the logic below is used to determine that.\n\n if (preloadSegment) {\n var parts = preloadSegment.parts || []; // _HLS_part is a zero based index\n\n var nextPart = getKnownPartCount(media) - 1; // if nextPart is > -1 and not equal to just the\n // length of parts, then we know we had part preload hints\n // and we need to add the _HLS_part= query\n\n if (nextPart > -1 && nextPart !== parts.length - 1) {\n // add existing parts to our preload hints\n // eslint-disable-next-line\n parameters._HLS_part = nextPart;\n } // this if statement makes sure that we request the msn\n // of the preload segment if:\n // 1. the preload segment had parts (and was not yet a full segment)\n // but was added to our segments array\n // 2. the preload segment had preload hints for parts that are not in\n // the manifest yet.\n // in all other cases we want the segment after the preload segment\n // which will be given by using media.segments.length because it is 1 based\n // rather than 0 based.\n\n\n if (nextPart > -1 || parts.length) {\n nextMSN--;\n }\n } // add _HLS_msn= in front of any _HLS_part query\n // eslint-disable-next-line\n\n\n parameters._HLS_msn = nextMSN;\n }\n\n if (media.serverControl && media.serverControl.canSkipUntil) {\n // add _HLS_skip= infront of all other queries.\n // eslint-disable-next-line\n parameters._HLS_skip = media.serverControl.canSkipDateranges ? 'v2' : 'YES';\n }\n\n if (Object.keys(parameters).length) {\n var parsedUri = new window$1.URL(uri);\n ['_HLS_skip', '_HLS_msn', '_HLS_part'].forEach(function (name) {\n if (!parameters.hasOwnProperty(name)) {\n return;\n }\n\n parsedUri.searchParams.set(name, parameters[name]);\n });\n uri = parsedUri.toString();\n }\n\n return uri;\n};\n/**\n * Returns a new segment object with properties and\n * the parts array merged.\n *\n * @param {Object} a the old segment\n * @param {Object} b the new segment\n *\n * @return {Object} the merged segment\n */\n\n\nvar updateSegment = function updateSegment(a, b) {\n if (!a) {\n return b;\n }\n\n var result = mergeOptions$2(a, b); // if only the old segment has preload hints\n // and the new one does not, remove preload hints.\n\n if (a.preloadHints && !b.preloadHints) {\n delete result.preloadHints;\n } // if only the old segment has parts\n // then the parts are no longer valid\n\n\n if (a.parts && !b.parts) {\n delete result.parts; // if both segments have parts\n // copy part propeties from the old segment\n // to the new one.\n } else if (a.parts && b.parts) {\n for (var i = 0; i < b.parts.length; i++) {\n if (a.parts && a.parts[i]) {\n result.parts[i] = mergeOptions$2(a.parts[i], b.parts[i]);\n }\n }\n } // set skipped to false for segments that have\n // have had information merged from the old segment.\n\n\n if (!a.skipped && b.skipped) {\n result.skipped = false;\n } // set preload to false for segments that have\n // had information added in the new segment.\n\n\n if (a.preload && !b.preload) {\n result.preload = false;\n }\n\n return result;\n};\n/**\n * Returns a new array of segments that is the result of merging\n * properties from an older list of segments onto an updated\n * list. No properties on the updated playlist will be ovewritten.\n *\n * @param {Array} original the outdated list of segments\n * @param {Array} update the updated list of segments\n * @param {number=} offset the index of the first update\n * segment in the original segment list. For non-live playlists,\n * this should always be zero and does not need to be\n * specified. For live playlists, it should be the difference\n * between the media sequence numbers in the original and updated\n * playlists.\n * @return {Array} a list of merged segment objects\n */\n\nvar updateSegments = function updateSegments(original, update, offset) {\n var oldSegments = original.slice();\n var newSegments = update.slice();\n offset = offset || 0;\n var result = [];\n var currentMap;\n\n for (var newIndex = 0; newIndex < newSegments.length; newIndex++) {\n var oldSegment = oldSegments[newIndex + offset];\n var newSegment = newSegments[newIndex];\n\n if (oldSegment) {\n currentMap = oldSegment.map || currentMap;\n result.push(updateSegment(oldSegment, newSegment));\n } else {\n // carry over map to new segment if it is missing\n if (currentMap && !newSegment.map) {\n newSegment.map = currentMap;\n }\n\n result.push(newSegment);\n }\n }\n\n return result;\n};\nvar resolveSegmentUris = function resolveSegmentUris(segment, baseUri) {\n // preloadSegment will not have a uri at all\n // as the segment isn't actually in the manifest yet, only parts\n if (!segment.resolvedUri && segment.uri) {\n segment.resolvedUri = resolveUrl(baseUri, segment.uri);\n }\n\n if (segment.key && !segment.key.resolvedUri) {\n segment.key.resolvedUri = resolveUrl(baseUri, segment.key.uri);\n }\n\n if (segment.map && !segment.map.resolvedUri) {\n segment.map.resolvedUri = resolveUrl(baseUri, segment.map.uri);\n }\n\n if (segment.map && segment.map.key && !segment.map.key.resolvedUri) {\n segment.map.key.resolvedUri = resolveUrl(baseUri, segment.map.key.uri);\n }\n\n if (segment.parts && segment.parts.length) {\n segment.parts.forEach(function (p) {\n if (p.resolvedUri) {\n return;\n }\n\n p.resolvedUri = resolveUrl(baseUri, p.uri);\n });\n }\n\n if (segment.preloadHints && segment.preloadHints.length) {\n segment.preloadHints.forEach(function (p) {\n if (p.resolvedUri) {\n return;\n }\n\n p.resolvedUri = resolveUrl(baseUri, p.uri);\n });\n }\n};\n\nvar getAllSegments = function getAllSegments(media) {\n var segments = media.segments || [];\n var preloadSegment = media.preloadSegment; // a preloadSegment with only preloadHints is not currently\n // a usable segment, only include a preloadSegment that has\n // parts.\n\n if (preloadSegment && preloadSegment.parts && preloadSegment.parts.length) {\n // if preloadHints has a MAP that means that the\n // init segment is going to change. We cannot use any of the parts\n // from this preload segment.\n if (preloadSegment.preloadHints) {\n for (var i = 0; i < preloadSegment.preloadHints.length; i++) {\n if (preloadSegment.preloadHints[i].type === 'MAP') {\n return segments;\n }\n }\n } // set the duration for our preload segment to target duration.\n\n\n preloadSegment.duration = media.targetDuration;\n preloadSegment.preload = true;\n segments.push(preloadSegment);\n }\n\n return segments;\n}; // consider the playlist unchanged if the playlist object is the same or\n// the number of segments is equal, the media sequence number is unchanged,\n// and this playlist hasn't become the end of the playlist\n\n\nvar isPlaylistUnchanged = function isPlaylistUnchanged(a, b) {\n return a === b || a.segments && b.segments && a.segments.length === b.segments.length && a.endList === b.endList && a.mediaSequence === b.mediaSequence && a.preloadSegment === b.preloadSegment;\n};\n/**\n * Returns a new master playlist that is the result of merging an\n * updated media playlist into the original version. If the\n * updated media playlist does not match any of the playlist\n * entries in the original master playlist, null is returned.\n *\n * @param {Object} master a parsed master M3U8 object\n * @param {Object} media a parsed media M3U8 object\n * @return {Object} a new object that represents the original\n * master playlist with the updated media playlist merged in, or\n * null if the merge produced no change.\n */\n\nvar updateMaster$1 = function updateMaster(master, newMedia, unchangedCheck) {\n if (unchangedCheck === void 0) {\n unchangedCheck = isPlaylistUnchanged;\n }\n\n var result = mergeOptions$2(master, {});\n var oldMedia = result.playlists[newMedia.id];\n\n if (!oldMedia) {\n return null;\n }\n\n if (unchangedCheck(oldMedia, newMedia)) {\n return null;\n }\n\n newMedia.segments = getAllSegments(newMedia);\n var mergedPlaylist = mergeOptions$2(oldMedia, newMedia); // always use the new media's preload segment\n\n if (mergedPlaylist.preloadSegment && !newMedia.preloadSegment) {\n delete mergedPlaylist.preloadSegment;\n } // if the update could overlap existing segment information, merge the two segment lists\n\n\n if (oldMedia.segments) {\n if (newMedia.skip) {\n newMedia.segments = newMedia.segments || []; // add back in objects for skipped segments, so that we merge\n // old properties into the new segments\n\n for (var i = 0; i < newMedia.skip.skippedSegments; i++) {\n newMedia.segments.unshift({\n skipped: true\n });\n }\n }\n\n mergedPlaylist.segments = updateSegments(oldMedia.segments, newMedia.segments, newMedia.mediaSequence - oldMedia.mediaSequence);\n } // resolve any segment URIs to prevent us from having to do it later\n\n\n mergedPlaylist.segments.forEach(function (segment) {\n resolveSegmentUris(segment, mergedPlaylist.resolvedUri);\n }); // TODO Right now in the playlists array there are two references to each playlist, one\n // that is referenced by index, and one by URI. The index reference may no longer be\n // necessary.\n\n for (var _i = 0; _i < result.playlists.length; _i++) {\n if (result.playlists[_i].id === newMedia.id) {\n result.playlists[_i] = mergedPlaylist;\n }\n }\n\n result.playlists[newMedia.id] = mergedPlaylist; // URI reference added for backwards compatibility\n\n result.playlists[newMedia.uri] = mergedPlaylist; // update media group playlist references.\n\n forEachMediaGroup(master, function (properties, mediaType, groupKey, labelKey) {\n if (!properties.playlists) {\n return;\n }\n\n for (var _i2 = 0; _i2 < properties.playlists.length; _i2++) {\n if (newMedia.id === properties.playlists[_i2].id) {\n properties.playlists[_i2] = newMedia;\n }\n }\n });\n return result;\n};\n/**\n * Calculates the time to wait before refreshing a live playlist\n *\n * @param {Object} media\n * The current media\n * @param {boolean} update\n * True if there were any updates from the last refresh, false otherwise\n * @return {number}\n * The time in ms to wait before refreshing the live playlist\n */\n\nvar refreshDelay = function refreshDelay(media, update) {\n var segments = media.segments || [];\n var lastSegment = segments[segments.length - 1];\n var lastPart = lastSegment && lastSegment.parts && lastSegment.parts[lastSegment.parts.length - 1];\n var lastDuration = lastPart && lastPart.duration || lastSegment && lastSegment.duration;\n\n if (update && lastDuration) {\n return lastDuration * 1000;\n } // if the playlist is unchanged since the last reload or last segment duration\n // cannot be determined, try again after half the target duration\n\n\n return (media.partTargetDuration || media.targetDuration || 10) * 500;\n};\n/**\n * Load a playlist from a remote location\n *\n * @class PlaylistLoader\n * @extends Stream\n * @param {string|Object} src url or object of manifest\n * @param {boolean} withCredentials the withCredentials xhr option\n * @class\n */\n\nvar PlaylistLoader = /*#__PURE__*/function (_EventTarget) {\n _inheritsLoose(PlaylistLoader, _EventTarget);\n\n function PlaylistLoader(src, vhs, options) {\n var _this;\n\n if (options === void 0) {\n options = {};\n }\n\n _this = _EventTarget.call(this) || this;\n\n if (!src) {\n throw new Error('A non-empty playlist URL or object is required');\n }\n\n _this.logger_ = logger('PlaylistLoader');\n var _options = options,\n _options$withCredenti = _options.withCredentials,\n withCredentials = _options$withCredenti === void 0 ? false : _options$withCredenti,\n _options$handleManife = _options.handleManifestRedirects,\n handleManifestRedirects = _options$handleManife === void 0 ? false : _options$handleManife;\n _this.src = src;\n _this.vhs_ = vhs;\n _this.withCredentials = withCredentials;\n _this.handleManifestRedirects = handleManifestRedirects;\n var vhsOptions = vhs.options_;\n _this.customTagParsers = vhsOptions && vhsOptions.customTagParsers || [];\n _this.customTagMappers = vhsOptions && vhsOptions.customTagMappers || [];\n _this.experimentalLLHLS = vhsOptions && vhsOptions.experimentalLLHLS || false; // force experimentalLLHLS for IE 11\n\n if (videojs.browser.IE_VERSION) {\n _this.experimentalLLHLS = false;\n } // initialize the loader state\n\n\n _this.state = 'HAVE_NOTHING'; // live playlist staleness timeout\n\n _this.handleMediaupdatetimeout_ = _this.handleMediaupdatetimeout_.bind(_assertThisInitialized(_this));\n\n _this.on('mediaupdatetimeout', _this.handleMediaupdatetimeout_);\n\n return _this;\n }\n\n var _proto = PlaylistLoader.prototype;\n\n _proto.handleMediaupdatetimeout_ = function handleMediaupdatetimeout_() {\n var _this2 = this;\n\n if (this.state !== 'HAVE_METADATA') {\n // only refresh the media playlist if no other activity is going on\n return;\n }\n\n var media = this.media();\n var uri = resolveUrl(this.master.uri, media.uri);\n\n if (this.experimentalLLHLS) {\n uri = addLLHLSQueryDirectives(uri, media);\n }\n\n this.state = 'HAVE_CURRENT_METADATA';\n this.request = this.vhs_.xhr({\n uri: uri,\n withCredentials: this.withCredentials\n }, function (error, req) {\n // disposed\n if (!_this2.request) {\n return;\n }\n\n if (error) {\n return _this2.playlistRequestError(_this2.request, _this2.media(), 'HAVE_METADATA');\n }\n\n _this2.haveMetadata({\n playlistString: _this2.request.responseText,\n url: _this2.media().uri,\n id: _this2.media().id\n });\n });\n };\n\n _proto.playlistRequestError = function playlistRequestError(xhr, playlist, startingState) {\n var uri = playlist.uri,\n id = playlist.id; // any in-flight request is now finished\n\n this.request = null;\n\n if (startingState) {\n this.state = startingState;\n }\n\n this.error = {\n playlist: this.master.playlists[id],\n status: xhr.status,\n message: \"HLS playlist request error at URL: \" + uri + \".\",\n responseText: xhr.responseText,\n code: xhr.status >= 500 ? 4 : 2\n };\n this.trigger('error');\n };\n\n _proto.parseManifest_ = function parseManifest_(_ref) {\n var _this3 = this;\n\n var url = _ref.url,\n manifestString = _ref.manifestString;\n return parseManifest({\n onwarn: function onwarn(_ref2) {\n var message = _ref2.message;\n return _this3.logger_(\"m3u8-parser warn for \" + url + \": \" + message);\n },\n oninfo: function oninfo(_ref3) {\n var message = _ref3.message;\n return _this3.logger_(\"m3u8-parser info for \" + url + \": \" + message);\n },\n manifestString: manifestString,\n customTagParsers: this.customTagParsers,\n customTagMappers: this.customTagMappers,\n experimentalLLHLS: this.experimentalLLHLS\n });\n }\n /**\n * Update the playlist loader's state in response to a new or updated playlist.\n *\n * @param {string} [playlistString]\n * Playlist string (if playlistObject is not provided)\n * @param {Object} [playlistObject]\n * Playlist object (if playlistString is not provided)\n * @param {string} url\n * URL of playlist\n * @param {string} id\n * ID to use for playlist\n */\n ;\n\n _proto.haveMetadata = function haveMetadata(_ref4) {\n var playlistString = _ref4.playlistString,\n playlistObject = _ref4.playlistObject,\n url = _ref4.url,\n id = _ref4.id;\n // any in-flight request is now finished\n this.request = null;\n this.state = 'HAVE_METADATA';\n var playlist = playlistObject || this.parseManifest_({\n url: url,\n manifestString: playlistString\n });\n playlist.lastRequest = Date.now();\n setupMediaPlaylist({\n playlist: playlist,\n uri: url,\n id: id\n }); // merge this playlist into the master\n\n var update = updateMaster$1(this.master, playlist);\n this.targetDuration = playlist.partTargetDuration || playlist.targetDuration;\n this.pendingMedia_ = null;\n\n if (update) {\n this.master = update;\n this.media_ = this.master.playlists[id];\n } else {\n this.trigger('playlistunchanged');\n }\n\n this.updateMediaUpdateTimeout_(refreshDelay(this.media(), !!update));\n this.trigger('loadedplaylist');\n }\n /**\n * Abort any outstanding work and clean up.\n */\n ;\n\n _proto.dispose = function dispose() {\n this.trigger('dispose');\n this.stopRequest();\n window$1.clearTimeout(this.mediaUpdateTimeout);\n window$1.clearTimeout(this.finalRenditionTimeout);\n this.off();\n };\n\n _proto.stopRequest = function stopRequest() {\n if (this.request) {\n var oldRequest = this.request;\n this.request = null;\n oldRequest.onreadystatechange = null;\n oldRequest.abort();\n }\n }\n /**\n * When called without any arguments, returns the currently\n * active media playlist. When called with a single argument,\n * triggers the playlist loader to asynchronously switch to the\n * specified media playlist. Calling this method while the\n * loader is in the HAVE_NOTHING causes an error to be emitted\n * but otherwise has no effect.\n *\n * @param {Object=} playlist the parsed media playlist\n * object to switch to\n * @param {boolean=} shouldDelay whether we should delay the request by half target duration\n *\n * @return {Playlist} the current loaded media\n */\n ;\n\n _proto.media = function media(playlist, shouldDelay) {\n var _this4 = this;\n\n // getter\n if (!playlist) {\n return this.media_;\n } // setter\n\n\n if (this.state === 'HAVE_NOTHING') {\n throw new Error('Cannot switch media playlist from ' + this.state);\n } // find the playlist object if the target playlist has been\n // specified by URI\n\n\n if (typeof playlist === 'string') {\n if (!this.master.playlists[playlist]) {\n throw new Error('Unknown playlist URI: ' + playlist);\n }\n\n playlist = this.master.playlists[playlist];\n }\n\n window$1.clearTimeout(this.finalRenditionTimeout);\n\n if (shouldDelay) {\n var delay = (playlist.partTargetDuration || playlist.targetDuration) / 2 * 1000 || 5 * 1000;\n this.finalRenditionTimeout = window$1.setTimeout(this.media.bind(this, playlist, false), delay);\n return;\n }\n\n var startingState = this.state;\n var mediaChange = !this.media_ || playlist.id !== this.media_.id;\n var masterPlaylistRef = this.master.playlists[playlist.id]; // switch to fully loaded playlists immediately\n\n if (masterPlaylistRef && masterPlaylistRef.endList || // handle the case of a playlist object (e.g., if using vhs-json with a resolved\n // media playlist or, for the case of demuxed audio, a resolved audio media group)\n playlist.endList && playlist.segments.length) {\n // abort outstanding playlist requests\n if (this.request) {\n this.request.onreadystatechange = null;\n this.request.abort();\n this.request = null;\n }\n\n this.state = 'HAVE_METADATA';\n this.media_ = playlist; // trigger media change if the active media has been updated\n\n if (mediaChange) {\n this.trigger('mediachanging');\n\n if (startingState === 'HAVE_MASTER') {\n // The initial playlist was a master manifest, and the first media selected was\n // also provided (in the form of a resolved playlist object) as part of the\n // source object (rather than just a URL). Therefore, since the media playlist\n // doesn't need to be requested, loadedmetadata won't trigger as part of the\n // normal flow, and needs an explicit trigger here.\n this.trigger('loadedmetadata');\n } else {\n this.trigger('mediachange');\n }\n }\n\n return;\n } // We update/set the timeout here so that live playlists\n // that are not a media change will \"start\" the loader as expected.\n // We expect that this function will start the media update timeout\n // cycle again. This also prevents a playlist switch failure from\n // causing us to stall during live.\n\n\n this.updateMediaUpdateTimeout_(refreshDelay(playlist, true)); // switching to the active playlist is a no-op\n\n if (!mediaChange) {\n return;\n }\n\n this.state = 'SWITCHING_MEDIA'; // there is already an outstanding playlist request\n\n if (this.request) {\n if (playlist.resolvedUri === this.request.url) {\n // requesting to switch to the same playlist multiple times\n // has no effect after the first\n return;\n }\n\n this.request.onreadystatechange = null;\n this.request.abort();\n this.request = null;\n } // request the new playlist\n\n\n if (this.media_) {\n this.trigger('mediachanging');\n }\n\n this.pendingMedia_ = playlist;\n this.request = this.vhs_.xhr({\n uri: playlist.resolvedUri,\n withCredentials: this.withCredentials\n }, function (error, req) {\n // disposed\n if (!_this4.request) {\n return;\n }\n\n playlist.lastRequest = Date.now();\n playlist.resolvedUri = resolveManifestRedirect(_this4.handleManifestRedirects, playlist.resolvedUri, req);\n\n if (error) {\n return _this4.playlistRequestError(_this4.request, playlist, startingState);\n }\n\n _this4.haveMetadata({\n playlistString: req.responseText,\n url: playlist.uri,\n id: playlist.id\n }); // fire loadedmetadata the first time a media playlist is loaded\n\n\n if (startingState === 'HAVE_MASTER') {\n _this4.trigger('loadedmetadata');\n } else {\n _this4.trigger('mediachange');\n }\n });\n }\n /**\n * pause loading of the playlist\n */\n ;\n\n _proto.pause = function pause() {\n if (this.mediaUpdateTimeout) {\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n }\n\n this.stopRequest();\n\n if (this.state === 'HAVE_NOTHING') {\n // If we pause the loader before any data has been retrieved, its as if we never\n // started, so reset to an unstarted state.\n this.started = false;\n } // Need to restore state now that no activity is happening\n\n\n if (this.state === 'SWITCHING_MEDIA') {\n // if the loader was in the process of switching media, it should either return to\n // HAVE_MASTER or HAVE_METADATA depending on if the loader has loaded a media\n // playlist yet. This is determined by the existence of loader.media_\n if (this.media_) {\n this.state = 'HAVE_METADATA';\n } else {\n this.state = 'HAVE_MASTER';\n }\n } else if (this.state === 'HAVE_CURRENT_METADATA') {\n this.state = 'HAVE_METADATA';\n }\n }\n /**\n * start loading of the playlist\n */\n ;\n\n _proto.load = function load(shouldDelay) {\n var _this5 = this;\n\n if (this.mediaUpdateTimeout) {\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n }\n\n var media = this.media();\n\n if (shouldDelay) {\n var delay = media ? (media.partTargetDuration || media.targetDuration) / 2 * 1000 : 5 * 1000;\n this.mediaUpdateTimeout = window$1.setTimeout(function () {\n _this5.mediaUpdateTimeout = null;\n\n _this5.load();\n }, delay);\n return;\n }\n\n if (!this.started) {\n this.start();\n return;\n }\n\n if (media && !media.endList) {\n this.trigger('mediaupdatetimeout');\n } else {\n this.trigger('loadedplaylist');\n }\n };\n\n _proto.updateMediaUpdateTimeout_ = function updateMediaUpdateTimeout_(delay) {\n var _this6 = this;\n\n if (this.mediaUpdateTimeout) {\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n } // we only have use mediaupdatetimeout for live playlists.\n\n\n if (!this.media() || this.media().endList) {\n return;\n }\n\n this.mediaUpdateTimeout = window$1.setTimeout(function () {\n _this6.mediaUpdateTimeout = null;\n\n _this6.trigger('mediaupdatetimeout');\n\n _this6.updateMediaUpdateTimeout_(delay);\n }, delay);\n }\n /**\n * start loading of the playlist\n */\n ;\n\n _proto.start = function start() {\n var _this7 = this;\n\n this.started = true;\n\n if (typeof this.src === 'object') {\n // in the case of an entirely constructed manifest object (meaning there's no actual\n // manifest on a server), default the uri to the page's href\n if (!this.src.uri) {\n this.src.uri = window$1.location.href;\n } // resolvedUri is added on internally after the initial request. Since there's no\n // request for pre-resolved manifests, add on resolvedUri here.\n\n\n this.src.resolvedUri = this.src.uri; // Since a manifest object was passed in as the source (instead of a URL), the first\n // request can be skipped (since the top level of the manifest, at a minimum, is\n // already available as a parsed manifest object). However, if the manifest object\n // represents a master playlist, some media playlists may need to be resolved before\n // the starting segment list is available. Therefore, go directly to setup of the\n // initial playlist, and let the normal flow continue from there.\n //\n // Note that the call to setup is asynchronous, as other sections of VHS may assume\n // that the first request is asynchronous.\n\n setTimeout(function () {\n _this7.setupInitialPlaylist(_this7.src);\n }, 0);\n return;\n } // request the specified URL\n\n\n this.request = this.vhs_.xhr({\n uri: this.src,\n withCredentials: this.withCredentials\n }, function (error, req) {\n // disposed\n if (!_this7.request) {\n return;\n } // clear the loader's request reference\n\n\n _this7.request = null;\n\n if (error) {\n _this7.error = {\n status: req.status,\n message: \"HLS playlist request error at URL: \" + _this7.src + \".\",\n responseText: req.responseText,\n // MEDIA_ERR_NETWORK\n code: 2\n };\n\n if (_this7.state === 'HAVE_NOTHING') {\n _this7.started = false;\n }\n\n return _this7.trigger('error');\n }\n\n _this7.src = resolveManifestRedirect(_this7.handleManifestRedirects, _this7.src, req);\n\n var manifest = _this7.parseManifest_({\n manifestString: req.responseText,\n url: _this7.src\n });\n\n _this7.setupInitialPlaylist(manifest);\n });\n };\n\n _proto.srcUri = function srcUri() {\n return typeof this.src === 'string' ? this.src : this.src.uri;\n }\n /**\n * Given a manifest object that's either a master or media playlist, trigger the proper\n * events and set the state of the playlist loader.\n *\n * If the manifest object represents a master playlist, `loadedplaylist` will be\n * triggered to allow listeners to select a playlist. If none is selected, the loader\n * will default to the first one in the playlists array.\n *\n * If the manifest object represents a media playlist, `loadedplaylist` will be\n * triggered followed by `loadedmetadata`, as the only available playlist is loaded.\n *\n * In the case of a media playlist, a master playlist object wrapper with one playlist\n * will be created so that all logic can handle playlists in the same fashion (as an\n * assumed manifest object schema).\n *\n * @param {Object} manifest\n * The parsed manifest object\n */\n ;\n\n _proto.setupInitialPlaylist = function setupInitialPlaylist(manifest) {\n this.state = 'HAVE_MASTER';\n\n if (manifest.playlists) {\n this.master = manifest;\n addPropertiesToMaster(this.master, this.srcUri()); // If the initial master playlist has playlists wtih segments already resolved,\n // then resolve URIs in advance, as they are usually done after a playlist request,\n // which may not happen if the playlist is resolved.\n\n manifest.playlists.forEach(function (playlist) {\n playlist.segments = getAllSegments(playlist);\n playlist.segments.forEach(function (segment) {\n resolveSegmentUris(segment, playlist.resolvedUri);\n });\n });\n this.trigger('loadedplaylist');\n\n if (!this.request) {\n // no media playlist was specifically selected so start\n // from the first listed one\n this.media(this.master.playlists[0]);\n }\n\n return;\n } // In order to support media playlists passed in as vhs-json, the case where the uri\n // is not provided as part of the manifest should be considered, and an appropriate\n // default used.\n\n\n var uri = this.srcUri() || window$1.location.href;\n this.master = masterForMedia(manifest, uri);\n this.haveMetadata({\n playlistObject: manifest,\n url: uri,\n id: this.master.playlists[0].id\n });\n this.trigger('loadedmetadata');\n };\n\n return PlaylistLoader;\n}(EventTarget$1);\n\n/**\n * @file xhr.js\n */\nvar videojsXHR = videojs.xhr,\n mergeOptions$1 = videojs.mergeOptions;\n\nvar callbackWrapper = function callbackWrapper(request, error, response, callback) {\n var reqResponse = request.responseType === 'arraybuffer' ? request.response : request.responseText;\n\n if (!error && reqResponse) {\n request.responseTime = Date.now();\n request.roundTripTime = request.responseTime - request.requestTime;\n request.bytesReceived = reqResponse.byteLength || reqResponse.length;\n\n if (!request.bandwidth) {\n request.bandwidth = Math.floor(request.bytesReceived / request.roundTripTime * 8 * 1000);\n }\n }\n\n if (response.headers) {\n request.responseHeaders = response.headers;\n } // videojs.xhr now uses a specific code on the error\n // object to signal that a request has timed out instead\n // of setting a boolean on the request object\n\n\n if (error && error.code === 'ETIMEDOUT') {\n request.timedout = true;\n } // videojs.xhr no longer considers status codes outside of 200 and 0\n // (for file uris) to be errors, but the old XHR did, so emulate that\n // behavior. Status 206 may be used in response to byterange requests.\n\n\n if (!error && !request.aborted && response.statusCode !== 200 && response.statusCode !== 206 && response.statusCode !== 0) {\n error = new Error('XHR Failed with a response of: ' + (request && (reqResponse || request.responseText)));\n }\n\n callback(error, request);\n};\n\nvar xhrFactory = function xhrFactory() {\n var xhr = function XhrFunction(options, callback) {\n // Add a default timeout\n options = mergeOptions$1({\n timeout: 45e3\n }, options); // Allow an optional user-specified function to modify the option\n // object before we construct the xhr request\n\n var beforeRequest = XhrFunction.beforeRequest || videojs.Vhs.xhr.beforeRequest;\n\n if (beforeRequest && typeof beforeRequest === 'function') {\n var newOptions = beforeRequest(options);\n\n if (newOptions) {\n options = newOptions;\n }\n } // Use the standard videojs.xhr() method unless `videojs.Vhs.xhr` has been overriden\n // TODO: switch back to videojs.Vhs.xhr.name === 'XhrFunction' when we drop IE11\n\n\n var xhrMethod = videojs.Vhs.xhr.original === true ? videojsXHR : videojs.Vhs.xhr;\n var request = xhrMethod(options, function (error, response) {\n return callbackWrapper(request, error, response, callback);\n });\n var originalAbort = request.abort;\n\n request.abort = function () {\n request.aborted = true;\n return originalAbort.apply(request, arguments);\n };\n\n request.uri = options.uri;\n request.requestTime = Date.now();\n return request;\n };\n\n xhr.original = true;\n return xhr;\n};\n/**\n * Turns segment byterange into a string suitable for use in\n * HTTP Range requests\n *\n * @param {Object} byterange - an object with two values defining the start and end\n * of a byte-range\n */\n\n\nvar byterangeStr = function byterangeStr(byterange) {\n // `byterangeEnd` is one less than `offset + length` because the HTTP range\n // header uses inclusive ranges\n var byterangeEnd;\n var byterangeStart = byterange.offset;\n\n if (typeof byterange.offset === 'bigint' || typeof byterange.length === 'bigint') {\n byterangeEnd = window$1.BigInt(byterange.offset) + window$1.BigInt(byterange.length) - window$1.BigInt(1);\n } else {\n byterangeEnd = byterange.offset + byterange.length - 1;\n }\n\n return 'bytes=' + byterangeStart + '-' + byterangeEnd;\n};\n/**\n * Defines headers for use in the xhr request for a particular segment.\n *\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n */\n\nvar segmentXhrHeaders = function segmentXhrHeaders(segment) {\n var headers = {};\n\n if (segment.byterange) {\n headers.Range = byterangeStr(segment.byterange);\n }\n\n return headers;\n};\n\n/**\n * @file bin-utils.js\n */\n\n/**\n * convert a TimeRange to text\n *\n * @param {TimeRange} range the timerange to use for conversion\n * @param {number} i the iterator on the range to convert\n * @return {string} the range in string format\n */\nvar textRange = function textRange(range, i) {\n return range.start(i) + '-' + range.end(i);\n};\n/**\n * format a number as hex string\n *\n * @param {number} e The number\n * @param {number} i the iterator\n * @return {string} the hex formatted number as a string\n */\n\n\nvar formatHexString = function formatHexString(e, i) {\n var value = e.toString(16);\n return '00'.substring(0, 2 - value.length) + value + (i % 2 ? ' ' : '');\n};\n\nvar formatAsciiString = function formatAsciiString(e) {\n if (e >= 0x20 && e < 0x7e) {\n return String.fromCharCode(e);\n }\n\n return '.';\n};\n/**\n * Creates an object for sending to a web worker modifying properties that are TypedArrays\n * into a new object with seperated properties for the buffer, byteOffset, and byteLength.\n *\n * @param {Object} message\n * Object of properties and values to send to the web worker\n * @return {Object}\n * Modified message with TypedArray values expanded\n * @function createTransferableMessage\n */\n\n\nvar createTransferableMessage = function createTransferableMessage(message) {\n var transferable = {};\n Object.keys(message).forEach(function (key) {\n var value = message[key];\n\n if (ArrayBuffer.isView(value)) {\n transferable[key] = {\n bytes: value.buffer,\n byteOffset: value.byteOffset,\n byteLength: value.byteLength\n };\n } else {\n transferable[key] = value;\n }\n });\n return transferable;\n};\n/**\n * Returns a unique string identifier for a media initialization\n * segment.\n *\n * @param {Object} initSegment\n * the init segment object.\n *\n * @return {string} the generated init segment id\n */\n\nvar initSegmentId = function initSegmentId(initSegment) {\n var byterange = initSegment.byterange || {\n length: Infinity,\n offset: 0\n };\n return [byterange.length, byterange.offset, initSegment.resolvedUri].join(',');\n};\n/**\n * Returns a unique string identifier for a media segment key.\n *\n * @param {Object} key the encryption key\n * @return {string} the unique id for the media segment key.\n */\n\nvar segmentKeyId = function segmentKeyId(key) {\n return key.resolvedUri;\n};\n/**\n * utils to help dump binary data to the console\n *\n * @param {Array|TypedArray} data\n * data to dump to a string\n *\n * @return {string} the data as a hex string.\n */\n\nvar hexDump = function hexDump(data) {\n var bytes = Array.prototype.slice.call(data);\n var step = 16;\n var result = '';\n var hex;\n var ascii;\n\n for (var j = 0; j < bytes.length / step; j++) {\n hex = bytes.slice(j * step, j * step + step).map(formatHexString).join('');\n ascii = bytes.slice(j * step, j * step + step).map(formatAsciiString).join('');\n result += hex + ' ' + ascii + '\\n';\n }\n\n return result;\n};\nvar tagDump = function tagDump(_ref) {\n var bytes = _ref.bytes;\n return hexDump(bytes);\n};\nvar textRanges = function textRanges(ranges) {\n var result = '';\n var i;\n\n for (i = 0; i < ranges.length; i++) {\n result += textRange(ranges, i) + ' ';\n }\n\n return result;\n};\n\nvar utils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createTransferableMessage: createTransferableMessage,\n initSegmentId: initSegmentId,\n segmentKeyId: segmentKeyId,\n hexDump: hexDump,\n tagDump: tagDump,\n textRanges: textRanges\n});\n\n// TODO handle fmp4 case where the timing info is accurate and doesn't involve transmux\n// 25% was arbitrarily chosen, and may need to be refined over time.\n\nvar SEGMENT_END_FUDGE_PERCENT = 0.25;\n/**\n * Converts a player time (any time that can be gotten/set from player.currentTime(),\n * e.g., any time within player.seekable().start(0) to player.seekable().end(0)) to a\n * program time (any time referencing the real world (e.g., EXT-X-PROGRAM-DATE-TIME)).\n *\n * The containing segment is required as the EXT-X-PROGRAM-DATE-TIME serves as an \"anchor\n * point\" (a point where we have a mapping from program time to player time, with player\n * time being the post transmux start of the segment).\n *\n * For more details, see [this doc](../../docs/program-time-from-player-time.md).\n *\n * @param {number} playerTime the player time\n * @param {Object} segment the segment which contains the player time\n * @return {Date} program time\n */\n\nvar playerTimeToProgramTime = function playerTimeToProgramTime(playerTime, segment) {\n if (!segment.dateTimeObject) {\n // Can't convert without an \"anchor point\" for the program time (i.e., a time that can\n // be used to map the start of a segment with a real world time).\n return null;\n }\n\n var transmuxerPrependedSeconds = segment.videoTimingInfo.transmuxerPrependedSeconds;\n var transmuxedStart = segment.videoTimingInfo.transmuxedPresentationStart; // get the start of the content from before old content is prepended\n\n var startOfSegment = transmuxedStart + transmuxerPrependedSeconds;\n var offsetFromSegmentStart = playerTime - startOfSegment;\n return new Date(segment.dateTimeObject.getTime() + offsetFromSegmentStart * 1000);\n};\nvar originalSegmentVideoDuration = function originalSegmentVideoDuration(videoTimingInfo) {\n return videoTimingInfo.transmuxedPresentationEnd - videoTimingInfo.transmuxedPresentationStart - videoTimingInfo.transmuxerPrependedSeconds;\n};\n/**\n * Finds a segment that contains the time requested given as an ISO-8601 string. The\n * returned segment might be an estimate or an accurate match.\n *\n * @param {string} programTime The ISO-8601 programTime to find a match for\n * @param {Object} playlist A playlist object to search within\n */\n\nvar findSegmentForProgramTime = function findSegmentForProgramTime(programTime, playlist) {\n // Assumptions:\n // - verifyProgramDateTimeTags has already been run\n // - live streams have been started\n var dateTimeObject;\n\n try {\n dateTimeObject = new Date(programTime);\n } catch (e) {\n return null;\n }\n\n if (!playlist || !playlist.segments || playlist.segments.length === 0) {\n return null;\n }\n\n var segment = playlist.segments[0];\n\n if (dateTimeObject < segment.dateTimeObject) {\n // Requested time is before stream start.\n return null;\n }\n\n for (var i = 0; i < playlist.segments.length - 1; i++) {\n segment = playlist.segments[i];\n var nextSegmentStart = playlist.segments[i + 1].dateTimeObject;\n\n if (dateTimeObject < nextSegmentStart) {\n break;\n }\n }\n\n var lastSegment = playlist.segments[playlist.segments.length - 1];\n var lastSegmentStart = lastSegment.dateTimeObject;\n var lastSegmentDuration = lastSegment.videoTimingInfo ? originalSegmentVideoDuration(lastSegment.videoTimingInfo) : lastSegment.duration + lastSegment.duration * SEGMENT_END_FUDGE_PERCENT;\n var lastSegmentEnd = new Date(lastSegmentStart.getTime() + lastSegmentDuration * 1000);\n\n if (dateTimeObject > lastSegmentEnd) {\n // Beyond the end of the stream, or our best guess of the end of the stream.\n return null;\n }\n\n if (dateTimeObject > lastSegmentStart) {\n segment = lastSegment;\n }\n\n return {\n segment: segment,\n estimatedStart: segment.videoTimingInfo ? segment.videoTimingInfo.transmuxedPresentationStart : Playlist.duration(playlist, playlist.mediaSequence + playlist.segments.indexOf(segment)),\n // Although, given that all segments have accurate date time objects, the segment\n // selected should be accurate, unless the video has been transmuxed at some point\n // (determined by the presence of the videoTimingInfo object), the segment's \"player\n // time\" (the start time in the player) can't be considered accurate.\n type: segment.videoTimingInfo ? 'accurate' : 'estimate'\n };\n};\n/**\n * Finds a segment that contains the given player time(in seconds).\n *\n * @param {number} time The player time to find a match for\n * @param {Object} playlist A playlist object to search within\n */\n\nvar findSegmentForPlayerTime = function findSegmentForPlayerTime(time, playlist) {\n // Assumptions:\n // - there will always be a segment.duration\n // - we can start from zero\n // - segments are in time order\n if (!playlist || !playlist.segments || playlist.segments.length === 0) {\n return null;\n }\n\n var segmentEnd = 0;\n var segment;\n\n for (var i = 0; i < playlist.segments.length; i++) {\n segment = playlist.segments[i]; // videoTimingInfo is set after the segment is downloaded and transmuxed, and\n // should contain the most accurate values we have for the segment's player times.\n //\n // Use the accurate transmuxedPresentationEnd value if it is available, otherwise fall\n // back to an estimate based on the manifest derived (inaccurate) segment.duration, to\n // calculate an end value.\n\n segmentEnd = segment.videoTimingInfo ? segment.videoTimingInfo.transmuxedPresentationEnd : segmentEnd + segment.duration;\n\n if (time <= segmentEnd) {\n break;\n }\n }\n\n var lastSegment = playlist.segments[playlist.segments.length - 1];\n\n if (lastSegment.videoTimingInfo && lastSegment.videoTimingInfo.transmuxedPresentationEnd < time) {\n // The time requested is beyond the stream end.\n return null;\n }\n\n if (time > segmentEnd) {\n // The time is within or beyond the last segment.\n //\n // Check to see if the time is beyond a reasonable guess of the end of the stream.\n if (time > segmentEnd + lastSegment.duration * SEGMENT_END_FUDGE_PERCENT) {\n // Technically, because the duration value is only an estimate, the time may still\n // exist in the last segment, however, there isn't enough information to make even\n // a reasonable estimate.\n return null;\n }\n\n segment = lastSegment;\n }\n\n return {\n segment: segment,\n estimatedStart: segment.videoTimingInfo ? segment.videoTimingInfo.transmuxedPresentationStart : segmentEnd - segment.duration,\n // Because videoTimingInfo is only set after transmux, it is the only way to get\n // accurate timing values.\n type: segment.videoTimingInfo ? 'accurate' : 'estimate'\n };\n};\n/**\n * Gives the offset of the comparisonTimestamp from the programTime timestamp in seconds.\n * If the offset returned is positive, the programTime occurs after the\n * comparisonTimestamp.\n * If the offset is negative, the programTime occurs before the comparisonTimestamp.\n *\n * @param {string} comparisonTimeStamp An ISO-8601 timestamp to compare against\n * @param {string} programTime The programTime as an ISO-8601 string\n * @return {number} offset\n */\n\nvar getOffsetFromTimestamp = function getOffsetFromTimestamp(comparisonTimeStamp, programTime) {\n var segmentDateTime;\n var programDateTime;\n\n try {\n segmentDateTime = new Date(comparisonTimeStamp);\n programDateTime = new Date(programTime);\n } catch (e) {// TODO handle error\n }\n\n var segmentTimeEpoch = segmentDateTime.getTime();\n var programTimeEpoch = programDateTime.getTime();\n return (programTimeEpoch - segmentTimeEpoch) / 1000;\n};\n/**\n * Checks that all segments in this playlist have programDateTime tags.\n *\n * @param {Object} playlist A playlist object\n */\n\nvar verifyProgramDateTimeTags = function verifyProgramDateTimeTags(playlist) {\n if (!playlist.segments || playlist.segments.length === 0) {\n return false;\n }\n\n for (var i = 0; i < playlist.segments.length; i++) {\n var segment = playlist.segments[i];\n\n if (!segment.dateTimeObject) {\n return false;\n }\n }\n\n return true;\n};\n/**\n * Returns the programTime of the media given a playlist and a playerTime.\n * The playlist must have programDateTime tags for a programDateTime tag to be returned.\n * If the segments containing the time requested have not been buffered yet, an estimate\n * may be returned to the callback.\n *\n * @param {Object} args\n * @param {Object} args.playlist A playlist object to search within\n * @param {number} time A playerTime in seconds\n * @param {Function} callback(err, programTime)\n * @return {string} err.message A detailed error message\n * @return {Object} programTime\n * @return {number} programTime.mediaSeconds The streamTime in seconds\n * @return {string} programTime.programDateTime The programTime as an ISO-8601 String\n */\n\nvar getProgramTime = function getProgramTime(_ref) {\n var playlist = _ref.playlist,\n _ref$time = _ref.time,\n time = _ref$time === void 0 ? undefined : _ref$time,\n callback = _ref.callback;\n\n if (!callback) {\n throw new Error('getProgramTime: callback must be provided');\n }\n\n if (!playlist || time === undefined) {\n return callback({\n message: 'getProgramTime: playlist and time must be provided'\n });\n }\n\n var matchedSegment = findSegmentForPlayerTime(time, playlist);\n\n if (!matchedSegment) {\n return callback({\n message: 'valid programTime was not found'\n });\n }\n\n if (matchedSegment.type === 'estimate') {\n return callback({\n message: 'Accurate programTime could not be determined.' + ' Please seek to e.seekTime and try again',\n seekTime: matchedSegment.estimatedStart\n });\n }\n\n var programTimeObject = {\n mediaSeconds: time\n };\n var programTime = playerTimeToProgramTime(time, matchedSegment.segment);\n\n if (programTime) {\n programTimeObject.programDateTime = programTime.toISOString();\n }\n\n return callback(null, programTimeObject);\n};\n/**\n * Seeks in the player to a time that matches the given programTime ISO-8601 string.\n *\n * @param {Object} args\n * @param {string} args.programTime A programTime to seek to as an ISO-8601 String\n * @param {Object} args.playlist A playlist to look within\n * @param {number} args.retryCount The number of times to try for an accurate seek. Default is 2.\n * @param {Function} args.seekTo A method to perform a seek\n * @param {boolean} args.pauseAfterSeek Whether to end in a paused state after seeking. Default is true.\n * @param {Object} args.tech The tech to seek on\n * @param {Function} args.callback(err, newTime) A callback to return the new time to\n * @return {string} err.message A detailed error message\n * @return {number} newTime The exact time that was seeked to in seconds\n */\n\nvar seekToProgramTime = function seekToProgramTime(_ref2) {\n var programTime = _ref2.programTime,\n playlist = _ref2.playlist,\n _ref2$retryCount = _ref2.retryCount,\n retryCount = _ref2$retryCount === void 0 ? 2 : _ref2$retryCount,\n seekTo = _ref2.seekTo,\n _ref2$pauseAfterSeek = _ref2.pauseAfterSeek,\n pauseAfterSeek = _ref2$pauseAfterSeek === void 0 ? true : _ref2$pauseAfterSeek,\n tech = _ref2.tech,\n callback = _ref2.callback;\n\n if (!callback) {\n throw new Error('seekToProgramTime: callback must be provided');\n }\n\n if (typeof programTime === 'undefined' || !playlist || !seekTo) {\n return callback({\n message: 'seekToProgramTime: programTime, seekTo and playlist must be provided'\n });\n }\n\n if (!playlist.endList && !tech.hasStarted_) {\n return callback({\n message: 'player must be playing a live stream to start buffering'\n });\n }\n\n if (!verifyProgramDateTimeTags(playlist)) {\n return callback({\n message: 'programDateTime tags must be provided in the manifest ' + playlist.resolvedUri\n });\n }\n\n var matchedSegment = findSegmentForProgramTime(programTime, playlist); // no match\n\n if (!matchedSegment) {\n return callback({\n message: programTime + \" was not found in the stream\"\n });\n }\n\n var segment = matchedSegment.segment;\n var mediaOffset = getOffsetFromTimestamp(segment.dateTimeObject, programTime);\n\n if (matchedSegment.type === 'estimate') {\n // we've run out of retries\n if (retryCount === 0) {\n return callback({\n message: programTime + \" is not buffered yet. Try again\"\n });\n }\n\n seekTo(matchedSegment.estimatedStart + mediaOffset);\n tech.one('seeked', function () {\n seekToProgramTime({\n programTime: programTime,\n playlist: playlist,\n retryCount: retryCount - 1,\n seekTo: seekTo,\n pauseAfterSeek: pauseAfterSeek,\n tech: tech,\n callback: callback\n });\n });\n return;\n } // Since the segment.start value is determined from the buffered end or ending time\n // of the prior segment, the seekToTime doesn't need to account for any transmuxer\n // modifications.\n\n\n var seekToTime = segment.start + mediaOffset;\n\n var seekedCallback = function seekedCallback() {\n return callback(null, tech.currentTime());\n }; // listen for seeked event\n\n\n tech.one('seeked', seekedCallback); // pause before seeking as video.js will restore this state\n\n if (pauseAfterSeek) {\n tech.pause();\n }\n\n seekTo(seekToTime);\n};\n\n// which will only happen if the request is complete.\n\nvar callbackOnCompleted = function callbackOnCompleted(request, cb) {\n if (request.readyState === 4) {\n return cb();\n }\n\n return;\n};\n\nvar containerRequest = function containerRequest(uri, xhr, cb) {\n var bytes = [];\n var id3Offset;\n var finished = false;\n\n var endRequestAndCallback = function endRequestAndCallback(err, req, type, _bytes) {\n req.abort();\n finished = true;\n return cb(err, req, type, _bytes);\n };\n\n var progressListener = function progressListener(error, request) {\n if (finished) {\n return;\n }\n\n if (error) {\n return endRequestAndCallback(error, request, '', bytes);\n } // grap the new part of content that was just downloaded\n\n\n var newPart = request.responseText.substring(bytes && bytes.byteLength || 0, request.responseText.length); // add that onto bytes\n\n bytes = concatTypedArrays(bytes, stringToBytes(newPart, true));\n id3Offset = id3Offset || getId3Offset(bytes); // we need at least 10 bytes to determine a type\n // or we need at least two bytes after an id3Offset\n\n if (bytes.length < 10 || id3Offset && bytes.length < id3Offset + 2) {\n return callbackOnCompleted(request, function () {\n return endRequestAndCallback(error, request, '', bytes);\n });\n }\n\n var type = detectContainerForBytes(bytes); // if this looks like a ts segment but we don't have enough data\n // to see the second sync byte, wait until we have enough data\n // before declaring it ts\n\n if (type === 'ts' && bytes.length < 188) {\n return callbackOnCompleted(request, function () {\n return endRequestAndCallback(error, request, '', bytes);\n });\n } // this may be an unsynced ts segment\n // wait for 376 bytes before detecting no container\n\n\n if (!type && bytes.length < 376) {\n return callbackOnCompleted(request, function () {\n return endRequestAndCallback(error, request, '', bytes);\n });\n }\n\n return endRequestAndCallback(null, request, type, bytes);\n };\n\n var options = {\n uri: uri,\n beforeSend: function beforeSend(request) {\n // this forces the browser to pass the bytes to us unprocessed\n request.overrideMimeType('text/plain; charset=x-user-defined');\n request.addEventListener('progress', function (_ref) {\n _ref.total;\n _ref.loaded;\n return callbackWrapper(request, null, {\n statusCode: request.status\n }, progressListener);\n });\n }\n };\n var request = xhr(options, function (error, response) {\n return callbackWrapper(request, error, response, progressListener);\n });\n return request;\n};\n\nvar EventTarget = videojs.EventTarget,\n mergeOptions = videojs.mergeOptions;\n\nvar dashPlaylistUnchanged = function dashPlaylistUnchanged(a, b) {\n if (!isPlaylistUnchanged(a, b)) {\n return false;\n } // for dash the above check will often return true in scenarios where\n // the playlist actually has changed because mediaSequence isn't a\n // dash thing, and we often set it to 1. So if the playlists have the same amount\n // of segments we return true.\n // So for dash we need to make sure that the underlying segments are different.\n // if sidx changed then the playlists are different.\n\n\n if (a.sidx && b.sidx && (a.sidx.offset !== b.sidx.offset || a.sidx.length !== b.sidx.length)) {\n return false;\n } else if (!a.sidx && b.sidx || a.sidx && !b.sidx) {\n return false;\n } // one or the other does not have segments\n // there was a change.\n\n\n if (a.segments && !b.segments || !a.segments && b.segments) {\n return false;\n } // neither has segments nothing changed\n\n\n if (!a.segments && !b.segments) {\n return true;\n } // check segments themselves\n\n\n for (var i = 0; i < a.segments.length; i++) {\n var aSegment = a.segments[i];\n var bSegment = b.segments[i]; // if uris are different between segments there was a change\n\n if (aSegment.uri !== bSegment.uri) {\n return false;\n } // neither segment has a byterange, there will be no byterange change.\n\n\n if (!aSegment.byterange && !bSegment.byterange) {\n continue;\n }\n\n var aByterange = aSegment.byterange;\n var bByterange = bSegment.byterange; // if byterange only exists on one of the segments, there was a change.\n\n if (aByterange && !bByterange || !aByterange && bByterange) {\n return false;\n } // if both segments have byterange with different offsets, there was a change.\n\n\n if (aByterange.offset !== bByterange.offset || aByterange.length !== bByterange.length) {\n return false;\n }\n } // if everything was the same with segments, this is the same playlist.\n\n\n return true;\n};\n/**\n * Parses the master XML string and updates playlist URI references.\n *\n * @param {Object} config\n * Object of arguments\n * @param {string} config.masterXml\n * The mpd XML\n * @param {string} config.srcUrl\n * The mpd URL\n * @param {Date} config.clientOffset\n * A time difference between server and client\n * @param {Object} config.sidxMapping\n * SIDX mappings for moof/mdat URIs and byte ranges\n * @return {Object}\n * The parsed mpd manifest object\n */\n\n\nvar parseMasterXml = function parseMasterXml(_ref) {\n var masterXml = _ref.masterXml,\n srcUrl = _ref.srcUrl,\n clientOffset = _ref.clientOffset,\n sidxMapping = _ref.sidxMapping,\n previousManifest = _ref.previousManifest;\n var manifest = parse(masterXml, {\n manifestUri: srcUrl,\n clientOffset: clientOffset,\n sidxMapping: sidxMapping,\n previousManifest: previousManifest\n });\n addPropertiesToMaster(manifest, srcUrl);\n return manifest;\n};\n/**\n * Returns a new master manifest that is the result of merging an updated master manifest\n * into the original version.\n *\n * @param {Object} oldMaster\n * The old parsed mpd object\n * @param {Object} newMaster\n * The updated parsed mpd object\n * @return {Object}\n * A new object representing the original master manifest with the updated media\n * playlists merged in\n */\n\nvar updateMaster = function updateMaster(oldMaster, newMaster, sidxMapping) {\n var noChanges = true;\n var update = mergeOptions(oldMaster, {\n // These are top level properties that can be updated\n duration: newMaster.duration,\n minimumUpdatePeriod: newMaster.minimumUpdatePeriod,\n timelineStarts: newMaster.timelineStarts\n }); // First update the playlists in playlist list\n\n for (var i = 0; i < newMaster.playlists.length; i++) {\n var playlist = newMaster.playlists[i];\n\n if (playlist.sidx) {\n var sidxKey = generateSidxKey(playlist.sidx); // add sidx segments to the playlist if we have all the sidx info already\n\n if (sidxMapping && sidxMapping[sidxKey] && sidxMapping[sidxKey].sidx) {\n addSidxSegmentsToPlaylist(playlist, sidxMapping[sidxKey].sidx, playlist.sidx.resolvedUri);\n }\n }\n\n var playlistUpdate = updateMaster$1(update, playlist, dashPlaylistUnchanged);\n\n if (playlistUpdate) {\n update = playlistUpdate;\n noChanges = false;\n }\n } // Then update media group playlists\n\n\n forEachMediaGroup(newMaster, function (properties, type, group, label) {\n if (properties.playlists && properties.playlists.length) {\n var id = properties.playlists[0].id;\n\n var _playlistUpdate = updateMaster$1(update, properties.playlists[0], dashPlaylistUnchanged);\n\n if (_playlistUpdate) {\n update = _playlistUpdate; // update the playlist reference within media groups\n\n update.mediaGroups[type][group][label].playlists[0] = update.playlists[id];\n noChanges = false;\n }\n }\n });\n\n if (newMaster.minimumUpdatePeriod !== oldMaster.minimumUpdatePeriod) {\n noChanges = false;\n }\n\n if (noChanges) {\n return null;\n }\n\n return update;\n}; // SIDX should be equivalent if the URI and byteranges of the SIDX match.\n// If the SIDXs have maps, the two maps should match,\n// both `a` and `b` missing SIDXs is considered matching.\n// If `a` or `b` but not both have a map, they aren't matching.\n\nvar equivalentSidx = function equivalentSidx(a, b) {\n var neitherMap = Boolean(!a.map && !b.map);\n var equivalentMap = neitherMap || Boolean(a.map && b.map && a.map.byterange.offset === b.map.byterange.offset && a.map.byterange.length === b.map.byterange.length);\n return equivalentMap && a.uri === b.uri && a.byterange.offset === b.byterange.offset && a.byterange.length === b.byterange.length;\n}; // exported for testing\n\n\nvar compareSidxEntry = function compareSidxEntry(playlists, oldSidxMapping) {\n var newSidxMapping = {};\n\n for (var id in playlists) {\n var playlist = playlists[id];\n var currentSidxInfo = playlist.sidx;\n\n if (currentSidxInfo) {\n var key = generateSidxKey(currentSidxInfo);\n\n if (!oldSidxMapping[key]) {\n break;\n }\n\n var savedSidxInfo = oldSidxMapping[key].sidxInfo;\n\n if (equivalentSidx(savedSidxInfo, currentSidxInfo)) {\n newSidxMapping[key] = oldSidxMapping[key];\n }\n }\n }\n\n return newSidxMapping;\n};\n/**\n * A function that filters out changed items as they need to be requested separately.\n *\n * The method is exported for testing\n *\n * @param {Object} master the parsed mpd XML returned via mpd-parser\n * @param {Object} oldSidxMapping the SIDX to compare against\n */\n\nvar filterChangedSidxMappings = function filterChangedSidxMappings(master, oldSidxMapping) {\n var videoSidx = compareSidxEntry(master.playlists, oldSidxMapping);\n var mediaGroupSidx = videoSidx;\n forEachMediaGroup(master, function (properties, mediaType, groupKey, labelKey) {\n if (properties.playlists && properties.playlists.length) {\n var playlists = properties.playlists;\n mediaGroupSidx = mergeOptions(mediaGroupSidx, compareSidxEntry(playlists, oldSidxMapping));\n }\n });\n return mediaGroupSidx;\n};\n\nvar DashPlaylistLoader = /*#__PURE__*/function (_EventTarget) {\n _inheritsLoose(DashPlaylistLoader, _EventTarget);\n\n // DashPlaylistLoader must accept either a src url or a playlist because subsequent\n // playlist loader setups from media groups will expect to be able to pass a playlist\n // (since there aren't external URLs to media playlists with DASH)\n function DashPlaylistLoader(srcUrlOrPlaylist, vhs, options, masterPlaylistLoader) {\n var _this;\n\n if (options === void 0) {\n options = {};\n }\n\n _this = _EventTarget.call(this) || this;\n _this.masterPlaylistLoader_ = masterPlaylistLoader || _assertThisInitialized(_this);\n\n if (!masterPlaylistLoader) {\n _this.isMaster_ = true;\n }\n\n var _options = options,\n _options$withCredenti = _options.withCredentials,\n withCredentials = _options$withCredenti === void 0 ? false : _options$withCredenti,\n _options$handleManife = _options.handleManifestRedirects,\n handleManifestRedirects = _options$handleManife === void 0 ? false : _options$handleManife;\n _this.vhs_ = vhs;\n _this.withCredentials = withCredentials;\n _this.handleManifestRedirects = handleManifestRedirects;\n\n if (!srcUrlOrPlaylist) {\n throw new Error('A non-empty playlist URL or object is required');\n } // event naming?\n\n\n _this.on('minimumUpdatePeriod', function () {\n _this.refreshXml_();\n }); // live playlist staleness timeout\n\n\n _this.on('mediaupdatetimeout', function () {\n _this.refreshMedia_(_this.media().id);\n });\n\n _this.state = 'HAVE_NOTHING';\n _this.loadedPlaylists_ = {};\n _this.logger_ = logger('DashPlaylistLoader'); // initialize the loader state\n // The masterPlaylistLoader will be created with a string\n\n if (_this.isMaster_) {\n _this.masterPlaylistLoader_.srcUrl = srcUrlOrPlaylist; // TODO: reset sidxMapping between period changes\n // once multi-period is refactored\n\n _this.masterPlaylistLoader_.sidxMapping_ = {};\n } else {\n _this.childPlaylist_ = srcUrlOrPlaylist;\n }\n\n return _this;\n }\n\n var _proto = DashPlaylistLoader.prototype;\n\n _proto.requestErrored_ = function requestErrored_(err, request, startingState) {\n // disposed\n if (!this.request) {\n return true;\n } // pending request is cleared\n\n\n this.request = null;\n\n if (err) {\n // use the provided error object or create one\n // based on the request/response\n this.error = typeof err === 'object' && !(err instanceof Error) ? err : {\n status: request.status,\n message: 'DASH request error at URL: ' + request.uri,\n response: request.response,\n // MEDIA_ERR_NETWORK\n code: 2\n };\n\n if (startingState) {\n this.state = startingState;\n }\n\n this.trigger('error');\n return true;\n }\n }\n /**\n * Verify that the container of the sidx segment can be parsed\n * and if it can, get and parse that segment.\n */\n ;\n\n _proto.addSidxSegments_ = function addSidxSegments_(playlist, startingState, cb) {\n var _this2 = this;\n\n var sidxKey = playlist.sidx && generateSidxKey(playlist.sidx); // playlist lacks sidx or sidx segments were added to this playlist already.\n\n if (!playlist.sidx || !sidxKey || this.masterPlaylistLoader_.sidxMapping_[sidxKey]) {\n // keep this function async\n this.mediaRequest_ = window$1.setTimeout(function () {\n return cb(false);\n }, 0);\n return;\n } // resolve the segment URL relative to the playlist\n\n\n var uri = resolveManifestRedirect(this.handleManifestRedirects, playlist.sidx.resolvedUri);\n\n var fin = function fin(err, request) {\n if (_this2.requestErrored_(err, request, startingState)) {\n return;\n }\n\n var sidxMapping = _this2.masterPlaylistLoader_.sidxMapping_;\n var sidx;\n\n try {\n sidx = parseSidx(toUint8(request.response).subarray(8));\n } catch (e) {\n // sidx parsing failed.\n _this2.requestErrored_(e, request, startingState);\n\n return;\n }\n\n sidxMapping[sidxKey] = {\n sidxInfo: playlist.sidx,\n sidx: sidx\n };\n addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri);\n return cb(true);\n };\n\n this.request = containerRequest(uri, this.vhs_.xhr, function (err, request, container, bytes) {\n if (err) {\n return fin(err, request);\n }\n\n if (!container || container !== 'mp4') {\n return fin({\n status: request.status,\n message: \"Unsupported \" + (container || 'unknown') + \" container type for sidx segment at URL: \" + uri,\n // response is just bytes in this case\n // but we really don't want to return that.\n response: '',\n playlist: playlist,\n internal: true,\n blacklistDuration: Infinity,\n // MEDIA_ERR_NETWORK\n code: 2\n }, request);\n } // if we already downloaded the sidx bytes in the container request, use them\n\n\n var _playlist$sidx$bytera = playlist.sidx.byterange,\n offset = _playlist$sidx$bytera.offset,\n length = _playlist$sidx$bytera.length;\n\n if (bytes.length >= length + offset) {\n return fin(err, {\n response: bytes.subarray(offset, offset + length),\n status: request.status,\n uri: request.uri\n });\n } // otherwise request sidx bytes\n\n\n _this2.request = _this2.vhs_.xhr({\n uri: uri,\n responseType: 'arraybuffer',\n headers: segmentXhrHeaders({\n byterange: playlist.sidx.byterange\n })\n }, fin);\n });\n };\n\n _proto.dispose = function dispose() {\n this.trigger('dispose');\n this.stopRequest();\n this.loadedPlaylists_ = {};\n window$1.clearTimeout(this.minimumUpdatePeriodTimeout_);\n window$1.clearTimeout(this.mediaRequest_);\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n this.mediaRequest_ = null;\n this.minimumUpdatePeriodTimeout_ = null;\n\n if (this.masterPlaylistLoader_.createMupOnMedia_) {\n this.off('loadedmetadata', this.masterPlaylistLoader_.createMupOnMedia_);\n this.masterPlaylistLoader_.createMupOnMedia_ = null;\n }\n\n this.off();\n };\n\n _proto.hasPendingRequest = function hasPendingRequest() {\n return this.request || this.mediaRequest_;\n };\n\n _proto.stopRequest = function stopRequest() {\n if (this.request) {\n var oldRequest = this.request;\n this.request = null;\n oldRequest.onreadystatechange = null;\n oldRequest.abort();\n }\n };\n\n _proto.media = function media(playlist) {\n var _this3 = this;\n\n // getter\n if (!playlist) {\n return this.media_;\n } // setter\n\n\n if (this.state === 'HAVE_NOTHING') {\n throw new Error('Cannot switch media playlist from ' + this.state);\n }\n\n var startingState = this.state; // find the playlist object if the target playlist has been specified by URI\n\n if (typeof playlist === 'string') {\n if (!this.masterPlaylistLoader_.master.playlists[playlist]) {\n throw new Error('Unknown playlist URI: ' + playlist);\n }\n\n playlist = this.masterPlaylistLoader_.master.playlists[playlist];\n }\n\n var mediaChange = !this.media_ || playlist.id !== this.media_.id; // switch to previously loaded playlists immediately\n\n if (mediaChange && this.loadedPlaylists_[playlist.id] && this.loadedPlaylists_[playlist.id].endList) {\n this.state = 'HAVE_METADATA';\n this.media_ = playlist; // trigger media change if the active media has been updated\n\n if (mediaChange) {\n this.trigger('mediachanging');\n this.trigger('mediachange');\n }\n\n return;\n } // switching to the active playlist is a no-op\n\n\n if (!mediaChange) {\n return;\n } // switching from an already loaded playlist\n\n\n if (this.media_) {\n this.trigger('mediachanging');\n }\n\n this.addSidxSegments_(playlist, startingState, function (sidxChanged) {\n // everything is ready just continue to haveMetadata\n _this3.haveMetadata({\n startingState: startingState,\n playlist: playlist\n });\n });\n };\n\n _proto.haveMetadata = function haveMetadata(_ref2) {\n var startingState = _ref2.startingState,\n playlist = _ref2.playlist;\n this.state = 'HAVE_METADATA';\n this.loadedPlaylists_[playlist.id] = playlist;\n this.mediaRequest_ = null; // This will trigger loadedplaylist\n\n this.refreshMedia_(playlist.id); // fire loadedmetadata the first time a media playlist is loaded\n // to resolve setup of media groups\n\n if (startingState === 'HAVE_MASTER') {\n this.trigger('loadedmetadata');\n } else {\n // trigger media change if the active media has been updated\n this.trigger('mediachange');\n }\n };\n\n _proto.pause = function pause() {\n if (this.masterPlaylistLoader_.createMupOnMedia_) {\n this.off('loadedmetadata', this.masterPlaylistLoader_.createMupOnMedia_);\n this.masterPlaylistLoader_.createMupOnMedia_ = null;\n }\n\n this.stopRequest();\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n\n if (this.isMaster_) {\n window$1.clearTimeout(this.masterPlaylistLoader_.minimumUpdatePeriodTimeout_);\n this.masterPlaylistLoader_.minimumUpdatePeriodTimeout_ = null;\n }\n\n if (this.state === 'HAVE_NOTHING') {\n // If we pause the loader before any data has been retrieved, its as if we never\n // started, so reset to an unstarted state.\n this.started = false;\n }\n };\n\n _proto.load = function load(isFinalRendition) {\n var _this4 = this;\n\n window$1.clearTimeout(this.mediaUpdateTimeout);\n this.mediaUpdateTimeout = null;\n var media = this.media();\n\n if (isFinalRendition) {\n var delay = media ? media.targetDuration / 2 * 1000 : 5 * 1000;\n this.mediaUpdateTimeout = window$1.setTimeout(function () {\n return _this4.load();\n }, delay);\n return;\n } // because the playlists are internal to the manifest, load should either load the\n // main manifest, or do nothing but trigger an event\n\n\n if (!this.started) {\n this.start();\n return;\n }\n\n if (media && !media.endList) {\n // Check to see if this is the master loader and the MUP was cleared (this happens\n // when the loader was paused). `media` should be set at this point since one is always\n // set during `start()`.\n if (this.isMaster_ && !this.minimumUpdatePeriodTimeout_) {\n // Trigger minimumUpdatePeriod to refresh the master manifest\n this.trigger('minimumUpdatePeriod'); // Since there was no prior minimumUpdatePeriodTimeout it should be recreated\n\n this.updateMinimumUpdatePeriodTimeout_();\n }\n\n this.trigger('mediaupdatetimeout');\n } else {\n this.trigger('loadedplaylist');\n }\n };\n\n _proto.start = function start() {\n var _this5 = this;\n\n this.started = true; // We don't need to request the master manifest again\n // Call this asynchronously to match the xhr request behavior below\n\n if (!this.isMaster_) {\n this.mediaRequest_ = window$1.setTimeout(function () {\n return _this5.haveMaster_();\n }, 0);\n return;\n }\n\n this.requestMaster_(function (req, masterChanged) {\n _this5.haveMaster_();\n\n if (!_this5.hasPendingRequest() && !_this5.media_) {\n _this5.media(_this5.masterPlaylistLoader_.master.playlists[0]);\n }\n });\n };\n\n _proto.requestMaster_ = function requestMaster_(cb) {\n var _this6 = this;\n\n this.request = this.vhs_.xhr({\n uri: this.masterPlaylistLoader_.srcUrl,\n withCredentials: this.withCredentials\n }, function (error, req) {\n if (_this6.requestErrored_(error, req)) {\n if (_this6.state === 'HAVE_NOTHING') {\n _this6.started = false;\n }\n\n return;\n }\n\n var masterChanged = req.responseText !== _this6.masterPlaylistLoader_.masterXml_;\n _this6.masterPlaylistLoader_.masterXml_ = req.responseText;\n\n if (req.responseHeaders && req.responseHeaders.date) {\n _this6.masterLoaded_ = Date.parse(req.responseHeaders.date);\n } else {\n _this6.masterLoaded_ = Date.now();\n }\n\n _this6.masterPlaylistLoader_.srcUrl = resolveManifestRedirect(_this6.handleManifestRedirects, _this6.masterPlaylistLoader_.srcUrl, req);\n\n if (masterChanged) {\n _this6.handleMaster_();\n\n _this6.syncClientServerClock_(function () {\n return cb(req, masterChanged);\n });\n\n return;\n }\n\n return cb(req, masterChanged);\n });\n }\n /**\n * Parses the master xml for UTCTiming node to sync the client clock to the server\n * clock. If the UTCTiming node requires a HEAD or GET request, that request is made.\n *\n * @param {Function} done\n * Function to call when clock sync has completed\n */\n ;\n\n _proto.syncClientServerClock_ = function syncClientServerClock_(done) {\n var _this7 = this;\n\n var utcTiming = parseUTCTiming(this.masterPlaylistLoader_.masterXml_); // No UTCTiming element found in the mpd. Use Date header from mpd request as the\n // server clock\n\n if (utcTiming === null) {\n this.masterPlaylistLoader_.clientOffset_ = this.masterLoaded_ - Date.now();\n return done();\n }\n\n if (utcTiming.method === 'DIRECT') {\n this.masterPlaylistLoader_.clientOffset_ = utcTiming.value - Date.now();\n return done();\n }\n\n this.request = this.vhs_.xhr({\n uri: resolveUrl(this.masterPlaylistLoader_.srcUrl, utcTiming.value),\n method: utcTiming.method,\n withCredentials: this.withCredentials\n }, function (error, req) {\n // disposed\n if (!_this7.request) {\n return;\n }\n\n if (error) {\n // sync request failed, fall back to using date header from mpd\n // TODO: log warning\n _this7.masterPlaylistLoader_.clientOffset_ = _this7.masterLoaded_ - Date.now();\n return done();\n }\n\n var serverTime;\n\n if (utcTiming.method === 'HEAD') {\n if (!req.responseHeaders || !req.responseHeaders.date) {\n // expected date header not preset, fall back to using date header from mpd\n // TODO: log warning\n serverTime = _this7.masterLoaded_;\n } else {\n serverTime = Date.parse(req.responseHeaders.date);\n }\n } else {\n serverTime = Date.parse(req.responseText);\n }\n\n _this7.masterPlaylistLoader_.clientOffset_ = serverTime - Date.now();\n done();\n });\n };\n\n _proto.haveMaster_ = function haveMaster_() {\n this.state = 'HAVE_MASTER';\n\n if (this.isMaster_) {\n // We have the master playlist at this point, so\n // trigger this to allow MasterPlaylistController\n // to make an initial playlist selection\n this.trigger('loadedplaylist');\n } else if (!this.media_) {\n // no media playlist was specifically selected so select\n // the one the child playlist loader was created with\n this.media(this.childPlaylist_);\n }\n };\n\n _proto.handleMaster_ = function handleMaster_() {\n // clear media request\n this.mediaRequest_ = null;\n var oldMaster = this.masterPlaylistLoader_.master;\n var newMaster = parseMasterXml({\n masterXml: this.masterPlaylistLoader_.masterXml_,\n srcUrl: this.masterPlaylistLoader_.srcUrl,\n clientOffset: this.masterPlaylistLoader_.clientOffset_,\n sidxMapping: this.masterPlaylistLoader_.sidxMapping_,\n previousManifest: oldMaster\n }); // if we have an old master to compare the new master against\n\n if (oldMaster) {\n newMaster = updateMaster(oldMaster, newMaster, this.masterPlaylistLoader_.sidxMapping_);\n } // only update master if we have a new master\n\n\n this.masterPlaylistLoader_.master = newMaster ? newMaster : oldMaster;\n var location = this.masterPlaylistLoader_.master.locations && this.masterPlaylistLoader_.master.locations[0];\n\n if (location && location !== this.masterPlaylistLoader_.srcUrl) {\n this.masterPlaylistLoader_.srcUrl = location;\n }\n\n if (!oldMaster || newMaster && newMaster.minimumUpdatePeriod !== oldMaster.minimumUpdatePeriod) {\n this.updateMinimumUpdatePeriodTimeout_();\n }\n\n return Boolean(newMaster);\n };\n\n _proto.updateMinimumUpdatePeriodTimeout_ = function updateMinimumUpdatePeriodTimeout_() {\n var mpl = this.masterPlaylistLoader_; // cancel any pending creation of mup on media\n // a new one will be added if needed.\n\n if (mpl.createMupOnMedia_) {\n mpl.off('loadedmetadata', mpl.createMupOnMedia_);\n mpl.createMupOnMedia_ = null;\n } // clear any pending timeouts\n\n\n if (mpl.minimumUpdatePeriodTimeout_) {\n window$1.clearTimeout(mpl.minimumUpdatePeriodTimeout_);\n mpl.minimumUpdatePeriodTimeout_ = null;\n }\n\n var mup = mpl.master && mpl.master.minimumUpdatePeriod; // If the minimumUpdatePeriod has a value of 0, that indicates that the current\n // MPD has no future validity, so a new one will need to be acquired when new\n // media segments are to be made available. Thus, we use the target duration\n // in this case\n\n if (mup === 0) {\n if (mpl.media()) {\n mup = mpl.media().targetDuration * 1000;\n } else {\n mpl.createMupOnMedia_ = mpl.updateMinimumUpdatePeriodTimeout_;\n mpl.one('loadedmetadata', mpl.createMupOnMedia_);\n }\n } // if minimumUpdatePeriod is invalid or <= zero, which\n // can happen when a live video becomes VOD. skip timeout\n // creation.\n\n\n if (typeof mup !== 'number' || mup <= 0) {\n if (mup < 0) {\n this.logger_(\"found invalid minimumUpdatePeriod of \" + mup + \", not setting a timeout\");\n }\n\n return;\n }\n\n this.createMUPTimeout_(mup);\n };\n\n _proto.createMUPTimeout_ = function createMUPTimeout_(mup) {\n var mpl = this.masterPlaylistLoader_;\n mpl.minimumUpdatePeriodTimeout_ = window$1.setTimeout(function () {\n mpl.minimumUpdatePeriodTimeout_ = null;\n mpl.trigger('minimumUpdatePeriod');\n mpl.createMUPTimeout_(mup);\n }, mup);\n }\n /**\n * Sends request to refresh the master xml and updates the parsed master manifest\n */\n ;\n\n _proto.refreshXml_ = function refreshXml_() {\n var _this8 = this;\n\n this.requestMaster_(function (req, masterChanged) {\n if (!masterChanged) {\n return;\n }\n\n if (_this8.media_) {\n _this8.media_ = _this8.masterPlaylistLoader_.master.playlists[_this8.media_.id];\n } // This will filter out updated sidx info from the mapping\n\n\n _this8.masterPlaylistLoader_.sidxMapping_ = filterChangedSidxMappings(_this8.masterPlaylistLoader_.master, _this8.masterPlaylistLoader_.sidxMapping_);\n\n _this8.addSidxSegments_(_this8.media(), _this8.state, function (sidxChanged) {\n // TODO: do we need to reload the current playlist?\n _this8.refreshMedia_(_this8.media().id);\n });\n });\n }\n /**\n * Refreshes the media playlist by re-parsing the master xml and updating playlist\n * references. If this is an alternate loader, the updated parsed manifest is retrieved\n * from the master loader.\n */\n ;\n\n _proto.refreshMedia_ = function refreshMedia_(mediaID) {\n var _this9 = this;\n\n if (!mediaID) {\n throw new Error('refreshMedia_ must take a media id');\n } // for master we have to reparse the master xml\n // to re-create segments based on current timing values\n // which may change media. We only skip updating master\n // if this is the first time this.media_ is being set.\n // as master was just parsed in that case.\n\n\n if (this.media_ && this.isMaster_) {\n this.handleMaster_();\n }\n\n var playlists = this.masterPlaylistLoader_.master.playlists;\n var mediaChanged = !this.media_ || this.media_ !== playlists[mediaID];\n\n if (mediaChanged) {\n this.media_ = playlists[mediaID];\n } else {\n this.trigger('playlistunchanged');\n }\n\n if (!this.mediaUpdateTimeout) {\n var createMediaUpdateTimeout = function createMediaUpdateTimeout() {\n if (_this9.media().endList) {\n return;\n }\n\n _this9.mediaUpdateTimeout = window$1.setTimeout(function () {\n _this9.trigger('mediaupdatetimeout');\n\n createMediaUpdateTimeout();\n }, refreshDelay(_this9.media(), Boolean(mediaChanged)));\n };\n\n createMediaUpdateTimeout();\n }\n\n this.trigger('loadedplaylist');\n };\n\n return DashPlaylistLoader;\n}(EventTarget);\n\nvar Config = {\n GOAL_BUFFER_LENGTH: 30,\n MAX_GOAL_BUFFER_LENGTH: 60,\n BACK_BUFFER_LENGTH: 30,\n GOAL_BUFFER_LENGTH_RATE: 1,\n // 0.5 MB/s\n INITIAL_BANDWIDTH: 4194304,\n // A fudge factor to apply to advertised playlist bitrates to account for\n // temporary flucations in client bandwidth\n BANDWIDTH_VARIANCE: 1.2,\n // How much of the buffer must be filled before we consider upswitching\n BUFFER_LOW_WATER_LINE: 0,\n MAX_BUFFER_LOW_WATER_LINE: 30,\n // TODO: Remove this when experimentalBufferBasedABR is removed\n EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE: 16,\n BUFFER_LOW_WATER_LINE_RATE: 1,\n // If the buffer is greater than the high water line, we won't switch down\n BUFFER_HIGH_WATER_LINE: 30\n};\n\nvar stringToArrayBuffer = function stringToArrayBuffer(string) {\n var view = new Uint8Array(new ArrayBuffer(string.length));\n\n for (var i = 0; i < string.length; i++) {\n view[i] = string.charCodeAt(i);\n }\n\n return view.buffer;\n};\n\n/* global Blob, BlobBuilder, Worker */\n// unify worker interface\nvar browserWorkerPolyFill = function browserWorkerPolyFill(workerObj) {\n // node only supports on/off\n workerObj.on = workerObj.addEventListener;\n workerObj.off = workerObj.removeEventListener;\n return workerObj;\n};\n\nvar createObjectURL = function createObjectURL(str) {\n try {\n return URL.createObjectURL(new Blob([str], {\n type: 'application/javascript'\n }));\n } catch (e) {\n var blob = new BlobBuilder();\n blob.append(str);\n return URL.createObjectURL(blob.getBlob());\n }\n};\n\nvar factory = function factory(code) {\n return function () {\n var objectUrl = createObjectURL(code);\n var worker = browserWorkerPolyFill(new Worker(objectUrl));\n worker.objURL = objectUrl;\n var terminate = worker.terminate;\n worker.on = worker.addEventListener;\n worker.off = worker.removeEventListener;\n\n worker.terminate = function () {\n URL.revokeObjectURL(objectUrl);\n return terminate.call(this);\n };\n\n return worker;\n };\n};\nvar transform = function transform(code) {\n return \"var browserWorkerPolyFill = \" + browserWorkerPolyFill.toString() + \";\\n\" + 'browserWorkerPolyFill(self);\\n' + code;\n};\n\nvar getWorkerString = function getWorkerString(fn) {\n return fn.toString().replace(/^function.+?{/, '').slice(0, -1);\n};\n\n/* rollup-plugin-worker-factory start for worker!/Users/gsinger/repos/clean/http-streaming/src/transmuxer-worker.js */\nvar workerCode$1 = transform(getWorkerString(function () {\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n *\n * A lightweight readable stream implemention that handles event dispatching.\n * Objects that inherit from streams should call init in their constructors.\n */\n\n var Stream = function Stream() {\n this.init = function () {\n var listeners = {};\n /**\n * Add a listener for a specified event type.\n * @param type {string} the event name\n * @param listener {function} the callback to be invoked when an event of\n * the specified type occurs\n */\n\n this.on = function (type, listener) {\n if (!listeners[type]) {\n listeners[type] = [];\n }\n\n listeners[type] = listeners[type].concat(listener);\n };\n /**\n * Remove a listener for a specified event type.\n * @param type {string} the event name\n * @param listener {function} a function previously registered for this\n * type of event through `on`\n */\n\n\n this.off = function (type, listener) {\n var index;\n\n if (!listeners[type]) {\n return false;\n }\n\n index = listeners[type].indexOf(listener);\n listeners[type] = listeners[type].slice();\n listeners[type].splice(index, 1);\n return index > -1;\n };\n /**\n * Trigger an event of the specified type on this stream. Any additional\n * arguments to this function are passed as parameters to event listeners.\n * @param type {string} the event name\n */\n\n\n this.trigger = function (type) {\n var callbacks, i, length, args;\n callbacks = listeners[type];\n\n if (!callbacks) {\n return;\n } // Slicing the arguments on every invocation of this method\n // can add a significant amount of overhead. Avoid the\n // intermediate object creation for the common case of a\n // single callback argument\n\n\n if (arguments.length === 2) {\n length = callbacks.length;\n\n for (i = 0; i < length; ++i) {\n callbacks[i].call(this, arguments[1]);\n }\n } else {\n args = [];\n i = arguments.length;\n\n for (i = 1; i < arguments.length; ++i) {\n args.push(arguments[i]);\n }\n\n length = callbacks.length;\n\n for (i = 0; i < length; ++i) {\n callbacks[i].apply(this, args);\n }\n }\n };\n /**\n * Destroys the stream and cleans up.\n */\n\n\n this.dispose = function () {\n listeners = {};\n };\n };\n };\n /**\n * Forwards all `data` events on this stream to the destination stream. The\n * destination stream should provide a method `push` to receive the data\n * events as they arrive.\n * @param destination {stream} the stream that will receive all `data` events\n * @param autoFlush {boolean} if false, we will not call `flush` on the destination\n * when the current stream emits a 'done' event\n * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options\n */\n\n\n Stream.prototype.pipe = function (destination) {\n this.on('data', function (data) {\n destination.push(data);\n });\n this.on('done', function (flushSource) {\n destination.flush(flushSource);\n });\n this.on('partialdone', function (flushSource) {\n destination.partialFlush(flushSource);\n });\n this.on('endedtimeline', function (flushSource) {\n destination.endTimeline(flushSource);\n });\n this.on('reset', function (flushSource) {\n destination.reset(flushSource);\n });\n return destination;\n }; // Default stream functions that are expected to be overridden to perform\n // actual work. These are provided by the prototype as a sort of no-op\n // implementation so that we don't have to check for their existence in the\n // `pipe` function above.\n\n\n Stream.prototype.push = function (data) {\n this.trigger('data', data);\n };\n\n Stream.prototype.flush = function (flushSource) {\n this.trigger('done', flushSource);\n };\n\n Stream.prototype.partialFlush = function (flushSource) {\n this.trigger('partialdone', flushSource);\n };\n\n Stream.prototype.endTimeline = function (flushSource) {\n this.trigger('endedtimeline', flushSource);\n };\n\n Stream.prototype.reset = function (flushSource) {\n this.trigger('reset', flushSource);\n };\n\n var stream = Stream;\n var MAX_UINT32$1 = Math.pow(2, 32);\n\n var getUint64$2 = function getUint64(uint8) {\n var dv = new DataView(uint8.buffer, uint8.byteOffset, uint8.byteLength);\n var value;\n\n if (dv.getBigUint64) {\n value = dv.getBigUint64(0);\n\n if (value < Number.MAX_SAFE_INTEGER) {\n return Number(value);\n }\n\n return value;\n }\n\n return dv.getUint32(0) * MAX_UINT32$1 + dv.getUint32(4);\n };\n\n var numbers = {\n getUint64: getUint64$2,\n MAX_UINT32: MAX_UINT32$1\n };\n var MAX_UINT32 = numbers.MAX_UINT32;\n var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, trak, tkhd, mdia, mdhd, hdlr, sdtp, stbl, stsd, traf, trex, trun$1, types, MAJOR_BRAND, MINOR_VERSION, AVC1_BRAND, VIDEO_HDLR, AUDIO_HDLR, HDLR_TYPES, VMHD, SMHD, DREF, STCO, STSC, STSZ, STTS; // pre-calculate constants\n\n (function () {\n var i;\n types = {\n avc1: [],\n // codingname\n avcC: [],\n btrt: [],\n dinf: [],\n dref: [],\n esds: [],\n ftyp: [],\n hdlr: [],\n mdat: [],\n mdhd: [],\n mdia: [],\n mfhd: [],\n minf: [],\n moof: [],\n moov: [],\n mp4a: [],\n // codingname\n mvex: [],\n mvhd: [],\n pasp: [],\n sdtp: [],\n smhd: [],\n stbl: [],\n stco: [],\n stsc: [],\n stsd: [],\n stsz: [],\n stts: [],\n styp: [],\n tfdt: [],\n tfhd: [],\n traf: [],\n trak: [],\n trun: [],\n trex: [],\n tkhd: [],\n vmhd: []\n }; // In environments where Uint8Array is undefined (e.g., IE8), skip set up so that we\n // don't throw an error\n\n if (typeof Uint8Array === 'undefined') {\n return;\n }\n\n for (i in types) {\n if (types.hasOwnProperty(i)) {\n types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)];\n }\n }\n\n MAJOR_BRAND = new Uint8Array(['i'.charCodeAt(0), 's'.charCodeAt(0), 'o'.charCodeAt(0), 'm'.charCodeAt(0)]);\n AVC1_BRAND = new Uint8Array(['a'.charCodeAt(0), 'v'.charCodeAt(0), 'c'.charCodeAt(0), '1'.charCodeAt(0)]);\n MINOR_VERSION = new Uint8Array([0, 0, 0, 1]);\n VIDEO_HDLR = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler'\n ]);\n AUDIO_HDLR = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun'\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler'\n ]);\n HDLR_TYPES = {\n video: VIDEO_HDLR,\n audio: AUDIO_HDLR\n };\n DREF = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01, // entry_count\n 0x00, 0x00, 0x00, 0x0c, // entry_size\n 0x75, 0x72, 0x6c, 0x20, // 'url' type\n 0x00, // version 0\n 0x00, 0x00, 0x01 // entry_flags\n ]);\n SMHD = new Uint8Array([0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, // balance, 0 means centered\n 0x00, 0x00 // reserved\n ]);\n STCO = new Uint8Array([0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00 // entry_count\n ]);\n STSC = STCO;\n STSZ = new Uint8Array([0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // sample_size\n 0x00, 0x00, 0x00, 0x00 // sample_count\n ]);\n STTS = STCO;\n VMHD = new Uint8Array([0x00, // version\n 0x00, 0x00, 0x01, // flags\n 0x00, 0x00, // graphicsmode\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // opcolor\n ]);\n })();\n\n box = function box(type) {\n var payload = [],\n size = 0,\n i,\n result,\n view;\n\n for (i = 1; i < arguments.length; i++) {\n payload.push(arguments[i]);\n }\n\n i = payload.length; // calculate the total size we need to allocate\n\n while (i--) {\n size += payload[i].byteLength;\n }\n\n result = new Uint8Array(size + 8);\n view = new DataView(result.buffer, result.byteOffset, result.byteLength);\n view.setUint32(0, result.byteLength);\n result.set(type, 4); // copy the payload into the result\n\n for (i = 0, size = 8; i < payload.length; i++) {\n result.set(payload[i], size);\n size += payload[i].byteLength;\n }\n\n return result;\n };\n\n dinf = function dinf() {\n return box(types.dinf, box(types.dref, DREF));\n };\n\n esds = function esds(track) {\n return box(types.esds, new Uint8Array([0x00, // version\n 0x00, 0x00, 0x00, // flags\n // ES_Descriptor\n 0x03, // tag, ES_DescrTag\n 0x19, // length\n 0x00, 0x00, // ES_ID\n 0x00, // streamDependenceFlag, URL_flag, reserved, streamPriority\n // DecoderConfigDescriptor\n 0x04, // tag, DecoderConfigDescrTag\n 0x11, // length\n 0x40, // object type\n 0x15, // streamType\n 0x00, 0x06, 0x00, // bufferSizeDB\n 0x00, 0x00, 0xda, 0xc0, // maxBitrate\n 0x00, 0x00, 0xda, 0xc0, // avgBitrate\n // DecoderSpecificInfo\n 0x05, // tag, DecoderSpecificInfoTag\n 0x02, // length\n // ISO/IEC 14496-3, AudioSpecificConfig\n // for samplingFrequencyIndex see ISO/IEC 13818-7:2006, 8.1.3.2.2, Table 35\n track.audioobjecttype << 3 | track.samplingfrequencyindex >>> 1, track.samplingfrequencyindex << 7 | track.channelcount << 3, 0x06, 0x01, 0x02 // GASpecificConfig\n ]));\n };\n\n ftyp = function ftyp() {\n return box(types.ftyp, MAJOR_BRAND, MINOR_VERSION, MAJOR_BRAND, AVC1_BRAND);\n };\n\n hdlr = function hdlr(type) {\n return box(types.hdlr, HDLR_TYPES[type]);\n };\n\n mdat = function mdat(data) {\n return box(types.mdat, data);\n };\n\n mdhd = function mdhd(track) {\n var result = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x02, // creation_time\n 0x00, 0x00, 0x00, 0x03, // modification_time\n 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 \"ticks\" per second\n track.duration >>> 24 & 0xFF, track.duration >>> 16 & 0xFF, track.duration >>> 8 & 0xFF, track.duration & 0xFF, // duration\n 0x55, 0xc4, // 'und' language (undetermined)\n 0x00, 0x00]); // Use the sample rate from the track metadata, when it is\n // defined. The sample rate can be parsed out of an ADTS header, for\n // instance.\n\n if (track.samplerate) {\n result[12] = track.samplerate >>> 24 & 0xFF;\n result[13] = track.samplerate >>> 16 & 0xFF;\n result[14] = track.samplerate >>> 8 & 0xFF;\n result[15] = track.samplerate & 0xFF;\n }\n\n return box(types.mdhd, result);\n };\n\n mdia = function mdia(track) {\n return box(types.mdia, mdhd(track), hdlr(track.type), minf(track));\n };\n\n mfhd = function mfhd(sequenceNumber) {\n return box(types.mfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // flags\n (sequenceNumber & 0xFF000000) >> 24, (sequenceNumber & 0xFF0000) >> 16, (sequenceNumber & 0xFF00) >> 8, sequenceNumber & 0xFF // sequence_number\n ]));\n };\n\n minf = function minf(track) {\n return box(types.minf, track.type === 'video' ? box(types.vmhd, VMHD) : box(types.smhd, SMHD), dinf(), stbl(track));\n };\n\n moof = function moof(sequenceNumber, tracks) {\n var trackFragments = [],\n i = tracks.length; // build traf boxes for each track fragment\n\n while (i--) {\n trackFragments[i] = traf(tracks[i]);\n }\n\n return box.apply(null, [types.moof, mfhd(sequenceNumber)].concat(trackFragments));\n };\n /**\n * Returns a movie box.\n * @param tracks {array} the tracks associated with this movie\n * @see ISO/IEC 14496-12:2012(E), section 8.2.1\n */\n\n\n moov = function moov(tracks) {\n var i = tracks.length,\n boxes = [];\n\n while (i--) {\n boxes[i] = trak(tracks[i]);\n }\n\n return box.apply(null, [types.moov, mvhd(0xffffffff)].concat(boxes).concat(mvex(tracks)));\n };\n\n mvex = function mvex(tracks) {\n var i = tracks.length,\n boxes = [];\n\n while (i--) {\n boxes[i] = trex(tracks[i]);\n }\n\n return box.apply(null, [types.mvex].concat(boxes));\n };\n\n mvhd = function mvhd(duration) {\n var bytes = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01, // creation_time\n 0x00, 0x00, 0x00, 0x02, // modification_time\n 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 \"ticks\" per second\n (duration & 0xFF000000) >> 24, (duration & 0xFF0000) >> 16, (duration & 0xFF00) >> 8, duration & 0xFF, // duration\n 0x00, 0x01, 0x00, 0x00, // 1.0 rate\n 0x01, 0x00, // 1.0 volume\n 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0xff, 0xff, 0xff, 0xff // next_track_ID\n ]);\n return box(types.mvhd, bytes);\n };\n\n sdtp = function sdtp(track) {\n var samples = track.samples || [],\n bytes = new Uint8Array(4 + samples.length),\n flags,\n i; // leave the full box header (4 bytes) all zero\n // write the sample table\n\n for (i = 0; i < samples.length; i++) {\n flags = samples[i].flags;\n bytes[i + 4] = flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy;\n }\n\n return box(types.sdtp, bytes);\n };\n\n stbl = function stbl(track) {\n return box(types.stbl, stsd(track), box(types.stts, STTS), box(types.stsc, STSC), box(types.stsz, STSZ), box(types.stco, STCO));\n };\n\n (function () {\n var videoSample, audioSample;\n\n stsd = function stsd(track) {\n return box(types.stsd, new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01]), track.type === 'video' ? videoSample(track) : audioSample(track));\n };\n\n videoSample = function videoSample(track) {\n var sps = track.sps || [],\n pps = track.pps || [],\n sequenceParameterSets = [],\n pictureParameterSets = [],\n i,\n avc1Box; // assemble the SPSs\n\n for (i = 0; i < sps.length; i++) {\n sequenceParameterSets.push((sps[i].byteLength & 0xFF00) >>> 8);\n sequenceParameterSets.push(sps[i].byteLength & 0xFF); // sequenceParameterSetLength\n\n sequenceParameterSets = sequenceParameterSets.concat(Array.prototype.slice.call(sps[i])); // SPS\n } // assemble the PPSs\n\n\n for (i = 0; i < pps.length; i++) {\n pictureParameterSets.push((pps[i].byteLength & 0xFF00) >>> 8);\n pictureParameterSets.push(pps[i].byteLength & 0xFF);\n pictureParameterSets = pictureParameterSets.concat(Array.prototype.slice.call(pps[i]));\n }\n\n avc1Box = [types.avc1, new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // data_reference_index\n 0x00, 0x00, // pre_defined\n 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined\n (track.width & 0xff00) >> 8, track.width & 0xff, // width\n (track.height & 0xff00) >> 8, track.height & 0xff, // height\n 0x00, 0x48, 0x00, 0x00, // horizresolution\n 0x00, 0x48, 0x00, 0x00, // vertresolution\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // frame_count\n 0x13, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6a, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2d, 0x68, 0x6c, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname\n 0x00, 0x18, // depth = 24\n 0x11, 0x11 // pre_defined = -1\n ]), box(types.avcC, new Uint8Array([0x01, // configurationVersion\n track.profileIdc, // AVCProfileIndication\n track.profileCompatibility, // profile_compatibility\n track.levelIdc, // AVCLevelIndication\n 0xff // lengthSizeMinusOne, hard-coded to 4 bytes\n ].concat([sps.length], // numOfSequenceParameterSets\n sequenceParameterSets, // \"SPS\"\n [pps.length], // numOfPictureParameterSets\n pictureParameterSets // \"PPS\"\n ))), box(types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB\n 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate\n 0x00, 0x2d, 0xc6, 0xc0 // avgBitrate\n ]))];\n\n if (track.sarRatio) {\n var hSpacing = track.sarRatio[0],\n vSpacing = track.sarRatio[1];\n avc1Box.push(box(types.pasp, new Uint8Array([(hSpacing & 0xFF000000) >> 24, (hSpacing & 0xFF0000) >> 16, (hSpacing & 0xFF00) >> 8, hSpacing & 0xFF, (vSpacing & 0xFF000000) >> 24, (vSpacing & 0xFF0000) >> 16, (vSpacing & 0xFF00) >> 8, vSpacing & 0xFF])));\n }\n\n return box.apply(null, avc1Box);\n };\n\n audioSample = function audioSample(track) {\n return box(types.mp4a, new Uint8Array([// SampleEntry, ISO/IEC 14496-12\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // data_reference_index\n // AudioSampleEntry, ISO/IEC 14496-12\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n (track.channelcount & 0xff00) >> 8, track.channelcount & 0xff, // channelcount\n (track.samplesize & 0xff00) >> 8, track.samplesize & 0xff, // samplesize\n 0x00, 0x00, // pre_defined\n 0x00, 0x00, // reserved\n (track.samplerate & 0xff00) >> 8, track.samplerate & 0xff, 0x00, 0x00 // samplerate, 16.16\n // MP4AudioSampleEntry, ISO/IEC 14496-14\n ]), esds(track));\n };\n })();\n\n tkhd = function tkhd(track) {\n var result = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x07, // flags\n 0x00, 0x00, 0x00, 0x00, // creation_time\n 0x00, 0x00, 0x00, 0x00, // modification_time\n (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID\n 0x00, 0x00, 0x00, 0x00, // reserved\n (track.duration & 0xFF000000) >> 24, (track.duration & 0xFF0000) >> 16, (track.duration & 0xFF00) >> 8, track.duration & 0xFF, // duration\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, // layer\n 0x00, 0x00, // alternate_group\n 0x01, 0x00, // non-audio track volume\n 0x00, 0x00, // reserved\n 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix\n (track.width & 0xFF00) >> 8, track.width & 0xFF, 0x00, 0x00, // width\n (track.height & 0xFF00) >> 8, track.height & 0xFF, 0x00, 0x00 // height\n ]);\n return box(types.tkhd, result);\n };\n /**\n * Generate a track fragment (traf) box. A traf box collects metadata\n * about tracks in a movie fragment (moof) box.\n */\n\n\n traf = function traf(track) {\n var trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun, sampleDependencyTable, dataOffset, upperWordBaseMediaDecodeTime, lowerWordBaseMediaDecodeTime;\n trackFragmentHeader = box(types.tfhd, new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x3a, // flags\n (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID\n 0x00, 0x00, 0x00, 0x01, // sample_description_index\n 0x00, 0x00, 0x00, 0x00, // default_sample_duration\n 0x00, 0x00, 0x00, 0x00, // default_sample_size\n 0x00, 0x00, 0x00, 0x00 // default_sample_flags\n ]));\n upperWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime / MAX_UINT32);\n lowerWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime % MAX_UINT32);\n trackFragmentDecodeTime = box(types.tfdt, new Uint8Array([0x01, // version 1\n 0x00, 0x00, 0x00, // flags\n // baseMediaDecodeTime\n upperWordBaseMediaDecodeTime >>> 24 & 0xFF, upperWordBaseMediaDecodeTime >>> 16 & 0xFF, upperWordBaseMediaDecodeTime >>> 8 & 0xFF, upperWordBaseMediaDecodeTime & 0xFF, lowerWordBaseMediaDecodeTime >>> 24 & 0xFF, lowerWordBaseMediaDecodeTime >>> 16 & 0xFF, lowerWordBaseMediaDecodeTime >>> 8 & 0xFF, lowerWordBaseMediaDecodeTime & 0xFF])); // the data offset specifies the number of bytes from the start of\n // the containing moof to the first payload byte of the associated\n // mdat\n\n dataOffset = 32 + // tfhd\n 20 + // tfdt\n 8 + // traf header\n 16 + // mfhd\n 8 + // moof header\n 8; // mdat header\n // audio tracks require less metadata\n\n if (track.type === 'audio') {\n trackFragmentRun = trun$1(track, dataOffset);\n return box(types.traf, trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun);\n } // video tracks should contain an independent and disposable samples\n // box (sdtp)\n // generate one and adjust offsets to match\n\n\n sampleDependencyTable = sdtp(track);\n trackFragmentRun = trun$1(track, sampleDependencyTable.length + dataOffset);\n return box(types.traf, trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun, sampleDependencyTable);\n };\n /**\n * Generate a track box.\n * @param track {object} a track definition\n * @return {Uint8Array} the track box\n */\n\n\n trak = function trak(track) {\n track.duration = track.duration || 0xffffffff;\n return box(types.trak, tkhd(track), mdia(track));\n };\n\n trex = function trex(track) {\n var result = new Uint8Array([0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID\n 0x00, 0x00, 0x00, 0x01, // default_sample_description_index\n 0x00, 0x00, 0x00, 0x00, // default_sample_duration\n 0x00, 0x00, 0x00, 0x00, // default_sample_size\n 0x00, 0x01, 0x00, 0x01 // default_sample_flags\n ]); // the last two bytes of default_sample_flags is the sample\n // degradation priority, a hint about the importance of this sample\n // relative to others. Lower the degradation priority for all sample\n // types other than video.\n\n if (track.type !== 'video') {\n result[result.length - 1] = 0x00;\n }\n\n return box(types.trex, result);\n };\n\n (function () {\n var audioTrun, videoTrun, trunHeader; // This method assumes all samples are uniform. That is, if a\n // duration is present for the first sample, it will be present for\n // all subsequent samples.\n // see ISO/IEC 14496-12:2012, Section 8.8.8.1\n\n trunHeader = function trunHeader(samples, offset) {\n var durationPresent = 0,\n sizePresent = 0,\n flagsPresent = 0,\n compositionTimeOffset = 0; // trun flag constants\n\n if (samples.length) {\n if (samples[0].duration !== undefined) {\n durationPresent = 0x1;\n }\n\n if (samples[0].size !== undefined) {\n sizePresent = 0x2;\n }\n\n if (samples[0].flags !== undefined) {\n flagsPresent = 0x4;\n }\n\n if (samples[0].compositionTimeOffset !== undefined) {\n compositionTimeOffset = 0x8;\n }\n }\n\n return [0x00, // version 0\n 0x00, durationPresent | sizePresent | flagsPresent | compositionTimeOffset, 0x01, // flags\n (samples.length & 0xFF000000) >>> 24, (samples.length & 0xFF0000) >>> 16, (samples.length & 0xFF00) >>> 8, samples.length & 0xFF, // sample_count\n (offset & 0xFF000000) >>> 24, (offset & 0xFF0000) >>> 16, (offset & 0xFF00) >>> 8, offset & 0xFF // data_offset\n ];\n };\n\n videoTrun = function videoTrun(track, offset) {\n var bytesOffest, bytes, header, samples, sample, i;\n samples = track.samples || [];\n offset += 8 + 12 + 16 * samples.length;\n header = trunHeader(samples, offset);\n bytes = new Uint8Array(header.length + samples.length * 16);\n bytes.set(header);\n bytesOffest = header.length;\n\n for (i = 0; i < samples.length; i++) {\n sample = samples[i];\n bytes[bytesOffest++] = (sample.duration & 0xFF000000) >>> 24;\n bytes[bytesOffest++] = (sample.duration & 0xFF0000) >>> 16;\n bytes[bytesOffest++] = (sample.duration & 0xFF00) >>> 8;\n bytes[bytesOffest++] = sample.duration & 0xFF; // sample_duration\n\n bytes[bytesOffest++] = (sample.size & 0xFF000000) >>> 24;\n bytes[bytesOffest++] = (sample.size & 0xFF0000) >>> 16;\n bytes[bytesOffest++] = (sample.size & 0xFF00) >>> 8;\n bytes[bytesOffest++] = sample.size & 0xFF; // sample_size\n\n bytes[bytesOffest++] = sample.flags.isLeading << 2 | sample.flags.dependsOn;\n bytes[bytesOffest++] = sample.flags.isDependedOn << 6 | sample.flags.hasRedundancy << 4 | sample.flags.paddingValue << 1 | sample.flags.isNonSyncSample;\n bytes[bytesOffest++] = sample.flags.degradationPriority & 0xF0 << 8;\n bytes[bytesOffest++] = sample.flags.degradationPriority & 0x0F; // sample_flags\n\n bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF000000) >>> 24;\n bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF0000) >>> 16;\n bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF00) >>> 8;\n bytes[bytesOffest++] = sample.compositionTimeOffset & 0xFF; // sample_composition_time_offset\n }\n\n return box(types.trun, bytes);\n };\n\n audioTrun = function audioTrun(track, offset) {\n var bytes, bytesOffest, header, samples, sample, i;\n samples = track.samples || [];\n offset += 8 + 12 + 8 * samples.length;\n header = trunHeader(samples, offset);\n bytes = new Uint8Array(header.length + samples.length * 8);\n bytes.set(header);\n bytesOffest = header.length;\n\n for (i = 0; i < samples.length; i++) {\n sample = samples[i];\n bytes[bytesOffest++] = (sample.duration & 0xFF000000) >>> 24;\n bytes[bytesOffest++] = (sample.duration & 0xFF0000) >>> 16;\n bytes[bytesOffest++] = (sample.duration & 0xFF00) >>> 8;\n bytes[bytesOffest++] = sample.duration & 0xFF; // sample_duration\n\n bytes[bytesOffest++] = (sample.size & 0xFF000000) >>> 24;\n bytes[bytesOffest++] = (sample.size & 0xFF0000) >>> 16;\n bytes[bytesOffest++] = (sample.size & 0xFF00) >>> 8;\n bytes[bytesOffest++] = sample.size & 0xFF; // sample_size\n }\n\n return box(types.trun, bytes);\n };\n\n trun$1 = function trun(track, offset) {\n if (track.type === 'audio') {\n return audioTrun(track, offset);\n }\n\n return videoTrun(track, offset);\n };\n })();\n\n var mp4Generator = {\n ftyp: ftyp,\n mdat: mdat,\n moof: moof,\n moov: moov,\n initSegment: function initSegment(tracks) {\n var fileType = ftyp(),\n movie = moov(tracks),\n result;\n result = new Uint8Array(fileType.byteLength + movie.byteLength);\n result.set(fileType);\n result.set(movie, fileType.byteLength);\n return result;\n }\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n // Convert an array of nal units into an array of frames with each frame being\n // composed of the nal units that make up that frame\n // Also keep track of cummulative data about the frame from the nal units such\n // as the frame duration, starting pts, etc.\n\n var groupNalsIntoFrames = function groupNalsIntoFrames(nalUnits) {\n var i,\n currentNal,\n currentFrame = [],\n frames = []; // TODO added for LHLS, make sure this is OK\n\n frames.byteLength = 0;\n frames.nalCount = 0;\n frames.duration = 0;\n currentFrame.byteLength = 0;\n\n for (i = 0; i < nalUnits.length; i++) {\n currentNal = nalUnits[i]; // Split on 'aud'-type nal units\n\n if (currentNal.nalUnitType === 'access_unit_delimiter_rbsp') {\n // Since the very first nal unit is expected to be an AUD\n // only push to the frames array when currentFrame is not empty\n if (currentFrame.length) {\n currentFrame.duration = currentNal.dts - currentFrame.dts; // TODO added for LHLS, make sure this is OK\n\n frames.byteLength += currentFrame.byteLength;\n frames.nalCount += currentFrame.length;\n frames.duration += currentFrame.duration;\n frames.push(currentFrame);\n }\n\n currentFrame = [currentNal];\n currentFrame.byteLength = currentNal.data.byteLength;\n currentFrame.pts = currentNal.pts;\n currentFrame.dts = currentNal.dts;\n } else {\n // Specifically flag key frames for ease of use later\n if (currentNal.nalUnitType === 'slice_layer_without_partitioning_rbsp_idr') {\n currentFrame.keyFrame = true;\n }\n\n currentFrame.duration = currentNal.dts - currentFrame.dts;\n currentFrame.byteLength += currentNal.data.byteLength;\n currentFrame.push(currentNal);\n }\n } // For the last frame, use the duration of the previous frame if we\n // have nothing better to go on\n\n\n if (frames.length && (!currentFrame.duration || currentFrame.duration <= 0)) {\n currentFrame.duration = frames[frames.length - 1].duration;\n } // Push the final frame\n // TODO added for LHLS, make sure this is OK\n\n\n frames.byteLength += currentFrame.byteLength;\n frames.nalCount += currentFrame.length;\n frames.duration += currentFrame.duration;\n frames.push(currentFrame);\n return frames;\n }; // Convert an array of frames into an array of Gop with each Gop being composed\n // of the frames that make up that Gop\n // Also keep track of cummulative data about the Gop from the frames such as the\n // Gop duration, starting pts, etc.\n\n\n var groupFramesIntoGops = function groupFramesIntoGops(frames) {\n var i,\n currentFrame,\n currentGop = [],\n gops = []; // We must pre-set some of the values on the Gop since we\n // keep running totals of these values\n\n currentGop.byteLength = 0;\n currentGop.nalCount = 0;\n currentGop.duration = 0;\n currentGop.pts = frames[0].pts;\n currentGop.dts = frames[0].dts; // store some metadata about all the Gops\n\n gops.byteLength = 0;\n gops.nalCount = 0;\n gops.duration = 0;\n gops.pts = frames[0].pts;\n gops.dts = frames[0].dts;\n\n for (i = 0; i < frames.length; i++) {\n currentFrame = frames[i];\n\n if (currentFrame.keyFrame) {\n // Since the very first frame is expected to be an keyframe\n // only push to the gops array when currentGop is not empty\n if (currentGop.length) {\n gops.push(currentGop);\n gops.byteLength += currentGop.byteLength;\n gops.nalCount += currentGop.nalCount;\n gops.duration += currentGop.duration;\n }\n\n currentGop = [currentFrame];\n currentGop.nalCount = currentFrame.length;\n currentGop.byteLength = currentFrame.byteLength;\n currentGop.pts = currentFrame.pts;\n currentGop.dts = currentFrame.dts;\n currentGop.duration = currentFrame.duration;\n } else {\n currentGop.duration += currentFrame.duration;\n currentGop.nalCount += currentFrame.length;\n currentGop.byteLength += currentFrame.byteLength;\n currentGop.push(currentFrame);\n }\n }\n\n if (gops.length && currentGop.duration <= 0) {\n currentGop.duration = gops[gops.length - 1].duration;\n }\n\n gops.byteLength += currentGop.byteLength;\n gops.nalCount += currentGop.nalCount;\n gops.duration += currentGop.duration; // push the final Gop\n\n gops.push(currentGop);\n return gops;\n };\n /*\n * Search for the first keyframe in the GOPs and throw away all frames\n * until that keyframe. Then extend the duration of the pulled keyframe\n * and pull the PTS and DTS of the keyframe so that it covers the time\n * range of the frames that were disposed.\n *\n * @param {Array} gops video GOPs\n * @returns {Array} modified video GOPs\n */\n\n\n var extendFirstKeyFrame = function extendFirstKeyFrame(gops) {\n var currentGop;\n\n if (!gops[0][0].keyFrame && gops.length > 1) {\n // Remove the first GOP\n currentGop = gops.shift();\n gops.byteLength -= currentGop.byteLength;\n gops.nalCount -= currentGop.nalCount; // Extend the first frame of what is now the\n // first gop to cover the time period of the\n // frames we just removed\n\n gops[0][0].dts = currentGop.dts;\n gops[0][0].pts = currentGop.pts;\n gops[0][0].duration += currentGop.duration;\n }\n\n return gops;\n };\n /**\n * Default sample object\n * see ISO/IEC 14496-12:2012, section 8.6.4.3\n */\n\n\n var createDefaultSample = function createDefaultSample() {\n return {\n size: 0,\n flags: {\n isLeading: 0,\n dependsOn: 1,\n isDependedOn: 0,\n hasRedundancy: 0,\n degradationPriority: 0,\n isNonSyncSample: 1\n }\n };\n };\n /*\n * Collates information from a video frame into an object for eventual\n * entry into an MP4 sample table.\n *\n * @param {Object} frame the video frame\n * @param {Number} dataOffset the byte offset to position the sample\n * @return {Object} object containing sample table info for a frame\n */\n\n\n var sampleForFrame = function sampleForFrame(frame, dataOffset) {\n var sample = createDefaultSample();\n sample.dataOffset = dataOffset;\n sample.compositionTimeOffset = frame.pts - frame.dts;\n sample.duration = frame.duration;\n sample.size = 4 * frame.length; // Space for nal unit size\n\n sample.size += frame.byteLength;\n\n if (frame.keyFrame) {\n sample.flags.dependsOn = 2;\n sample.flags.isNonSyncSample = 0;\n }\n\n return sample;\n }; // generate the track's sample table from an array of gops\n\n\n var generateSampleTable$1 = function generateSampleTable(gops, baseDataOffset) {\n var h,\n i,\n sample,\n currentGop,\n currentFrame,\n dataOffset = baseDataOffset || 0,\n samples = [];\n\n for (h = 0; h < gops.length; h++) {\n currentGop = gops[h];\n\n for (i = 0; i < currentGop.length; i++) {\n currentFrame = currentGop[i];\n sample = sampleForFrame(currentFrame, dataOffset);\n dataOffset += sample.size;\n samples.push(sample);\n }\n }\n\n return samples;\n }; // generate the track's raw mdat data from an array of gops\n\n\n var concatenateNalData = function concatenateNalData(gops) {\n var h,\n i,\n j,\n currentGop,\n currentFrame,\n currentNal,\n dataOffset = 0,\n nalsByteLength = gops.byteLength,\n numberOfNals = gops.nalCount,\n totalByteLength = nalsByteLength + 4 * numberOfNals,\n data = new Uint8Array(totalByteLength),\n view = new DataView(data.buffer); // For each Gop..\n\n for (h = 0; h < gops.length; h++) {\n currentGop = gops[h]; // For each Frame..\n\n for (i = 0; i < currentGop.length; i++) {\n currentFrame = currentGop[i]; // For each NAL..\n\n for (j = 0; j < currentFrame.length; j++) {\n currentNal = currentFrame[j];\n view.setUint32(dataOffset, currentNal.data.byteLength);\n dataOffset += 4;\n data.set(currentNal.data, dataOffset);\n dataOffset += currentNal.data.byteLength;\n }\n }\n }\n\n return data;\n }; // generate the track's sample table from a frame\n\n\n var generateSampleTableForFrame = function generateSampleTableForFrame(frame, baseDataOffset) {\n var sample,\n dataOffset = baseDataOffset || 0,\n samples = [];\n sample = sampleForFrame(frame, dataOffset);\n samples.push(sample);\n return samples;\n }; // generate the track's raw mdat data from a frame\n\n\n var concatenateNalDataForFrame = function concatenateNalDataForFrame(frame) {\n var i,\n currentNal,\n dataOffset = 0,\n nalsByteLength = frame.byteLength,\n numberOfNals = frame.length,\n totalByteLength = nalsByteLength + 4 * numberOfNals,\n data = new Uint8Array(totalByteLength),\n view = new DataView(data.buffer); // For each NAL..\n\n for (i = 0; i < frame.length; i++) {\n currentNal = frame[i];\n view.setUint32(dataOffset, currentNal.data.byteLength);\n dataOffset += 4;\n data.set(currentNal.data, dataOffset);\n dataOffset += currentNal.data.byteLength;\n }\n\n return data;\n };\n\n var frameUtils = {\n groupNalsIntoFrames: groupNalsIntoFrames,\n groupFramesIntoGops: groupFramesIntoGops,\n extendFirstKeyFrame: extendFirstKeyFrame,\n generateSampleTable: generateSampleTable$1,\n concatenateNalData: concatenateNalData,\n generateSampleTableForFrame: generateSampleTableForFrame,\n concatenateNalDataForFrame: concatenateNalDataForFrame\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n var highPrefix = [33, 16, 5, 32, 164, 27];\n var lowPrefix = [33, 65, 108, 84, 1, 2, 4, 8, 168, 2, 4, 8, 17, 191, 252];\n\n var zeroFill = function zeroFill(count) {\n var a = [];\n\n while (count--) {\n a.push(0);\n }\n\n return a;\n };\n\n var makeTable = function makeTable(metaTable) {\n return Object.keys(metaTable).reduce(function (obj, key) {\n obj[key] = new Uint8Array(metaTable[key].reduce(function (arr, part) {\n return arr.concat(part);\n }, []));\n return obj;\n }, {});\n };\n\n var silence;\n\n var silence_1 = function silence_1() {\n if (!silence) {\n // Frames-of-silence to use for filling in missing AAC frames\n var coneOfSilence = {\n 96000: [highPrefix, [227, 64], zeroFill(154), [56]],\n 88200: [highPrefix, [231], zeroFill(170), [56]],\n 64000: [highPrefix, [248, 192], zeroFill(240), [56]],\n 48000: [highPrefix, [255, 192], zeroFill(268), [55, 148, 128], zeroFill(54), [112]],\n 44100: [highPrefix, [255, 192], zeroFill(268), [55, 163, 128], zeroFill(84), [112]],\n 32000: [highPrefix, [255, 192], zeroFill(268), [55, 234], zeroFill(226), [112]],\n 24000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 112], zeroFill(126), [224]],\n 16000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 255], zeroFill(269), [223, 108], zeroFill(195), [1, 192]],\n 12000: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 253, 128], zeroFill(259), [56]],\n 11025: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 255, 192], zeroFill(268), [55, 175, 128], zeroFill(108), [112]],\n 8000: [lowPrefix, zeroFill(268), [3, 121, 16], zeroFill(47), [7]]\n };\n silence = makeTable(coneOfSilence);\n }\n\n return silence;\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n\n var ONE_SECOND_IN_TS$4 = 90000,\n // 90kHz clock\n secondsToVideoTs,\n secondsToAudioTs,\n videoTsToSeconds,\n audioTsToSeconds,\n audioTsToVideoTs,\n videoTsToAudioTs,\n metadataTsToSeconds;\n\n secondsToVideoTs = function secondsToVideoTs(seconds) {\n return seconds * ONE_SECOND_IN_TS$4;\n };\n\n secondsToAudioTs = function secondsToAudioTs(seconds, sampleRate) {\n return seconds * sampleRate;\n };\n\n videoTsToSeconds = function videoTsToSeconds(timestamp) {\n return timestamp / ONE_SECOND_IN_TS$4;\n };\n\n audioTsToSeconds = function audioTsToSeconds(timestamp, sampleRate) {\n return timestamp / sampleRate;\n };\n\n audioTsToVideoTs = function audioTsToVideoTs(timestamp, sampleRate) {\n return secondsToVideoTs(audioTsToSeconds(timestamp, sampleRate));\n };\n\n videoTsToAudioTs = function videoTsToAudioTs(timestamp, sampleRate) {\n return secondsToAudioTs(videoTsToSeconds(timestamp), sampleRate);\n };\n /**\n * Adjust ID3 tag or caption timing information by the timeline pts values\n * (if keepOriginalTimestamps is false) and convert to seconds\n */\n\n\n metadataTsToSeconds = function metadataTsToSeconds(timestamp, timelineStartPts, keepOriginalTimestamps) {\n return videoTsToSeconds(keepOriginalTimestamps ? timestamp : timestamp - timelineStartPts);\n };\n\n var clock = {\n ONE_SECOND_IN_TS: ONE_SECOND_IN_TS$4,\n secondsToVideoTs: secondsToVideoTs,\n secondsToAudioTs: secondsToAudioTs,\n videoTsToSeconds: videoTsToSeconds,\n audioTsToSeconds: audioTsToSeconds,\n audioTsToVideoTs: audioTsToVideoTs,\n videoTsToAudioTs: videoTsToAudioTs,\n metadataTsToSeconds: metadataTsToSeconds\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n /**\n * Sum the `byteLength` properties of the data in each AAC frame\n */\n\n var sumFrameByteLengths = function sumFrameByteLengths(array) {\n var i,\n currentObj,\n sum = 0; // sum the byteLength's all each nal unit in the frame\n\n for (i = 0; i < array.length; i++) {\n currentObj = array[i];\n sum += currentObj.data.byteLength;\n }\n\n return sum;\n }; // Possibly pad (prefix) the audio track with silence if appending this track\n // would lead to the introduction of a gap in the audio buffer\n\n\n var prefixWithSilence = function prefixWithSilence(track, frames, audioAppendStartTs, videoBaseMediaDecodeTime) {\n var baseMediaDecodeTimeTs,\n frameDuration = 0,\n audioGapDuration = 0,\n audioFillFrameCount = 0,\n audioFillDuration = 0,\n silentFrame,\n i,\n firstFrame;\n\n if (!frames.length) {\n return;\n }\n\n baseMediaDecodeTimeTs = clock.audioTsToVideoTs(track.baseMediaDecodeTime, track.samplerate); // determine frame clock duration based on sample rate, round up to avoid overfills\n\n frameDuration = Math.ceil(clock.ONE_SECOND_IN_TS / (track.samplerate / 1024));\n\n if (audioAppendStartTs && videoBaseMediaDecodeTime) {\n // insert the shortest possible amount (audio gap or audio to video gap)\n audioGapDuration = baseMediaDecodeTimeTs - Math.max(audioAppendStartTs, videoBaseMediaDecodeTime); // number of full frames in the audio gap\n\n audioFillFrameCount = Math.floor(audioGapDuration / frameDuration);\n audioFillDuration = audioFillFrameCount * frameDuration;\n } // don't attempt to fill gaps smaller than a single frame or larger\n // than a half second\n\n\n if (audioFillFrameCount < 1 || audioFillDuration > clock.ONE_SECOND_IN_TS / 2) {\n return;\n }\n\n silentFrame = silence_1()[track.samplerate];\n\n if (!silentFrame) {\n // we don't have a silent frame pregenerated for the sample rate, so use a frame\n // from the content instead\n silentFrame = frames[0].data;\n }\n\n for (i = 0; i < audioFillFrameCount; i++) {\n firstFrame = frames[0];\n frames.splice(0, 0, {\n data: silentFrame,\n dts: firstFrame.dts - frameDuration,\n pts: firstFrame.pts - frameDuration\n });\n }\n\n track.baseMediaDecodeTime -= Math.floor(clock.videoTsToAudioTs(audioFillDuration, track.samplerate));\n return audioFillDuration;\n }; // If the audio segment extends before the earliest allowed dts\n // value, remove AAC frames until starts at or after the earliest\n // allowed DTS so that we don't end up with a negative baseMedia-\n // DecodeTime for the audio track\n\n\n var trimAdtsFramesByEarliestDts = function trimAdtsFramesByEarliestDts(adtsFrames, track, earliestAllowedDts) {\n if (track.minSegmentDts >= earliestAllowedDts) {\n return adtsFrames;\n } // We will need to recalculate the earliest segment Dts\n\n\n track.minSegmentDts = Infinity;\n return adtsFrames.filter(function (currentFrame) {\n // If this is an allowed frame, keep it and record it's Dts\n if (currentFrame.dts >= earliestAllowedDts) {\n track.minSegmentDts = Math.min(track.minSegmentDts, currentFrame.dts);\n track.minSegmentPts = track.minSegmentDts;\n return true;\n } // Otherwise, discard it\n\n\n return false;\n });\n }; // generate the track's raw mdat data from an array of frames\n\n\n var generateSampleTable = function generateSampleTable(frames) {\n var i,\n currentFrame,\n samples = [];\n\n for (i = 0; i < frames.length; i++) {\n currentFrame = frames[i];\n samples.push({\n size: currentFrame.data.byteLength,\n duration: 1024 // For AAC audio, all samples contain 1024 samples\n\n });\n }\n\n return samples;\n }; // generate the track's sample table from an array of frames\n\n\n var concatenateFrameData = function concatenateFrameData(frames) {\n var i,\n currentFrame,\n dataOffset = 0,\n data = new Uint8Array(sumFrameByteLengths(frames));\n\n for (i = 0; i < frames.length; i++) {\n currentFrame = frames[i];\n data.set(currentFrame.data, dataOffset);\n dataOffset += currentFrame.data.byteLength;\n }\n\n return data;\n };\n\n var audioFrameUtils = {\n prefixWithSilence: prefixWithSilence,\n trimAdtsFramesByEarliestDts: trimAdtsFramesByEarliestDts,\n generateSampleTable: generateSampleTable,\n concatenateFrameData: concatenateFrameData\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n var ONE_SECOND_IN_TS$3 = clock.ONE_SECOND_IN_TS;\n /**\n * Store information about the start and end of the track and the\n * duration for each frame/sample we process in order to calculate\n * the baseMediaDecodeTime\n */\n\n var collectDtsInfo = function collectDtsInfo(track, data) {\n if (typeof data.pts === 'number') {\n if (track.timelineStartInfo.pts === undefined) {\n track.timelineStartInfo.pts = data.pts;\n }\n\n if (track.minSegmentPts === undefined) {\n track.minSegmentPts = data.pts;\n } else {\n track.minSegmentPts = Math.min(track.minSegmentPts, data.pts);\n }\n\n if (track.maxSegmentPts === undefined) {\n track.maxSegmentPts = data.pts;\n } else {\n track.maxSegmentPts = Math.max(track.maxSegmentPts, data.pts);\n }\n }\n\n if (typeof data.dts === 'number') {\n if (track.timelineStartInfo.dts === undefined) {\n track.timelineStartInfo.dts = data.dts;\n }\n\n if (track.minSegmentDts === undefined) {\n track.minSegmentDts = data.dts;\n } else {\n track.minSegmentDts = Math.min(track.minSegmentDts, data.dts);\n }\n\n if (track.maxSegmentDts === undefined) {\n track.maxSegmentDts = data.dts;\n } else {\n track.maxSegmentDts = Math.max(track.maxSegmentDts, data.dts);\n }\n }\n };\n /**\n * Clear values used to calculate the baseMediaDecodeTime between\n * tracks\n */\n\n\n var clearDtsInfo = function clearDtsInfo(track) {\n delete track.minSegmentDts;\n delete track.maxSegmentDts;\n delete track.minSegmentPts;\n delete track.maxSegmentPts;\n };\n /**\n * Calculate the track's baseMediaDecodeTime based on the earliest\n * DTS the transmuxer has ever seen and the minimum DTS for the\n * current track\n * @param track {object} track metadata configuration\n * @param keepOriginalTimestamps {boolean} If true, keep the timestamps\n * in the source; false to adjust the first segment to start at 0.\n */\n\n\n var calculateTrackBaseMediaDecodeTime = function calculateTrackBaseMediaDecodeTime(track, keepOriginalTimestamps) {\n var baseMediaDecodeTime,\n scale,\n minSegmentDts = track.minSegmentDts; // Optionally adjust the time so the first segment starts at zero.\n\n if (!keepOriginalTimestamps) {\n minSegmentDts -= track.timelineStartInfo.dts;\n } // track.timelineStartInfo.baseMediaDecodeTime is the location, in time, where\n // we want the start of the first segment to be placed\n\n\n baseMediaDecodeTime = track.timelineStartInfo.baseMediaDecodeTime; // Add to that the distance this segment is from the very first\n\n baseMediaDecodeTime += minSegmentDts; // baseMediaDecodeTime must not become negative\n\n baseMediaDecodeTime = Math.max(0, baseMediaDecodeTime);\n\n if (track.type === 'audio') {\n // Audio has a different clock equal to the sampling_rate so we need to\n // scale the PTS values into the clock rate of the track\n scale = track.samplerate / ONE_SECOND_IN_TS$3;\n baseMediaDecodeTime *= scale;\n baseMediaDecodeTime = Math.floor(baseMediaDecodeTime);\n }\n\n return baseMediaDecodeTime;\n };\n\n var trackDecodeInfo = {\n clearDtsInfo: clearDtsInfo,\n calculateTrackBaseMediaDecodeTime: calculateTrackBaseMediaDecodeTime,\n collectDtsInfo: collectDtsInfo\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n *\n * Reads in-band caption information from a video elementary\n * stream. Captions must follow the CEA-708 standard for injection\n * into an MPEG-2 transport streams.\n * @see https://en.wikipedia.org/wiki/CEA-708\n * @see https://www.gpo.gov/fdsys/pkg/CFR-2007-title47-vol1/pdf/CFR-2007-title47-vol1-sec15-119.pdf\n */\n // payload type field to indicate how they are to be\n // interpreted. CEAS-708 caption content is always transmitted with\n // payload type 0x04.\n\n var USER_DATA_REGISTERED_ITU_T_T35 = 4,\n RBSP_TRAILING_BITS = 128;\n /**\n * Parse a supplemental enhancement information (SEI) NAL unit.\n * Stops parsing once a message of type ITU T T35 has been found.\n *\n * @param bytes {Uint8Array} the bytes of a SEI NAL unit\n * @return {object} the parsed SEI payload\n * @see Rec. ITU-T H.264, 7.3.2.3.1\n */\n\n var parseSei = function parseSei(bytes) {\n var i = 0,\n result = {\n payloadType: -1,\n payloadSize: 0\n },\n payloadType = 0,\n payloadSize = 0; // go through the sei_rbsp parsing each each individual sei_message\n\n while (i < bytes.byteLength) {\n // stop once we have hit the end of the sei_rbsp\n if (bytes[i] === RBSP_TRAILING_BITS) {\n break;\n } // Parse payload type\n\n\n while (bytes[i] === 0xFF) {\n payloadType += 255;\n i++;\n }\n\n payloadType += bytes[i++]; // Parse payload size\n\n while (bytes[i] === 0xFF) {\n payloadSize += 255;\n i++;\n }\n\n payloadSize += bytes[i++]; // this sei_message is a 608/708 caption so save it and break\n // there can only ever be one caption message in a frame's sei\n\n if (!result.payload && payloadType === USER_DATA_REGISTERED_ITU_T_T35) {\n var userIdentifier = String.fromCharCode(bytes[i + 3], bytes[i + 4], bytes[i + 5], bytes[i + 6]);\n\n if (userIdentifier === 'GA94') {\n result.payloadType = payloadType;\n result.payloadSize = payloadSize;\n result.payload = bytes.subarray(i, i + payloadSize);\n break;\n } else {\n result.payload = void 0;\n }\n } // skip the payload and parse the next message\n\n\n i += payloadSize;\n payloadType = 0;\n payloadSize = 0;\n }\n\n return result;\n }; // see ANSI/SCTE 128-1 (2013), section 8.1\n\n\n var parseUserData = function parseUserData(sei) {\n // itu_t_t35_contry_code must be 181 (United States) for\n // captions\n if (sei.payload[0] !== 181) {\n return null;\n } // itu_t_t35_provider_code should be 49 (ATSC) for captions\n\n\n if ((sei.payload[1] << 8 | sei.payload[2]) !== 49) {\n return null;\n } // the user_identifier should be \"GA94\" to indicate ATSC1 data\n\n\n if (String.fromCharCode(sei.payload[3], sei.payload[4], sei.payload[5], sei.payload[6]) !== 'GA94') {\n return null;\n } // finally, user_data_type_code should be 0x03 for caption data\n\n\n if (sei.payload[7] !== 0x03) {\n return null;\n } // return the user_data_type_structure and strip the trailing\n // marker bits\n\n\n return sei.payload.subarray(8, sei.payload.length - 1);\n }; // see CEA-708-D, section 4.4\n\n\n var parseCaptionPackets = function parseCaptionPackets(pts, userData) {\n var results = [],\n i,\n count,\n offset,\n data; // if this is just filler, return immediately\n\n if (!(userData[0] & 0x40)) {\n return results;\n } // parse out the cc_data_1 and cc_data_2 fields\n\n\n count = userData[0] & 0x1f;\n\n for (i = 0; i < count; i++) {\n offset = i * 3;\n data = {\n type: userData[offset + 2] & 0x03,\n pts: pts\n }; // capture cc data when cc_valid is 1\n\n if (userData[offset + 2] & 0x04) {\n data.ccData = userData[offset + 3] << 8 | userData[offset + 4];\n results.push(data);\n }\n }\n\n return results;\n };\n\n var discardEmulationPreventionBytes$1 = function discardEmulationPreventionBytes(data) {\n var length = data.byteLength,\n emulationPreventionBytesPositions = [],\n i = 1,\n newLength,\n newData; // Find all `Emulation Prevention Bytes`\n\n while (i < length - 2) {\n if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {\n emulationPreventionBytesPositions.push(i + 2);\n i += 2;\n } else {\n i++;\n }\n } // If no Emulation Prevention Bytes were found just return the original\n // array\n\n\n if (emulationPreventionBytesPositions.length === 0) {\n return data;\n } // Create a new array to hold the NAL unit data\n\n\n newLength = length - emulationPreventionBytesPositions.length;\n newData = new Uint8Array(newLength);\n var sourceIndex = 0;\n\n for (i = 0; i < newLength; sourceIndex++, i++) {\n if (sourceIndex === emulationPreventionBytesPositions[0]) {\n // Skip this byte\n sourceIndex++; // Remove this position index\n\n emulationPreventionBytesPositions.shift();\n }\n\n newData[i] = data[sourceIndex];\n }\n\n return newData;\n }; // exports\n\n\n var captionPacketParser = {\n parseSei: parseSei,\n parseUserData: parseUserData,\n parseCaptionPackets: parseCaptionPackets,\n discardEmulationPreventionBytes: discardEmulationPreventionBytes$1,\n USER_DATA_REGISTERED_ITU_T_T35: USER_DATA_REGISTERED_ITU_T_T35\n }; // Link To Transport\n // -----------------\n\n var CaptionStream$1 = function CaptionStream(options) {\n options = options || {};\n CaptionStream.prototype.init.call(this); // parse708captions flag, default to true\n\n this.parse708captions_ = typeof options.parse708captions === 'boolean' ? options.parse708captions : true;\n this.captionPackets_ = [];\n this.ccStreams_ = [new Cea608Stream(0, 0), // eslint-disable-line no-use-before-define\n new Cea608Stream(0, 1), // eslint-disable-line no-use-before-define\n new Cea608Stream(1, 0), // eslint-disable-line no-use-before-define\n new Cea608Stream(1, 1) // eslint-disable-line no-use-before-define\n ];\n\n if (this.parse708captions_) {\n this.cc708Stream_ = new Cea708Stream({\n captionServices: options.captionServices\n }); // eslint-disable-line no-use-before-define\n }\n\n this.reset(); // forward data and done events from CCs to this CaptionStream\n\n this.ccStreams_.forEach(function (cc) {\n cc.on('data', this.trigger.bind(this, 'data'));\n cc.on('partialdone', this.trigger.bind(this, 'partialdone'));\n cc.on('done', this.trigger.bind(this, 'done'));\n }, this);\n\n if (this.parse708captions_) {\n this.cc708Stream_.on('data', this.trigger.bind(this, 'data'));\n this.cc708Stream_.on('partialdone', this.trigger.bind(this, 'partialdone'));\n this.cc708Stream_.on('done', this.trigger.bind(this, 'done'));\n }\n };\n\n CaptionStream$1.prototype = new stream();\n\n CaptionStream$1.prototype.push = function (event) {\n var sei, userData, newCaptionPackets; // only examine SEI NALs\n\n if (event.nalUnitType !== 'sei_rbsp') {\n return;\n } // parse the sei\n\n\n sei = captionPacketParser.parseSei(event.escapedRBSP); // no payload data, skip\n\n if (!sei.payload) {\n return;\n } // ignore everything but user_data_registered_itu_t_t35\n\n\n if (sei.payloadType !== captionPacketParser.USER_DATA_REGISTERED_ITU_T_T35) {\n return;\n } // parse out the user data payload\n\n\n userData = captionPacketParser.parseUserData(sei); // ignore unrecognized userData\n\n if (!userData) {\n return;\n } // Sometimes, the same segment # will be downloaded twice. To stop the\n // caption data from being processed twice, we track the latest dts we've\n // received and ignore everything with a dts before that. However, since\n // data for a specific dts can be split across packets on either side of\n // a segment boundary, we need to make sure we *don't* ignore the packets\n // from the *next* segment that have dts === this.latestDts_. By constantly\n // tracking the number of packets received with dts === this.latestDts_, we\n // know how many should be ignored once we start receiving duplicates.\n\n\n if (event.dts < this.latestDts_) {\n // We've started getting older data, so set the flag.\n this.ignoreNextEqualDts_ = true;\n return;\n } else if (event.dts === this.latestDts_ && this.ignoreNextEqualDts_) {\n this.numSameDts_--;\n\n if (!this.numSameDts_) {\n // We've received the last duplicate packet, time to start processing again\n this.ignoreNextEqualDts_ = false;\n }\n\n return;\n } // parse out CC data packets and save them for later\n\n\n newCaptionPackets = captionPacketParser.parseCaptionPackets(event.pts, userData);\n this.captionPackets_ = this.captionPackets_.concat(newCaptionPackets);\n\n if (this.latestDts_ !== event.dts) {\n this.numSameDts_ = 0;\n }\n\n this.numSameDts_++;\n this.latestDts_ = event.dts;\n };\n\n CaptionStream$1.prototype.flushCCStreams = function (flushType) {\n this.ccStreams_.forEach(function (cc) {\n return flushType === 'flush' ? cc.flush() : cc.partialFlush();\n }, this);\n };\n\n CaptionStream$1.prototype.flushStream = function (flushType) {\n // make sure we actually parsed captions before proceeding\n if (!this.captionPackets_.length) {\n this.flushCCStreams(flushType);\n return;\n } // In Chrome, the Array#sort function is not stable so add a\n // presortIndex that we can use to ensure we get a stable-sort\n\n\n this.captionPackets_.forEach(function (elem, idx) {\n elem.presortIndex = idx;\n }); // sort caption byte-pairs based on their PTS values\n\n this.captionPackets_.sort(function (a, b) {\n if (a.pts === b.pts) {\n return a.presortIndex - b.presortIndex;\n }\n\n return a.pts - b.pts;\n });\n this.captionPackets_.forEach(function (packet) {\n if (packet.type < 2) {\n // Dispatch packet to the right Cea608Stream\n this.dispatchCea608Packet(packet);\n } else {\n // Dispatch packet to the Cea708Stream\n this.dispatchCea708Packet(packet);\n }\n }, this);\n this.captionPackets_.length = 0;\n this.flushCCStreams(flushType);\n };\n\n CaptionStream$1.prototype.flush = function () {\n return this.flushStream('flush');\n }; // Only called if handling partial data\n\n\n CaptionStream$1.prototype.partialFlush = function () {\n return this.flushStream('partialFlush');\n };\n\n CaptionStream$1.prototype.reset = function () {\n this.latestDts_ = null;\n this.ignoreNextEqualDts_ = false;\n this.numSameDts_ = 0;\n this.activeCea608Channel_ = [null, null];\n this.ccStreams_.forEach(function (ccStream) {\n ccStream.reset();\n });\n }; // From the CEA-608 spec:\n\n /*\n * When XDS sub-packets are interleaved with other services, the end of each sub-packet shall be followed\n * by a control pair to change to a different service. When any of the control codes from 0x10 to 0x1F is\n * used to begin a control code pair, it indicates the return to captioning or Text data. The control code pair\n * and subsequent data should then be processed according to the FCC rules. It may be necessary for the\n * line 21 data encoder to automatically insert a control code pair (i.e. RCL, RU2, RU3, RU4, RDC, or RTD)\n * to switch to captioning or Text.\n */\n // With that in mind, we ignore any data between an XDS control code and a\n // subsequent closed-captioning control code.\n\n\n CaptionStream$1.prototype.dispatchCea608Packet = function (packet) {\n // NOTE: packet.type is the CEA608 field\n if (this.setsTextOrXDSActive(packet)) {\n this.activeCea608Channel_[packet.type] = null;\n } else if (this.setsChannel1Active(packet)) {\n this.activeCea608Channel_[packet.type] = 0;\n } else if (this.setsChannel2Active(packet)) {\n this.activeCea608Channel_[packet.type] = 1;\n }\n\n if (this.activeCea608Channel_[packet.type] === null) {\n // If we haven't received anything to set the active channel, or the\n // packets are Text/XDS data, discard the data; we don't want jumbled\n // captions\n return;\n }\n\n this.ccStreams_[(packet.type << 1) + this.activeCea608Channel_[packet.type]].push(packet);\n };\n\n CaptionStream$1.prototype.setsChannel1Active = function (packet) {\n return (packet.ccData & 0x7800) === 0x1000;\n };\n\n CaptionStream$1.prototype.setsChannel2Active = function (packet) {\n return (packet.ccData & 0x7800) === 0x1800;\n };\n\n CaptionStream$1.prototype.setsTextOrXDSActive = function (packet) {\n return (packet.ccData & 0x7100) === 0x0100 || (packet.ccData & 0x78fe) === 0x102a || (packet.ccData & 0x78fe) === 0x182a;\n };\n\n CaptionStream$1.prototype.dispatchCea708Packet = function (packet) {\n if (this.parse708captions_) {\n this.cc708Stream_.push(packet);\n }\n }; // ----------------------\n // Session to Application\n // ----------------------\n // This hash maps special and extended character codes to their\n // proper Unicode equivalent. The first one-byte key is just a\n // non-standard character code. The two-byte keys that follow are\n // the extended CEA708 character codes, along with the preceding\n // 0x10 extended character byte to distinguish these codes from\n // non-extended character codes. Every CEA708 character code that\n // is not in this object maps directly to a standard unicode\n // character code.\n // The transparent space and non-breaking transparent space are\n // technically not fully supported since there is no code to\n // make them transparent, so they have normal non-transparent\n // stand-ins.\n // The special closed caption (CC) character isn't a standard\n // unicode character, so a fairly similar unicode character was\n // chosen in it's place.\n\n\n var CHARACTER_TRANSLATION_708 = {\n 0x7f: 0x266a,\n // ♪\n 0x1020: 0x20,\n // Transparent Space\n 0x1021: 0xa0,\n // Nob-breaking Transparent Space\n 0x1025: 0x2026,\n // …\n 0x102a: 0x0160,\n // Š\n 0x102c: 0x0152,\n // Œ\n 0x1030: 0x2588,\n // █\n 0x1031: 0x2018,\n // ‘\n 0x1032: 0x2019,\n // ’\n 0x1033: 0x201c,\n // “\n 0x1034: 0x201d,\n // ”\n 0x1035: 0x2022,\n // •\n 0x1039: 0x2122,\n // ™\n 0x103a: 0x0161,\n // š\n 0x103c: 0x0153,\n // œ\n 0x103d: 0x2120,\n // ℠\n 0x103f: 0x0178,\n // Ÿ\n 0x1076: 0x215b,\n // ⅛\n 0x1077: 0x215c,\n // ⅜\n 0x1078: 0x215d,\n // ⅝\n 0x1079: 0x215e,\n // ⅞\n 0x107a: 0x23d0,\n // ⏐\n 0x107b: 0x23a4,\n // ⎤\n 0x107c: 0x23a3,\n // ⎣\n 0x107d: 0x23af,\n // ⎯\n 0x107e: 0x23a6,\n // ⎦\n 0x107f: 0x23a1,\n // ⎡\n 0x10a0: 0x3138 // ㄸ (CC char)\n\n };\n\n var get708CharFromCode = function get708CharFromCode(code) {\n var newCode = CHARACTER_TRANSLATION_708[code] || code;\n\n if (code & 0x1000 && code === newCode) {\n // Invalid extended code\n return '';\n }\n\n return String.fromCharCode(newCode);\n };\n\n var within708TextBlock = function within708TextBlock(b) {\n return 0x20 <= b && b <= 0x7f || 0xa0 <= b && b <= 0xff;\n };\n\n var Cea708Window = function Cea708Window(windowNum) {\n this.windowNum = windowNum;\n this.reset();\n };\n\n Cea708Window.prototype.reset = function () {\n this.clearText();\n this.pendingNewLine = false;\n this.winAttr = {};\n this.penAttr = {};\n this.penLoc = {};\n this.penColor = {}; // These default values are arbitrary,\n // defineWindow will usually override them\n\n this.visible = 0;\n this.rowLock = 0;\n this.columnLock = 0;\n this.priority = 0;\n this.relativePositioning = 0;\n this.anchorVertical = 0;\n this.anchorHorizontal = 0;\n this.anchorPoint = 0;\n this.rowCount = 1;\n this.virtualRowCount = this.rowCount + 1;\n this.columnCount = 41;\n this.windowStyle = 0;\n this.penStyle = 0;\n };\n\n Cea708Window.prototype.getText = function () {\n return this.rows.join('\\n');\n };\n\n Cea708Window.prototype.clearText = function () {\n this.rows = [''];\n this.rowIdx = 0;\n };\n\n Cea708Window.prototype.newLine = function (pts) {\n if (this.rows.length >= this.virtualRowCount && typeof this.beforeRowOverflow === 'function') {\n this.beforeRowOverflow(pts);\n }\n\n if (this.rows.length > 0) {\n this.rows.push('');\n this.rowIdx++;\n } // Show all virtual rows since there's no visible scrolling\n\n\n while (this.rows.length > this.virtualRowCount) {\n this.rows.shift();\n this.rowIdx--;\n }\n };\n\n Cea708Window.prototype.isEmpty = function () {\n if (this.rows.length === 0) {\n return true;\n } else if (this.rows.length === 1) {\n return this.rows[0] === '';\n }\n\n return false;\n };\n\n Cea708Window.prototype.addText = function (text) {\n this.rows[this.rowIdx] += text;\n };\n\n Cea708Window.prototype.backspace = function () {\n if (!this.isEmpty()) {\n var row = this.rows[this.rowIdx];\n this.rows[this.rowIdx] = row.substr(0, row.length - 1);\n }\n };\n\n var Cea708Service = function Cea708Service(serviceNum, encoding, stream) {\n this.serviceNum = serviceNum;\n this.text = '';\n this.currentWindow = new Cea708Window(-1);\n this.windows = [];\n this.stream = stream; // Try to setup a TextDecoder if an `encoding` value was provided\n\n if (typeof encoding === 'string') {\n this.createTextDecoder(encoding);\n }\n };\n /**\n * Initialize service windows\n * Must be run before service use\n *\n * @param {Integer} pts PTS value\n * @param {Function} beforeRowOverflow Function to execute before row overflow of a window\n */\n\n\n Cea708Service.prototype.init = function (pts, beforeRowOverflow) {\n this.startPts = pts;\n\n for (var win = 0; win < 8; win++) {\n this.windows[win] = new Cea708Window(win);\n\n if (typeof beforeRowOverflow === 'function') {\n this.windows[win].beforeRowOverflow = beforeRowOverflow;\n }\n }\n };\n /**\n * Set current window of service to be affected by commands\n *\n * @param {Integer} windowNum Window number\n */\n\n\n Cea708Service.prototype.setCurrentWindow = function (windowNum) {\n this.currentWindow = this.windows[windowNum];\n };\n /**\n * Try to create a TextDecoder if it is natively supported\n */\n\n\n Cea708Service.prototype.createTextDecoder = function (encoding) {\n if (typeof TextDecoder === 'undefined') {\n this.stream.trigger('log', {\n level: 'warn',\n message: 'The `encoding` option is unsupported without TextDecoder support'\n });\n } else {\n try {\n this.textDecoder_ = new TextDecoder(encoding);\n } catch (error) {\n this.stream.trigger('log', {\n level: 'warn',\n message: 'TextDecoder could not be created with ' + encoding + ' encoding. ' + error\n });\n }\n }\n };\n\n var Cea708Stream = function Cea708Stream(options) {\n options = options || {};\n Cea708Stream.prototype.init.call(this);\n var self = this;\n var captionServices = options.captionServices || {};\n var captionServiceEncodings = {};\n var serviceProps; // Get service encodings from captionServices option block\n\n Object.keys(captionServices).forEach(function (serviceName) {\n serviceProps = captionServices[serviceName];\n\n if (/^SERVICE/.test(serviceName)) {\n captionServiceEncodings[serviceName] = serviceProps.encoding;\n }\n });\n this.serviceEncodings = captionServiceEncodings;\n this.current708Packet = null;\n this.services = {};\n\n this.push = function (packet) {\n if (packet.type === 3) {\n // 708 packet start\n self.new708Packet();\n self.add708Bytes(packet);\n } else {\n if (self.current708Packet === null) {\n // This should only happen at the start of a file if there's no packet start.\n self.new708Packet();\n }\n\n self.add708Bytes(packet);\n }\n };\n };\n\n Cea708Stream.prototype = new stream();\n /**\n * Push current 708 packet, create new 708 packet.\n */\n\n Cea708Stream.prototype.new708Packet = function () {\n if (this.current708Packet !== null) {\n this.push708Packet();\n }\n\n this.current708Packet = {\n data: [],\n ptsVals: []\n };\n };\n /**\n * Add pts and both bytes from packet into current 708 packet.\n */\n\n\n Cea708Stream.prototype.add708Bytes = function (packet) {\n var data = packet.ccData;\n var byte0 = data >>> 8;\n var byte1 = data & 0xff; // I would just keep a list of packets instead of bytes, but it isn't clear in the spec\n // that service blocks will always line up with byte pairs.\n\n this.current708Packet.ptsVals.push(packet.pts);\n this.current708Packet.data.push(byte0);\n this.current708Packet.data.push(byte1);\n };\n /**\n * Parse completed 708 packet into service blocks and push each service block.\n */\n\n\n Cea708Stream.prototype.push708Packet = function () {\n var packet708 = this.current708Packet;\n var packetData = packet708.data;\n var serviceNum = null;\n var blockSize = null;\n var i = 0;\n var b = packetData[i++];\n packet708.seq = b >> 6;\n packet708.sizeCode = b & 0x3f; // 0b00111111;\n\n for (; i < packetData.length; i++) {\n b = packetData[i++];\n serviceNum = b >> 5;\n blockSize = b & 0x1f; // 0b00011111\n\n if (serviceNum === 7 && blockSize > 0) {\n // Extended service num\n b = packetData[i++];\n serviceNum = b;\n }\n\n this.pushServiceBlock(serviceNum, i, blockSize);\n\n if (blockSize > 0) {\n i += blockSize - 1;\n }\n }\n };\n /**\n * Parse service block, execute commands, read text.\n *\n * Note: While many of these commands serve important purposes,\n * many others just parse out the parameters or attributes, but\n * nothing is done with them because this is not a full and complete\n * implementation of the entire 708 spec.\n *\n * @param {Integer} serviceNum Service number\n * @param {Integer} start Start index of the 708 packet data\n * @param {Integer} size Block size\n */\n\n\n Cea708Stream.prototype.pushServiceBlock = function (serviceNum, start, size) {\n var b;\n var i = start;\n var packetData = this.current708Packet.data;\n var service = this.services[serviceNum];\n\n if (!service) {\n service = this.initService(serviceNum, i);\n }\n\n for (; i < start + size && i < packetData.length; i++) {\n b = packetData[i];\n\n if (within708TextBlock(b)) {\n i = this.handleText(i, service);\n } else if (b === 0x18) {\n i = this.multiByteCharacter(i, service);\n } else if (b === 0x10) {\n i = this.extendedCommands(i, service);\n } else if (0x80 <= b && b <= 0x87) {\n i = this.setCurrentWindow(i, service);\n } else if (0x98 <= b && b <= 0x9f) {\n i = this.defineWindow(i, service);\n } else if (b === 0x88) {\n i = this.clearWindows(i, service);\n } else if (b === 0x8c) {\n i = this.deleteWindows(i, service);\n } else if (b === 0x89) {\n i = this.displayWindows(i, service);\n } else if (b === 0x8a) {\n i = this.hideWindows(i, service);\n } else if (b === 0x8b) {\n i = this.toggleWindows(i, service);\n } else if (b === 0x97) {\n i = this.setWindowAttributes(i, service);\n } else if (b === 0x90) {\n i = this.setPenAttributes(i, service);\n } else if (b === 0x91) {\n i = this.setPenColor(i, service);\n } else if (b === 0x92) {\n i = this.setPenLocation(i, service);\n } else if (b === 0x8f) {\n service = this.reset(i, service);\n } else if (b === 0x08) {\n // BS: Backspace\n service.currentWindow.backspace();\n } else if (b === 0x0c) {\n // FF: Form feed\n service.currentWindow.clearText();\n } else if (b === 0x0d) {\n // CR: Carriage return\n service.currentWindow.pendingNewLine = true;\n } else if (b === 0x0e) {\n // HCR: Horizontal carriage return\n service.currentWindow.clearText();\n } else if (b === 0x8d) {\n // DLY: Delay, nothing to do\n i++;\n } else ;\n }\n };\n /**\n * Execute an extended command\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.extendedCommands = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n\n if (within708TextBlock(b)) {\n i = this.handleText(i, service, {\n isExtended: true\n });\n }\n\n return i;\n };\n /**\n * Get PTS value of a given byte index\n *\n * @param {Integer} byteIndex Index of the byte\n * @return {Integer} PTS\n */\n\n\n Cea708Stream.prototype.getPts = function (byteIndex) {\n // There's 1 pts value per 2 bytes\n return this.current708Packet.ptsVals[Math.floor(byteIndex / 2)];\n };\n /**\n * Initializes a service\n *\n * @param {Integer} serviceNum Service number\n * @return {Service} Initialized service object\n */\n\n\n Cea708Stream.prototype.initService = function (serviceNum, i) {\n var serviceName = 'SERVICE' + serviceNum;\n var self = this;\n var serviceName;\n var encoding;\n\n if (serviceName in this.serviceEncodings) {\n encoding = this.serviceEncodings[serviceName];\n }\n\n this.services[serviceNum] = new Cea708Service(serviceNum, encoding, self);\n this.services[serviceNum].init(this.getPts(i), function (pts) {\n self.flushDisplayed(pts, self.services[serviceNum]);\n });\n return this.services[serviceNum];\n };\n /**\n * Execute text writing to current window\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.handleText = function (i, service, options) {\n var isExtended = options && options.isExtended;\n var isMultiByte = options && options.isMultiByte;\n var packetData = this.current708Packet.data;\n var extended = isExtended ? 0x1000 : 0x0000;\n var currentByte = packetData[i];\n var nextByte = packetData[i + 1];\n var win = service.currentWindow;\n var char;\n var charCodeArray; // Use the TextDecoder if one was created for this service\n\n if (service.textDecoder_ && !isExtended) {\n if (isMultiByte) {\n charCodeArray = [currentByte, nextByte];\n i++;\n } else {\n charCodeArray = [currentByte];\n }\n\n char = service.textDecoder_.decode(new Uint8Array(charCodeArray));\n } else {\n char = get708CharFromCode(extended | currentByte);\n }\n\n if (win.pendingNewLine && !win.isEmpty()) {\n win.newLine(this.getPts(i));\n }\n\n win.pendingNewLine = false;\n win.addText(char);\n return i;\n };\n /**\n * Handle decoding of multibyte character\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.multiByteCharacter = function (i, service) {\n var packetData = this.current708Packet.data;\n var firstByte = packetData[i + 1];\n var secondByte = packetData[i + 2];\n\n if (within708TextBlock(firstByte) && within708TextBlock(secondByte)) {\n i = this.handleText(++i, service, {\n isMultiByte: true\n });\n }\n\n return i;\n };\n /**\n * Parse and execute the CW# command.\n *\n * Set the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.setCurrentWindow = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var windowNum = b & 0x07;\n service.setCurrentWindow(windowNum);\n return i;\n };\n /**\n * Parse and execute the DF# command.\n *\n * Define a window and set it as the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.defineWindow = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var windowNum = b & 0x07;\n service.setCurrentWindow(windowNum);\n var win = service.currentWindow;\n b = packetData[++i];\n win.visible = (b & 0x20) >> 5; // v\n\n win.rowLock = (b & 0x10) >> 4; // rl\n\n win.columnLock = (b & 0x08) >> 3; // cl\n\n win.priority = b & 0x07; // p\n\n b = packetData[++i];\n win.relativePositioning = (b & 0x80) >> 7; // rp\n\n win.anchorVertical = b & 0x7f; // av\n\n b = packetData[++i];\n win.anchorHorizontal = b; // ah\n\n b = packetData[++i];\n win.anchorPoint = (b & 0xf0) >> 4; // ap\n\n win.rowCount = b & 0x0f; // rc\n\n b = packetData[++i];\n win.columnCount = b & 0x3f; // cc\n\n b = packetData[++i];\n win.windowStyle = (b & 0x38) >> 3; // ws\n\n win.penStyle = b & 0x07; // ps\n // The spec says there are (rowCount+1) \"virtual rows\"\n\n win.virtualRowCount = win.rowCount + 1;\n return i;\n };\n /**\n * Parse and execute the SWA command.\n *\n * Set attributes of the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.setWindowAttributes = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var winAttr = service.currentWindow.winAttr;\n b = packetData[++i];\n winAttr.fillOpacity = (b & 0xc0) >> 6; // fo\n\n winAttr.fillRed = (b & 0x30) >> 4; // fr\n\n winAttr.fillGreen = (b & 0x0c) >> 2; // fg\n\n winAttr.fillBlue = b & 0x03; // fb\n\n b = packetData[++i];\n winAttr.borderType = (b & 0xc0) >> 6; // bt\n\n winAttr.borderRed = (b & 0x30) >> 4; // br\n\n winAttr.borderGreen = (b & 0x0c) >> 2; // bg\n\n winAttr.borderBlue = b & 0x03; // bb\n\n b = packetData[++i];\n winAttr.borderType += (b & 0x80) >> 5; // bt\n\n winAttr.wordWrap = (b & 0x40) >> 6; // ww\n\n winAttr.printDirection = (b & 0x30) >> 4; // pd\n\n winAttr.scrollDirection = (b & 0x0c) >> 2; // sd\n\n winAttr.justify = b & 0x03; // j\n\n b = packetData[++i];\n winAttr.effectSpeed = (b & 0xf0) >> 4; // es\n\n winAttr.effectDirection = (b & 0x0c) >> 2; // ed\n\n winAttr.displayEffect = b & 0x03; // de\n\n return i;\n };\n /**\n * Gather text from all displayed windows and push a caption to output.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n */\n\n\n Cea708Stream.prototype.flushDisplayed = function (pts, service) {\n var displayedText = []; // TODO: Positioning not supported, displaying multiple windows will not necessarily\n // display text in the correct order, but sample files so far have not shown any issue.\n\n for (var winId = 0; winId < 8; winId++) {\n if (service.windows[winId].visible && !service.windows[winId].isEmpty()) {\n displayedText.push(service.windows[winId].getText());\n }\n }\n\n service.endPts = pts;\n service.text = displayedText.join('\\n\\n');\n this.pushCaption(service);\n service.startPts = pts;\n };\n /**\n * Push a caption to output if the caption contains text.\n *\n * @param {Service} service The service object to be affected\n */\n\n\n Cea708Stream.prototype.pushCaption = function (service) {\n if (service.text !== '') {\n this.trigger('data', {\n startPts: service.startPts,\n endPts: service.endPts,\n text: service.text,\n stream: 'cc708_' + service.serviceNum\n });\n service.text = '';\n service.startPts = service.endPts;\n }\n };\n /**\n * Parse and execute the DSW command.\n *\n * Set visible property of windows based on the parsed bitmask.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.displayWindows = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n\n for (var winId = 0; winId < 8; winId++) {\n if (b & 0x01 << winId) {\n service.windows[winId].visible = 1;\n }\n }\n\n return i;\n };\n /**\n * Parse and execute the HDW command.\n *\n * Set visible property of windows based on the parsed bitmask.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.hideWindows = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n\n for (var winId = 0; winId < 8; winId++) {\n if (b & 0x01 << winId) {\n service.windows[winId].visible = 0;\n }\n }\n\n return i;\n };\n /**\n * Parse and execute the TGW command.\n *\n * Set visible property of windows based on the parsed bitmask.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.toggleWindows = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n\n for (var winId = 0; winId < 8; winId++) {\n if (b & 0x01 << winId) {\n service.windows[winId].visible ^= 1;\n }\n }\n\n return i;\n };\n /**\n * Parse and execute the CLW command.\n *\n * Clear text of windows based on the parsed bitmask.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.clearWindows = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n\n for (var winId = 0; winId < 8; winId++) {\n if (b & 0x01 << winId) {\n service.windows[winId].clearText();\n }\n }\n\n return i;\n };\n /**\n * Parse and execute the DLW command.\n *\n * Re-initialize windows based on the parsed bitmask.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.deleteWindows = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[++i];\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n\n for (var winId = 0; winId < 8; winId++) {\n if (b & 0x01 << winId) {\n service.windows[winId].reset();\n }\n }\n\n return i;\n };\n /**\n * Parse and execute the SPA command.\n *\n * Set pen attributes of the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.setPenAttributes = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var penAttr = service.currentWindow.penAttr;\n b = packetData[++i];\n penAttr.textTag = (b & 0xf0) >> 4; // tt\n\n penAttr.offset = (b & 0x0c) >> 2; // o\n\n penAttr.penSize = b & 0x03; // s\n\n b = packetData[++i];\n penAttr.italics = (b & 0x80) >> 7; // i\n\n penAttr.underline = (b & 0x40) >> 6; // u\n\n penAttr.edgeType = (b & 0x38) >> 3; // et\n\n penAttr.fontStyle = b & 0x07; // fs\n\n return i;\n };\n /**\n * Parse and execute the SPC command.\n *\n * Set pen color of the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.setPenColor = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var penColor = service.currentWindow.penColor;\n b = packetData[++i];\n penColor.fgOpacity = (b & 0xc0) >> 6; // fo\n\n penColor.fgRed = (b & 0x30) >> 4; // fr\n\n penColor.fgGreen = (b & 0x0c) >> 2; // fg\n\n penColor.fgBlue = b & 0x03; // fb\n\n b = packetData[++i];\n penColor.bgOpacity = (b & 0xc0) >> 6; // bo\n\n penColor.bgRed = (b & 0x30) >> 4; // br\n\n penColor.bgGreen = (b & 0x0c) >> 2; // bg\n\n penColor.bgBlue = b & 0x03; // bb\n\n b = packetData[++i];\n penColor.edgeRed = (b & 0x30) >> 4; // er\n\n penColor.edgeGreen = (b & 0x0c) >> 2; // eg\n\n penColor.edgeBlue = b & 0x03; // eb\n\n return i;\n };\n /**\n * Parse and execute the SPL command.\n *\n * Set pen location of the current window.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Integer} New index after parsing\n */\n\n\n Cea708Stream.prototype.setPenLocation = function (i, service) {\n var packetData = this.current708Packet.data;\n var b = packetData[i];\n var penLoc = service.currentWindow.penLoc; // Positioning isn't really supported at the moment, so this essentially just inserts a linebreak\n\n service.currentWindow.pendingNewLine = true;\n b = packetData[++i];\n penLoc.row = b & 0x0f; // r\n\n b = packetData[++i];\n penLoc.column = b & 0x3f; // c\n\n return i;\n };\n /**\n * Execute the RST command.\n *\n * Reset service to a clean slate. Re-initialize.\n *\n * @param {Integer} i Current index in the 708 packet\n * @param {Service} service The service object to be affected\n * @return {Service} Re-initialized service\n */\n\n\n Cea708Stream.prototype.reset = function (i, service) {\n var pts = this.getPts(i);\n this.flushDisplayed(pts, service);\n return this.initService(service.serviceNum, i);\n }; // This hash maps non-ASCII, special, and extended character codes to their\n // proper Unicode equivalent. The first keys that are only a single byte\n // are the non-standard ASCII characters, which simply map the CEA608 byte\n // to the standard ASCII/Unicode. The two-byte keys that follow are the CEA608\n // character codes, but have their MSB bitmasked with 0x03 so that a lookup\n // can be performed regardless of the field and data channel on which the\n // character code was received.\n\n\n var CHARACTER_TRANSLATION = {\n 0x2a: 0xe1,\n // á\n 0x5c: 0xe9,\n // é\n 0x5e: 0xed,\n // í\n 0x5f: 0xf3,\n // ó\n 0x60: 0xfa,\n // ú\n 0x7b: 0xe7,\n // ç\n 0x7c: 0xf7,\n // ÷\n 0x7d: 0xd1,\n // Ñ\n 0x7e: 0xf1,\n // ñ\n 0x7f: 0x2588,\n // █\n 0x0130: 0xae,\n // ®\n 0x0131: 0xb0,\n // °\n 0x0132: 0xbd,\n // ½\n 0x0133: 0xbf,\n // ¿\n 0x0134: 0x2122,\n // ™\n 0x0135: 0xa2,\n // ¢\n 0x0136: 0xa3,\n // £\n 0x0137: 0x266a,\n // ♪\n 0x0138: 0xe0,\n // à\n 0x0139: 0xa0,\n //\n 0x013a: 0xe8,\n // è\n 0x013b: 0xe2,\n // â\n 0x013c: 0xea,\n // ê\n 0x013d: 0xee,\n // î\n 0x013e: 0xf4,\n // ô\n 0x013f: 0xfb,\n // û\n 0x0220: 0xc1,\n // Á\n 0x0221: 0xc9,\n // É\n 0x0222: 0xd3,\n // Ó\n 0x0223: 0xda,\n // Ú\n 0x0224: 0xdc,\n // Ü\n 0x0225: 0xfc,\n // ü\n 0x0226: 0x2018,\n // ‘\n 0x0227: 0xa1,\n // ¡\n 0x0228: 0x2a,\n // *\n 0x0229: 0x27,\n // '\n 0x022a: 0x2014,\n // —\n 0x022b: 0xa9,\n // ©\n 0x022c: 0x2120,\n // ℠\n 0x022d: 0x2022,\n // •\n 0x022e: 0x201c,\n // “\n 0x022f: 0x201d,\n // ”\n 0x0230: 0xc0,\n // À\n 0x0231: 0xc2,\n // Â\n 0x0232: 0xc7,\n // Ç\n 0x0233: 0xc8,\n // È\n 0x0234: 0xca,\n // Ê\n 0x0235: 0xcb,\n // Ë\n 0x0236: 0xeb,\n // ë\n 0x0237: 0xce,\n // Î\n 0x0238: 0xcf,\n // Ï\n 0x0239: 0xef,\n // ï\n 0x023a: 0xd4,\n // Ô\n 0x023b: 0xd9,\n // Ù\n 0x023c: 0xf9,\n // ù\n 0x023d: 0xdb,\n // Û\n 0x023e: 0xab,\n // «\n 0x023f: 0xbb,\n // »\n 0x0320: 0xc3,\n // Ã\n 0x0321: 0xe3,\n // ã\n 0x0322: 0xcd,\n // Í\n 0x0323: 0xcc,\n // Ì\n 0x0324: 0xec,\n // ì\n 0x0325: 0xd2,\n // Ò\n 0x0326: 0xf2,\n // ò\n 0x0327: 0xd5,\n // Õ\n 0x0328: 0xf5,\n // õ\n 0x0329: 0x7b,\n // {\n 0x032a: 0x7d,\n // }\n 0x032b: 0x5c,\n // \\\n 0x032c: 0x5e,\n // ^\n 0x032d: 0x5f,\n // _\n 0x032e: 0x7c,\n // |\n 0x032f: 0x7e,\n // ~\n 0x0330: 0xc4,\n // Ä\n 0x0331: 0xe4,\n // ä\n 0x0332: 0xd6,\n // Ö\n 0x0333: 0xf6,\n // ö\n 0x0334: 0xdf,\n // ß\n 0x0335: 0xa5,\n // ¥\n 0x0336: 0xa4,\n // ¤\n 0x0337: 0x2502,\n // │\n 0x0338: 0xc5,\n // Å\n 0x0339: 0xe5,\n // å\n 0x033a: 0xd8,\n // Ø\n 0x033b: 0xf8,\n // ø\n 0x033c: 0x250c,\n // ┌\n 0x033d: 0x2510,\n // ┐\n 0x033e: 0x2514,\n // └\n 0x033f: 0x2518 // ┘\n\n };\n\n var getCharFromCode = function getCharFromCode(code) {\n if (code === null) {\n return '';\n }\n\n code = CHARACTER_TRANSLATION[code] || code;\n return String.fromCharCode(code);\n }; // the index of the last row in a CEA-608 display buffer\n\n\n var BOTTOM_ROW = 14; // This array is used for mapping PACs -> row #, since there's no way of\n // getting it through bit logic.\n\n var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character\n // cells. The \"bottom\" row is the last element in the outer array.\n\n var createDisplayBuffer = function createDisplayBuffer() {\n var result = [],\n i = BOTTOM_ROW + 1;\n\n while (i--) {\n result.push('');\n }\n\n return result;\n };\n\n var Cea608Stream = function Cea608Stream(field, dataChannel) {\n Cea608Stream.prototype.init.call(this);\n this.field_ = field || 0;\n this.dataChannel_ = dataChannel || 0;\n this.name_ = 'CC' + ((this.field_ << 1 | this.dataChannel_) + 1);\n this.setConstants();\n this.reset();\n\n this.push = function (packet) {\n var data, swap, char0, char1, text; // remove the parity bits\n\n data = packet.ccData & 0x7f7f; // ignore duplicate control codes; the spec demands they're sent twice\n\n if (data === this.lastControlCode_) {\n this.lastControlCode_ = null;\n return;\n } // Store control codes\n\n\n if ((data & 0xf000) === 0x1000) {\n this.lastControlCode_ = data;\n } else if (data !== this.PADDING_) {\n this.lastControlCode_ = null;\n }\n\n char0 = data >>> 8;\n char1 = data & 0xff;\n\n if (data === this.PADDING_) {\n return;\n } else if (data === this.RESUME_CAPTION_LOADING_) {\n this.mode_ = 'popOn';\n } else if (data === this.END_OF_CAPTION_) {\n // If an EOC is received while in paint-on mode, the displayed caption\n // text should be swapped to non-displayed memory as if it was a pop-on\n // caption. Because of that, we should explicitly switch back to pop-on\n // mode\n this.mode_ = 'popOn';\n this.clearFormatting(packet.pts); // if a caption was being displayed, it's gone now\n\n this.flushDisplayed(packet.pts); // flip memory\n\n swap = this.displayed_;\n this.displayed_ = this.nonDisplayed_;\n this.nonDisplayed_ = swap; // start measuring the time to display the caption\n\n this.startPts_ = packet.pts;\n } else if (data === this.ROLL_UP_2_ROWS_) {\n this.rollUpRows_ = 2;\n this.setRollUp(packet.pts);\n } else if (data === this.ROLL_UP_3_ROWS_) {\n this.rollUpRows_ = 3;\n this.setRollUp(packet.pts);\n } else if (data === this.ROLL_UP_4_ROWS_) {\n this.rollUpRows_ = 4;\n this.setRollUp(packet.pts);\n } else if (data === this.CARRIAGE_RETURN_) {\n this.clearFormatting(packet.pts);\n this.flushDisplayed(packet.pts);\n this.shiftRowsUp_();\n this.startPts_ = packet.pts;\n } else if (data === this.BACKSPACE_) {\n if (this.mode_ === 'popOn') {\n this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);\n } else {\n this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);\n }\n } else if (data === this.ERASE_DISPLAYED_MEMORY_) {\n this.flushDisplayed(packet.pts);\n this.displayed_ = createDisplayBuffer();\n } else if (data === this.ERASE_NON_DISPLAYED_MEMORY_) {\n this.nonDisplayed_ = createDisplayBuffer();\n } else if (data === this.RESUME_DIRECT_CAPTIONING_) {\n if (this.mode_ !== 'paintOn') {\n // NOTE: This should be removed when proper caption positioning is\n // implemented\n this.flushDisplayed(packet.pts);\n this.displayed_ = createDisplayBuffer();\n }\n\n this.mode_ = 'paintOn';\n this.startPts_ = packet.pts; // Append special characters to caption text\n } else if (this.isSpecialCharacter(char0, char1)) {\n // Bitmask char0 so that we can apply character transformations\n // regardless of field and data channel.\n // Then byte-shift to the left and OR with char1 so we can pass the\n // entire character code to `getCharFromCode`.\n char0 = (char0 & 0x03) << 8;\n text = getCharFromCode(char0 | char1);\n this[this.mode_](packet.pts, text);\n this.column_++; // Append extended characters to caption text\n } else if (this.isExtCharacter(char0, char1)) {\n // Extended characters always follow their \"non-extended\" equivalents.\n // IE if a \"è\" is desired, you'll always receive \"eè\"; non-compliant\n // decoders are supposed to drop the \"è\", while compliant decoders\n // backspace the \"e\" and insert \"è\".\n // Delete the previous character\n if (this.mode_ === 'popOn') {\n this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);\n } else {\n this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);\n } // Bitmask char0 so that we can apply character transformations\n // regardless of field and data channel.\n // Then byte-shift to the left and OR with char1 so we can pass the\n // entire character code to `getCharFromCode`.\n\n\n char0 = (char0 & 0x03) << 8;\n text = getCharFromCode(char0 | char1);\n this[this.mode_](packet.pts, text);\n this.column_++; // Process mid-row codes\n } else if (this.isMidRowCode(char0, char1)) {\n // Attributes are not additive, so clear all formatting\n this.clearFormatting(packet.pts); // According to the standard, mid-row codes\n // should be replaced with spaces, so add one now\n\n this[this.mode_](packet.pts, ' ');\n this.column_++;\n\n if ((char1 & 0xe) === 0xe) {\n this.addFormatting(packet.pts, ['i']);\n }\n\n if ((char1 & 0x1) === 0x1) {\n this.addFormatting(packet.pts, ['u']);\n } // Detect offset control codes and adjust cursor\n\n } else if (this.isOffsetControlCode(char0, char1)) {\n // Cursor position is set by indent PAC (see below) in 4-column\n // increments, with an additional offset code of 1-3 to reach any\n // of the 32 columns specified by CEA-608. So all we need to do\n // here is increment the column cursor by the given offset.\n this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)\n } else if (this.isPAC(char0, char1)) {\n // There's no logic for PAC -> row mapping, so we have to just\n // find the row code in an array and use its index :(\n var row = ROWS.indexOf(data & 0x1f20); // Configure the caption window if we're in roll-up mode\n\n if (this.mode_ === 'rollUp') {\n // This implies that the base row is incorrectly set.\n // As per the recommendation in CEA-608(Base Row Implementation), defer to the number\n // of roll-up rows set.\n if (row - this.rollUpRows_ + 1 < 0) {\n row = this.rollUpRows_ - 1;\n }\n\n this.setRollUp(packet.pts, row);\n }\n\n if (row !== this.row_) {\n // formatting is only persistent for current row\n this.clearFormatting(packet.pts);\n this.row_ = row;\n } // All PACs can apply underline, so detect and apply\n // (All odd-numbered second bytes set underline)\n\n\n if (char1 & 0x1 && this.formatting_.indexOf('u') === -1) {\n this.addFormatting(packet.pts, ['u']);\n }\n\n if ((data & 0x10) === 0x10) {\n // We've got an indent level code. Each successive even number\n // increments the column cursor by 4, so we can get the desired\n // column position by bit-shifting to the right (to get n/2)\n // and multiplying by 4.\n this.column_ = ((data & 0xe) >> 1) * 4;\n }\n\n if (this.isColorPAC(char1)) {\n // it's a color code, though we only support white, which\n // can be either normal or italicized. white italics can be\n // either 0x4e or 0x6e depending on the row, so we just\n // bitwise-and with 0xe to see if italics should be turned on\n if ((char1 & 0xe) === 0xe) {\n this.addFormatting(packet.pts, ['i']);\n }\n } // We have a normal character in char0, and possibly one in char1\n\n } else if (this.isNormalChar(char0)) {\n if (char1 === 0x00) {\n char1 = null;\n }\n\n text = getCharFromCode(char0);\n text += getCharFromCode(char1);\n this[this.mode_](packet.pts, text);\n this.column_ += text.length;\n } // finish data processing\n\n };\n };\n\n Cea608Stream.prototype = new stream(); // Trigger a cue point that captures the current state of the\n // display buffer\n\n Cea608Stream.prototype.flushDisplayed = function (pts) {\n var content = this.displayed_ // remove spaces from the start and end of the string\n .map(function (row, index) {\n try {\n return row.trim();\n } catch (e) {\n // Ordinarily, this shouldn't happen. However, caption\n // parsing errors should not throw exceptions and\n // break playback.\n this.trigger('log', {\n level: 'warn',\n message: 'Skipping a malformed 608 caption at index ' + index + '.'\n });\n return '';\n }\n }, this) // combine all text rows to display in one cue\n .join('\\n') // and remove blank rows from the start and end, but not the middle\n .replace(/^\\n+|\\n+$/g, '');\n\n if (content.length) {\n this.trigger('data', {\n startPts: this.startPts_,\n endPts: pts,\n text: content,\n stream: this.name_\n });\n }\n };\n /**\n * Zero out the data, used for startup and on seek\n */\n\n\n Cea608Stream.prototype.reset = function () {\n this.mode_ = 'popOn'; // When in roll-up mode, the index of the last row that will\n // actually display captions. If a caption is shifted to a row\n // with a lower index than this, it is cleared from the display\n // buffer\n\n this.topRow_ = 0;\n this.startPts_ = 0;\n this.displayed_ = createDisplayBuffer();\n this.nonDisplayed_ = createDisplayBuffer();\n this.lastControlCode_ = null; // Track row and column for proper line-breaking and spacing\n\n this.column_ = 0;\n this.row_ = BOTTOM_ROW;\n this.rollUpRows_ = 2; // This variable holds currently-applied formatting\n\n this.formatting_ = [];\n };\n /**\n * Sets up control code and related constants for this instance\n */\n\n\n Cea608Stream.prototype.setConstants = function () {\n // The following attributes have these uses:\n // ext_ : char0 for mid-row codes, and the base for extended\n // chars (ext_+0, ext_+1, and ext_+2 are char0s for\n // extended codes)\n // control_: char0 for control codes, except byte-shifted to the\n // left so that we can do this.control_ | CONTROL_CODE\n // offset_: char0 for tab offset codes\n //\n // It's also worth noting that control codes, and _only_ control codes,\n // differ between field 1 and field2. Field 2 control codes are always\n // their field 1 value plus 1. That's why there's the \"| field\" on the\n // control value.\n if (this.dataChannel_ === 0) {\n this.BASE_ = 0x10;\n this.EXT_ = 0x11;\n this.CONTROL_ = (0x14 | this.field_) << 8;\n this.OFFSET_ = 0x17;\n } else if (this.dataChannel_ === 1) {\n this.BASE_ = 0x18;\n this.EXT_ = 0x19;\n this.CONTROL_ = (0x1c | this.field_) << 8;\n this.OFFSET_ = 0x1f;\n } // Constants for the LSByte command codes recognized by Cea608Stream. This\n // list is not exhaustive. For a more comprehensive listing and semantics see\n // http://www.gpo.gov/fdsys/pkg/CFR-2010-title47-vol1/pdf/CFR-2010-title47-vol1-sec15-119.pdf\n // Padding\n\n\n this.PADDING_ = 0x0000; // Pop-on Mode\n\n this.RESUME_CAPTION_LOADING_ = this.CONTROL_ | 0x20;\n this.END_OF_CAPTION_ = this.CONTROL_ | 0x2f; // Roll-up Mode\n\n this.ROLL_UP_2_ROWS_ = this.CONTROL_ | 0x25;\n this.ROLL_UP_3_ROWS_ = this.CONTROL_ | 0x26;\n this.ROLL_UP_4_ROWS_ = this.CONTROL_ | 0x27;\n this.CARRIAGE_RETURN_ = this.CONTROL_ | 0x2d; // paint-on mode\n\n this.RESUME_DIRECT_CAPTIONING_ = this.CONTROL_ | 0x29; // Erasure\n\n this.BACKSPACE_ = this.CONTROL_ | 0x21;\n this.ERASE_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2c;\n this.ERASE_NON_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2e;\n };\n /**\n * Detects if the 2-byte packet data is a special character\n *\n * Special characters have a second byte in the range 0x30 to 0x3f,\n * with the first byte being 0x11 (for data channel 1) or 0x19 (for\n * data channel 2).\n *\n * @param {Integer} char0 The first byte\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the 2 bytes are an special character\n */\n\n\n Cea608Stream.prototype.isSpecialCharacter = function (char0, char1) {\n return char0 === this.EXT_ && char1 >= 0x30 && char1 <= 0x3f;\n };\n /**\n * Detects if the 2-byte packet data is an extended character\n *\n * Extended characters have a second byte in the range 0x20 to 0x3f,\n * with the first byte being 0x12 or 0x13 (for data channel 1) or\n * 0x1a or 0x1b (for data channel 2).\n *\n * @param {Integer} char0 The first byte\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the 2 bytes are an extended character\n */\n\n\n Cea608Stream.prototype.isExtCharacter = function (char0, char1) {\n return (char0 === this.EXT_ + 1 || char0 === this.EXT_ + 2) && char1 >= 0x20 && char1 <= 0x3f;\n };\n /**\n * Detects if the 2-byte packet is a mid-row code\n *\n * Mid-row codes have a second byte in the range 0x20 to 0x2f, with\n * the first byte being 0x11 (for data channel 1) or 0x19 (for data\n * channel 2).\n *\n * @param {Integer} char0 The first byte\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the 2 bytes are a mid-row code\n */\n\n\n Cea608Stream.prototype.isMidRowCode = function (char0, char1) {\n return char0 === this.EXT_ && char1 >= 0x20 && char1 <= 0x2f;\n };\n /**\n * Detects if the 2-byte packet is an offset control code\n *\n * Offset control codes have a second byte in the range 0x21 to 0x23,\n * with the first byte being 0x17 (for data channel 1) or 0x1f (for\n * data channel 2).\n *\n * @param {Integer} char0 The first byte\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the 2 bytes are an offset control code\n */\n\n\n Cea608Stream.prototype.isOffsetControlCode = function (char0, char1) {\n return char0 === this.OFFSET_ && char1 >= 0x21 && char1 <= 0x23;\n };\n /**\n * Detects if the 2-byte packet is a Preamble Address Code\n *\n * PACs have a first byte in the range 0x10 to 0x17 (for data channel 1)\n * or 0x18 to 0x1f (for data channel 2), with the second byte in the\n * range 0x40 to 0x7f.\n *\n * @param {Integer} char0 The first byte\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the 2 bytes are a PAC\n */\n\n\n Cea608Stream.prototype.isPAC = function (char0, char1) {\n return char0 >= this.BASE_ && char0 < this.BASE_ + 8 && char1 >= 0x40 && char1 <= 0x7f;\n };\n /**\n * Detects if a packet's second byte is in the range of a PAC color code\n *\n * PAC color codes have the second byte be in the range 0x40 to 0x4f, or\n * 0x60 to 0x6f.\n *\n * @param {Integer} char1 The second byte\n * @return {Boolean} Whether the byte is a color PAC\n */\n\n\n Cea608Stream.prototype.isColorPAC = function (char1) {\n return char1 >= 0x40 && char1 <= 0x4f || char1 >= 0x60 && char1 <= 0x7f;\n };\n /**\n * Detects if a single byte is in the range of a normal character\n *\n * Normal text bytes are in the range 0x20 to 0x7f.\n *\n * @param {Integer} char The byte\n * @return {Boolean} Whether the byte is a normal character\n */\n\n\n Cea608Stream.prototype.isNormalChar = function (char) {\n return char >= 0x20 && char <= 0x7f;\n };\n /**\n * Configures roll-up\n *\n * @param {Integer} pts Current PTS\n * @param {Integer} newBaseRow Used by PACs to slide the current window to\n * a new position\n */\n\n\n Cea608Stream.prototype.setRollUp = function (pts, newBaseRow) {\n // Reset the base row to the bottom row when switching modes\n if (this.mode_ !== 'rollUp') {\n this.row_ = BOTTOM_ROW;\n this.mode_ = 'rollUp'; // Spec says to wipe memories when switching to roll-up\n\n this.flushDisplayed(pts);\n this.nonDisplayed_ = createDisplayBuffer();\n this.displayed_ = createDisplayBuffer();\n }\n\n if (newBaseRow !== undefined && newBaseRow !== this.row_) {\n // move currently displayed captions (up or down) to the new base row\n for (var i = 0; i < this.rollUpRows_; i++) {\n this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];\n this.displayed_[this.row_ - i] = '';\n }\n }\n\n if (newBaseRow === undefined) {\n newBaseRow = this.row_;\n }\n\n this.topRow_ = newBaseRow - this.rollUpRows_ + 1;\n }; // Adds the opening HTML tag for the passed character to the caption text,\n // and keeps track of it for later closing\n\n\n Cea608Stream.prototype.addFormatting = function (pts, format) {\n this.formatting_ = this.formatting_.concat(format);\n var text = format.reduce(function (text, format) {\n return text + '<' + format + '>';\n }, '');\n this[this.mode_](pts, text);\n }; // Adds HTML closing tags for current formatting to caption text and\n // clears remembered formatting\n\n\n Cea608Stream.prototype.clearFormatting = function (pts) {\n if (!this.formatting_.length) {\n return;\n }\n\n var text = this.formatting_.reverse().reduce(function (text, format) {\n return text + '';\n }, '');\n this.formatting_ = [];\n this[this.mode_](pts, text);\n }; // Mode Implementations\n\n\n Cea608Stream.prototype.popOn = function (pts, text) {\n var baseRow = this.nonDisplayed_[this.row_]; // buffer characters\n\n baseRow += text;\n this.nonDisplayed_[this.row_] = baseRow;\n };\n\n Cea608Stream.prototype.rollUp = function (pts, text) {\n var baseRow = this.displayed_[this.row_];\n baseRow += text;\n this.displayed_[this.row_] = baseRow;\n };\n\n Cea608Stream.prototype.shiftRowsUp_ = function () {\n var i; // clear out inactive rows\n\n for (i = 0; i < this.topRow_; i++) {\n this.displayed_[i] = '';\n }\n\n for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {\n this.displayed_[i] = '';\n } // shift displayed rows up\n\n\n for (i = this.topRow_; i < this.row_; i++) {\n this.displayed_[i] = this.displayed_[i + 1];\n } // clear out the bottom row\n\n\n this.displayed_[this.row_] = '';\n };\n\n Cea608Stream.prototype.paintOn = function (pts, text) {\n var baseRow = this.displayed_[this.row_];\n baseRow += text;\n this.displayed_[this.row_] = baseRow;\n }; // exports\n\n\n var captionStream = {\n CaptionStream: CaptionStream$1,\n Cea608Stream: Cea608Stream,\n Cea708Stream: Cea708Stream\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n var streamTypes = {\n H264_STREAM_TYPE: 0x1B,\n ADTS_STREAM_TYPE: 0x0F,\n METADATA_STREAM_TYPE: 0x15\n };\n var MAX_TS = 8589934592;\n var RO_THRESH = 4294967296;\n var TYPE_SHARED = 'shared';\n\n var handleRollover$1 = function handleRollover(value, reference) {\n var direction = 1;\n\n if (value > reference) {\n // If the current timestamp value is greater than our reference timestamp and we detect a\n // timestamp rollover, this means the roll over is happening in the opposite direction.\n // Example scenario: Enter a long stream/video just after a rollover occurred. The reference\n // point will be set to a small number, e.g. 1. The user then seeks backwards over the\n // rollover point. In loading this segment, the timestamp values will be very large,\n // e.g. 2^33 - 1. Since this comes before the data we loaded previously, we want to adjust\n // the time stamp to be `value - 2^33`.\n direction = -1;\n } // Note: A seek forwards or back that is greater than the RO_THRESH (2^32, ~13 hours) will\n // cause an incorrect adjustment.\n\n\n while (Math.abs(reference - value) > RO_THRESH) {\n value += direction * MAX_TS;\n }\n\n return value;\n };\n\n var TimestampRolloverStream$1 = function TimestampRolloverStream(type) {\n var lastDTS, referenceDTS;\n TimestampRolloverStream.prototype.init.call(this); // The \"shared\" type is used in cases where a stream will contain muxed\n // video and audio. We could use `undefined` here, but having a string\n // makes debugging a little clearer.\n\n this.type_ = type || TYPE_SHARED;\n\n this.push = function (data) {\n // Any \"shared\" rollover streams will accept _all_ data. Otherwise,\n // streams will only accept data that matches their type.\n if (this.type_ !== TYPE_SHARED && data.type !== this.type_) {\n return;\n }\n\n if (referenceDTS === undefined) {\n referenceDTS = data.dts;\n }\n\n data.dts = handleRollover$1(data.dts, referenceDTS);\n data.pts = handleRollover$1(data.pts, referenceDTS);\n lastDTS = data.dts;\n this.trigger('data', data);\n };\n\n this.flush = function () {\n referenceDTS = lastDTS;\n this.trigger('done');\n };\n\n this.endTimeline = function () {\n this.flush();\n this.trigger('endedtimeline');\n };\n\n this.discontinuity = function () {\n referenceDTS = void 0;\n lastDTS = void 0;\n };\n\n this.reset = function () {\n this.discontinuity();\n this.trigger('reset');\n };\n };\n\n TimestampRolloverStream$1.prototype = new stream();\n var timestampRolloverStream = {\n TimestampRolloverStream: TimestampRolloverStream$1,\n handleRollover: handleRollover$1\n };\n\n var percentEncode$1 = function percentEncode(bytes, start, end) {\n var i,\n result = '';\n\n for (i = start; i < end; i++) {\n result += '%' + ('00' + bytes[i].toString(16)).slice(-2);\n }\n\n return result;\n },\n // return the string representation of the specified byte range,\n // interpreted as UTf-8.\n parseUtf8 = function parseUtf8(bytes, start, end) {\n return decodeURIComponent(percentEncode$1(bytes, start, end));\n },\n // return the string representation of the specified byte range,\n // interpreted as ISO-8859-1.\n parseIso88591$1 = function parseIso88591(bytes, start, end) {\n return unescape(percentEncode$1(bytes, start, end)); // jshint ignore:line\n },\n parseSyncSafeInteger$1 = function parseSyncSafeInteger(data) {\n return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3];\n },\n tagParsers = {\n TXXX: function TXXX(tag) {\n var i;\n\n if (tag.data[0] !== 3) {\n // ignore frames with unrecognized character encodings\n return;\n }\n\n for (i = 1; i < tag.data.length; i++) {\n if (tag.data[i] === 0) {\n // parse the text fields\n tag.description = parseUtf8(tag.data, 1, i); // do not include the null terminator in the tag value\n\n tag.value = parseUtf8(tag.data, i + 1, tag.data.length).replace(/\\0*$/, '');\n break;\n }\n }\n\n tag.data = tag.value;\n },\n WXXX: function WXXX(tag) {\n var i;\n\n if (tag.data[0] !== 3) {\n // ignore frames with unrecognized character encodings\n return;\n }\n\n for (i = 1; i < tag.data.length; i++) {\n if (tag.data[i] === 0) {\n // parse the description and URL fields\n tag.description = parseUtf8(tag.data, 1, i);\n tag.url = parseUtf8(tag.data, i + 1, tag.data.length);\n break;\n }\n }\n },\n PRIV: function PRIV(tag) {\n var i;\n\n for (i = 0; i < tag.data.length; i++) {\n if (tag.data[i] === 0) {\n // parse the description and URL fields\n tag.owner = parseIso88591$1(tag.data, 0, i);\n break;\n }\n }\n\n tag.privateData = tag.data.subarray(i + 1);\n tag.data = tag.privateData;\n }\n },\n _MetadataStream;\n\n _MetadataStream = function MetadataStream(options) {\n var settings = {\n // the bytes of the program-level descriptor field in MP2T\n // see ISO/IEC 13818-1:2013 (E), section 2.6 \"Program and\n // program element descriptors\"\n descriptor: options && options.descriptor\n },\n // the total size in bytes of the ID3 tag being parsed\n tagSize = 0,\n // tag data that is not complete enough to be parsed\n buffer = [],\n // the total number of bytes currently in the buffer\n bufferSize = 0,\n i;\n\n _MetadataStream.prototype.init.call(this); // calculate the text track in-band metadata track dispatch type\n // https://html.spec.whatwg.org/multipage/embedded-content.html#steps-to-expose-a-media-resource-specific-text-track\n\n\n this.dispatchType = streamTypes.METADATA_STREAM_TYPE.toString(16);\n\n if (settings.descriptor) {\n for (i = 0; i < settings.descriptor.length; i++) {\n this.dispatchType += ('00' + settings.descriptor[i].toString(16)).slice(-2);\n }\n }\n\n this.push = function (chunk) {\n var tag, frameStart, frameSize, frame, i, frameHeader;\n\n if (chunk.type !== 'timed-metadata') {\n return;\n } // if data_alignment_indicator is set in the PES header,\n // we must have the start of a new ID3 tag. Assume anything\n // remaining in the buffer was malformed and throw it out\n\n\n if (chunk.dataAlignmentIndicator) {\n bufferSize = 0;\n buffer.length = 0;\n } // ignore events that don't look like ID3 data\n\n\n if (buffer.length === 0 && (chunk.data.length < 10 || chunk.data[0] !== 'I'.charCodeAt(0) || chunk.data[1] !== 'D'.charCodeAt(0) || chunk.data[2] !== '3'.charCodeAt(0))) {\n this.trigger('log', {\n level: 'warn',\n message: 'Skipping unrecognized metadata packet'\n });\n return;\n } // add this chunk to the data we've collected so far\n\n\n buffer.push(chunk);\n bufferSize += chunk.data.byteLength; // grab the size of the entire frame from the ID3 header\n\n if (buffer.length === 1) {\n // the frame size is transmitted as a 28-bit integer in the\n // last four bytes of the ID3 header.\n // The most significant bit of each byte is dropped and the\n // results concatenated to recover the actual value.\n tagSize = parseSyncSafeInteger$1(chunk.data.subarray(6, 10)); // ID3 reports the tag size excluding the header but it's more\n // convenient for our comparisons to include it\n\n tagSize += 10;\n } // if the entire frame has not arrived, wait for more data\n\n\n if (bufferSize < tagSize) {\n return;\n } // collect the entire frame so it can be parsed\n\n\n tag = {\n data: new Uint8Array(tagSize),\n frames: [],\n pts: buffer[0].pts,\n dts: buffer[0].dts\n };\n\n for (i = 0; i < tagSize;) {\n tag.data.set(buffer[0].data.subarray(0, tagSize - i), i);\n i += buffer[0].data.byteLength;\n bufferSize -= buffer[0].data.byteLength;\n buffer.shift();\n } // find the start of the first frame and the end of the tag\n\n\n frameStart = 10;\n\n if (tag.data[5] & 0x40) {\n // advance the frame start past the extended header\n frameStart += 4; // header size field\n\n frameStart += parseSyncSafeInteger$1(tag.data.subarray(10, 14)); // clip any padding off the end\n\n tagSize -= parseSyncSafeInteger$1(tag.data.subarray(16, 20));\n } // parse one or more ID3 frames\n // http://id3.org/id3v2.3.0#ID3v2_frame_overview\n\n\n do {\n // determine the number of bytes in this frame\n frameSize = parseSyncSafeInteger$1(tag.data.subarray(frameStart + 4, frameStart + 8));\n\n if (frameSize < 1) {\n this.trigger('log', {\n level: 'warn',\n message: 'Malformed ID3 frame encountered. Skipping metadata parsing.'\n });\n return;\n }\n\n frameHeader = String.fromCharCode(tag.data[frameStart], tag.data[frameStart + 1], tag.data[frameStart + 2], tag.data[frameStart + 3]);\n frame = {\n id: frameHeader,\n data: tag.data.subarray(frameStart + 10, frameStart + frameSize + 10)\n };\n frame.key = frame.id;\n\n if (tagParsers[frame.id]) {\n tagParsers[frame.id](frame); // handle the special PRIV frame used to indicate the start\n // time for raw AAC data\n\n if (frame.owner === 'com.apple.streaming.transportStreamTimestamp') {\n var d = frame.data,\n size = (d[3] & 0x01) << 30 | d[4] << 22 | d[5] << 14 | d[6] << 6 | d[7] >>> 2;\n size *= 4;\n size += d[7] & 0x03;\n frame.timeStamp = size; // in raw AAC, all subsequent data will be timestamped based\n // on the value of this frame\n // we couldn't have known the appropriate pts and dts before\n // parsing this ID3 tag so set those values now\n\n if (tag.pts === undefined && tag.dts === undefined) {\n tag.pts = frame.timeStamp;\n tag.dts = frame.timeStamp;\n }\n\n this.trigger('timestamp', frame);\n }\n }\n\n tag.frames.push(frame);\n frameStart += 10; // advance past the frame header\n\n frameStart += frameSize; // advance past the frame body\n } while (frameStart < tagSize);\n\n this.trigger('data', tag);\n };\n };\n\n _MetadataStream.prototype = new stream();\n var metadataStream = _MetadataStream;\n var TimestampRolloverStream = timestampRolloverStream.TimestampRolloverStream; // object types\n\n var _TransportPacketStream, _TransportParseStream, _ElementaryStream; // constants\n\n\n var MP2T_PACKET_LENGTH$1 = 188,\n // bytes\n SYNC_BYTE$1 = 0x47;\n /**\n * Splits an incoming stream of binary data into MPEG-2 Transport\n * Stream packets.\n */\n\n _TransportPacketStream = function TransportPacketStream() {\n var buffer = new Uint8Array(MP2T_PACKET_LENGTH$1),\n bytesInBuffer = 0;\n\n _TransportPacketStream.prototype.init.call(this); // Deliver new bytes to the stream.\n\n /**\n * Split a stream of data into M2TS packets\n **/\n\n\n this.push = function (bytes) {\n var startIndex = 0,\n endIndex = MP2T_PACKET_LENGTH$1,\n everything; // If there are bytes remaining from the last segment, prepend them to the\n // bytes that were pushed in\n\n if (bytesInBuffer) {\n everything = new Uint8Array(bytes.byteLength + bytesInBuffer);\n everything.set(buffer.subarray(0, bytesInBuffer));\n everything.set(bytes, bytesInBuffer);\n bytesInBuffer = 0;\n } else {\n everything = bytes;\n } // While we have enough data for a packet\n\n\n while (endIndex < everything.byteLength) {\n // Look for a pair of start and end sync bytes in the data..\n if (everything[startIndex] === SYNC_BYTE$1 && everything[endIndex] === SYNC_BYTE$1) {\n // We found a packet so emit it and jump one whole packet forward in\n // the stream\n this.trigger('data', everything.subarray(startIndex, endIndex));\n startIndex += MP2T_PACKET_LENGTH$1;\n endIndex += MP2T_PACKET_LENGTH$1;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex++;\n endIndex++;\n } // If there was some data left over at the end of the segment that couldn't\n // possibly be a whole packet, keep it because it might be the start of a packet\n // that continues in the next segment\n\n\n if (startIndex < everything.byteLength) {\n buffer.set(everything.subarray(startIndex), 0);\n bytesInBuffer = everything.byteLength - startIndex;\n }\n };\n /**\n * Passes identified M2TS packets to the TransportParseStream to be parsed\n **/\n\n\n this.flush = function () {\n // If the buffer contains a whole packet when we are being flushed, emit it\n // and empty the buffer. Otherwise hold onto the data because it may be\n // important for decoding the next segment\n if (bytesInBuffer === MP2T_PACKET_LENGTH$1 && buffer[0] === SYNC_BYTE$1) {\n this.trigger('data', buffer);\n bytesInBuffer = 0;\n }\n\n this.trigger('done');\n };\n\n this.endTimeline = function () {\n this.flush();\n this.trigger('endedtimeline');\n };\n\n this.reset = function () {\n bytesInBuffer = 0;\n this.trigger('reset');\n };\n };\n\n _TransportPacketStream.prototype = new stream();\n /**\n * Accepts an MP2T TransportPacketStream and emits data events with parsed\n * forms of the individual transport stream packets.\n */\n\n _TransportParseStream = function TransportParseStream() {\n var parsePsi, parsePat, parsePmt, self;\n\n _TransportParseStream.prototype.init.call(this);\n\n self = this;\n this.packetsWaitingForPmt = [];\n this.programMapTable = undefined;\n\n parsePsi = function parsePsi(payload, psi) {\n var offset = 0; // PSI packets may be split into multiple sections and those\n // sections may be split into multiple packets. If a PSI\n // section starts in this packet, the payload_unit_start_indicator\n // will be true and the first byte of the payload will indicate\n // the offset from the current position to the start of the\n // section.\n\n if (psi.payloadUnitStartIndicator) {\n offset += payload[offset] + 1;\n }\n\n if (psi.type === 'pat') {\n parsePat(payload.subarray(offset), psi);\n } else {\n parsePmt(payload.subarray(offset), psi);\n }\n };\n\n parsePat = function parsePat(payload, pat) {\n pat.section_number = payload[7]; // eslint-disable-line camelcase\n\n pat.last_section_number = payload[8]; // eslint-disable-line camelcase\n // skip the PSI header and parse the first PMT entry\n\n self.pmtPid = (payload[10] & 0x1F) << 8 | payload[11];\n pat.pmtPid = self.pmtPid;\n };\n /**\n * Parse out the relevant fields of a Program Map Table (PMT).\n * @param payload {Uint8Array} the PMT-specific portion of an MP2T\n * packet. The first byte in this array should be the table_id\n * field.\n * @param pmt {object} the object that should be decorated with\n * fields parsed from the PMT.\n */\n\n\n parsePmt = function parsePmt(payload, pmt) {\n var sectionLength, tableEnd, programInfoLength, offset; // PMTs can be sent ahead of the time when they should actually\n // take effect. We don't believe this should ever be the case\n // for HLS but we'll ignore \"forward\" PMT declarations if we see\n // them. Future PMT declarations have the current_next_indicator\n // set to zero.\n\n if (!(payload[5] & 0x01)) {\n return;\n } // overwrite any existing program map table\n\n\n self.programMapTable = {\n video: null,\n audio: null,\n 'timed-metadata': {}\n }; // the mapping table ends at the end of the current section\n\n sectionLength = (payload[1] & 0x0f) << 8 | payload[2];\n tableEnd = 3 + sectionLength - 4; // to determine where the table is, we have to figure out how\n // long the program info descriptors are\n\n programInfoLength = (payload[10] & 0x0f) << 8 | payload[11]; // advance the offset to the first entry in the mapping table\n\n offset = 12 + programInfoLength;\n\n while (offset < tableEnd) {\n var streamType = payload[offset];\n var pid = (payload[offset + 1] & 0x1F) << 8 | payload[offset + 2]; // only map a single elementary_pid for audio and video stream types\n // TODO: should this be done for metadata too? for now maintain behavior of\n // multiple metadata streams\n\n if (streamType === streamTypes.H264_STREAM_TYPE && self.programMapTable.video === null) {\n self.programMapTable.video = pid;\n } else if (streamType === streamTypes.ADTS_STREAM_TYPE && self.programMapTable.audio === null) {\n self.programMapTable.audio = pid;\n } else if (streamType === streamTypes.METADATA_STREAM_TYPE) {\n // map pid to stream type for metadata streams\n self.programMapTable['timed-metadata'][pid] = streamType;\n } // move to the next table entry\n // skip past the elementary stream descriptors, if present\n\n\n offset += ((payload[offset + 3] & 0x0F) << 8 | payload[offset + 4]) + 5;\n } // record the map on the packet as well\n\n\n pmt.programMapTable = self.programMapTable;\n };\n /**\n * Deliver a new MP2T packet to the next stream in the pipeline.\n */\n\n\n this.push = function (packet) {\n var result = {},\n offset = 4;\n result.payloadUnitStartIndicator = !!(packet[1] & 0x40); // pid is a 13-bit field starting at the last bit of packet[1]\n\n result.pid = packet[1] & 0x1f;\n result.pid <<= 8;\n result.pid |= packet[2]; // if an adaption field is present, its length is specified by the\n // fifth byte of the TS packet header. The adaptation field is\n // used to add stuffing to PES packets that don't fill a complete\n // TS packet, and to specify some forms of timing and control data\n // that we do not currently use.\n\n if ((packet[3] & 0x30) >>> 4 > 0x01) {\n offset += packet[offset] + 1;\n } // parse the rest of the packet based on the type\n\n\n if (result.pid === 0) {\n result.type = 'pat';\n parsePsi(packet.subarray(offset), result);\n this.trigger('data', result);\n } else if (result.pid === this.pmtPid) {\n result.type = 'pmt';\n parsePsi(packet.subarray(offset), result);\n this.trigger('data', result); // if there are any packets waiting for a PMT to be found, process them now\n\n while (this.packetsWaitingForPmt.length) {\n this.processPes_.apply(this, this.packetsWaitingForPmt.shift());\n }\n } else if (this.programMapTable === undefined) {\n // When we have not seen a PMT yet, defer further processing of\n // PES packets until one has been parsed\n this.packetsWaitingForPmt.push([packet, offset, result]);\n } else {\n this.processPes_(packet, offset, result);\n }\n };\n\n this.processPes_ = function (packet, offset, result) {\n // set the appropriate stream type\n if (result.pid === this.programMapTable.video) {\n result.streamType = streamTypes.H264_STREAM_TYPE;\n } else if (result.pid === this.programMapTable.audio) {\n result.streamType = streamTypes.ADTS_STREAM_TYPE;\n } else {\n // if not video or audio, it is timed-metadata or unknown\n // if unknown, streamType will be undefined\n result.streamType = this.programMapTable['timed-metadata'][result.pid];\n }\n\n result.type = 'pes';\n result.data = packet.subarray(offset);\n this.trigger('data', result);\n };\n };\n\n _TransportParseStream.prototype = new stream();\n _TransportParseStream.STREAM_TYPES = {\n h264: 0x1b,\n adts: 0x0f\n };\n /**\n * Reconsistutes program elementary stream (PES) packets from parsed\n * transport stream packets. That is, if you pipe an\n * mp2t.TransportParseStream into a mp2t.ElementaryStream, the output\n * events will be events which capture the bytes for individual PES\n * packets plus relevant metadata that has been extracted from the\n * container.\n */\n\n _ElementaryStream = function ElementaryStream() {\n var self = this,\n segmentHadPmt = false,\n // PES packet fragments\n video = {\n data: [],\n size: 0\n },\n audio = {\n data: [],\n size: 0\n },\n timedMetadata = {\n data: [],\n size: 0\n },\n programMapTable,\n parsePes = function parsePes(payload, pes) {\n var ptsDtsFlags;\n var startPrefix = payload[0] << 16 | payload[1] << 8 | payload[2]; // default to an empty array\n\n pes.data = new Uint8Array(); // In certain live streams, the start of a TS fragment has ts packets\n // that are frame data that is continuing from the previous fragment. This\n // is to check that the pes data is the start of a new pes payload\n\n if (startPrefix !== 1) {\n return;\n } // get the packet length, this will be 0 for video\n\n\n pes.packetLength = 6 + (payload[4] << 8 | payload[5]); // find out if this packets starts a new keyframe\n\n pes.dataAlignmentIndicator = (payload[6] & 0x04) !== 0; // PES packets may be annotated with a PTS value, or a PTS value\n // and a DTS value. Determine what combination of values is\n // available to work with.\n\n ptsDtsFlags = payload[7]; // PTS and DTS are normally stored as a 33-bit number. Javascript\n // performs all bitwise operations on 32-bit integers but javascript\n // supports a much greater range (52-bits) of integer using standard\n // mathematical operations.\n // We construct a 31-bit value using bitwise operators over the 31\n // most significant bits and then multiply by 4 (equal to a left-shift\n // of 2) before we add the final 2 least significant bits of the\n // timestamp (equal to an OR.)\n\n if (ptsDtsFlags & 0xC0) {\n // the PTS and DTS are not written out directly. For information\n // on how they are encoded, see\n // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html\n pes.pts = (payload[9] & 0x0E) << 27 | (payload[10] & 0xFF) << 20 | (payload[11] & 0xFE) << 12 | (payload[12] & 0xFF) << 5 | (payload[13] & 0xFE) >>> 3;\n pes.pts *= 4; // Left shift by 2\n\n pes.pts += (payload[13] & 0x06) >>> 1; // OR by the two LSBs\n\n pes.dts = pes.pts;\n\n if (ptsDtsFlags & 0x40) {\n pes.dts = (payload[14] & 0x0E) << 27 | (payload[15] & 0xFF) << 20 | (payload[16] & 0xFE) << 12 | (payload[17] & 0xFF) << 5 | (payload[18] & 0xFE) >>> 3;\n pes.dts *= 4; // Left shift by 2\n\n pes.dts += (payload[18] & 0x06) >>> 1; // OR by the two LSBs\n }\n } // the data section starts immediately after the PES header.\n // pes_header_data_length specifies the number of header bytes\n // that follow the last byte of the field.\n\n\n pes.data = payload.subarray(9 + payload[8]);\n },\n\n /**\n * Pass completely parsed PES packets to the next stream in the pipeline\n **/\n flushStream = function flushStream(stream, type, forceFlush) {\n var packetData = new Uint8Array(stream.size),\n event = {\n type: type\n },\n i = 0,\n offset = 0,\n packetFlushable = false,\n fragment; // do nothing if there is not enough buffered data for a complete\n // PES header\n\n if (!stream.data.length || stream.size < 9) {\n return;\n }\n\n event.trackId = stream.data[0].pid; // reassemble the packet\n\n for (i = 0; i < stream.data.length; i++) {\n fragment = stream.data[i];\n packetData.set(fragment.data, offset);\n offset += fragment.data.byteLength;\n } // parse assembled packet's PES header\n\n\n parsePes(packetData, event); // non-video PES packets MUST have a non-zero PES_packet_length\n // check that there is enough stream data to fill the packet\n\n packetFlushable = type === 'video' || event.packetLength <= stream.size; // flush pending packets if the conditions are right\n\n if (forceFlush || packetFlushable) {\n stream.size = 0;\n stream.data.length = 0;\n } // only emit packets that are complete. this is to avoid assembling\n // incomplete PES packets due to poor segmentation\n\n\n if (packetFlushable) {\n self.trigger('data', event);\n }\n };\n\n _ElementaryStream.prototype.init.call(this);\n /**\n * Identifies M2TS packet types and parses PES packets using metadata\n * parsed from the PMT\n **/\n\n\n this.push = function (data) {\n ({\n pat: function pat() {// we have to wait for the PMT to arrive as well before we\n // have any meaningful metadata\n },\n pes: function pes() {\n var stream, streamType;\n\n switch (data.streamType) {\n case streamTypes.H264_STREAM_TYPE:\n stream = video;\n streamType = 'video';\n break;\n\n case streamTypes.ADTS_STREAM_TYPE:\n stream = audio;\n streamType = 'audio';\n break;\n\n case streamTypes.METADATA_STREAM_TYPE:\n stream = timedMetadata;\n streamType = 'timed-metadata';\n break;\n\n default:\n // ignore unknown stream types\n return;\n } // if a new packet is starting, we can flush the completed\n // packet\n\n\n if (data.payloadUnitStartIndicator) {\n flushStream(stream, streamType, true);\n } // buffer this fragment until we are sure we've received the\n // complete payload\n\n\n stream.data.push(data);\n stream.size += data.data.byteLength;\n },\n pmt: function pmt() {\n var event = {\n type: 'metadata',\n tracks: []\n };\n programMapTable = data.programMapTable; // translate audio and video streams to tracks\n\n if (programMapTable.video !== null) {\n event.tracks.push({\n timelineStartInfo: {\n baseMediaDecodeTime: 0\n },\n id: +programMapTable.video,\n codec: 'avc',\n type: 'video'\n });\n }\n\n if (programMapTable.audio !== null) {\n event.tracks.push({\n timelineStartInfo: {\n baseMediaDecodeTime: 0\n },\n id: +programMapTable.audio,\n codec: 'adts',\n type: 'audio'\n });\n }\n\n segmentHadPmt = true;\n self.trigger('data', event);\n }\n })[data.type]();\n };\n\n this.reset = function () {\n video.size = 0;\n video.data.length = 0;\n audio.size = 0;\n audio.data.length = 0;\n this.trigger('reset');\n };\n /**\n * Flush any remaining input. Video PES packets may be of variable\n * length. Normally, the start of a new video packet can trigger the\n * finalization of the previous packet. That is not possible if no\n * more video is forthcoming, however. In that case, some other\n * mechanism (like the end of the file) has to be employed. When it is\n * clear that no additional data is forthcoming, calling this method\n * will flush the buffered packets.\n */\n\n\n this.flushStreams_ = function () {\n // !!THIS ORDER IS IMPORTANT!!\n // video first then audio\n flushStream(video, 'video');\n flushStream(audio, 'audio');\n flushStream(timedMetadata, 'timed-metadata');\n };\n\n this.flush = function () {\n // if on flush we haven't had a pmt emitted\n // and we have a pmt to emit. emit the pmt\n // so that we trigger a trackinfo downstream.\n if (!segmentHadPmt && programMapTable) {\n var pmt = {\n type: 'metadata',\n tracks: []\n }; // translate audio and video streams to tracks\n\n if (programMapTable.video !== null) {\n pmt.tracks.push({\n timelineStartInfo: {\n baseMediaDecodeTime: 0\n },\n id: +programMapTable.video,\n codec: 'avc',\n type: 'video'\n });\n }\n\n if (programMapTable.audio !== null) {\n pmt.tracks.push({\n timelineStartInfo: {\n baseMediaDecodeTime: 0\n },\n id: +programMapTable.audio,\n codec: 'adts',\n type: 'audio'\n });\n }\n\n self.trigger('data', pmt);\n }\n\n segmentHadPmt = false;\n this.flushStreams_();\n this.trigger('done');\n };\n };\n\n _ElementaryStream.prototype = new stream();\n var m2ts = {\n PAT_PID: 0x0000,\n MP2T_PACKET_LENGTH: MP2T_PACKET_LENGTH$1,\n TransportPacketStream: _TransportPacketStream,\n TransportParseStream: _TransportParseStream,\n ElementaryStream: _ElementaryStream,\n TimestampRolloverStream: TimestampRolloverStream,\n CaptionStream: captionStream.CaptionStream,\n Cea608Stream: captionStream.Cea608Stream,\n Cea708Stream: captionStream.Cea708Stream,\n MetadataStream: metadataStream\n };\n\n for (var type in streamTypes) {\n if (streamTypes.hasOwnProperty(type)) {\n m2ts[type] = streamTypes[type];\n }\n }\n\n var m2ts_1 = m2ts;\n var ONE_SECOND_IN_TS$2 = clock.ONE_SECOND_IN_TS;\n\n var _AdtsStream;\n\n var ADTS_SAMPLING_FREQUENCIES$1 = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];\n /*\n * Accepts a ElementaryStream and emits data events with parsed\n * AAC Audio Frames of the individual packets. Input audio in ADTS\n * format is unpacked and re-emitted as AAC frames.\n *\n * @see http://wiki.multimedia.cx/index.php?title=ADTS\n * @see http://wiki.multimedia.cx/?title=Understanding_AAC\n */\n\n _AdtsStream = function AdtsStream(handlePartialSegments) {\n var buffer,\n frameNum = 0;\n\n _AdtsStream.prototype.init.call(this);\n\n this.skipWarn_ = function (start, end) {\n this.trigger('log', {\n level: 'warn',\n message: \"adts skiping bytes \" + start + \" to \" + end + \" in frame \" + frameNum + \" outside syncword\"\n });\n };\n\n this.push = function (packet) {\n var i = 0,\n frameLength,\n protectionSkipBytes,\n oldBuffer,\n sampleCount,\n adtsFrameDuration;\n\n if (!handlePartialSegments) {\n frameNum = 0;\n }\n\n if (packet.type !== 'audio') {\n // ignore non-audio data\n return;\n } // Prepend any data in the buffer to the input data so that we can parse\n // aac frames the cross a PES packet boundary\n\n\n if (buffer && buffer.length) {\n oldBuffer = buffer;\n buffer = new Uint8Array(oldBuffer.byteLength + packet.data.byteLength);\n buffer.set(oldBuffer);\n buffer.set(packet.data, oldBuffer.byteLength);\n } else {\n buffer = packet.data;\n } // unpack any ADTS frames which have been fully received\n // for details on the ADTS header, see http://wiki.multimedia.cx/index.php?title=ADTS\n\n\n var skip; // We use i + 7 here because we want to be able to parse the entire header.\n // If we don't have enough bytes to do that, then we definitely won't have a full frame.\n\n while (i + 7 < buffer.length) {\n // Look for the start of an ADTS header..\n if (buffer[i] !== 0xFF || (buffer[i + 1] & 0xF6) !== 0xF0) {\n if (typeof skip !== 'number') {\n skip = i;\n } // If a valid header was not found, jump one forward and attempt to\n // find a valid ADTS header starting at the next byte\n\n\n i++;\n continue;\n }\n\n if (typeof skip === 'number') {\n this.skipWarn_(skip, i);\n skip = null;\n } // The protection skip bit tells us if we have 2 bytes of CRC data at the\n // end of the ADTS header\n\n\n protectionSkipBytes = (~buffer[i + 1] & 0x01) * 2; // Frame length is a 13 bit integer starting 16 bits from the\n // end of the sync sequence\n // NOTE: frame length includes the size of the header\n\n frameLength = (buffer[i + 3] & 0x03) << 11 | buffer[i + 4] << 3 | (buffer[i + 5] & 0xe0) >> 5;\n sampleCount = ((buffer[i + 6] & 0x03) + 1) * 1024;\n adtsFrameDuration = sampleCount * ONE_SECOND_IN_TS$2 / ADTS_SAMPLING_FREQUENCIES$1[(buffer[i + 2] & 0x3c) >>> 2]; // If we don't have enough data to actually finish this ADTS frame,\n // then we have to wait for more data\n\n if (buffer.byteLength - i < frameLength) {\n break;\n } // Otherwise, deliver the complete AAC frame\n\n\n this.trigger('data', {\n pts: packet.pts + frameNum * adtsFrameDuration,\n dts: packet.dts + frameNum * adtsFrameDuration,\n sampleCount: sampleCount,\n audioobjecttype: (buffer[i + 2] >>> 6 & 0x03) + 1,\n channelcount: (buffer[i + 2] & 1) << 2 | (buffer[i + 3] & 0xc0) >>> 6,\n samplerate: ADTS_SAMPLING_FREQUENCIES$1[(buffer[i + 2] & 0x3c) >>> 2],\n samplingfrequencyindex: (buffer[i + 2] & 0x3c) >>> 2,\n // assume ISO/IEC 14496-12 AudioSampleEntry default of 16\n samplesize: 16,\n // data is the frame without it's header\n data: buffer.subarray(i + 7 + protectionSkipBytes, i + frameLength)\n });\n frameNum++;\n i += frameLength;\n }\n\n if (typeof skip === 'number') {\n this.skipWarn_(skip, i);\n skip = null;\n } // remove processed bytes from the buffer.\n\n\n buffer = buffer.subarray(i);\n };\n\n this.flush = function () {\n frameNum = 0;\n this.trigger('done');\n };\n\n this.reset = function () {\n buffer = void 0;\n this.trigger('reset');\n };\n\n this.endTimeline = function () {\n buffer = void 0;\n this.trigger('endedtimeline');\n };\n };\n\n _AdtsStream.prototype = new stream();\n var adts = _AdtsStream;\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n var ExpGolomb;\n /**\n * Parser for exponential Golomb codes, a variable-bitwidth number encoding\n * scheme used by h264.\n */\n\n ExpGolomb = function ExpGolomb(workingData) {\n var // the number of bytes left to examine in workingData\n workingBytesAvailable = workingData.byteLength,\n // the current word being examined\n workingWord = 0,\n // :uint\n // the number of bits left to examine in the current word\n workingBitsAvailable = 0; // :uint;\n // ():uint\n\n this.length = function () {\n return 8 * workingBytesAvailable;\n }; // ():uint\n\n\n this.bitsAvailable = function () {\n return 8 * workingBytesAvailable + workingBitsAvailable;\n }; // ():void\n\n\n this.loadWord = function () {\n var position = workingData.byteLength - workingBytesAvailable,\n workingBytes = new Uint8Array(4),\n availableBytes = Math.min(4, workingBytesAvailable);\n\n if (availableBytes === 0) {\n throw new Error('no bytes available');\n }\n\n workingBytes.set(workingData.subarray(position, position + availableBytes));\n workingWord = new DataView(workingBytes.buffer).getUint32(0); // track the amount of workingData that has been processed\n\n workingBitsAvailable = availableBytes * 8;\n workingBytesAvailable -= availableBytes;\n }; // (count:int):void\n\n\n this.skipBits = function (count) {\n var skipBytes; // :int\n\n if (workingBitsAvailable > count) {\n workingWord <<= count;\n workingBitsAvailable -= count;\n } else {\n count -= workingBitsAvailable;\n skipBytes = Math.floor(count / 8);\n count -= skipBytes * 8;\n workingBytesAvailable -= skipBytes;\n this.loadWord();\n workingWord <<= count;\n workingBitsAvailable -= count;\n }\n }; // (size:int):uint\n\n\n this.readBits = function (size) {\n var bits = Math.min(workingBitsAvailable, size),\n // :uint\n valu = workingWord >>> 32 - bits; // :uint\n // if size > 31, handle error\n\n workingBitsAvailable -= bits;\n\n if (workingBitsAvailable > 0) {\n workingWord <<= bits;\n } else if (workingBytesAvailable > 0) {\n this.loadWord();\n }\n\n bits = size - bits;\n\n if (bits > 0) {\n return valu << bits | this.readBits(bits);\n }\n\n return valu;\n }; // ():uint\n\n\n this.skipLeadingZeros = function () {\n var leadingZeroCount; // :uint\n\n for (leadingZeroCount = 0; leadingZeroCount < workingBitsAvailable; ++leadingZeroCount) {\n if ((workingWord & 0x80000000 >>> leadingZeroCount) !== 0) {\n // the first bit of working word is 1\n workingWord <<= leadingZeroCount;\n workingBitsAvailable -= leadingZeroCount;\n return leadingZeroCount;\n }\n } // we exhausted workingWord and still have not found a 1\n\n\n this.loadWord();\n return leadingZeroCount + this.skipLeadingZeros();\n }; // ():void\n\n\n this.skipUnsignedExpGolomb = function () {\n this.skipBits(1 + this.skipLeadingZeros());\n }; // ():void\n\n\n this.skipExpGolomb = function () {\n this.skipBits(1 + this.skipLeadingZeros());\n }; // ():uint\n\n\n this.readUnsignedExpGolomb = function () {\n var clz = this.skipLeadingZeros(); // :uint\n\n return this.readBits(clz + 1) - 1;\n }; // ():int\n\n\n this.readExpGolomb = function () {\n var valu = this.readUnsignedExpGolomb(); // :int\n\n if (0x01 & valu) {\n // the number is odd if the low order bit is set\n return 1 + valu >>> 1; // add 1 to make it even, and divide by 2\n }\n\n return -1 * (valu >>> 1); // divide by two then make it negative\n }; // Some convenience functions\n // :Boolean\n\n\n this.readBoolean = function () {\n return this.readBits(1) === 1;\n }; // ():int\n\n\n this.readUnsignedByte = function () {\n return this.readBits(8);\n };\n\n this.loadWord();\n };\n\n var expGolomb = ExpGolomb;\n\n var _H264Stream, _NalByteStream;\n\n var PROFILES_WITH_OPTIONAL_SPS_DATA;\n /**\n * Accepts a NAL unit byte stream and unpacks the embedded NAL units.\n */\n\n _NalByteStream = function NalByteStream() {\n var syncPoint = 0,\n i,\n buffer;\n\n _NalByteStream.prototype.init.call(this);\n /*\n * Scans a byte stream and triggers a data event with the NAL units found.\n * @param {Object} data Event received from H264Stream\n * @param {Uint8Array} data.data The h264 byte stream to be scanned\n *\n * @see H264Stream.push\n */\n\n\n this.push = function (data) {\n var swapBuffer;\n\n if (!buffer) {\n buffer = data.data;\n } else {\n swapBuffer = new Uint8Array(buffer.byteLength + data.data.byteLength);\n swapBuffer.set(buffer);\n swapBuffer.set(data.data, buffer.byteLength);\n buffer = swapBuffer;\n }\n\n var len = buffer.byteLength; // Rec. ITU-T H.264, Annex B\n // scan for NAL unit boundaries\n // a match looks like this:\n // 0 0 1 .. NAL .. 0 0 1\n // ^ sync point ^ i\n // or this:\n // 0 0 1 .. NAL .. 0 0 0\n // ^ sync point ^ i\n // advance the sync point to a NAL start, if necessary\n\n for (; syncPoint < len - 3; syncPoint++) {\n if (buffer[syncPoint + 2] === 1) {\n // the sync point is properly aligned\n i = syncPoint + 5;\n break;\n }\n }\n\n while (i < len) {\n // look at the current byte to determine if we've hit the end of\n // a NAL unit boundary\n switch (buffer[i]) {\n case 0:\n // skip past non-sync sequences\n if (buffer[i - 1] !== 0) {\n i += 2;\n break;\n } else if (buffer[i - 2] !== 0) {\n i++;\n break;\n } // deliver the NAL unit if it isn't empty\n\n\n if (syncPoint + 3 !== i - 2) {\n this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));\n } // drop trailing zeroes\n\n\n do {\n i++;\n } while (buffer[i] !== 1 && i < len);\n\n syncPoint = i - 2;\n i += 3;\n break;\n\n case 1:\n // skip past non-sync sequences\n if (buffer[i - 1] !== 0 || buffer[i - 2] !== 0) {\n i += 3;\n break;\n } // deliver the NAL unit\n\n\n this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));\n syncPoint = i - 2;\n i += 3;\n break;\n\n default:\n // the current byte isn't a one or zero, so it cannot be part\n // of a sync sequence\n i += 3;\n break;\n }\n } // filter out the NAL units that were delivered\n\n\n buffer = buffer.subarray(syncPoint);\n i -= syncPoint;\n syncPoint = 0;\n };\n\n this.reset = function () {\n buffer = null;\n syncPoint = 0;\n this.trigger('reset');\n };\n\n this.flush = function () {\n // deliver the last buffered NAL unit\n if (buffer && buffer.byteLength > 3) {\n this.trigger('data', buffer.subarray(syncPoint + 3));\n } // reset the stream state\n\n\n buffer = null;\n syncPoint = 0;\n this.trigger('done');\n };\n\n this.endTimeline = function () {\n this.flush();\n this.trigger('endedtimeline');\n };\n };\n\n _NalByteStream.prototype = new stream(); // values of profile_idc that indicate additional fields are included in the SPS\n // see Recommendation ITU-T H.264 (4/2013),\n // 7.3.2.1.1 Sequence parameter set data syntax\n\n PROFILES_WITH_OPTIONAL_SPS_DATA = {\n 100: true,\n 110: true,\n 122: true,\n 244: true,\n 44: true,\n 83: true,\n 86: true,\n 118: true,\n 128: true,\n // TODO: the three profiles below don't\n // appear to have sps data in the specificiation anymore?\n 138: true,\n 139: true,\n 134: true\n };\n /**\n * Accepts input from a ElementaryStream and produces H.264 NAL unit data\n * events.\n */\n\n _H264Stream = function H264Stream() {\n var nalByteStream = new _NalByteStream(),\n self,\n trackId,\n currentPts,\n currentDts,\n discardEmulationPreventionBytes,\n readSequenceParameterSet,\n skipScalingList;\n\n _H264Stream.prototype.init.call(this);\n\n self = this;\n /*\n * Pushes a packet from a stream onto the NalByteStream\n *\n * @param {Object} packet - A packet received from a stream\n * @param {Uint8Array} packet.data - The raw bytes of the packet\n * @param {Number} packet.dts - Decode timestamp of the packet\n * @param {Number} packet.pts - Presentation timestamp of the packet\n * @param {Number} packet.trackId - The id of the h264 track this packet came from\n * @param {('video'|'audio')} packet.type - The type of packet\n *\n */\n\n this.push = function (packet) {\n if (packet.type !== 'video') {\n return;\n }\n\n trackId = packet.trackId;\n currentPts = packet.pts;\n currentDts = packet.dts;\n nalByteStream.push(packet);\n };\n /*\n * Identify NAL unit types and pass on the NALU, trackId, presentation and decode timestamps\n * for the NALUs to the next stream component.\n * Also, preprocess caption and sequence parameter NALUs.\n *\n * @param {Uint8Array} data - A NAL unit identified by `NalByteStream.push`\n * @see NalByteStream.push\n */\n\n\n nalByteStream.on('data', function (data) {\n var event = {\n trackId: trackId,\n pts: currentPts,\n dts: currentDts,\n data: data,\n nalUnitTypeCode: data[0] & 0x1f\n };\n\n switch (event.nalUnitTypeCode) {\n case 0x05:\n event.nalUnitType = 'slice_layer_without_partitioning_rbsp_idr';\n break;\n\n case 0x06:\n event.nalUnitType = 'sei_rbsp';\n event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));\n break;\n\n case 0x07:\n event.nalUnitType = 'seq_parameter_set_rbsp';\n event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));\n event.config = readSequenceParameterSet(event.escapedRBSP);\n break;\n\n case 0x08:\n event.nalUnitType = 'pic_parameter_set_rbsp';\n break;\n\n case 0x09:\n event.nalUnitType = 'access_unit_delimiter_rbsp';\n break;\n } // This triggers data on the H264Stream\n\n\n self.trigger('data', event);\n });\n nalByteStream.on('done', function () {\n self.trigger('done');\n });\n nalByteStream.on('partialdone', function () {\n self.trigger('partialdone');\n });\n nalByteStream.on('reset', function () {\n self.trigger('reset');\n });\n nalByteStream.on('endedtimeline', function () {\n self.trigger('endedtimeline');\n });\n\n this.flush = function () {\n nalByteStream.flush();\n };\n\n this.partialFlush = function () {\n nalByteStream.partialFlush();\n };\n\n this.reset = function () {\n nalByteStream.reset();\n };\n\n this.endTimeline = function () {\n nalByteStream.endTimeline();\n };\n /**\n * Advance the ExpGolomb decoder past a scaling list. The scaling\n * list is optionally transmitted as part of a sequence parameter\n * set and is not relevant to transmuxing.\n * @param count {number} the number of entries in this scaling list\n * @param expGolombDecoder {object} an ExpGolomb pointed to the\n * start of a scaling list\n * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1\n */\n\n\n skipScalingList = function skipScalingList(count, expGolombDecoder) {\n var lastScale = 8,\n nextScale = 8,\n j,\n deltaScale;\n\n for (j = 0; j < count; j++) {\n if (nextScale !== 0) {\n deltaScale = expGolombDecoder.readExpGolomb();\n nextScale = (lastScale + deltaScale + 256) % 256;\n }\n\n lastScale = nextScale === 0 ? lastScale : nextScale;\n }\n };\n /**\n * Expunge any \"Emulation Prevention\" bytes from a \"Raw Byte\n * Sequence Payload\"\n * @param data {Uint8Array} the bytes of a RBSP from a NAL\n * unit\n * @return {Uint8Array} the RBSP without any Emulation\n * Prevention Bytes\n */\n\n\n discardEmulationPreventionBytes = function discardEmulationPreventionBytes(data) {\n var length = data.byteLength,\n emulationPreventionBytesPositions = [],\n i = 1,\n newLength,\n newData; // Find all `Emulation Prevention Bytes`\n\n while (i < length - 2) {\n if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {\n emulationPreventionBytesPositions.push(i + 2);\n i += 2;\n } else {\n i++;\n }\n } // If no Emulation Prevention Bytes were found just return the original\n // array\n\n\n if (emulationPreventionBytesPositions.length === 0) {\n return data;\n } // Create a new array to hold the NAL unit data\n\n\n newLength = length - emulationPreventionBytesPositions.length;\n newData = new Uint8Array(newLength);\n var sourceIndex = 0;\n\n for (i = 0; i < newLength; sourceIndex++, i++) {\n if (sourceIndex === emulationPreventionBytesPositions[0]) {\n // Skip this byte\n sourceIndex++; // Remove this position index\n\n emulationPreventionBytesPositions.shift();\n }\n\n newData[i] = data[sourceIndex];\n }\n\n return newData;\n };\n /**\n * Read a sequence parameter set and return some interesting video\n * properties. A sequence parameter set is the H264 metadata that\n * describes the properties of upcoming video frames.\n * @param data {Uint8Array} the bytes of a sequence parameter set\n * @return {object} an object with configuration parsed from the\n * sequence parameter set, including the dimensions of the\n * associated video frames.\n */\n\n\n readSequenceParameterSet = function readSequenceParameterSet(data) {\n var frameCropLeftOffset = 0,\n frameCropRightOffset = 0,\n frameCropTopOffset = 0,\n frameCropBottomOffset = 0,\n expGolombDecoder,\n profileIdc,\n levelIdc,\n profileCompatibility,\n chromaFormatIdc,\n picOrderCntType,\n numRefFramesInPicOrderCntCycle,\n picWidthInMbsMinus1,\n picHeightInMapUnitsMinus1,\n frameMbsOnlyFlag,\n scalingListCount,\n sarRatio = [1, 1],\n aspectRatioIdc,\n i;\n expGolombDecoder = new expGolomb(data);\n profileIdc = expGolombDecoder.readUnsignedByte(); // profile_idc\n\n profileCompatibility = expGolombDecoder.readUnsignedByte(); // constraint_set[0-5]_flag\n\n levelIdc = expGolombDecoder.readUnsignedByte(); // level_idc u(8)\n\n expGolombDecoder.skipUnsignedExpGolomb(); // seq_parameter_set_id\n // some profiles have more optional data we don't need\n\n if (PROFILES_WITH_OPTIONAL_SPS_DATA[profileIdc]) {\n chromaFormatIdc = expGolombDecoder.readUnsignedExpGolomb();\n\n if (chromaFormatIdc === 3) {\n expGolombDecoder.skipBits(1); // separate_colour_plane_flag\n }\n\n expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_luma_minus8\n\n expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_chroma_minus8\n\n expGolombDecoder.skipBits(1); // qpprime_y_zero_transform_bypass_flag\n\n if (expGolombDecoder.readBoolean()) {\n // seq_scaling_matrix_present_flag\n scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;\n\n for (i = 0; i < scalingListCount; i++) {\n if (expGolombDecoder.readBoolean()) {\n // seq_scaling_list_present_flag[ i ]\n if (i < 6) {\n skipScalingList(16, expGolombDecoder);\n } else {\n skipScalingList(64, expGolombDecoder);\n }\n }\n }\n }\n }\n\n expGolombDecoder.skipUnsignedExpGolomb(); // log2_max_frame_num_minus4\n\n picOrderCntType = expGolombDecoder.readUnsignedExpGolomb();\n\n if (picOrderCntType === 0) {\n expGolombDecoder.readUnsignedExpGolomb(); // log2_max_pic_order_cnt_lsb_minus4\n } else if (picOrderCntType === 1) {\n expGolombDecoder.skipBits(1); // delta_pic_order_always_zero_flag\n\n expGolombDecoder.skipExpGolomb(); // offset_for_non_ref_pic\n\n expGolombDecoder.skipExpGolomb(); // offset_for_top_to_bottom_field\n\n numRefFramesInPicOrderCntCycle = expGolombDecoder.readUnsignedExpGolomb();\n\n for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {\n expGolombDecoder.skipExpGolomb(); // offset_for_ref_frame[ i ]\n }\n }\n\n expGolombDecoder.skipUnsignedExpGolomb(); // max_num_ref_frames\n\n expGolombDecoder.skipBits(1); // gaps_in_frame_num_value_allowed_flag\n\n picWidthInMbsMinus1 = expGolombDecoder.readUnsignedExpGolomb();\n picHeightInMapUnitsMinus1 = expGolombDecoder.readUnsignedExpGolomb();\n frameMbsOnlyFlag = expGolombDecoder.readBits(1);\n\n if (frameMbsOnlyFlag === 0) {\n expGolombDecoder.skipBits(1); // mb_adaptive_frame_field_flag\n }\n\n expGolombDecoder.skipBits(1); // direct_8x8_inference_flag\n\n if (expGolombDecoder.readBoolean()) {\n // frame_cropping_flag\n frameCropLeftOffset = expGolombDecoder.readUnsignedExpGolomb();\n frameCropRightOffset = expGolombDecoder.readUnsignedExpGolomb();\n frameCropTopOffset = expGolombDecoder.readUnsignedExpGolomb();\n frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();\n }\n\n if (expGolombDecoder.readBoolean()) {\n // vui_parameters_present_flag\n if (expGolombDecoder.readBoolean()) {\n // aspect_ratio_info_present_flag\n aspectRatioIdc = expGolombDecoder.readUnsignedByte();\n\n switch (aspectRatioIdc) {\n case 1:\n sarRatio = [1, 1];\n break;\n\n case 2:\n sarRatio = [12, 11];\n break;\n\n case 3:\n sarRatio = [10, 11];\n break;\n\n case 4:\n sarRatio = [16, 11];\n break;\n\n case 5:\n sarRatio = [40, 33];\n break;\n\n case 6:\n sarRatio = [24, 11];\n break;\n\n case 7:\n sarRatio = [20, 11];\n break;\n\n case 8:\n sarRatio = [32, 11];\n break;\n\n case 9:\n sarRatio = [80, 33];\n break;\n\n case 10:\n sarRatio = [18, 11];\n break;\n\n case 11:\n sarRatio = [15, 11];\n break;\n\n case 12:\n sarRatio = [64, 33];\n break;\n\n case 13:\n sarRatio = [160, 99];\n break;\n\n case 14:\n sarRatio = [4, 3];\n break;\n\n case 15:\n sarRatio = [3, 2];\n break;\n\n case 16:\n sarRatio = [2, 1];\n break;\n\n case 255:\n {\n sarRatio = [expGolombDecoder.readUnsignedByte() << 8 | expGolombDecoder.readUnsignedByte(), expGolombDecoder.readUnsignedByte() << 8 | expGolombDecoder.readUnsignedByte()];\n break;\n }\n }\n\n if (sarRatio) {\n sarRatio[0] / sarRatio[1];\n }\n }\n }\n\n return {\n profileIdc: profileIdc,\n levelIdc: levelIdc,\n profileCompatibility: profileCompatibility,\n width: (picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2,\n height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - frameCropTopOffset * 2 - frameCropBottomOffset * 2,\n // sar is sample aspect ratio\n sarRatio: sarRatio\n };\n };\n };\n\n _H264Stream.prototype = new stream();\n var h264 = {\n H264Stream: _H264Stream,\n NalByteStream: _NalByteStream\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n *\n * Utilities to detect basic properties and metadata about Aac data.\n */\n\n var ADTS_SAMPLING_FREQUENCIES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];\n\n var parseId3TagSize = function parseId3TagSize(header, byteIndex) {\n var returnSize = header[byteIndex + 6] << 21 | header[byteIndex + 7] << 14 | header[byteIndex + 8] << 7 | header[byteIndex + 9],\n flags = header[byteIndex + 5],\n footerPresent = (flags & 16) >> 4; // if we get a negative returnSize clamp it to 0\n\n returnSize = returnSize >= 0 ? returnSize : 0;\n\n if (footerPresent) {\n return returnSize + 20;\n }\n\n return returnSize + 10;\n };\n\n var getId3Offset = function getId3Offset(data, offset) {\n if (data.length - offset < 10 || data[offset] !== 'I'.charCodeAt(0) || data[offset + 1] !== 'D'.charCodeAt(0) || data[offset + 2] !== '3'.charCodeAt(0)) {\n return offset;\n }\n\n offset += parseId3TagSize(data, offset);\n return getId3Offset(data, offset);\n }; // TODO: use vhs-utils\n\n\n var isLikelyAacData$1 = function isLikelyAacData(data) {\n var offset = getId3Offset(data, 0);\n return data.length >= offset + 2 && (data[offset] & 0xFF) === 0xFF && (data[offset + 1] & 0xF0) === 0xF0 && // verify that the 2 layer bits are 0, aka this\n // is not mp3 data but aac data.\n (data[offset + 1] & 0x16) === 0x10;\n };\n\n var parseSyncSafeInteger = function parseSyncSafeInteger(data) {\n return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3];\n }; // return a percent-encoded representation of the specified byte range\n // @see http://en.wikipedia.org/wiki/Percent-encoding\n\n\n var percentEncode = function percentEncode(bytes, start, end) {\n var i,\n result = '';\n\n for (i = start; i < end; i++) {\n result += '%' + ('00' + bytes[i].toString(16)).slice(-2);\n }\n\n return result;\n }; // return the string representation of the specified byte range,\n // interpreted as ISO-8859-1.\n\n\n var parseIso88591 = function parseIso88591(bytes, start, end) {\n return unescape(percentEncode(bytes, start, end)); // jshint ignore:line\n };\n\n var parseAdtsSize = function parseAdtsSize(header, byteIndex) {\n var lowThree = (header[byteIndex + 5] & 0xE0) >> 5,\n middle = header[byteIndex + 4] << 3,\n highTwo = header[byteIndex + 3] & 0x3 << 11;\n return highTwo | middle | lowThree;\n };\n\n var parseType$2 = function parseType(header, byteIndex) {\n if (header[byteIndex] === 'I'.charCodeAt(0) && header[byteIndex + 1] === 'D'.charCodeAt(0) && header[byteIndex + 2] === '3'.charCodeAt(0)) {\n return 'timed-metadata';\n } else if (header[byteIndex] & 0xff === 0xff && (header[byteIndex + 1] & 0xf0) === 0xf0) {\n return 'audio';\n }\n\n return null;\n };\n\n var parseSampleRate = function parseSampleRate(packet) {\n var i = 0;\n\n while (i + 5 < packet.length) {\n if (packet[i] !== 0xFF || (packet[i + 1] & 0xF6) !== 0xF0) {\n // If a valid header was not found, jump one forward and attempt to\n // find a valid ADTS header starting at the next byte\n i++;\n continue;\n }\n\n return ADTS_SAMPLING_FREQUENCIES[(packet[i + 2] & 0x3c) >>> 2];\n }\n\n return null;\n };\n\n var parseAacTimestamp = function parseAacTimestamp(packet) {\n var frameStart, frameSize, frame, frameHeader; // find the start of the first frame and the end of the tag\n\n frameStart = 10;\n\n if (packet[5] & 0x40) {\n // advance the frame start past the extended header\n frameStart += 4; // header size field\n\n frameStart += parseSyncSafeInteger(packet.subarray(10, 14));\n } // parse one or more ID3 frames\n // http://id3.org/id3v2.3.0#ID3v2_frame_overview\n\n\n do {\n // determine the number of bytes in this frame\n frameSize = parseSyncSafeInteger(packet.subarray(frameStart + 4, frameStart + 8));\n\n if (frameSize < 1) {\n return null;\n }\n\n frameHeader = String.fromCharCode(packet[frameStart], packet[frameStart + 1], packet[frameStart + 2], packet[frameStart + 3]);\n\n if (frameHeader === 'PRIV') {\n frame = packet.subarray(frameStart + 10, frameStart + frameSize + 10);\n\n for (var i = 0; i < frame.byteLength; i++) {\n if (frame[i] === 0) {\n var owner = parseIso88591(frame, 0, i);\n\n if (owner === 'com.apple.streaming.transportStreamTimestamp') {\n var d = frame.subarray(i + 1);\n var size = (d[3] & 0x01) << 30 | d[4] << 22 | d[5] << 14 | d[6] << 6 | d[7] >>> 2;\n size *= 4;\n size += d[7] & 0x03;\n return size;\n }\n\n break;\n }\n }\n }\n\n frameStart += 10; // advance past the frame header\n\n frameStart += frameSize; // advance past the frame body\n } while (frameStart < packet.byteLength);\n\n return null;\n };\n\n var utils = {\n isLikelyAacData: isLikelyAacData$1,\n parseId3TagSize: parseId3TagSize,\n parseAdtsSize: parseAdtsSize,\n parseType: parseType$2,\n parseSampleRate: parseSampleRate,\n parseAacTimestamp: parseAacTimestamp\n };\n\n var _AacStream;\n /**\n * Splits an incoming stream of binary data into ADTS and ID3 Frames.\n */\n\n\n _AacStream = function AacStream() {\n var everything = new Uint8Array(),\n timeStamp = 0;\n\n _AacStream.prototype.init.call(this);\n\n this.setTimestamp = function (timestamp) {\n timeStamp = timestamp;\n };\n\n this.push = function (bytes) {\n var frameSize = 0,\n byteIndex = 0,\n bytesLeft,\n chunk,\n packet,\n tempLength; // If there are bytes remaining from the last segment, prepend them to the\n // bytes that were pushed in\n\n if (everything.length) {\n tempLength = everything.length;\n everything = new Uint8Array(bytes.byteLength + tempLength);\n everything.set(everything.subarray(0, tempLength));\n everything.set(bytes, tempLength);\n } else {\n everything = bytes;\n }\n\n while (everything.length - byteIndex >= 3) {\n if (everything[byteIndex] === 'I'.charCodeAt(0) && everything[byteIndex + 1] === 'D'.charCodeAt(0) && everything[byteIndex + 2] === '3'.charCodeAt(0)) {\n // Exit early because we don't have enough to parse\n // the ID3 tag header\n if (everything.length - byteIndex < 10) {\n break;\n } // check framesize\n\n\n frameSize = utils.parseId3TagSize(everything, byteIndex); // Exit early if we don't have enough in the buffer\n // to emit a full packet\n // Add to byteIndex to support multiple ID3 tags in sequence\n\n if (byteIndex + frameSize > everything.length) {\n break;\n }\n\n chunk = {\n type: 'timed-metadata',\n data: everything.subarray(byteIndex, byteIndex + frameSize)\n };\n this.trigger('data', chunk);\n byteIndex += frameSize;\n continue;\n } else if ((everything[byteIndex] & 0xff) === 0xff && (everything[byteIndex + 1] & 0xf0) === 0xf0) {\n // Exit early because we don't have enough to parse\n // the ADTS frame header\n if (everything.length - byteIndex < 7) {\n break;\n }\n\n frameSize = utils.parseAdtsSize(everything, byteIndex); // Exit early if we don't have enough in the buffer\n // to emit a full packet\n\n if (byteIndex + frameSize > everything.length) {\n break;\n }\n\n packet = {\n type: 'audio',\n data: everything.subarray(byteIndex, byteIndex + frameSize),\n pts: timeStamp,\n dts: timeStamp\n };\n this.trigger('data', packet);\n byteIndex += frameSize;\n continue;\n }\n\n byteIndex++;\n }\n\n bytesLeft = everything.length - byteIndex;\n\n if (bytesLeft > 0) {\n everything = everything.subarray(byteIndex);\n } else {\n everything = new Uint8Array();\n }\n };\n\n this.reset = function () {\n everything = new Uint8Array();\n this.trigger('reset');\n };\n\n this.endTimeline = function () {\n everything = new Uint8Array();\n this.trigger('endedtimeline');\n };\n };\n\n _AacStream.prototype = new stream();\n var aac = _AacStream; // constants\n\n var AUDIO_PROPERTIES = ['audioobjecttype', 'channelcount', 'samplerate', 'samplingfrequencyindex', 'samplesize'];\n var audioProperties = AUDIO_PROPERTIES;\n var VIDEO_PROPERTIES = ['width', 'height', 'profileIdc', 'levelIdc', 'profileCompatibility', 'sarRatio'];\n var videoProperties = VIDEO_PROPERTIES;\n var H264Stream = h264.H264Stream;\n var isLikelyAacData = utils.isLikelyAacData;\n var ONE_SECOND_IN_TS$1 = clock.ONE_SECOND_IN_TS; // object types\n\n var _VideoSegmentStream, _AudioSegmentStream, _Transmuxer, _CoalesceStream;\n\n var retriggerForStream = function retriggerForStream(key, event) {\n event.stream = key;\n this.trigger('log', event);\n };\n\n var addPipelineLogRetriggers = function addPipelineLogRetriggers(transmuxer, pipeline) {\n var keys = Object.keys(pipeline);\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i]; // skip non-stream keys and headOfPipeline\n // which is just a duplicate\n\n if (key === 'headOfPipeline' || !pipeline[key].on) {\n continue;\n }\n\n pipeline[key].on('log', retriggerForStream.bind(transmuxer, key));\n }\n };\n /**\n * Compare two arrays (even typed) for same-ness\n */\n\n\n var arrayEquals = function arrayEquals(a, b) {\n var i;\n\n if (a.length !== b.length) {\n return false;\n } // compare the value of each element in the array\n\n\n for (i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n\n return true;\n };\n\n var generateSegmentTimingInfo = function generateSegmentTimingInfo(baseMediaDecodeTime, startDts, startPts, endDts, endPts, prependedContentDuration) {\n var ptsOffsetFromDts = startPts - startDts,\n decodeDuration = endDts - startDts,\n presentationDuration = endPts - startPts; // The PTS and DTS values are based on the actual stream times from the segment,\n // however, the player time values will reflect a start from the baseMediaDecodeTime.\n // In order to provide relevant values for the player times, base timing info on the\n // baseMediaDecodeTime and the DTS and PTS durations of the segment.\n\n return {\n start: {\n dts: baseMediaDecodeTime,\n pts: baseMediaDecodeTime + ptsOffsetFromDts\n },\n end: {\n dts: baseMediaDecodeTime + decodeDuration,\n pts: baseMediaDecodeTime + presentationDuration\n },\n prependedContentDuration: prependedContentDuration,\n baseMediaDecodeTime: baseMediaDecodeTime\n };\n };\n /**\n * Constructs a single-track, ISO BMFF media segment from AAC data\n * events. The output of this stream can be fed to a SourceBuffer\n * configured with a suitable initialization segment.\n * @param track {object} track metadata configuration\n * @param options {object} transmuxer options object\n * @param options.keepOriginalTimestamps {boolean} If true, keep the timestamps\n * in the source; false to adjust the first segment to start at 0.\n */\n\n\n _AudioSegmentStream = function AudioSegmentStream(track, options) {\n var adtsFrames = [],\n sequenceNumber,\n earliestAllowedDts = 0,\n audioAppendStartTs = 0,\n videoBaseMediaDecodeTime = Infinity;\n options = options || {};\n sequenceNumber = options.firstSequenceNumber || 0;\n\n _AudioSegmentStream.prototype.init.call(this);\n\n this.push = function (data) {\n trackDecodeInfo.collectDtsInfo(track, data);\n\n if (track) {\n audioProperties.forEach(function (prop) {\n track[prop] = data[prop];\n });\n } // buffer audio data until end() is called\n\n\n adtsFrames.push(data);\n };\n\n this.setEarliestDts = function (earliestDts) {\n earliestAllowedDts = earliestDts;\n };\n\n this.setVideoBaseMediaDecodeTime = function (baseMediaDecodeTime) {\n videoBaseMediaDecodeTime = baseMediaDecodeTime;\n };\n\n this.setAudioAppendStart = function (timestamp) {\n audioAppendStartTs = timestamp;\n };\n\n this.flush = function () {\n var frames, moof, mdat, boxes, frameDuration, segmentDuration, videoClockCyclesOfSilencePrefixed; // return early if no audio data has been observed\n\n if (adtsFrames.length === 0) {\n this.trigger('done', 'AudioSegmentStream');\n return;\n }\n\n frames = audioFrameUtils.trimAdtsFramesByEarliestDts(adtsFrames, track, earliestAllowedDts);\n track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(track, options.keepOriginalTimestamps); // amount of audio filled but the value is in video clock rather than audio clock\n\n videoClockCyclesOfSilencePrefixed = audioFrameUtils.prefixWithSilence(track, frames, audioAppendStartTs, videoBaseMediaDecodeTime); // we have to build the index from byte locations to\n // samples (that is, adts frames) in the audio data\n\n track.samples = audioFrameUtils.generateSampleTable(frames); // concatenate the audio data to constuct the mdat\n\n mdat = mp4Generator.mdat(audioFrameUtils.concatenateFrameData(frames));\n adtsFrames = [];\n moof = mp4Generator.moof(sequenceNumber, [track]);\n boxes = new Uint8Array(moof.byteLength + mdat.byteLength); // bump the sequence number for next time\n\n sequenceNumber++;\n boxes.set(moof);\n boxes.set(mdat, moof.byteLength);\n trackDecodeInfo.clearDtsInfo(track);\n frameDuration = Math.ceil(ONE_SECOND_IN_TS$1 * 1024 / track.samplerate); // TODO this check was added to maintain backwards compatibility (particularly with\n // tests) on adding the timingInfo event. However, it seems unlikely that there's a\n // valid use-case where an init segment/data should be triggered without associated\n // frames. Leaving for now, but should be looked into.\n\n if (frames.length) {\n segmentDuration = frames.length * frameDuration;\n this.trigger('segmentTimingInfo', generateSegmentTimingInfo( // The audio track's baseMediaDecodeTime is in audio clock cycles, but the\n // frame info is in video clock cycles. Convert to match expectation of\n // listeners (that all timestamps will be based on video clock cycles).\n clock.audioTsToVideoTs(track.baseMediaDecodeTime, track.samplerate), // frame times are already in video clock, as is segment duration\n frames[0].dts, frames[0].pts, frames[0].dts + segmentDuration, frames[0].pts + segmentDuration, videoClockCyclesOfSilencePrefixed || 0));\n this.trigger('timingInfo', {\n start: frames[0].pts,\n end: frames[0].pts + segmentDuration\n });\n }\n\n this.trigger('data', {\n track: track,\n boxes: boxes\n });\n this.trigger('done', 'AudioSegmentStream');\n };\n\n this.reset = function () {\n trackDecodeInfo.clearDtsInfo(track);\n adtsFrames = [];\n this.trigger('reset');\n };\n };\n\n _AudioSegmentStream.prototype = new stream();\n /**\n * Constructs a single-track, ISO BMFF media segment from H264 data\n * events. The output of this stream can be fed to a SourceBuffer\n * configured with a suitable initialization segment.\n * @param track {object} track metadata configuration\n * @param options {object} transmuxer options object\n * @param options.alignGopsAtEnd {boolean} If true, start from the end of the\n * gopsToAlignWith list when attempting to align gop pts\n * @param options.keepOriginalTimestamps {boolean} If true, keep the timestamps\n * in the source; false to adjust the first segment to start at 0.\n */\n\n _VideoSegmentStream = function VideoSegmentStream(track, options) {\n var sequenceNumber,\n nalUnits = [],\n gopsToAlignWith = [],\n config,\n pps;\n options = options || {};\n sequenceNumber = options.firstSequenceNumber || 0;\n\n _VideoSegmentStream.prototype.init.call(this);\n\n delete track.minPTS;\n this.gopCache_ = [];\n /**\n * Constructs a ISO BMFF segment given H264 nalUnits\n * @param {Object} nalUnit A data event representing a nalUnit\n * @param {String} nalUnit.nalUnitType\n * @param {Object} nalUnit.config Properties for a mp4 track\n * @param {Uint8Array} nalUnit.data The nalUnit bytes\n * @see lib/codecs/h264.js\n **/\n\n this.push = function (nalUnit) {\n trackDecodeInfo.collectDtsInfo(track, nalUnit); // record the track config\n\n if (nalUnit.nalUnitType === 'seq_parameter_set_rbsp' && !config) {\n config = nalUnit.config;\n track.sps = [nalUnit.data];\n videoProperties.forEach(function (prop) {\n track[prop] = config[prop];\n }, this);\n }\n\n if (nalUnit.nalUnitType === 'pic_parameter_set_rbsp' && !pps) {\n pps = nalUnit.data;\n track.pps = [nalUnit.data];\n } // buffer video until flush() is called\n\n\n nalUnits.push(nalUnit);\n };\n /**\n * Pass constructed ISO BMFF track and boxes on to the\n * next stream in the pipeline\n **/\n\n\n this.flush = function () {\n var frames,\n gopForFusion,\n gops,\n moof,\n mdat,\n boxes,\n prependedContentDuration = 0,\n firstGop,\n lastGop; // Throw away nalUnits at the start of the byte stream until\n // we find the first AUD\n\n while (nalUnits.length) {\n if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') {\n break;\n }\n\n nalUnits.shift();\n } // Return early if no video data has been observed\n\n\n if (nalUnits.length === 0) {\n this.resetStream_();\n this.trigger('done', 'VideoSegmentStream');\n return;\n } // Organize the raw nal-units into arrays that represent\n // higher-level constructs such as frames and gops\n // (group-of-pictures)\n\n\n frames = frameUtils.groupNalsIntoFrames(nalUnits);\n gops = frameUtils.groupFramesIntoGops(frames); // If the first frame of this fragment is not a keyframe we have\n // a problem since MSE (on Chrome) requires a leading keyframe.\n //\n // We have two approaches to repairing this situation:\n // 1) GOP-FUSION:\n // This is where we keep track of the GOPS (group-of-pictures)\n // from previous fragments and attempt to find one that we can\n // prepend to the current fragment in order to create a valid\n // fragment.\n // 2) KEYFRAME-PULLING:\n // Here we search for the first keyframe in the fragment and\n // throw away all the frames between the start of the fragment\n // and that keyframe. We then extend the duration and pull the\n // PTS of the keyframe forward so that it covers the time range\n // of the frames that were disposed of.\n //\n // #1 is far prefereable over #2 which can cause \"stuttering\" but\n // requires more things to be just right.\n\n if (!gops[0][0].keyFrame) {\n // Search for a gop for fusion from our gopCache\n gopForFusion = this.getGopForFusion_(nalUnits[0], track);\n\n if (gopForFusion) {\n // in order to provide more accurate timing information about the segment, save\n // the number of seconds prepended to the original segment due to GOP fusion\n prependedContentDuration = gopForFusion.duration;\n gops.unshift(gopForFusion); // Adjust Gops' metadata to account for the inclusion of the\n // new gop at the beginning\n\n gops.byteLength += gopForFusion.byteLength;\n gops.nalCount += gopForFusion.nalCount;\n gops.pts = gopForFusion.pts;\n gops.dts = gopForFusion.dts;\n gops.duration += gopForFusion.duration;\n } else {\n // If we didn't find a candidate gop fall back to keyframe-pulling\n gops = frameUtils.extendFirstKeyFrame(gops);\n }\n } // Trim gops to align with gopsToAlignWith\n\n\n if (gopsToAlignWith.length) {\n var alignedGops;\n\n if (options.alignGopsAtEnd) {\n alignedGops = this.alignGopsAtEnd_(gops);\n } else {\n alignedGops = this.alignGopsAtStart_(gops);\n }\n\n if (!alignedGops) {\n // save all the nals in the last GOP into the gop cache\n this.gopCache_.unshift({\n gop: gops.pop(),\n pps: track.pps,\n sps: track.sps\n }); // Keep a maximum of 6 GOPs in the cache\n\n this.gopCache_.length = Math.min(6, this.gopCache_.length); // Clear nalUnits\n\n nalUnits = []; // return early no gops can be aligned with desired gopsToAlignWith\n\n this.resetStream_();\n this.trigger('done', 'VideoSegmentStream');\n return;\n } // Some gops were trimmed. clear dts info so minSegmentDts and pts are correct\n // when recalculated before sending off to CoalesceStream\n\n\n trackDecodeInfo.clearDtsInfo(track);\n gops = alignedGops;\n }\n\n trackDecodeInfo.collectDtsInfo(track, gops); // First, we have to build the index from byte locations to\n // samples (that is, frames) in the video data\n\n track.samples = frameUtils.generateSampleTable(gops); // Concatenate the video data and construct the mdat\n\n mdat = mp4Generator.mdat(frameUtils.concatenateNalData(gops));\n track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(track, options.keepOriginalTimestamps);\n this.trigger('processedGopsInfo', gops.map(function (gop) {\n return {\n pts: gop.pts,\n dts: gop.dts,\n byteLength: gop.byteLength\n };\n }));\n firstGop = gops[0];\n lastGop = gops[gops.length - 1];\n this.trigger('segmentTimingInfo', generateSegmentTimingInfo(track.baseMediaDecodeTime, firstGop.dts, firstGop.pts, lastGop.dts + lastGop.duration, lastGop.pts + lastGop.duration, prependedContentDuration));\n this.trigger('timingInfo', {\n start: gops[0].pts,\n end: gops[gops.length - 1].pts + gops[gops.length - 1].duration\n }); // save all the nals in the last GOP into the gop cache\n\n this.gopCache_.unshift({\n gop: gops.pop(),\n pps: track.pps,\n sps: track.sps\n }); // Keep a maximum of 6 GOPs in the cache\n\n this.gopCache_.length = Math.min(6, this.gopCache_.length); // Clear nalUnits\n\n nalUnits = [];\n this.trigger('baseMediaDecodeTime', track.baseMediaDecodeTime);\n this.trigger('timelineStartInfo', track.timelineStartInfo);\n moof = mp4Generator.moof(sequenceNumber, [track]); // it would be great to allocate this array up front instead of\n // throwing away hundreds of media segment fragments\n\n boxes = new Uint8Array(moof.byteLength + mdat.byteLength); // Bump the sequence number for next time\n\n sequenceNumber++;\n boxes.set(moof);\n boxes.set(mdat, moof.byteLength);\n this.trigger('data', {\n track: track,\n boxes: boxes\n });\n this.resetStream_(); // Continue with the flush process now\n\n this.trigger('done', 'VideoSegmentStream');\n };\n\n this.reset = function () {\n this.resetStream_();\n nalUnits = [];\n this.gopCache_.length = 0;\n gopsToAlignWith.length = 0;\n this.trigger('reset');\n };\n\n this.resetStream_ = function () {\n trackDecodeInfo.clearDtsInfo(track); // reset config and pps because they may differ across segments\n // for instance, when we are rendition switching\n\n config = undefined;\n pps = undefined;\n }; // Search for a candidate Gop for gop-fusion from the gop cache and\n // return it or return null if no good candidate was found\n\n\n this.getGopForFusion_ = function (nalUnit) {\n var halfSecond = 45000,\n // Half-a-second in a 90khz clock\n allowableOverlap = 10000,\n // About 3 frames @ 30fps\n nearestDistance = Infinity,\n dtsDistance,\n nearestGopObj,\n currentGop,\n currentGopObj,\n i; // Search for the GOP nearest to the beginning of this nal unit\n\n for (i = 0; i < this.gopCache_.length; i++) {\n currentGopObj = this.gopCache_[i];\n currentGop = currentGopObj.gop; // Reject Gops with different SPS or PPS\n\n if (!(track.pps && arrayEquals(track.pps[0], currentGopObj.pps[0])) || !(track.sps && arrayEquals(track.sps[0], currentGopObj.sps[0]))) {\n continue;\n } // Reject Gops that would require a negative baseMediaDecodeTime\n\n\n if (currentGop.dts < track.timelineStartInfo.dts) {\n continue;\n } // The distance between the end of the gop and the start of the nalUnit\n\n\n dtsDistance = nalUnit.dts - currentGop.dts - currentGop.duration; // Only consider GOPS that start before the nal unit and end within\n // a half-second of the nal unit\n\n if (dtsDistance >= -allowableOverlap && dtsDistance <= halfSecond) {\n // Always use the closest GOP we found if there is more than\n // one candidate\n if (!nearestGopObj || nearestDistance > dtsDistance) {\n nearestGopObj = currentGopObj;\n nearestDistance = dtsDistance;\n }\n }\n }\n\n if (nearestGopObj) {\n return nearestGopObj.gop;\n }\n\n return null;\n }; // trim gop list to the first gop found that has a matching pts with a gop in the list\n // of gopsToAlignWith starting from the START of the list\n\n\n this.alignGopsAtStart_ = function (gops) {\n var alignIndex, gopIndex, align, gop, byteLength, nalCount, duration, alignedGops;\n byteLength = gops.byteLength;\n nalCount = gops.nalCount;\n duration = gops.duration;\n alignIndex = gopIndex = 0;\n\n while (alignIndex < gopsToAlignWith.length && gopIndex < gops.length) {\n align = gopsToAlignWith[alignIndex];\n gop = gops[gopIndex];\n\n if (align.pts === gop.pts) {\n break;\n }\n\n if (gop.pts > align.pts) {\n // this current gop starts after the current gop we want to align on, so increment\n // align index\n alignIndex++;\n continue;\n } // current gop starts before the current gop we want to align on. so increment gop\n // index\n\n\n gopIndex++;\n byteLength -= gop.byteLength;\n nalCount -= gop.nalCount;\n duration -= gop.duration;\n }\n\n if (gopIndex === 0) {\n // no gops to trim\n return gops;\n }\n\n if (gopIndex === gops.length) {\n // all gops trimmed, skip appending all gops\n return null;\n }\n\n alignedGops = gops.slice(gopIndex);\n alignedGops.byteLength = byteLength;\n alignedGops.duration = duration;\n alignedGops.nalCount = nalCount;\n alignedGops.pts = alignedGops[0].pts;\n alignedGops.dts = alignedGops[0].dts;\n return alignedGops;\n }; // trim gop list to the first gop found that has a matching pts with a gop in the list\n // of gopsToAlignWith starting from the END of the list\n\n\n this.alignGopsAtEnd_ = function (gops) {\n var alignIndex, gopIndex, align, gop, alignEndIndex, matchFound;\n alignIndex = gopsToAlignWith.length - 1;\n gopIndex = gops.length - 1;\n alignEndIndex = null;\n matchFound = false;\n\n while (alignIndex >= 0 && gopIndex >= 0) {\n align = gopsToAlignWith[alignIndex];\n gop = gops[gopIndex];\n\n if (align.pts === gop.pts) {\n matchFound = true;\n break;\n }\n\n if (align.pts > gop.pts) {\n alignIndex--;\n continue;\n }\n\n if (alignIndex === gopsToAlignWith.length - 1) {\n // gop.pts is greater than the last alignment candidate. If no match is found\n // by the end of this loop, we still want to append gops that come after this\n // point\n alignEndIndex = gopIndex;\n }\n\n gopIndex--;\n }\n\n if (!matchFound && alignEndIndex === null) {\n return null;\n }\n\n var trimIndex;\n\n if (matchFound) {\n trimIndex = gopIndex;\n } else {\n trimIndex = alignEndIndex;\n }\n\n if (trimIndex === 0) {\n return gops;\n }\n\n var alignedGops = gops.slice(trimIndex);\n var metadata = alignedGops.reduce(function (total, gop) {\n total.byteLength += gop.byteLength;\n total.duration += gop.duration;\n total.nalCount += gop.nalCount;\n return total;\n }, {\n byteLength: 0,\n duration: 0,\n nalCount: 0\n });\n alignedGops.byteLength = metadata.byteLength;\n alignedGops.duration = metadata.duration;\n alignedGops.nalCount = metadata.nalCount;\n alignedGops.pts = alignedGops[0].pts;\n alignedGops.dts = alignedGops[0].dts;\n return alignedGops;\n };\n\n this.alignGopsWith = function (newGopsToAlignWith) {\n gopsToAlignWith = newGopsToAlignWith;\n };\n };\n\n _VideoSegmentStream.prototype = new stream();\n /**\n * A Stream that can combine multiple streams (ie. audio & video)\n * into a single output segment for MSE. Also supports audio-only\n * and video-only streams.\n * @param options {object} transmuxer options object\n * @param options.keepOriginalTimestamps {boolean} If true, keep the timestamps\n * in the source; false to adjust the first segment to start at media timeline start.\n */\n\n _CoalesceStream = function CoalesceStream(options, metadataStream) {\n // Number of Tracks per output segment\n // If greater than 1, we combine multiple\n // tracks into a single segment\n this.numberOfTracks = 0;\n this.metadataStream = metadataStream;\n options = options || {};\n\n if (typeof options.remux !== 'undefined') {\n this.remuxTracks = !!options.remux;\n } else {\n this.remuxTracks = true;\n }\n\n if (typeof options.keepOriginalTimestamps === 'boolean') {\n this.keepOriginalTimestamps = options.keepOriginalTimestamps;\n } else {\n this.keepOriginalTimestamps = false;\n }\n\n this.pendingTracks = [];\n this.videoTrack = null;\n this.pendingBoxes = [];\n this.pendingCaptions = [];\n this.pendingMetadata = [];\n this.pendingBytes = 0;\n this.emittedTracks = 0;\n\n _CoalesceStream.prototype.init.call(this); // Take output from multiple\n\n\n this.push = function (output) {\n // buffer incoming captions until the associated video segment\n // finishes\n if (output.text) {\n return this.pendingCaptions.push(output);\n } // buffer incoming id3 tags until the final flush\n\n\n if (output.frames) {\n return this.pendingMetadata.push(output);\n } // Add this track to the list of pending tracks and store\n // important information required for the construction of\n // the final segment\n\n\n this.pendingTracks.push(output.track);\n this.pendingBytes += output.boxes.byteLength; // TODO: is there an issue for this against chrome?\n // We unshift audio and push video because\n // as of Chrome 75 when switching from\n // one init segment to another if the video\n // mdat does not appear after the audio mdat\n // only audio will play for the duration of our transmux.\n\n if (output.track.type === 'video') {\n this.videoTrack = output.track;\n this.pendingBoxes.push(output.boxes);\n }\n\n if (output.track.type === 'audio') {\n this.audioTrack = output.track;\n this.pendingBoxes.unshift(output.boxes);\n }\n };\n };\n\n _CoalesceStream.prototype = new stream();\n\n _CoalesceStream.prototype.flush = function (flushSource) {\n var offset = 0,\n event = {\n captions: [],\n captionStreams: {},\n metadata: [],\n info: {}\n },\n caption,\n id3,\n initSegment,\n timelineStartPts = 0,\n i;\n\n if (this.pendingTracks.length < this.numberOfTracks) {\n if (flushSource !== 'VideoSegmentStream' && flushSource !== 'AudioSegmentStream') {\n // Return because we haven't received a flush from a data-generating\n // portion of the segment (meaning that we have only recieved meta-data\n // or captions.)\n return;\n } else if (this.remuxTracks) {\n // Return until we have enough tracks from the pipeline to remux (if we\n // are remuxing audio and video into a single MP4)\n return;\n } else if (this.pendingTracks.length === 0) {\n // In the case where we receive a flush without any data having been\n // received we consider it an emitted track for the purposes of coalescing\n // `done` events.\n // We do this for the case where there is an audio and video track in the\n // segment but no audio data. (seen in several playlists with alternate\n // audio tracks and no audio present in the main TS segments.)\n this.emittedTracks++;\n\n if (this.emittedTracks >= this.numberOfTracks) {\n this.trigger('done');\n this.emittedTracks = 0;\n }\n\n return;\n }\n }\n\n if (this.videoTrack) {\n timelineStartPts = this.videoTrack.timelineStartInfo.pts;\n videoProperties.forEach(function (prop) {\n event.info[prop] = this.videoTrack[prop];\n }, this);\n } else if (this.audioTrack) {\n timelineStartPts = this.audioTrack.timelineStartInfo.pts;\n audioProperties.forEach(function (prop) {\n event.info[prop] = this.audioTrack[prop];\n }, this);\n }\n\n if (this.videoTrack || this.audioTrack) {\n if (this.pendingTracks.length === 1) {\n event.type = this.pendingTracks[0].type;\n } else {\n event.type = 'combined';\n }\n\n this.emittedTracks += this.pendingTracks.length;\n initSegment = mp4Generator.initSegment(this.pendingTracks); // Create a new typed array to hold the init segment\n\n event.initSegment = new Uint8Array(initSegment.byteLength); // Create an init segment containing a moov\n // and track definitions\n\n event.initSegment.set(initSegment); // Create a new typed array to hold the moof+mdats\n\n event.data = new Uint8Array(this.pendingBytes); // Append each moof+mdat (one per track) together\n\n for (i = 0; i < this.pendingBoxes.length; i++) {\n event.data.set(this.pendingBoxes[i], offset);\n offset += this.pendingBoxes[i].byteLength;\n } // Translate caption PTS times into second offsets to match the\n // video timeline for the segment, and add track info\n\n\n for (i = 0; i < this.pendingCaptions.length; i++) {\n caption = this.pendingCaptions[i];\n caption.startTime = clock.metadataTsToSeconds(caption.startPts, timelineStartPts, this.keepOriginalTimestamps);\n caption.endTime = clock.metadataTsToSeconds(caption.endPts, timelineStartPts, this.keepOriginalTimestamps);\n event.captionStreams[caption.stream] = true;\n event.captions.push(caption);\n } // Translate ID3 frame PTS times into second offsets to match the\n // video timeline for the segment\n\n\n for (i = 0; i < this.pendingMetadata.length; i++) {\n id3 = this.pendingMetadata[i];\n id3.cueTime = clock.metadataTsToSeconds(id3.pts, timelineStartPts, this.keepOriginalTimestamps);\n event.metadata.push(id3);\n } // We add this to every single emitted segment even though we only need\n // it for the first\n\n\n event.metadata.dispatchType = this.metadataStream.dispatchType; // Reset stream state\n\n this.pendingTracks.length = 0;\n this.videoTrack = null;\n this.pendingBoxes.length = 0;\n this.pendingCaptions.length = 0;\n this.pendingBytes = 0;\n this.pendingMetadata.length = 0; // Emit the built segment\n // We include captions and ID3 tags for backwards compatibility,\n // ideally we should send only video and audio in the data event\n\n this.trigger('data', event); // Emit each caption to the outside world\n // Ideally, this would happen immediately on parsing captions,\n // but we need to ensure that video data is sent back first\n // so that caption timing can be adjusted to match video timing\n\n for (i = 0; i < event.captions.length; i++) {\n caption = event.captions[i];\n this.trigger('caption', caption);\n } // Emit each id3 tag to the outside world\n // Ideally, this would happen immediately on parsing the tag,\n // but we need to ensure that video data is sent back first\n // so that ID3 frame timing can be adjusted to match video timing\n\n\n for (i = 0; i < event.metadata.length; i++) {\n id3 = event.metadata[i];\n this.trigger('id3Frame', id3);\n }\n } // Only emit `done` if all tracks have been flushed and emitted\n\n\n if (this.emittedTracks >= this.numberOfTracks) {\n this.trigger('done');\n this.emittedTracks = 0;\n }\n };\n\n _CoalesceStream.prototype.setRemux = function (val) {\n this.remuxTracks = val;\n };\n /**\n * A Stream that expects MP2T binary data as input and produces\n * corresponding media segments, suitable for use with Media Source\n * Extension (MSE) implementations that support the ISO BMFF byte\n * stream format, like Chrome.\n */\n\n\n _Transmuxer = function Transmuxer(options) {\n var self = this,\n hasFlushed = true,\n videoTrack,\n audioTrack;\n\n _Transmuxer.prototype.init.call(this);\n\n options = options || {};\n this.baseMediaDecodeTime = options.baseMediaDecodeTime || 0;\n this.transmuxPipeline_ = {};\n\n this.setupAacPipeline = function () {\n var pipeline = {};\n this.transmuxPipeline_ = pipeline;\n pipeline.type = 'aac';\n pipeline.metadataStream = new m2ts_1.MetadataStream(); // set up the parsing pipeline\n\n pipeline.aacStream = new aac();\n pipeline.audioTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('audio');\n pipeline.timedMetadataTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('timed-metadata');\n pipeline.adtsStream = new adts();\n pipeline.coalesceStream = new _CoalesceStream(options, pipeline.metadataStream);\n pipeline.headOfPipeline = pipeline.aacStream;\n pipeline.aacStream.pipe(pipeline.audioTimestampRolloverStream).pipe(pipeline.adtsStream);\n pipeline.aacStream.pipe(pipeline.timedMetadataTimestampRolloverStream).pipe(pipeline.metadataStream).pipe(pipeline.coalesceStream);\n pipeline.metadataStream.on('timestamp', function (frame) {\n pipeline.aacStream.setTimestamp(frame.timeStamp);\n });\n pipeline.aacStream.on('data', function (data) {\n if (data.type !== 'timed-metadata' && data.type !== 'audio' || pipeline.audioSegmentStream) {\n return;\n }\n\n audioTrack = audioTrack || {\n timelineStartInfo: {\n baseMediaDecodeTime: self.baseMediaDecodeTime\n },\n codec: 'adts',\n type: 'audio'\n }; // hook up the audio segment stream to the first track with aac data\n\n pipeline.coalesceStream.numberOfTracks++;\n pipeline.audioSegmentStream = new _AudioSegmentStream(audioTrack, options);\n pipeline.audioSegmentStream.on('log', self.getLogTrigger_('audioSegmentStream'));\n pipeline.audioSegmentStream.on('timingInfo', self.trigger.bind(self, 'audioTimingInfo')); // Set up the final part of the audio pipeline\n\n pipeline.adtsStream.pipe(pipeline.audioSegmentStream).pipe(pipeline.coalesceStream); // emit pmt info\n\n self.trigger('trackinfo', {\n hasAudio: !!audioTrack,\n hasVideo: !!videoTrack\n });\n }); // Re-emit any data coming from the coalesce stream to the outside world\n\n pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data')); // Let the consumer know we have finished flushing the entire pipeline\n\n pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));\n addPipelineLogRetriggers(this, pipeline);\n };\n\n this.setupTsPipeline = function () {\n var pipeline = {};\n this.transmuxPipeline_ = pipeline;\n pipeline.type = 'ts';\n pipeline.metadataStream = new m2ts_1.MetadataStream(); // set up the parsing pipeline\n\n pipeline.packetStream = new m2ts_1.TransportPacketStream();\n pipeline.parseStream = new m2ts_1.TransportParseStream();\n pipeline.elementaryStream = new m2ts_1.ElementaryStream();\n pipeline.timestampRolloverStream = new m2ts_1.TimestampRolloverStream();\n pipeline.adtsStream = new adts();\n pipeline.h264Stream = new H264Stream();\n pipeline.captionStream = new m2ts_1.CaptionStream(options);\n pipeline.coalesceStream = new _CoalesceStream(options, pipeline.metadataStream);\n pipeline.headOfPipeline = pipeline.packetStream; // disassemble MPEG2-TS packets into elementary streams\n\n pipeline.packetStream.pipe(pipeline.parseStream).pipe(pipeline.elementaryStream).pipe(pipeline.timestampRolloverStream); // !!THIS ORDER IS IMPORTANT!!\n // demux the streams\n\n pipeline.timestampRolloverStream.pipe(pipeline.h264Stream);\n pipeline.timestampRolloverStream.pipe(pipeline.adtsStream);\n pipeline.timestampRolloverStream.pipe(pipeline.metadataStream).pipe(pipeline.coalesceStream); // Hook up CEA-608/708 caption stream\n\n pipeline.h264Stream.pipe(pipeline.captionStream).pipe(pipeline.coalesceStream);\n pipeline.elementaryStream.on('data', function (data) {\n var i;\n\n if (data.type === 'metadata') {\n i = data.tracks.length; // scan the tracks listed in the metadata\n\n while (i--) {\n if (!videoTrack && data.tracks[i].type === 'video') {\n videoTrack = data.tracks[i];\n videoTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;\n } else if (!audioTrack && data.tracks[i].type === 'audio') {\n audioTrack = data.tracks[i];\n audioTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;\n }\n } // hook up the video segment stream to the first track with h264 data\n\n\n if (videoTrack && !pipeline.videoSegmentStream) {\n pipeline.coalesceStream.numberOfTracks++;\n pipeline.videoSegmentStream = new _VideoSegmentStream(videoTrack, options);\n pipeline.videoSegmentStream.on('log', self.getLogTrigger_('videoSegmentStream'));\n pipeline.videoSegmentStream.on('timelineStartInfo', function (timelineStartInfo) {\n // When video emits timelineStartInfo data after a flush, we forward that\n // info to the AudioSegmentStream, if it exists, because video timeline\n // data takes precedence. Do not do this if keepOriginalTimestamps is set,\n // because this is a particularly subtle form of timestamp alteration.\n if (audioTrack && !options.keepOriginalTimestamps) {\n audioTrack.timelineStartInfo = timelineStartInfo; // On the first segment we trim AAC frames that exist before the\n // very earliest DTS we have seen in video because Chrome will\n // interpret any video track with a baseMediaDecodeTime that is\n // non-zero as a gap.\n\n pipeline.audioSegmentStream.setEarliestDts(timelineStartInfo.dts - self.baseMediaDecodeTime);\n }\n });\n pipeline.videoSegmentStream.on('processedGopsInfo', self.trigger.bind(self, 'gopInfo'));\n pipeline.videoSegmentStream.on('segmentTimingInfo', self.trigger.bind(self, 'videoSegmentTimingInfo'));\n pipeline.videoSegmentStream.on('baseMediaDecodeTime', function (baseMediaDecodeTime) {\n if (audioTrack) {\n pipeline.audioSegmentStream.setVideoBaseMediaDecodeTime(baseMediaDecodeTime);\n }\n });\n pipeline.videoSegmentStream.on('timingInfo', self.trigger.bind(self, 'videoTimingInfo')); // Set up the final part of the video pipeline\n\n pipeline.h264Stream.pipe(pipeline.videoSegmentStream).pipe(pipeline.coalesceStream);\n }\n\n if (audioTrack && !pipeline.audioSegmentStream) {\n // hook up the audio segment stream to the first track with aac data\n pipeline.coalesceStream.numberOfTracks++;\n pipeline.audioSegmentStream = new _AudioSegmentStream(audioTrack, options);\n pipeline.audioSegmentStream.on('log', self.getLogTrigger_('audioSegmentStream'));\n pipeline.audioSegmentStream.on('timingInfo', self.trigger.bind(self, 'audioTimingInfo'));\n pipeline.audioSegmentStream.on('segmentTimingInfo', self.trigger.bind(self, 'audioSegmentTimingInfo')); // Set up the final part of the audio pipeline\n\n pipeline.adtsStream.pipe(pipeline.audioSegmentStream).pipe(pipeline.coalesceStream);\n } // emit pmt info\n\n\n self.trigger('trackinfo', {\n hasAudio: !!audioTrack,\n hasVideo: !!videoTrack\n });\n }\n }); // Re-emit any data coming from the coalesce stream to the outside world\n\n pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data'));\n pipeline.coalesceStream.on('id3Frame', function (id3Frame) {\n id3Frame.dispatchType = pipeline.metadataStream.dispatchType;\n self.trigger('id3Frame', id3Frame);\n });\n pipeline.coalesceStream.on('caption', this.trigger.bind(this, 'caption')); // Let the consumer know we have finished flushing the entire pipeline\n\n pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));\n addPipelineLogRetriggers(this, pipeline);\n }; // hook up the segment streams once track metadata is delivered\n\n\n this.setBaseMediaDecodeTime = function (baseMediaDecodeTime) {\n var pipeline = this.transmuxPipeline_;\n\n if (!options.keepOriginalTimestamps) {\n this.baseMediaDecodeTime = baseMediaDecodeTime;\n }\n\n if (audioTrack) {\n audioTrack.timelineStartInfo.dts = undefined;\n audioTrack.timelineStartInfo.pts = undefined;\n trackDecodeInfo.clearDtsInfo(audioTrack);\n\n if (pipeline.audioTimestampRolloverStream) {\n pipeline.audioTimestampRolloverStream.discontinuity();\n }\n }\n\n if (videoTrack) {\n if (pipeline.videoSegmentStream) {\n pipeline.videoSegmentStream.gopCache_ = [];\n }\n\n videoTrack.timelineStartInfo.dts = undefined;\n videoTrack.timelineStartInfo.pts = undefined;\n trackDecodeInfo.clearDtsInfo(videoTrack);\n pipeline.captionStream.reset();\n }\n\n if (pipeline.timestampRolloverStream) {\n pipeline.timestampRolloverStream.discontinuity();\n }\n };\n\n this.setAudioAppendStart = function (timestamp) {\n if (audioTrack) {\n this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(timestamp);\n }\n };\n\n this.setRemux = function (val) {\n var pipeline = this.transmuxPipeline_;\n options.remux = val;\n\n if (pipeline && pipeline.coalesceStream) {\n pipeline.coalesceStream.setRemux(val);\n }\n };\n\n this.alignGopsWith = function (gopsToAlignWith) {\n if (videoTrack && this.transmuxPipeline_.videoSegmentStream) {\n this.transmuxPipeline_.videoSegmentStream.alignGopsWith(gopsToAlignWith);\n }\n };\n\n this.getLogTrigger_ = function (key) {\n var self = this;\n return function (event) {\n event.stream = key;\n self.trigger('log', event);\n };\n }; // feed incoming data to the front of the parsing pipeline\n\n\n this.push = function (data) {\n if (hasFlushed) {\n var isAac = isLikelyAacData(data);\n\n if (isAac && this.transmuxPipeline_.type !== 'aac') {\n this.setupAacPipeline();\n } else if (!isAac && this.transmuxPipeline_.type !== 'ts') {\n this.setupTsPipeline();\n }\n\n hasFlushed = false;\n }\n\n this.transmuxPipeline_.headOfPipeline.push(data);\n }; // flush any buffered data\n\n\n this.flush = function () {\n hasFlushed = true; // Start at the top of the pipeline and flush all pending work\n\n this.transmuxPipeline_.headOfPipeline.flush();\n };\n\n this.endTimeline = function () {\n this.transmuxPipeline_.headOfPipeline.endTimeline();\n };\n\n this.reset = function () {\n if (this.transmuxPipeline_.headOfPipeline) {\n this.transmuxPipeline_.headOfPipeline.reset();\n }\n }; // Caption data has to be reset when seeking outside buffered range\n\n\n this.resetCaptions = function () {\n if (this.transmuxPipeline_.captionStream) {\n this.transmuxPipeline_.captionStream.reset();\n }\n };\n };\n\n _Transmuxer.prototype = new stream();\n var transmuxer = {\n Transmuxer: _Transmuxer,\n VideoSegmentStream: _VideoSegmentStream,\n AudioSegmentStream: _AudioSegmentStream,\n AUDIO_PROPERTIES: audioProperties,\n VIDEO_PROPERTIES: videoProperties,\n // exported for testing\n generateSegmentTimingInfo: generateSegmentTimingInfo\n };\n /**\n * mux.js\n *\n * Copyright (c) Brightcove\n * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE\n */\n\n var toUnsigned$3 = function toUnsigned(value) {\n return value >>> 0;\n };\n\n var toHexString$1 = function toHexString(value) {\n return ('00' + value.toString(16)).slice(-2);\n };\n\n var bin = {\n toUnsigned: toUnsigned$3,\n toHexString: toHexString$1\n };\n\n var parseType$1 = function parseType(buffer) {\n var result = '';\n result += String.fromCharCode(buffer[0]);\n result += String.fromCharCode(buffer[1]);\n result += String.fromCharCode(buffer[2]);\n result += String.fromCharCode(buffer[3]);\n return result;\n };\n\n var parseType_1 = parseType$1;\n var toUnsigned$2 = bin.toUnsigned;\n\n var findBox = function findBox(data, path) {\n var results = [],\n i,\n size,\n type,\n end,\n subresults;\n\n if (!path.length) {\n // short-circuit the search for empty paths\n return null;\n }\n\n for (i = 0; i < data.byteLength;) {\n size = toUnsigned$2(data[i] << 24 | data[i + 1] << 16 | data[i + 2] << 8 | data[i + 3]);\n type = parseType_1(data.subarray(i + 4, i + 8));\n end = size > 1 ? i + size : data.byteLength;\n\n if (type === path[0]) {\n if (path.length === 1) {\n // this is the end of the path and we've found the box we were\n // looking for\n results.push(data.subarray(i + 8, end));\n } else {\n // recursively search for the next box along the path\n subresults = findBox(data.subarray(i + 8, end), path.slice(1));\n\n if (subresults.length) {\n results = results.concat(subresults);\n }\n }\n }\n\n i = end;\n } // we've finished searching all of data\n\n\n return results;\n };\n\n var findBox_1 = findBox;\n var toUnsigned$1 = bin.toUnsigned;\n var getUint64$1 = numbers.getUint64;\n\n var tfdt = function tfdt(data) {\n var result = {\n version: data[0],\n flags: new Uint8Array(data.subarray(1, 4))\n };\n\n if (result.version === 1) {\n result.baseMediaDecodeTime = getUint64$1(data.subarray(4));\n } else {\n result.baseMediaDecodeTime = toUnsigned$1(data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);\n }\n\n return result;\n };\n\n var parseTfdt = tfdt;\n\n var parseSampleFlags = function parseSampleFlags(flags) {\n return {\n isLeading: (flags[0] & 0x0c) >>> 2,\n dependsOn: flags[0] & 0x03,\n isDependedOn: (flags[1] & 0xc0) >>> 6,\n hasRedundancy: (flags[1] & 0x30) >>> 4,\n paddingValue: (flags[1] & 0x0e) >>> 1,\n isNonSyncSample: flags[1] & 0x01,\n degradationPriority: flags[2] << 8 | flags[3]\n };\n };\n\n var parseSampleFlags_1 = parseSampleFlags;\n\n var trun = function trun(data) {\n var result = {\n version: data[0],\n flags: new Uint8Array(data.subarray(1, 4)),\n samples: []\n },\n view = new DataView(data.buffer, data.byteOffset, data.byteLength),\n // Flag interpretation\n dataOffsetPresent = result.flags[2] & 0x01,\n // compare with 2nd byte of 0x1\n firstSampleFlagsPresent = result.flags[2] & 0x04,\n // compare with 2nd byte of 0x4\n sampleDurationPresent = result.flags[1] & 0x01,\n // compare with 2nd byte of 0x100\n sampleSizePresent = result.flags[1] & 0x02,\n // compare with 2nd byte of 0x200\n sampleFlagsPresent = result.flags[1] & 0x04,\n // compare with 2nd byte of 0x400\n sampleCompositionTimeOffsetPresent = result.flags[1] & 0x08,\n // compare with 2nd byte of 0x800\n sampleCount = view.getUint32(4),\n offset = 8,\n sample;\n\n if (dataOffsetPresent) {\n // 32 bit signed integer\n result.dataOffset = view.getInt32(offset);\n offset += 4;\n } // Overrides the flags for the first sample only. The order of\n // optional values will be: duration, size, compositionTimeOffset\n\n\n if (firstSampleFlagsPresent && sampleCount) {\n sample = {\n flags: parseSampleFlags_1(data.subarray(offset, offset + 4))\n };\n offset += 4;\n\n if (sampleDurationPresent) {\n sample.duration = view.getUint32(offset);\n offset += 4;\n }\n\n if (sampleSizePresent) {\n sample.size = view.getUint32(offset);\n offset += 4;\n }\n\n if (sampleCompositionTimeOffsetPresent) {\n if (result.version === 1) {\n sample.compositionTimeOffset = view.getInt32(offset);\n } else {\n sample.compositionTimeOffset = view.getUint32(offset);\n }\n\n offset += 4;\n }\n\n result.samples.push(sample);\n sampleCount--;\n }\n\n while (sampleCount--) {\n sample = {};\n\n if (sampleDurationPresent) {\n sample.duration = view.getUint32(offset);\n offset += 4;\n }\n\n if (sampleSizePresent) {\n sample.size = view.getUint32(offset);\n offset += 4;\n }\n\n if (sampleFlagsPresent) {\n sample.flags = parseSampleFlags_1(data.subarray(offset, offset + 4));\n offset += 4;\n }\n\n if (sampleCompositionTimeOffsetPresent) {\n if (result.version === 1) {\n sample.compositionTimeOffset = view.getInt32(offset);\n } else {\n sample.compositionTimeOffset = view.getUint32(offset);\n }\n\n offset += 4;\n }\n\n result.samples.push(sample);\n }\n\n return result;\n };\n\n var parseTrun = trun;\n\n var tfhd = function tfhd(data) {\n var view = new DataView(data.buffer, data.byteOffset, data.byteLength),\n result = {\n version: data[0],\n flags: new Uint8Array(data.subarray(1, 4)),\n trackId: view.getUint32(4)\n },\n baseDataOffsetPresent = result.flags[2] & 0x01,\n sampleDescriptionIndexPresent = result.flags[2] & 0x02,\n defaultSampleDurationPresent = result.flags[2] & 0x08,\n defaultSampleSizePresent = result.flags[2] & 0x10,\n defaultSampleFlagsPresent = result.flags[2] & 0x20,\n durationIsEmpty = result.flags[0] & 0x010000,\n defaultBaseIsMoof = result.flags[0] & 0x020000,\n i;\n i = 8;\n\n if (baseDataOffsetPresent) {\n i += 4; // truncate top 4 bytes\n // FIXME: should we read the full 64 bits?\n\n result.baseDataOffset = view.getUint32(12);\n i += 4;\n }\n\n if (sampleDescriptionIndexPresent) {\n result.sampleDescriptionIndex = view.getUint32(i);\n i += 4;\n }\n\n if (defaultSampleDurationPresent) {\n result.defaultSampleDuration = view.getUint32(i);\n i += 4;\n }\n\n if (defaultSampleSizePresent) {\n result.defaultSampleSize = view.getUint32(i);\n i += 4;\n }\n\n if (defaultSampleFlagsPresent) {\n result.defaultSampleFlags = view.getUint32(i);\n }\n\n if (durationIsEmpty) {\n result.durationIsEmpty = true;\n }\n\n if (!baseDataOffsetPresent && defaultBaseIsMoof) {\n result.baseDataOffsetIsMoof = true;\n }\n\n return result;\n };\n\n var parseTfhd = tfhd;\n var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n var win;\n\n if (typeof window !== \"undefined\") {\n win = window;\n } else if (typeof commonjsGlobal !== \"undefined\") {\n win = commonjsGlobal;\n } else if (typeof self !== \"undefined\") {\n win = self;\n } else {\n win = {};\n }\n\n var window_1 = win;\n var discardEmulationPreventionBytes = captionPacketParser.discardEmulationPreventionBytes;\n var CaptionStream = captionStream.CaptionStream;\n /**\n * Maps an offset in the mdat to a sample based on the the size of the samples.\n * Assumes that `parseSamples` has been called first.\n *\n * @param {Number} offset - The offset into the mdat\n * @param {Object[]} samples - An array of samples, parsed using `parseSamples`\n * @return {?Object} The matching sample, or null if no match was found.\n *\n * @see ISO-BMFF-12/2015, Section 8.8.8\n **/\n\n var mapToSample = function mapToSample(offset, samples) {\n var approximateOffset = offset;\n\n for (var i = 0; i < samples.length; i++) {\n var sample = samples[i];\n\n if (approximateOffset < sample.size) {\n return sample;\n }\n\n approximateOffset -= sample.size;\n }\n\n return null;\n };\n /**\n * Finds SEI nal units contained in a Media Data Box.\n * Assumes that `parseSamples` has been called first.\n *\n * @param {Uint8Array} avcStream - The bytes of the mdat\n * @param {Object[]} samples - The samples parsed out by `parseSamples`\n * @param {Number} trackId - The trackId of this video track\n * @return {Object[]} seiNals - the parsed SEI NALUs found.\n * The contents of the seiNal should match what is expected by\n * CaptionStream.push (nalUnitType, size, data, escapedRBSP, pts, dts)\n *\n * @see ISO-BMFF-12/2015, Section 8.1.1\n * @see Rec. ITU-T H.264, 7.3.2.3.1\n **/\n\n\n var findSeiNals = function findSeiNals(avcStream, samples, trackId) {\n var avcView = new DataView(avcStream.buffer, avcStream.byteOffset, avcStream.byteLength),\n result = {\n logs: [],\n seiNals: []\n },\n seiNal,\n i,\n length,\n lastMatchedSample;\n\n for (i = 0; i + 4 < avcStream.length; i += length) {\n length = avcView.getUint32(i);\n i += 4; // Bail if this doesn't appear to be an H264 stream\n\n if (length <= 0) {\n continue;\n }\n\n switch (avcStream[i] & 0x1F) {\n case 0x06:\n var data = avcStream.subarray(i + 1, i + 1 + length);\n var matchingSample = mapToSample(i, samples);\n seiNal = {\n nalUnitType: 'sei_rbsp',\n size: length,\n data: data,\n escapedRBSP: discardEmulationPreventionBytes(data),\n trackId: trackId\n };\n\n if (matchingSample) {\n seiNal.pts = matchingSample.pts;\n seiNal.dts = matchingSample.dts;\n lastMatchedSample = matchingSample;\n } else if (lastMatchedSample) {\n // If a matching sample cannot be found, use the last\n // sample's values as they should be as close as possible\n seiNal.pts = lastMatchedSample.pts;\n seiNal.dts = lastMatchedSample.dts;\n } else {\n result.logs.push({\n level: 'warn',\n message: 'We\\'ve encountered a nal unit without data at ' + i + ' for trackId ' + trackId + '. See mux.js#223.'\n });\n break;\n }\n\n result.seiNals.push(seiNal);\n break;\n }\n }\n\n return result;\n };\n /**\n * Parses sample information out of Track Run Boxes and calculates\n * the absolute presentation and decode timestamps of each sample.\n *\n * @param {Array} truns - The Trun Run boxes to be parsed\n * @param {Number|BigInt} baseMediaDecodeTime - base media decode time from tfdt\n @see ISO-BMFF-12/2015, Section 8.8.12\n * @param {Object} tfhd - The parsed Track Fragment Header\n * @see inspect.parseTfhd\n * @return {Object[]} the parsed samples\n *\n * @see ISO-BMFF-12/2015, Section 8.8.8\n **/\n\n\n var parseSamples = function parseSamples(truns, baseMediaDecodeTime, tfhd) {\n var currentDts = baseMediaDecodeTime;\n var defaultSampleDuration = tfhd.defaultSampleDuration || 0;\n var defaultSampleSize = tfhd.defaultSampleSize || 0;\n var trackId = tfhd.trackId;\n var allSamples = [];\n truns.forEach(function (trun) {\n // Note: We currently do not parse the sample table as well\n // as the trun. It's possible some sources will require this.\n // moov > trak > mdia > minf > stbl\n var trackRun = parseTrun(trun);\n var samples = trackRun.samples;\n samples.forEach(function (sample) {\n if (sample.duration === undefined) {\n sample.duration = defaultSampleDuration;\n }\n\n if (sample.size === undefined) {\n sample.size = defaultSampleSize;\n }\n\n sample.trackId = trackId;\n sample.dts = currentDts;\n\n if (sample.compositionTimeOffset === undefined) {\n sample.compositionTimeOffset = 0;\n }\n\n if (typeof currentDts === 'bigint') {\n sample.pts = currentDts + window_1.BigInt(sample.compositionTimeOffset);\n currentDts += window_1.BigInt(sample.duration);\n } else {\n sample.pts = currentDts + sample.compositionTimeOffset;\n currentDts += sample.duration;\n }\n });\n allSamples = allSamples.concat(samples);\n });\n return allSamples;\n };\n /**\n * Parses out caption nals from an FMP4 segment's video tracks.\n *\n * @param {Uint8Array} segment - The bytes of a single segment\n * @param {Number} videoTrackId - The trackId of a video track in the segment\n * @return {Object.} A mapping of video trackId to\n * a list of seiNals found in that track\n **/\n\n\n var parseCaptionNals = function parseCaptionNals(segment, videoTrackId) {\n // To get the samples\n var trafs = findBox_1(segment, ['moof', 'traf']); // To get SEI NAL units\n\n var mdats = findBox_1(segment, ['mdat']);\n var captionNals = {};\n var mdatTrafPairs = []; // Pair up each traf with a mdat as moofs and mdats are in pairs\n\n mdats.forEach(function (mdat, index) {\n var matchingTraf = trafs[index];\n mdatTrafPairs.push({\n mdat: mdat,\n traf: matchingTraf\n });\n });\n mdatTrafPairs.forEach(function (pair) {\n var mdat = pair.mdat;\n var traf = pair.traf;\n var tfhd = findBox_1(traf, ['tfhd']); // Exactly 1 tfhd per traf\n\n var headerInfo = parseTfhd(tfhd[0]);\n var trackId = headerInfo.trackId;\n var tfdt = findBox_1(traf, ['tfdt']); // Either 0 or 1 tfdt per traf\n\n var baseMediaDecodeTime = tfdt.length > 0 ? parseTfdt(tfdt[0]).baseMediaDecodeTime : 0;\n var truns = findBox_1(traf, ['trun']);\n var samples;\n var result; // Only parse video data for the chosen video track\n\n if (videoTrackId === trackId && truns.length > 0) {\n samples = parseSamples(truns, baseMediaDecodeTime, headerInfo);\n result = findSeiNals(mdat, samples, trackId);\n\n if (!captionNals[trackId]) {\n captionNals[trackId] = {\n seiNals: [],\n logs: []\n };\n }\n\n captionNals[trackId].seiNals = captionNals[trackId].seiNals.concat(result.seiNals);\n captionNals[trackId].logs = captionNals[trackId].logs.concat(result.logs);\n }\n });\n return captionNals;\n };\n /**\n * Parses out inband captions from an MP4 container and returns\n * caption objects that can be used by WebVTT and the TextTrack API.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/VTTCue\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TextTrack\n * Assumes that `probe.getVideoTrackIds` and `probe.timescale` have been called first\n *\n * @param {Uint8Array} segment - The fmp4 segment containing embedded captions\n * @param {Number} trackId - The id of the video track to parse\n * @param {Number} timescale - The timescale for the video track from the init segment\n *\n * @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks\n * @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds\n * @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds\n * @return {String} parsedCaptions[].text - The visible content of the caption\n **/\n\n\n var parseEmbeddedCaptions = function parseEmbeddedCaptions(segment, trackId, timescale) {\n var captionNals; // the ISO-BMFF spec says that trackId can't be zero, but there's some broken content out there\n\n if (trackId === null) {\n return null;\n }\n\n captionNals = parseCaptionNals(segment, trackId);\n var trackNals = captionNals[trackId] || {};\n return {\n seiNals: trackNals.seiNals,\n logs: trackNals.logs,\n timescale: timescale\n };\n };\n /**\n * Converts SEI NALUs into captions that can be used by video.js\n **/\n\n\n var CaptionParser = function CaptionParser() {\n var isInitialized = false;\n var captionStream; // Stores segments seen before trackId and timescale are set\n\n var segmentCache; // Stores video track ID of the track being parsed\n\n var trackId; // Stores the timescale of the track being parsed\n\n var timescale; // Stores captions parsed so far\n\n var parsedCaptions; // Stores whether we are receiving partial data or not\n\n var parsingPartial;\n /**\n * A method to indicate whether a CaptionParser has been initalized\n * @returns {Boolean}\n **/\n\n this.isInitialized = function () {\n return isInitialized;\n };\n /**\n * Initializes the underlying CaptionStream, SEI NAL parsing\n * and management, and caption collection\n **/\n\n\n this.init = function (options) {\n captionStream = new CaptionStream();\n isInitialized = true;\n parsingPartial = options ? options.isPartial : false; // Collect dispatched captions\n\n captionStream.on('data', function (event) {\n // Convert to seconds in the source's timescale\n event.startTime = event.startPts / timescale;\n event.endTime = event.endPts / timescale;\n parsedCaptions.captions.push(event);\n parsedCaptions.captionStreams[event.stream] = true;\n });\n captionStream.on('log', function (log) {\n parsedCaptions.logs.push(log);\n });\n };\n /**\n * Determines if a new video track will be selected\n * or if the timescale changed\n * @return {Boolean}\n **/\n\n\n this.isNewInit = function (videoTrackIds, timescales) {\n if (videoTrackIds && videoTrackIds.length === 0 || timescales && typeof timescales === 'object' && Object.keys(timescales).length === 0) {\n return false;\n }\n\n return trackId !== videoTrackIds[0] || timescale !== timescales[trackId];\n };\n /**\n * Parses out SEI captions and interacts with underlying\n * CaptionStream to return dispatched captions\n *\n * @param {Uint8Array} segment - The fmp4 segment containing embedded captions\n * @param {Number[]} videoTrackIds - A list of video tracks found in the init segment\n * @param {Object.} timescales - The timescales found in the init segment\n * @see parseEmbeddedCaptions\n * @see m2ts/caption-stream.js\n **/\n\n\n this.parse = function (segment, videoTrackIds, timescales) {\n var parsedData;\n\n if (!this.isInitialized()) {\n return null; // This is not likely to be a video segment\n } else if (!videoTrackIds || !timescales) {\n return null;\n } else if (this.isNewInit(videoTrackIds, timescales)) {\n // Use the first video track only as there is no\n // mechanism to switch to other video tracks\n trackId = videoTrackIds[0];\n timescale = timescales[trackId]; // If an init segment has not been seen yet, hold onto segment\n // data until we have one.\n // the ISO-BMFF spec says that trackId can't be zero, but there's some broken content out there\n } else if (trackId === null || !timescale) {\n segmentCache.push(segment);\n return null;\n } // Now that a timescale and trackId is set, parse cached segments\n\n\n while (segmentCache.length > 0) {\n var cachedSegment = segmentCache.shift();\n this.parse(cachedSegment, videoTrackIds, timescales);\n }\n\n parsedData = parseEmbeddedCaptions(segment, trackId, timescale);\n\n if (parsedData && parsedData.logs) {\n parsedCaptions.logs = parsedCaptions.logs.concat(parsedData.logs);\n }\n\n if (parsedData === null || !parsedData.seiNals) {\n if (parsedCaptions.logs.length) {\n return {\n logs: parsedCaptions.logs,\n captions: [],\n captionStreams: []\n };\n }\n\n return null;\n }\n\n this.pushNals(parsedData.seiNals); // Force the parsed captions to be dispatched\n\n this.flushStream();\n return parsedCaptions;\n };\n /**\n * Pushes SEI NALUs onto CaptionStream\n * @param {Object[]} nals - A list of SEI nals parsed using `parseCaptionNals`\n * Assumes that `parseCaptionNals` has been called first\n * @see m2ts/caption-stream.js\n **/\n\n\n this.pushNals = function (nals) {\n if (!this.isInitialized() || !nals || nals.length === 0) {\n return null;\n }\n\n nals.forEach(function (nal) {\n captionStream.push(nal);\n });\n };\n /**\n * Flushes underlying CaptionStream to dispatch processed, displayable captions\n * @see m2ts/caption-stream.js\n **/\n\n\n this.flushStream = function () {\n if (!this.isInitialized()) {\n return null;\n }\n\n if (!parsingPartial) {\n captionStream.flush();\n } else {\n captionStream.partialFlush();\n }\n };\n /**\n * Reset caption buckets for new data\n **/\n\n\n this.clearParsedCaptions = function () {\n parsedCaptions.captions = [];\n parsedCaptions.captionStreams = {};\n parsedCaptions.logs = [];\n };\n /**\n * Resets underlying CaptionStream\n * @see m2ts/caption-stream.js\n **/\n\n\n this.resetCaptionStream = function () {\n if (!this.isInitialized()) {\n return null;\n }\n\n captionStream.reset();\n };\n /**\n * Convenience method to clear all captions flushed from the\n * CaptionStream and still being parsed\n * @see m2ts/caption-stream.js\n **/\n\n\n this.clearAllCaptions = function () {\n this.clearParsedCaptions();\n this.resetCaptionStream();\n };\n /**\n * Reset caption parser\n **/\n\n\n this.reset = function () {\n segmentCache = [];\n trackId = null;\n timescale = null;\n\n if (!parsedCaptions) {\n parsedCaptions = {\n captions: [],\n // CC1, CC2, CC3, CC4\n captionStreams: {},\n logs: []\n };\n } else {\n this.clearParsedCaptions();\n }\n\n this.resetCaptionStream();\n };\n\n this.reset();\n };\n\n var captionParser = CaptionParser;\n var toUnsigned = bin.toUnsigned;\n var toHexString = bin.toHexString;\n var getUint64 = numbers.getUint64;\n var timescale, startTime, compositionStartTime, getVideoTrackIds, getTracks, getTimescaleFromMediaHeader;\n /**\n * Parses an MP4 initialization segment and extracts the timescale\n * values for any declared tracks. Timescale values indicate the\n * number of clock ticks per second to assume for time-based values\n * elsewhere in the MP4.\n *\n * To determine the start time of an MP4, you need two pieces of\n * information: the timescale unit and the earliest base media decode\n * time. Multiple timescales can be specified within an MP4 but the\n * base media decode time is always expressed in the timescale from\n * the media header box for the track:\n * ```\n * moov > trak > mdia > mdhd.timescale\n * ```\n * @param init {Uint8Array} the bytes of the init segment\n * @return {object} a hash of track ids to timescale values or null if\n * the init segment is malformed.\n */\n\n timescale = function timescale(init) {\n var result = {},\n traks = findBox_1(init, ['moov', 'trak']); // mdhd timescale\n\n return traks.reduce(function (result, trak) {\n var tkhd, version, index, id, mdhd;\n tkhd = findBox_1(trak, ['tkhd'])[0];\n\n if (!tkhd) {\n return null;\n }\n\n version = tkhd[0];\n index = version === 0 ? 12 : 20;\n id = toUnsigned(tkhd[index] << 24 | tkhd[index + 1] << 16 | tkhd[index + 2] << 8 | tkhd[index + 3]);\n mdhd = findBox_1(trak, ['mdia', 'mdhd'])[0];\n\n if (!mdhd) {\n return null;\n }\n\n version = mdhd[0];\n index = version === 0 ? 12 : 20;\n result[id] = toUnsigned(mdhd[index] << 24 | mdhd[index + 1] << 16 | mdhd[index + 2] << 8 | mdhd[index + 3]);\n return result;\n }, result);\n };\n /**\n * Determine the base media decode start time, in seconds, for an MP4\n * fragment. If multiple fragments are specified, the earliest time is\n * returned.\n *\n * The base media decode time can be parsed from track fragment\n * metadata:\n * ```\n * moof > traf > tfdt.baseMediaDecodeTime\n * ```\n * It requires the timescale value from the mdhd to interpret.\n *\n * @param timescale {object} a hash of track ids to timescale values.\n * @return {number} the earliest base media decode start time for the\n * fragment, in seconds\n */\n\n\n startTime = function startTime(timescale, fragment) {\n var trafs; // we need info from two childrend of each track fragment box\n\n trafs = findBox_1(fragment, ['moof', 'traf']); // determine the start times for each track\n\n var lowestTime = trafs.reduce(function (acc, traf) {\n var tfhd = findBox_1(traf, ['tfhd'])[0]; // get the track id from the tfhd\n\n var id = toUnsigned(tfhd[4] << 24 | tfhd[5] << 16 | tfhd[6] << 8 | tfhd[7]); // assume a 90kHz clock if no timescale was specified\n\n var scale = timescale[id] || 90e3; // get the base media decode time from the tfdt\n\n var tfdt = findBox_1(traf, ['tfdt'])[0];\n var dv = new DataView(tfdt.buffer, tfdt.byteOffset, tfdt.byteLength);\n var baseTime; // version 1 is 64 bit\n\n if (tfdt[0] === 1) {\n baseTime = getUint64(tfdt.subarray(4, 12));\n } else {\n baseTime = dv.getUint32(4);\n } // convert base time to seconds if it is a valid number.\n\n\n var seconds;\n\n if (typeof baseTime === 'bigint') {\n seconds = baseTime / window_1.BigInt(scale);\n } else if (typeof baseTime === 'number' && !isNaN(baseTime)) {\n seconds = baseTime / scale;\n }\n\n if (seconds < Number.MAX_SAFE_INTEGER) {\n seconds = Number(seconds);\n }\n\n if (seconds < acc) {\n acc = seconds;\n }\n\n return acc;\n }, Infinity);\n return typeof lowestTime === 'bigint' || isFinite(lowestTime) ? lowestTime : 0;\n };\n /**\n * Determine the composition start, in seconds, for an MP4\n * fragment.\n *\n * The composition start time of a fragment can be calculated using the base\n * media decode time, composition time offset, and timescale, as follows:\n *\n * compositionStartTime = (baseMediaDecodeTime + compositionTimeOffset) / timescale\n *\n * All of the aforementioned information is contained within a media fragment's\n * `traf` box, except for timescale info, which comes from the initialization\n * segment, so a track id (also contained within a `traf`) is also necessary to\n * associate it with a timescale\n *\n *\n * @param timescales {object} - a hash of track ids to timescale values.\n * @param fragment {Unit8Array} - the bytes of a media segment\n * @return {number} the composition start time for the fragment, in seconds\n **/\n\n\n compositionStartTime = function compositionStartTime(timescales, fragment) {\n var trafBoxes = findBox_1(fragment, ['moof', 'traf']);\n var baseMediaDecodeTime = 0;\n var compositionTimeOffset = 0;\n var trackId;\n\n if (trafBoxes && trafBoxes.length) {\n // The spec states that track run samples contained within a `traf` box are contiguous, but\n // it does not explicitly state whether the `traf` boxes themselves are contiguous.\n // We will assume that they are, so we only need the first to calculate start time.\n var tfhd = findBox_1(trafBoxes[0], ['tfhd'])[0];\n var trun = findBox_1(trafBoxes[0], ['trun'])[0];\n var tfdt = findBox_1(trafBoxes[0], ['tfdt'])[0];\n\n if (tfhd) {\n var parsedTfhd = parseTfhd(tfhd);\n trackId = parsedTfhd.trackId;\n }\n\n if (tfdt) {\n var parsedTfdt = parseTfdt(tfdt);\n baseMediaDecodeTime = parsedTfdt.baseMediaDecodeTime;\n }\n\n if (trun) {\n var parsedTrun = parseTrun(trun);\n\n if (parsedTrun.samples && parsedTrun.samples.length) {\n compositionTimeOffset = parsedTrun.samples[0].compositionTimeOffset || 0;\n }\n }\n } // Get timescale for this specific track. Assume a 90kHz clock if no timescale was\n // specified.\n\n\n var timescale = timescales[trackId] || 90e3; // return the composition start time, in seconds\n\n if (typeof baseMediaDecodeTime === 'bigint') {\n compositionTimeOffset = window_1.BigInt(compositionTimeOffset);\n timescale = window_1.BigInt(timescale);\n }\n\n var result = (baseMediaDecodeTime + compositionTimeOffset) / timescale;\n\n if (typeof result === 'bigint' && result < Number.MAX_SAFE_INTEGER) {\n result = Number(result);\n }\n\n return result;\n };\n /**\n * Find the trackIds of the video tracks in this source.\n * Found by parsing the Handler Reference and Track Header Boxes:\n * moov > trak > mdia > hdlr\n * moov > trak > tkhd\n *\n * @param {Uint8Array} init - The bytes of the init segment for this source\n * @return {Number[]} A list of trackIds\n *\n * @see ISO-BMFF-12/2015, Section 8.4.3\n **/\n\n\n getVideoTrackIds = function getVideoTrackIds(init) {\n var traks = findBox_1(init, ['moov', 'trak']);\n var videoTrackIds = [];\n traks.forEach(function (trak) {\n var hdlrs = findBox_1(trak, ['mdia', 'hdlr']);\n var tkhds = findBox_1(trak, ['tkhd']);\n hdlrs.forEach(function (hdlr, index) {\n var handlerType = parseType_1(hdlr.subarray(8, 12));\n var tkhd = tkhds[index];\n var view;\n var version;\n var trackId;\n\n if (handlerType === 'vide') {\n view = new DataView(tkhd.buffer, tkhd.byteOffset, tkhd.byteLength);\n version = view.getUint8(0);\n trackId = version === 0 ? view.getUint32(12) : view.getUint32(20);\n videoTrackIds.push(trackId);\n }\n });\n });\n return videoTrackIds;\n };\n\n getTimescaleFromMediaHeader = function getTimescaleFromMediaHeader(mdhd) {\n // mdhd is a FullBox, meaning it will have its own version as the first byte\n var version = mdhd[0];\n var index = version === 0 ? 12 : 20;\n return toUnsigned(mdhd[index] << 24 | mdhd[index + 1] << 16 | mdhd[index + 2] << 8 | mdhd[index + 3]);\n };\n /**\n * Get all the video, audio, and hint tracks from a non fragmented\n * mp4 segment\n */\n\n\n getTracks = function getTracks(init) {\n var traks = findBox_1(init, ['moov', 'trak']);\n var tracks = [];\n traks.forEach(function (trak) {\n var track = {};\n var tkhd = findBox_1(trak, ['tkhd'])[0];\n var view, tkhdVersion; // id\n\n if (tkhd) {\n view = new DataView(tkhd.buffer, tkhd.byteOffset, tkhd.byteLength);\n tkhdVersion = view.getUint8(0);\n track.id = tkhdVersion === 0 ? view.getUint32(12) : view.getUint32(20);\n }\n\n var hdlr = findBox_1(trak, ['mdia', 'hdlr'])[0]; // type\n\n if (hdlr) {\n var type = parseType_1(hdlr.subarray(8, 12));\n\n if (type === 'vide') {\n track.type = 'video';\n } else if (type === 'soun') {\n track.type = 'audio';\n } else {\n track.type = type;\n }\n } // codec\n\n\n var stsd = findBox_1(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0];\n\n if (stsd) {\n var sampleDescriptions = stsd.subarray(8); // gives the codec type string\n\n track.codec = parseType_1(sampleDescriptions.subarray(4, 8));\n var codecBox = findBox_1(sampleDescriptions, [track.codec])[0];\n var codecConfig, codecConfigType;\n\n if (codecBox) {\n // https://tools.ietf.org/html/rfc6381#section-3.3\n if (/^[asm]vc[1-9]$/i.test(track.codec)) {\n // we don't need anything but the \"config\" parameter of the\n // avc1 codecBox\n codecConfig = codecBox.subarray(78);\n codecConfigType = parseType_1(codecConfig.subarray(4, 8));\n\n if (codecConfigType === 'avcC' && codecConfig.length > 11) {\n track.codec += '.'; // left padded with zeroes for single digit hex\n // profile idc\n\n track.codec += toHexString(codecConfig[9]); // the byte containing the constraint_set flags\n\n track.codec += toHexString(codecConfig[10]); // level idc\n\n track.codec += toHexString(codecConfig[11]);\n } else {\n // TODO: show a warning that we couldn't parse the codec\n // and are using the default\n track.codec = 'avc1.4d400d';\n }\n } else if (/^mp4[a,v]$/i.test(track.codec)) {\n // we do not need anything but the streamDescriptor of the mp4a codecBox\n codecConfig = codecBox.subarray(28);\n codecConfigType = parseType_1(codecConfig.subarray(4, 8));\n\n if (codecConfigType === 'esds' && codecConfig.length > 20 && codecConfig[19] !== 0) {\n track.codec += '.' + toHexString(codecConfig[19]); // this value is only a single digit\n\n track.codec += '.' + toHexString(codecConfig[20] >>> 2 & 0x3f).replace(/^0/, '');\n } else {\n // TODO: show a warning that we couldn't parse the codec\n // and are using the default\n track.codec = 'mp4a.40.2';\n }\n } else {\n // flac, opus, etc\n track.codec = track.codec.toLowerCase();\n }\n }\n }\n\n var mdhd = findBox_1(trak, ['mdia', 'mdhd'])[0];\n\n if (mdhd) {\n track.timescale = getTimescaleFromMediaHeader(mdhd);\n }\n\n tracks.push(track);\n });\n return tracks;\n };\n\n var probe$2 = {\n // export mp4 inspector's findBox and parseType for backwards compatibility\n findBox: findBox_1,\n parseType: parseType_1,\n timescale: timescale,\n startTime: startTime,\n compositionStartTime: compositionStartTime,\n videoTrackIds: getVideoTrackIds,\n tracks: getTracks,\n getTimescaleFromMediaHeader: getTimescaleFromMediaHeader\n };\n\n var parsePid = function parsePid(packet) {\n var pid = packet[1] & 0x1f;\n pid <<= 8;\n pid |= packet[2];\n return pid;\n };\n\n var parsePayloadUnitStartIndicator = function parsePayloadUnitStartIndicator(packet) {\n return !!(packet[1] & 0x40);\n };\n\n var parseAdaptionField = function parseAdaptionField(packet) {\n var offset = 0; // if an adaption field is present, its length is specified by the\n // fifth byte of the TS packet header. The adaptation field is\n // used to add stuffing to PES packets that don't fill a complete\n // TS packet, and to specify some forms of timing and control data\n // that we do not currently use.\n\n if ((packet[3] & 0x30) >>> 4 > 0x01) {\n offset += packet[4] + 1;\n }\n\n return offset;\n };\n\n var parseType = function parseType(packet, pmtPid) {\n var pid = parsePid(packet);\n\n if (pid === 0) {\n return 'pat';\n } else if (pid === pmtPid) {\n return 'pmt';\n } else if (pmtPid) {\n return 'pes';\n }\n\n return null;\n };\n\n var parsePat = function parsePat(packet) {\n var pusi = parsePayloadUnitStartIndicator(packet);\n var offset = 4 + parseAdaptionField(packet);\n\n if (pusi) {\n offset += packet[offset] + 1;\n }\n\n return (packet[offset + 10] & 0x1f) << 8 | packet[offset + 11];\n };\n\n var parsePmt = function parsePmt(packet) {\n var programMapTable = {};\n var pusi = parsePayloadUnitStartIndicator(packet);\n var payloadOffset = 4 + parseAdaptionField(packet);\n\n if (pusi) {\n payloadOffset += packet[payloadOffset] + 1;\n } // PMTs can be sent ahead of the time when they should actually\n // take effect. We don't believe this should ever be the case\n // for HLS but we'll ignore \"forward\" PMT declarations if we see\n // them. Future PMT declarations have the current_next_indicator\n // set to zero.\n\n\n if (!(packet[payloadOffset + 5] & 0x01)) {\n return;\n }\n\n var sectionLength, tableEnd, programInfoLength; // the mapping table ends at the end of the current section\n\n sectionLength = (packet[payloadOffset + 1] & 0x0f) << 8 | packet[payloadOffset + 2];\n tableEnd = 3 + sectionLength - 4; // to determine where the table is, we have to figure out how\n // long the program info descriptors are\n\n programInfoLength = (packet[payloadOffset + 10] & 0x0f) << 8 | packet[payloadOffset + 11]; // advance the offset to the first entry in the mapping table\n\n var offset = 12 + programInfoLength;\n\n while (offset < tableEnd) {\n var i = payloadOffset + offset; // add an entry that maps the elementary_pid to the stream_type\n\n programMapTable[(packet[i + 1] & 0x1F) << 8 | packet[i + 2]] = packet[i]; // move to the next table entry\n // skip past the elementary stream descriptors, if present\n\n offset += ((packet[i + 3] & 0x0F) << 8 | packet[i + 4]) + 5;\n }\n\n return programMapTable;\n };\n\n var parsePesType = function parsePesType(packet, programMapTable) {\n var pid = parsePid(packet);\n var type = programMapTable[pid];\n\n switch (type) {\n case streamTypes.H264_STREAM_TYPE:\n return 'video';\n\n case streamTypes.ADTS_STREAM_TYPE:\n return 'audio';\n\n case streamTypes.METADATA_STREAM_TYPE:\n return 'timed-metadata';\n\n default:\n return null;\n }\n };\n\n var parsePesTime = function parsePesTime(packet) {\n var pusi = parsePayloadUnitStartIndicator(packet);\n\n if (!pusi) {\n return null;\n }\n\n var offset = 4 + parseAdaptionField(packet);\n\n if (offset >= packet.byteLength) {\n // From the H 222.0 MPEG-TS spec\n // \"For transport stream packets carrying PES packets, stuffing is needed when there\n // is insufficient PES packet data to completely fill the transport stream packet\n // payload bytes. Stuffing is accomplished by defining an adaptation field longer than\n // the sum of the lengths of the data elements in it, so that the payload bytes\n // remaining after the adaptation field exactly accommodates the available PES packet\n // data.\"\n //\n // If the offset is >= the length of the packet, then the packet contains no data\n // and instead is just adaption field stuffing bytes\n return null;\n }\n\n var pes = null;\n var ptsDtsFlags; // PES packets may be annotated with a PTS value, or a PTS value\n // and a DTS value. Determine what combination of values is\n // available to work with.\n\n ptsDtsFlags = packet[offset + 7]; // PTS and DTS are normally stored as a 33-bit number. Javascript\n // performs all bitwise operations on 32-bit integers but javascript\n // supports a much greater range (52-bits) of integer using standard\n // mathematical operations.\n // We construct a 31-bit value using bitwise operators over the 31\n // most significant bits and then multiply by 4 (equal to a left-shift\n // of 2) before we add the final 2 least significant bits of the\n // timestamp (equal to an OR.)\n\n if (ptsDtsFlags & 0xC0) {\n pes = {}; // the PTS and DTS are not written out directly. For information\n // on how they are encoded, see\n // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html\n\n pes.pts = (packet[offset + 9] & 0x0E) << 27 | (packet[offset + 10] & 0xFF) << 20 | (packet[offset + 11] & 0xFE) << 12 | (packet[offset + 12] & 0xFF) << 5 | (packet[offset + 13] & 0xFE) >>> 3;\n pes.pts *= 4; // Left shift by 2\n\n pes.pts += (packet[offset + 13] & 0x06) >>> 1; // OR by the two LSBs\n\n pes.dts = pes.pts;\n\n if (ptsDtsFlags & 0x40) {\n pes.dts = (packet[offset + 14] & 0x0E) << 27 | (packet[offset + 15] & 0xFF) << 20 | (packet[offset + 16] & 0xFE) << 12 | (packet[offset + 17] & 0xFF) << 5 | (packet[offset + 18] & 0xFE) >>> 3;\n pes.dts *= 4; // Left shift by 2\n\n pes.dts += (packet[offset + 18] & 0x06) >>> 1; // OR by the two LSBs\n }\n }\n\n return pes;\n };\n\n var parseNalUnitType = function parseNalUnitType(type) {\n switch (type) {\n case 0x05:\n return 'slice_layer_without_partitioning_rbsp_idr';\n\n case 0x06:\n return 'sei_rbsp';\n\n case 0x07:\n return 'seq_parameter_set_rbsp';\n\n case 0x08:\n return 'pic_parameter_set_rbsp';\n\n case 0x09:\n return 'access_unit_delimiter_rbsp';\n\n default:\n return null;\n }\n };\n\n var videoPacketContainsKeyFrame = function videoPacketContainsKeyFrame(packet) {\n var offset = 4 + parseAdaptionField(packet);\n var frameBuffer = packet.subarray(offset);\n var frameI = 0;\n var frameSyncPoint = 0;\n var foundKeyFrame = false;\n var nalType; // advance the sync point to a NAL start, if necessary\n\n for (; frameSyncPoint < frameBuffer.byteLength - 3; frameSyncPoint++) {\n if (frameBuffer[frameSyncPoint + 2] === 1) {\n // the sync point is properly aligned\n frameI = frameSyncPoint + 5;\n break;\n }\n }\n\n while (frameI < frameBuffer.byteLength) {\n // look at the current byte to determine if we've hit the end of\n // a NAL unit boundary\n switch (frameBuffer[frameI]) {\n case 0:\n // skip past non-sync sequences\n if (frameBuffer[frameI - 1] !== 0) {\n frameI += 2;\n break;\n } else if (frameBuffer[frameI - 2] !== 0) {\n frameI++;\n break;\n }\n\n if (frameSyncPoint + 3 !== frameI - 2) {\n nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f);\n\n if (nalType === 'slice_layer_without_partitioning_rbsp_idr') {\n foundKeyFrame = true;\n }\n } // drop trailing zeroes\n\n\n do {\n frameI++;\n } while (frameBuffer[frameI] !== 1 && frameI < frameBuffer.length);\n\n frameSyncPoint = frameI - 2;\n frameI += 3;\n break;\n\n case 1:\n // skip past non-sync sequences\n if (frameBuffer[frameI - 1] !== 0 || frameBuffer[frameI - 2] !== 0) {\n frameI += 3;\n break;\n }\n\n nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f);\n\n if (nalType === 'slice_layer_without_partitioning_rbsp_idr') {\n foundKeyFrame = true;\n }\n\n frameSyncPoint = frameI - 2;\n frameI += 3;\n break;\n\n default:\n // the current byte isn't a one or zero, so it cannot be part\n // of a sync sequence\n frameI += 3;\n break;\n }\n }\n\n frameBuffer = frameBuffer.subarray(frameSyncPoint);\n frameI -= frameSyncPoint;\n frameSyncPoint = 0; // parse the final nal\n\n if (frameBuffer && frameBuffer.byteLength > 3) {\n nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f);\n\n if (nalType === 'slice_layer_without_partitioning_rbsp_idr') {\n foundKeyFrame = true;\n }\n }\n\n return foundKeyFrame;\n };\n\n var probe$1 = {\n parseType: parseType,\n parsePat: parsePat,\n parsePmt: parsePmt,\n parsePayloadUnitStartIndicator: parsePayloadUnitStartIndicator,\n parsePesType: parsePesType,\n parsePesTime: parsePesTime,\n videoPacketContainsKeyFrame: videoPacketContainsKeyFrame\n };\n var handleRollover = timestampRolloverStream.handleRollover;\n var probe = {};\n probe.ts = probe$1;\n probe.aac = utils;\n var ONE_SECOND_IN_TS = clock.ONE_SECOND_IN_TS;\n var MP2T_PACKET_LENGTH = 188,\n // bytes\n SYNC_BYTE = 0x47;\n /**\n * walks through segment data looking for pat and pmt packets to parse out\n * program map table information\n */\n\n var parsePsi_ = function parsePsi_(bytes, pmt) {\n var startIndex = 0,\n endIndex = MP2T_PACKET_LENGTH,\n packet,\n type;\n\n while (endIndex < bytes.byteLength) {\n // Look for a pair of start and end sync bytes in the data..\n if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) {\n // We found a packet\n packet = bytes.subarray(startIndex, endIndex);\n type = probe.ts.parseType(packet, pmt.pid);\n\n switch (type) {\n case 'pat':\n pmt.pid = probe.ts.parsePat(packet);\n break;\n\n case 'pmt':\n var table = probe.ts.parsePmt(packet);\n pmt.table = pmt.table || {};\n Object.keys(table).forEach(function (key) {\n pmt.table[key] = table[key];\n });\n break;\n }\n\n startIndex += MP2T_PACKET_LENGTH;\n endIndex += MP2T_PACKET_LENGTH;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex++;\n endIndex++;\n }\n };\n /**\n * walks through the segment data from the start and end to get timing information\n * for the first and last audio pes packets\n */\n\n\n var parseAudioPes_ = function parseAudioPes_(bytes, pmt, result) {\n var startIndex = 0,\n endIndex = MP2T_PACKET_LENGTH,\n packet,\n type,\n pesType,\n pusi,\n parsed;\n var endLoop = false; // Start walking from start of segment to get first audio packet\n\n while (endIndex <= bytes.byteLength) {\n // Look for a pair of start and end sync bytes in the data..\n if (bytes[startIndex] === SYNC_BYTE && (bytes[endIndex] === SYNC_BYTE || endIndex === bytes.byteLength)) {\n // We found a packet\n packet = bytes.subarray(startIndex, endIndex);\n type = probe.ts.parseType(packet, pmt.pid);\n\n switch (type) {\n case 'pes':\n pesType = probe.ts.parsePesType(packet, pmt.table);\n pusi = probe.ts.parsePayloadUnitStartIndicator(packet);\n\n if (pesType === 'audio' && pusi) {\n parsed = probe.ts.parsePesTime(packet);\n\n if (parsed) {\n parsed.type = 'audio';\n result.audio.push(parsed);\n endLoop = true;\n }\n }\n\n break;\n }\n\n if (endLoop) {\n break;\n }\n\n startIndex += MP2T_PACKET_LENGTH;\n endIndex += MP2T_PACKET_LENGTH;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex++;\n endIndex++;\n } // Start walking from end of segment to get last audio packet\n\n\n endIndex = bytes.byteLength;\n startIndex = endIndex - MP2T_PACKET_LENGTH;\n endLoop = false;\n\n while (startIndex >= 0) {\n // Look for a pair of start and end sync bytes in the data..\n if (bytes[startIndex] === SYNC_BYTE && (bytes[endIndex] === SYNC_BYTE || endIndex === bytes.byteLength)) {\n // We found a packet\n packet = bytes.subarray(startIndex, endIndex);\n type = probe.ts.parseType(packet, pmt.pid);\n\n switch (type) {\n case 'pes':\n pesType = probe.ts.parsePesType(packet, pmt.table);\n pusi = probe.ts.parsePayloadUnitStartIndicator(packet);\n\n if (pesType === 'audio' && pusi) {\n parsed = probe.ts.parsePesTime(packet);\n\n if (parsed) {\n parsed.type = 'audio';\n result.audio.push(parsed);\n endLoop = true;\n }\n }\n\n break;\n }\n\n if (endLoop) {\n break;\n }\n\n startIndex -= MP2T_PACKET_LENGTH;\n endIndex -= MP2T_PACKET_LENGTH;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex--;\n endIndex--;\n }\n };\n /**\n * walks through the segment data from the start and end to get timing information\n * for the first and last video pes packets as well as timing information for the first\n * key frame.\n */\n\n\n var parseVideoPes_ = function parseVideoPes_(bytes, pmt, result) {\n var startIndex = 0,\n endIndex = MP2T_PACKET_LENGTH,\n packet,\n type,\n pesType,\n pusi,\n parsed,\n frame,\n i,\n pes;\n var endLoop = false;\n var currentFrame = {\n data: [],\n size: 0\n }; // Start walking from start of segment to get first video packet\n\n while (endIndex < bytes.byteLength) {\n // Look for a pair of start and end sync bytes in the data..\n if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) {\n // We found a packet\n packet = bytes.subarray(startIndex, endIndex);\n type = probe.ts.parseType(packet, pmt.pid);\n\n switch (type) {\n case 'pes':\n pesType = probe.ts.parsePesType(packet, pmt.table);\n pusi = probe.ts.parsePayloadUnitStartIndicator(packet);\n\n if (pesType === 'video') {\n if (pusi && !endLoop) {\n parsed = probe.ts.parsePesTime(packet);\n\n if (parsed) {\n parsed.type = 'video';\n result.video.push(parsed);\n endLoop = true;\n }\n }\n\n if (!result.firstKeyFrame) {\n if (pusi) {\n if (currentFrame.size !== 0) {\n frame = new Uint8Array(currentFrame.size);\n i = 0;\n\n while (currentFrame.data.length) {\n pes = currentFrame.data.shift();\n frame.set(pes, i);\n i += pes.byteLength;\n }\n\n if (probe.ts.videoPacketContainsKeyFrame(frame)) {\n var firstKeyFrame = probe.ts.parsePesTime(frame); // PTS/DTS may not be available. Simply *not* setting\n // the keyframe seems to work fine with HLS playback\n // and definitely preferable to a crash with TypeError...\n\n if (firstKeyFrame) {\n result.firstKeyFrame = firstKeyFrame;\n result.firstKeyFrame.type = 'video';\n } else {\n // eslint-disable-next-line\n console.warn('Failed to extract PTS/DTS from PES at first keyframe. ' + 'This could be an unusual TS segment, or else mux.js did not ' + 'parse your TS segment correctly. If you know your TS ' + 'segments do contain PTS/DTS on keyframes please file a bug ' + 'report! You can try ffprobe to double check for yourself.');\n }\n }\n\n currentFrame.size = 0;\n }\n }\n\n currentFrame.data.push(packet);\n currentFrame.size += packet.byteLength;\n }\n }\n\n break;\n }\n\n if (endLoop && result.firstKeyFrame) {\n break;\n }\n\n startIndex += MP2T_PACKET_LENGTH;\n endIndex += MP2T_PACKET_LENGTH;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex++;\n endIndex++;\n } // Start walking from end of segment to get last video packet\n\n\n endIndex = bytes.byteLength;\n startIndex = endIndex - MP2T_PACKET_LENGTH;\n endLoop = false;\n\n while (startIndex >= 0) {\n // Look for a pair of start and end sync bytes in the data..\n if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) {\n // We found a packet\n packet = bytes.subarray(startIndex, endIndex);\n type = probe.ts.parseType(packet, pmt.pid);\n\n switch (type) {\n case 'pes':\n pesType = probe.ts.parsePesType(packet, pmt.table);\n pusi = probe.ts.parsePayloadUnitStartIndicator(packet);\n\n if (pesType === 'video' && pusi) {\n parsed = probe.ts.parsePesTime(packet);\n\n if (parsed) {\n parsed.type = 'video';\n result.video.push(parsed);\n endLoop = true;\n }\n }\n\n break;\n }\n\n if (endLoop) {\n break;\n }\n\n startIndex -= MP2T_PACKET_LENGTH;\n endIndex -= MP2T_PACKET_LENGTH;\n continue;\n } // If we get here, we have somehow become de-synchronized and we need to step\n // forward one byte at a time until we find a pair of sync bytes that denote\n // a packet\n\n\n startIndex--;\n endIndex--;\n }\n };\n /**\n * Adjusts the timestamp information for the segment to account for\n * rollover and convert to seconds based on pes packet timescale (90khz clock)\n */\n\n\n var adjustTimestamp_ = function adjustTimestamp_(segmentInfo, baseTimestamp) {\n if (segmentInfo.audio && segmentInfo.audio.length) {\n var audioBaseTimestamp = baseTimestamp;\n\n if (typeof audioBaseTimestamp === 'undefined' || isNaN(audioBaseTimestamp)) {\n audioBaseTimestamp = segmentInfo.audio[0].dts;\n }\n\n segmentInfo.audio.forEach(function (info) {\n info.dts = handleRollover(info.dts, audioBaseTimestamp);\n info.pts = handleRollover(info.pts, audioBaseTimestamp); // time in seconds\n\n info.dtsTime = info.dts / ONE_SECOND_IN_TS;\n info.ptsTime = info.pts / ONE_SECOND_IN_TS;\n });\n }\n\n if (segmentInfo.video && segmentInfo.video.length) {\n var videoBaseTimestamp = baseTimestamp;\n\n if (typeof videoBaseTimestamp === 'undefined' || isNaN(videoBaseTimestamp)) {\n videoBaseTimestamp = segmentInfo.video[0].dts;\n }\n\n segmentInfo.video.forEach(function (info) {\n info.dts = handleRollover(info.dts, videoBaseTimestamp);\n info.pts = handleRollover(info.pts, videoBaseTimestamp); // time in seconds\n\n info.dtsTime = info.dts / ONE_SECOND_IN_TS;\n info.ptsTime = info.pts / ONE_SECOND_IN_TS;\n });\n\n if (segmentInfo.firstKeyFrame) {\n var frame = segmentInfo.firstKeyFrame;\n frame.dts = handleRollover(frame.dts, videoBaseTimestamp);\n frame.pts = handleRollover(frame.pts, videoBaseTimestamp); // time in seconds\n\n frame.dtsTime = frame.dts / ONE_SECOND_IN_TS;\n frame.ptsTime = frame.pts / ONE_SECOND_IN_TS;\n }\n }\n };\n /**\n * inspects the aac data stream for start and end time information\n */\n\n\n var inspectAac_ = function inspectAac_(bytes) {\n var endLoop = false,\n audioCount = 0,\n sampleRate = null,\n timestamp = null,\n frameSize = 0,\n byteIndex = 0,\n packet;\n\n while (bytes.length - byteIndex >= 3) {\n var type = probe.aac.parseType(bytes, byteIndex);\n\n switch (type) {\n case 'timed-metadata':\n // Exit early because we don't have enough to parse\n // the ID3 tag header\n if (bytes.length - byteIndex < 10) {\n endLoop = true;\n break;\n }\n\n frameSize = probe.aac.parseId3TagSize(bytes, byteIndex); // Exit early if we don't have enough in the buffer\n // to emit a full packet\n\n if (frameSize > bytes.length) {\n endLoop = true;\n break;\n }\n\n if (timestamp === null) {\n packet = bytes.subarray(byteIndex, byteIndex + frameSize);\n timestamp = probe.aac.parseAacTimestamp(packet);\n }\n\n byteIndex += frameSize;\n break;\n\n case 'audio':\n // Exit early because we don't have enough to parse\n // the ADTS frame header\n if (bytes.length - byteIndex < 7) {\n endLoop = true;\n break;\n }\n\n frameSize = probe.aac.parseAdtsSize(bytes, byteIndex); // Exit early if we don't have enough in the buffer\n // to emit a full packet\n\n if (frameSize > bytes.length) {\n endLoop = true;\n break;\n }\n\n if (sampleRate === null) {\n packet = bytes.subarray(byteIndex, byteIndex + frameSize);\n sampleRate = probe.aac.parseSampleRate(packet);\n }\n\n audioCount++;\n byteIndex += frameSize;\n break;\n\n default:\n byteIndex++;\n break;\n }\n\n if (endLoop) {\n return null;\n }\n }\n\n if (sampleRate === null || timestamp === null) {\n return null;\n }\n\n var audioTimescale = ONE_SECOND_IN_TS / sampleRate;\n var result = {\n audio: [{\n type: 'audio',\n dts: timestamp,\n pts: timestamp\n }, {\n type: 'audio',\n dts: timestamp + audioCount * 1024 * audioTimescale,\n pts: timestamp + audioCount * 1024 * audioTimescale\n }]\n };\n return result;\n };\n /**\n * inspects the transport stream segment data for start and end time information\n * of the audio and video tracks (when present) as well as the first key frame's\n * start time.\n */\n\n\n var inspectTs_ = function inspectTs_(bytes) {\n var pmt = {\n pid: null,\n table: null\n };\n var result = {};\n parsePsi_(bytes, pmt);\n\n for (var pid in pmt.table) {\n if (pmt.table.hasOwnProperty(pid)) {\n var type = pmt.table[pid];\n\n switch (type) {\n case streamTypes.H264_STREAM_TYPE:\n result.video = [];\n parseVideoPes_(bytes, pmt, result);\n\n if (result.video.length === 0) {\n delete result.video;\n }\n\n break;\n\n case streamTypes.ADTS_STREAM_TYPE:\n result.audio = [];\n parseAudioPes_(bytes, pmt, result);\n\n if (result.audio.length === 0) {\n delete result.audio;\n }\n\n break;\n }\n }\n }\n\n return result;\n };\n /**\n * Inspects segment byte data and returns an object with start and end timing information\n *\n * @param {Uint8Array} bytes The segment byte data\n * @param {Number} baseTimestamp Relative reference timestamp used when adjusting frame\n * timestamps for rollover. This value must be in 90khz clock.\n * @return {Object} Object containing start and end frame timing info of segment.\n */\n\n\n var inspect = function inspect(bytes, baseTimestamp) {\n var isAacData = probe.aac.isLikelyAacData(bytes);\n var result;\n\n if (isAacData) {\n result = inspectAac_(bytes);\n } else {\n result = inspectTs_(bytes);\n }\n\n if (!result || !result.audio && !result.video) {\n return null;\n }\n\n adjustTimestamp_(result, baseTimestamp);\n return result;\n };\n\n var tsInspector = {\n inspect: inspect,\n parseAudioPes_: parseAudioPes_\n };\n /* global self */\n\n /**\n * Re-emits transmuxer events by converting them into messages to the\n * world outside the worker.\n *\n * @param {Object} transmuxer the transmuxer to wire events on\n * @private\n */\n\n var wireTransmuxerEvents = function wireTransmuxerEvents(self, transmuxer) {\n transmuxer.on('data', function (segment) {\n // transfer ownership of the underlying ArrayBuffer\n // instead of doing a copy to save memory\n // ArrayBuffers are transferable but generic TypedArrays are not\n // @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)\n var initArray = segment.initSegment;\n segment.initSegment = {\n data: initArray.buffer,\n byteOffset: initArray.byteOffset,\n byteLength: initArray.byteLength\n };\n var typedArray = segment.data;\n segment.data = typedArray.buffer;\n self.postMessage({\n action: 'data',\n segment: segment,\n byteOffset: typedArray.byteOffset,\n byteLength: typedArray.byteLength\n }, [segment.data]);\n });\n transmuxer.on('done', function (data) {\n self.postMessage({\n action: 'done'\n });\n });\n transmuxer.on('gopInfo', function (gopInfo) {\n self.postMessage({\n action: 'gopInfo',\n gopInfo: gopInfo\n });\n });\n transmuxer.on('videoSegmentTimingInfo', function (timingInfo) {\n var videoSegmentTimingInfo = {\n start: {\n decode: clock.videoTsToSeconds(timingInfo.start.dts),\n presentation: clock.videoTsToSeconds(timingInfo.start.pts)\n },\n end: {\n decode: clock.videoTsToSeconds(timingInfo.end.dts),\n presentation: clock.videoTsToSeconds(timingInfo.end.pts)\n },\n baseMediaDecodeTime: clock.videoTsToSeconds(timingInfo.baseMediaDecodeTime)\n };\n\n if (timingInfo.prependedContentDuration) {\n videoSegmentTimingInfo.prependedContentDuration = clock.videoTsToSeconds(timingInfo.prependedContentDuration);\n }\n\n self.postMessage({\n action: 'videoSegmentTimingInfo',\n videoSegmentTimingInfo: videoSegmentTimingInfo\n });\n });\n transmuxer.on('audioSegmentTimingInfo', function (timingInfo) {\n // Note that all times for [audio/video]SegmentTimingInfo events are in video clock\n var audioSegmentTimingInfo = {\n start: {\n decode: clock.videoTsToSeconds(timingInfo.start.dts),\n presentation: clock.videoTsToSeconds(timingInfo.start.pts)\n },\n end: {\n decode: clock.videoTsToSeconds(timingInfo.end.dts),\n presentation: clock.videoTsToSeconds(timingInfo.end.pts)\n },\n baseMediaDecodeTime: clock.videoTsToSeconds(timingInfo.baseMediaDecodeTime)\n };\n\n if (timingInfo.prependedContentDuration) {\n audioSegmentTimingInfo.prependedContentDuration = clock.videoTsToSeconds(timingInfo.prependedContentDuration);\n }\n\n self.postMessage({\n action: 'audioSegmentTimingInfo',\n audioSegmentTimingInfo: audioSegmentTimingInfo\n });\n });\n transmuxer.on('id3Frame', function (id3Frame) {\n self.postMessage({\n action: 'id3Frame',\n id3Frame: id3Frame\n });\n });\n transmuxer.on('caption', function (caption) {\n self.postMessage({\n action: 'caption',\n caption: caption\n });\n });\n transmuxer.on('trackinfo', function (trackInfo) {\n self.postMessage({\n action: 'trackinfo',\n trackInfo: trackInfo\n });\n });\n transmuxer.on('audioTimingInfo', function (audioTimingInfo) {\n // convert to video TS since we prioritize video time over audio\n self.postMessage({\n action: 'audioTimingInfo',\n audioTimingInfo: {\n start: clock.videoTsToSeconds(audioTimingInfo.start),\n end: clock.videoTsToSeconds(audioTimingInfo.end)\n }\n });\n });\n transmuxer.on('videoTimingInfo', function (videoTimingInfo) {\n self.postMessage({\n action: 'videoTimingInfo',\n videoTimingInfo: {\n start: clock.videoTsToSeconds(videoTimingInfo.start),\n end: clock.videoTsToSeconds(videoTimingInfo.end)\n }\n });\n });\n transmuxer.on('log', function (log) {\n self.postMessage({\n action: 'log',\n log: log\n });\n });\n };\n /**\n * All incoming messages route through this hash. If no function exists\n * to handle an incoming message, then we ignore the message.\n *\n * @class MessageHandlers\n * @param {Object} options the options to initialize with\n */\n\n\n var MessageHandlers = /*#__PURE__*/function () {\n function MessageHandlers(self, options) {\n this.options = options || {};\n this.self = self;\n this.init();\n }\n /**\n * initialize our web worker and wire all the events.\n */\n\n\n var _proto = MessageHandlers.prototype;\n\n _proto.init = function init() {\n if (this.transmuxer) {\n this.transmuxer.dispose();\n }\n\n this.transmuxer = new transmuxer.Transmuxer(this.options);\n wireTransmuxerEvents(this.self, this.transmuxer);\n };\n\n _proto.pushMp4Captions = function pushMp4Captions(data) {\n if (!this.captionParser) {\n this.captionParser = new captionParser();\n this.captionParser.init();\n }\n\n var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);\n var parsed = this.captionParser.parse(segment, data.trackIds, data.timescales);\n this.self.postMessage({\n action: 'mp4Captions',\n captions: parsed && parsed.captions || [],\n logs: parsed && parsed.logs || [],\n data: segment.buffer\n }, [segment.buffer]);\n };\n\n _proto.probeMp4StartTime = function probeMp4StartTime(_ref) {\n var timescales = _ref.timescales,\n data = _ref.data;\n var startTime = probe$2.startTime(timescales, data);\n this.self.postMessage({\n action: 'probeMp4StartTime',\n startTime: startTime,\n data: data\n }, [data.buffer]);\n };\n\n _proto.probeMp4Tracks = function probeMp4Tracks(_ref2) {\n var data = _ref2.data;\n var tracks = probe$2.tracks(data);\n this.self.postMessage({\n action: 'probeMp4Tracks',\n tracks: tracks,\n data: data\n }, [data.buffer]);\n }\n /**\n * Probe an mpeg2-ts segment to determine the start time of the segment in it's\n * internal \"media time,\" as well as whether it contains video and/or audio.\n *\n * @private\n * @param {Uint8Array} bytes - segment bytes\n * @param {number} baseStartTime\n * Relative reference timestamp used when adjusting frame timestamps for rollover.\n * This value should be in seconds, as it's converted to a 90khz clock within the\n * function body.\n * @return {Object} The start time of the current segment in \"media time\" as well as\n * whether it contains video and/or audio\n */\n ;\n\n _proto.probeTs = function probeTs(_ref3) {\n var data = _ref3.data,\n baseStartTime = _ref3.baseStartTime;\n var tsStartTime = typeof baseStartTime === 'number' && !isNaN(baseStartTime) ? baseStartTime * clock.ONE_SECOND_IN_TS : void 0;\n var timeInfo = tsInspector.inspect(data, tsStartTime);\n var result = null;\n\n if (timeInfo) {\n result = {\n // each type's time info comes back as an array of 2 times, start and end\n hasVideo: timeInfo.video && timeInfo.video.length === 2 || false,\n hasAudio: timeInfo.audio && timeInfo.audio.length === 2 || false\n };\n\n if (result.hasVideo) {\n result.videoStart = timeInfo.video[0].ptsTime;\n }\n\n if (result.hasAudio) {\n result.audioStart = timeInfo.audio[0].ptsTime;\n }\n }\n\n this.self.postMessage({\n action: 'probeTs',\n result: result,\n data: data\n }, [data.buffer]);\n };\n\n _proto.clearAllMp4Captions = function clearAllMp4Captions() {\n if (this.captionParser) {\n this.captionParser.clearAllCaptions();\n }\n };\n\n _proto.clearParsedMp4Captions = function clearParsedMp4Captions() {\n if (this.captionParser) {\n this.captionParser.clearParsedCaptions();\n }\n }\n /**\n * Adds data (a ts segment) to the start of the transmuxer pipeline for\n * processing.\n *\n * @param {ArrayBuffer} data data to push into the muxer\n */\n ;\n\n _proto.push = function push(data) {\n // Cast array buffer to correct type for transmuxer\n var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);\n this.transmuxer.push(segment);\n }\n /**\n * Recreate the transmuxer so that the next segment added via `push`\n * start with a fresh transmuxer.\n */\n ;\n\n _proto.reset = function reset() {\n this.transmuxer.reset();\n }\n /**\n * Set the value that will be used as the `baseMediaDecodeTime` time for the\n * next segment pushed in. Subsequent segments will have their `baseMediaDecodeTime`\n * set relative to the first based on the PTS values.\n *\n * @param {Object} data used to set the timestamp offset in the muxer\n */\n ;\n\n _proto.setTimestampOffset = function setTimestampOffset(data) {\n var timestampOffset = data.timestampOffset || 0;\n this.transmuxer.setBaseMediaDecodeTime(Math.round(clock.secondsToVideoTs(timestampOffset)));\n };\n\n _proto.setAudioAppendStart = function setAudioAppendStart(data) {\n this.transmuxer.setAudioAppendStart(Math.ceil(clock.secondsToVideoTs(data.appendStart)));\n };\n\n _proto.setRemux = function setRemux(data) {\n this.transmuxer.setRemux(data.remux);\n }\n /**\n * Forces the pipeline to finish processing the last segment and emit it's\n * results.\n *\n * @param {Object} data event data, not really used\n */\n ;\n\n _proto.flush = function flush(data) {\n this.transmuxer.flush(); // transmuxed done action is fired after both audio/video pipelines are flushed\n\n self.postMessage({\n action: 'done',\n type: 'transmuxed'\n });\n };\n\n _proto.endTimeline = function endTimeline() {\n this.transmuxer.endTimeline(); // transmuxed endedtimeline action is fired after both audio/video pipelines end their\n // timelines\n\n self.postMessage({\n action: 'endedtimeline',\n type: 'transmuxed'\n });\n };\n\n _proto.alignGopsWith = function alignGopsWith(data) {\n this.transmuxer.alignGopsWith(data.gopsToAlignWith.slice());\n };\n\n return MessageHandlers;\n }();\n /**\n * Our web worker interface so that things can talk to mux.js\n * that will be running in a web worker. the scope is passed to this by\n * webworkify.\n *\n * @param {Object} self the scope for the web worker\n */\n\n\n self.onmessage = function (event) {\n if (event.data.action === 'init' && event.data.options) {\n this.messageHandlers = new MessageHandlers(self, event.data.options);\n return;\n }\n\n if (!this.messageHandlers) {\n this.messageHandlers = new MessageHandlers(self);\n }\n\n if (event.data && event.data.action && event.data.action !== 'init') {\n if (this.messageHandlers[event.data.action]) {\n this.messageHandlers[event.data.action](event.data);\n }\n }\n };\n}));\nvar TransmuxWorker = factory(workerCode$1);\n/* rollup-plugin-worker-factory end for worker!/Users/gsinger/repos/clean/http-streaming/src/transmuxer-worker.js */\n\nvar handleData_ = function handleData_(event, transmuxedData, callback) {\n var _event$data$segment = event.data.segment,\n type = _event$data$segment.type,\n initSegment = _event$data$segment.initSegment,\n captions = _event$data$segment.captions,\n captionStreams = _event$data$segment.captionStreams,\n metadata = _event$data$segment.metadata,\n videoFrameDtsTime = _event$data$segment.videoFrameDtsTime,\n videoFramePtsTime = _event$data$segment.videoFramePtsTime;\n transmuxedData.buffer.push({\n captions: captions,\n captionStreams: captionStreams,\n metadata: metadata\n });\n var boxes = event.data.segment.boxes || {\n data: event.data.segment.data\n };\n var result = {\n type: type,\n // cast ArrayBuffer to TypedArray\n data: new Uint8Array(boxes.data, boxes.data.byteOffset, boxes.data.byteLength),\n initSegment: new Uint8Array(initSegment.data, initSegment.byteOffset, initSegment.byteLength)\n };\n\n if (typeof videoFrameDtsTime !== 'undefined') {\n result.videoFrameDtsTime = videoFrameDtsTime;\n }\n\n if (typeof videoFramePtsTime !== 'undefined') {\n result.videoFramePtsTime = videoFramePtsTime;\n }\n\n callback(result);\n};\nvar handleDone_ = function handleDone_(_ref) {\n var transmuxedData = _ref.transmuxedData,\n callback = _ref.callback;\n // Previously we only returned data on data events,\n // not on done events. Clear out the buffer to keep that consistent.\n transmuxedData.buffer = []; // all buffers should have been flushed from the muxer, so start processing anything we\n // have received\n\n callback(transmuxedData);\n};\nvar handleGopInfo_ = function handleGopInfo_(event, transmuxedData) {\n transmuxedData.gopInfo = event.data.gopInfo;\n};\nvar processTransmux = function processTransmux(options) {\n var transmuxer = options.transmuxer,\n bytes = options.bytes,\n audioAppendStart = options.audioAppendStart,\n gopsToAlignWith = options.gopsToAlignWith,\n remux = options.remux,\n onData = options.onData,\n onTrackInfo = options.onTrackInfo,\n onAudioTimingInfo = options.onAudioTimingInfo,\n onVideoTimingInfo = options.onVideoTimingInfo,\n onVideoSegmentTimingInfo = options.onVideoSegmentTimingInfo,\n onAudioSegmentTimingInfo = options.onAudioSegmentTimingInfo,\n onId3 = options.onId3,\n onCaptions = options.onCaptions,\n onDone = options.onDone,\n onEndedTimeline = options.onEndedTimeline,\n onTransmuxerLog = options.onTransmuxerLog,\n isEndOfTimeline = options.isEndOfTimeline;\n var transmuxedData = {\n buffer: []\n };\n var waitForEndedTimelineEvent = isEndOfTimeline;\n\n var handleMessage = function handleMessage(event) {\n if (transmuxer.currentTransmux !== options) {\n // disposed\n return;\n }\n\n if (event.data.action === 'data') {\n handleData_(event, transmuxedData, onData);\n }\n\n if (event.data.action === 'trackinfo') {\n onTrackInfo(event.data.trackInfo);\n }\n\n if (event.data.action === 'gopInfo') {\n handleGopInfo_(event, transmuxedData);\n }\n\n if (event.data.action === 'audioTimingInfo') {\n onAudioTimingInfo(event.data.audioTimingInfo);\n }\n\n if (event.data.action === 'videoTimingInfo') {\n onVideoTimingInfo(event.data.videoTimingInfo);\n }\n\n if (event.data.action === 'videoSegmentTimingInfo') {\n onVideoSegmentTimingInfo(event.data.videoSegmentTimingInfo);\n }\n\n if (event.data.action === 'audioSegmentTimingInfo') {\n onAudioSegmentTimingInfo(event.data.audioSegmentTimingInfo);\n }\n\n if (event.data.action === 'id3Frame') {\n onId3([event.data.id3Frame], event.data.id3Frame.dispatchType);\n }\n\n if (event.data.action === 'caption') {\n onCaptions(event.data.caption);\n }\n\n if (event.data.action === 'endedtimeline') {\n waitForEndedTimelineEvent = false;\n onEndedTimeline();\n }\n\n if (event.data.action === 'log') {\n onTransmuxerLog(event.data.log);\n } // wait for the transmuxed event since we may have audio and video\n\n\n if (event.data.type !== 'transmuxed') {\n return;\n } // If the \"endedtimeline\" event has not yet fired, and this segment represents the end\n // of a timeline, that means there may still be data events before the segment\n // processing can be considerred complete. In that case, the final event should be\n // an \"endedtimeline\" event with the type \"transmuxed.\"\n\n\n if (waitForEndedTimelineEvent) {\n return;\n }\n\n transmuxer.onmessage = null;\n handleDone_({\n transmuxedData: transmuxedData,\n callback: onDone\n });\n /* eslint-disable no-use-before-define */\n\n dequeue(transmuxer);\n /* eslint-enable */\n };\n\n transmuxer.onmessage = handleMessage;\n\n if (audioAppendStart) {\n transmuxer.postMessage({\n action: 'setAudioAppendStart',\n appendStart: audioAppendStart\n });\n } // allow empty arrays to be passed to clear out GOPs\n\n\n if (Array.isArray(gopsToAlignWith)) {\n transmuxer.postMessage({\n action: 'alignGopsWith',\n gopsToAlignWith: gopsToAlignWith\n });\n }\n\n if (typeof remux !== 'undefined') {\n transmuxer.postMessage({\n action: 'setRemux',\n remux: remux\n });\n }\n\n if (bytes.byteLength) {\n var buffer = bytes instanceof ArrayBuffer ? bytes : bytes.buffer;\n var byteOffset = bytes instanceof ArrayBuffer ? 0 : bytes.byteOffset;\n transmuxer.postMessage({\n action: 'push',\n // Send the typed-array of data as an ArrayBuffer so that\n // it can be sent as a \"Transferable\" and avoid the costly\n // memory copy\n data: buffer,\n // To recreate the original typed-array, we need information\n // about what portion of the ArrayBuffer it was a view into\n byteOffset: byteOffset,\n byteLength: bytes.byteLength\n }, [buffer]);\n }\n\n if (isEndOfTimeline) {\n transmuxer.postMessage({\n action: 'endTimeline'\n });\n } // even if we didn't push any bytes, we have to make sure we flush in case we reached\n // the end of the segment\n\n\n transmuxer.postMessage({\n action: 'flush'\n });\n};\nvar dequeue = function dequeue(transmuxer) {\n transmuxer.currentTransmux = null;\n\n if (transmuxer.transmuxQueue.length) {\n transmuxer.currentTransmux = transmuxer.transmuxQueue.shift();\n\n if (typeof transmuxer.currentTransmux === 'function') {\n transmuxer.currentTransmux();\n } else {\n processTransmux(transmuxer.currentTransmux);\n }\n }\n};\nvar processAction = function processAction(transmuxer, action) {\n transmuxer.postMessage({\n action: action\n });\n dequeue(transmuxer);\n};\nvar enqueueAction = function enqueueAction(action, transmuxer) {\n if (!transmuxer.currentTransmux) {\n transmuxer.currentTransmux = action;\n processAction(transmuxer, action);\n return;\n }\n\n transmuxer.transmuxQueue.push(processAction.bind(null, transmuxer, action));\n};\nvar reset = function reset(transmuxer) {\n enqueueAction('reset', transmuxer);\n};\nvar endTimeline = function endTimeline(transmuxer) {\n enqueueAction('endTimeline', transmuxer);\n};\nvar transmux = function transmux(options) {\n if (!options.transmuxer.currentTransmux) {\n options.transmuxer.currentTransmux = options;\n processTransmux(options);\n return;\n }\n\n options.transmuxer.transmuxQueue.push(options);\n};\nvar createTransmuxer = function createTransmuxer(options) {\n var transmuxer = new TransmuxWorker();\n transmuxer.currentTransmux = null;\n transmuxer.transmuxQueue = [];\n var term = transmuxer.terminate;\n\n transmuxer.terminate = function () {\n transmuxer.currentTransmux = null;\n transmuxer.transmuxQueue.length = 0;\n return term.call(transmuxer);\n };\n\n transmuxer.postMessage({\n action: 'init',\n options: options\n });\n return transmuxer;\n};\nvar segmentTransmuxer = {\n reset: reset,\n endTimeline: endTimeline,\n transmux: transmux,\n createTransmuxer: createTransmuxer\n};\n\nvar workerCallback = function workerCallback(options) {\n var transmuxer = options.transmuxer;\n var endAction = options.endAction || options.action;\n var callback = options.callback;\n\n var message = _extends({}, options, {\n endAction: null,\n transmuxer: null,\n callback: null\n });\n\n var listenForEndEvent = function listenForEndEvent(event) {\n if (event.data.action !== endAction) {\n return;\n }\n\n transmuxer.removeEventListener('message', listenForEndEvent); // transfer ownership of bytes back to us.\n\n if (event.data.data) {\n event.data.data = new Uint8Array(event.data.data, options.byteOffset || 0, options.byteLength || event.data.data.byteLength);\n\n if (options.data) {\n options.data = event.data.data;\n }\n }\n\n callback(event.data);\n };\n\n transmuxer.addEventListener('message', listenForEndEvent);\n\n if (options.data) {\n var isArrayBuffer = options.data instanceof ArrayBuffer;\n message.byteOffset = isArrayBuffer ? 0 : options.data.byteOffset;\n message.byteLength = options.data.byteLength;\n var transfers = [isArrayBuffer ? options.data : options.data.buffer];\n transmuxer.postMessage(message, transfers);\n } else {\n transmuxer.postMessage(message);\n }\n};\n\nvar REQUEST_ERRORS = {\n FAILURE: 2,\n TIMEOUT: -101,\n ABORTED: -102\n};\n/**\n * Abort all requests\n *\n * @param {Object} activeXhrs - an object that tracks all XHR requests\n */\n\nvar abortAll = function abortAll(activeXhrs) {\n activeXhrs.forEach(function (xhr) {\n xhr.abort();\n });\n};\n/**\n * Gather important bandwidth stats once a request has completed\n *\n * @param {Object} request - the XHR request from which to gather stats\n */\n\n\nvar getRequestStats = function getRequestStats(request) {\n return {\n bandwidth: request.bandwidth,\n bytesReceived: request.bytesReceived || 0,\n roundTripTime: request.roundTripTime || 0\n };\n};\n/**\n * If possible gather bandwidth stats as a request is in\n * progress\n *\n * @param {Event} progressEvent - an event object from an XHR's progress event\n */\n\n\nvar getProgressStats = function getProgressStats(progressEvent) {\n var request = progressEvent.target;\n var roundTripTime = Date.now() - request.requestTime;\n var stats = {\n bandwidth: Infinity,\n bytesReceived: 0,\n roundTripTime: roundTripTime || 0\n };\n stats.bytesReceived = progressEvent.loaded; // This can result in Infinity if stats.roundTripTime is 0 but that is ok\n // because we should only use bandwidth stats on progress to determine when\n // abort a request early due to insufficient bandwidth\n\n stats.bandwidth = Math.floor(stats.bytesReceived / stats.roundTripTime * 8 * 1000);\n return stats;\n};\n/**\n * Handle all error conditions in one place and return an object\n * with all the information\n *\n * @param {Error|null} error - if non-null signals an error occured with the XHR\n * @param {Object} request - the XHR request that possibly generated the error\n */\n\n\nvar handleErrors = function handleErrors(error, request) {\n if (request.timedout) {\n return {\n status: request.status,\n message: 'HLS request timed-out at URL: ' + request.uri,\n code: REQUEST_ERRORS.TIMEOUT,\n xhr: request\n };\n }\n\n if (request.aborted) {\n return {\n status: request.status,\n message: 'HLS request aborted at URL: ' + request.uri,\n code: REQUEST_ERRORS.ABORTED,\n xhr: request\n };\n }\n\n if (error) {\n return {\n status: request.status,\n message: 'HLS request errored at URL: ' + request.uri,\n code: REQUEST_ERRORS.FAILURE,\n xhr: request\n };\n }\n\n if (request.responseType === 'arraybuffer' && request.response.byteLength === 0) {\n return {\n status: request.status,\n message: 'Empty HLS response at URL: ' + request.uri,\n code: REQUEST_ERRORS.FAILURE,\n xhr: request\n };\n }\n\n return null;\n};\n/**\n * Handle responses for key data and convert the key data to the correct format\n * for the decryption step later\n *\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Array} objects - objects to add the key bytes to.\n * @param {Function} finishProcessingFn - a callback to execute to continue processing\n * this request\n */\n\n\nvar handleKeyResponse = function handleKeyResponse(segment, objects, finishProcessingFn) {\n return function (error, request) {\n var response = request.response;\n var errorObj = handleErrors(error, request);\n\n if (errorObj) {\n return finishProcessingFn(errorObj, segment);\n }\n\n if (response.byteLength !== 16) {\n return finishProcessingFn({\n status: request.status,\n message: 'Invalid HLS key at URL: ' + request.uri,\n code: REQUEST_ERRORS.FAILURE,\n xhr: request\n }, segment);\n }\n\n var view = new DataView(response);\n var bytes = new Uint32Array([view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)]);\n\n for (var i = 0; i < objects.length; i++) {\n objects[i].bytes = bytes;\n }\n\n return finishProcessingFn(null, segment);\n };\n};\n\nvar parseInitSegment = function parseInitSegment(segment, _callback) {\n var type = detectContainerForBytes(segment.map.bytes); // TODO: We should also handle ts init segments here, but we\n // only know how to parse mp4 init segments at the moment\n\n if (type !== 'mp4') {\n var uri = segment.map.resolvedUri || segment.map.uri;\n return _callback({\n internal: true,\n message: \"Found unsupported \" + (type || 'unknown') + \" container for initialization segment at URL: \" + uri,\n code: REQUEST_ERRORS.FAILURE\n });\n }\n\n workerCallback({\n action: 'probeMp4Tracks',\n data: segment.map.bytes,\n transmuxer: segment.transmuxer,\n callback: function callback(_ref) {\n var tracks = _ref.tracks,\n data = _ref.data;\n // transfer bytes back to us\n segment.map.bytes = data;\n tracks.forEach(function (track) {\n segment.map.tracks = segment.map.tracks || {}; // only support one track of each type for now\n\n if (segment.map.tracks[track.type]) {\n return;\n }\n\n segment.map.tracks[track.type] = track;\n\n if (typeof track.id === 'number' && track.timescale) {\n segment.map.timescales = segment.map.timescales || {};\n segment.map.timescales[track.id] = track.timescale;\n }\n });\n return _callback(null);\n }\n });\n};\n/**\n * Handle init-segment responses\n *\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Function} finishProcessingFn - a callback to execute to continue processing\n * this request\n */\n\n\nvar handleInitSegmentResponse = function handleInitSegmentResponse(_ref2) {\n var segment = _ref2.segment,\n finishProcessingFn = _ref2.finishProcessingFn;\n return function (error, request) {\n var errorObj = handleErrors(error, request);\n\n if (errorObj) {\n return finishProcessingFn(errorObj, segment);\n }\n\n var bytes = new Uint8Array(request.response); // init segment is encypted, we will have to wait\n // until the key request is done to decrypt.\n\n if (segment.map.key) {\n segment.map.encryptedBytes = bytes;\n return finishProcessingFn(null, segment);\n }\n\n segment.map.bytes = bytes;\n parseInitSegment(segment, function (parseError) {\n if (parseError) {\n parseError.xhr = request;\n parseError.status = request.status;\n return finishProcessingFn(parseError, segment);\n }\n\n finishProcessingFn(null, segment);\n });\n };\n};\n/**\n * Response handler for segment-requests being sure to set the correct\n * property depending on whether the segment is encryped or not\n * Also records and keeps track of stats that are used for ABR purposes\n *\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Function} finishProcessingFn - a callback to execute to continue processing\n * this request\n */\n\n\nvar handleSegmentResponse = function handleSegmentResponse(_ref3) {\n var segment = _ref3.segment,\n finishProcessingFn = _ref3.finishProcessingFn,\n responseType = _ref3.responseType;\n return function (error, request) {\n var errorObj = handleErrors(error, request);\n\n if (errorObj) {\n return finishProcessingFn(errorObj, segment);\n }\n\n var newBytes = // although responseText \"should\" exist, this guard serves to prevent an error being\n // thrown for two primary cases:\n // 1. the mime type override stops working, or is not implemented for a specific\n // browser\n // 2. when using mock XHR libraries like sinon that do not allow the override behavior\n responseType === 'arraybuffer' || !request.responseText ? request.response : stringToArrayBuffer(request.responseText.substring(segment.lastReachedChar || 0));\n segment.stats = getRequestStats(request);\n\n if (segment.key) {\n segment.encryptedBytes = new Uint8Array(newBytes);\n } else {\n segment.bytes = new Uint8Array(newBytes);\n }\n\n return finishProcessingFn(null, segment);\n };\n};\n\nvar transmuxAndNotify = function transmuxAndNotify(_ref4) {\n var segment = _ref4.segment,\n bytes = _ref4.bytes,\n trackInfoFn = _ref4.trackInfoFn,\n timingInfoFn = _ref4.timingInfoFn,\n videoSegmentTimingInfoFn = _ref4.videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn = _ref4.audioSegmentTimingInfoFn,\n id3Fn = _ref4.id3Fn,\n captionsFn = _ref4.captionsFn,\n isEndOfTimeline = _ref4.isEndOfTimeline,\n endedTimelineFn = _ref4.endedTimelineFn,\n dataFn = _ref4.dataFn,\n doneFn = _ref4.doneFn,\n onTransmuxerLog = _ref4.onTransmuxerLog;\n var fmp4Tracks = segment.map && segment.map.tracks || {};\n var isMuxed = Boolean(fmp4Tracks.audio && fmp4Tracks.video); // Keep references to each function so we can null them out after we're done with them.\n // One reason for this is that in the case of full segments, we want to trust start\n // times from the probe, rather than the transmuxer.\n\n var audioStartFn = timingInfoFn.bind(null, segment, 'audio', 'start');\n var audioEndFn = timingInfoFn.bind(null, segment, 'audio', 'end');\n var videoStartFn = timingInfoFn.bind(null, segment, 'video', 'start');\n var videoEndFn = timingInfoFn.bind(null, segment, 'video', 'end');\n\n var finish = function finish() {\n return transmux({\n bytes: bytes,\n transmuxer: segment.transmuxer,\n audioAppendStart: segment.audioAppendStart,\n gopsToAlignWith: segment.gopsToAlignWith,\n remux: isMuxed,\n onData: function onData(result) {\n result.type = result.type === 'combined' ? 'video' : result.type;\n dataFn(segment, result);\n },\n onTrackInfo: function onTrackInfo(trackInfo) {\n if (trackInfoFn) {\n if (isMuxed) {\n trackInfo.isMuxed = true;\n }\n\n trackInfoFn(segment, trackInfo);\n }\n },\n onAudioTimingInfo: function onAudioTimingInfo(audioTimingInfo) {\n // we only want the first start value we encounter\n if (audioStartFn && typeof audioTimingInfo.start !== 'undefined') {\n audioStartFn(audioTimingInfo.start);\n audioStartFn = null;\n } // we want to continually update the end time\n\n\n if (audioEndFn && typeof audioTimingInfo.end !== 'undefined') {\n audioEndFn(audioTimingInfo.end);\n }\n },\n onVideoTimingInfo: function onVideoTimingInfo(videoTimingInfo) {\n // we only want the first start value we encounter\n if (videoStartFn && typeof videoTimingInfo.start !== 'undefined') {\n videoStartFn(videoTimingInfo.start);\n videoStartFn = null;\n } // we want to continually update the end time\n\n\n if (videoEndFn && typeof videoTimingInfo.end !== 'undefined') {\n videoEndFn(videoTimingInfo.end);\n }\n },\n onVideoSegmentTimingInfo: function onVideoSegmentTimingInfo(videoSegmentTimingInfo) {\n videoSegmentTimingInfoFn(videoSegmentTimingInfo);\n },\n onAudioSegmentTimingInfo: function onAudioSegmentTimingInfo(audioSegmentTimingInfo) {\n audioSegmentTimingInfoFn(audioSegmentTimingInfo);\n },\n onId3: function onId3(id3Frames, dispatchType) {\n id3Fn(segment, id3Frames, dispatchType);\n },\n onCaptions: function onCaptions(captions) {\n captionsFn(segment, [captions]);\n },\n isEndOfTimeline: isEndOfTimeline,\n onEndedTimeline: function onEndedTimeline() {\n endedTimelineFn();\n },\n onTransmuxerLog: onTransmuxerLog,\n onDone: function onDone(result) {\n if (!doneFn) {\n return;\n }\n\n result.type = result.type === 'combined' ? 'video' : result.type;\n doneFn(null, segment, result);\n }\n });\n }; // In the transmuxer, we don't yet have the ability to extract a \"proper\" start time.\n // Meaning cached frame data may corrupt our notion of where this segment\n // really starts. To get around this, probe for the info needed.\n\n\n workerCallback({\n action: 'probeTs',\n transmuxer: segment.transmuxer,\n data: bytes,\n baseStartTime: segment.baseStartTime,\n callback: function callback(data) {\n segment.bytes = bytes = data.data;\n var probeResult = data.result;\n\n if (probeResult) {\n trackInfoFn(segment, {\n hasAudio: probeResult.hasAudio,\n hasVideo: probeResult.hasVideo,\n isMuxed: isMuxed\n });\n trackInfoFn = null;\n\n if (probeResult.hasAudio && !isMuxed) {\n audioStartFn(probeResult.audioStart);\n }\n\n if (probeResult.hasVideo) {\n videoStartFn(probeResult.videoStart);\n }\n\n audioStartFn = null;\n videoStartFn = null;\n }\n\n finish();\n }\n });\n};\n\nvar handleSegmentBytes = function handleSegmentBytes(_ref5) {\n var segment = _ref5.segment,\n bytes = _ref5.bytes,\n trackInfoFn = _ref5.trackInfoFn,\n timingInfoFn = _ref5.timingInfoFn,\n videoSegmentTimingInfoFn = _ref5.videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn = _ref5.audioSegmentTimingInfoFn,\n id3Fn = _ref5.id3Fn,\n captionsFn = _ref5.captionsFn,\n isEndOfTimeline = _ref5.isEndOfTimeline,\n endedTimelineFn = _ref5.endedTimelineFn,\n dataFn = _ref5.dataFn,\n doneFn = _ref5.doneFn,\n onTransmuxerLog = _ref5.onTransmuxerLog;\n var bytesAsUint8Array = new Uint8Array(bytes); // TODO:\n // We should have a handler that fetches the number of bytes required\n // to check if something is fmp4. This will allow us to save bandwidth\n // because we can only blacklist a playlist and abort requests\n // by codec after trackinfo triggers.\n\n if (isLikelyFmp4MediaSegment(bytesAsUint8Array)) {\n segment.isFmp4 = true;\n var tracks = segment.map.tracks;\n var trackInfo = {\n isFmp4: true,\n hasVideo: !!tracks.video,\n hasAudio: !!tracks.audio\n }; // if we have a audio track, with a codec that is not set to\n // encrypted audio\n\n if (tracks.audio && tracks.audio.codec && tracks.audio.codec !== 'enca') {\n trackInfo.audioCodec = tracks.audio.codec;\n } // if we have a video track, with a codec that is not set to\n // encrypted video\n\n\n if (tracks.video && tracks.video.codec && tracks.video.codec !== 'encv') {\n trackInfo.videoCodec = tracks.video.codec;\n }\n\n if (tracks.video && tracks.audio) {\n trackInfo.isMuxed = true;\n } // since we don't support appending fmp4 data on progress, we know we have the full\n // segment here\n\n\n trackInfoFn(segment, trackInfo); // The probe doesn't provide the segment end time, so only callback with the start\n // time. The end time can be roughly calculated by the receiver using the duration.\n //\n // Note that the start time returned by the probe reflects the baseMediaDecodeTime, as\n // that is the true start of the segment (where the playback engine should begin\n // decoding).\n\n var finishLoading = function finishLoading(captions) {\n // if the track still has audio at this point it is only possible\n // for it to be audio only. See `tracks.video && tracks.audio` if statement\n // above.\n // we make sure to use segment.bytes here as that\n dataFn(segment, {\n data: bytesAsUint8Array,\n type: trackInfo.hasAudio && !trackInfo.isMuxed ? 'audio' : 'video'\n });\n\n if (captions && captions.length) {\n captionsFn(segment, captions);\n }\n\n doneFn(null, segment, {});\n };\n\n workerCallback({\n action: 'probeMp4StartTime',\n timescales: segment.map.timescales,\n data: bytesAsUint8Array,\n transmuxer: segment.transmuxer,\n callback: function callback(_ref6) {\n var data = _ref6.data,\n startTime = _ref6.startTime;\n // transfer bytes back to us\n bytes = data.buffer;\n segment.bytes = bytesAsUint8Array = data;\n\n if (trackInfo.hasAudio && !trackInfo.isMuxed) {\n timingInfoFn(segment, 'audio', 'start', startTime);\n }\n\n if (trackInfo.hasVideo) {\n timingInfoFn(segment, 'video', 'start', startTime);\n } // Run through the CaptionParser in case there are captions.\n // Initialize CaptionParser if it hasn't been yet\n\n\n if (!tracks.video || !data.byteLength || !segment.transmuxer) {\n finishLoading();\n return;\n }\n\n workerCallback({\n action: 'pushMp4Captions',\n endAction: 'mp4Captions',\n transmuxer: segment.transmuxer,\n data: bytesAsUint8Array,\n timescales: segment.map.timescales,\n trackIds: [tracks.video.id],\n callback: function callback(message) {\n // transfer bytes back to us\n bytes = message.data.buffer;\n segment.bytes = bytesAsUint8Array = message.data;\n message.logs.forEach(function (log) {\n onTransmuxerLog(videojs.mergeOptions(log, {\n stream: 'mp4CaptionParser'\n }));\n });\n finishLoading(message.captions);\n }\n });\n }\n });\n return;\n } // VTT or other segments that don't need processing\n\n\n if (!segment.transmuxer) {\n doneFn(null, segment, {});\n return;\n }\n\n if (typeof segment.container === 'undefined') {\n segment.container = detectContainerForBytes(bytesAsUint8Array);\n }\n\n if (segment.container !== 'ts' && segment.container !== 'aac') {\n trackInfoFn(segment, {\n hasAudio: false,\n hasVideo: false\n });\n doneFn(null, segment, {});\n return;\n } // ts or aac\n\n\n transmuxAndNotify({\n segment: segment,\n bytes: bytes,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn,\n doneFn: doneFn,\n onTransmuxerLog: onTransmuxerLog\n });\n};\n\nvar decrypt = function decrypt(_ref7, callback) {\n var id = _ref7.id,\n key = _ref7.key,\n encryptedBytes = _ref7.encryptedBytes,\n decryptionWorker = _ref7.decryptionWorker;\n\n var decryptionHandler = function decryptionHandler(event) {\n if (event.data.source === id) {\n decryptionWorker.removeEventListener('message', decryptionHandler);\n var decrypted = event.data.decrypted;\n callback(new Uint8Array(decrypted.bytes, decrypted.byteOffset, decrypted.byteLength));\n }\n };\n\n decryptionWorker.addEventListener('message', decryptionHandler);\n var keyBytes;\n\n if (key.bytes.slice) {\n keyBytes = key.bytes.slice();\n } else {\n keyBytes = new Uint32Array(Array.prototype.slice.call(key.bytes));\n } // incrementally decrypt the bytes\n\n\n decryptionWorker.postMessage(createTransferableMessage({\n source: id,\n encrypted: encryptedBytes,\n key: keyBytes,\n iv: key.iv\n }), [encryptedBytes.buffer, keyBytes.buffer]);\n};\n/**\n * Decrypt the segment via the decryption web worker\n *\n * @param {WebWorker} decryptionWorker - a WebWorker interface to AES-128 decryption\n * routines\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Function} trackInfoFn - a callback that receives track info\n * @param {Function} timingInfoFn - a callback that receives timing info\n * @param {Function} videoSegmentTimingInfoFn\n * a callback that receives video timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} audioSegmentTimingInfoFn\n * a callback that receives audio timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {boolean} isEndOfTimeline\n * true if this segment represents the last segment in a timeline\n * @param {Function} endedTimelineFn\n * a callback made when a timeline is ended, will only be called if\n * isEndOfTimeline is true\n * @param {Function} dataFn - a callback that is executed when segment bytes are available\n * and ready to use\n * @param {Function} doneFn - a callback that is executed after decryption has completed\n */\n\n\nvar decryptSegment = function decryptSegment(_ref8) {\n var decryptionWorker = _ref8.decryptionWorker,\n segment = _ref8.segment,\n trackInfoFn = _ref8.trackInfoFn,\n timingInfoFn = _ref8.timingInfoFn,\n videoSegmentTimingInfoFn = _ref8.videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn = _ref8.audioSegmentTimingInfoFn,\n id3Fn = _ref8.id3Fn,\n captionsFn = _ref8.captionsFn,\n isEndOfTimeline = _ref8.isEndOfTimeline,\n endedTimelineFn = _ref8.endedTimelineFn,\n dataFn = _ref8.dataFn,\n doneFn = _ref8.doneFn,\n onTransmuxerLog = _ref8.onTransmuxerLog;\n decrypt({\n id: segment.requestId,\n key: segment.key,\n encryptedBytes: segment.encryptedBytes,\n decryptionWorker: decryptionWorker\n }, function (decryptedBytes) {\n segment.bytes = decryptedBytes;\n handleSegmentBytes({\n segment: segment,\n bytes: segment.bytes,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn,\n doneFn: doneFn,\n onTransmuxerLog: onTransmuxerLog\n });\n });\n};\n/**\n * This function waits for all XHRs to finish (with either success or failure)\n * before continueing processing via it's callback. The function gathers errors\n * from each request into a single errors array so that the error status for\n * each request can be examined later.\n *\n * @param {Object} activeXhrs - an object that tracks all XHR requests\n * @param {WebWorker} decryptionWorker - a WebWorker interface to AES-128 decryption\n * routines\n * @param {Function} trackInfoFn - a callback that receives track info\n * @param {Function} timingInfoFn - a callback that receives timing info\n * @param {Function} videoSegmentTimingInfoFn\n * a callback that receives video timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} audioSegmentTimingInfoFn\n * a callback that receives audio timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} id3Fn - a callback that receives ID3 metadata\n * @param {Function} captionsFn - a callback that receives captions\n * @param {boolean} isEndOfTimeline\n * true if this segment represents the last segment in a timeline\n * @param {Function} endedTimelineFn\n * a callback made when a timeline is ended, will only be called if\n * isEndOfTimeline is true\n * @param {Function} dataFn - a callback that is executed when segment bytes are available\n * and ready to use\n * @param {Function} doneFn - a callback that is executed after all resources have been\n * downloaded and any decryption completed\n */\n\n\nvar waitForCompletion = function waitForCompletion(_ref9) {\n var activeXhrs = _ref9.activeXhrs,\n decryptionWorker = _ref9.decryptionWorker,\n trackInfoFn = _ref9.trackInfoFn,\n timingInfoFn = _ref9.timingInfoFn,\n videoSegmentTimingInfoFn = _ref9.videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn = _ref9.audioSegmentTimingInfoFn,\n id3Fn = _ref9.id3Fn,\n captionsFn = _ref9.captionsFn,\n isEndOfTimeline = _ref9.isEndOfTimeline,\n endedTimelineFn = _ref9.endedTimelineFn,\n dataFn = _ref9.dataFn,\n doneFn = _ref9.doneFn,\n onTransmuxerLog = _ref9.onTransmuxerLog;\n var count = 0;\n var didError = false;\n return function (error, segment) {\n if (didError) {\n return;\n }\n\n if (error) {\n didError = true; // If there are errors, we have to abort any outstanding requests\n\n abortAll(activeXhrs); // Even though the requests above are aborted, and in theory we could wait until we\n // handle the aborted events from those requests, there are some cases where we may\n // never get an aborted event. For instance, if the network connection is lost and\n // there were two requests, the first may have triggered an error immediately, while\n // the second request remains unsent. In that case, the aborted algorithm will not\n // trigger an abort: see https://xhr.spec.whatwg.org/#the-abort()-method\n //\n // We also can't rely on the ready state of the XHR, since the request that\n // triggered the connection error may also show as a ready state of 0 (unsent).\n // Therefore, we have to finish this group of requests immediately after the first\n // seen error.\n\n return doneFn(error, segment);\n }\n\n count += 1;\n\n if (count === activeXhrs.length) {\n var segmentFinish = function segmentFinish() {\n if (segment.encryptedBytes) {\n return decryptSegment({\n decryptionWorker: decryptionWorker,\n segment: segment,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn,\n doneFn: doneFn,\n onTransmuxerLog: onTransmuxerLog\n });\n } // Otherwise, everything is ready just continue\n\n\n handleSegmentBytes({\n segment: segment,\n bytes: segment.bytes,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn,\n doneFn: doneFn,\n onTransmuxerLog: onTransmuxerLog\n });\n }; // Keep track of when *all* of the requests have completed\n\n\n segment.endOfAllRequests = Date.now();\n\n if (segment.map && segment.map.encryptedBytes && !segment.map.bytes) {\n return decrypt({\n decryptionWorker: decryptionWorker,\n // add -init to the \"id\" to differentiate between segment\n // and init segment decryption, just in case they happen\n // at the same time at some point in the future.\n id: segment.requestId + '-init',\n encryptedBytes: segment.map.encryptedBytes,\n key: segment.map.key\n }, function (decryptedBytes) {\n segment.map.bytes = decryptedBytes;\n parseInitSegment(segment, function (parseError) {\n if (parseError) {\n abortAll(activeXhrs);\n return doneFn(parseError, segment);\n }\n\n segmentFinish();\n });\n });\n }\n\n segmentFinish();\n }\n };\n};\n/**\n * Calls the abort callback if any request within the batch was aborted. Will only call\n * the callback once per batch of requests, even if multiple were aborted.\n *\n * @param {Object} loadendState - state to check to see if the abort function was called\n * @param {Function} abortFn - callback to call for abort\n */\n\n\nvar handleLoadEnd = function handleLoadEnd(_ref10) {\n var loadendState = _ref10.loadendState,\n abortFn = _ref10.abortFn;\n return function (event) {\n var request = event.target;\n\n if (request.aborted && abortFn && !loadendState.calledAbortFn) {\n abortFn();\n loadendState.calledAbortFn = true;\n }\n };\n};\n/**\n * Simple progress event callback handler that gathers some stats before\n * executing a provided callback with the `segment` object\n *\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Function} progressFn - a callback that is executed each time a progress event\n * is received\n * @param {Function} trackInfoFn - a callback that receives track info\n * @param {Function} timingInfoFn - a callback that receives timing info\n * @param {Function} videoSegmentTimingInfoFn\n * a callback that receives video timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} audioSegmentTimingInfoFn\n * a callback that receives audio timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {boolean} isEndOfTimeline\n * true if this segment represents the last segment in a timeline\n * @param {Function} endedTimelineFn\n * a callback made when a timeline is ended, will only be called if\n * isEndOfTimeline is true\n * @param {Function} dataFn - a callback that is executed when segment bytes are available\n * and ready to use\n * @param {Event} event - the progress event object from XMLHttpRequest\n */\n\n\nvar handleProgress = function handleProgress(_ref11) {\n var segment = _ref11.segment,\n progressFn = _ref11.progressFn;\n _ref11.trackInfoFn;\n _ref11.timingInfoFn;\n _ref11.videoSegmentTimingInfoFn;\n _ref11.audioSegmentTimingInfoFn;\n _ref11.id3Fn;\n _ref11.captionsFn;\n _ref11.isEndOfTimeline;\n _ref11.endedTimelineFn;\n _ref11.dataFn;\n return function (event) {\n var request = event.target;\n\n if (request.aborted) {\n return;\n }\n\n segment.stats = videojs.mergeOptions(segment.stats, getProgressStats(event)); // record the time that we receive the first byte of data\n\n if (!segment.stats.firstBytesReceivedAt && segment.stats.bytesReceived) {\n segment.stats.firstBytesReceivedAt = Date.now();\n }\n\n return progressFn(event, segment);\n };\n};\n/**\n * Load all resources and does any processing necessary for a media-segment\n *\n * Features:\n * decrypts the media-segment if it has a key uri and an iv\n * aborts *all* requests if *any* one request fails\n *\n * The segment object, at minimum, has the following format:\n * {\n * resolvedUri: String,\n * [transmuxer]: Object,\n * [byterange]: {\n * offset: Number,\n * length: Number\n * },\n * [key]: {\n * resolvedUri: String\n * [byterange]: {\n * offset: Number,\n * length: Number\n * },\n * iv: {\n * bytes: Uint32Array\n * }\n * },\n * [map]: {\n * resolvedUri: String,\n * [byterange]: {\n * offset: Number,\n * length: Number\n * },\n * [bytes]: Uint8Array\n * }\n * }\n * ...where [name] denotes optional properties\n *\n * @param {Function} xhr - an instance of the xhr wrapper in xhr.js\n * @param {Object} xhrOptions - the base options to provide to all xhr requests\n * @param {WebWorker} decryptionWorker - a WebWorker interface to AES-128\n * decryption routines\n * @param {Object} segment - a simplified copy of the segmentInfo object\n * from SegmentLoader\n * @param {Function} abortFn - a callback called (only once) if any piece of a request was\n * aborted\n * @param {Function} progressFn - a callback that receives progress events from the main\n * segment's xhr request\n * @param {Function} trackInfoFn - a callback that receives track info\n * @param {Function} timingInfoFn - a callback that receives timing info\n * @param {Function} videoSegmentTimingInfoFn\n * a callback that receives video timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} audioSegmentTimingInfoFn\n * a callback that receives audio timing info based on media times and\n * any adjustments made by the transmuxer\n * @param {Function} id3Fn - a callback that receives ID3 metadata\n * @param {Function} captionsFn - a callback that receives captions\n * @param {boolean} isEndOfTimeline\n * true if this segment represents the last segment in a timeline\n * @param {Function} endedTimelineFn\n * a callback made when a timeline is ended, will only be called if\n * isEndOfTimeline is true\n * @param {Function} dataFn - a callback that receives data from the main segment's xhr\n * request, transmuxed if needed\n * @param {Function} doneFn - a callback that is executed only once all requests have\n * succeeded or failed\n * @return {Function} a function that, when invoked, immediately aborts all\n * outstanding requests\n */\n\n\nvar mediaSegmentRequest = function mediaSegmentRequest(_ref12) {\n var xhr = _ref12.xhr,\n xhrOptions = _ref12.xhrOptions,\n decryptionWorker = _ref12.decryptionWorker,\n segment = _ref12.segment,\n abortFn = _ref12.abortFn,\n progressFn = _ref12.progressFn,\n trackInfoFn = _ref12.trackInfoFn,\n timingInfoFn = _ref12.timingInfoFn,\n videoSegmentTimingInfoFn = _ref12.videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn = _ref12.audioSegmentTimingInfoFn,\n id3Fn = _ref12.id3Fn,\n captionsFn = _ref12.captionsFn,\n isEndOfTimeline = _ref12.isEndOfTimeline,\n endedTimelineFn = _ref12.endedTimelineFn,\n dataFn = _ref12.dataFn,\n doneFn = _ref12.doneFn,\n onTransmuxerLog = _ref12.onTransmuxerLog;\n var activeXhrs = [];\n var finishProcessingFn = waitForCompletion({\n activeXhrs: activeXhrs,\n decryptionWorker: decryptionWorker,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn,\n doneFn: doneFn,\n onTransmuxerLog: onTransmuxerLog\n }); // optionally, request the decryption key\n\n if (segment.key && !segment.key.bytes) {\n var objects = [segment.key];\n\n if (segment.map && !segment.map.bytes && segment.map.key && segment.map.key.resolvedUri === segment.key.resolvedUri) {\n objects.push(segment.map.key);\n }\n\n var keyRequestOptions = videojs.mergeOptions(xhrOptions, {\n uri: segment.key.resolvedUri,\n responseType: 'arraybuffer'\n });\n var keyRequestCallback = handleKeyResponse(segment, objects, finishProcessingFn);\n var keyXhr = xhr(keyRequestOptions, keyRequestCallback);\n activeXhrs.push(keyXhr);\n } // optionally, request the associated media init segment\n\n\n if (segment.map && !segment.map.bytes) {\n var differentMapKey = segment.map.key && (!segment.key || segment.key.resolvedUri !== segment.map.key.resolvedUri);\n\n if (differentMapKey) {\n var mapKeyRequestOptions = videojs.mergeOptions(xhrOptions, {\n uri: segment.map.key.resolvedUri,\n responseType: 'arraybuffer'\n });\n var mapKeyRequestCallback = handleKeyResponse(segment, [segment.map.key], finishProcessingFn);\n var mapKeyXhr = xhr(mapKeyRequestOptions, mapKeyRequestCallback);\n activeXhrs.push(mapKeyXhr);\n }\n\n var initSegmentOptions = videojs.mergeOptions(xhrOptions, {\n uri: segment.map.resolvedUri,\n responseType: 'arraybuffer',\n headers: segmentXhrHeaders(segment.map)\n });\n var initSegmentRequestCallback = handleInitSegmentResponse({\n segment: segment,\n finishProcessingFn: finishProcessingFn\n });\n var initSegmentXhr = xhr(initSegmentOptions, initSegmentRequestCallback);\n activeXhrs.push(initSegmentXhr);\n }\n\n var segmentRequestOptions = videojs.mergeOptions(xhrOptions, {\n uri: segment.part && segment.part.resolvedUri || segment.resolvedUri,\n responseType: 'arraybuffer',\n headers: segmentXhrHeaders(segment)\n });\n var segmentRequestCallback = handleSegmentResponse({\n segment: segment,\n finishProcessingFn: finishProcessingFn,\n responseType: segmentRequestOptions.responseType\n });\n var segmentXhr = xhr(segmentRequestOptions, segmentRequestCallback);\n segmentXhr.addEventListener('progress', handleProgress({\n segment: segment,\n progressFn: progressFn,\n trackInfoFn: trackInfoFn,\n timingInfoFn: timingInfoFn,\n videoSegmentTimingInfoFn: videoSegmentTimingInfoFn,\n audioSegmentTimingInfoFn: audioSegmentTimingInfoFn,\n id3Fn: id3Fn,\n captionsFn: captionsFn,\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: endedTimelineFn,\n dataFn: dataFn\n }));\n activeXhrs.push(segmentXhr); // since all parts of the request must be considered, but should not make callbacks\n // multiple times, provide a shared state object\n\n var loadendState = {};\n activeXhrs.forEach(function (activeXhr) {\n activeXhr.addEventListener('loadend', handleLoadEnd({\n loadendState: loadendState,\n abortFn: abortFn\n }));\n });\n return function () {\n return abortAll(activeXhrs);\n };\n};\n\n/**\n * @file - codecs.js - Handles tasks regarding codec strings such as translating them to\n * codec strings, or translating codec strings into objects that can be examined.\n */\nvar logFn$1 = logger('CodecUtils');\n/**\n * Returns a set of codec strings parsed from the playlist or the default\n * codec strings if no codecs were specified in the playlist\n *\n * @param {Playlist} media the current media playlist\n * @return {Object} an object with the video and audio codecs\n */\n\nvar getCodecs = function getCodecs(media) {\n // if the codecs were explicitly specified, use them instead of the\n // defaults\n var mediaAttributes = media.attributes || {};\n\n if (mediaAttributes.CODECS) {\n return parseCodecs(mediaAttributes.CODECS);\n }\n};\n\nvar isMaat = function isMaat(master, media) {\n var mediaAttributes = media.attributes || {};\n return master && master.mediaGroups && master.mediaGroups.AUDIO && mediaAttributes.AUDIO && master.mediaGroups.AUDIO[mediaAttributes.AUDIO];\n};\nvar isMuxed = function isMuxed(master, media) {\n if (!isMaat(master, media)) {\n return true;\n }\n\n var mediaAttributes = media.attributes || {};\n var audioGroup = master.mediaGroups.AUDIO[mediaAttributes.AUDIO];\n\n for (var groupId in audioGroup) {\n // If an audio group has a URI (the case for HLS, as HLS will use external playlists),\n // or there are listed playlists (the case for DASH, as the manifest will have already\n // provided all of the details necessary to generate the audio playlist, as opposed to\n // HLS' externally requested playlists), then the content is demuxed.\n if (!audioGroup[groupId].uri && !audioGroup[groupId].playlists) {\n return true;\n }\n }\n\n return false;\n};\nvar unwrapCodecList = function unwrapCodecList(codecList) {\n var codecs = {};\n codecList.forEach(function (_ref) {\n var mediaType = _ref.mediaType,\n type = _ref.type,\n details = _ref.details;\n codecs[mediaType] = codecs[mediaType] || [];\n codecs[mediaType].push(translateLegacyCodec(\"\" + type + details));\n });\n Object.keys(codecs).forEach(function (mediaType) {\n if (codecs[mediaType].length > 1) {\n logFn$1(\"multiple \" + mediaType + \" codecs found as attributes: \" + codecs[mediaType].join(', ') + \". Setting playlist codecs to null so that we wait for mux.js to probe segments for real codecs.\");\n codecs[mediaType] = null;\n return;\n }\n\n codecs[mediaType] = codecs[mediaType][0];\n });\n return codecs;\n};\nvar codecCount = function codecCount(codecObj) {\n var count = 0;\n\n if (codecObj.audio) {\n count++;\n }\n\n if (codecObj.video) {\n count++;\n }\n\n return count;\n};\n/**\n * Calculates the codec strings for a working configuration of\n * SourceBuffers to play variant streams in a master playlist. If\n * there is no possible working configuration, an empty object will be\n * returned.\n *\n * @param master {Object} the m3u8 object for the master playlist\n * @param media {Object} the m3u8 object for the variant playlist\n * @return {Object} the codec strings.\n *\n * @private\n */\n\nvar codecsForPlaylist = function codecsForPlaylist(master, media) {\n var mediaAttributes = media.attributes || {};\n var codecInfo = unwrapCodecList(getCodecs(media) || []); // HLS with multiple-audio tracks must always get an audio codec.\n // Put another way, there is no way to have a video-only multiple-audio HLS!\n\n if (isMaat(master, media) && !codecInfo.audio) {\n if (!isMuxed(master, media)) {\n // It is possible for codecs to be specified on the audio media group playlist but\n // not on the rendition playlist. This is mostly the case for DASH, where audio and\n // video are always separate (and separately specified).\n var defaultCodecs = unwrapCodecList(codecsFromDefault(master, mediaAttributes.AUDIO) || []);\n\n if (defaultCodecs.audio) {\n codecInfo.audio = defaultCodecs.audio;\n }\n }\n }\n\n return codecInfo;\n};\n\nvar logFn = logger('PlaylistSelector');\n\nvar representationToString = function representationToString(representation) {\n if (!representation || !representation.playlist) {\n return;\n }\n\n var playlist = representation.playlist;\n return JSON.stringify({\n id: playlist.id,\n bandwidth: representation.bandwidth,\n width: representation.width,\n height: representation.height,\n codecs: playlist.attributes && playlist.attributes.CODECS || ''\n });\n}; // Utilities\n\n/**\n * Returns the CSS value for the specified property on an element\n * using `getComputedStyle`. Firefox has a long-standing issue where\n * getComputedStyle() may return null when running in an iframe with\n * `display: none`.\n *\n * @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n * @param {HTMLElement} el the htmlelement to work on\n * @param {string} the proprety to get the style for\n */\n\n\nvar safeGetComputedStyle = function safeGetComputedStyle(el, property) {\n if (!el) {\n return '';\n }\n\n var result = window$1.getComputedStyle(el);\n\n if (!result) {\n return '';\n }\n\n return result[property];\n};\n/**\n * Resuable stable sort function\n *\n * @param {Playlists} array\n * @param {Function} sortFn Different comparators\n * @function stableSort\n */\n\n\nvar stableSort = function stableSort(array, sortFn) {\n var newArray = array.slice();\n array.sort(function (left, right) {\n var cmp = sortFn(left, right);\n\n if (cmp === 0) {\n return newArray.indexOf(left) - newArray.indexOf(right);\n }\n\n return cmp;\n });\n};\n/**\n * A comparator function to sort two playlist object by bandwidth.\n *\n * @param {Object} left a media playlist object\n * @param {Object} right a media playlist object\n * @return {number} Greater than zero if the bandwidth attribute of\n * left is greater than the corresponding attribute of right. Less\n * than zero if the bandwidth of right is greater than left and\n * exactly zero if the two are equal.\n */\n\n\nvar comparePlaylistBandwidth = function comparePlaylistBandwidth(left, right) {\n var leftBandwidth;\n var rightBandwidth;\n\n if (left.attributes.BANDWIDTH) {\n leftBandwidth = left.attributes.BANDWIDTH;\n }\n\n leftBandwidth = leftBandwidth || window$1.Number.MAX_VALUE;\n\n if (right.attributes.BANDWIDTH) {\n rightBandwidth = right.attributes.BANDWIDTH;\n }\n\n rightBandwidth = rightBandwidth || window$1.Number.MAX_VALUE;\n return leftBandwidth - rightBandwidth;\n};\n/**\n * A comparator function to sort two playlist object by resolution (width).\n *\n * @param {Object} left a media playlist object\n * @param {Object} right a media playlist object\n * @return {number} Greater than zero if the resolution.width attribute of\n * left is greater than the corresponding attribute of right. Less\n * than zero if the resolution.width of right is greater than left and\n * exactly zero if the two are equal.\n */\n\nvar comparePlaylistResolution = function comparePlaylistResolution(left, right) {\n var leftWidth;\n var rightWidth;\n\n if (left.attributes.RESOLUTION && left.attributes.RESOLUTION.width) {\n leftWidth = left.attributes.RESOLUTION.width;\n }\n\n leftWidth = leftWidth || window$1.Number.MAX_VALUE;\n\n if (right.attributes.RESOLUTION && right.attributes.RESOLUTION.width) {\n rightWidth = right.attributes.RESOLUTION.width;\n }\n\n rightWidth = rightWidth || window$1.Number.MAX_VALUE; // NOTE - Fallback to bandwidth sort as appropriate in cases where multiple renditions\n // have the same media dimensions/ resolution\n\n if (leftWidth === rightWidth && left.attributes.BANDWIDTH && right.attributes.BANDWIDTH) {\n return left.attributes.BANDWIDTH - right.attributes.BANDWIDTH;\n }\n\n return leftWidth - rightWidth;\n};\n/**\n * Chooses the appropriate media playlist based on bandwidth and player size\n *\n * @param {Object} master\n * Object representation of the master manifest\n * @param {number} playerBandwidth\n * Current calculated bandwidth of the player\n * @param {number} playerWidth\n * Current width of the player element (should account for the device pixel ratio)\n * @param {number} playerHeight\n * Current height of the player element (should account for the device pixel ratio)\n * @param {boolean} limitRenditionByPlayerDimensions\n * True if the player width and height should be used during the selection, false otherwise\n * @param {Object} masterPlaylistController\n * the current masterPlaylistController object\n * @return {Playlist} the highest bitrate playlist less than the\n * currently detected bandwidth, accounting for some amount of\n * bandwidth variance\n */\n\nvar simpleSelector = function simpleSelector(master, playerBandwidth, playerWidth, playerHeight, limitRenditionByPlayerDimensions, masterPlaylistController) {\n // If we end up getting called before `master` is available, exit early\n if (!master) {\n return;\n }\n\n var options = {\n bandwidth: playerBandwidth,\n width: playerWidth,\n height: playerHeight,\n limitRenditionByPlayerDimensions: limitRenditionByPlayerDimensions\n };\n var playlists = master.playlists; // if playlist is audio only, select between currently active audio group playlists.\n\n if (Playlist.isAudioOnly(master)) {\n playlists = masterPlaylistController.getAudioTrackPlaylists_(); // add audioOnly to options so that we log audioOnly: true\n // at the buttom of this function for debugging.\n\n options.audioOnly = true;\n } // convert the playlists to an intermediary representation to make comparisons easier\n\n\n var sortedPlaylistReps = playlists.map(function (playlist) {\n var bandwidth;\n var width = playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.width;\n var height = playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height;\n bandwidth = playlist.attributes && playlist.attributes.BANDWIDTH;\n bandwidth = bandwidth || window$1.Number.MAX_VALUE;\n return {\n bandwidth: bandwidth,\n width: width,\n height: height,\n playlist: playlist\n };\n });\n stableSort(sortedPlaylistReps, function (left, right) {\n return left.bandwidth - right.bandwidth;\n }); // filter out any playlists that have been excluded due to\n // incompatible configurations\n\n sortedPlaylistReps = sortedPlaylistReps.filter(function (rep) {\n return !Playlist.isIncompatible(rep.playlist);\n }); // filter out any playlists that have been disabled manually through the representations\n // api or blacklisted temporarily due to playback errors.\n\n var enabledPlaylistReps = sortedPlaylistReps.filter(function (rep) {\n return Playlist.isEnabled(rep.playlist);\n });\n\n if (!enabledPlaylistReps.length) {\n // if there are no enabled playlists, then they have all been blacklisted or disabled\n // by the user through the representations api. In this case, ignore blacklisting and\n // fallback to what the user wants by using playlists the user has not disabled.\n enabledPlaylistReps = sortedPlaylistReps.filter(function (rep) {\n return !Playlist.isDisabled(rep.playlist);\n });\n } // filter out any variant that has greater effective bitrate\n // than the current estimated bandwidth\n\n\n var bandwidthPlaylistReps = enabledPlaylistReps.filter(function (rep) {\n return rep.bandwidth * Config.BANDWIDTH_VARIANCE < playerBandwidth;\n });\n var highestRemainingBandwidthRep = bandwidthPlaylistReps[bandwidthPlaylistReps.length - 1]; // get all of the renditions with the same (highest) bandwidth\n // and then taking the very first element\n\n var bandwidthBestRep = bandwidthPlaylistReps.filter(function (rep) {\n return rep.bandwidth === highestRemainingBandwidthRep.bandwidth;\n })[0]; // if we're not going to limit renditions by player size, make an early decision.\n\n if (limitRenditionByPlayerDimensions === false) {\n var _chosenRep = bandwidthBestRep || enabledPlaylistReps[0] || sortedPlaylistReps[0];\n\n if (_chosenRep && _chosenRep.playlist) {\n var type = 'sortedPlaylistReps';\n\n if (bandwidthBestRep) {\n type = 'bandwidthBestRep';\n }\n\n if (enabledPlaylistReps[0]) {\n type = 'enabledPlaylistReps';\n }\n\n logFn(\"choosing \" + representationToString(_chosenRep) + \" using \" + type + \" with options\", options);\n return _chosenRep.playlist;\n }\n\n logFn('could not choose a playlist with options', options);\n return null;\n } // filter out playlists without resolution information\n\n\n var haveResolution = bandwidthPlaylistReps.filter(function (rep) {\n return rep.width && rep.height;\n }); // sort variants by resolution\n\n stableSort(haveResolution, function (left, right) {\n return left.width - right.width;\n }); // if we have the exact resolution as the player use it\n\n var resolutionBestRepList = haveResolution.filter(function (rep) {\n return rep.width === playerWidth && rep.height === playerHeight;\n });\n highestRemainingBandwidthRep = resolutionBestRepList[resolutionBestRepList.length - 1]; // ensure that we pick the highest bandwidth variant that have exact resolution\n\n var resolutionBestRep = resolutionBestRepList.filter(function (rep) {\n return rep.bandwidth === highestRemainingBandwidthRep.bandwidth;\n })[0];\n var resolutionPlusOneList;\n var resolutionPlusOneSmallest;\n var resolutionPlusOneRep; // find the smallest variant that is larger than the player\n // if there is no match of exact resolution\n\n if (!resolutionBestRep) {\n resolutionPlusOneList = haveResolution.filter(function (rep) {\n return rep.width > playerWidth || rep.height > playerHeight;\n }); // find all the variants have the same smallest resolution\n\n resolutionPlusOneSmallest = resolutionPlusOneList.filter(function (rep) {\n return rep.width === resolutionPlusOneList[0].width && rep.height === resolutionPlusOneList[0].height;\n }); // ensure that we also pick the highest bandwidth variant that\n // is just-larger-than the video player\n\n highestRemainingBandwidthRep = resolutionPlusOneSmallest[resolutionPlusOneSmallest.length - 1];\n resolutionPlusOneRep = resolutionPlusOneSmallest.filter(function (rep) {\n return rep.bandwidth === highestRemainingBandwidthRep.bandwidth;\n })[0];\n }\n\n var leastPixelDiffRep; // If this selector proves to be better than others,\n // resolutionPlusOneRep and resolutionBestRep and all\n // the code involving them should be removed.\n\n if (masterPlaylistController.experimentalLeastPixelDiffSelector) {\n // find the variant that is closest to the player's pixel size\n var leastPixelDiffList = haveResolution.map(function (rep) {\n rep.pixelDiff = Math.abs(rep.width - playerWidth) + Math.abs(rep.height - playerHeight);\n return rep;\n }); // get the highest bandwidth, closest resolution playlist\n\n stableSort(leastPixelDiffList, function (left, right) {\n // sort by highest bandwidth if pixelDiff is the same\n if (left.pixelDiff === right.pixelDiff) {\n return right.bandwidth - left.bandwidth;\n }\n\n return left.pixelDiff - right.pixelDiff;\n });\n leastPixelDiffRep = leastPixelDiffList[0];\n } // fallback chain of variants\n\n\n var chosenRep = leastPixelDiffRep || resolutionPlusOneRep || resolutionBestRep || bandwidthBestRep || enabledPlaylistReps[0] || sortedPlaylistReps[0];\n\n if (chosenRep && chosenRep.playlist) {\n var _type = 'sortedPlaylistReps';\n\n if (leastPixelDiffRep) {\n _type = 'leastPixelDiffRep';\n } else if (resolutionPlusOneRep) {\n _type = 'resolutionPlusOneRep';\n } else if (resolutionBestRep) {\n _type = 'resolutionBestRep';\n } else if (bandwidthBestRep) {\n _type = 'bandwidthBestRep';\n } else if (enabledPlaylistReps[0]) {\n _type = 'enabledPlaylistReps';\n }\n\n logFn(\"choosing \" + representationToString(chosenRep) + \" using \" + _type + \" with options\", options);\n return chosenRep.playlist;\n }\n\n logFn('could not choose a playlist with options', options);\n return null;\n};\n\n/**\n * Chooses the appropriate media playlist based on the most recent\n * bandwidth estimate and the player size.\n *\n * Expects to be called within the context of an instance of VhsHandler\n *\n * @return {Playlist} the highest bitrate playlist less than the\n * currently detected bandwidth, accounting for some amount of\n * bandwidth variance\n */\n\nvar lastBandwidthSelector = function lastBandwidthSelector() {\n var pixelRatio = this.useDevicePixelRatio ? window$1.devicePixelRatio || 1 : 1;\n return simpleSelector(this.playlists.master, this.systemBandwidth, parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio, parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio, this.limitRenditionByPlayerDimensions, this.masterPlaylistController_);\n};\n/**\n * Chooses the appropriate media playlist based on an\n * exponential-weighted moving average of the bandwidth after\n * filtering for player size.\n *\n * Expects to be called within the context of an instance of VhsHandler\n *\n * @param {number} decay - a number between 0 and 1. Higher values of\n * this parameter will cause previous bandwidth estimates to lose\n * significance more quickly.\n * @return {Function} a function which can be invoked to create a new\n * playlist selector function.\n * @see https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n */\n\nvar movingAverageBandwidthSelector = function movingAverageBandwidthSelector(decay) {\n var average = -1;\n var lastSystemBandwidth = -1;\n\n if (decay < 0 || decay > 1) {\n throw new Error('Moving average bandwidth decay must be between 0 and 1.');\n }\n\n return function () {\n var pixelRatio = this.useDevicePixelRatio ? window$1.devicePixelRatio || 1 : 1;\n\n if (average < 0) {\n average = this.systemBandwidth;\n lastSystemBandwidth = this.systemBandwidth;\n } // stop the average value from decaying for every 250ms\n // when the systemBandwidth is constant\n // and\n // stop average from setting to a very low value when the\n // systemBandwidth becomes 0 in case of chunk cancellation\n\n\n if (this.systemBandwidth > 0 && this.systemBandwidth !== lastSystemBandwidth) {\n average = decay * this.systemBandwidth + (1 - decay) * average;\n lastSystemBandwidth = this.systemBandwidth;\n }\n\n return simpleSelector(this.playlists.master, average, parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio, parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio, this.limitRenditionByPlayerDimensions, this.masterPlaylistController_);\n };\n};\n/**\n * Chooses the appropriate media playlist based on the potential to rebuffer\n *\n * @param {Object} settings\n * Object of information required to use this selector\n * @param {Object} settings.master\n * Object representation of the master manifest\n * @param {number} settings.currentTime\n * The current time of the player\n * @param {number} settings.bandwidth\n * Current measured bandwidth\n * @param {number} settings.duration\n * Duration of the media\n * @param {number} settings.segmentDuration\n * Segment duration to be used in round trip time calculations\n * @param {number} settings.timeUntilRebuffer\n * Time left in seconds until the player has to rebuffer\n * @param {number} settings.currentTimeline\n * The current timeline segments are being loaded from\n * @param {SyncController} settings.syncController\n * SyncController for determining if we have a sync point for a given playlist\n * @return {Object|null}\n * {Object} return.playlist\n * The highest bandwidth playlist with the least amount of rebuffering\n * {Number} return.rebufferingImpact\n * The amount of time in seconds switching to this playlist will rebuffer. A\n * negative value means that switching will cause zero rebuffering.\n */\n\nvar minRebufferMaxBandwidthSelector = function minRebufferMaxBandwidthSelector(settings) {\n var master = settings.master,\n currentTime = settings.currentTime,\n bandwidth = settings.bandwidth,\n duration = settings.duration,\n segmentDuration = settings.segmentDuration,\n timeUntilRebuffer = settings.timeUntilRebuffer,\n currentTimeline = settings.currentTimeline,\n syncController = settings.syncController; // filter out any playlists that have been excluded due to\n // incompatible configurations\n\n var compatiblePlaylists = master.playlists.filter(function (playlist) {\n return !Playlist.isIncompatible(playlist);\n }); // filter out any playlists that have been disabled manually through the representations\n // api or blacklisted temporarily due to playback errors.\n\n var enabledPlaylists = compatiblePlaylists.filter(Playlist.isEnabled);\n\n if (!enabledPlaylists.length) {\n // if there are no enabled playlists, then they have all been blacklisted or disabled\n // by the user through the representations api. In this case, ignore blacklisting and\n // fallback to what the user wants by using playlists the user has not disabled.\n enabledPlaylists = compatiblePlaylists.filter(function (playlist) {\n return !Playlist.isDisabled(playlist);\n });\n }\n\n var bandwidthPlaylists = enabledPlaylists.filter(Playlist.hasAttribute.bind(null, 'BANDWIDTH'));\n var rebufferingEstimates = bandwidthPlaylists.map(function (playlist) {\n var syncPoint = syncController.getSyncPoint(playlist, duration, currentTimeline, currentTime); // If there is no sync point for this playlist, switching to it will require a\n // sync request first. This will double the request time\n\n var numRequests = syncPoint ? 1 : 2;\n var requestTimeEstimate = Playlist.estimateSegmentRequestTime(segmentDuration, bandwidth, playlist);\n var rebufferingImpact = requestTimeEstimate * numRequests - timeUntilRebuffer;\n return {\n playlist: playlist,\n rebufferingImpact: rebufferingImpact\n };\n });\n var noRebufferingPlaylists = rebufferingEstimates.filter(function (estimate) {\n return estimate.rebufferingImpact <= 0;\n }); // Sort by bandwidth DESC\n\n stableSort(noRebufferingPlaylists, function (a, b) {\n return comparePlaylistBandwidth(b.playlist, a.playlist);\n });\n\n if (noRebufferingPlaylists.length) {\n return noRebufferingPlaylists[0];\n }\n\n stableSort(rebufferingEstimates, function (a, b) {\n return a.rebufferingImpact - b.rebufferingImpact;\n });\n return rebufferingEstimates[0] || null;\n};\n/**\n * Chooses the appropriate media playlist, which in this case is the lowest bitrate\n * one with video. If no renditions with video exist, return the lowest audio rendition.\n *\n * Expects to be called within the context of an instance of VhsHandler\n *\n * @return {Object|null}\n * {Object} return.playlist\n * The lowest bitrate playlist that contains a video codec. If no such rendition\n * exists pick the lowest audio rendition.\n */\n\nvar lowestBitrateCompatibleVariantSelector = function lowestBitrateCompatibleVariantSelector() {\n var _this = this;\n\n // filter out any playlists that have been excluded due to\n // incompatible configurations or playback errors\n var playlists = this.playlists.master.playlists.filter(Playlist.isEnabled); // Sort ascending by bitrate\n\n stableSort(playlists, function (a, b) {\n return comparePlaylistBandwidth(a, b);\n }); // Parse and assume that playlists with no video codec have no video\n // (this is not necessarily true, although it is generally true).\n //\n // If an entire manifest has no valid videos everything will get filtered\n // out.\n\n var playlistsWithVideo = playlists.filter(function (playlist) {\n return !!codecsForPlaylist(_this.playlists.master, playlist).video;\n });\n return playlistsWithVideo[0] || null;\n};\n\n/**\n * Combine all segments into a single Uint8Array\n *\n * @param {Object} segmentObj\n * @return {Uint8Array} concatenated bytes\n * @private\n */\nvar concatSegments = function concatSegments(segmentObj) {\n var offset = 0;\n var tempBuffer;\n\n if (segmentObj.bytes) {\n tempBuffer = new Uint8Array(segmentObj.bytes); // combine the individual segments into one large typed-array\n\n segmentObj.segments.forEach(function (segment) {\n tempBuffer.set(segment, offset);\n offset += segment.byteLength;\n });\n }\n\n return tempBuffer;\n};\n\n/**\n * @file text-tracks.js\n */\n/**\n * Create captions text tracks on video.js if they do not exist\n *\n * @param {Object} inbandTextTracks a reference to current inbandTextTracks\n * @param {Object} tech the video.js tech\n * @param {Object} captionStream the caption stream to create\n * @private\n */\n\nvar createCaptionsTrackIfNotExists = function createCaptionsTrackIfNotExists(inbandTextTracks, tech, captionStream) {\n if (!inbandTextTracks[captionStream]) {\n tech.trigger({\n type: 'usage',\n name: 'vhs-608'\n });\n tech.trigger({\n type: 'usage',\n name: 'hls-608'\n });\n var instreamId = captionStream; // we need to translate SERVICEn for 708 to how mux.js currently labels them\n\n if (/^cc708_/.test(captionStream)) {\n instreamId = 'SERVICE' + captionStream.split('_')[1];\n }\n\n var track = tech.textTracks().getTrackById(instreamId);\n\n if (track) {\n // Resuse an existing track with a CC# id because this was\n // very likely created by videojs-contrib-hls from information\n // in the m3u8 for us to use\n inbandTextTracks[captionStream] = track;\n } else {\n // This section gets called when we have caption services that aren't specified in the manifest.\n // Manifest level caption services are handled in media-groups.js under CLOSED-CAPTIONS.\n var captionServices = tech.options_.vhs && tech.options_.vhs.captionServices || {};\n var label = captionStream;\n var language = captionStream;\n var def = false;\n var captionService = captionServices[instreamId];\n\n if (captionService) {\n label = captionService.label;\n language = captionService.language;\n def = captionService.default;\n } // Otherwise, create a track with the default `CC#` label and\n // without a language\n\n\n inbandTextTracks[captionStream] = tech.addRemoteTextTrack({\n kind: 'captions',\n id: instreamId,\n // TODO: investigate why this doesn't seem to turn the caption on by default\n default: def,\n label: label,\n language: language\n }, false).track;\n }\n }\n};\n/**\n * Add caption text track data to a source handler given an array of captions\n *\n * @param {Object}\n * @param {Object} inbandTextTracks the inband text tracks\n * @param {number} timestampOffset the timestamp offset of the source buffer\n * @param {Array} captionArray an array of caption data\n * @private\n */\n\nvar addCaptionData = function addCaptionData(_ref) {\n var inbandTextTracks = _ref.inbandTextTracks,\n captionArray = _ref.captionArray,\n timestampOffset = _ref.timestampOffset;\n\n if (!captionArray) {\n return;\n }\n\n var Cue = window$1.WebKitDataCue || window$1.VTTCue;\n captionArray.forEach(function (caption) {\n var track = caption.stream;\n inbandTextTracks[track].addCue(new Cue(caption.startTime + timestampOffset, caption.endTime + timestampOffset, caption.text));\n });\n};\n/**\n * Define properties on a cue for backwards compatability,\n * but warn the user that the way that they are using it\n * is depricated and will be removed at a later date.\n *\n * @param {Cue} cue the cue to add the properties on\n * @private\n */\n\nvar deprecateOldCue = function deprecateOldCue(cue) {\n Object.defineProperties(cue.frame, {\n id: {\n get: function get() {\n videojs.log.warn('cue.frame.id is deprecated. Use cue.value.key instead.');\n return cue.value.key;\n }\n },\n value: {\n get: function get() {\n videojs.log.warn('cue.frame.value is deprecated. Use cue.value.data instead.');\n return cue.value.data;\n }\n },\n privateData: {\n get: function get() {\n videojs.log.warn('cue.frame.privateData is deprecated. Use cue.value.data instead.');\n return cue.value.data;\n }\n }\n });\n};\n/**\n * Add metadata text track data to a source handler given an array of metadata\n *\n * @param {Object}\n * @param {Object} inbandTextTracks the inband text tracks\n * @param {Array} metadataArray an array of meta data\n * @param {number} timestampOffset the timestamp offset of the source buffer\n * @param {number} videoDuration the duration of the video\n * @private\n */\n\n\nvar addMetadata = function addMetadata(_ref2) {\n var inbandTextTracks = _ref2.inbandTextTracks,\n metadataArray = _ref2.metadataArray,\n timestampOffset = _ref2.timestampOffset,\n videoDuration = _ref2.videoDuration;\n\n if (!metadataArray) {\n return;\n }\n\n var Cue = window$1.WebKitDataCue || window$1.VTTCue;\n var metadataTrack = inbandTextTracks.metadataTrack_;\n\n if (!metadataTrack) {\n return;\n }\n\n metadataArray.forEach(function (metadata) {\n var time = metadata.cueTime + timestampOffset; // if time isn't a finite number between 0 and Infinity, like NaN,\n // ignore this bit of metadata.\n // This likely occurs when you have an non-timed ID3 tag like TIT2,\n // which is the \"Title/Songname/Content description\" frame\n\n if (typeof time !== 'number' || window$1.isNaN(time) || time < 0 || !(time < Infinity)) {\n return;\n }\n\n metadata.frames.forEach(function (frame) {\n var cue = new Cue(time, time, frame.value || frame.url || frame.data || '');\n cue.frame = frame;\n cue.value = frame;\n deprecateOldCue(cue);\n metadataTrack.addCue(cue);\n });\n });\n\n if (!metadataTrack.cues || !metadataTrack.cues.length) {\n return;\n } // Updating the metadeta cues so that\n // the endTime of each cue is the startTime of the next cue\n // the endTime of last cue is the duration of the video\n\n\n var cues = metadataTrack.cues;\n var cuesArray = []; // Create a copy of the TextTrackCueList...\n // ...disregarding cues with a falsey value\n\n for (var i = 0; i < cues.length; i++) {\n if (cues[i]) {\n cuesArray.push(cues[i]);\n }\n } // Group cues by their startTime value\n\n\n var cuesGroupedByStartTime = cuesArray.reduce(function (obj, cue) {\n var timeSlot = obj[cue.startTime] || [];\n timeSlot.push(cue);\n obj[cue.startTime] = timeSlot;\n return obj;\n }, {}); // Sort startTimes by ascending order\n\n var sortedStartTimes = Object.keys(cuesGroupedByStartTime).sort(function (a, b) {\n return Number(a) - Number(b);\n }); // Map each cue group's endTime to the next group's startTime\n\n sortedStartTimes.forEach(function (startTime, idx) {\n var cueGroup = cuesGroupedByStartTime[startTime];\n var nextTime = Number(sortedStartTimes[idx + 1]) || videoDuration; // Map each cue's endTime the next group's startTime\n\n cueGroup.forEach(function (cue) {\n cue.endTime = nextTime;\n });\n });\n};\n/**\n * Create metadata text track on video.js if it does not exist\n *\n * @param {Object} inbandTextTracks a reference to current inbandTextTracks\n * @param {string} dispatchType the inband metadata track dispatch type\n * @param {Object} tech the video.js tech\n * @private\n */\n\nvar createMetadataTrackIfNotExists = function createMetadataTrackIfNotExists(inbandTextTracks, dispatchType, tech) {\n if (inbandTextTracks.metadataTrack_) {\n return;\n }\n\n inbandTextTracks.metadataTrack_ = tech.addRemoteTextTrack({\n kind: 'metadata',\n label: 'Timed Metadata'\n }, false).track;\n inbandTextTracks.metadataTrack_.inBandMetadataTrackDispatchType = dispatchType;\n};\n/**\n * Remove cues from a track on video.js.\n *\n * @param {Double} start start of where we should remove the cue\n * @param {Double} end end of where the we should remove the cue\n * @param {Object} track the text track to remove the cues from\n * @private\n */\n\nvar removeCuesFromTrack = function removeCuesFromTrack(start, end, track) {\n var i;\n var cue;\n\n if (!track) {\n return;\n }\n\n if (!track.cues) {\n return;\n }\n\n i = track.cues.length;\n\n while (i--) {\n cue = track.cues[i]; // Remove any cue within the provided start and end time\n\n if (cue.startTime >= start && cue.endTime <= end) {\n track.removeCue(cue);\n }\n }\n};\n/**\n * Remove duplicate cues from a track on video.js (a cue is considered a\n * duplicate if it has the same time interval and text as another)\n *\n * @param {Object} track the text track to remove the duplicate cues from\n * @private\n */\n\nvar removeDuplicateCuesFromTrack = function removeDuplicateCuesFromTrack(track) {\n var cues = track.cues;\n\n if (!cues) {\n return;\n }\n\n for (var i = 0; i < cues.length; i++) {\n var duplicates = [];\n var occurrences = 0;\n\n for (var j = 0; j < cues.length; j++) {\n if (cues[i].startTime === cues[j].startTime && cues[i].endTime === cues[j].endTime && cues[i].text === cues[j].text) {\n occurrences++;\n\n if (occurrences > 1) {\n duplicates.push(cues[j]);\n }\n }\n }\n\n if (duplicates.length) {\n duplicates.forEach(function (dupe) {\n return track.removeCue(dupe);\n });\n }\n }\n};\n\n/**\n * Returns a list of gops in the buffer that have a pts value of 3 seconds or more in\n * front of current time.\n *\n * @param {Array} buffer\n * The current buffer of gop information\n * @param {number} currentTime\n * The current time\n * @param {Double} mapping\n * Offset to map display time to stream presentation time\n * @return {Array}\n * List of gops considered safe to append over\n */\n\nvar gopsSafeToAlignWith = function gopsSafeToAlignWith(buffer, currentTime, mapping) {\n if (typeof currentTime === 'undefined' || currentTime === null || !buffer.length) {\n return [];\n } // pts value for current time + 3 seconds to give a bit more wiggle room\n\n\n var currentTimePts = Math.ceil((currentTime - mapping + 3) * ONE_SECOND_IN_TS);\n var i;\n\n for (i = 0; i < buffer.length; i++) {\n if (buffer[i].pts > currentTimePts) {\n break;\n }\n }\n\n return buffer.slice(i);\n};\n/**\n * Appends gop information (timing and byteLength) received by the transmuxer for the\n * gops appended in the last call to appendBuffer\n *\n * @param {Array} buffer\n * The current buffer of gop information\n * @param {Array} gops\n * List of new gop information\n * @param {boolean} replace\n * If true, replace the buffer with the new gop information. If false, append the\n * new gop information to the buffer in the right location of time.\n * @return {Array}\n * Updated list of gop information\n */\n\nvar updateGopBuffer = function updateGopBuffer(buffer, gops, replace) {\n if (!gops.length) {\n return buffer;\n }\n\n if (replace) {\n // If we are in safe append mode, then completely overwrite the gop buffer\n // with the most recent appeneded data. This will make sure that when appending\n // future segments, we only try to align with gops that are both ahead of current\n // time and in the last segment appended.\n return gops.slice();\n }\n\n var start = gops[0].pts;\n var i = 0;\n\n for (i; i < buffer.length; i++) {\n if (buffer[i].pts >= start) {\n break;\n }\n }\n\n return buffer.slice(0, i).concat(gops);\n};\n/**\n * Removes gop information in buffer that overlaps with provided start and end\n *\n * @param {Array} buffer\n * The current buffer of gop information\n * @param {Double} start\n * position to start the remove at\n * @param {Double} end\n * position to end the remove at\n * @param {Double} mapping\n * Offset to map display time to stream presentation time\n */\n\nvar removeGopBuffer = function removeGopBuffer(buffer, start, end, mapping) {\n var startPts = Math.ceil((start - mapping) * ONE_SECOND_IN_TS);\n var endPts = Math.ceil((end - mapping) * ONE_SECOND_IN_TS);\n var updatedBuffer = buffer.slice();\n var i = buffer.length;\n\n while (i--) {\n if (buffer[i].pts <= endPts) {\n break;\n }\n }\n\n if (i === -1) {\n // no removal because end of remove range is before start of buffer\n return updatedBuffer;\n }\n\n var j = i + 1;\n\n while (j--) {\n if (buffer[j].pts <= startPts) {\n break;\n }\n } // clamp remove range start to 0 index\n\n\n j = Math.max(j, 0);\n updatedBuffer.splice(j, i - j + 1);\n return updatedBuffer;\n};\n\nvar shallowEqual = function shallowEqual(a, b) {\n // if both are undefined\n // or one or the other is undefined\n // they are not equal\n if (!a && !b || !a && b || a && !b) {\n return false;\n } // they are the same object and thus, equal\n\n\n if (a === b) {\n return true;\n } // sort keys so we can make sure they have\n // all the same keys later.\n\n\n var akeys = Object.keys(a).sort();\n var bkeys = Object.keys(b).sort(); // different number of keys, not equal\n\n if (akeys.length !== bkeys.length) {\n return false;\n }\n\n for (var i = 0; i < akeys.length; i++) {\n var key = akeys[i]; // different sorted keys, not equal\n\n if (key !== bkeys[i]) {\n return false;\n } // different values, not equal\n\n\n if (a[key] !== b[key]) {\n return false;\n }\n }\n\n return true;\n};\n\n// https://www.w3.org/TR/WebIDL-1/#quotaexceedederror\nvar QUOTA_EXCEEDED_ERR = 22;\n\n/**\n * The segment loader has no recourse except to fetch a segment in the\n * current playlist and use the internal timestamps in that segment to\n * generate a syncPoint. This function returns a good candidate index\n * for that process.\n *\n * @param {Array} segments - the segments array from a playlist.\n * @return {number} An index of a segment from the playlist to load\n */\n\nvar getSyncSegmentCandidate = function getSyncSegmentCandidate(currentTimeline, segments, targetTime) {\n segments = segments || [];\n var timelineSegments = [];\n var time = 0;\n\n for (var i = 0; i < segments.length; i++) {\n var segment = segments[i];\n\n if (currentTimeline === segment.timeline) {\n timelineSegments.push(i);\n time += segment.duration;\n\n if (time > targetTime) {\n return i;\n }\n }\n }\n\n if (timelineSegments.length === 0) {\n return 0;\n } // default to the last timeline segment\n\n\n return timelineSegments[timelineSegments.length - 1];\n}; // In the event of a quota exceeded error, keep at least one second of back buffer. This\n// number was arbitrarily chosen and may be updated in the future, but seemed reasonable\n// as a start to prevent any potential issues with removing content too close to the\n// playhead.\n\nvar MIN_BACK_BUFFER = 1; // in ms\n\nvar CHECK_BUFFER_DELAY = 500;\n\nvar finite = function finite(num) {\n return typeof num === 'number' && isFinite(num);\n}; // With most content hovering around 30fps, if a segment has a duration less than a half\n// frame at 30fps or one frame at 60fps, the bandwidth and throughput calculations will\n// not accurately reflect the rest of the content.\n\n\nvar MIN_SEGMENT_DURATION_TO_SAVE_STATS = 1 / 60;\nvar illegalMediaSwitch = function illegalMediaSwitch(loaderType, startingMedia, trackInfo) {\n // Although these checks should most likely cover non 'main' types, for now it narrows\n // the scope of our checks.\n if (loaderType !== 'main' || !startingMedia || !trackInfo) {\n return null;\n }\n\n if (!trackInfo.hasAudio && !trackInfo.hasVideo) {\n return 'Neither audio nor video found in segment.';\n }\n\n if (startingMedia.hasVideo && !trackInfo.hasVideo) {\n return 'Only audio found in segment when we expected video.' + ' We can\\'t switch to audio only from a stream that had video.' + ' To get rid of this message, please add codec information to the manifest.';\n }\n\n if (!startingMedia.hasVideo && trackInfo.hasVideo) {\n return 'Video found in segment when we expected only audio.' + ' We can\\'t switch to a stream with video from an audio only stream.' + ' To get rid of this message, please add codec information to the manifest.';\n }\n\n return null;\n};\n/**\n * Calculates a time value that is safe to remove from the back buffer without interrupting\n * playback.\n *\n * @param {TimeRange} seekable\n * The current seekable range\n * @param {number} currentTime\n * The current time of the player\n * @param {number} targetDuration\n * The target duration of the current playlist\n * @return {number}\n * Time that is safe to remove from the back buffer without interrupting playback\n */\n\nvar safeBackBufferTrimTime = function safeBackBufferTrimTime(seekable, currentTime, targetDuration) {\n // 30 seconds before the playhead provides a safe default for trimming.\n //\n // Choosing a reasonable default is particularly important for high bitrate content and\n // VOD videos/live streams with large windows, as the buffer may end up overfilled and\n // throw an APPEND_BUFFER_ERR.\n var trimTime = currentTime - Config.BACK_BUFFER_LENGTH;\n\n if (seekable.length) {\n // Some live playlists may have a shorter window of content than the full allowed back\n // buffer. For these playlists, don't save content that's no longer within the window.\n trimTime = Math.max(trimTime, seekable.start(0));\n } // Don't remove within target duration of the current time to avoid the possibility of\n // removing the GOP currently being played, as removing it can cause playback stalls.\n\n\n var maxTrimTime = currentTime - targetDuration;\n return Math.min(maxTrimTime, trimTime);\n};\nvar segmentInfoString = function segmentInfoString(segmentInfo) {\n var startOfSegment = segmentInfo.startOfSegment,\n duration = segmentInfo.duration,\n segment = segmentInfo.segment,\n part = segmentInfo.part,\n _segmentInfo$playlist = segmentInfo.playlist,\n seq = _segmentInfo$playlist.mediaSequence,\n id = _segmentInfo$playlist.id,\n _segmentInfo$playlist2 = _segmentInfo$playlist.segments,\n segments = _segmentInfo$playlist2 === void 0 ? [] : _segmentInfo$playlist2,\n index = segmentInfo.mediaIndex,\n partIndex = segmentInfo.partIndex,\n timeline = segmentInfo.timeline;\n var segmentLen = segments.length - 1;\n var selection = 'mediaIndex/partIndex increment';\n\n if (segmentInfo.getMediaInfoForTime) {\n selection = \"getMediaInfoForTime (\" + segmentInfo.getMediaInfoForTime + \")\";\n } else if (segmentInfo.isSyncRequest) {\n selection = 'getSyncSegmentCandidate (isSyncRequest)';\n }\n\n if (segmentInfo.independent) {\n selection += \" with independent \" + segmentInfo.independent;\n }\n\n var hasPartIndex = typeof partIndex === 'number';\n var name = segmentInfo.segment.uri ? 'segment' : 'pre-segment';\n var zeroBasedPartCount = hasPartIndex ? getKnownPartCount({\n preloadSegment: segment\n }) - 1 : 0;\n return name + \" [\" + (seq + index) + \"/\" + (seq + segmentLen) + \"]\" + (hasPartIndex ? \" part [\" + partIndex + \"/\" + zeroBasedPartCount + \"]\" : '') + (\" segment start/end [\" + segment.start + \" => \" + segment.end + \"]\") + (hasPartIndex ? \" part start/end [\" + part.start + \" => \" + part.end + \"]\" : '') + (\" startOfSegment [\" + startOfSegment + \"]\") + (\" duration [\" + duration + \"]\") + (\" timeline [\" + timeline + \"]\") + (\" selected by [\" + selection + \"]\") + (\" playlist [\" + id + \"]\");\n};\n\nvar timingInfoPropertyForMedia = function timingInfoPropertyForMedia(mediaType) {\n return mediaType + \"TimingInfo\";\n};\n/**\n * Returns the timestamp offset to use for the segment.\n *\n * @param {number} segmentTimeline\n * The timeline of the segment\n * @param {number} currentTimeline\n * The timeline currently being followed by the loader\n * @param {number} startOfSegment\n * The estimated segment start\n * @param {TimeRange[]} buffered\n * The loader's buffer\n * @param {boolean} overrideCheck\n * If true, no checks are made to see if the timestamp offset value should be set,\n * but sets it directly to a value.\n *\n * @return {number|null}\n * Either a number representing a new timestamp offset, or null if the segment is\n * part of the same timeline\n */\n\n\nvar timestampOffsetForSegment = function timestampOffsetForSegment(_ref) {\n var segmentTimeline = _ref.segmentTimeline,\n currentTimeline = _ref.currentTimeline,\n startOfSegment = _ref.startOfSegment,\n buffered = _ref.buffered,\n overrideCheck = _ref.overrideCheck;\n\n // Check to see if we are crossing a discontinuity to see if we need to set the\n // timestamp offset on the transmuxer and source buffer.\n //\n // Previously, we changed the timestampOffset if the start of this segment was less than\n // the currently set timestampOffset, but this isn't desirable as it can produce bad\n // behavior, especially around long running live streams.\n if (!overrideCheck && segmentTimeline === currentTimeline) {\n return null;\n } // When changing renditions, it's possible to request a segment on an older timeline. For\n // instance, given two renditions with the following:\n //\n // #EXTINF:10\n // segment1\n // #EXT-X-DISCONTINUITY\n // #EXTINF:10\n // segment2\n // #EXTINF:10\n // segment3\n //\n // And the current player state:\n //\n // current time: 8\n // buffer: 0 => 20\n //\n // The next segment on the current rendition would be segment3, filling the buffer from\n // 20s onwards. However, if a rendition switch happens after segment2 was requested,\n // then the next segment to be requested will be segment1 from the new rendition in\n // order to fill time 8 and onwards. Using the buffered end would result in repeated\n // content (since it would position segment1 of the new rendition starting at 20s). This\n // case can be identified when the new segment's timeline is a prior value. Instead of\n // using the buffered end, the startOfSegment can be used, which, hopefully, will be\n // more accurate to the actual start time of the segment.\n\n\n if (segmentTimeline < currentTimeline) {\n return startOfSegment;\n } // segmentInfo.startOfSegment used to be used as the timestamp offset, however, that\n // value uses the end of the last segment if it is available. While this value\n // should often be correct, it's better to rely on the buffered end, as the new\n // content post discontinuity should line up with the buffered end as if it were\n // time 0 for the new content.\n\n\n return buffered.length ? buffered.end(buffered.length - 1) : startOfSegment;\n};\n/**\n * Returns whether or not the loader should wait for a timeline change from the timeline\n * change controller before processing the segment.\n *\n * Primary timing in VHS goes by video. This is different from most media players, as\n * audio is more often used as the primary timing source. For the foreseeable future, VHS\n * will continue to use video as the primary timing source, due to the current logic and\n * expectations built around it.\n\n * Since the timing follows video, in order to maintain sync, the video loader is\n * responsible for setting both audio and video source buffer timestamp offsets.\n *\n * Setting different values for audio and video source buffers could lead to\n * desyncing. The following examples demonstrate some of the situations where this\n * distinction is important. Note that all of these cases involve demuxed content. When\n * content is muxed, the audio and video are packaged together, therefore syncing\n * separate media playlists is not an issue.\n *\n * CASE 1: Audio prepares to load a new timeline before video:\n *\n * Timeline: 0 1\n * Audio Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Audio Loader: ^\n * Video Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Video Loader ^\n *\n * In the above example, the audio loader is preparing to load the 6th segment, the first\n * after a discontinuity, while the video loader is still loading the 5th segment, before\n * the discontinuity.\n *\n * If the audio loader goes ahead and loads and appends the 6th segment before the video\n * loader crosses the discontinuity, then when appended, the 6th audio segment will use\n * the timestamp offset from timeline 0. This will likely lead to desyncing. In addition,\n * the audio loader must provide the audioAppendStart value to trim the content in the\n * transmuxer, and that value relies on the audio timestamp offset. Since the audio\n * timestamp offset is set by the video (main) loader, the audio loader shouldn't load the\n * segment until that value is provided.\n *\n * CASE 2: Video prepares to load a new timeline before audio:\n *\n * Timeline: 0 1\n * Audio Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Audio Loader: ^\n * Video Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Video Loader ^\n *\n * In the above example, the video loader is preparing to load the 6th segment, the first\n * after a discontinuity, while the audio loader is still loading the 5th segment, before\n * the discontinuity.\n *\n * If the video loader goes ahead and loads and appends the 6th segment, then once the\n * segment is loaded and processed, both the video and audio timestamp offsets will be\n * set, since video is used as the primary timing source. This is to ensure content lines\n * up appropriately, as any modifications to the video timing are reflected by audio when\n * the video loader sets the audio and video timestamp offsets to the same value. However,\n * setting the timestamp offset for audio before audio has had a chance to change\n * timelines will likely lead to desyncing, as the audio loader will append segment 5 with\n * a timestamp intended to apply to segments from timeline 1 rather than timeline 0.\n *\n * CASE 3: When seeking, audio prepares to load a new timeline before video\n *\n * Timeline: 0 1\n * Audio Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Audio Loader: ^\n * Video Segments: 0 1 2 3 4 5 DISCO 6 7 8 9\n * Video Loader ^\n *\n * In the above example, both audio and video loaders are loading segments from timeline\n * 0, but imagine that the seek originated from timeline 1.\n *\n * When seeking to a new timeline, the timestamp offset will be set based on the expected\n * segment start of the loaded video segment. In order to maintain sync, the audio loader\n * must wait for the video loader to load its segment and update both the audio and video\n * timestamp offsets before it may load and append its own segment. This is the case\n * whether the seek results in a mismatched segment request (e.g., the audio loader\n * chooses to load segment 3 and the video loader chooses to load segment 4) or the\n * loaders choose to load the same segment index from each playlist, as the segments may\n * not be aligned perfectly, even for matching segment indexes.\n *\n * @param {Object} timelinechangeController\n * @param {number} currentTimeline\n * The timeline currently being followed by the loader\n * @param {number} segmentTimeline\n * The timeline of the segment being loaded\n * @param {('main'|'audio')} loaderType\n * The loader type\n * @param {boolean} audioDisabled\n * Whether the audio is disabled for the loader. This should only be true when the\n * loader may have muxed audio in its segment, but should not append it, e.g., for\n * the main loader when an alternate audio playlist is active.\n *\n * @return {boolean}\n * Whether the loader should wait for a timeline change from the timeline change\n * controller before processing the segment\n */\n\nvar shouldWaitForTimelineChange = function shouldWaitForTimelineChange(_ref2) {\n var timelineChangeController = _ref2.timelineChangeController,\n currentTimeline = _ref2.currentTimeline,\n segmentTimeline = _ref2.segmentTimeline,\n loaderType = _ref2.loaderType,\n audioDisabled = _ref2.audioDisabled;\n\n if (currentTimeline === segmentTimeline) {\n return false;\n }\n\n if (loaderType === 'audio') {\n var lastMainTimelineChange = timelineChangeController.lastTimelineChange({\n type: 'main'\n }); // Audio loader should wait if:\n //\n // * main hasn't had a timeline change yet (thus has not loaded its first segment)\n // * main hasn't yet changed to the timeline audio is looking to load\n\n return !lastMainTimelineChange || lastMainTimelineChange.to !== segmentTimeline;\n } // The main loader only needs to wait for timeline changes if there's demuxed audio.\n // Otherwise, there's nothing to wait for, since audio would be muxed into the main\n // loader's segments (or the content is audio/video only and handled by the main\n // loader).\n\n\n if (loaderType === 'main' && audioDisabled) {\n var pendingAudioTimelineChange = timelineChangeController.pendingTimelineChange({\n type: 'audio'\n }); // Main loader should wait for the audio loader if audio is not pending a timeline\n // change to the current timeline.\n //\n // Since the main loader is responsible for setting the timestamp offset for both\n // audio and video, the main loader must wait for audio to be about to change to its\n // timeline before setting the offset, otherwise, if audio is behind in loading,\n // segments from the previous timeline would be adjusted by the new timestamp offset.\n //\n // This requirement means that video will not cross a timeline until the audio is\n // about to cross to it, so that way audio and video will always cross the timeline\n // together.\n //\n // In addition to normal timeline changes, these rules also apply to the start of a\n // stream (going from a non-existent timeline, -1, to timeline 0). It's important\n // that these rules apply to the first timeline change because if they did not, it's\n // possible that the main loader will cross two timelines before the audio loader has\n // crossed one. Logic may be implemented to handle the startup as a special case, but\n // it's easier to simply treat all timeline changes the same.\n\n if (pendingAudioTimelineChange && pendingAudioTimelineChange.to === segmentTimeline) {\n return false;\n }\n\n return true;\n }\n\n return false;\n};\nvar mediaDuration = function mediaDuration(timingInfos) {\n var maxDuration = 0;\n ['video', 'audio'].forEach(function (type) {\n var typeTimingInfo = timingInfos[type + \"TimingInfo\"];\n\n if (!typeTimingInfo) {\n return;\n }\n\n var start = typeTimingInfo.start,\n end = typeTimingInfo.end;\n var duration;\n\n if (typeof start === 'bigint' || typeof end === 'bigint') {\n duration = window$1.BigInt(end) - window$1.BigInt(start);\n } else if (typeof start === 'number' && typeof end === 'number') {\n duration = end - start;\n }\n\n if (typeof duration !== 'undefined' && duration > maxDuration) {\n maxDuration = duration;\n }\n }); // convert back to a number if it is lower than MAX_SAFE_INTEGER\n // as we only need BigInt when we are above that.\n\n if (typeof maxDuration === 'bigint' && maxDuration < Number.MAX_SAFE_INTEGER) {\n maxDuration = Number(maxDuration);\n }\n\n return maxDuration;\n};\nvar segmentTooLong = function segmentTooLong(_ref3) {\n var segmentDuration = _ref3.segmentDuration,\n maxDuration = _ref3.maxDuration;\n\n // 0 duration segments are most likely due to metadata only segments or a lack of\n // information.\n if (!segmentDuration) {\n return false;\n } // For HLS:\n //\n // https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1\n // The EXTINF duration of each Media Segment in the Playlist\n // file, when rounded to the nearest integer, MUST be less than or equal\n // to the target duration; longer segments can trigger playback stalls\n // or other errors.\n //\n // For DASH, the mpd-parser uses the largest reported segment duration as the target\n // duration. Although that reported duration is occasionally approximate (i.e., not\n // exact), a strict check may report that a segment is too long more often in DASH.\n\n\n return Math.round(segmentDuration) > maxDuration + TIME_FUDGE_FACTOR;\n};\nvar getTroublesomeSegmentDurationMessage = function getTroublesomeSegmentDurationMessage(segmentInfo, sourceType) {\n // Right now we aren't following DASH's timing model exactly, so only perform\n // this check for HLS content.\n if (sourceType !== 'hls') {\n return null;\n }\n\n var segmentDuration = mediaDuration({\n audioTimingInfo: segmentInfo.audioTimingInfo,\n videoTimingInfo: segmentInfo.videoTimingInfo\n }); // Don't report if we lack information.\n //\n // If the segment has a duration of 0 it is either a lack of information or a\n // metadata only segment and shouldn't be reported here.\n\n if (!segmentDuration) {\n return null;\n }\n\n var targetDuration = segmentInfo.playlist.targetDuration;\n var isSegmentWayTooLong = segmentTooLong({\n segmentDuration: segmentDuration,\n maxDuration: targetDuration * 2\n });\n var isSegmentSlightlyTooLong = segmentTooLong({\n segmentDuration: segmentDuration,\n maxDuration: targetDuration\n });\n var segmentTooLongMessage = \"Segment with index \" + segmentInfo.mediaIndex + \" \" + (\"from playlist \" + segmentInfo.playlist.id + \" \") + (\"has a duration of \" + segmentDuration + \" \") + (\"when the reported duration is \" + segmentInfo.duration + \" \") + (\"and the target duration is \" + targetDuration + \". \") + 'For HLS content, a duration in excess of the target duration may result in ' + 'playback issues. See the HLS specification section on EXT-X-TARGETDURATION for ' + 'more details: ' + 'https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1';\n\n if (isSegmentWayTooLong || isSegmentSlightlyTooLong) {\n return {\n severity: isSegmentWayTooLong ? 'warn' : 'info',\n message: segmentTooLongMessage\n };\n }\n\n return null;\n};\n/**\n * An object that manages segment loading and appending.\n *\n * @class SegmentLoader\n * @param {Object} options required and optional options\n * @extends videojs.EventTarget\n */\n\nvar SegmentLoader = /*#__PURE__*/function (_videojs$EventTarget) {\n _inheritsLoose(SegmentLoader, _videojs$EventTarget);\n\n function SegmentLoader(settings, options) {\n var _this;\n\n _this = _videojs$EventTarget.call(this) || this; // check pre-conditions\n\n if (!settings) {\n throw new TypeError('Initialization settings are required');\n }\n\n if (typeof settings.currentTime !== 'function') {\n throw new TypeError('No currentTime getter specified');\n }\n\n if (!settings.mediaSource) {\n throw new TypeError('No MediaSource specified');\n } // public properties\n\n\n _this.bandwidth = settings.bandwidth;\n _this.throughput = {\n rate: 0,\n count: 0\n };\n _this.roundTrip = NaN;\n\n _this.resetStats_();\n\n _this.mediaIndex = null;\n _this.partIndex = null; // private settings\n\n _this.hasPlayed_ = settings.hasPlayed;\n _this.currentTime_ = settings.currentTime;\n _this.seekable_ = settings.seekable;\n _this.seeking_ = settings.seeking;\n _this.duration_ = settings.duration;\n _this.mediaSource_ = settings.mediaSource;\n _this.vhs_ = settings.vhs;\n _this.loaderType_ = settings.loaderType;\n _this.currentMediaInfo_ = void 0;\n _this.startingMediaInfo_ = void 0;\n _this.segmentMetadataTrack_ = settings.segmentMetadataTrack;\n _this.goalBufferLength_ = settings.goalBufferLength;\n _this.sourceType_ = settings.sourceType;\n _this.sourceUpdater_ = settings.sourceUpdater;\n _this.inbandTextTracks_ = settings.inbandTextTracks;\n _this.state_ = 'INIT';\n _this.timelineChangeController_ = settings.timelineChangeController;\n _this.shouldSaveSegmentTimingInfo_ = true;\n _this.parse708captions_ = settings.parse708captions;\n _this.captionServices_ = settings.captionServices;\n _this.experimentalExactManifestTimings = settings.experimentalExactManifestTimings; // private instance variables\n\n _this.checkBufferTimeout_ = null;\n _this.error_ = void 0;\n _this.currentTimeline_ = -1;\n _this.pendingSegment_ = null;\n _this.xhrOptions_ = null;\n _this.pendingSegments_ = [];\n _this.audioDisabled_ = false;\n _this.isPendingTimestampOffset_ = false; // TODO possibly move gopBuffer and timeMapping info to a separate controller\n\n _this.gopBuffer_ = [];\n _this.timeMapping_ = 0;\n _this.safeAppend_ = videojs.browser.IE_VERSION >= 11;\n _this.appendInitSegment_ = {\n audio: true,\n video: true\n };\n _this.playlistOfLastInitSegment_ = {\n audio: null,\n video: null\n };\n _this.callQueue_ = []; // If the segment loader prepares to load a segment, but does not have enough\n // information yet to start the loading process (e.g., if the audio loader wants to\n // load a segment from the next timeline but the main loader hasn't yet crossed that\n // timeline), then the load call will be added to the queue until it is ready to be\n // processed.\n\n _this.loadQueue_ = [];\n _this.metadataQueue_ = {\n id3: [],\n caption: []\n };\n _this.waitingOnRemove_ = false;\n _this.quotaExceededErrorRetryTimeout_ = null; // Fragmented mp4 playback\n\n _this.activeInitSegmentId_ = null;\n _this.initSegments_ = {}; // HLSe playback\n\n _this.cacheEncryptionKeys_ = settings.cacheEncryptionKeys;\n _this.keyCache_ = {};\n _this.decrypter_ = settings.decrypter; // Manages the tracking and generation of sync-points, mappings\n // between a time in the display time and a segment index within\n // a playlist\n\n _this.syncController_ = settings.syncController;\n _this.syncPoint_ = {\n segmentIndex: 0,\n time: 0\n };\n _this.transmuxer_ = _this.createTransmuxer_();\n\n _this.triggerSyncInfoUpdate_ = function () {\n return _this.trigger('syncinfoupdate');\n };\n\n _this.syncController_.on('syncinfoupdate', _this.triggerSyncInfoUpdate_);\n\n _this.mediaSource_.addEventListener('sourceopen', function () {\n if (!_this.isEndOfStream_()) {\n _this.ended_ = false;\n }\n }); // ...for determining the fetch location\n\n\n _this.fetchAtBuffer_ = false;\n _this.logger_ = logger(\"SegmentLoader[\" + _this.loaderType_ + \"]\");\n Object.defineProperty(_assertThisInitialized(_this), 'state', {\n get: function get() {\n return this.state_;\n },\n set: function set(newState) {\n if (newState !== this.state_) {\n this.logger_(this.state_ + \" -> \" + newState);\n this.state_ = newState;\n this.trigger('statechange');\n }\n }\n });\n\n _this.sourceUpdater_.on('ready', function () {\n if (_this.hasEnoughInfoToAppend_()) {\n _this.processCallQueue_();\n }\n }); // Only the main loader needs to listen for pending timeline changes, as the main\n // loader should wait for audio to be ready to change its timeline so that both main\n // and audio timelines change together. For more details, see the\n // shouldWaitForTimelineChange function.\n\n\n if (_this.loaderType_ === 'main') {\n _this.timelineChangeController_.on('pendingtimelinechange', function () {\n if (_this.hasEnoughInfoToAppend_()) {\n _this.processCallQueue_();\n }\n });\n } // The main loader only listens on pending timeline changes, but the audio loader,\n // since its loads follow main, needs to listen on timeline changes. For more details,\n // see the shouldWaitForTimelineChange function.\n\n\n if (_this.loaderType_ === 'audio') {\n _this.timelineChangeController_.on('timelinechange', function () {\n if (_this.hasEnoughInfoToLoad_()) {\n _this.processLoadQueue_();\n }\n\n if (_this.hasEnoughInfoToAppend_()) {\n _this.processCallQueue_();\n }\n });\n }\n\n return _this;\n }\n\n var _proto = SegmentLoader.prototype;\n\n _proto.createTransmuxer_ = function createTransmuxer_() {\n return segmentTransmuxer.createTransmuxer({\n remux: false,\n alignGopsAtEnd: this.safeAppend_,\n keepOriginalTimestamps: true,\n parse708captions: this.parse708captions_,\n captionServices: this.captionServices_\n });\n }\n /**\n * reset all of our media stats\n *\n * @private\n */\n ;\n\n _proto.resetStats_ = function resetStats_() {\n this.mediaBytesTransferred = 0;\n this.mediaRequests = 0;\n this.mediaRequestsAborted = 0;\n this.mediaRequestsTimedout = 0;\n this.mediaRequestsErrored = 0;\n this.mediaTransferDuration = 0;\n this.mediaSecondsLoaded = 0;\n this.mediaAppends = 0;\n }\n /**\n * dispose of the SegmentLoader and reset to the default state\n */\n ;\n\n _proto.dispose = function dispose() {\n this.trigger('dispose');\n this.state = 'DISPOSED';\n this.pause();\n this.abort_();\n\n if (this.transmuxer_) {\n this.transmuxer_.terminate();\n }\n\n this.resetStats_();\n\n if (this.checkBufferTimeout_) {\n window$1.clearTimeout(this.checkBufferTimeout_);\n }\n\n if (this.syncController_ && this.triggerSyncInfoUpdate_) {\n this.syncController_.off('syncinfoupdate', this.triggerSyncInfoUpdate_);\n }\n\n this.off();\n };\n\n _proto.setAudio = function setAudio(enable) {\n this.audioDisabled_ = !enable;\n\n if (enable) {\n this.appendInitSegment_.audio = true;\n } else {\n // remove current track audio if it gets disabled\n this.sourceUpdater_.removeAudio(0, this.duration_());\n }\n }\n /**\n * abort anything that is currently doing on with the SegmentLoader\n * and reset to a default state\n */\n ;\n\n _proto.abort = function abort() {\n if (this.state !== 'WAITING') {\n if (this.pendingSegment_) {\n this.pendingSegment_ = null;\n }\n\n return;\n }\n\n this.abort_(); // We aborted the requests we were waiting on, so reset the loader's state to READY\n // since we are no longer \"waiting\" on any requests. XHR callback is not always run\n // when the request is aborted. This will prevent the loader from being stuck in the\n // WAITING state indefinitely.\n\n this.state = 'READY'; // don't wait for buffer check timeouts to begin fetching the\n // next segment\n\n if (!this.paused()) {\n this.monitorBuffer_();\n }\n }\n /**\n * abort all pending xhr requests and null any pending segements\n *\n * @private\n */\n ;\n\n _proto.abort_ = function abort_() {\n if (this.pendingSegment_ && this.pendingSegment_.abortRequests) {\n this.pendingSegment_.abortRequests();\n } // clear out the segment being processed\n\n\n this.pendingSegment_ = null;\n this.callQueue_ = [];\n this.loadQueue_ = [];\n this.metadataQueue_.id3 = [];\n this.metadataQueue_.caption = [];\n this.timelineChangeController_.clearPendingTimelineChange(this.loaderType_);\n this.waitingOnRemove_ = false;\n window$1.clearTimeout(this.quotaExceededErrorRetryTimeout_);\n this.quotaExceededErrorRetryTimeout_ = null;\n };\n\n _proto.checkForAbort_ = function checkForAbort_(requestId) {\n // If the state is APPENDING, then aborts will not modify the state, meaning the first\n // callback that happens should reset the state to READY so that loading can continue.\n if (this.state === 'APPENDING' && !this.pendingSegment_) {\n this.state = 'READY';\n return true;\n }\n\n if (!this.pendingSegment_ || this.pendingSegment_.requestId !== requestId) {\n return true;\n }\n\n return false;\n }\n /**\n * set an error on the segment loader and null out any pending segements\n *\n * @param {Error} error the error to set on the SegmentLoader\n * @return {Error} the error that was set or that is currently set\n */\n ;\n\n _proto.error = function error(_error) {\n if (typeof _error !== 'undefined') {\n this.logger_('error occurred:', _error);\n this.error_ = _error;\n }\n\n this.pendingSegment_ = null;\n return this.error_;\n };\n\n _proto.endOfStream = function endOfStream() {\n this.ended_ = true;\n\n if (this.transmuxer_) {\n // need to clear out any cached data to prepare for the new segment\n segmentTransmuxer.reset(this.transmuxer_);\n }\n\n this.gopBuffer_.length = 0;\n this.pause();\n this.trigger('ended');\n }\n /**\n * Indicates which time ranges are buffered\n *\n * @return {TimeRange}\n * TimeRange object representing the current buffered ranges\n */\n ;\n\n _proto.buffered_ = function buffered_() {\n var trackInfo = this.getMediaInfo_();\n\n if (!this.sourceUpdater_ || !trackInfo) {\n return videojs.createTimeRanges();\n }\n\n if (this.loaderType_ === 'main') {\n var hasAudio = trackInfo.hasAudio,\n hasVideo = trackInfo.hasVideo,\n isMuxed = trackInfo.isMuxed;\n\n if (hasVideo && hasAudio && !this.audioDisabled_ && !isMuxed) {\n return this.sourceUpdater_.buffered();\n }\n\n if (hasVideo) {\n return this.sourceUpdater_.videoBuffered();\n }\n } // One case that can be ignored for now is audio only with alt audio,\n // as we don't yet have proper support for that.\n\n\n return this.sourceUpdater_.audioBuffered();\n }\n /**\n * Gets and sets init segment for the provided map\n *\n * @param {Object} map\n * The map object representing the init segment to get or set\n * @param {boolean=} set\n * If true, the init segment for the provided map should be saved\n * @return {Object}\n * map object for desired init segment\n */\n ;\n\n _proto.initSegmentForMap = function initSegmentForMap(map, set) {\n if (set === void 0) {\n set = false;\n }\n\n if (!map) {\n return null;\n }\n\n var id = initSegmentId(map);\n var storedMap = this.initSegments_[id];\n\n if (set && !storedMap && map.bytes) {\n this.initSegments_[id] = storedMap = {\n resolvedUri: map.resolvedUri,\n byterange: map.byterange,\n bytes: map.bytes,\n tracks: map.tracks,\n timescales: map.timescales\n };\n }\n\n return storedMap || map;\n }\n /**\n * Gets and sets key for the provided key\n *\n * @param {Object} key\n * The key object representing the key to get or set\n * @param {boolean=} set\n * If true, the key for the provided key should be saved\n * @return {Object}\n * Key object for desired key\n */\n ;\n\n _proto.segmentKey = function segmentKey(key, set) {\n if (set === void 0) {\n set = false;\n }\n\n if (!key) {\n return null;\n }\n\n var id = segmentKeyId(key);\n var storedKey = this.keyCache_[id]; // TODO: We should use the HTTP Expires header to invalidate our cache per\n // https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-6.2.3\n\n if (this.cacheEncryptionKeys_ && set && !storedKey && key.bytes) {\n this.keyCache_[id] = storedKey = {\n resolvedUri: key.resolvedUri,\n bytes: key.bytes\n };\n }\n\n var result = {\n resolvedUri: (storedKey || key).resolvedUri\n };\n\n if (storedKey) {\n result.bytes = storedKey.bytes;\n }\n\n return result;\n }\n /**\n * Returns true if all configuration required for loading is present, otherwise false.\n *\n * @return {boolean} True if the all configuration is ready for loading\n * @private\n */\n ;\n\n _proto.couldBeginLoading_ = function couldBeginLoading_() {\n return this.playlist_ && !this.paused();\n }\n /**\n * load a playlist and start to fill the buffer\n */\n ;\n\n _proto.load = function load() {\n // un-pause\n this.monitorBuffer_(); // if we don't have a playlist yet, keep waiting for one to be\n // specified\n\n if (!this.playlist_) {\n return;\n } // if all the configuration is ready, initialize and begin loading\n\n\n if (this.state === 'INIT' && this.couldBeginLoading_()) {\n return this.init_();\n } // if we're in the middle of processing a segment already, don't\n // kick off an additional segment request\n\n\n if (!this.couldBeginLoading_() || this.state !== 'READY' && this.state !== 'INIT') {\n return;\n }\n\n this.state = 'READY';\n }\n /**\n * Once all the starting parameters have been specified, begin\n * operation. This method should only be invoked from the INIT\n * state.\n *\n * @private\n */\n ;\n\n _proto.init_ = function init_() {\n this.state = 'READY'; // if this is the audio segment loader, and it hasn't been inited before, then any old\n // audio data from the muxed content should be removed\n\n this.resetEverything();\n return this.monitorBuffer_();\n }\n /**\n * set a playlist on the segment loader\n *\n * @param {PlaylistLoader} media the playlist to set on the segment loader\n */\n ;\n\n _proto.playlist = function playlist(newPlaylist, options) {\n if (options === void 0) {\n options = {};\n }\n\n if (!newPlaylist) {\n return;\n }\n\n var oldPlaylist = this.playlist_;\n var segmentInfo = this.pendingSegment_;\n this.playlist_ = newPlaylist;\n this.xhrOptions_ = options; // when we haven't started playing yet, the start of a live playlist\n // is always our zero-time so force a sync update each time the playlist\n // is refreshed from the server\n //\n // Use the INIT state to determine if playback has started, as the playlist sync info\n // should be fixed once requests begin (as sync points are generated based on sync\n // info), but not before then.\n\n if (this.state === 'INIT') {\n newPlaylist.syncInfo = {\n mediaSequence: newPlaylist.mediaSequence,\n time: 0\n }; // Setting the date time mapping means mapping the program date time (if available)\n // to time 0 on the player's timeline. The playlist's syncInfo serves a similar\n // purpose, mapping the initial mediaSequence to time zero. Since the syncInfo can\n // be updated as the playlist is refreshed before the loader starts loading, the\n // program date time mapping needs to be updated as well.\n //\n // This mapping is only done for the main loader because a program date time should\n // map equivalently between playlists.\n\n if (this.loaderType_ === 'main') {\n this.syncController_.setDateTimeMappingForStart(newPlaylist);\n }\n }\n\n var oldId = null;\n\n if (oldPlaylist) {\n if (oldPlaylist.id) {\n oldId = oldPlaylist.id;\n } else if (oldPlaylist.uri) {\n oldId = oldPlaylist.uri;\n }\n }\n\n this.logger_(\"playlist update [\" + oldId + \" => \" + (newPlaylist.id || newPlaylist.uri) + \"]\"); // in VOD, this is always a rendition switch (or we updated our syncInfo above)\n // in LIVE, we always want to update with new playlists (including refreshes)\n\n this.trigger('syncinfoupdate'); // if we were unpaused but waiting for a playlist, start\n // buffering now\n\n if (this.state === 'INIT' && this.couldBeginLoading_()) {\n return this.init_();\n }\n\n if (!oldPlaylist || oldPlaylist.uri !== newPlaylist.uri) {\n if (this.mediaIndex !== null) {\n // we must reset/resync the segment loader when we switch renditions and\n // the segment loader is already synced to the previous rendition\n // on playlist changes we want it to be possible to fetch\n // at the buffer for vod but not for live. So we use resetLoader\n // for live and resyncLoader for vod. We want this because\n // if a playlist uses independent and non-independent segments/parts the\n // buffer may not accurately reflect the next segment that we should try\n // downloading.\n if (!newPlaylist.endList) {\n this.resetLoader();\n } else {\n this.resyncLoader();\n }\n }\n\n this.currentMediaInfo_ = void 0;\n this.trigger('playlistupdate'); // the rest of this function depends on `oldPlaylist` being defined\n\n return;\n } // we reloaded the same playlist so we are in a live scenario\n // and we will likely need to adjust the mediaIndex\n\n\n var mediaSequenceDiff = newPlaylist.mediaSequence - oldPlaylist.mediaSequence;\n this.logger_(\"live window shift [\" + mediaSequenceDiff + \"]\"); // update the mediaIndex on the SegmentLoader\n // this is important because we can abort a request and this value must be\n // equal to the last appended mediaIndex\n\n if (this.mediaIndex !== null) {\n this.mediaIndex -= mediaSequenceDiff; // this can happen if we are going to load the first segment, but get a playlist\n // update during that. mediaIndex would go from 0 to -1 if mediaSequence in the\n // new playlist was incremented by 1.\n\n if (this.mediaIndex < 0) {\n this.mediaIndex = null;\n this.partIndex = null;\n } else {\n var segment = this.playlist_.segments[this.mediaIndex]; // partIndex should remain the same for the same segment\n // unless parts fell off of the playlist for this segment.\n // In that case we need to reset partIndex and resync\n\n if (this.partIndex && (!segment.parts || !segment.parts.length || !segment.parts[this.partIndex])) {\n var mediaIndex = this.mediaIndex;\n this.logger_(\"currently processing part (index \" + this.partIndex + \") no longer exists.\");\n this.resetLoader(); // We want to throw away the partIndex and the data associated with it,\n // as the part was dropped from our current playlists segment.\n // The mediaIndex will still be valid so keep that around.\n\n this.mediaIndex = mediaIndex;\n }\n }\n } // update the mediaIndex on the SegmentInfo object\n // this is important because we will update this.mediaIndex with this value\n // in `handleAppendsDone_` after the segment has been successfully appended\n\n\n if (segmentInfo) {\n segmentInfo.mediaIndex -= mediaSequenceDiff;\n\n if (segmentInfo.mediaIndex < 0) {\n segmentInfo.mediaIndex = null;\n segmentInfo.partIndex = null;\n } else {\n // we need to update the referenced segment so that timing information is\n // saved for the new playlist's segment, however, if the segment fell off the\n // playlist, we can leave the old reference and just lose the timing info\n if (segmentInfo.mediaIndex >= 0) {\n segmentInfo.segment = newPlaylist.segments[segmentInfo.mediaIndex];\n }\n\n if (segmentInfo.partIndex >= 0 && segmentInfo.segment.parts) {\n segmentInfo.part = segmentInfo.segment.parts[segmentInfo.partIndex];\n }\n }\n }\n\n this.syncController_.saveExpiredSegmentInfo(oldPlaylist, newPlaylist);\n }\n /**\n * Prevent the loader from fetching additional segments. If there\n * is a segment request outstanding, it will finish processing\n * before the loader halts. A segment loader can be unpaused by\n * calling load().\n */\n ;\n\n _proto.pause = function pause() {\n if (this.checkBufferTimeout_) {\n window$1.clearTimeout(this.checkBufferTimeout_);\n this.checkBufferTimeout_ = null;\n }\n }\n /**\n * Returns whether the segment loader is fetching additional\n * segments when given the opportunity. This property can be\n * modified through calls to pause() and load().\n */\n ;\n\n _proto.paused = function paused() {\n return this.checkBufferTimeout_ === null;\n }\n /**\n * Delete all the buffered data and reset the SegmentLoader\n *\n * @param {Function} [done] an optional callback to be executed when the remove\n * operation is complete\n */\n ;\n\n _proto.resetEverything = function resetEverything(done) {\n this.ended_ = false;\n this.appendInitSegment_ = {\n audio: true,\n video: true\n };\n this.resetLoader(); // remove from 0, the earliest point, to Infinity, to signify removal of everything.\n // VTT Segment Loader doesn't need to do anything but in the regular SegmentLoader,\n // we then clamp the value to duration if necessary.\n\n this.remove(0, Infinity, done); // clears fmp4 captions\n\n if (this.transmuxer_) {\n this.transmuxer_.postMessage({\n action: 'clearAllMp4Captions'\n }); // reset the cache in the transmuxer\n\n this.transmuxer_.postMessage({\n action: 'reset'\n });\n }\n }\n /**\n * Force the SegmentLoader to resync and start loading around the currentTime instead\n * of starting at the end of the buffer\n *\n * Useful for fast quality changes\n */\n ;\n\n _proto.resetLoader = function resetLoader() {\n this.fetchAtBuffer_ = false;\n this.resyncLoader();\n }\n /**\n * Force the SegmentLoader to restart synchronization and make a conservative guess\n * before returning to the simple walk-forward method\n */\n ;\n\n _proto.resyncLoader = function resyncLoader() {\n if (this.transmuxer_) {\n // need to clear out any cached data to prepare for the new segment\n segmentTransmuxer.reset(this.transmuxer_);\n }\n\n this.mediaIndex = null;\n this.partIndex = null;\n this.syncPoint_ = null;\n this.isPendingTimestampOffset_ = false;\n this.callQueue_ = [];\n this.loadQueue_ = [];\n this.metadataQueue_.id3 = [];\n this.metadataQueue_.caption = [];\n this.abort();\n\n if (this.transmuxer_) {\n this.transmuxer_.postMessage({\n action: 'clearParsedMp4Captions'\n });\n }\n }\n /**\n * Remove any data in the source buffer between start and end times\n *\n * @param {number} start - the start time of the region to remove from the buffer\n * @param {number} end - the end time of the region to remove from the buffer\n * @param {Function} [done] - an optional callback to be executed when the remove\n * @param {boolean} force - force all remove operations to happen\n * operation is complete\n */\n ;\n\n _proto.remove = function remove(start, end, done, force) {\n if (done === void 0) {\n done = function done() {};\n }\n\n if (force === void 0) {\n force = false;\n }\n\n // clamp end to duration if we need to remove everything.\n // This is due to a browser bug that causes issues if we remove to Infinity.\n // videojs/videojs-contrib-hls#1225\n if (end === Infinity) {\n end = this.duration_();\n } // skip removes that would throw an error\n // commonly happens during a rendition switch at the start of a video\n // from start 0 to end 0\n\n\n if (end <= start) {\n this.logger_('skipping remove because end ${end} is <= start ${start}');\n return;\n }\n\n if (!this.sourceUpdater_ || !this.getMediaInfo_()) {\n this.logger_('skipping remove because no source updater or starting media info'); // nothing to remove if we haven't processed any media\n\n return;\n } // set it to one to complete this function's removes\n\n\n var removesRemaining = 1;\n\n var removeFinished = function removeFinished() {\n removesRemaining--;\n\n if (removesRemaining === 0) {\n done();\n }\n };\n\n if (force || !this.audioDisabled_) {\n removesRemaining++;\n this.sourceUpdater_.removeAudio(start, end, removeFinished);\n } // While it would be better to only remove video if the main loader has video, this\n // should be safe with audio only as removeVideo will call back even if there's no\n // video buffer.\n //\n // In theory we can check to see if there's video before calling the remove, but in\n // the event that we're switching between renditions and from video to audio only\n // (when we add support for that), we may need to clear the video contents despite\n // what the new media will contain.\n\n\n if (force || this.loaderType_ === 'main') {\n this.gopBuffer_ = removeGopBuffer(this.gopBuffer_, start, end, this.timeMapping_);\n removesRemaining++;\n this.sourceUpdater_.removeVideo(start, end, removeFinished);\n } // remove any captions and ID3 tags\n\n\n for (var track in this.inbandTextTracks_) {\n removeCuesFromTrack(start, end, this.inbandTextTracks_[track]);\n }\n\n removeCuesFromTrack(start, end, this.segmentMetadataTrack_); // finished this function's removes\n\n removeFinished();\n }\n /**\n * (re-)schedule monitorBufferTick_ to run as soon as possible\n *\n * @private\n */\n ;\n\n _proto.monitorBuffer_ = function monitorBuffer_() {\n if (this.checkBufferTimeout_) {\n window$1.clearTimeout(this.checkBufferTimeout_);\n }\n\n this.checkBufferTimeout_ = window$1.setTimeout(this.monitorBufferTick_.bind(this), 1);\n }\n /**\n * As long as the SegmentLoader is in the READY state, periodically\n * invoke fillBuffer_().\n *\n * @private\n */\n ;\n\n _proto.monitorBufferTick_ = function monitorBufferTick_() {\n if (this.state === 'READY') {\n this.fillBuffer_();\n }\n\n if (this.checkBufferTimeout_) {\n window$1.clearTimeout(this.checkBufferTimeout_);\n }\n\n this.checkBufferTimeout_ = window$1.setTimeout(this.monitorBufferTick_.bind(this), CHECK_BUFFER_DELAY);\n }\n /**\n * fill the buffer with segements unless the sourceBuffers are\n * currently updating\n *\n * Note: this function should only ever be called by monitorBuffer_\n * and never directly\n *\n * @private\n */\n ;\n\n _proto.fillBuffer_ = function fillBuffer_() {\n // TODO since the source buffer maintains a queue, and we shouldn't call this function\n // except when we're ready for the next segment, this check can most likely be removed\n if (this.sourceUpdater_.updating()) {\n return;\n } // see if we need to begin loading immediately\n\n\n var segmentInfo = this.chooseNextRequest_();\n\n if (!segmentInfo) {\n return;\n }\n\n if (typeof segmentInfo.timestampOffset === 'number') {\n this.isPendingTimestampOffset_ = false;\n this.timelineChangeController_.pendingTimelineChange({\n type: this.loaderType_,\n from: this.currentTimeline_,\n to: segmentInfo.timeline\n });\n }\n\n this.loadSegment_(segmentInfo);\n }\n /**\n * Determines if we should call endOfStream on the media source based\n * on the state of the buffer or if appened segment was the final\n * segment in the playlist.\n *\n * @param {number} [mediaIndex] the media index of segment we last appended\n * @param {Object} [playlist] a media playlist object\n * @return {boolean} do we need to call endOfStream on the MediaSource\n */\n ;\n\n _proto.isEndOfStream_ = function isEndOfStream_(mediaIndex, playlist, partIndex) {\n if (mediaIndex === void 0) {\n mediaIndex = this.mediaIndex;\n }\n\n if (playlist === void 0) {\n playlist = this.playlist_;\n }\n\n if (partIndex === void 0) {\n partIndex = this.partIndex;\n }\n\n if (!playlist || !this.mediaSource_) {\n return false;\n }\n\n var segment = typeof mediaIndex === 'number' && playlist.segments[mediaIndex]; // mediaIndex is zero based but length is 1 based\n\n var appendedLastSegment = mediaIndex + 1 === playlist.segments.length; // true if there are no parts, or this is the last part.\n\n var appendedLastPart = !segment || !segment.parts || partIndex + 1 === segment.parts.length; // if we've buffered to the end of the video, we need to call endOfStream\n // so that MediaSources can trigger the `ended` event when it runs out of\n // buffered data instead of waiting for me\n\n return playlist.endList && this.mediaSource_.readyState === 'open' && appendedLastSegment && appendedLastPart;\n }\n /**\n * Determines what request should be made given current segment loader state.\n *\n * @return {Object} a request object that describes the segment/part to load\n */\n ;\n\n _proto.chooseNextRequest_ = function chooseNextRequest_() {\n var buffered = this.buffered_();\n var bufferedEnd = lastBufferedEnd(buffered) || 0;\n var bufferedTime = timeAheadOf(buffered, this.currentTime_());\n var preloaded = !this.hasPlayed_() && bufferedTime >= 1;\n var haveEnoughBuffer = bufferedTime >= this.goalBufferLength_();\n var segments = this.playlist_.segments; // return no segment if:\n // 1. we don't have segments\n // 2. The video has not yet played and we already downloaded a segment\n // 3. we already have enough buffered time\n\n if (!segments.length || preloaded || haveEnoughBuffer) {\n return null;\n }\n\n this.syncPoint_ = this.syncPoint_ || this.syncController_.getSyncPoint(this.playlist_, this.duration_(), this.currentTimeline_, this.currentTime_());\n var next = {\n partIndex: null,\n mediaIndex: null,\n startOfSegment: null,\n playlist: this.playlist_,\n isSyncRequest: Boolean(!this.syncPoint_)\n };\n\n if (next.isSyncRequest) {\n next.mediaIndex = getSyncSegmentCandidate(this.currentTimeline_, segments, bufferedEnd);\n } else if (this.mediaIndex !== null) {\n var segment = segments[this.mediaIndex];\n var partIndex = typeof this.partIndex === 'number' ? this.partIndex : -1;\n next.startOfSegment = segment.end ? segment.end : bufferedEnd;\n\n if (segment.parts && segment.parts[partIndex + 1]) {\n next.mediaIndex = this.mediaIndex;\n next.partIndex = partIndex + 1;\n } else {\n next.mediaIndex = this.mediaIndex + 1;\n }\n } else {\n // Find the segment containing the end of the buffer or current time.\n var _Playlist$getMediaInf = Playlist.getMediaInfoForTime({\n experimentalExactManifestTimings: this.experimentalExactManifestTimings,\n playlist: this.playlist_,\n currentTime: this.fetchAtBuffer_ ? bufferedEnd : this.currentTime_(),\n startingPartIndex: this.syncPoint_.partIndex,\n startingSegmentIndex: this.syncPoint_.segmentIndex,\n startTime: this.syncPoint_.time\n }),\n segmentIndex = _Playlist$getMediaInf.segmentIndex,\n startTime = _Playlist$getMediaInf.startTime,\n _partIndex = _Playlist$getMediaInf.partIndex;\n\n next.getMediaInfoForTime = this.fetchAtBuffer_ ? \"bufferedEnd \" + bufferedEnd : \"currentTime \" + this.currentTime_();\n next.mediaIndex = segmentIndex;\n next.startOfSegment = startTime;\n next.partIndex = _partIndex;\n }\n\n var nextSegment = segments[next.mediaIndex];\n var nextPart = nextSegment && typeof next.partIndex === 'number' && nextSegment.parts && nextSegment.parts[next.partIndex]; // if the next segment index is invalid or\n // the next partIndex is invalid do not choose a next segment.\n\n if (!nextSegment || typeof next.partIndex === 'number' && !nextPart) {\n return null;\n } // if the next segment has parts, and we don't have a partIndex.\n // Set partIndex to 0\n\n\n if (typeof next.partIndex !== 'number' && nextSegment.parts) {\n next.partIndex = 0;\n nextPart = nextSegment.parts[0];\n } // if we have no buffered data then we need to make sure\n // that the next part we append is \"independent\" if possible.\n // So we check if the previous part is independent, and request\n // it if it is.\n\n\n if (!bufferedTime && nextPart && !nextPart.independent) {\n if (next.partIndex === 0) {\n var lastSegment = segments[next.mediaIndex - 1];\n var lastSegmentLastPart = lastSegment.parts && lastSegment.parts.length && lastSegment.parts[lastSegment.parts.length - 1];\n\n if (lastSegmentLastPart && lastSegmentLastPart.independent) {\n next.mediaIndex -= 1;\n next.partIndex = lastSegment.parts.length - 1;\n next.independent = 'previous segment';\n }\n } else if (nextSegment.parts[next.partIndex - 1].independent) {\n next.partIndex -= 1;\n next.independent = 'previous part';\n }\n }\n\n var ended = this.mediaSource_ && this.mediaSource_.readyState === 'ended'; // do not choose a next segment if all of the following:\n // 1. this is the last segment in the playlist\n // 2. end of stream has been called on the media source already\n // 3. the player is not seeking\n\n if (next.mediaIndex >= segments.length - 1 && ended && !this.seeking_()) {\n return null;\n }\n\n return this.generateSegmentInfo_(next);\n };\n\n _proto.generateSegmentInfo_ = function generateSegmentInfo_(options) {\n var independent = options.independent,\n playlist = options.playlist,\n mediaIndex = options.mediaIndex,\n startOfSegment = options.startOfSegment,\n isSyncRequest = options.isSyncRequest,\n partIndex = options.partIndex,\n forceTimestampOffset = options.forceTimestampOffset,\n getMediaInfoForTime = options.getMediaInfoForTime;\n var segment = playlist.segments[mediaIndex];\n var part = typeof partIndex === 'number' && segment.parts[partIndex];\n var segmentInfo = {\n requestId: 'segment-loader-' + Math.random(),\n // resolve the segment URL relative to the playlist\n uri: part && part.resolvedUri || segment.resolvedUri,\n // the segment's mediaIndex at the time it was requested\n mediaIndex: mediaIndex,\n partIndex: part ? partIndex : null,\n // whether or not to update the SegmentLoader's state with this\n // segment's mediaIndex\n isSyncRequest: isSyncRequest,\n startOfSegment: startOfSegment,\n // the segment's playlist\n playlist: playlist,\n // unencrypted bytes of the segment\n bytes: null,\n // when a key is defined for this segment, the encrypted bytes\n encryptedBytes: null,\n // The target timestampOffset for this segment when we append it\n // to the source buffer\n timestampOffset: null,\n // The timeline that the segment is in\n timeline: segment.timeline,\n // The expected duration of the segment in seconds\n duration: part && part.duration || segment.duration,\n // retain the segment in case the playlist updates while doing an async process\n segment: segment,\n part: part,\n byteLength: 0,\n transmuxer: this.transmuxer_,\n // type of getMediaInfoForTime that was used to get this segment\n getMediaInfoForTime: getMediaInfoForTime,\n independent: independent\n };\n var overrideCheck = typeof forceTimestampOffset !== 'undefined' ? forceTimestampOffset : this.isPendingTimestampOffset_;\n segmentInfo.timestampOffset = this.timestampOffsetForSegment_({\n segmentTimeline: segment.timeline,\n currentTimeline: this.currentTimeline_,\n startOfSegment: startOfSegment,\n buffered: this.buffered_(),\n overrideCheck: overrideCheck\n });\n var audioBufferedEnd = lastBufferedEnd(this.sourceUpdater_.audioBuffered());\n\n if (typeof audioBufferedEnd === 'number') {\n // since the transmuxer is using the actual timing values, but the buffer is\n // adjusted by the timestamp offset, we must adjust the value here\n segmentInfo.audioAppendStart = audioBufferedEnd - this.sourceUpdater_.audioTimestampOffset();\n }\n\n if (this.sourceUpdater_.videoBuffered().length) {\n segmentInfo.gopsToAlignWith = gopsSafeToAlignWith(this.gopBuffer_, // since the transmuxer is using the actual timing values, but the time is\n // adjusted by the timestmap offset, we must adjust the value here\n this.currentTime_() - this.sourceUpdater_.videoTimestampOffset(), this.timeMapping_);\n }\n\n return segmentInfo;\n } // get the timestampoffset for a segment,\n // added so that vtt segment loader can override and prevent\n // adding timestamp offsets.\n ;\n\n _proto.timestampOffsetForSegment_ = function timestampOffsetForSegment_(options) {\n return timestampOffsetForSegment(options);\n }\n /**\n * Determines if the network has enough bandwidth to complete the current segment\n * request in a timely manner. If not, the request will be aborted early and bandwidth\n * updated to trigger a playlist switch.\n *\n * @param {Object} stats\n * Object containing stats about the request timing and size\n * @private\n */\n ;\n\n _proto.earlyAbortWhenNeeded_ = function earlyAbortWhenNeeded_(stats) {\n if (this.vhs_.tech_.paused() || // Don't abort if the current playlist is on the lowestEnabledRendition\n // TODO: Replace using timeout with a boolean indicating whether this playlist is\n // the lowestEnabledRendition.\n !this.xhrOptions_.timeout || // Don't abort if we have no bandwidth information to estimate segment sizes\n !this.playlist_.attributes.BANDWIDTH) {\n return;\n } // Wait at least 1 second since the first byte of data has been received before\n // using the calculated bandwidth from the progress event to allow the bitrate\n // to stabilize\n\n\n if (Date.now() - (stats.firstBytesReceivedAt || Date.now()) < 1000) {\n return;\n }\n\n var currentTime = this.currentTime_();\n var measuredBandwidth = stats.bandwidth;\n var segmentDuration = this.pendingSegment_.duration;\n var requestTimeRemaining = Playlist.estimateSegmentRequestTime(segmentDuration, measuredBandwidth, this.playlist_, stats.bytesReceived); // Subtract 1 from the timeUntilRebuffer so we still consider an early abort\n // if we are only left with less than 1 second when the request completes.\n // A negative timeUntilRebuffering indicates we are already rebuffering\n\n var timeUntilRebuffer$1 = timeUntilRebuffer(this.buffered_(), currentTime, this.vhs_.tech_.playbackRate()) - 1; // Only consider aborting early if the estimated time to finish the download\n // is larger than the estimated time until the player runs out of forward buffer\n\n if (requestTimeRemaining <= timeUntilRebuffer$1) {\n return;\n }\n\n var switchCandidate = minRebufferMaxBandwidthSelector({\n master: this.vhs_.playlists.master,\n currentTime: currentTime,\n bandwidth: measuredBandwidth,\n duration: this.duration_(),\n segmentDuration: segmentDuration,\n timeUntilRebuffer: timeUntilRebuffer$1,\n currentTimeline: this.currentTimeline_,\n syncController: this.syncController_\n });\n\n if (!switchCandidate) {\n return;\n }\n\n var rebufferingImpact = requestTimeRemaining - timeUntilRebuffer$1;\n var timeSavedBySwitching = rebufferingImpact - switchCandidate.rebufferingImpact;\n var minimumTimeSaving = 0.5; // If we are already rebuffering, increase the amount of variance we add to the\n // potential round trip time of the new request so that we are not too aggressive\n // with switching to a playlist that might save us a fraction of a second.\n\n if (timeUntilRebuffer$1 <= TIME_FUDGE_FACTOR) {\n minimumTimeSaving = 1;\n }\n\n if (!switchCandidate.playlist || switchCandidate.playlist.uri === this.playlist_.uri || timeSavedBySwitching < minimumTimeSaving) {\n return;\n } // set the bandwidth to that of the desired playlist being sure to scale by\n // BANDWIDTH_VARIANCE and add one so the playlist selector does not exclude it\n // don't trigger a bandwidthupdate as the bandwidth is artifial\n\n\n this.bandwidth = switchCandidate.playlist.attributes.BANDWIDTH * Config.BANDWIDTH_VARIANCE + 1;\n this.trigger('earlyabort');\n };\n\n _proto.handleAbort_ = function handleAbort_(segmentInfo) {\n this.logger_(\"Aborting \" + segmentInfoString(segmentInfo));\n this.mediaRequestsAborted += 1;\n }\n /**\n * XHR `progress` event handler\n *\n * @param {Event}\n * The XHR `progress` event\n * @param {Object} simpleSegment\n * A simplified segment object copy\n * @private\n */\n ;\n\n _proto.handleProgress_ = function handleProgress_(event, simpleSegment) {\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n }\n\n this.trigger('progress');\n };\n\n _proto.handleTrackInfo_ = function handleTrackInfo_(simpleSegment, trackInfo) {\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n }\n\n if (this.checkForIllegalMediaSwitch(trackInfo)) {\n return;\n }\n\n trackInfo = trackInfo || {}; // When we have track info, determine what media types this loader is dealing with.\n // Guard against cases where we're not getting track info at all until we are\n // certain that all streams will provide it.\n\n if (!shallowEqual(this.currentMediaInfo_, trackInfo)) {\n this.appendInitSegment_ = {\n audio: true,\n video: true\n };\n this.startingMediaInfo_ = trackInfo;\n this.currentMediaInfo_ = trackInfo;\n this.logger_('trackinfo update', trackInfo);\n this.trigger('trackinfo');\n } // trackinfo may cause an abort if the trackinfo\n // causes a codec change to an unsupported codec.\n\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n } // set trackinfo on the pending segment so that\n // it can append.\n\n\n this.pendingSegment_.trackInfo = trackInfo; // check if any calls were waiting on the track info\n\n if (this.hasEnoughInfoToAppend_()) {\n this.processCallQueue_();\n }\n };\n\n _proto.handleTimingInfo_ = function handleTimingInfo_(simpleSegment, mediaType, timeType, time) {\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n }\n\n var segmentInfo = this.pendingSegment_;\n var timingInfoProperty = timingInfoPropertyForMedia(mediaType);\n segmentInfo[timingInfoProperty] = segmentInfo[timingInfoProperty] || {};\n segmentInfo[timingInfoProperty][timeType] = time;\n this.logger_(\"timinginfo: \" + mediaType + \" - \" + timeType + \" - \" + time); // check if any calls were waiting on the timing info\n\n if (this.hasEnoughInfoToAppend_()) {\n this.processCallQueue_();\n }\n };\n\n _proto.handleCaptions_ = function handleCaptions_(simpleSegment, captionData) {\n var _this2 = this;\n\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n } // This could only happen with fmp4 segments, but\n // should still not happen in general\n\n\n if (captionData.length === 0) {\n this.logger_('SegmentLoader received no captions from a caption event');\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // Wait until we have some video data so that caption timing\n // can be adjusted by the timestamp offset\n\n if (!segmentInfo.hasAppendedData_) {\n this.metadataQueue_.caption.push(this.handleCaptions_.bind(this, simpleSegment, captionData));\n return;\n }\n\n var timestampOffset = this.sourceUpdater_.videoTimestampOffset() === null ? this.sourceUpdater_.audioTimestampOffset() : this.sourceUpdater_.videoTimestampOffset();\n var captionTracks = {}; // get total start/end and captions for each track/stream\n\n captionData.forEach(function (caption) {\n // caption.stream is actually a track name...\n // set to the existing values in tracks or default values\n captionTracks[caption.stream] = captionTracks[caption.stream] || {\n // Infinity, as any other value will be less than this\n startTime: Infinity,\n captions: [],\n // 0 as an other value will be more than this\n endTime: 0\n };\n var captionTrack = captionTracks[caption.stream];\n captionTrack.startTime = Math.min(captionTrack.startTime, caption.startTime + timestampOffset);\n captionTrack.endTime = Math.max(captionTrack.endTime, caption.endTime + timestampOffset);\n captionTrack.captions.push(caption);\n });\n Object.keys(captionTracks).forEach(function (trackName) {\n var _captionTracks$trackN = captionTracks[trackName],\n startTime = _captionTracks$trackN.startTime,\n endTime = _captionTracks$trackN.endTime,\n captions = _captionTracks$trackN.captions;\n var inbandTextTracks = _this2.inbandTextTracks_;\n\n _this2.logger_(\"adding cues from \" + startTime + \" -> \" + endTime + \" for \" + trackName);\n\n createCaptionsTrackIfNotExists(inbandTextTracks, _this2.vhs_.tech_, trackName); // clear out any cues that start and end at the same time period for the same track.\n // We do this because a rendition change that also changes the timescale for captions\n // will result in captions being re-parsed for certain segments. If we add them again\n // without clearing we will have two of the same captions visible.\n\n removeCuesFromTrack(startTime, endTime, inbandTextTracks[trackName]);\n addCaptionData({\n captionArray: captions,\n inbandTextTracks: inbandTextTracks,\n timestampOffset: timestampOffset\n });\n }); // Reset stored captions since we added parsed\n // captions to a text track at this point\n\n if (this.transmuxer_) {\n this.transmuxer_.postMessage({\n action: 'clearParsedMp4Captions'\n });\n }\n };\n\n _proto.handleId3_ = function handleId3_(simpleSegment, id3Frames, dispatchType) {\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // we need to have appended data in order for the timestamp offset to be set\n\n if (!segmentInfo.hasAppendedData_) {\n this.metadataQueue_.id3.push(this.handleId3_.bind(this, simpleSegment, id3Frames, dispatchType));\n return;\n }\n\n var timestampOffset = this.sourceUpdater_.videoTimestampOffset() === null ? this.sourceUpdater_.audioTimestampOffset() : this.sourceUpdater_.videoTimestampOffset(); // There's potentially an issue where we could double add metadata if there's a muxed\n // audio/video source with a metadata track, and an alt audio with a metadata track.\n // However, this probably won't happen, and if it does it can be handled then.\n\n createMetadataTrackIfNotExists(this.inbandTextTracks_, dispatchType, this.vhs_.tech_);\n addMetadata({\n inbandTextTracks: this.inbandTextTracks_,\n metadataArray: id3Frames,\n timestampOffset: timestampOffset,\n videoDuration: this.duration_()\n });\n };\n\n _proto.processMetadataQueue_ = function processMetadataQueue_() {\n this.metadataQueue_.id3.forEach(function (fn) {\n return fn();\n });\n this.metadataQueue_.caption.forEach(function (fn) {\n return fn();\n });\n this.metadataQueue_.id3 = [];\n this.metadataQueue_.caption = [];\n };\n\n _proto.processCallQueue_ = function processCallQueue_() {\n var callQueue = this.callQueue_; // Clear out the queue before the queued functions are run, since some of the\n // functions may check the length of the load queue and default to pushing themselves\n // back onto the queue.\n\n this.callQueue_ = [];\n callQueue.forEach(function (fun) {\n return fun();\n });\n };\n\n _proto.processLoadQueue_ = function processLoadQueue_() {\n var loadQueue = this.loadQueue_; // Clear out the queue before the queued functions are run, since some of the\n // functions may check the length of the load queue and default to pushing themselves\n // back onto the queue.\n\n this.loadQueue_ = [];\n loadQueue.forEach(function (fun) {\n return fun();\n });\n }\n /**\n * Determines whether the loader has enough info to load the next segment.\n *\n * @return {boolean}\n * Whether or not the loader has enough info to load the next segment\n */\n ;\n\n _proto.hasEnoughInfoToLoad_ = function hasEnoughInfoToLoad_() {\n // Since primary timing goes by video, only the audio loader potentially needs to wait\n // to load.\n if (this.loaderType_ !== 'audio') {\n return true;\n }\n\n var segmentInfo = this.pendingSegment_; // A fill buffer must have already run to establish a pending segment before there's\n // enough info to load.\n\n if (!segmentInfo) {\n return false;\n } // The first segment can and should be loaded immediately so that source buffers are\n // created together (before appending). Source buffer creation uses the presence of\n // audio and video data to determine whether to create audio/video source buffers, and\n // uses processed (transmuxed or parsed) media to determine the types required.\n\n\n if (!this.getCurrentMediaInfo_()) {\n return true;\n }\n\n if ( // Technically, instead of waiting to load a segment on timeline changes, a segment\n // can be requested and downloaded and only wait before it is transmuxed or parsed.\n // But in practice, there are a few reasons why it is better to wait until a loader\n // is ready to append that segment before requesting and downloading:\n //\n // 1. Because audio and main loaders cross discontinuities together, if this loader\n // is waiting for the other to catch up, then instead of requesting another\n // segment and using up more bandwidth, by not yet loading, more bandwidth is\n // allotted to the loader currently behind.\n // 2. media-segment-request doesn't have to have logic to consider whether a segment\n // is ready to be processed or not, isolating the queueing behavior to the loader.\n // 3. The audio loader bases some of its segment properties on timing information\n // provided by the main loader, meaning that, if the logic for waiting on\n // processing was in media-segment-request, then it would also need to know how\n // to re-generate the segment information after the main loader caught up.\n shouldWaitForTimelineChange({\n timelineChangeController: this.timelineChangeController_,\n currentTimeline: this.currentTimeline_,\n segmentTimeline: segmentInfo.timeline,\n loaderType: this.loaderType_,\n audioDisabled: this.audioDisabled_\n })) {\n return false;\n }\n\n return true;\n };\n\n _proto.getCurrentMediaInfo_ = function getCurrentMediaInfo_(segmentInfo) {\n if (segmentInfo === void 0) {\n segmentInfo = this.pendingSegment_;\n }\n\n return segmentInfo && segmentInfo.trackInfo || this.currentMediaInfo_;\n };\n\n _proto.getMediaInfo_ = function getMediaInfo_(segmentInfo) {\n if (segmentInfo === void 0) {\n segmentInfo = this.pendingSegment_;\n }\n\n return this.getCurrentMediaInfo_(segmentInfo) || this.startingMediaInfo_;\n };\n\n _proto.hasEnoughInfoToAppend_ = function hasEnoughInfoToAppend_() {\n if (!this.sourceUpdater_.ready()) {\n return false;\n } // If content needs to be removed or the loader is waiting on an append reattempt,\n // then no additional content should be appended until the prior append is resolved.\n\n\n if (this.waitingOnRemove_ || this.quotaExceededErrorRetryTimeout_) {\n return false;\n }\n\n var segmentInfo = this.pendingSegment_;\n var trackInfo = this.getCurrentMediaInfo_(); // no segment to append any data for or\n // we do not have information on this specific\n // segment yet\n\n if (!segmentInfo || !trackInfo) {\n return false;\n }\n\n var hasAudio = trackInfo.hasAudio,\n hasVideo = trackInfo.hasVideo,\n isMuxed = trackInfo.isMuxed;\n\n if (hasVideo && !segmentInfo.videoTimingInfo) {\n return false;\n } // muxed content only relies on video timing information for now.\n\n\n if (hasAudio && !this.audioDisabled_ && !isMuxed && !segmentInfo.audioTimingInfo) {\n return false;\n }\n\n if (shouldWaitForTimelineChange({\n timelineChangeController: this.timelineChangeController_,\n currentTimeline: this.currentTimeline_,\n segmentTimeline: segmentInfo.timeline,\n loaderType: this.loaderType_,\n audioDisabled: this.audioDisabled_\n })) {\n return false;\n }\n\n return true;\n };\n\n _proto.handleData_ = function handleData_(simpleSegment, result) {\n this.earlyAbortWhenNeeded_(simpleSegment.stats);\n\n if (this.checkForAbort_(simpleSegment.requestId)) {\n return;\n } // If there's anything in the call queue, then this data came later and should be\n // executed after the calls currently queued.\n\n\n if (this.callQueue_.length || !this.hasEnoughInfoToAppend_()) {\n this.callQueue_.push(this.handleData_.bind(this, simpleSegment, result));\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // update the time mapping so we can translate from display time to media time\n\n this.setTimeMapping_(segmentInfo.timeline); // for tracking overall stats\n\n this.updateMediaSecondsLoaded_(segmentInfo.part || segmentInfo.segment); // Note that the state isn't changed from loading to appending. This is because abort\n // logic may change behavior depending on the state, and changing state too early may\n // inflate our estimates of bandwidth. In the future this should be re-examined to\n // note more granular states.\n // don't process and append data if the mediaSource is closed\n\n if (this.mediaSource_.readyState === 'closed') {\n return;\n } // if this request included an initialization segment, save that data\n // to the initSegment cache\n\n\n if (simpleSegment.map) {\n simpleSegment.map = this.initSegmentForMap(simpleSegment.map, true); // move over init segment properties to media request\n\n segmentInfo.segment.map = simpleSegment.map;\n } // if this request included a segment key, save that data in the cache\n\n\n if (simpleSegment.key) {\n this.segmentKey(simpleSegment.key, true);\n }\n\n segmentInfo.isFmp4 = simpleSegment.isFmp4;\n segmentInfo.timingInfo = segmentInfo.timingInfo || {};\n\n if (segmentInfo.isFmp4) {\n this.trigger('fmp4');\n segmentInfo.timingInfo.start = segmentInfo[timingInfoPropertyForMedia(result.type)].start;\n } else {\n var trackInfo = this.getCurrentMediaInfo_();\n var useVideoTimingInfo = this.loaderType_ === 'main' && trackInfo && trackInfo.hasVideo;\n var firstVideoFrameTimeForData;\n\n if (useVideoTimingInfo) {\n firstVideoFrameTimeForData = segmentInfo.videoTimingInfo.start;\n } // Segment loader knows more about segment timing than the transmuxer (in certain\n // aspects), so make any changes required for a more accurate start time.\n // Don't set the end time yet, as the segment may not be finished processing.\n\n\n segmentInfo.timingInfo.start = this.trueSegmentStart_({\n currentStart: segmentInfo.timingInfo.start,\n playlist: segmentInfo.playlist,\n mediaIndex: segmentInfo.mediaIndex,\n currentVideoTimestampOffset: this.sourceUpdater_.videoTimestampOffset(),\n useVideoTimingInfo: useVideoTimingInfo,\n firstVideoFrameTimeForData: firstVideoFrameTimeForData,\n videoTimingInfo: segmentInfo.videoTimingInfo,\n audioTimingInfo: segmentInfo.audioTimingInfo\n });\n } // Init segments for audio and video only need to be appended in certain cases. Now\n // that data is about to be appended, we can check the final cases to determine\n // whether we should append an init segment.\n\n\n this.updateAppendInitSegmentStatus(segmentInfo, result.type); // Timestamp offset should be updated once we get new data and have its timing info,\n // as we use the start of the segment to offset the best guess (playlist provided)\n // timestamp offset.\n\n this.updateSourceBufferTimestampOffset_(segmentInfo); // if this is a sync request we need to determine whether it should\n // be appended or not.\n\n if (segmentInfo.isSyncRequest) {\n // first save/update our timing info for this segment.\n // this is what allows us to choose an accurate segment\n // and the main reason we make a sync request.\n this.updateTimingInfoEnd_(segmentInfo);\n this.syncController_.saveSegmentTimingInfo({\n segmentInfo: segmentInfo,\n shouldSaveTimelineMapping: this.loaderType_ === 'main'\n });\n var next = this.chooseNextRequest_(); // If the sync request isn't the segment that would be requested next\n // after taking into account its timing info, do not append it.\n\n if (next.mediaIndex !== segmentInfo.mediaIndex || next.partIndex !== segmentInfo.partIndex) {\n this.logger_('sync segment was incorrect, not appending');\n return;\n } // otherwise append it like any other segment as our guess was correct.\n\n\n this.logger_('sync segment was correct, appending');\n } // Save some state so that in the future anything waiting on first append (and/or\n // timestamp offset(s)) can process immediately. While the extra state isn't optimal,\n // we need some notion of whether the timestamp offset or other relevant information\n // has had a chance to be set.\n\n\n segmentInfo.hasAppendedData_ = true; // Now that the timestamp offset should be set, we can append any waiting ID3 tags.\n\n this.processMetadataQueue_();\n this.appendData_(segmentInfo, result);\n };\n\n _proto.updateAppendInitSegmentStatus = function updateAppendInitSegmentStatus(segmentInfo, type) {\n // alt audio doesn't manage timestamp offset\n if (this.loaderType_ === 'main' && typeof segmentInfo.timestampOffset === 'number' && // in the case that we're handling partial data, we don't want to append an init\n // segment for each chunk\n !segmentInfo.changedTimestampOffset) {\n // if the timestamp offset changed, the timeline may have changed, so we have to re-\n // append init segments\n this.appendInitSegment_ = {\n audio: true,\n video: true\n };\n }\n\n if (this.playlistOfLastInitSegment_[type] !== segmentInfo.playlist) {\n // make sure we append init segment on playlist changes, in case the media config\n // changed\n this.appendInitSegment_[type] = true;\n }\n };\n\n _proto.getInitSegmentAndUpdateState_ = function getInitSegmentAndUpdateState_(_ref4) {\n var type = _ref4.type,\n initSegment = _ref4.initSegment,\n map = _ref4.map,\n playlist = _ref4.playlist;\n\n // \"The EXT-X-MAP tag specifies how to obtain the Media Initialization Section\n // (Section 3) required to parse the applicable Media Segments. It applies to every\n // Media Segment that appears after it in the Playlist until the next EXT-X-MAP tag\n // or until the end of the playlist.\"\n // https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.2.5\n if (map) {\n var id = initSegmentId(map);\n\n if (this.activeInitSegmentId_ === id) {\n // don't need to re-append the init segment if the ID matches\n return null;\n } // a map-specified init segment takes priority over any transmuxed (or otherwise\n // obtained) init segment\n //\n // this also caches the init segment for later use\n\n\n initSegment = this.initSegmentForMap(map, true).bytes;\n this.activeInitSegmentId_ = id;\n } // We used to always prepend init segments for video, however, that shouldn't be\n // necessary. Instead, we should only append on changes, similar to what we've always\n // done for audio. This is more important (though may not be that important) for\n // frame-by-frame appending for LHLS, simply because of the increased quantity of\n // appends.\n\n\n if (initSegment && this.appendInitSegment_[type]) {\n // Make sure we track the playlist that we last used for the init segment, so that\n // we can re-append the init segment in the event that we get data from a new\n // playlist. Discontinuities and track changes are handled in other sections.\n this.playlistOfLastInitSegment_[type] = playlist; // Disable future init segment appends for this type. Until a change is necessary.\n\n this.appendInitSegment_[type] = false; // we need to clear out the fmp4 active init segment id, since\n // we are appending the muxer init segment\n\n this.activeInitSegmentId_ = null;\n return initSegment;\n }\n\n return null;\n };\n\n _proto.handleQuotaExceededError_ = function handleQuotaExceededError_(_ref5, error) {\n var _this3 = this;\n\n var segmentInfo = _ref5.segmentInfo,\n type = _ref5.type,\n bytes = _ref5.bytes;\n var audioBuffered = this.sourceUpdater_.audioBuffered();\n var videoBuffered = this.sourceUpdater_.videoBuffered(); // For now we're ignoring any notion of gaps in the buffer, but they, in theory,\n // should be cleared out during the buffer removals. However, log in case it helps\n // debug.\n\n if (audioBuffered.length > 1) {\n this.logger_('On QUOTA_EXCEEDED_ERR, found gaps in the audio buffer: ' + timeRangesToArray(audioBuffered).join(', '));\n }\n\n if (videoBuffered.length > 1) {\n this.logger_('On QUOTA_EXCEEDED_ERR, found gaps in the video buffer: ' + timeRangesToArray(videoBuffered).join(', '));\n }\n\n var audioBufferStart = audioBuffered.length ? audioBuffered.start(0) : 0;\n var audioBufferEnd = audioBuffered.length ? audioBuffered.end(audioBuffered.length - 1) : 0;\n var videoBufferStart = videoBuffered.length ? videoBuffered.start(0) : 0;\n var videoBufferEnd = videoBuffered.length ? videoBuffered.end(videoBuffered.length - 1) : 0;\n\n if (audioBufferEnd - audioBufferStart <= MIN_BACK_BUFFER && videoBufferEnd - videoBufferStart <= MIN_BACK_BUFFER) {\n // Can't remove enough buffer to make room for new segment (or the browser doesn't\n // allow for appends of segments this size). In the future, it may be possible to\n // split up the segment and append in pieces, but for now, error out this playlist\n // in an attempt to switch to a more manageable rendition.\n this.logger_('On QUOTA_EXCEEDED_ERR, single segment too large to append to ' + 'buffer, triggering an error. ' + (\"Appended byte length: \" + bytes.byteLength + \", \") + (\"audio buffer: \" + timeRangesToArray(audioBuffered).join(', ') + \", \") + (\"video buffer: \" + timeRangesToArray(videoBuffered).join(', ') + \", \"));\n this.error({\n message: 'Quota exceeded error with append of a single segment of content',\n excludeUntil: Infinity\n });\n this.trigger('error');\n return;\n } // To try to resolve the quota exceeded error, clear back buffer and retry. This means\n // that the segment-loader should block on future events until this one is handled, so\n // that it doesn't keep moving onto further segments. Adding the call to the call\n // queue will prevent further appends until waitingOnRemove_ and\n // quotaExceededErrorRetryTimeout_ are cleared.\n //\n // Note that this will only block the current loader. In the case of demuxed content,\n // the other load may keep filling as fast as possible. In practice, this should be\n // OK, as it is a rare case when either audio has a high enough bitrate to fill up a\n // source buffer, or video fills without enough room for audio to append (and without\n // the availability of clearing out seconds of back buffer to make room for audio).\n // But it might still be good to handle this case in the future as a TODO.\n\n\n this.waitingOnRemove_ = true;\n this.callQueue_.push(this.appendToSourceBuffer_.bind(this, {\n segmentInfo: segmentInfo,\n type: type,\n bytes: bytes\n }));\n var currentTime = this.currentTime_(); // Try to remove as much audio and video as possible to make room for new content\n // before retrying.\n\n var timeToRemoveUntil = currentTime - MIN_BACK_BUFFER;\n this.logger_(\"On QUOTA_EXCEEDED_ERR, removing audio/video from 0 to \" + timeToRemoveUntil);\n this.remove(0, timeToRemoveUntil, function () {\n _this3.logger_(\"On QUOTA_EXCEEDED_ERR, retrying append in \" + MIN_BACK_BUFFER + \"s\");\n\n _this3.waitingOnRemove_ = false; // wait the length of time alotted in the back buffer to prevent wasted\n // attempts (since we can't clear less than the minimum)\n\n _this3.quotaExceededErrorRetryTimeout_ = window$1.setTimeout(function () {\n _this3.logger_('On QUOTA_EXCEEDED_ERR, re-processing call queue');\n\n _this3.quotaExceededErrorRetryTimeout_ = null;\n\n _this3.processCallQueue_();\n }, MIN_BACK_BUFFER * 1000);\n }, true);\n };\n\n _proto.handleAppendError_ = function handleAppendError_(_ref6, error) {\n var segmentInfo = _ref6.segmentInfo,\n type = _ref6.type,\n bytes = _ref6.bytes;\n\n // if there's no error, nothing to do\n if (!error) {\n return;\n }\n\n if (error.code === QUOTA_EXCEEDED_ERR) {\n this.handleQuotaExceededError_({\n segmentInfo: segmentInfo,\n type: type,\n bytes: bytes\n }); // A quota exceeded error should be recoverable with a future re-append, so no need\n // to trigger an append error.\n\n return;\n }\n\n this.logger_('Received non QUOTA_EXCEEDED_ERR on append', error);\n this.error(type + \" append of \" + bytes.length + \"b failed for segment \" + (\"#\" + segmentInfo.mediaIndex + \" in playlist \" + segmentInfo.playlist.id)); // If an append errors, we often can't recover.\n // (see https://w3c.github.io/media-source/#sourcebuffer-append-error).\n //\n // Trigger a special error so that it can be handled separately from normal,\n // recoverable errors.\n\n this.trigger('appenderror');\n };\n\n _proto.appendToSourceBuffer_ = function appendToSourceBuffer_(_ref7) {\n var segmentInfo = _ref7.segmentInfo,\n type = _ref7.type,\n initSegment = _ref7.initSegment,\n data = _ref7.data,\n bytes = _ref7.bytes;\n\n // If this is a re-append, bytes were already created and don't need to be recreated\n if (!bytes) {\n var segments = [data];\n var byteLength = data.byteLength;\n\n if (initSegment) {\n // if the media initialization segment is changing, append it before the content\n // segment\n segments.unshift(initSegment);\n byteLength += initSegment.byteLength;\n } // Technically we should be OK appending the init segment separately, however, we\n // haven't yet tested that, and prepending is how we have always done things.\n\n\n bytes = concatSegments({\n bytes: byteLength,\n segments: segments\n });\n }\n\n this.sourceUpdater_.appendBuffer({\n segmentInfo: segmentInfo,\n type: type,\n bytes: bytes\n }, this.handleAppendError_.bind(this, {\n segmentInfo: segmentInfo,\n type: type,\n bytes: bytes\n }));\n };\n\n _proto.handleSegmentTimingInfo_ = function handleSegmentTimingInfo_(type, requestId, segmentTimingInfo) {\n if (!this.pendingSegment_ || requestId !== this.pendingSegment_.requestId) {\n return;\n }\n\n var segment = this.pendingSegment_.segment;\n var timingInfoProperty = type + \"TimingInfo\";\n\n if (!segment[timingInfoProperty]) {\n segment[timingInfoProperty] = {};\n }\n\n segment[timingInfoProperty].transmuxerPrependedSeconds = segmentTimingInfo.prependedContentDuration || 0;\n segment[timingInfoProperty].transmuxedPresentationStart = segmentTimingInfo.start.presentation;\n segment[timingInfoProperty].transmuxedDecodeStart = segmentTimingInfo.start.decode;\n segment[timingInfoProperty].transmuxedPresentationEnd = segmentTimingInfo.end.presentation;\n segment[timingInfoProperty].transmuxedDecodeEnd = segmentTimingInfo.end.decode; // mainly used as a reference for debugging\n\n segment[timingInfoProperty].baseMediaDecodeTime = segmentTimingInfo.baseMediaDecodeTime;\n };\n\n _proto.appendData_ = function appendData_(segmentInfo, result) {\n var type = result.type,\n data = result.data;\n\n if (!data || !data.byteLength) {\n return;\n }\n\n if (type === 'audio' && this.audioDisabled_) {\n return;\n }\n\n var initSegment = this.getInitSegmentAndUpdateState_({\n type: type,\n initSegment: result.initSegment,\n playlist: segmentInfo.playlist,\n map: segmentInfo.isFmp4 ? segmentInfo.segment.map : null\n });\n this.appendToSourceBuffer_({\n segmentInfo: segmentInfo,\n type: type,\n initSegment: initSegment,\n data: data\n });\n }\n /**\n * load a specific segment from a request into the buffer\n *\n * @private\n */\n ;\n\n _proto.loadSegment_ = function loadSegment_(segmentInfo) {\n var _this4 = this;\n\n this.state = 'WAITING';\n this.pendingSegment_ = segmentInfo;\n this.trimBackBuffer_(segmentInfo);\n\n if (typeof segmentInfo.timestampOffset === 'number') {\n if (this.transmuxer_) {\n this.transmuxer_.postMessage({\n action: 'clearAllMp4Captions'\n });\n }\n }\n\n if (!this.hasEnoughInfoToLoad_()) {\n this.loadQueue_.push(function () {\n // regenerate the audioAppendStart, timestampOffset, etc as they\n // may have changed since this function was added to the queue.\n var options = _extends({}, segmentInfo, {\n forceTimestampOffset: true\n });\n\n _extends(segmentInfo, _this4.generateSegmentInfo_(options));\n\n _this4.isPendingTimestampOffset_ = false;\n\n _this4.updateTransmuxerAndRequestSegment_(segmentInfo);\n });\n return;\n }\n\n this.updateTransmuxerAndRequestSegment_(segmentInfo);\n };\n\n _proto.updateTransmuxerAndRequestSegment_ = function updateTransmuxerAndRequestSegment_(segmentInfo) {\n var _this5 = this;\n\n // We'll update the source buffer's timestamp offset once we have transmuxed data, but\n // the transmuxer still needs to be updated before then.\n //\n // Even though keepOriginalTimestamps is set to true for the transmuxer, timestamp\n // offset must be passed to the transmuxer for stream correcting adjustments.\n if (this.shouldUpdateTransmuxerTimestampOffset_(segmentInfo.timestampOffset)) {\n this.gopBuffer_.length = 0; // gopsToAlignWith was set before the GOP buffer was cleared\n\n segmentInfo.gopsToAlignWith = [];\n this.timeMapping_ = 0; // reset values in the transmuxer since a discontinuity should start fresh\n\n this.transmuxer_.postMessage({\n action: 'reset'\n });\n this.transmuxer_.postMessage({\n action: 'setTimestampOffset',\n timestampOffset: segmentInfo.timestampOffset\n });\n }\n\n var simpleSegment = this.createSimplifiedSegmentObj_(segmentInfo);\n var isEndOfStream = this.isEndOfStream_(segmentInfo.mediaIndex, segmentInfo.playlist, segmentInfo.partIndex);\n var isWalkingForward = this.mediaIndex !== null;\n var isDiscontinuity = segmentInfo.timeline !== this.currentTimeline_ && // currentTimeline starts at -1, so we shouldn't end the timeline switching to 0,\n // the first timeline\n segmentInfo.timeline > 0;\n var isEndOfTimeline = isEndOfStream || isWalkingForward && isDiscontinuity;\n this.logger_(\"Requesting \" + segmentInfoString(segmentInfo)); // If there's an init segment associated with this segment, but it is not cached (identified by a lack of bytes),\n // then this init segment has never been seen before and should be appended.\n //\n // At this point the content type (audio/video or both) is not yet known, but it should be safe to set\n // both to true and leave the decision of whether to append the init segment to append time.\n\n if (simpleSegment.map && !simpleSegment.map.bytes) {\n this.logger_('going to request init segment.');\n this.appendInitSegment_ = {\n video: true,\n audio: true\n };\n }\n\n segmentInfo.abortRequests = mediaSegmentRequest({\n xhr: this.vhs_.xhr,\n xhrOptions: this.xhrOptions_,\n decryptionWorker: this.decrypter_,\n segment: simpleSegment,\n abortFn: this.handleAbort_.bind(this, segmentInfo),\n progressFn: this.handleProgress_.bind(this),\n trackInfoFn: this.handleTrackInfo_.bind(this),\n timingInfoFn: this.handleTimingInfo_.bind(this),\n videoSegmentTimingInfoFn: this.handleSegmentTimingInfo_.bind(this, 'video', segmentInfo.requestId),\n audioSegmentTimingInfoFn: this.handleSegmentTimingInfo_.bind(this, 'audio', segmentInfo.requestId),\n captionsFn: this.handleCaptions_.bind(this),\n isEndOfTimeline: isEndOfTimeline,\n endedTimelineFn: function endedTimelineFn() {\n _this5.logger_('received endedtimeline callback');\n },\n id3Fn: this.handleId3_.bind(this),\n dataFn: this.handleData_.bind(this),\n doneFn: this.segmentRequestFinished_.bind(this),\n onTransmuxerLog: function onTransmuxerLog(_ref8) {\n var message = _ref8.message,\n level = _ref8.level,\n stream = _ref8.stream;\n\n _this5.logger_(segmentInfoString(segmentInfo) + \" logged from transmuxer stream \" + stream + \" as a \" + level + \": \" + message);\n }\n });\n }\n /**\n * trim the back buffer so that we don't have too much data\n * in the source buffer\n *\n * @private\n *\n * @param {Object} segmentInfo - the current segment\n */\n ;\n\n _proto.trimBackBuffer_ = function trimBackBuffer_(segmentInfo) {\n var removeToTime = safeBackBufferTrimTime(this.seekable_(), this.currentTime_(), this.playlist_.targetDuration || 10); // Chrome has a hard limit of 150MB of\n // buffer and a very conservative \"garbage collector\"\n // We manually clear out the old buffer to ensure\n // we don't trigger the QuotaExceeded error\n // on the source buffer during subsequent appends\n\n if (removeToTime > 0) {\n this.remove(0, removeToTime);\n }\n }\n /**\n * created a simplified copy of the segment object with just the\n * information necessary to perform the XHR and decryption\n *\n * @private\n *\n * @param {Object} segmentInfo - the current segment\n * @return {Object} a simplified segment object copy\n */\n ;\n\n _proto.createSimplifiedSegmentObj_ = function createSimplifiedSegmentObj_(segmentInfo) {\n var segment = segmentInfo.segment;\n var part = segmentInfo.part;\n var simpleSegment = {\n resolvedUri: part ? part.resolvedUri : segment.resolvedUri,\n byterange: part ? part.byterange : segment.byterange,\n requestId: segmentInfo.requestId,\n transmuxer: segmentInfo.transmuxer,\n audioAppendStart: segmentInfo.audioAppendStart,\n gopsToAlignWith: segmentInfo.gopsToAlignWith,\n part: segmentInfo.part\n };\n var previousSegment = segmentInfo.playlist.segments[segmentInfo.mediaIndex - 1];\n\n if (previousSegment && previousSegment.timeline === segment.timeline) {\n // The baseStartTime of a segment is used to handle rollover when probing the TS\n // segment to retrieve timing information. Since the probe only looks at the media's\n // times (e.g., PTS and DTS values of the segment), and doesn't consider the\n // player's time (e.g., player.currentTime()), baseStartTime should reflect the\n // media time as well. transmuxedDecodeEnd represents the end time of a segment, in\n // seconds of media time, so should be used here. The previous segment is used since\n // the end of the previous segment should represent the beginning of the current\n // segment, so long as they are on the same timeline.\n if (previousSegment.videoTimingInfo) {\n simpleSegment.baseStartTime = previousSegment.videoTimingInfo.transmuxedDecodeEnd;\n } else if (previousSegment.audioTimingInfo) {\n simpleSegment.baseStartTime = previousSegment.audioTimingInfo.transmuxedDecodeEnd;\n }\n }\n\n if (segment.key) {\n // if the media sequence is greater than 2^32, the IV will be incorrect\n // assuming 10s segments, that would be about 1300 years\n var iv = segment.key.iv || new Uint32Array([0, 0, 0, segmentInfo.mediaIndex + segmentInfo.playlist.mediaSequence]);\n simpleSegment.key = this.segmentKey(segment.key);\n simpleSegment.key.iv = iv;\n }\n\n if (segment.map) {\n simpleSegment.map = this.initSegmentForMap(segment.map);\n }\n\n return simpleSegment;\n };\n\n _proto.saveTransferStats_ = function saveTransferStats_(stats) {\n // every request counts as a media request even if it has been aborted\n // or canceled due to a timeout\n this.mediaRequests += 1;\n\n if (stats) {\n this.mediaBytesTransferred += stats.bytesReceived;\n this.mediaTransferDuration += stats.roundTripTime;\n }\n };\n\n _proto.saveBandwidthRelatedStats_ = function saveBandwidthRelatedStats_(duration, stats) {\n // byteLength will be used for throughput, and should be based on bytes receieved,\n // which we only know at the end of the request and should reflect total bytes\n // downloaded rather than just bytes processed from components of the segment\n this.pendingSegment_.byteLength = stats.bytesReceived;\n\n if (duration < MIN_SEGMENT_DURATION_TO_SAVE_STATS) {\n this.logger_(\"Ignoring segment's bandwidth because its duration of \" + duration + (\" is less than the min to record \" + MIN_SEGMENT_DURATION_TO_SAVE_STATS));\n return;\n }\n\n this.bandwidth = stats.bandwidth;\n this.roundTrip = stats.roundTripTime;\n };\n\n _proto.handleTimeout_ = function handleTimeout_() {\n // although the VTT segment loader bandwidth isn't really used, it's good to\n // maintain functinality between segment loaders\n this.mediaRequestsTimedout += 1;\n this.bandwidth = 1;\n this.roundTrip = NaN;\n this.trigger('bandwidthupdate');\n }\n /**\n * Handle the callback from the segmentRequest function and set the\n * associated SegmentLoader state and errors if necessary\n *\n * @private\n */\n ;\n\n _proto.segmentRequestFinished_ = function segmentRequestFinished_(error, simpleSegment, result) {\n // TODO handle special cases, e.g., muxed audio/video but only audio in the segment\n // check the call queue directly since this function doesn't need to deal with any\n // data, and can continue even if the source buffers are not set up and we didn't get\n // any data from the segment\n if (this.callQueue_.length) {\n this.callQueue_.push(this.segmentRequestFinished_.bind(this, error, simpleSegment, result));\n return;\n }\n\n this.saveTransferStats_(simpleSegment.stats); // The request was aborted and the SegmentLoader has already been reset\n\n if (!this.pendingSegment_) {\n return;\n } // the request was aborted and the SegmentLoader has already started\n // another request. this can happen when the timeout for an aborted\n // request triggers due to a limitation in the XHR library\n // do not count this as any sort of request or we risk double-counting\n\n\n if (simpleSegment.requestId !== this.pendingSegment_.requestId) {\n return;\n } // an error occurred from the active pendingSegment_ so reset everything\n\n\n if (error) {\n this.pendingSegment_ = null;\n this.state = 'READY'; // aborts are not a true error condition and nothing corrective needs to be done\n\n if (error.code === REQUEST_ERRORS.ABORTED) {\n return;\n }\n\n this.pause(); // the error is really just that at least one of the requests timed-out\n // set the bandwidth to a very low value and trigger an ABR switch to\n // take emergency action\n\n if (error.code === REQUEST_ERRORS.TIMEOUT) {\n this.handleTimeout_();\n return;\n } // if control-flow has arrived here, then the error is real\n // emit an error event to blacklist the current playlist\n\n\n this.mediaRequestsErrored += 1;\n this.error(error);\n this.trigger('error');\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // the response was a success so set any bandwidth stats the request\n // generated for ABR purposes\n\n this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);\n segmentInfo.endOfAllRequests = simpleSegment.endOfAllRequests;\n\n if (result.gopInfo) {\n this.gopBuffer_ = updateGopBuffer(this.gopBuffer_, result.gopInfo, this.safeAppend_);\n } // Although we may have already started appending on progress, we shouldn't switch the\n // state away from loading until we are officially done loading the segment data.\n\n\n this.state = 'APPENDING'; // used for testing\n\n this.trigger('appending');\n this.waitForAppendsToComplete_(segmentInfo);\n };\n\n _proto.setTimeMapping_ = function setTimeMapping_(timeline) {\n var timelineMapping = this.syncController_.mappingForTimeline(timeline);\n\n if (timelineMapping !== null) {\n this.timeMapping_ = timelineMapping;\n }\n };\n\n _proto.updateMediaSecondsLoaded_ = function updateMediaSecondsLoaded_(segment) {\n if (typeof segment.start === 'number' && typeof segment.end === 'number') {\n this.mediaSecondsLoaded += segment.end - segment.start;\n } else {\n this.mediaSecondsLoaded += segment.duration;\n }\n };\n\n _proto.shouldUpdateTransmuxerTimestampOffset_ = function shouldUpdateTransmuxerTimestampOffset_(timestampOffset) {\n if (timestampOffset === null) {\n return false;\n } // note that we're potentially using the same timestamp offset for both video and\n // audio\n\n\n if (this.loaderType_ === 'main' && timestampOffset !== this.sourceUpdater_.videoTimestampOffset()) {\n return true;\n }\n\n if (!this.audioDisabled_ && timestampOffset !== this.sourceUpdater_.audioTimestampOffset()) {\n return true;\n }\n\n return false;\n };\n\n _proto.trueSegmentStart_ = function trueSegmentStart_(_ref9) {\n var currentStart = _ref9.currentStart,\n playlist = _ref9.playlist,\n mediaIndex = _ref9.mediaIndex,\n firstVideoFrameTimeForData = _ref9.firstVideoFrameTimeForData,\n currentVideoTimestampOffset = _ref9.currentVideoTimestampOffset,\n useVideoTimingInfo = _ref9.useVideoTimingInfo,\n videoTimingInfo = _ref9.videoTimingInfo,\n audioTimingInfo = _ref9.audioTimingInfo;\n\n if (typeof currentStart !== 'undefined') {\n // if start was set once, keep using it\n return currentStart;\n }\n\n if (!useVideoTimingInfo) {\n return audioTimingInfo.start;\n }\n\n var previousSegment = playlist.segments[mediaIndex - 1]; // The start of a segment should be the start of the first full frame contained\n // within that segment. Since the transmuxer maintains a cache of incomplete data\n // from and/or the last frame seen, the start time may reflect a frame that starts\n // in the previous segment. Check for that case and ensure the start time is\n // accurate for the segment.\n\n if (mediaIndex === 0 || !previousSegment || typeof previousSegment.start === 'undefined' || previousSegment.end !== firstVideoFrameTimeForData + currentVideoTimestampOffset) {\n return firstVideoFrameTimeForData;\n }\n\n return videoTimingInfo.start;\n };\n\n _proto.waitForAppendsToComplete_ = function waitForAppendsToComplete_(segmentInfo) {\n var trackInfo = this.getCurrentMediaInfo_(segmentInfo);\n\n if (!trackInfo) {\n this.error({\n message: 'No starting media returned, likely due to an unsupported media format.',\n blacklistDuration: Infinity\n });\n this.trigger('error');\n return;\n } // Although transmuxing is done, appends may not yet be finished. Throw a marker\n // on each queue this loader is responsible for to ensure that the appends are\n // complete.\n\n\n var hasAudio = trackInfo.hasAudio,\n hasVideo = trackInfo.hasVideo,\n isMuxed = trackInfo.isMuxed;\n var waitForVideo = this.loaderType_ === 'main' && hasVideo;\n var waitForAudio = !this.audioDisabled_ && hasAudio && !isMuxed;\n segmentInfo.waitingOnAppends = 0; // segments with no data\n\n if (!segmentInfo.hasAppendedData_) {\n if (!segmentInfo.timingInfo && typeof segmentInfo.timestampOffset === 'number') {\n // When there's no audio or video data in the segment, there's no audio or video\n // timing information.\n //\n // If there's no audio or video timing information, then the timestamp offset\n // can't be adjusted to the appropriate value for the transmuxer and source\n // buffers.\n //\n // Therefore, the next segment should be used to set the timestamp offset.\n this.isPendingTimestampOffset_ = true;\n } // override settings for metadata only segments\n\n\n segmentInfo.timingInfo = {\n start: 0\n };\n segmentInfo.waitingOnAppends++;\n\n if (!this.isPendingTimestampOffset_) {\n // update the timestampoffset\n this.updateSourceBufferTimestampOffset_(segmentInfo); // make sure the metadata queue is processed even though we have\n // no video/audio data.\n\n this.processMetadataQueue_();\n } // append is \"done\" instantly with no data.\n\n\n this.checkAppendsDone_(segmentInfo);\n return;\n } // Since source updater could call back synchronously, do the increments first.\n\n\n if (waitForVideo) {\n segmentInfo.waitingOnAppends++;\n }\n\n if (waitForAudio) {\n segmentInfo.waitingOnAppends++;\n }\n\n if (waitForVideo) {\n this.sourceUpdater_.videoQueueCallback(this.checkAppendsDone_.bind(this, segmentInfo));\n }\n\n if (waitForAudio) {\n this.sourceUpdater_.audioQueueCallback(this.checkAppendsDone_.bind(this, segmentInfo));\n }\n };\n\n _proto.checkAppendsDone_ = function checkAppendsDone_(segmentInfo) {\n if (this.checkForAbort_(segmentInfo.requestId)) {\n return;\n }\n\n segmentInfo.waitingOnAppends--;\n\n if (segmentInfo.waitingOnAppends === 0) {\n this.handleAppendsDone_();\n }\n };\n\n _proto.checkForIllegalMediaSwitch = function checkForIllegalMediaSwitch(trackInfo) {\n var illegalMediaSwitchError = illegalMediaSwitch(this.loaderType_, this.getCurrentMediaInfo_(), trackInfo);\n\n if (illegalMediaSwitchError) {\n this.error({\n message: illegalMediaSwitchError,\n blacklistDuration: Infinity\n });\n this.trigger('error');\n return true;\n }\n\n return false;\n };\n\n _proto.updateSourceBufferTimestampOffset_ = function updateSourceBufferTimestampOffset_(segmentInfo) {\n if (segmentInfo.timestampOffset === null || // we don't yet have the start for whatever media type (video or audio) has\n // priority, timing-wise, so we must wait\n typeof segmentInfo.timingInfo.start !== 'number' || // already updated the timestamp offset for this segment\n segmentInfo.changedTimestampOffset || // the alt audio loader should not be responsible for setting the timestamp offset\n this.loaderType_ !== 'main') {\n return;\n }\n\n var didChange = false; // Primary timing goes by video, and audio is trimmed in the transmuxer, meaning that\n // the timing info here comes from video. In the event that the audio is longer than\n // the video, this will trim the start of the audio.\n // This also trims any offset from 0 at the beginning of the media\n\n segmentInfo.timestampOffset -= segmentInfo.timingInfo.start; // In the event that there are part segment downloads, each will try to update the\n // timestamp offset. Retaining this bit of state prevents us from updating in the\n // future (within the same segment), however, there may be a better way to handle it.\n\n segmentInfo.changedTimestampOffset = true;\n\n if (segmentInfo.timestampOffset !== this.sourceUpdater_.videoTimestampOffset()) {\n this.sourceUpdater_.videoTimestampOffset(segmentInfo.timestampOffset);\n didChange = true;\n }\n\n if (segmentInfo.timestampOffset !== this.sourceUpdater_.audioTimestampOffset()) {\n this.sourceUpdater_.audioTimestampOffset(segmentInfo.timestampOffset);\n didChange = true;\n }\n\n if (didChange) {\n this.trigger('timestampoffset');\n }\n };\n\n _proto.updateTimingInfoEnd_ = function updateTimingInfoEnd_(segmentInfo) {\n segmentInfo.timingInfo = segmentInfo.timingInfo || {};\n var trackInfo = this.getMediaInfo_();\n var useVideoTimingInfo = this.loaderType_ === 'main' && trackInfo && trackInfo.hasVideo;\n var prioritizedTimingInfo = useVideoTimingInfo && segmentInfo.videoTimingInfo ? segmentInfo.videoTimingInfo : segmentInfo.audioTimingInfo;\n\n if (!prioritizedTimingInfo) {\n return;\n }\n\n segmentInfo.timingInfo.end = typeof prioritizedTimingInfo.end === 'number' ? // End time may not exist in a case where we aren't parsing the full segment (one\n // current example is the case of fmp4), so use the rough duration to calculate an\n // end time.\n prioritizedTimingInfo.end : prioritizedTimingInfo.start + segmentInfo.duration;\n }\n /**\n * callback to run when appendBuffer is finished. detects if we are\n * in a good state to do things with the data we got, or if we need\n * to wait for more\n *\n * @private\n */\n ;\n\n _proto.handleAppendsDone_ = function handleAppendsDone_() {\n // appendsdone can cause an abort\n if (this.pendingSegment_) {\n this.trigger('appendsdone');\n }\n\n if (!this.pendingSegment_) {\n this.state = 'READY'; // TODO should this move into this.checkForAbort to speed up requests post abort in\n // all appending cases?\n\n if (!this.paused()) {\n this.monitorBuffer_();\n }\n\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // Now that the end of the segment has been reached, we can set the end time. It's\n // best to wait until all appends are done so we're sure that the primary media is\n // finished (and we have its end time).\n\n this.updateTimingInfoEnd_(segmentInfo);\n\n if (this.shouldSaveSegmentTimingInfo_) {\n // Timeline mappings should only be saved for the main loader. This is for multiple\n // reasons:\n //\n // 1) Only one mapping is saved per timeline, meaning that if both the audio loader\n // and the main loader try to save the timeline mapping, whichever comes later\n // will overwrite the first. In theory this is OK, as the mappings should be the\n // same, however, it breaks for (2)\n // 2) In the event of a live stream, the initial live point will make for a somewhat\n // arbitrary mapping. If audio and video streams are not perfectly in-sync, then\n // the mapping will be off for one of the streams, dependent on which one was\n // first saved (see (1)).\n // 3) Primary timing goes by video in VHS, so the mapping should be video.\n //\n // Since the audio loader will wait for the main loader to load the first segment,\n // the main loader will save the first timeline mapping, and ensure that there won't\n // be a case where audio loads two segments without saving a mapping (thus leading\n // to missing segment timing info).\n this.syncController_.saveSegmentTimingInfo({\n segmentInfo: segmentInfo,\n shouldSaveTimelineMapping: this.loaderType_ === 'main'\n });\n }\n\n var segmentDurationMessage = getTroublesomeSegmentDurationMessage(segmentInfo, this.sourceType_);\n\n if (segmentDurationMessage) {\n if (segmentDurationMessage.severity === 'warn') {\n videojs.log.warn(segmentDurationMessage.message);\n } else {\n this.logger_(segmentDurationMessage.message);\n }\n }\n\n this.recordThroughput_(segmentInfo);\n this.pendingSegment_ = null;\n this.state = 'READY';\n\n if (segmentInfo.isSyncRequest) {\n this.trigger('syncinfoupdate'); // if the sync request was not appended\n // then it was not the correct segment.\n // throw it away and use the data it gave us\n // to get the correct one.\n\n if (!segmentInfo.hasAppendedData_) {\n this.logger_(\"Throwing away un-appended sync request \" + segmentInfoString(segmentInfo));\n return;\n }\n }\n\n this.logger_(\"Appended \" + segmentInfoString(segmentInfo));\n this.addSegmentMetadataCue_(segmentInfo);\n this.fetchAtBuffer_ = true;\n\n if (this.currentTimeline_ !== segmentInfo.timeline) {\n this.timelineChangeController_.lastTimelineChange({\n type: this.loaderType_,\n from: this.currentTimeline_,\n to: segmentInfo.timeline\n }); // If audio is not disabled, the main segment loader is responsible for updating\n // the audio timeline as well. If the content is video only, this won't have any\n // impact.\n\n if (this.loaderType_ === 'main' && !this.audioDisabled_) {\n this.timelineChangeController_.lastTimelineChange({\n type: 'audio',\n from: this.currentTimeline_,\n to: segmentInfo.timeline\n });\n }\n }\n\n this.currentTimeline_ = segmentInfo.timeline; // We must update the syncinfo to recalculate the seekable range before\n // the following conditional otherwise it may consider this a bad \"guess\"\n // and attempt to resync when the post-update seekable window and live\n // point would mean that this was the perfect segment to fetch\n\n this.trigger('syncinfoupdate');\n var segment = segmentInfo.segment;\n var part = segmentInfo.part;\n var badSegmentGuess = segment.end && this.currentTime_() - segment.end > segmentInfo.playlist.targetDuration * 3;\n var badPartGuess = part && part.end && this.currentTime_() - part.end > segmentInfo.playlist.partTargetDuration * 3; // If we previously appended a segment/part that ends more than 3 part/targetDurations before\n // the currentTime_ that means that our conservative guess was too conservative.\n // In that case, reset the loader state so that we try to use any information gained\n // from the previous request to create a new, more accurate, sync-point.\n\n if (badSegmentGuess || badPartGuess) {\n this.logger_(\"bad \" + (badSegmentGuess ? 'segment' : 'part') + \" \" + segmentInfoString(segmentInfo));\n this.resetEverything();\n return;\n }\n\n var isWalkingForward = this.mediaIndex !== null; // Don't do a rendition switch unless we have enough time to get a sync segment\n // and conservatively guess\n\n if (isWalkingForward) {\n this.trigger('bandwidthupdate');\n }\n\n this.trigger('progress');\n this.mediaIndex = segmentInfo.mediaIndex;\n this.partIndex = segmentInfo.partIndex; // any time an update finishes and the last segment is in the\n // buffer, end the stream. this ensures the \"ended\" event will\n // fire if playback reaches that point.\n\n if (this.isEndOfStream_(segmentInfo.mediaIndex, segmentInfo.playlist, segmentInfo.partIndex)) {\n this.endOfStream();\n } // used for testing\n\n\n this.trigger('appended');\n\n if (segmentInfo.hasAppendedData_) {\n this.mediaAppends++;\n }\n\n if (!this.paused()) {\n this.monitorBuffer_();\n }\n }\n /**\n * Records the current throughput of the decrypt, transmux, and append\n * portion of the semgment pipeline. `throughput.rate` is a the cumulative\n * moving average of the throughput. `throughput.count` is the number of\n * data points in the average.\n *\n * @private\n * @param {Object} segmentInfo the object returned by loadSegment\n */\n ;\n\n _proto.recordThroughput_ = function recordThroughput_(segmentInfo) {\n if (segmentInfo.duration < MIN_SEGMENT_DURATION_TO_SAVE_STATS) {\n this.logger_(\"Ignoring segment's throughput because its duration of \" + segmentInfo.duration + (\" is less than the min to record \" + MIN_SEGMENT_DURATION_TO_SAVE_STATS));\n return;\n }\n\n var rate = this.throughput.rate; // Add one to the time to ensure that we don't accidentally attempt to divide\n // by zero in the case where the throughput is ridiculously high\n\n var segmentProcessingTime = Date.now() - segmentInfo.endOfAllRequests + 1; // Multiply by 8000 to convert from bytes/millisecond to bits/second\n\n var segmentProcessingThroughput = Math.floor(segmentInfo.byteLength / segmentProcessingTime * 8 * 1000); // This is just a cumulative moving average calculation:\n // newAvg = oldAvg + (sample - oldAvg) / (sampleCount + 1)\n\n this.throughput.rate += (segmentProcessingThroughput - rate) / ++this.throughput.count;\n }\n /**\n * Adds a cue to the segment-metadata track with some metadata information about the\n * segment\n *\n * @private\n * @param {Object} segmentInfo\n * the object returned by loadSegment\n * @method addSegmentMetadataCue_\n */\n ;\n\n _proto.addSegmentMetadataCue_ = function addSegmentMetadataCue_(segmentInfo) {\n if (!this.segmentMetadataTrack_) {\n return;\n }\n\n var segment = segmentInfo.segment;\n var start = segment.start;\n var end = segment.end; // Do not try adding the cue if the start and end times are invalid.\n\n if (!finite(start) || !finite(end)) {\n return;\n }\n\n removeCuesFromTrack(start, end, this.segmentMetadataTrack_);\n var Cue = window$1.WebKitDataCue || window$1.VTTCue;\n var value = {\n custom: segment.custom,\n dateTimeObject: segment.dateTimeObject,\n dateTimeString: segment.dateTimeString,\n bandwidth: segmentInfo.playlist.attributes.BANDWIDTH,\n resolution: segmentInfo.playlist.attributes.RESOLUTION,\n codecs: segmentInfo.playlist.attributes.CODECS,\n byteLength: segmentInfo.byteLength,\n uri: segmentInfo.uri,\n timeline: segmentInfo.timeline,\n playlist: segmentInfo.playlist.id,\n start: start,\n end: end\n };\n var data = JSON.stringify(value);\n var cue = new Cue(start, end, data); // Attach the metadata to the value property of the cue to keep consistency between\n // the differences of WebKitDataCue in safari and VTTCue in other browsers\n\n cue.value = value;\n this.segmentMetadataTrack_.addCue(cue);\n };\n\n return SegmentLoader;\n}(videojs.EventTarget);\n\nfunction noop() {}\n\nvar toTitleCase = function toTitleCase(string) {\n if (typeof string !== 'string') {\n return string;\n }\n\n return string.replace(/./, function (w) {\n return w.toUpperCase();\n });\n};\n\nvar bufferTypes = ['video', 'audio'];\n\nvar _updating = function updating(type, sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"];\n return sourceBuffer && sourceBuffer.updating || sourceUpdater.queuePending[type];\n};\n\nvar nextQueueIndexOfType = function nextQueueIndexOfType(type, queue) {\n for (var i = 0; i < queue.length; i++) {\n var queueEntry = queue[i];\n\n if (queueEntry.type === 'mediaSource') {\n // If the next entry is a media source entry (uses multiple source buffers), block\n // processing to allow it to go through first.\n return null;\n }\n\n if (queueEntry.type === type) {\n return i;\n }\n }\n\n return null;\n};\n\nvar shiftQueue = function shiftQueue(type, sourceUpdater) {\n if (sourceUpdater.queue.length === 0) {\n return;\n }\n\n var queueIndex = 0;\n var queueEntry = sourceUpdater.queue[queueIndex];\n\n if (queueEntry.type === 'mediaSource') {\n if (!sourceUpdater.updating() && sourceUpdater.mediaSource.readyState !== 'closed') {\n sourceUpdater.queue.shift();\n queueEntry.action(sourceUpdater);\n\n if (queueEntry.doneFn) {\n queueEntry.doneFn();\n } // Only specific source buffer actions must wait for async updateend events. Media\n // Source actions process synchronously. Therefore, both audio and video source\n // buffers are now clear to process the next queue entries.\n\n\n shiftQueue('audio', sourceUpdater);\n shiftQueue('video', sourceUpdater);\n } // Media Source actions require both source buffers, so if the media source action\n // couldn't process yet (because one or both source buffers are busy), block other\n // queue actions until both are available and the media source action can process.\n\n\n return;\n }\n\n if (type === 'mediaSource') {\n // If the queue was shifted by a media source action (this happens when pushing a\n // media source action onto the queue), then it wasn't from an updateend event from an\n // audio or video source buffer, so there's no change from previous state, and no\n // processing should be done.\n return;\n } // Media source queue entries don't need to consider whether the source updater is\n // started (i.e., source buffers are created) as they don't need the source buffers, but\n // source buffer queue entries do.\n\n\n if (!sourceUpdater.ready() || sourceUpdater.mediaSource.readyState === 'closed' || _updating(type, sourceUpdater)) {\n return;\n }\n\n if (queueEntry.type !== type) {\n queueIndex = nextQueueIndexOfType(type, sourceUpdater.queue);\n\n if (queueIndex === null) {\n // Either there's no queue entry that uses this source buffer type in the queue, or\n // there's a media source queue entry before the next entry of this type, in which\n // case wait for that action to process first.\n return;\n }\n\n queueEntry = sourceUpdater.queue[queueIndex];\n }\n\n sourceUpdater.queue.splice(queueIndex, 1); // Keep a record that this source buffer type is in use.\n //\n // The queue pending operation must be set before the action is performed in the event\n // that the action results in a synchronous event that is acted upon. For instance, if\n // an exception is thrown that can be handled, it's possible that new actions will be\n // appended to an empty queue and immediately executed, but would not have the correct\n // pending information if this property was set after the action was performed.\n\n sourceUpdater.queuePending[type] = queueEntry;\n queueEntry.action(type, sourceUpdater);\n\n if (!queueEntry.doneFn) {\n // synchronous operation, process next entry\n sourceUpdater.queuePending[type] = null;\n shiftQueue(type, sourceUpdater);\n return;\n }\n};\n\nvar cleanupBuffer = function cleanupBuffer(type, sourceUpdater) {\n var buffer = sourceUpdater[type + \"Buffer\"];\n var titleType = toTitleCase(type);\n\n if (!buffer) {\n return;\n }\n\n buffer.removeEventListener('updateend', sourceUpdater[\"on\" + titleType + \"UpdateEnd_\"]);\n buffer.removeEventListener('error', sourceUpdater[\"on\" + titleType + \"Error_\"]);\n sourceUpdater.codecs[type] = null;\n sourceUpdater[type + \"Buffer\"] = null;\n};\n\nvar inSourceBuffers = function inSourceBuffers(mediaSource, sourceBuffer) {\n return mediaSource && sourceBuffer && Array.prototype.indexOf.call(mediaSource.sourceBuffers, sourceBuffer) !== -1;\n};\n\nvar actions = {\n appendBuffer: function appendBuffer(bytes, segmentInfo, onError) {\n return function (type, sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"]; // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n }\n\n sourceUpdater.logger_(\"Appending segment \" + segmentInfo.mediaIndex + \"'s \" + bytes.length + \" bytes to \" + type + \"Buffer\");\n\n try {\n sourceBuffer.appendBuffer(bytes);\n } catch (e) {\n sourceUpdater.logger_(\"Error with code \" + e.code + \" \" + (e.code === QUOTA_EXCEEDED_ERR ? '(QUOTA_EXCEEDED_ERR) ' : '') + (\"when appending segment \" + segmentInfo.mediaIndex + \" to \" + type + \"Buffer\"));\n sourceUpdater.queuePending[type] = null;\n onError(e);\n }\n };\n },\n remove: function remove(start, end) {\n return function (type, sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"]; // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n }\n\n sourceUpdater.logger_(\"Removing \" + start + \" to \" + end + \" from \" + type + \"Buffer\");\n\n try {\n sourceBuffer.remove(start, end);\n } catch (e) {\n sourceUpdater.logger_(\"Remove \" + start + \" to \" + end + \" from \" + type + \"Buffer failed\");\n }\n };\n },\n timestampOffset: function timestampOffset(offset) {\n return function (type, sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"]; // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n }\n\n sourceUpdater.logger_(\"Setting \" + type + \"timestampOffset to \" + offset);\n sourceBuffer.timestampOffset = offset;\n };\n },\n callback: function callback(_callback) {\n return function (type, sourceUpdater) {\n _callback();\n };\n },\n endOfStream: function endOfStream(error) {\n return function (sourceUpdater) {\n if (sourceUpdater.mediaSource.readyState !== 'open') {\n return;\n }\n\n sourceUpdater.logger_(\"Calling mediaSource endOfStream(\" + (error || '') + \")\");\n\n try {\n sourceUpdater.mediaSource.endOfStream(error);\n } catch (e) {\n videojs.log.warn('Failed to call media source endOfStream', e);\n }\n };\n },\n duration: function duration(_duration) {\n return function (sourceUpdater) {\n sourceUpdater.logger_(\"Setting mediaSource duration to \" + _duration);\n\n try {\n sourceUpdater.mediaSource.duration = _duration;\n } catch (e) {\n videojs.log.warn('Failed to set media source duration', e);\n }\n };\n },\n abort: function abort() {\n return function (type, sourceUpdater) {\n if (sourceUpdater.mediaSource.readyState !== 'open') {\n return;\n }\n\n var sourceBuffer = sourceUpdater[type + \"Buffer\"]; // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n }\n\n sourceUpdater.logger_(\"calling abort on \" + type + \"Buffer\");\n\n try {\n sourceBuffer.abort();\n } catch (e) {\n videojs.log.warn(\"Failed to abort on \" + type + \"Buffer\", e);\n }\n };\n },\n addSourceBuffer: function addSourceBuffer(type, codec) {\n return function (sourceUpdater) {\n var titleType = toTitleCase(type);\n var mime = getMimeForCodec(codec);\n sourceUpdater.logger_(\"Adding \" + type + \"Buffer with codec \" + codec + \" to mediaSource\");\n var sourceBuffer = sourceUpdater.mediaSource.addSourceBuffer(mime);\n sourceBuffer.addEventListener('updateend', sourceUpdater[\"on\" + titleType + \"UpdateEnd_\"]);\n sourceBuffer.addEventListener('error', sourceUpdater[\"on\" + titleType + \"Error_\"]);\n sourceUpdater.codecs[type] = codec;\n sourceUpdater[type + \"Buffer\"] = sourceBuffer;\n };\n },\n removeSourceBuffer: function removeSourceBuffer(type) {\n return function (sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"];\n cleanupBuffer(type, sourceUpdater); // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n }\n\n sourceUpdater.logger_(\"Removing \" + type + \"Buffer with codec \" + sourceUpdater.codecs[type] + \" from mediaSource\");\n\n try {\n sourceUpdater.mediaSource.removeSourceBuffer(sourceBuffer);\n } catch (e) {\n videojs.log.warn(\"Failed to removeSourceBuffer \" + type + \"Buffer\", e);\n }\n };\n },\n changeType: function changeType(codec) {\n return function (type, sourceUpdater) {\n var sourceBuffer = sourceUpdater[type + \"Buffer\"];\n var mime = getMimeForCodec(codec); // can't do anything if the media source / source buffer is null\n // or the media source does not contain this source buffer.\n\n if (!inSourceBuffers(sourceUpdater.mediaSource, sourceBuffer)) {\n return;\n } // do not update codec if we don't need to.\n\n\n if (sourceUpdater.codecs[type] === codec) {\n return;\n }\n\n sourceUpdater.logger_(\"changing \" + type + \"Buffer codec from \" + sourceUpdater.codecs[type] + \" to \" + codec);\n sourceBuffer.changeType(mime);\n sourceUpdater.codecs[type] = codec;\n };\n }\n};\n\nvar pushQueue = function pushQueue(_ref) {\n var type = _ref.type,\n sourceUpdater = _ref.sourceUpdater,\n action = _ref.action,\n doneFn = _ref.doneFn,\n name = _ref.name;\n sourceUpdater.queue.push({\n type: type,\n action: action,\n doneFn: doneFn,\n name: name\n });\n shiftQueue(type, sourceUpdater);\n};\n\nvar onUpdateend = function onUpdateend(type, sourceUpdater) {\n return function (e) {\n // Although there should, in theory, be a pending action for any updateend receieved,\n // there are some actions that may trigger updateend events without set definitions in\n // the w3c spec. For instance, setting the duration on the media source may trigger\n // updateend events on source buffers. This does not appear to be in the spec. As such,\n // if we encounter an updateend without a corresponding pending action from our queue\n // for that source buffer type, process the next action.\n if (sourceUpdater.queuePending[type]) {\n var doneFn = sourceUpdater.queuePending[type].doneFn;\n sourceUpdater.queuePending[type] = null;\n\n if (doneFn) {\n // if there's an error, report it\n doneFn(sourceUpdater[type + \"Error_\"]);\n }\n }\n\n shiftQueue(type, sourceUpdater);\n };\n};\n/**\n * A queue of callbacks to be serialized and applied when a\n * MediaSource and its associated SourceBuffers are not in the\n * updating state. It is used by the segment loader to update the\n * underlying SourceBuffers when new data is loaded, for instance.\n *\n * @class SourceUpdater\n * @param {MediaSource} mediaSource the MediaSource to create the SourceBuffer from\n * @param {string} mimeType the desired MIME type of the underlying SourceBuffer\n */\n\n\nvar SourceUpdater = /*#__PURE__*/function (_videojs$EventTarget) {\n _inheritsLoose(SourceUpdater, _videojs$EventTarget);\n\n function SourceUpdater(mediaSource) {\n var _this;\n\n _this = _videojs$EventTarget.call(this) || this;\n _this.mediaSource = mediaSource;\n\n _this.sourceopenListener_ = function () {\n return shiftQueue('mediaSource', _assertThisInitialized(_this));\n };\n\n _this.mediaSource.addEventListener('sourceopen', _this.sourceopenListener_);\n\n _this.logger_ = logger('SourceUpdater'); // initial timestamp offset is 0\n\n _this.audioTimestampOffset_ = 0;\n _this.videoTimestampOffset_ = 0;\n _this.queue = [];\n _this.queuePending = {\n audio: null,\n video: null\n };\n _this.delayedAudioAppendQueue_ = [];\n _this.videoAppendQueued_ = false;\n _this.codecs = {};\n _this.onVideoUpdateEnd_ = onUpdateend('video', _assertThisInitialized(_this));\n _this.onAudioUpdateEnd_ = onUpdateend('audio', _assertThisInitialized(_this));\n\n _this.onVideoError_ = function (e) {\n // used for debugging\n _this.videoError_ = e;\n };\n\n _this.onAudioError_ = function (e) {\n // used for debugging\n _this.audioError_ = e;\n };\n\n _this.createdSourceBuffers_ = false;\n _this.initializedEme_ = false;\n _this.triggeredReady_ = false;\n return _this;\n }\n\n var _proto = SourceUpdater.prototype;\n\n _proto.initializedEme = function initializedEme() {\n this.initializedEme_ = true;\n this.triggerReady();\n };\n\n _proto.hasCreatedSourceBuffers = function hasCreatedSourceBuffers() {\n // if false, likely waiting on one of the segment loaders to get enough data to create\n // source buffers\n return this.createdSourceBuffers_;\n };\n\n _proto.hasInitializedAnyEme = function hasInitializedAnyEme() {\n return this.initializedEme_;\n };\n\n _proto.ready = function ready() {\n return this.hasCreatedSourceBuffers() && this.hasInitializedAnyEme();\n };\n\n _proto.createSourceBuffers = function createSourceBuffers(codecs) {\n if (this.hasCreatedSourceBuffers()) {\n // already created them before\n return;\n } // the intial addOrChangeSourceBuffers will always be\n // two add buffers.\n\n\n this.addOrChangeSourceBuffers(codecs);\n this.createdSourceBuffers_ = true;\n this.trigger('createdsourcebuffers');\n this.triggerReady();\n };\n\n _proto.triggerReady = function triggerReady() {\n // only allow ready to be triggered once, this prevents the case\n // where:\n // 1. we trigger createdsourcebuffers\n // 2. ie 11 synchronously initializates eme\n // 3. the synchronous initialization causes us to trigger ready\n // 4. We go back to the ready check in createSourceBuffers and ready is triggered again.\n if (this.ready() && !this.triggeredReady_) {\n this.triggeredReady_ = true;\n this.trigger('ready');\n }\n }\n /**\n * Add a type of source buffer to the media source.\n *\n * @param {string} type\n * The type of source buffer to add.\n *\n * @param {string} codec\n * The codec to add the source buffer with.\n */\n ;\n\n _proto.addSourceBuffer = function addSourceBuffer(type, codec) {\n pushQueue({\n type: 'mediaSource',\n sourceUpdater: this,\n action: actions.addSourceBuffer(type, codec),\n name: 'addSourceBuffer'\n });\n }\n /**\n * call abort on a source buffer.\n *\n * @param {string} type\n * The type of source buffer to call abort on.\n */\n ;\n\n _proto.abort = function abort(type) {\n pushQueue({\n type: type,\n sourceUpdater: this,\n action: actions.abort(type),\n name: 'abort'\n });\n }\n /**\n * Call removeSourceBuffer and remove a specific type\n * of source buffer on the mediaSource.\n *\n * @param {string} type\n * The type of source buffer to remove.\n */\n ;\n\n _proto.removeSourceBuffer = function removeSourceBuffer(type) {\n if (!this.canRemoveSourceBuffer()) {\n videojs.log.error('removeSourceBuffer is not supported!');\n return;\n }\n\n pushQueue({\n type: 'mediaSource',\n sourceUpdater: this,\n action: actions.removeSourceBuffer(type),\n name: 'removeSourceBuffer'\n });\n }\n /**\n * Whether or not the removeSourceBuffer function is supported\n * on the mediaSource.\n *\n * @return {boolean}\n * if removeSourceBuffer can be called.\n */\n ;\n\n _proto.canRemoveSourceBuffer = function canRemoveSourceBuffer() {\n // IE reports that it supports removeSourceBuffer, but often throws\n // errors when attempting to use the function. So we report that it\n // does not support removeSourceBuffer. As of Firefox 83 removeSourceBuffer\n // throws errors, so we report that it does not support this as well.\n return !videojs.browser.IE_VERSION && !videojs.browser.IS_FIREFOX && window$1.MediaSource && window$1.MediaSource.prototype && typeof window$1.MediaSource.prototype.removeSourceBuffer === 'function';\n }\n /**\n * Whether or not the changeType function is supported\n * on our SourceBuffers.\n *\n * @return {boolean}\n * if changeType can be called.\n */\n ;\n\n SourceUpdater.canChangeType = function canChangeType() {\n return window$1.SourceBuffer && window$1.SourceBuffer.prototype && typeof window$1.SourceBuffer.prototype.changeType === 'function';\n }\n /**\n * Whether or not the changeType function is supported\n * on our SourceBuffers.\n *\n * @return {boolean}\n * if changeType can be called.\n */\n ;\n\n _proto.canChangeType = function canChangeType() {\n return this.constructor.canChangeType();\n }\n /**\n * Call the changeType function on a source buffer, given the code and type.\n *\n * @param {string} type\n * The type of source buffer to call changeType on.\n *\n * @param {string} codec\n * The codec string to change type with on the source buffer.\n */\n ;\n\n _proto.changeType = function changeType(type, codec) {\n if (!this.canChangeType()) {\n videojs.log.error('changeType is not supported!');\n return;\n }\n\n pushQueue({\n type: type,\n sourceUpdater: this,\n action: actions.changeType(codec),\n name: 'changeType'\n });\n }\n /**\n * Add source buffers with a codec or, if they are already created,\n * call changeType on source buffers using changeType.\n *\n * @param {Object} codecs\n * Codecs to switch to\n */\n ;\n\n _proto.addOrChangeSourceBuffers = function addOrChangeSourceBuffers(codecs) {\n var _this2 = this;\n\n if (!codecs || typeof codecs !== 'object' || Object.keys(codecs).length === 0) {\n throw new Error('Cannot addOrChangeSourceBuffers to undefined codecs');\n }\n\n Object.keys(codecs).forEach(function (type) {\n var codec = codecs[type];\n\n if (!_this2.hasCreatedSourceBuffers()) {\n return _this2.addSourceBuffer(type, codec);\n }\n\n if (_this2.canChangeType()) {\n _this2.changeType(type, codec);\n }\n });\n }\n /**\n * Queue an update to append an ArrayBuffer.\n *\n * @param {MediaObject} object containing audioBytes and/or videoBytes\n * @param {Function} done the function to call when done\n * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-appendBuffer-void-ArrayBuffer-data\n */\n ;\n\n _proto.appendBuffer = function appendBuffer(options, doneFn) {\n var _this3 = this;\n\n var segmentInfo = options.segmentInfo,\n type = options.type,\n bytes = options.bytes;\n this.processedAppend_ = true;\n\n if (type === 'audio' && this.videoBuffer && !this.videoAppendQueued_) {\n this.delayedAudioAppendQueue_.push([options, doneFn]);\n this.logger_(\"delayed audio append of \" + bytes.length + \" until video append\");\n return;\n } // In the case of certain errors, for instance, QUOTA_EXCEEDED_ERR, updateend will\n // not be fired. This means that the queue will be blocked until the next action\n // taken by the segment-loader. Provide a mechanism for segment-loader to handle\n // these errors by calling the doneFn with the specific error.\n\n\n var onError = doneFn;\n pushQueue({\n type: type,\n sourceUpdater: this,\n action: actions.appendBuffer(bytes, segmentInfo || {\n mediaIndex: -1\n }, onError),\n doneFn: doneFn,\n name: 'appendBuffer'\n });\n\n if (type === 'video') {\n this.videoAppendQueued_ = true;\n\n if (!this.delayedAudioAppendQueue_.length) {\n return;\n }\n\n var queue = this.delayedAudioAppendQueue_.slice();\n this.logger_(\"queuing delayed audio \" + queue.length + \" appendBuffers\");\n this.delayedAudioAppendQueue_.length = 0;\n queue.forEach(function (que) {\n _this3.appendBuffer.apply(_this3, que);\n });\n }\n }\n /**\n * Get the audio buffer's buffered timerange.\n *\n * @return {TimeRange}\n * The audio buffer's buffered time range\n */\n ;\n\n _proto.audioBuffered = function audioBuffered() {\n // no media source/source buffer or it isn't in the media sources\n // source buffer list\n if (!inSourceBuffers(this.mediaSource, this.audioBuffer)) {\n return videojs.createTimeRange();\n }\n\n return this.audioBuffer.buffered ? this.audioBuffer.buffered : videojs.createTimeRange();\n }\n /**\n * Get the video buffer's buffered timerange.\n *\n * @return {TimeRange}\n * The video buffer's buffered time range\n */\n ;\n\n _proto.videoBuffered = function videoBuffered() {\n // no media source/source buffer or it isn't in the media sources\n // source buffer list\n if (!inSourceBuffers(this.mediaSource, this.videoBuffer)) {\n return videojs.createTimeRange();\n }\n\n return this.videoBuffer.buffered ? this.videoBuffer.buffered : videojs.createTimeRange();\n }\n /**\n * Get a combined video/audio buffer's buffered timerange.\n *\n * @return {TimeRange}\n * the combined time range\n */\n ;\n\n _proto.buffered = function buffered() {\n var video = inSourceBuffers(this.mediaSource, this.videoBuffer) ? this.videoBuffer : null;\n var audio = inSourceBuffers(this.mediaSource, this.audioBuffer) ? this.audioBuffer : null;\n\n if (audio && !video) {\n return this.audioBuffered();\n }\n\n if (video && !audio) {\n return this.videoBuffered();\n }\n\n return bufferIntersection(this.audioBuffered(), this.videoBuffered());\n }\n /**\n * Add a callback to the queue that will set duration on the mediaSource.\n *\n * @param {number} duration\n * The duration to set\n *\n * @param {Function} [doneFn]\n * function to run after duration has been set.\n */\n ;\n\n _proto.setDuration = function setDuration(duration, doneFn) {\n if (doneFn === void 0) {\n doneFn = noop;\n }\n\n // In order to set the duration on the media source, it's necessary to wait for all\n // source buffers to no longer be updating. \"If the updating attribute equals true on\n // any SourceBuffer in sourceBuffers, then throw an InvalidStateError exception and\n // abort these steps.\" (source: https://www.w3.org/TR/media-source/#attributes).\n pushQueue({\n type: 'mediaSource',\n sourceUpdater: this,\n action: actions.duration(duration),\n name: 'duration',\n doneFn: doneFn\n });\n }\n /**\n * Add a mediaSource endOfStream call to the queue\n *\n * @param {Error} [error]\n * Call endOfStream with an error\n *\n * @param {Function} [doneFn]\n * A function that should be called when the\n * endOfStream call has finished.\n */\n ;\n\n _proto.endOfStream = function endOfStream(error, doneFn) {\n if (error === void 0) {\n error = null;\n }\n\n if (doneFn === void 0) {\n doneFn = noop;\n }\n\n if (typeof error !== 'string') {\n error = undefined;\n } // In order to set the duration on the media source, it's necessary to wait for all\n // source buffers to no longer be updating. \"If the updating attribute equals true on\n // any SourceBuffer in sourceBuffers, then throw an InvalidStateError exception and\n // abort these steps.\" (source: https://www.w3.org/TR/media-source/#attributes).\n\n\n pushQueue({\n type: 'mediaSource',\n sourceUpdater: this,\n action: actions.endOfStream(error),\n name: 'endOfStream',\n doneFn: doneFn\n });\n }\n /**\n * Queue an update to remove a time range from the buffer.\n *\n * @param {number} start where to start the removal\n * @param {number} end where to end the removal\n * @param {Function} [done=noop] optional callback to be executed when the remove\n * operation is complete\n * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-remove-void-double-start-unrestricted-double-end\n */\n ;\n\n _proto.removeAudio = function removeAudio(start, end, done) {\n if (done === void 0) {\n done = noop;\n }\n\n if (!this.audioBuffered().length || this.audioBuffered().end(0) === 0) {\n done();\n return;\n }\n\n pushQueue({\n type: 'audio',\n sourceUpdater: this,\n action: actions.remove(start, end),\n doneFn: done,\n name: 'remove'\n });\n }\n /**\n * Queue an update to remove a time range from the buffer.\n *\n * @param {number} start where to start the removal\n * @param {number} end where to end the removal\n * @param {Function} [done=noop] optional callback to be executed when the remove\n * operation is complete\n * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-remove-void-double-start-unrestricted-double-end\n */\n ;\n\n _proto.removeVideo = function removeVideo(start, end, done) {\n if (done === void 0) {\n done = noop;\n }\n\n if (!this.videoBuffered().length || this.videoBuffered().end(0) === 0) {\n done();\n return;\n }\n\n pushQueue({\n type: 'video',\n sourceUpdater: this,\n action: actions.remove(start, end),\n doneFn: done,\n name: 'remove'\n });\n }\n /**\n * Whether the underlying sourceBuffer is updating or not\n *\n * @return {boolean} the updating status of the SourceBuffer\n */\n ;\n\n _proto.updating = function updating() {\n // the audio/video source buffer is updating\n if (_updating('audio', this) || _updating('video', this)) {\n return true;\n }\n\n return false;\n }\n /**\n * Set/get the timestampoffset on the audio SourceBuffer\n *\n * @return {number} the timestamp offset\n */\n ;\n\n _proto.audioTimestampOffset = function audioTimestampOffset(offset) {\n if (typeof offset !== 'undefined' && this.audioBuffer && // no point in updating if it's the same\n this.audioTimestampOffset_ !== offset) {\n pushQueue({\n type: 'audio',\n sourceUpdater: this,\n action: actions.timestampOffset(offset),\n name: 'timestampOffset'\n });\n this.audioTimestampOffset_ = offset;\n }\n\n return this.audioTimestampOffset_;\n }\n /**\n * Set/get the timestampoffset on the video SourceBuffer\n *\n * @return {number} the timestamp offset\n */\n ;\n\n _proto.videoTimestampOffset = function videoTimestampOffset(offset) {\n if (typeof offset !== 'undefined' && this.videoBuffer && // no point in updating if it's the same\n this.videoTimestampOffset !== offset) {\n pushQueue({\n type: 'video',\n sourceUpdater: this,\n action: actions.timestampOffset(offset),\n name: 'timestampOffset'\n });\n this.videoTimestampOffset_ = offset;\n }\n\n return this.videoTimestampOffset_;\n }\n /**\n * Add a function to the queue that will be called\n * when it is its turn to run in the audio queue.\n *\n * @param {Function} callback\n * The callback to queue.\n */\n ;\n\n _proto.audioQueueCallback = function audioQueueCallback(callback) {\n if (!this.audioBuffer) {\n return;\n }\n\n pushQueue({\n type: 'audio',\n sourceUpdater: this,\n action: actions.callback(callback),\n name: 'callback'\n });\n }\n /**\n * Add a function to the queue that will be called\n * when it is its turn to run in the video queue.\n *\n * @param {Function} callback\n * The callback to queue.\n */\n ;\n\n _proto.videoQueueCallback = function videoQueueCallback(callback) {\n if (!this.videoBuffer) {\n return;\n }\n\n pushQueue({\n type: 'video',\n sourceUpdater: this,\n action: actions.callback(callback),\n name: 'callback'\n });\n }\n /**\n * dispose of the source updater and the underlying sourceBuffer\n */\n ;\n\n _proto.dispose = function dispose() {\n var _this4 = this;\n\n this.trigger('dispose');\n bufferTypes.forEach(function (type) {\n _this4.abort(type);\n\n if (_this4.canRemoveSourceBuffer()) {\n _this4.removeSourceBuffer(type);\n } else {\n _this4[type + \"QueueCallback\"](function () {\n return cleanupBuffer(type, _this4);\n });\n }\n });\n this.videoAppendQueued_ = false;\n this.delayedAudioAppendQueue_.length = 0;\n\n if (this.sourceopenListener_) {\n this.mediaSource.removeEventListener('sourceopen', this.sourceopenListener_);\n }\n\n this.off();\n };\n\n return SourceUpdater;\n}(videojs.EventTarget);\n\nvar uint8ToUtf8 = function uint8ToUtf8(uintArray) {\n return decodeURIComponent(escape(String.fromCharCode.apply(null, uintArray)));\n};\n\nvar VTT_LINE_TERMINATORS = new Uint8Array('\\n\\n'.split('').map(function (char) {\n return char.charCodeAt(0);\n}));\n/**\n * An object that manages segment loading and appending.\n *\n * @class VTTSegmentLoader\n * @param {Object} options required and optional options\n * @extends videojs.EventTarget\n */\n\nvar VTTSegmentLoader = /*#__PURE__*/function (_SegmentLoader) {\n _inheritsLoose(VTTSegmentLoader, _SegmentLoader);\n\n function VTTSegmentLoader(settings, options) {\n var _this;\n\n if (options === void 0) {\n options = {};\n }\n\n _this = _SegmentLoader.call(this, settings, options) || this; // SegmentLoader requires a MediaSource be specified or it will throw an error;\n // however, VTTSegmentLoader has no need of a media source, so delete the reference\n\n _this.mediaSource_ = null;\n _this.subtitlesTrack_ = null;\n _this.loaderType_ = 'subtitle';\n _this.featuresNativeTextTracks_ = settings.featuresNativeTextTracks; // The VTT segment will have its own time mappings. Saving VTT segment timing info in\n // the sync controller leads to improper behavior.\n\n _this.shouldSaveSegmentTimingInfo_ = false;\n return _this;\n }\n\n var _proto = VTTSegmentLoader.prototype;\n\n _proto.createTransmuxer_ = function createTransmuxer_() {\n // don't need to transmux any subtitles\n return null;\n }\n /**\n * Indicates which time ranges are buffered\n *\n * @return {TimeRange}\n * TimeRange object representing the current buffered ranges\n */\n ;\n\n _proto.buffered_ = function buffered_() {\n if (!this.subtitlesTrack_ || !this.subtitlesTrack_.cues || !this.subtitlesTrack_.cues.length) {\n return videojs.createTimeRanges();\n }\n\n var cues = this.subtitlesTrack_.cues;\n var start = cues[0].startTime;\n var end = cues[cues.length - 1].startTime;\n return videojs.createTimeRanges([[start, end]]);\n }\n /**\n * Gets and sets init segment for the provided map\n *\n * @param {Object} map\n * The map object representing the init segment to get or set\n * @param {boolean=} set\n * If true, the init segment for the provided map should be saved\n * @return {Object}\n * map object for desired init segment\n */\n ;\n\n _proto.initSegmentForMap = function initSegmentForMap(map, set) {\n if (set === void 0) {\n set = false;\n }\n\n if (!map) {\n return null;\n }\n\n var id = initSegmentId(map);\n var storedMap = this.initSegments_[id];\n\n if (set && !storedMap && map.bytes) {\n // append WebVTT line terminators to the media initialization segment if it exists\n // to follow the WebVTT spec (https://w3c.github.io/webvtt/#file-structure) that\n // requires two or more WebVTT line terminators between the WebVTT header and the\n // rest of the file\n var combinedByteLength = VTT_LINE_TERMINATORS.byteLength + map.bytes.byteLength;\n var combinedSegment = new Uint8Array(combinedByteLength);\n combinedSegment.set(map.bytes);\n combinedSegment.set(VTT_LINE_TERMINATORS, map.bytes.byteLength);\n this.initSegments_[id] = storedMap = {\n resolvedUri: map.resolvedUri,\n byterange: map.byterange,\n bytes: combinedSegment\n };\n }\n\n return storedMap || map;\n }\n /**\n * Returns true if all configuration required for loading is present, otherwise false.\n *\n * @return {boolean} True if the all configuration is ready for loading\n * @private\n */\n ;\n\n _proto.couldBeginLoading_ = function couldBeginLoading_() {\n return this.playlist_ && this.subtitlesTrack_ && !this.paused();\n }\n /**\n * Once all the starting parameters have been specified, begin\n * operation. This method should only be invoked from the INIT\n * state.\n *\n * @private\n */\n ;\n\n _proto.init_ = function init_() {\n this.state = 'READY';\n this.resetEverything();\n return this.monitorBuffer_();\n }\n /**\n * Set a subtitle track on the segment loader to add subtitles to\n *\n * @param {TextTrack=} track\n * The text track to add loaded subtitles to\n * @return {TextTrack}\n * Returns the subtitles track\n */\n ;\n\n _proto.track = function track(_track) {\n if (typeof _track === 'undefined') {\n return this.subtitlesTrack_;\n }\n\n this.subtitlesTrack_ = _track; // if we were unpaused but waiting for a sourceUpdater, start\n // buffering now\n\n if (this.state === 'INIT' && this.couldBeginLoading_()) {\n this.init_();\n }\n\n return this.subtitlesTrack_;\n }\n /**\n * Remove any data in the source buffer between start and end times\n *\n * @param {number} start - the start time of the region to remove from the buffer\n * @param {number} end - the end time of the region to remove from the buffer\n */\n ;\n\n _proto.remove = function remove(start, end) {\n removeCuesFromTrack(start, end, this.subtitlesTrack_);\n }\n /**\n * fill the buffer with segements unless the sourceBuffers are\n * currently updating\n *\n * Note: this function should only ever be called by monitorBuffer_\n * and never directly\n *\n * @private\n */\n ;\n\n _proto.fillBuffer_ = function fillBuffer_() {\n var _this2 = this;\n\n // see if we need to begin loading immediately\n var segmentInfo = this.chooseNextRequest_();\n\n if (!segmentInfo) {\n return;\n }\n\n if (this.syncController_.timestampOffsetForTimeline(segmentInfo.timeline) === null) {\n // We don't have the timestamp offset that we need to sync subtitles.\n // Rerun on a timestamp offset or user interaction.\n var checkTimestampOffset = function checkTimestampOffset() {\n _this2.state = 'READY';\n\n if (!_this2.paused()) {\n // if not paused, queue a buffer check as soon as possible\n _this2.monitorBuffer_();\n }\n };\n\n this.syncController_.one('timestampoffset', checkTimestampOffset);\n this.state = 'WAITING_ON_TIMELINE';\n return;\n }\n\n this.loadSegment_(segmentInfo);\n } // never set a timestamp offset for vtt segments.\n ;\n\n _proto.timestampOffsetForSegment_ = function timestampOffsetForSegment_() {\n return null;\n };\n\n _proto.chooseNextRequest_ = function chooseNextRequest_() {\n return this.skipEmptySegments_(_SegmentLoader.prototype.chooseNextRequest_.call(this));\n }\n /**\n * Prevents the segment loader from requesting segments we know contain no subtitles\n * by walking forward until we find the next segment that we don't know whether it is\n * empty or not.\n *\n * @param {Object} segmentInfo\n * a segment info object that describes the current segment\n * @return {Object}\n * a segment info object that describes the current segment\n */\n ;\n\n _proto.skipEmptySegments_ = function skipEmptySegments_(segmentInfo) {\n while (segmentInfo && segmentInfo.segment.empty) {\n // stop at the last possible segmentInfo\n if (segmentInfo.mediaIndex + 1 >= segmentInfo.playlist.segments.length) {\n segmentInfo = null;\n break;\n }\n\n segmentInfo = this.generateSegmentInfo_({\n playlist: segmentInfo.playlist,\n mediaIndex: segmentInfo.mediaIndex + 1,\n startOfSegment: segmentInfo.startOfSegment + segmentInfo.duration,\n isSyncRequest: segmentInfo.isSyncRequest\n });\n }\n\n return segmentInfo;\n };\n\n _proto.stopForError = function stopForError(error) {\n this.error(error);\n this.state = 'READY';\n this.pause();\n this.trigger('error');\n }\n /**\n * append a decrypted segement to the SourceBuffer through a SourceUpdater\n *\n * @private\n */\n ;\n\n _proto.segmentRequestFinished_ = function segmentRequestFinished_(error, simpleSegment, result) {\n var _this3 = this;\n\n if (!this.subtitlesTrack_) {\n this.state = 'READY';\n return;\n }\n\n this.saveTransferStats_(simpleSegment.stats); // the request was aborted\n\n if (!this.pendingSegment_) {\n this.state = 'READY';\n this.mediaRequestsAborted += 1;\n return;\n }\n\n if (error) {\n if (error.code === REQUEST_ERRORS.TIMEOUT) {\n this.handleTimeout_();\n }\n\n if (error.code === REQUEST_ERRORS.ABORTED) {\n this.mediaRequestsAborted += 1;\n } else {\n this.mediaRequestsErrored += 1;\n }\n\n this.stopForError(error);\n return;\n }\n\n var segmentInfo = this.pendingSegment_; // although the VTT segment loader bandwidth isn't really used, it's good to\n // maintain functionality between segment loaders\n\n this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);\n this.state = 'APPENDING'; // used for tests\n\n this.trigger('appending');\n var segment = segmentInfo.segment;\n\n if (segment.map) {\n segment.map.bytes = simpleSegment.map.bytes;\n }\n\n segmentInfo.bytes = simpleSegment.bytes; // Make sure that vttjs has loaded, otherwise, wait till it finished loading\n\n if (typeof window$1.WebVTT !== 'function' && this.subtitlesTrack_ && this.subtitlesTrack_.tech_) {\n var loadHandler;\n\n var errorHandler = function errorHandler() {\n _this3.subtitlesTrack_.tech_.off('vttjsloaded', loadHandler);\n\n _this3.stopForError({\n message: 'Error loading vtt.js'\n });\n\n return;\n };\n\n loadHandler = function loadHandler() {\n _this3.subtitlesTrack_.tech_.off('vttjserror', errorHandler);\n\n _this3.segmentRequestFinished_(error, simpleSegment, result);\n };\n\n this.state = 'WAITING_ON_VTTJS';\n this.subtitlesTrack_.tech_.one('vttjsloaded', loadHandler);\n this.subtitlesTrack_.tech_.one('vttjserror', errorHandler);\n return;\n }\n\n segment.requested = true;\n\n try {\n this.parseVTTCues_(segmentInfo);\n } catch (e) {\n this.stopForError({\n message: e.message\n });\n return;\n }\n\n this.updateTimeMapping_(segmentInfo, this.syncController_.timelines[segmentInfo.timeline], this.playlist_);\n\n if (segmentInfo.cues.length) {\n segmentInfo.timingInfo = {\n start: segmentInfo.cues[0].startTime,\n end: segmentInfo.cues[segmentInfo.cues.length - 1].endTime\n };\n } else {\n segmentInfo.timingInfo = {\n start: segmentInfo.startOfSegment,\n end: segmentInfo.startOfSegment + segmentInfo.duration\n };\n }\n\n if (segmentInfo.isSyncRequest) {\n this.trigger('syncinfoupdate');\n this.pendingSegment_ = null;\n this.state = 'READY';\n return;\n }\n\n segmentInfo.byteLength = segmentInfo.bytes.byteLength;\n this.mediaSecondsLoaded += segment.duration; // Create VTTCue instances for each cue in the new segment and add them to\n // the subtitle track\n\n segmentInfo.cues.forEach(function (cue) {\n _this3.subtitlesTrack_.addCue(_this3.featuresNativeTextTracks_ ? new window$1.VTTCue(cue.startTime, cue.endTime, cue.text) : cue);\n }); // Remove any duplicate cues from the subtitle track. The WebVTT spec allows\n // cues to have identical time-intervals, but if the text is also identical\n // we can safely assume it is a duplicate that can be removed (ex. when a cue\n // \"overlaps\" VTT segments)\n\n removeDuplicateCuesFromTrack(this.subtitlesTrack_);\n this.handleAppendsDone_();\n };\n\n _proto.handleData_ = function handleData_() {// noop as we shouldn't be getting video/audio data captions\n // that we do not support here.\n };\n\n _proto.updateTimingInfoEnd_ = function updateTimingInfoEnd_() {// noop\n }\n /**\n * Uses the WebVTT parser to parse the segment response\n *\n * @param {Object} segmentInfo\n * a segment info object that describes the current segment\n * @private\n */\n ;\n\n _proto.parseVTTCues_ = function parseVTTCues_(segmentInfo) {\n var decoder;\n var decodeBytesToString = false;\n\n if (typeof window$1.TextDecoder === 'function') {\n decoder = new window$1.TextDecoder('utf8');\n } else {\n decoder = window$1.WebVTT.StringDecoder();\n decodeBytesToString = true;\n }\n\n var parser = new window$1.WebVTT.Parser(window$1, window$1.vttjs, decoder);\n segmentInfo.cues = [];\n segmentInfo.timestampmap = {\n MPEGTS: 0,\n LOCAL: 0\n };\n parser.oncue = segmentInfo.cues.push.bind(segmentInfo.cues);\n\n parser.ontimestampmap = function (map) {\n segmentInfo.timestampmap = map;\n };\n\n parser.onparsingerror = function (error) {\n videojs.log.warn('Error encountered when parsing cues: ' + error.message);\n };\n\n if (segmentInfo.segment.map) {\n var mapData = segmentInfo.segment.map.bytes;\n\n if (decodeBytesToString) {\n mapData = uint8ToUtf8(mapData);\n }\n\n parser.parse(mapData);\n }\n\n var segmentData = segmentInfo.bytes;\n\n if (decodeBytesToString) {\n segmentData = uint8ToUtf8(segmentData);\n }\n\n parser.parse(segmentData);\n parser.flush();\n }\n /**\n * Updates the start and end times of any cues parsed by the WebVTT parser using\n * the information parsed from the X-TIMESTAMP-MAP header and a TS to media time mapping\n * from the SyncController\n *\n * @param {Object} segmentInfo\n * a segment info object that describes the current segment\n * @param {Object} mappingObj\n * object containing a mapping from TS to media time\n * @param {Object} playlist\n * the playlist object containing the segment\n * @private\n */\n ;\n\n _proto.updateTimeMapping_ = function updateTimeMapping_(segmentInfo, mappingObj, playlist) {\n var segment = segmentInfo.segment;\n\n if (!mappingObj) {\n // If the sync controller does not have a mapping of TS to Media Time for the\n // timeline, then we don't have enough information to update the cue\n // start/end times\n return;\n }\n\n if (!segmentInfo.cues.length) {\n // If there are no cues, we also do not have enough information to figure out\n // segment timing. Mark that the segment contains no cues so we don't re-request\n // an empty segment.\n segment.empty = true;\n return;\n }\n\n var timestampmap = segmentInfo.timestampmap;\n var diff = timestampmap.MPEGTS / ONE_SECOND_IN_TS - timestampmap.LOCAL + mappingObj.mapping;\n segmentInfo.cues.forEach(function (cue) {\n // First convert cue time to TS time using the timestamp-map provided within the vtt\n cue.startTime += diff;\n cue.endTime += diff;\n });\n\n if (!playlist.syncInfo) {\n var firstStart = segmentInfo.cues[0].startTime;\n var lastStart = segmentInfo.cues[segmentInfo.cues.length - 1].startTime;\n playlist.syncInfo = {\n mediaSequence: playlist.mediaSequence + segmentInfo.mediaIndex,\n time: Math.min(firstStart, lastStart - segment.duration)\n };\n }\n };\n\n return VTTSegmentLoader;\n}(SegmentLoader);\n\n/**\n * @file ad-cue-tags.js\n */\n/**\n * Searches for an ad cue that overlaps with the given mediaTime\n *\n * @param {Object} track\n * the track to find the cue for\n *\n * @param {number} mediaTime\n * the time to find the cue at\n *\n * @return {Object|null}\n * the found cue or null\n */\n\nvar findAdCue = function findAdCue(track, mediaTime) {\n var cues = track.cues;\n\n for (var i = 0; i < cues.length; i++) {\n var cue = cues[i];\n\n if (mediaTime >= cue.adStartTime && mediaTime <= cue.adEndTime) {\n return cue;\n }\n }\n\n return null;\n};\nvar updateAdCues = function updateAdCues(media, track, offset) {\n if (offset === void 0) {\n offset = 0;\n }\n\n if (!media.segments) {\n return;\n }\n\n var mediaTime = offset;\n var cue;\n\n for (var i = 0; i < media.segments.length; i++) {\n var segment = media.segments[i];\n\n if (!cue) {\n // Since the cues will span for at least the segment duration, adding a fudge\n // factor of half segment duration will prevent duplicate cues from being\n // created when timing info is not exact (e.g. cue start time initialized\n // at 10.006677, but next call mediaTime is 10.003332 )\n cue = findAdCue(track, mediaTime + segment.duration / 2);\n }\n\n if (cue) {\n if ('cueIn' in segment) {\n // Found a CUE-IN so end the cue\n cue.endTime = mediaTime;\n cue.adEndTime = mediaTime;\n mediaTime += segment.duration;\n cue = null;\n continue;\n }\n\n if (mediaTime < cue.endTime) {\n // Already processed this mediaTime for this cue\n mediaTime += segment.duration;\n continue;\n } // otherwise extend cue until a CUE-IN is found\n\n\n cue.endTime += segment.duration;\n } else {\n if ('cueOut' in segment) {\n cue = new window$1.VTTCue(mediaTime, mediaTime + segment.duration, segment.cueOut);\n cue.adStartTime = mediaTime; // Assumes tag format to be\n // #EXT-X-CUE-OUT:30\n\n cue.adEndTime = mediaTime + parseFloat(segment.cueOut);\n track.addCue(cue);\n }\n\n if ('cueOutCont' in segment) {\n // Entered into the middle of an ad cue\n // Assumes tag formate to be\n // #EXT-X-CUE-OUT-CONT:10/30\n var _segment$cueOutCont$s = segment.cueOutCont.split('/').map(parseFloat),\n adOffset = _segment$cueOutCont$s[0],\n adTotal = _segment$cueOutCont$s[1];\n\n cue = new window$1.VTTCue(mediaTime, mediaTime + segment.duration, '');\n cue.adStartTime = mediaTime - adOffset;\n cue.adEndTime = cue.adStartTime + adTotal;\n track.addCue(cue);\n }\n }\n\n mediaTime += segment.duration;\n }\n};\n\n// synchronize expired playlist segments.\n// the max media sequence diff is 48 hours of live stream\n// content with two second segments. Anything larger than that\n// will likely be invalid.\n\nvar MAX_MEDIA_SEQUENCE_DIFF_FOR_SYNC = 86400;\nvar syncPointStrategies = [// Stategy \"VOD\": Handle the VOD-case where the sync-point is *always*\n// the equivalence display-time 0 === segment-index 0\n{\n name: 'VOD',\n run: function run(syncController, playlist, duration, currentTimeline, currentTime) {\n if (duration !== Infinity) {\n var syncPoint = {\n time: 0,\n segmentIndex: 0,\n partIndex: null\n };\n return syncPoint;\n }\n\n return null;\n }\n}, // Stategy \"ProgramDateTime\": We have a program-date-time tag in this playlist\n{\n name: 'ProgramDateTime',\n run: function run(syncController, playlist, duration, currentTimeline, currentTime) {\n if (!Object.keys(syncController.timelineToDatetimeMappings).length) {\n return null;\n }\n\n var syncPoint = null;\n var lastDistance = null;\n var partsAndSegments = getPartsAndSegments(playlist);\n currentTime = currentTime || 0;\n\n for (var i = 0; i < partsAndSegments.length; i++) {\n // start from the end and loop backwards for live\n // or start from the front and loop forwards for non-live\n var index = playlist.endList || currentTime === 0 ? i : partsAndSegments.length - (i + 1);\n var partAndSegment = partsAndSegments[index];\n var segment = partAndSegment.segment;\n var datetimeMapping = syncController.timelineToDatetimeMappings[segment.timeline];\n\n if (!datetimeMapping || !segment.dateTimeObject) {\n continue;\n }\n\n var segmentTime = segment.dateTimeObject.getTime() / 1000;\n var start = segmentTime + datetimeMapping; // take part duration into account.\n\n if (segment.parts && typeof partAndSegment.partIndex === 'number') {\n for (var z = 0; z < partAndSegment.partIndex; z++) {\n start += segment.parts[z].duration;\n }\n }\n\n var distance = Math.abs(currentTime - start); // Once the distance begins to increase, or if distance is 0, we have passed\n // currentTime and can stop looking for better candidates\n\n if (lastDistance !== null && (distance === 0 || lastDistance < distance)) {\n break;\n }\n\n lastDistance = distance;\n syncPoint = {\n time: start,\n segmentIndex: partAndSegment.segmentIndex,\n partIndex: partAndSegment.partIndex\n };\n }\n\n return syncPoint;\n }\n}, // Stategy \"Segment\": We have a known time mapping for a timeline and a\n// segment in the current timeline with timing data\n{\n name: 'Segment',\n run: function run(syncController, playlist, duration, currentTimeline, currentTime) {\n var syncPoint = null;\n var lastDistance = null;\n currentTime = currentTime || 0;\n var partsAndSegments = getPartsAndSegments(playlist);\n\n for (var i = 0; i < partsAndSegments.length; i++) {\n // start from the end and loop backwards for live\n // or start from the front and loop forwards for non-live\n var index = playlist.endList || currentTime === 0 ? i : partsAndSegments.length - (i + 1);\n var partAndSegment = partsAndSegments[index];\n var segment = partAndSegment.segment;\n var start = partAndSegment.part && partAndSegment.part.start || segment && segment.start;\n\n if (segment.timeline === currentTimeline && typeof start !== 'undefined') {\n var distance = Math.abs(currentTime - start); // Once the distance begins to increase, we have passed\n // currentTime and can stop looking for better candidates\n\n if (lastDistance !== null && lastDistance < distance) {\n break;\n }\n\n if (!syncPoint || lastDistance === null || lastDistance >= distance) {\n lastDistance = distance;\n syncPoint = {\n time: start,\n segmentIndex: partAndSegment.segmentIndex,\n partIndex: partAndSegment.partIndex\n };\n }\n }\n }\n\n return syncPoint;\n }\n}, // Stategy \"Discontinuity\": We have a discontinuity with a known\n// display-time\n{\n name: 'Discontinuity',\n run: function run(syncController, playlist, duration, currentTimeline, currentTime) {\n var syncPoint = null;\n currentTime = currentTime || 0;\n\n if (playlist.discontinuityStarts && playlist.discontinuityStarts.length) {\n var lastDistance = null;\n\n for (var i = 0; i < playlist.discontinuityStarts.length; i++) {\n var segmentIndex = playlist.discontinuityStarts[i];\n var discontinuity = playlist.discontinuitySequence + i + 1;\n var discontinuitySync = syncController.discontinuities[discontinuity];\n\n if (discontinuitySync) {\n var distance = Math.abs(currentTime - discontinuitySync.time); // Once the distance begins to increase, we have passed\n // currentTime and can stop looking for better candidates\n\n if (lastDistance !== null && lastDistance < distance) {\n break;\n }\n\n if (!syncPoint || lastDistance === null || lastDistance >= distance) {\n lastDistance = distance;\n syncPoint = {\n time: discontinuitySync.time,\n segmentIndex: segmentIndex,\n partIndex: null\n };\n }\n }\n }\n }\n\n return syncPoint;\n }\n}, // Stategy \"Playlist\": We have a playlist with a known mapping of\n// segment index to display time\n{\n name: 'Playlist',\n run: function run(syncController, playlist, duration, currentTimeline, currentTime) {\n if (playlist.syncInfo) {\n var syncPoint = {\n time: playlist.syncInfo.time,\n segmentIndex: playlist.syncInfo.mediaSequence - playlist.mediaSequence,\n partIndex: null\n };\n return syncPoint;\n }\n\n return null;\n }\n}];\n\nvar SyncController = /*#__PURE__*/function (_videojs$EventTarget) {\n _inheritsLoose(SyncController, _videojs$EventTarget);\n\n function SyncController(options) {\n var _this;\n\n _this = _videojs$EventTarget.call(this) || this; // ...for synching across variants\n\n _this.timelines = [];\n _this.discontinuities = [];\n _this.timelineToDatetimeMappings = {};\n _this.logger_ = logger('SyncController');\n return _this;\n }\n /**\n * Find a sync-point for the playlist specified\n *\n * A sync-point is defined as a known mapping from display-time to\n * a segment-index in the current playlist.\n *\n * @param {Playlist} playlist\n * The playlist that needs a sync-point\n * @param {number} duration\n * Duration of the MediaSource (Infinite if playing a live source)\n * @param {number} currentTimeline\n * The last timeline from which a segment was loaded\n * @return {Object}\n * A sync-point object\n */\n\n\n var _proto = SyncController.prototype;\n\n _proto.getSyncPoint = function getSyncPoint(playlist, duration, currentTimeline, currentTime) {\n var syncPoints = this.runStrategies_(playlist, duration, currentTimeline, currentTime);\n\n if (!syncPoints.length) {\n // Signal that we need to attempt to get a sync-point manually\n // by fetching a segment in the playlist and constructing\n // a sync-point from that information\n return null;\n } // Now find the sync-point that is closest to the currentTime because\n // that should result in the most accurate guess about which segment\n // to fetch\n\n\n return this.selectSyncPoint_(syncPoints, {\n key: 'time',\n value: currentTime\n });\n }\n /**\n * Calculate the amount of time that has expired off the playlist during playback\n *\n * @param {Playlist} playlist\n * Playlist object to calculate expired from\n * @param {number} duration\n * Duration of the MediaSource (Infinity if playling a live source)\n * @return {number|null}\n * The amount of time that has expired off the playlist during playback. Null\n * if no sync-points for the playlist can be found.\n */\n ;\n\n _proto.getExpiredTime = function getExpiredTime(playlist, duration) {\n if (!playlist || !playlist.segments) {\n return null;\n }\n\n var syncPoints = this.runStrategies_(playlist, duration, playlist.discontinuitySequence, 0); // Without sync-points, there is not enough information to determine the expired time\n\n if (!syncPoints.length) {\n return null;\n }\n\n var syncPoint = this.selectSyncPoint_(syncPoints, {\n key: 'segmentIndex',\n value: 0\n }); // If the sync-point is beyond the start of the playlist, we want to subtract the\n // duration from index 0 to syncPoint.segmentIndex instead of adding.\n\n if (syncPoint.segmentIndex > 0) {\n syncPoint.time *= -1;\n }\n\n return Math.abs(syncPoint.time + sumDurations({\n defaultDuration: playlist.targetDuration,\n durationList: playlist.segments,\n startIndex: syncPoint.segmentIndex,\n endIndex: 0\n }));\n }\n /**\n * Runs each sync-point strategy and returns a list of sync-points returned by the\n * strategies\n *\n * @private\n * @param {Playlist} playlist\n * The playlist that needs a sync-point\n * @param {number} duration\n * Duration of the MediaSource (Infinity if playing a live source)\n * @param {number} currentTimeline\n * The last timeline from which a segment was loaded\n * @return {Array}\n * A list of sync-point objects\n */\n ;\n\n _proto.runStrategies_ = function runStrategies_(playlist, duration, currentTimeline, currentTime) {\n var syncPoints = []; // Try to find a sync-point in by utilizing various strategies...\n\n for (var i = 0; i < syncPointStrategies.length; i++) {\n var strategy = syncPointStrategies[i];\n var syncPoint = strategy.run(this, playlist, duration, currentTimeline, currentTime);\n\n if (syncPoint) {\n syncPoint.strategy = strategy.name;\n syncPoints.push({\n strategy: strategy.name,\n syncPoint: syncPoint\n });\n }\n }\n\n return syncPoints;\n }\n /**\n * Selects the sync-point nearest the specified target\n *\n * @private\n * @param {Array} syncPoints\n * List of sync-points to select from\n * @param {Object} target\n * Object specifying the property and value we are targeting\n * @param {string} target.key\n * Specifies the property to target. Must be either 'time' or 'segmentIndex'\n * @param {number} target.value\n * The value to target for the specified key.\n * @return {Object}\n * The sync-point nearest the target\n */\n ;\n\n _proto.selectSyncPoint_ = function selectSyncPoint_(syncPoints, target) {\n var bestSyncPoint = syncPoints[0].syncPoint;\n var bestDistance = Math.abs(syncPoints[0].syncPoint[target.key] - target.value);\n var bestStrategy = syncPoints[0].strategy;\n\n for (var i = 1; i < syncPoints.length; i++) {\n var newDistance = Math.abs(syncPoints[i].syncPoint[target.key] - target.value);\n\n if (newDistance < bestDistance) {\n bestDistance = newDistance;\n bestSyncPoint = syncPoints[i].syncPoint;\n bestStrategy = syncPoints[i].strategy;\n }\n }\n\n this.logger_(\"syncPoint for [\" + target.key + \": \" + target.value + \"] chosen with strategy\" + (\" [\" + bestStrategy + \"]: [time:\" + bestSyncPoint.time + \",\") + (\" segmentIndex:\" + bestSyncPoint.segmentIndex) + (typeof bestSyncPoint.partIndex === 'number' ? \",partIndex:\" + bestSyncPoint.partIndex : '') + ']');\n return bestSyncPoint;\n }\n /**\n * Save any meta-data present on the segments when segments leave\n * the live window to the playlist to allow for synchronization at the\n * playlist level later.\n *\n * @param {Playlist} oldPlaylist - The previous active playlist\n * @param {Playlist} newPlaylist - The updated and most current playlist\n */\n ;\n\n _proto.saveExpiredSegmentInfo = function saveExpiredSegmentInfo(oldPlaylist, newPlaylist) {\n var mediaSequenceDiff = newPlaylist.mediaSequence - oldPlaylist.mediaSequence; // Ignore large media sequence gaps\n\n if (mediaSequenceDiff > MAX_MEDIA_SEQUENCE_DIFF_FOR_SYNC) {\n videojs.log.warn(\"Not saving expired segment info. Media sequence gap \" + mediaSequenceDiff + \" is too large.\");\n return;\n } // When a segment expires from the playlist and it has a start time\n // save that information as a possible sync-point reference in future\n\n\n for (var i = mediaSequenceDiff - 1; i >= 0; i--) {\n var lastRemovedSegment = oldPlaylist.segments[i];\n\n if (lastRemovedSegment && typeof lastRemovedSegment.start !== 'undefined') {\n newPlaylist.syncInfo = {\n mediaSequence: oldPlaylist.mediaSequence + i,\n time: lastRemovedSegment.start\n };\n this.logger_(\"playlist refresh sync: [time:\" + newPlaylist.syncInfo.time + \",\" + (\" mediaSequence: \" + newPlaylist.syncInfo.mediaSequence + \"]\"));\n this.trigger('syncinfoupdate');\n break;\n }\n }\n }\n /**\n * Save the mapping from playlist's ProgramDateTime to display. This should only happen\n * before segments start to load.\n *\n * @param {Playlist} playlist - The currently active playlist\n */\n ;\n\n _proto.setDateTimeMappingForStart = function setDateTimeMappingForStart(playlist) {\n // It's possible for the playlist to be updated before playback starts, meaning time\n // zero is not yet set. If, during these playlist refreshes, a discontinuity is\n // crossed, then the old time zero mapping (for the prior timeline) would be retained\n // unless the mappings are cleared.\n this.timelineToDatetimeMappings = {};\n\n if (playlist.segments && playlist.segments.length && playlist.segments[0].dateTimeObject) {\n var firstSegment = playlist.segments[0];\n var playlistTimestamp = firstSegment.dateTimeObject.getTime() / 1000;\n this.timelineToDatetimeMappings[firstSegment.timeline] = -playlistTimestamp;\n }\n }\n /**\n * Calculates and saves timeline mappings, playlist sync info, and segment timing values\n * based on the latest timing information.\n *\n * @param {Object} options\n * Options object\n * @param {SegmentInfo} options.segmentInfo\n * The current active request information\n * @param {boolean} options.shouldSaveTimelineMapping\n * If there's a timeline change, determines if the timeline mapping should be\n * saved for timeline mapping and program date time mappings.\n */\n ;\n\n _proto.saveSegmentTimingInfo = function saveSegmentTimingInfo(_ref) {\n var segmentInfo = _ref.segmentInfo,\n shouldSaveTimelineMapping = _ref.shouldSaveTimelineMapping;\n var didCalculateSegmentTimeMapping = this.calculateSegmentTimeMapping_(segmentInfo, segmentInfo.timingInfo, shouldSaveTimelineMapping);\n var segment = segmentInfo.segment;\n\n if (didCalculateSegmentTimeMapping) {\n this.saveDiscontinuitySyncInfo_(segmentInfo); // If the playlist does not have sync information yet, record that information\n // now with segment timing information\n\n if (!segmentInfo.playlist.syncInfo) {\n segmentInfo.playlist.syncInfo = {\n mediaSequence: segmentInfo.playlist.mediaSequence + segmentInfo.mediaIndex,\n time: segment.start\n };\n }\n }\n\n var dateTime = segment.dateTimeObject;\n\n if (segment.discontinuity && shouldSaveTimelineMapping && dateTime) {\n this.timelineToDatetimeMappings[segment.timeline] = -(dateTime.getTime() / 1000);\n }\n };\n\n _proto.timestampOffsetForTimeline = function timestampOffsetForTimeline(timeline) {\n if (typeof this.timelines[timeline] === 'undefined') {\n return null;\n }\n\n return this.timelines[timeline].time;\n };\n\n _proto.mappingForTimeline = function mappingForTimeline(timeline) {\n if (typeof this.timelines[timeline] === 'undefined') {\n return null;\n }\n\n return this.timelines[timeline].mapping;\n }\n /**\n * Use the \"media time\" for a segment to generate a mapping to \"display time\" and\n * save that display time to the segment.\n *\n * @private\n * @param {SegmentInfo} segmentInfo\n * The current active request information\n * @param {Object} timingInfo\n * The start and end time of the current segment in \"media time\"\n * @param {boolean} shouldSaveTimelineMapping\n * If there's a timeline change, determines if the timeline mapping should be\n * saved in timelines.\n * @return {boolean}\n * Returns false if segment time mapping could not be calculated\n */\n ;\n\n _proto.calculateSegmentTimeMapping_ = function calculateSegmentTimeMapping_(segmentInfo, timingInfo, shouldSaveTimelineMapping) {\n // TODO: remove side effects\n var segment = segmentInfo.segment;\n var part = segmentInfo.part;\n var mappingObj = this.timelines[segmentInfo.timeline];\n var start;\n var end;\n\n if (typeof segmentInfo.timestampOffset === 'number') {\n mappingObj = {\n time: segmentInfo.startOfSegment,\n mapping: segmentInfo.startOfSegment - timingInfo.start\n };\n\n if (shouldSaveTimelineMapping) {\n this.timelines[segmentInfo.timeline] = mappingObj;\n this.trigger('timestampoffset');\n this.logger_(\"time mapping for timeline \" + segmentInfo.timeline + \": \" + (\"[time: \" + mappingObj.time + \"] [mapping: \" + mappingObj.mapping + \"]\"));\n }\n\n start = segmentInfo.startOfSegment;\n end = timingInfo.end + mappingObj.mapping;\n } else if (mappingObj) {\n start = timingInfo.start + mappingObj.mapping;\n end = timingInfo.end + mappingObj.mapping;\n } else {\n return false;\n }\n\n if (part) {\n part.start = start;\n part.end = end;\n } // If we don't have a segment start yet or the start value we got\n // is less than our current segment.start value, save a new start value.\n // We have to do this because parts will have segment timing info saved\n // multiple times and we want segment start to be the earliest part start\n // value for that segment.\n\n\n if (!segment.start || start < segment.start) {\n segment.start = start;\n }\n\n segment.end = end;\n return true;\n }\n /**\n * Each time we have discontinuity in the playlist, attempt to calculate the location\n * in display of the start of the discontinuity and save that. We also save an accuracy\n * value so that we save values with the most accuracy (closest to 0.)\n *\n * @private\n * @param {SegmentInfo} segmentInfo - The current active request information\n */\n ;\n\n _proto.saveDiscontinuitySyncInfo_ = function saveDiscontinuitySyncInfo_(segmentInfo) {\n var playlist = segmentInfo.playlist;\n var segment = segmentInfo.segment; // If the current segment is a discontinuity then we know exactly where\n // the start of the range and it's accuracy is 0 (greater accuracy values\n // mean more approximation)\n\n if (segment.discontinuity) {\n this.discontinuities[segment.timeline] = {\n time: segment.start,\n accuracy: 0\n };\n } else if (playlist.discontinuityStarts && playlist.discontinuityStarts.length) {\n // Search for future discontinuities that we can provide better timing\n // information for and save that information for sync purposes\n for (var i = 0; i < playlist.discontinuityStarts.length; i++) {\n var segmentIndex = playlist.discontinuityStarts[i];\n var discontinuity = playlist.discontinuitySequence + i + 1;\n var mediaIndexDiff = segmentIndex - segmentInfo.mediaIndex;\n var accuracy = Math.abs(mediaIndexDiff);\n\n if (!this.discontinuities[discontinuity] || this.discontinuities[discontinuity].accuracy > accuracy) {\n var time = void 0;\n\n if (mediaIndexDiff < 0) {\n time = segment.start - sumDurations({\n defaultDuration: playlist.targetDuration,\n durationList: playlist.segments,\n startIndex: segmentInfo.mediaIndex,\n endIndex: segmentIndex\n });\n } else {\n time = segment.end + sumDurations({\n defaultDuration: playlist.targetDuration,\n durationList: playlist.segments,\n startIndex: segmentInfo.mediaIndex + 1,\n endIndex: segmentIndex\n });\n }\n\n this.discontinuities[discontinuity] = {\n time: time,\n accuracy: accuracy\n };\n }\n }\n }\n };\n\n _proto.dispose = function dispose() {\n this.trigger('dispose');\n this.off();\n };\n\n return SyncController;\n}(videojs.EventTarget);\n\n/**\n * The TimelineChangeController acts as a source for segment loaders to listen for and\n * keep track of latest and pending timeline changes. This is useful to ensure proper\n * sync, as each loader may need to make a consideration for what timeline the other\n * loader is on before making changes which could impact the other loader's media.\n *\n * @class TimelineChangeController\n * @extends videojs.EventTarget\n */\n\nvar TimelineChangeController = /*#__PURE__*/function (_videojs$EventTarget) {\n _inheritsLoose(TimelineChangeController, _videojs$EventTarget);\n\n function TimelineChangeController() {\n var _this;\n\n _this = _videojs$EventTarget.call(this) || this;\n _this.pendingTimelineChanges_ = {};\n _this.lastTimelineChanges_ = {};\n return _this;\n }\n\n var _proto = TimelineChangeController.prototype;\n\n _proto.clearPendingTimelineChange = function clearPendingTimelineChange(type) {\n this.pendingTimelineChanges_[type] = null;\n this.trigger('pendingtimelinechange');\n };\n\n _proto.pendingTimelineChange = function pendingTimelineChange(_ref) {\n var type = _ref.type,\n from = _ref.from,\n to = _ref.to;\n\n if (typeof from === 'number' && typeof to === 'number') {\n this.pendingTimelineChanges_[type] = {\n type: type,\n from: from,\n to: to\n };\n this.trigger('pendingtimelinechange');\n }\n\n return this.pendingTimelineChanges_[type];\n };\n\n _proto.lastTimelineChange = function lastTimelineChange(_ref2) {\n var type = _ref2.type,\n from = _ref2.from,\n to = _ref2.to;\n\n if (typeof from === 'number' && typeof to === 'number') {\n this.lastTimelineChanges_[type] = {\n type: type,\n from: from,\n to: to\n };\n delete this.pendingTimelineChanges_[type];\n this.trigger('timelinechange');\n }\n\n return this.lastTimelineChanges_[type];\n };\n\n _proto.dispose = function dispose() {\n this.trigger('dispose');\n this.pendingTimelineChanges_ = {};\n this.lastTimelineChanges_ = {};\n this.off();\n };\n\n return TimelineChangeController;\n}(videojs.EventTarget);\n\n/* rollup-plugin-worker-factory start for worker!/Users/gsinger/repos/clean/http-streaming/src/decrypter-worker.js */\nvar workerCode = transform(getWorkerString(function () {\n\n function createCommonjsModule(fn, basedir, module) {\n return module = {\n path: basedir,\n exports: {},\n require: function require(path, base) {\n return commonjsRequire(path, base === undefined || base === null ? module.path : base);\n }\n }, fn(module, module.exports), module.exports;\n }\n\n function commonjsRequire() {\n throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');\n }\n\n var createClass = createCommonjsModule(function (module) {\n function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n }\n\n module.exports = _createClass;\n module.exports[\"default\"] = module.exports, module.exports.__esModule = true;\n });\n var setPrototypeOf = createCommonjsModule(function (module) {\n function _setPrototypeOf(o, p) {\n module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n module.exports[\"default\"] = module.exports, module.exports.__esModule = true;\n return _setPrototypeOf(o, p);\n }\n\n module.exports = _setPrototypeOf;\n module.exports[\"default\"] = module.exports, module.exports.__esModule = true;\n });\n var inheritsLoose = createCommonjsModule(function (module) {\n function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n setPrototypeOf(subClass, superClass);\n }\n\n module.exports = _inheritsLoose;\n module.exports[\"default\"] = module.exports, module.exports.__esModule = true;\n });\n /**\n * @file stream.js\n */\n\n /**\n * A lightweight readable stream implemention that handles event dispatching.\n *\n * @class Stream\n */\n\n var Stream = /*#__PURE__*/function () {\n function Stream() {\n this.listeners = {};\n }\n /**\n * Add a listener for a specified event type.\n *\n * @param {string} type the event name\n * @param {Function} listener the callback to be invoked when an event of\n * the specified type occurs\n */\n\n\n var _proto = Stream.prototype;\n\n _proto.on = function on(type, listener) {\n if (!this.listeners[type]) {\n this.listeners[type] = [];\n }\n\n this.listeners[type].push(listener);\n }\n /**\n * Remove a listener for a specified event type.\n *\n * @param {string} type the event name\n * @param {Function} listener a function previously registered for this\n * type of event through `on`\n * @return {boolean} if we could turn it off or not\n */\n ;\n\n _proto.off = function off(type, listener) {\n if (!this.listeners[type]) {\n return false;\n }\n\n var index = this.listeners[type].indexOf(listener); // TODO: which is better?\n // In Video.js we slice listener functions\n // on trigger so that it does not mess up the order\n // while we loop through.\n //\n // Here we slice on off so that the loop in trigger\n // can continue using it's old reference to loop without\n // messing up the order.\n\n this.listeners[type] = this.listeners[type].slice(0);\n this.listeners[type].splice(index, 1);\n return index > -1;\n }\n /**\n * Trigger an event of the specified type on this stream. Any additional\n * arguments to this function are passed as parameters to event listeners.\n *\n * @param {string} type the event name\n */\n ;\n\n _proto.trigger = function trigger(type) {\n var callbacks = this.listeners[type];\n\n if (!callbacks) {\n return;\n } // Slicing the arguments on every invocation of this method\n // can add a significant amount of overhead. Avoid the\n // intermediate object creation for the common case of a\n // single callback argument\n\n\n if (arguments.length === 2) {\n var length = callbacks.length;\n\n for (var i = 0; i < length; ++i) {\n callbacks[i].call(this, arguments[1]);\n }\n } else {\n var args = Array.prototype.slice.call(arguments, 1);\n var _length = callbacks.length;\n\n for (var _i = 0; _i < _length; ++_i) {\n callbacks[_i].apply(this, args);\n }\n }\n }\n /**\n * Destroys the stream and cleans up.\n */\n ;\n\n _proto.dispose = function dispose() {\n this.listeners = {};\n }\n /**\n * Forwards all `data` events on this stream to the destination stream. The\n * destination stream should provide a method `push` to receive the data\n * events as they arrive.\n *\n * @param {Stream} destination the stream that will receive all `data` events\n * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options\n */\n ;\n\n _proto.pipe = function pipe(destination) {\n this.on('data', function (data) {\n destination.push(data);\n });\n };\n\n return Stream;\n }();\n /*! @name pkcs7 @version 1.0.4 @license Apache-2.0 */\n\n /**\n * Returns the subarray of a Uint8Array without PKCS#7 padding.\n *\n * @param padded {Uint8Array} unencrypted bytes that have been padded\n * @return {Uint8Array} the unpadded bytes\n * @see http://tools.ietf.org/html/rfc5652\n */\n\n\n function unpad(padded) {\n return padded.subarray(0, padded.byteLength - padded[padded.byteLength - 1]);\n }\n /*! @name aes-decrypter @version 3.1.2 @license Apache-2.0 */\n\n /**\n * @file aes.js\n *\n * This file contains an adaptation of the AES decryption algorithm\n * from the Standford Javascript Cryptography Library. That work is\n * covered by the following copyright and permissions notice:\n *\n * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following\n * disclaimer in the documentation and/or other materials provided\n * with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation\n * are those of the authors and should not be interpreted as representing\n * official policies, either expressed or implied, of the authors.\n */\n\n /**\n * Expand the S-box tables.\n *\n * @private\n */\n\n\n var precompute = function precompute() {\n var tables = [[[], [], [], [], []], [[], [], [], [], []]];\n var encTable = tables[0];\n var decTable = tables[1];\n var sbox = encTable[4];\n var sboxInv = decTable[4];\n var i;\n var x;\n var xInv;\n var d = [];\n var th = [];\n var x2;\n var x4;\n var x8;\n var s;\n var tEnc;\n var tDec; // Compute double and third tables\n\n for (i = 0; i < 256; i++) {\n th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;\n }\n\n for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {\n // Compute sbox\n s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;\n s = s >> 8 ^ s & 255 ^ 99;\n sbox[x] = s;\n sboxInv[s] = x; // Compute MixColumns\n\n x8 = d[x4 = d[x2 = d[x]]];\n tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;\n tEnc = d[s] * 0x101 ^ s * 0x1010100;\n\n for (i = 0; i < 4; i++) {\n encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;\n decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;\n }\n } // Compactify. Considerable speedup on Firefox.\n\n\n for (i = 0; i < 5; i++) {\n encTable[i] = encTable[i].slice(0);\n decTable[i] = decTable[i].slice(0);\n }\n\n return tables;\n };\n\n var aesTables = null;\n /**\n * Schedule out an AES key for both encryption and decryption. This\n * is a low-level class. Use a cipher mode to do bulk encryption.\n *\n * @class AES\n * @param key {Array} The key as an array of 4, 6 or 8 words.\n */\n\n var AES = /*#__PURE__*/function () {\n function AES(key) {\n /**\n * The expanded S-box and inverse S-box tables. These will be computed\n * on the client so that we don't have to send them down the wire.\n *\n * There are two tables, _tables[0] is for encryption and\n * _tables[1] is for decryption.\n *\n * The first 4 sub-tables are the expanded S-box with MixColumns. The\n * last (_tables[01][4]) is the S-box itself.\n *\n * @private\n */\n // if we have yet to precompute the S-box tables\n // do so now\n if (!aesTables) {\n aesTables = precompute();\n } // then make a copy of that object for use\n\n\n this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]];\n var i;\n var j;\n var tmp;\n var sbox = this._tables[0][4];\n var decTable = this._tables[1];\n var keyLen = key.length;\n var rcon = 1;\n\n if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {\n throw new Error('Invalid aes key size');\n }\n\n var encKey = key.slice(0);\n var decKey = [];\n this._key = [encKey, decKey]; // schedule encryption keys\n\n for (i = keyLen; i < 4 * keyLen + 28; i++) {\n tmp = encKey[i - 1]; // apply sbox\n\n if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) {\n tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; // shift rows and add rcon\n\n if (i % keyLen === 0) {\n tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;\n rcon = rcon << 1 ^ (rcon >> 7) * 283;\n }\n }\n\n encKey[i] = encKey[i - keyLen] ^ tmp;\n } // schedule decryption keys\n\n\n for (j = 0; i; j++, i--) {\n tmp = encKey[j & 3 ? i : i - 4];\n\n if (i <= 4 || j < 4) {\n decKey[j] = tmp;\n } else {\n decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]];\n }\n }\n }\n /**\n * Decrypt 16 bytes, specified as four 32-bit words.\n *\n * @param {number} encrypted0 the first word to decrypt\n * @param {number} encrypted1 the second word to decrypt\n * @param {number} encrypted2 the third word to decrypt\n * @param {number} encrypted3 the fourth word to decrypt\n * @param {Int32Array} out the array to write the decrypted words\n * into\n * @param {number} offset the offset into the output array to start\n * writing results\n * @return {Array} The plaintext.\n */\n\n\n var _proto = AES.prototype;\n\n _proto.decrypt = function decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) {\n var key = this._key[1]; // state variables a,b,c,d are loaded with pre-whitened data\n\n var a = encrypted0 ^ key[0];\n var b = encrypted3 ^ key[1];\n var c = encrypted2 ^ key[2];\n var d = encrypted1 ^ key[3];\n var a2;\n var b2;\n var c2; // key.length === 2 ?\n\n var nInnerRounds = key.length / 4 - 2;\n var i;\n var kIndex = 4;\n var table = this._tables[1]; // load up the tables\n\n var table0 = table[0];\n var table1 = table[1];\n var table2 = table[2];\n var table3 = table[3];\n var sbox = table[4]; // Inner rounds. Cribbed from OpenSSL.\n\n for (i = 0; i < nInnerRounds; i++) {\n a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex];\n b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1];\n c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2];\n d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3];\n kIndex += 4;\n a = a2;\n b = b2;\n c = c2;\n } // Last round.\n\n\n for (i = 0; i < 4; i++) {\n out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++];\n a2 = a;\n a = b;\n b = c;\n c = d;\n d = a2;\n }\n };\n\n return AES;\n }();\n /**\n * A wrapper around the Stream class to use setTimeout\n * and run stream \"jobs\" Asynchronously\n *\n * @class AsyncStream\n * @extends Stream\n */\n\n\n var AsyncStream = /*#__PURE__*/function (_Stream) {\n inheritsLoose(AsyncStream, _Stream);\n\n function AsyncStream() {\n var _this;\n\n _this = _Stream.call(this, Stream) || this;\n _this.jobs = [];\n _this.delay = 1;\n _this.timeout_ = null;\n return _this;\n }\n /**\n * process an async job\n *\n * @private\n */\n\n\n var _proto = AsyncStream.prototype;\n\n _proto.processJob_ = function processJob_() {\n this.jobs.shift()();\n\n if (this.jobs.length) {\n this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);\n } else {\n this.timeout_ = null;\n }\n }\n /**\n * push a job into the stream\n *\n * @param {Function} job the job to push into the stream\n */\n ;\n\n _proto.push = function push(job) {\n this.jobs.push(job);\n\n if (!this.timeout_) {\n this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);\n }\n };\n\n return AsyncStream;\n }(Stream);\n /**\n * Convert network-order (big-endian) bytes into their little-endian\n * representation.\n */\n\n\n var ntoh = function ntoh(word) {\n return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24;\n };\n /**\n * Decrypt bytes using AES-128 with CBC and PKCS#7 padding.\n *\n * @param {Uint8Array} encrypted the encrypted bytes\n * @param {Uint32Array} key the bytes of the decryption key\n * @param {Uint32Array} initVector the initialization vector (IV) to\n * use for the first round of CBC.\n * @return {Uint8Array} the decrypted bytes\n *\n * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard\n * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29\n * @see https://tools.ietf.org/html/rfc2315\n */\n\n\n var decrypt = function decrypt(encrypted, key, initVector) {\n // word-level access to the encrypted bytes\n var encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2);\n var decipher = new AES(Array.prototype.slice.call(key)); // byte and word-level access for the decrypted output\n\n var decrypted = new Uint8Array(encrypted.byteLength);\n var decrypted32 = new Int32Array(decrypted.buffer); // temporary variables for working with the IV, encrypted, and\n // decrypted data\n\n var init0;\n var init1;\n var init2;\n var init3;\n var encrypted0;\n var encrypted1;\n var encrypted2;\n var encrypted3; // iteration variable\n\n var wordIx; // pull out the words of the IV to ensure we don't modify the\n // passed-in reference and easier access\n\n init0 = initVector[0];\n init1 = initVector[1];\n init2 = initVector[2];\n init3 = initVector[3]; // decrypt four word sequences, applying cipher-block chaining (CBC)\n // to each decrypted block\n\n for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {\n // convert big-endian (network order) words into little-endian\n // (javascript order)\n encrypted0 = ntoh(encrypted32[wordIx]);\n encrypted1 = ntoh(encrypted32[wordIx + 1]);\n encrypted2 = ntoh(encrypted32[wordIx + 2]);\n encrypted3 = ntoh(encrypted32[wordIx + 3]); // decrypt the block\n\n decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); // XOR with the IV, and restore network byte-order to obtain the\n // plaintext\n\n decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0);\n decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1);\n decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2);\n decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3); // setup the IV for the next round\n\n init0 = encrypted0;\n init1 = encrypted1;\n init2 = encrypted2;\n init3 = encrypted3;\n }\n\n return decrypted;\n };\n /**\n * The `Decrypter` class that manages decryption of AES\n * data through `AsyncStream` objects and the `decrypt`\n * function\n *\n * @param {Uint8Array} encrypted the encrypted bytes\n * @param {Uint32Array} key the bytes of the decryption key\n * @param {Uint32Array} initVector the initialization vector (IV) to\n * @param {Function} done the function to run when done\n * @class Decrypter\n */\n\n\n var Decrypter = /*#__PURE__*/function () {\n function Decrypter(encrypted, key, initVector, done) {\n var step = Decrypter.STEP;\n var encrypted32 = new Int32Array(encrypted.buffer);\n var decrypted = new Uint8Array(encrypted.byteLength);\n var i = 0;\n this.asyncStream_ = new AsyncStream(); // split up the encryption job and do the individual chunks asynchronously\n\n this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));\n\n for (i = step; i < encrypted32.length; i += step) {\n initVector = new Uint32Array([ntoh(encrypted32[i - 4]), ntoh(encrypted32[i - 3]), ntoh(encrypted32[i - 2]), ntoh(encrypted32[i - 1])]);\n this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));\n } // invoke the done() callback when everything is finished\n\n\n this.asyncStream_.push(function () {\n // remove pkcs#7 padding from the decrypted bytes\n done(null, unpad(decrypted));\n });\n }\n /**\n * a getter for step the maximum number of bytes to process at one time\n *\n * @return {number} the value of step 32000\n */\n\n\n var _proto = Decrypter.prototype;\n /**\n * @private\n */\n\n _proto.decryptChunk_ = function decryptChunk_(encrypted, key, initVector, decrypted) {\n return function () {\n var bytes = decrypt(encrypted, key, initVector);\n decrypted.set(bytes, encrypted.byteOffset);\n };\n };\n\n createClass(Decrypter, null, [{\n key: \"STEP\",\n get: function get() {\n // 4 * 8000;\n return 32000;\n }\n }]);\n return Decrypter;\n }();\n /**\n * @file bin-utils.js\n */\n\n /**\n * Creates an object for sending to a web worker modifying properties that are TypedArrays\n * into a new object with seperated properties for the buffer, byteOffset, and byteLength.\n *\n * @param {Object} message\n * Object of properties and values to send to the web worker\n * @return {Object}\n * Modified message with TypedArray values expanded\n * @function createTransferableMessage\n */\n\n\n var createTransferableMessage = function createTransferableMessage(message) {\n var transferable = {};\n Object.keys(message).forEach(function (key) {\n var value = message[key];\n\n if (ArrayBuffer.isView(value)) {\n transferable[key] = {\n bytes: value.buffer,\n byteOffset: value.byteOffset,\n byteLength: value.byteLength\n };\n } else {\n transferable[key] = value;\n }\n });\n return transferable;\n };\n /* global self */\n\n /**\n * Our web worker interface so that things can talk to aes-decrypter\n * that will be running in a web worker. the scope is passed to this by\n * webworkify.\n */\n\n\n self.onmessage = function (event) {\n var data = event.data;\n var encrypted = new Uint8Array(data.encrypted.bytes, data.encrypted.byteOffset, data.encrypted.byteLength);\n var key = new Uint32Array(data.key.bytes, data.key.byteOffset, data.key.byteLength / 4);\n var iv = new Uint32Array(data.iv.bytes, data.iv.byteOffset, data.iv.byteLength / 4);\n /* eslint-disable no-new, handle-callback-err */\n\n new Decrypter(encrypted, key, iv, function (err, bytes) {\n self.postMessage(createTransferableMessage({\n source: data.source,\n decrypted: bytes\n }), [bytes.buffer]);\n });\n /* eslint-enable */\n };\n}));\nvar Decrypter = factory(workerCode);\n/* rollup-plugin-worker-factory end for worker!/Users/gsinger/repos/clean/http-streaming/src/decrypter-worker.js */\n\n/**\n * Convert the properties of an HLS track into an audioTrackKind.\n *\n * @private\n */\n\nvar audioTrackKind_ = function audioTrackKind_(properties) {\n var kind = properties.default ? 'main' : 'alternative';\n\n if (properties.characteristics && properties.characteristics.indexOf('public.accessibility.describes-video') >= 0) {\n kind = 'main-desc';\n }\n\n return kind;\n};\n/**\n * Pause provided segment loader and playlist loader if active\n *\n * @param {SegmentLoader} segmentLoader\n * SegmentLoader to pause\n * @param {Object} mediaType\n * Active media type\n * @function stopLoaders\n */\n\n\nvar stopLoaders = function stopLoaders(segmentLoader, mediaType) {\n segmentLoader.abort();\n segmentLoader.pause();\n\n if (mediaType && mediaType.activePlaylistLoader) {\n mediaType.activePlaylistLoader.pause();\n mediaType.activePlaylistLoader = null;\n }\n};\n/**\n * Start loading provided segment loader and playlist loader\n *\n * @param {PlaylistLoader} playlistLoader\n * PlaylistLoader to start loading\n * @param {Object} mediaType\n * Active media type\n * @function startLoaders\n */\n\nvar startLoaders = function startLoaders(playlistLoader, mediaType) {\n // Segment loader will be started after `loadedmetadata` or `loadedplaylist` from the\n // playlist loader\n mediaType.activePlaylistLoader = playlistLoader;\n playlistLoader.load();\n};\n/**\n * Returns a function to be called when the media group changes. It performs a\n * non-destructive (preserve the buffer) resync of the SegmentLoader. This is because a\n * change of group is merely a rendition switch of the same content at another encoding,\n * rather than a change of content, such as switching audio from English to Spanish.\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Handler for a non-destructive resync of SegmentLoader when the active media\n * group changes.\n * @function onGroupChanged\n */\n\nvar onGroupChanged = function onGroupChanged(type, settings) {\n return function () {\n var _settings$segmentLoad = settings.segmentLoaders,\n segmentLoader = _settings$segmentLoad[type],\n mainSegmentLoader = _settings$segmentLoad.main,\n mediaType = settings.mediaTypes[type];\n var activeTrack = mediaType.activeTrack();\n var activeGroup = mediaType.getActiveGroup();\n var previousActiveLoader = mediaType.activePlaylistLoader;\n var lastGroup = mediaType.lastGroup_; // the group did not change do nothing\n\n if (activeGroup && lastGroup && activeGroup.id === lastGroup.id) {\n return;\n }\n\n mediaType.lastGroup_ = activeGroup;\n mediaType.lastTrack_ = activeTrack;\n stopLoaders(segmentLoader, mediaType);\n\n if (!activeGroup || activeGroup.isMasterPlaylist) {\n // there is no group active or active group is a main playlist and won't change\n return;\n }\n\n if (!activeGroup.playlistLoader) {\n if (previousActiveLoader) {\n // The previous group had a playlist loader but the new active group does not\n // this means we are switching from demuxed to muxed audio. In this case we want to\n // do a destructive reset of the main segment loader and not restart the audio\n // loaders.\n mainSegmentLoader.resetEverything();\n }\n\n return;\n } // Non-destructive resync\n\n\n segmentLoader.resyncLoader();\n startLoaders(activeGroup.playlistLoader, mediaType);\n };\n};\nvar onGroupChanging = function onGroupChanging(type, settings) {\n return function () {\n var segmentLoader = settings.segmentLoaders[type],\n mediaType = settings.mediaTypes[type];\n mediaType.lastGroup_ = null;\n segmentLoader.abort();\n segmentLoader.pause();\n };\n};\n/**\n * Returns a function to be called when the media track changes. It performs a\n * destructive reset of the SegmentLoader to ensure we start loading as close to\n * currentTime as possible.\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Handler for a destructive reset of SegmentLoader when the active media\n * track changes.\n * @function onTrackChanged\n */\n\nvar onTrackChanged = function onTrackChanged(type, settings) {\n return function () {\n var masterPlaylistLoader = settings.masterPlaylistLoader,\n _settings$segmentLoad2 = settings.segmentLoaders,\n segmentLoader = _settings$segmentLoad2[type],\n mainSegmentLoader = _settings$segmentLoad2.main,\n mediaType = settings.mediaTypes[type];\n var activeTrack = mediaType.activeTrack();\n var activeGroup = mediaType.getActiveGroup();\n var previousActiveLoader = mediaType.activePlaylistLoader;\n var lastTrack = mediaType.lastTrack_; // track did not change, do nothing\n\n if (lastTrack && activeTrack && lastTrack.id === activeTrack.id) {\n return;\n }\n\n mediaType.lastGroup_ = activeGroup;\n mediaType.lastTrack_ = activeTrack;\n stopLoaders(segmentLoader, mediaType);\n\n if (!activeGroup) {\n // there is no group active so we do not want to restart loaders\n return;\n }\n\n if (activeGroup.isMasterPlaylist) {\n // track did not change, do nothing\n if (!activeTrack || !lastTrack || activeTrack.id === lastTrack.id) {\n return;\n }\n\n var mpc = settings.vhs.masterPlaylistController_;\n var newPlaylist = mpc.selectPlaylist(); // media will not change do nothing\n\n if (mpc.media() === newPlaylist) {\n return;\n }\n\n mediaType.logger_(\"track change. Switching master audio from \" + lastTrack.id + \" to \" + activeTrack.id);\n masterPlaylistLoader.pause();\n mainSegmentLoader.resetEverything();\n mpc.fastQualityChange_(newPlaylist);\n return;\n }\n\n if (type === 'AUDIO') {\n if (!activeGroup.playlistLoader) {\n // when switching from demuxed audio/video to muxed audio/video (noted by no\n // playlist loader for the audio group), we want to do a destructive reset of the\n // main segment loader and not restart the audio loaders\n mainSegmentLoader.setAudio(true); // don't have to worry about disabling the audio of the audio segment loader since\n // it should be stopped\n\n mainSegmentLoader.resetEverything();\n return;\n } // although the segment loader is an audio segment loader, call the setAudio\n // function to ensure it is prepared to re-append the init segment (or handle other\n // config changes)\n\n\n segmentLoader.setAudio(true);\n mainSegmentLoader.setAudio(false);\n }\n\n if (previousActiveLoader === activeGroup.playlistLoader) {\n // Nothing has actually changed. This can happen because track change events can fire\n // multiple times for a \"single\" change. One for enabling the new active track, and\n // one for disabling the track that was active\n startLoaders(activeGroup.playlistLoader, mediaType);\n return;\n }\n\n if (segmentLoader.track) {\n // For WebVTT, set the new text track in the segmentloader\n segmentLoader.track(activeTrack);\n } // destructive reset\n\n\n segmentLoader.resetEverything();\n startLoaders(activeGroup.playlistLoader, mediaType);\n };\n};\nvar onError = {\n /**\n * Returns a function to be called when a SegmentLoader or PlaylistLoader encounters\n * an error.\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Error handler. Logs warning (or error if the playlist is blacklisted) to\n * console and switches back to default audio track.\n * @function onError.AUDIO\n */\n AUDIO: function AUDIO(type, settings) {\n return function () {\n var segmentLoader = settings.segmentLoaders[type],\n mediaType = settings.mediaTypes[type],\n blacklistCurrentPlaylist = settings.blacklistCurrentPlaylist;\n stopLoaders(segmentLoader, mediaType); // switch back to default audio track\n\n var activeTrack = mediaType.activeTrack();\n var activeGroup = mediaType.activeGroup();\n var id = (activeGroup.filter(function (group) {\n return group.default;\n })[0] || activeGroup[0]).id;\n var defaultTrack = mediaType.tracks[id];\n\n if (activeTrack === defaultTrack) {\n // Default track encountered an error. All we can do now is blacklist the current\n // rendition and hope another will switch audio groups\n blacklistCurrentPlaylist({\n message: 'Problem encountered loading the default audio track.'\n });\n return;\n }\n\n videojs.log.warn('Problem encountered loading the alternate audio track.' + 'Switching back to default.');\n\n for (var trackId in mediaType.tracks) {\n mediaType.tracks[trackId].enabled = mediaType.tracks[trackId] === defaultTrack;\n }\n\n mediaType.onTrackChanged();\n };\n },\n\n /**\n * Returns a function to be called when a SegmentLoader or PlaylistLoader encounters\n * an error.\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Error handler. Logs warning to console and disables the active subtitle track\n * @function onError.SUBTITLES\n */\n SUBTITLES: function SUBTITLES(type, settings) {\n return function () {\n var segmentLoader = settings.segmentLoaders[type],\n mediaType = settings.mediaTypes[type];\n videojs.log.warn('Problem encountered loading the subtitle track.' + 'Disabling subtitle track.');\n stopLoaders(segmentLoader, mediaType);\n var track = mediaType.activeTrack();\n\n if (track) {\n track.mode = 'disabled';\n }\n\n mediaType.onTrackChanged();\n };\n }\n};\nvar setupListeners = {\n /**\n * Setup event listeners for audio playlist loader\n *\n * @param {string} type\n * MediaGroup type\n * @param {PlaylistLoader|null} playlistLoader\n * PlaylistLoader to register listeners on\n * @param {Object} settings\n * Object containing required information for media groups\n * @function setupListeners.AUDIO\n */\n AUDIO: function AUDIO(type, playlistLoader, settings) {\n if (!playlistLoader) {\n // no playlist loader means audio will be muxed with the video\n return;\n }\n\n var tech = settings.tech,\n requestOptions = settings.requestOptions,\n segmentLoader = settings.segmentLoaders[type];\n playlistLoader.on('loadedmetadata', function () {\n var media = playlistLoader.media();\n segmentLoader.playlist(media, requestOptions); // if the video is already playing, or if this isn't a live video and preload\n // permits, start downloading segments\n\n if (!tech.paused() || media.endList && tech.preload() !== 'none') {\n segmentLoader.load();\n }\n });\n playlistLoader.on('loadedplaylist', function () {\n segmentLoader.playlist(playlistLoader.media(), requestOptions); // If the player isn't paused, ensure that the segment loader is running\n\n if (!tech.paused()) {\n segmentLoader.load();\n }\n });\n playlistLoader.on('error', onError[type](type, settings));\n },\n\n /**\n * Setup event listeners for subtitle playlist loader\n *\n * @param {string} type\n * MediaGroup type\n * @param {PlaylistLoader|null} playlistLoader\n * PlaylistLoader to register listeners on\n * @param {Object} settings\n * Object containing required information for media groups\n * @function setupListeners.SUBTITLES\n */\n SUBTITLES: function SUBTITLES(type, playlistLoader, settings) {\n var tech = settings.tech,\n requestOptions = settings.requestOptions,\n segmentLoader = settings.segmentLoaders[type],\n mediaType = settings.mediaTypes[type];\n playlistLoader.on('loadedmetadata', function () {\n var media = playlistLoader.media();\n segmentLoader.playlist(media, requestOptions);\n segmentLoader.track(mediaType.activeTrack()); // if the video is already playing, or if this isn't a live video and preload\n // permits, start downloading segments\n\n if (!tech.paused() || media.endList && tech.preload() !== 'none') {\n segmentLoader.load();\n }\n });\n playlistLoader.on('loadedplaylist', function () {\n segmentLoader.playlist(playlistLoader.media(), requestOptions); // If the player isn't paused, ensure that the segment loader is running\n\n if (!tech.paused()) {\n segmentLoader.load();\n }\n });\n playlistLoader.on('error', onError[type](type, settings));\n }\n};\nvar initialize = {\n /**\n * Setup PlaylistLoaders and AudioTracks for the audio groups\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @function initialize.AUDIO\n */\n 'AUDIO': function AUDIO(type, settings) {\n var vhs = settings.vhs,\n sourceType = settings.sourceType,\n segmentLoader = settings.segmentLoaders[type],\n requestOptions = settings.requestOptions,\n mediaGroups = settings.master.mediaGroups,\n _settings$mediaTypes$ = settings.mediaTypes[type],\n groups = _settings$mediaTypes$.groups,\n tracks = _settings$mediaTypes$.tracks,\n logger_ = _settings$mediaTypes$.logger_,\n masterPlaylistLoader = settings.masterPlaylistLoader;\n var audioOnlyMaster = isAudioOnly(masterPlaylistLoader.master); // force a default if we have none\n\n if (!mediaGroups[type] || Object.keys(mediaGroups[type]).length === 0) {\n mediaGroups[type] = {\n main: {\n default: {\n default: true\n }\n }\n };\n\n if (audioOnlyMaster) {\n mediaGroups[type].main.default.playlists = masterPlaylistLoader.master.playlists;\n }\n }\n\n for (var groupId in mediaGroups[type]) {\n if (!groups[groupId]) {\n groups[groupId] = [];\n }\n\n for (var variantLabel in mediaGroups[type][groupId]) {\n var properties = mediaGroups[type][groupId][variantLabel];\n var playlistLoader = void 0;\n\n if (audioOnlyMaster) {\n logger_(\"AUDIO group '\" + groupId + \"' label '\" + variantLabel + \"' is a master playlist\");\n properties.isMasterPlaylist = true;\n playlistLoader = null; // if vhs-json was provided as the source, and the media playlist was resolved,\n // use the resolved media playlist object\n } else if (sourceType === 'vhs-json' && properties.playlists) {\n playlistLoader = new PlaylistLoader(properties.playlists[0], vhs, requestOptions);\n } else if (properties.resolvedUri) {\n playlistLoader = new PlaylistLoader(properties.resolvedUri, vhs, requestOptions); // TODO: dash isn't the only type with properties.playlists\n // should we even have properties.playlists in this check.\n } else if (properties.playlists && sourceType === 'dash') {\n playlistLoader = new DashPlaylistLoader(properties.playlists[0], vhs, requestOptions, masterPlaylistLoader);\n } else {\n // no resolvedUri means the audio is muxed with the video when using this\n // audio track\n playlistLoader = null;\n }\n\n properties = videojs.mergeOptions({\n id: variantLabel,\n playlistLoader: playlistLoader\n }, properties);\n setupListeners[type](type, properties.playlistLoader, settings);\n groups[groupId].push(properties);\n\n if (typeof tracks[variantLabel] === 'undefined') {\n var track = new videojs.AudioTrack({\n id: variantLabel,\n kind: audioTrackKind_(properties),\n enabled: false,\n language: properties.language,\n default: properties.default,\n label: variantLabel\n });\n tracks[variantLabel] = track;\n }\n }\n } // setup single error event handler for the segment loader\n\n\n segmentLoader.on('error', onError[type](type, settings));\n },\n\n /**\n * Setup PlaylistLoaders and TextTracks for the subtitle groups\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @function initialize.SUBTITLES\n */\n 'SUBTITLES': function SUBTITLES(type, settings) {\n var tech = settings.tech,\n vhs = settings.vhs,\n sourceType = settings.sourceType,\n segmentLoader = settings.segmentLoaders[type],\n requestOptions = settings.requestOptions,\n mediaGroups = settings.master.mediaGroups,\n _settings$mediaTypes$2 = settings.mediaTypes[type],\n groups = _settings$mediaTypes$2.groups,\n tracks = _settings$mediaTypes$2.tracks,\n masterPlaylistLoader = settings.masterPlaylistLoader;\n\n for (var groupId in mediaGroups[type]) {\n if (!groups[groupId]) {\n groups[groupId] = [];\n }\n\n for (var variantLabel in mediaGroups[type][groupId]) {\n if (mediaGroups[type][groupId][variantLabel].forced) {\n // Subtitle playlists with the forced attribute are not selectable in Safari.\n // According to Apple's HLS Authoring Specification:\n // If content has forced subtitles and regular subtitles in a given language,\n // the regular subtitles track in that language MUST contain both the forced\n // subtitles and the regular subtitles for that language.\n // Because of this requirement and that Safari does not add forced subtitles,\n // forced subtitles are skipped here to maintain consistent experience across\n // all platforms\n continue;\n }\n\n var properties = mediaGroups[type][groupId][variantLabel];\n var playlistLoader = void 0;\n\n if (sourceType === 'hls') {\n playlistLoader = new PlaylistLoader(properties.resolvedUri, vhs, requestOptions);\n } else if (sourceType === 'dash') {\n var playlists = properties.playlists.filter(function (p) {\n return p.excludeUntil !== Infinity;\n });\n\n if (!playlists.length) {\n return;\n }\n\n playlistLoader = new DashPlaylistLoader(properties.playlists[0], vhs, requestOptions, masterPlaylistLoader);\n } else if (sourceType === 'vhs-json') {\n playlistLoader = new PlaylistLoader( // if the vhs-json object included the media playlist, use the media playlist\n // as provided, otherwise use the resolved URI to load the playlist\n properties.playlists ? properties.playlists[0] : properties.resolvedUri, vhs, requestOptions);\n }\n\n properties = videojs.mergeOptions({\n id: variantLabel,\n playlistLoader: playlistLoader\n }, properties);\n setupListeners[type](type, properties.playlistLoader, settings);\n groups[groupId].push(properties);\n\n if (typeof tracks[variantLabel] === 'undefined') {\n var track = tech.addRemoteTextTrack({\n id: variantLabel,\n kind: 'subtitles',\n default: properties.default && properties.autoselect,\n language: properties.language,\n label: variantLabel\n }, false).track;\n tracks[variantLabel] = track;\n }\n }\n } // setup single error event handler for the segment loader\n\n\n segmentLoader.on('error', onError[type](type, settings));\n },\n\n /**\n * Setup TextTracks for the closed-caption groups\n *\n * @param {String} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @function initialize['CLOSED-CAPTIONS']\n */\n 'CLOSED-CAPTIONS': function CLOSEDCAPTIONS(type, settings) {\n var tech = settings.tech,\n mediaGroups = settings.master.mediaGroups,\n _settings$mediaTypes$3 = settings.mediaTypes[type],\n groups = _settings$mediaTypes$3.groups,\n tracks = _settings$mediaTypes$3.tracks;\n\n for (var groupId in mediaGroups[type]) {\n if (!groups[groupId]) {\n groups[groupId] = [];\n }\n\n for (var variantLabel in mediaGroups[type][groupId]) {\n var properties = mediaGroups[type][groupId][variantLabel]; // Look for either 608 (CCn) or 708 (SERVICEn) caption services\n\n if (!/^(?:CC|SERVICE)/.test(properties.instreamId)) {\n continue;\n }\n\n var captionServices = tech.options_.vhs && tech.options_.vhs.captionServices || {};\n var newProps = {\n label: variantLabel,\n language: properties.language,\n instreamId: properties.instreamId,\n default: properties.default && properties.autoselect\n };\n\n if (captionServices[newProps.instreamId]) {\n newProps = videojs.mergeOptions(newProps, captionServices[newProps.instreamId]);\n }\n\n if (newProps.default === undefined) {\n delete newProps.default;\n } // No PlaylistLoader is required for Closed-Captions because the captions are\n // embedded within the video stream\n\n\n groups[groupId].push(videojs.mergeOptions({\n id: variantLabel\n }, properties));\n\n if (typeof tracks[variantLabel] === 'undefined') {\n var track = tech.addRemoteTextTrack({\n id: newProps.instreamId,\n kind: 'captions',\n default: newProps.default,\n language: newProps.language,\n label: newProps.label\n }, false).track;\n tracks[variantLabel] = track;\n }\n }\n }\n }\n};\n\nvar groupMatch = function groupMatch(list, media) {\n for (var i = 0; i < list.length; i++) {\n if (playlistMatch(media, list[i])) {\n return true;\n }\n\n if (list[i].playlists && groupMatch(list[i].playlists, media)) {\n return true;\n }\n }\n\n return false;\n};\n/**\n * Returns a function used to get the active group of the provided type\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Function that returns the active media group for the provided type. Takes an\n * optional parameter {TextTrack} track. If no track is provided, a list of all\n * variants in the group, otherwise the variant corresponding to the provided\n * track is returned.\n * @function activeGroup\n */\n\n\nvar activeGroup = function activeGroup(type, settings) {\n return function (track) {\n var masterPlaylistLoader = settings.masterPlaylistLoader,\n groups = settings.mediaTypes[type].groups;\n var media = masterPlaylistLoader.media();\n\n if (!media) {\n return null;\n }\n\n var variants = null; // set to variants to main media active group\n\n if (media.attributes[type]) {\n variants = groups[media.attributes[type]];\n }\n\n var groupKeys = Object.keys(groups);\n\n if (!variants) {\n // find the masterPlaylistLoader media\n // that is in a media group if we are dealing\n // with audio only\n if (type === 'AUDIO' && groupKeys.length > 1 && isAudioOnly(settings.master)) {\n for (var i = 0; i < groupKeys.length; i++) {\n var groupPropertyList = groups[groupKeys[i]];\n\n if (groupMatch(groupPropertyList, media)) {\n variants = groupPropertyList;\n break;\n }\n } // use the main group if it exists\n\n } else if (groups.main) {\n variants = groups.main; // only one group, use that one\n } else if (groupKeys.length === 1) {\n variants = groups[groupKeys[0]];\n }\n }\n\n if (typeof track === 'undefined') {\n return variants;\n }\n\n if (track === null || !variants) {\n // An active track was specified so a corresponding group is expected. track === null\n // means no track is currently active so there is no corresponding group\n return null;\n }\n\n return variants.filter(function (props) {\n return props.id === track.id;\n })[0] || null;\n };\n};\nvar activeTrack = {\n /**\n * Returns a function used to get the active track of type provided\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Function that returns the active media track for the provided type. Returns\n * null if no track is active\n * @function activeTrack.AUDIO\n */\n AUDIO: function AUDIO(type, settings) {\n return function () {\n var tracks = settings.mediaTypes[type].tracks;\n\n for (var id in tracks) {\n if (tracks[id].enabled) {\n return tracks[id];\n }\n }\n\n return null;\n };\n },\n\n /**\n * Returns a function used to get the active track of type provided\n *\n * @param {string} type\n * MediaGroup type\n * @param {Object} settings\n * Object containing required information for media groups\n * @return {Function}\n * Function that returns the active media track for the provided type. Returns\n * null if no track is active\n * @function activeTrack.SUBTITLES\n */\n SUBTITLES: function SUBTITLES(type, settings) {\n return function () {\n var tracks = settings.mediaTypes[type].tracks;\n\n for (var id in tracks) {\n if (tracks[id].mode === 'showing' || tracks[id].mode === 'hidden') {\n return tracks[id];\n }\n }\n\n return null;\n };\n }\n};\nvar getActiveGroup = function getActiveGroup(type, _ref) {\n var mediaTypes = _ref.mediaTypes;\n return function () {\n var activeTrack_ = mediaTypes[type].activeTrack();\n\n if (!activeTrack_) {\n return null;\n }\n\n return mediaTypes[type].activeGroup(activeTrack_);\n };\n};\n/**\n * Setup PlaylistLoaders and Tracks for media groups (Audio, Subtitles,\n * Closed-Captions) specified in the master manifest.\n *\n * @param {Object} settings\n * Object containing required information for setting up the media groups\n * @param {Tech} settings.tech\n * The tech of the player\n * @param {Object} settings.requestOptions\n * XHR request options used by the segment loaders\n * @param {PlaylistLoader} settings.masterPlaylistLoader\n * PlaylistLoader for the master source\n * @param {VhsHandler} settings.vhs\n * VHS SourceHandler\n * @param {Object} settings.master\n * The parsed master manifest\n * @param {Object} settings.mediaTypes\n * Object to store the loaders, tracks, and utility methods for each media type\n * @param {Function} settings.blacklistCurrentPlaylist\n * Blacklists the current rendition and forces a rendition switch.\n * @function setupMediaGroups\n */\n\nvar setupMediaGroups = function setupMediaGroups(settings) {\n ['AUDIO', 'SUBTITLES', 'CLOSED-CAPTIONS'].forEach(function (type) {\n initialize[type](type, settings);\n });\n var mediaTypes = settings.mediaTypes,\n masterPlaylistLoader = settings.masterPlaylistLoader,\n tech = settings.tech,\n vhs = settings.vhs,\n _settings$segmentLoad3 = settings.segmentLoaders,\n audioSegmentLoader = _settings$segmentLoad3['AUDIO'],\n mainSegmentLoader = _settings$segmentLoad3.main; // setup active group and track getters and change event handlers\n\n ['AUDIO', 'SUBTITLES'].forEach(function (type) {\n mediaTypes[type].activeGroup = activeGroup(type, settings);\n mediaTypes[type].activeTrack = activeTrack[type](type, settings);\n mediaTypes[type].onGroupChanged = onGroupChanged(type, settings);\n mediaTypes[type].onGroupChanging = onGroupChanging(type, settings);\n mediaTypes[type].onTrackChanged = onTrackChanged(type, settings);\n mediaTypes[type].getActiveGroup = getActiveGroup(type, settings);\n }); // DO NOT enable the default subtitle or caption track.\n // DO enable the default audio track\n\n var audioGroup = mediaTypes.AUDIO.activeGroup();\n\n if (audioGroup) {\n var groupId = (audioGroup.filter(function (group) {\n return group.default;\n })[0] || audioGroup[0]).id;\n mediaTypes.AUDIO.tracks[groupId].enabled = true;\n mediaTypes.AUDIO.onGroupChanged();\n mediaTypes.AUDIO.onTrackChanged();\n var activeAudioGroup = mediaTypes.AUDIO.getActiveGroup(); // a similar check for handling setAudio on each loader is run again each time the\n // track is changed, but needs to be handled here since the track may not be considered\n // changed on the first call to onTrackChanged\n\n if (!activeAudioGroup.playlistLoader) {\n // either audio is muxed with video or the stream is audio only\n mainSegmentLoader.setAudio(true);\n } else {\n // audio is demuxed\n mainSegmentLoader.setAudio(false);\n audioSegmentLoader.setAudio(true);\n }\n }\n\n masterPlaylistLoader.on('mediachange', function () {\n ['AUDIO', 'SUBTITLES'].forEach(function (type) {\n return mediaTypes[type].onGroupChanged();\n });\n });\n masterPlaylistLoader.on('mediachanging', function () {\n ['AUDIO', 'SUBTITLES'].forEach(function (type) {\n return mediaTypes[type].onGroupChanging();\n });\n }); // custom audio track change event handler for usage event\n\n var onAudioTrackChanged = function onAudioTrackChanged() {\n mediaTypes.AUDIO.onTrackChanged();\n tech.trigger({\n type: 'usage',\n name: 'vhs-audio-change'\n });\n tech.trigger({\n type: 'usage',\n name: 'hls-audio-change'\n });\n };\n\n tech.audioTracks().addEventListener('change', onAudioTrackChanged);\n tech.remoteTextTracks().addEventListener('change', mediaTypes.SUBTITLES.onTrackChanged);\n vhs.on('dispose', function () {\n tech.audioTracks().removeEventListener('change', onAudioTrackChanged);\n tech.remoteTextTracks().removeEventListener('change', mediaTypes.SUBTITLES.onTrackChanged);\n }); // clear existing audio tracks and add the ones we just created\n\n tech.clearTracks('audio');\n\n for (var id in mediaTypes.AUDIO.tracks) {\n tech.audioTracks().addTrack(mediaTypes.AUDIO.tracks[id]);\n }\n};\n/**\n * Creates skeleton object used to store the loaders, tracks, and utility methods for each\n * media type\n *\n * @return {Object}\n * Object to store the loaders, tracks, and utility methods for each media type\n * @function createMediaTypes\n */\n\nvar createMediaTypes = function createMediaTypes() {\n var mediaTypes = {};\n ['AUDIO', 'SUBTITLES', 'CLOSED-CAPTIONS'].forEach(function (type) {\n mediaTypes[type] = {\n groups: {},\n tracks: {},\n activePlaylistLoader: null,\n activeGroup: noop,\n activeTrack: noop,\n getActiveGroup: noop,\n onGroupChanged: noop,\n onTrackChanged: noop,\n lastTrack_: null,\n logger_: logger(\"MediaGroups[\" + type + \"]\")\n };\n });\n return mediaTypes;\n};\n\nvar ABORT_EARLY_BLACKLIST_SECONDS = 60 * 2;\nvar Vhs$1; // SegmentLoader stats that need to have each loader's\n// values summed to calculate the final value\n\nvar loaderStats = ['mediaRequests', 'mediaRequestsAborted', 'mediaRequestsTimedout', 'mediaRequestsErrored', 'mediaTransferDuration', 'mediaBytesTransferred', 'mediaAppends'];\n\nvar sumLoaderStat = function sumLoaderStat(stat) {\n return this.audioSegmentLoader_[stat] + this.mainSegmentLoader_[stat];\n};\n\nvar shouldSwitchToMedia = function shouldSwitchToMedia(_ref) {\n var currentPlaylist = _ref.currentPlaylist,\n buffered = _ref.buffered,\n currentTime = _ref.currentTime,\n nextPlaylist = _ref.nextPlaylist,\n bufferLowWaterLine = _ref.bufferLowWaterLine,\n bufferHighWaterLine = _ref.bufferHighWaterLine,\n duration = _ref.duration,\n experimentalBufferBasedABR = _ref.experimentalBufferBasedABR,\n log = _ref.log;\n\n // we have no other playlist to switch to\n if (!nextPlaylist) {\n videojs.log.warn('We received no playlist to switch to. Please check your stream.');\n return false;\n }\n\n var sharedLogLine = \"allowing switch \" + (currentPlaylist && currentPlaylist.id || 'null') + \" -> \" + nextPlaylist.id;\n\n if (!currentPlaylist) {\n log(sharedLogLine + \" as current playlist is not set\");\n return true;\n } // no need to switch if playlist is the same\n\n\n if (nextPlaylist.id === currentPlaylist.id) {\n return false;\n } // determine if current time is in a buffered range.\n\n\n var isBuffered = Boolean(findRange(buffered, currentTime).length); // If the playlist is live, then we want to not take low water line into account.\n // This is because in LIVE, the player plays 3 segments from the end of the\n // playlist, and if `BUFFER_LOW_WATER_LINE` is greater than the duration availble\n // in those segments, a viewer will never experience a rendition upswitch.\n\n if (!currentPlaylist.endList) {\n // For LLHLS live streams, don't switch renditions before playback has started, as it almost\n // doubles the time to first playback.\n if (!isBuffered && typeof currentPlaylist.partTargetDuration === 'number') {\n log(\"not \" + sharedLogLine + \" as current playlist is live llhls, but currentTime isn't in buffered.\");\n return false;\n }\n\n log(sharedLogLine + \" as current playlist is live\");\n return true;\n }\n\n var forwardBuffer = timeAheadOf(buffered, currentTime);\n var maxBufferLowWaterLine = experimentalBufferBasedABR ? Config.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE : Config.MAX_BUFFER_LOW_WATER_LINE; // For the same reason as LIVE, we ignore the low water line when the VOD\n // duration is below the max potential low water line\n\n if (duration < maxBufferLowWaterLine) {\n log(sharedLogLine + \" as duration < max low water line (\" + duration + \" < \" + maxBufferLowWaterLine + \")\");\n return true;\n }\n\n var nextBandwidth = nextPlaylist.attributes.BANDWIDTH;\n var currBandwidth = currentPlaylist.attributes.BANDWIDTH; // when switching down, if our buffer is lower than the high water line,\n // we can switch down\n\n if (nextBandwidth < currBandwidth && (!experimentalBufferBasedABR || forwardBuffer < bufferHighWaterLine)) {\n var logLine = sharedLogLine + \" as next bandwidth < current bandwidth (\" + nextBandwidth + \" < \" + currBandwidth + \")\";\n\n if (experimentalBufferBasedABR) {\n logLine += \" and forwardBuffer < bufferHighWaterLine (\" + forwardBuffer + \" < \" + bufferHighWaterLine + \")\";\n }\n\n log(logLine);\n return true;\n } // and if our buffer is higher than the low water line,\n // we can switch up\n\n\n if ((!experimentalBufferBasedABR || nextBandwidth > currBandwidth) && forwardBuffer >= bufferLowWaterLine) {\n var _logLine = sharedLogLine + \" as forwardBuffer >= bufferLowWaterLine (\" + forwardBuffer + \" >= \" + bufferLowWaterLine + \")\";\n\n if (experimentalBufferBasedABR) {\n _logLine += \" and next bandwidth > current bandwidth (\" + nextBandwidth + \" > \" + currBandwidth + \")\";\n }\n\n log(_logLine);\n return true;\n }\n\n log(\"not \" + sharedLogLine + \" as no switching criteria met\");\n return false;\n};\n/**\n * the master playlist controller controller all interactons\n * between playlists and segmentloaders. At this time this mainly\n * involves a master playlist and a series of audio playlists\n * if they are available\n *\n * @class MasterPlaylistController\n * @extends videojs.EventTarget\n */\n\n\nvar MasterPlaylistController = /*#__PURE__*/function (_videojs$EventTarget) {\n _inheritsLoose(MasterPlaylistController, _videojs$EventTarget);\n\n function MasterPlaylistController(options) {\n var _this;\n\n _this = _videojs$EventTarget.call(this) || this;\n var src = options.src,\n handleManifestRedirects = options.handleManifestRedirects,\n withCredentials = options.withCredentials,\n tech = options.tech,\n bandwidth = options.bandwidth,\n externVhs = options.externVhs,\n useCueTags = options.useCueTags,\n blacklistDuration = options.blacklistDuration,\n enableLowInitialPlaylist = options.enableLowInitialPlaylist,\n sourceType = options.sourceType,\n cacheEncryptionKeys = options.cacheEncryptionKeys,\n experimentalBufferBasedABR = options.experimentalBufferBasedABR,\n experimentalLeastPixelDiffSelector = options.experimentalLeastPixelDiffSelector,\n captionServices = options.captionServices;\n\n if (!src) {\n throw new Error('A non-empty playlist URL or JSON manifest string is required');\n }\n\n var maxPlaylistRetries = options.maxPlaylistRetries;\n\n if (maxPlaylistRetries === null || typeof maxPlaylistRetries === 'undefined') {\n maxPlaylistRetries = Infinity;\n }\n\n Vhs$1 = externVhs;\n _this.experimentalBufferBasedABR = Boolean(experimentalBufferBasedABR);\n _this.experimentalLeastPixelDiffSelector = Boolean(experimentalLeastPixelDiffSelector);\n _this.withCredentials = withCredentials;\n _this.tech_ = tech;\n _this.vhs_ = tech.vhs;\n _this.sourceType_ = sourceType;\n _this.useCueTags_ = useCueTags;\n _this.blacklistDuration = blacklistDuration;\n _this.maxPlaylistRetries = maxPlaylistRetries;\n _this.enableLowInitialPlaylist = enableLowInitialPlaylist;\n\n if (_this.useCueTags_) {\n _this.cueTagsTrack_ = _this.tech_.addTextTrack('metadata', 'ad-cues');\n _this.cueTagsTrack_.inBandMetadataTrackDispatchType = '';\n }\n\n _this.requestOptions_ = {\n withCredentials: withCredentials,\n handleManifestRedirects: handleManifestRedirects,\n maxPlaylistRetries: maxPlaylistRetries,\n timeout: null\n };\n\n _this.on('error', _this.pauseLoading);\n\n _this.mediaTypes_ = createMediaTypes();\n _this.mediaSource = new window$1.MediaSource();\n _this.handleDurationChange_ = _this.handleDurationChange_.bind(_assertThisInitialized(_this));\n _this.handleSourceOpen_ = _this.handleSourceOpen_.bind(_assertThisInitialized(_this));\n _this.handleSourceEnded_ = _this.handleSourceEnded_.bind(_assertThisInitialized(_this));\n\n _this.mediaSource.addEventListener('durationchange', _this.handleDurationChange_); // load the media source into the player\n\n\n _this.mediaSource.addEventListener('sourceopen', _this.handleSourceOpen_);\n\n _this.mediaSource.addEventListener('sourceended', _this.handleSourceEnded_); // we don't have to handle sourceclose since dispose will handle termination of\n // everything, and the MediaSource should not be detached without a proper disposal\n\n\n _this.seekable_ = videojs.createTimeRanges();\n _this.hasPlayed_ = false;\n _this.syncController_ = new SyncController(options);\n _this.segmentMetadataTrack_ = tech.addRemoteTextTrack({\n kind: 'metadata',\n label: 'segment-metadata'\n }, false).track;\n _this.decrypter_ = new Decrypter();\n _this.sourceUpdater_ = new SourceUpdater(_this.mediaSource);\n _this.inbandTextTracks_ = {};\n _this.timelineChangeController_ = new TimelineChangeController();\n var segmentLoaderSettings = {\n vhs: _this.vhs_,\n parse708captions: options.parse708captions,\n captionServices: captionServices,\n mediaSource: _this.mediaSource,\n currentTime: _this.tech_.currentTime.bind(_this.tech_),\n seekable: function seekable() {\n return _this.seekable();\n },\n seeking: function seeking() {\n return _this.tech_.seeking();\n },\n duration: function duration() {\n return _this.duration();\n },\n hasPlayed: function hasPlayed() {\n return _this.hasPlayed_;\n },\n goalBufferLength: function goalBufferLength() {\n return _this.goalBufferLength();\n },\n bandwidth: bandwidth,\n syncController: _this.syncController_,\n decrypter: _this.decrypter_,\n sourceType: _this.sourceType_,\n inbandTextTracks: _this.inbandTextTracks_,\n cacheEncryptionKeys: cacheEncryptionKeys,\n sourceUpdater: _this.sourceUpdater_,\n timelineChangeController: _this.timelineChangeController_,\n experimentalExactManifestTimings: options.experimentalExactManifestTimings\n }; // The source type check not only determines whether a special DASH playlist loader\n // should be used, but also covers the case where the provided src is a vhs-json\n // manifest object (instead of a URL). In the case of vhs-json, the default\n // PlaylistLoader should be used.\n\n _this.masterPlaylistLoader_ = _this.sourceType_ === 'dash' ? new DashPlaylistLoader(src, _this.vhs_, _this.requestOptions_) : new PlaylistLoader(src, _this.vhs_, _this.requestOptions_);\n\n _this.setupMasterPlaylistLoaderListeners_(); // setup segment loaders\n // combined audio/video or just video when alternate audio track is selected\n\n\n _this.mainSegmentLoader_ = new SegmentLoader(videojs.mergeOptions(segmentLoaderSettings, {\n segmentMetadataTrack: _this.segmentMetadataTrack_,\n loaderType: 'main'\n }), options); // alternate audio track\n\n _this.audioSegmentLoader_ = new SegmentLoader(videojs.mergeOptions(segmentLoaderSettings, {\n loaderType: 'audio'\n }), options);\n _this.subtitleSegmentLoader_ = new VTTSegmentLoader(videojs.mergeOptions(segmentLoaderSettings, {\n loaderType: 'vtt',\n featuresNativeTextTracks: _this.tech_.featuresNativeTextTracks\n }), options);\n\n _this.setupSegmentLoaderListeners_();\n\n if (_this.experimentalBufferBasedABR) {\n _this.masterPlaylistLoader_.one('loadedplaylist', function () {\n return _this.startABRTimer_();\n });\n\n _this.tech_.on('pause', function () {\n return _this.stopABRTimer_();\n });\n\n _this.tech_.on('play', function () {\n return _this.startABRTimer_();\n });\n } // Create SegmentLoader stat-getters\n // mediaRequests_\n // mediaRequestsAborted_\n // mediaRequestsTimedout_\n // mediaRequestsErrored_\n // mediaTransferDuration_\n // mediaBytesTransferred_\n // mediaAppends_\n\n\n loaderStats.forEach(function (stat) {\n _this[stat + '_'] = sumLoaderStat.bind(_assertThisInitialized(_this), stat);\n });\n _this.logger_ = logger('MPC');\n _this.triggeredFmp4Usage = false;\n\n if (_this.tech_.preload() === 'none') {\n _this.loadOnPlay_ = function () {\n _this.loadOnPlay_ = null;\n\n _this.masterPlaylistLoader_.load();\n };\n\n _this.tech_.one('play', _this.loadOnPlay_);\n } else {\n _this.masterPlaylistLoader_.load();\n }\n\n _this.timeToLoadedData__ = -1;\n _this.mainAppendsToLoadedData__ = -1;\n _this.audioAppendsToLoadedData__ = -1;\n var event = _this.tech_.preload() === 'none' ? 'play' : 'loadstart'; // start the first frame timer on loadstart or play (for preload none)\n\n _this.tech_.one(event, function () {\n var timeToLoadedDataStart = Date.now();\n\n _this.tech_.one('loadeddata', function () {\n _this.timeToLoadedData__ = Date.now() - timeToLoadedDataStart;\n _this.mainAppendsToLoadedData__ = _this.mainSegmentLoader_.mediaAppends;\n _this.audioAppendsToLoadedData__ = _this.audioSegmentLoader_.mediaAppends;\n });\n });\n\n return _this;\n }\n\n var _proto = MasterPlaylistController.prototype;\n\n _proto.mainAppendsToLoadedData_ = function mainAppendsToLoadedData_() {\n return this.mainAppendsToLoadedData__;\n };\n\n _proto.audioAppendsToLoadedData_ = function audioAppendsToLoadedData_() {\n return this.audioAppendsToLoadedData__;\n };\n\n _proto.appendsToLoadedData_ = function appendsToLoadedData_() {\n var main = this.mainAppendsToLoadedData_();\n var audio = this.audioAppendsToLoadedData_();\n\n if (main === -1 || audio === -1) {\n return -1;\n }\n\n return main + audio;\n };\n\n _proto.timeToLoadedData_ = function timeToLoadedData_() {\n return this.timeToLoadedData__;\n }\n /**\n * Run selectPlaylist and switch to the new playlist if we should\n *\n * @private\n *\n */\n ;\n\n _proto.checkABR_ = function checkABR_() {\n var nextPlaylist = this.selectPlaylist();\n\n if (nextPlaylist && this.shouldSwitchToMedia_(nextPlaylist)) {\n this.switchMedia_(nextPlaylist, 'abr');\n }\n };\n\n _proto.switchMedia_ = function switchMedia_(playlist, cause, delay) {\n var oldMedia = this.media();\n var oldId = oldMedia && (oldMedia.id || oldMedia.uri);\n var newId = playlist.id || playlist.uri;\n\n if (oldId && oldId !== newId) {\n this.logger_(\"switch media \" + oldId + \" -> \" + newId + \" from \" + cause);\n this.tech_.trigger({\n type: 'usage',\n name: \"vhs-rendition-change-\" + cause\n });\n }\n\n this.masterPlaylistLoader_.media(playlist, delay);\n }\n /**\n * Start a timer that periodically calls checkABR_\n *\n * @private\n */\n ;\n\n _proto.startABRTimer_ = function startABRTimer_() {\n var _this2 = this;\n\n this.stopABRTimer_();\n this.abrTimer_ = window$1.setInterval(function () {\n return _this2.checkABR_();\n }, 250);\n }\n /**\n * Stop the timer that periodically calls checkABR_\n *\n * @private\n */\n ;\n\n _proto.stopABRTimer_ = function stopABRTimer_() {\n // if we're scrubbing, we don't need to pause.\n // This getter will be added to Video.js in version 7.11.\n if (this.tech_.scrubbing && this.tech_.scrubbing()) {\n return;\n }\n\n window$1.clearInterval(this.abrTimer_);\n this.abrTimer_ = null;\n }\n /**\n * Get a list of playlists for the currently selected audio playlist\n *\n * @return {Array} the array of audio playlists\n */\n ;\n\n _proto.getAudioTrackPlaylists_ = function getAudioTrackPlaylists_() {\n var master = this.master();\n var defaultPlaylists = master && master.playlists || []; // if we don't have any audio groups then we can only\n // assume that the audio tracks are contained in masters\n // playlist array, use that or an empty array.\n\n if (!master || !master.mediaGroups || !master.mediaGroups.AUDIO) {\n return defaultPlaylists;\n }\n\n var AUDIO = master.mediaGroups.AUDIO;\n var groupKeys = Object.keys(AUDIO);\n var track; // get the current active track\n\n if (Object.keys(this.mediaTypes_.AUDIO.groups).length) {\n track = this.mediaTypes_.AUDIO.activeTrack(); // or get the default track from master if mediaTypes_ isn't setup yet\n } else {\n // default group is `main` or just the first group.\n var defaultGroup = AUDIO.main || groupKeys.length && AUDIO[groupKeys[0]];\n\n for (var label in defaultGroup) {\n if (defaultGroup[label].default) {\n track = {\n label: label\n };\n break;\n }\n }\n } // no active track no playlists.\n\n\n if (!track) {\n return defaultPlaylists;\n }\n\n var playlists = []; // get all of the playlists that are possible for the\n // active track.\n\n for (var group in AUDIO) {\n if (AUDIO[group][track.label]) {\n var properties = AUDIO[group][track.label];\n\n if (properties.playlists && properties.playlists.length) {\n playlists.push.apply(playlists, properties.playlists);\n } else if (properties.uri) {\n playlists.push(properties);\n } else if (master.playlists.length) {\n // if an audio group does not have a uri\n // see if we have main playlists that use it as a group.\n // if we do then add those to the playlists list.\n for (var i = 0; i < master.playlists.length; i++) {\n var playlist = master.playlists[i];\n\n if (playlist.attributes && playlist.attributes.AUDIO && playlist.attributes.AUDIO === group) {\n playlists.push(playlist);\n }\n }\n }\n }\n }\n\n if (!playlists.length) {\n return defaultPlaylists;\n }\n\n return playlists;\n }\n /**\n * Register event handlers on the master playlist loader. A helper\n * function for construction time.\n *\n * @private\n */\n ;\n\n _proto.setupMasterPlaylistLoaderListeners_ = function setupMasterPlaylistLoaderListeners_() {\n var _this3 = this;\n\n this.masterPlaylistLoader_.on('loadedmetadata', function () {\n var media = _this3.masterPlaylistLoader_.media();\n\n var requestTimeout = media.targetDuration * 1.5 * 1000; // If we don't have any more available playlists, we don't want to\n // timeout the request.\n\n if (isLowestEnabledRendition(_this3.masterPlaylistLoader_.master, _this3.masterPlaylistLoader_.media())) {\n _this3.requestOptions_.timeout = 0;\n } else {\n _this3.requestOptions_.timeout = requestTimeout;\n } // if this isn't a live video and preload permits, start\n // downloading segments\n\n\n if (media.endList && _this3.tech_.preload() !== 'none') {\n _this3.mainSegmentLoader_.playlist(media, _this3.requestOptions_);\n\n _this3.mainSegmentLoader_.load();\n }\n\n setupMediaGroups({\n sourceType: _this3.sourceType_,\n segmentLoaders: {\n AUDIO: _this3.audioSegmentLoader_,\n SUBTITLES: _this3.subtitleSegmentLoader_,\n main: _this3.mainSegmentLoader_\n },\n tech: _this3.tech_,\n requestOptions: _this3.requestOptions_,\n masterPlaylistLoader: _this3.masterPlaylistLoader_,\n vhs: _this3.vhs_,\n master: _this3.master(),\n mediaTypes: _this3.mediaTypes_,\n blacklistCurrentPlaylist: _this3.blacklistCurrentPlaylist.bind(_this3)\n });\n\n _this3.triggerPresenceUsage_(_this3.master(), media);\n\n _this3.setupFirstPlay();\n\n if (!_this3.mediaTypes_.AUDIO.activePlaylistLoader || _this3.mediaTypes_.AUDIO.activePlaylistLoader.media()) {\n _this3.trigger('selectedinitialmedia');\n } else {\n // We must wait for the active audio playlist loader to\n // finish setting up before triggering this event so the\n // representations API and EME setup is correct\n _this3.mediaTypes_.AUDIO.activePlaylistLoader.one('loadedmetadata', function () {\n _this3.trigger('selectedinitialmedia');\n });\n }\n });\n this.masterPlaylistLoader_.on('loadedplaylist', function () {\n if (_this3.loadOnPlay_) {\n _this3.tech_.off('play', _this3.loadOnPlay_);\n }\n\n var updatedPlaylist = _this3.masterPlaylistLoader_.media();\n\n if (!updatedPlaylist) {\n // exclude any variants that are not supported by the browser before selecting\n // an initial media as the playlist selectors do not consider browser support\n _this3.excludeUnsupportedVariants_();\n\n var selectedMedia;\n\n if (_this3.enableLowInitialPlaylist) {\n selectedMedia = _this3.selectInitialPlaylist();\n }\n\n if (!selectedMedia) {\n selectedMedia = _this3.selectPlaylist();\n }\n\n if (!selectedMedia || !_this3.shouldSwitchToMedia_(selectedMedia)) {\n return;\n }\n\n _this3.initialMedia_ = selectedMedia;\n\n _this3.switchMedia_(_this3.initialMedia_, 'initial'); // Under the standard case where a source URL is provided, loadedplaylist will\n // fire again since the playlist will be requested. In the case of vhs-json\n // (where the manifest object is provided as the source), when the media\n // playlist's `segments` list is already available, a media playlist won't be\n // requested, and loadedplaylist won't fire again, so the playlist handler must be\n // called on its own here.\n\n\n var haveJsonSource = _this3.sourceType_ === 'vhs-json' && _this3.initialMedia_.segments;\n\n if (!haveJsonSource) {\n return;\n }\n\n updatedPlaylist = _this3.initialMedia_;\n }\n\n _this3.handleUpdatedMediaPlaylist(updatedPlaylist);\n });\n this.masterPlaylistLoader_.on('error', function () {\n _this3.blacklistCurrentPlaylist(_this3.masterPlaylistLoader_.error);\n });\n this.masterPlaylistLoader_.on('mediachanging', function () {\n _this3.mainSegmentLoader_.abort();\n\n _this3.mainSegmentLoader_.pause();\n });\n this.masterPlaylistLoader_.on('mediachange', function () {\n var media = _this3.masterPlaylistLoader_.media();\n\n var requestTimeout = media.targetDuration * 1.5 * 1000; // If we don't have any more available playlists, we don't want to\n // timeout the request.\n\n if (isLowestEnabledRendition(_this3.masterPlaylistLoader_.master, _this3.masterPlaylistLoader_.media())) {\n _this3.requestOptions_.timeout = 0;\n } else {\n _this3.requestOptions_.timeout = requestTimeout;\n } // TODO: Create a new event on the PlaylistLoader that signals\n // that the segments have changed in some way and use that to\n // update the SegmentLoader instead of doing it twice here and\n // on `loadedplaylist`\n\n\n _this3.mainSegmentLoader_.playlist(media, _this3.requestOptions_);\n\n _this3.mainSegmentLoader_.load();\n\n _this3.tech_.trigger({\n type: 'mediachange',\n bubbles: true\n });\n });\n this.masterPlaylistLoader_.on('playlistunchanged', function () {\n var updatedPlaylist = _this3.masterPlaylistLoader_.media(); // ignore unchanged playlists that have already been\n // excluded for not-changing. We likely just have a really slowly updating\n // playlist.\n\n\n if (updatedPlaylist.lastExcludeReason_ === 'playlist-unchanged') {\n return;\n }\n\n var playlistOutdated = _this3.stuckAtPlaylistEnd_(updatedPlaylist);\n\n if (playlistOutdated) {\n // Playlist has stopped updating and we're stuck at its end. Try to\n // blacklist it and switch to another playlist in the hope that that\n // one is updating (and give the player a chance to re-adjust to the\n // safe live point).\n _this3.blacklistCurrentPlaylist({\n message: 'Playlist no longer updating.',\n reason: 'playlist-unchanged'\n }); // useful for monitoring QoS\n\n\n _this3.tech_.trigger('playliststuck');\n }\n });\n this.masterPlaylistLoader_.on('renditiondisabled', function () {\n _this3.tech_.trigger({\n type: 'usage',\n name: 'vhs-rendition-disabled'\n });\n\n _this3.tech_.trigger({\n type: 'usage',\n name: 'hls-rendition-disabled'\n });\n });\n this.masterPlaylistLoader_.on('renditionenabled', function () {\n _this3.tech_.trigger({\n type: 'usage',\n name: 'vhs-rendition-enabled'\n });\n\n _this3.tech_.trigger({\n type: 'usage',\n name: 'hls-rendition-enabled'\n });\n });\n }\n /**\n * Given an updated media playlist (whether it was loaded for the first time, or\n * refreshed for live playlists), update any relevant properties and state to reflect\n * changes in the media that should be accounted for (e.g., cues and duration).\n *\n * @param {Object} updatedPlaylist the updated media playlist object\n *\n * @private\n */\n ;\n\n _proto.handleUpdatedMediaPlaylist = function handleUpdatedMediaPlaylist(updatedPlaylist) {\n if (this.useCueTags_) {\n this.updateAdCues_(updatedPlaylist);\n } // TODO: Create a new event on the PlaylistLoader that signals\n // that the segments have changed in some way and use that to\n // update the SegmentLoader instead of doing it twice here and\n // on `mediachange`\n\n\n this.mainSegmentLoader_.playlist(updatedPlaylist, this.requestOptions_);\n this.updateDuration(!updatedPlaylist.endList); // If the player isn't paused, ensure that the segment loader is running,\n // as it is possible that it was temporarily stopped while waiting for\n // a playlist (e.g., in case the playlist errored and we re-requested it).\n\n if (!this.tech_.paused()) {\n this.mainSegmentLoader_.load();\n\n if (this.audioSegmentLoader_) {\n this.audioSegmentLoader_.load();\n }\n }\n }\n /**\n * A helper function for triggerring presence usage events once per source\n *\n * @private\n */\n ;\n\n _proto.triggerPresenceUsage_ = function triggerPresenceUsage_(master, media) {\n var mediaGroups = master.mediaGroups || {};\n var defaultDemuxed = true;\n var audioGroupKeys = Object.keys(mediaGroups.AUDIO);\n\n for (var mediaGroup in mediaGroups.AUDIO) {\n for (var label in mediaGroups.AUDIO[mediaGroup]) {\n var properties = mediaGroups.AUDIO[mediaGroup][label];\n\n if (!properties.uri) {\n defaultDemuxed = false;\n }\n }\n }\n\n if (defaultDemuxed) {\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-demuxed'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-demuxed'\n });\n }\n\n if (Object.keys(mediaGroups.SUBTITLES).length) {\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-webvtt'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-webvtt'\n });\n }\n\n if (Vhs$1.Playlist.isAes(media)) {\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-aes'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-aes'\n });\n }\n\n if (audioGroupKeys.length && Object.keys(mediaGroups.AUDIO[audioGroupKeys[0]]).length > 1) {\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-alternate-audio'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-alternate-audio'\n });\n }\n\n if (this.useCueTags_) {\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-playlist-cue-tags'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-playlist-cue-tags'\n });\n }\n };\n\n _proto.shouldSwitchToMedia_ = function shouldSwitchToMedia_(nextPlaylist) {\n var currentPlaylist = this.masterPlaylistLoader_.media() || this.masterPlaylistLoader_.pendingMedia_;\n var currentTime = this.tech_.currentTime();\n var bufferLowWaterLine = this.bufferLowWaterLine();\n var bufferHighWaterLine = this.bufferHighWaterLine();\n var buffered = this.tech_.buffered();\n return shouldSwitchToMedia({\n buffered: buffered,\n currentTime: currentTime,\n currentPlaylist: currentPlaylist,\n nextPlaylist: nextPlaylist,\n bufferLowWaterLine: bufferLowWaterLine,\n bufferHighWaterLine: bufferHighWaterLine,\n duration: this.duration(),\n experimentalBufferBasedABR: this.experimentalBufferBasedABR,\n log: this.logger_\n });\n }\n /**\n * Register event handlers on the segment loaders. A helper function\n * for construction time.\n *\n * @private\n */\n ;\n\n _proto.setupSegmentLoaderListeners_ = function setupSegmentLoaderListeners_() {\n var _this4 = this;\n\n if (!this.experimentalBufferBasedABR) {\n this.mainSegmentLoader_.on('bandwidthupdate', function () {\n var nextPlaylist = _this4.selectPlaylist();\n\n if (_this4.shouldSwitchToMedia_(nextPlaylist)) {\n _this4.switchMedia_(nextPlaylist, 'bandwidthupdate');\n }\n\n _this4.tech_.trigger('bandwidthupdate');\n });\n this.mainSegmentLoader_.on('progress', function () {\n _this4.trigger('progress');\n });\n }\n\n this.mainSegmentLoader_.on('error', function () {\n _this4.blacklistCurrentPlaylist(_this4.mainSegmentLoader_.error());\n });\n this.mainSegmentLoader_.on('appenderror', function () {\n _this4.error = _this4.mainSegmentLoader_.error_;\n\n _this4.trigger('error');\n });\n this.mainSegmentLoader_.on('syncinfoupdate', function () {\n _this4.onSyncInfoUpdate_();\n });\n this.mainSegmentLoader_.on('timestampoffset', function () {\n _this4.tech_.trigger({\n type: 'usage',\n name: 'vhs-timestamp-offset'\n });\n\n _this4.tech_.trigger({\n type: 'usage',\n name: 'hls-timestamp-offset'\n });\n });\n this.audioSegmentLoader_.on('syncinfoupdate', function () {\n _this4.onSyncInfoUpdate_();\n });\n this.audioSegmentLoader_.on('appenderror', function () {\n _this4.error = _this4.audioSegmentLoader_.error_;\n\n _this4.trigger('error');\n });\n this.mainSegmentLoader_.on('ended', function () {\n _this4.logger_('main segment loader ended');\n\n _this4.onEndOfStream();\n });\n this.mainSegmentLoader_.on('earlyabort', function (event) {\n // never try to early abort with the new ABR algorithm\n if (_this4.experimentalBufferBasedABR) {\n return;\n }\n\n _this4.delegateLoaders_('all', ['abort']);\n\n _this4.blacklistCurrentPlaylist({\n message: 'Aborted early because there isn\\'t enough bandwidth to complete the ' + 'request without rebuffering.'\n }, ABORT_EARLY_BLACKLIST_SECONDS);\n });\n\n var updateCodecs = function updateCodecs() {\n if (!_this4.sourceUpdater_.hasCreatedSourceBuffers()) {\n return _this4.tryToCreateSourceBuffers_();\n }\n\n var codecs = _this4.getCodecsOrExclude_(); // no codecs means that the playlist was excluded\n\n\n if (!codecs) {\n return;\n }\n\n _this4.sourceUpdater_.addOrChangeSourceBuffers(codecs);\n };\n\n this.mainSegmentLoader_.on('trackinfo', updateCodecs);\n this.audioSegmentLoader_.on('trackinfo', updateCodecs);\n this.mainSegmentLoader_.on('fmp4', function () {\n if (!_this4.triggeredFmp4Usage) {\n _this4.tech_.trigger({\n type: 'usage',\n name: 'vhs-fmp4'\n });\n\n _this4.tech_.trigger({\n type: 'usage',\n name: 'hls-fmp4'\n });\n\n _this4.triggeredFmp4Usage = true;\n }\n });\n this.audioSegmentLoader_.on('fmp4', function () {\n if (!_this4.triggeredFmp4Usage) {\n _this4.tech_.trigger({\n type: 'usage',\n name: 'vhs-fmp4'\n });\n\n _this4.tech_.trigger({\n type: 'usage',\n name: 'hls-fmp4'\n });\n\n _this4.triggeredFmp4Usage = true;\n }\n });\n this.audioSegmentLoader_.on('ended', function () {\n _this4.logger_('audioSegmentLoader ended');\n\n _this4.onEndOfStream();\n });\n };\n\n _proto.mediaSecondsLoaded_ = function mediaSecondsLoaded_() {\n return Math.max(this.audioSegmentLoader_.mediaSecondsLoaded + this.mainSegmentLoader_.mediaSecondsLoaded);\n }\n /**\n * Call load on our SegmentLoaders\n */\n ;\n\n _proto.load = function load() {\n this.mainSegmentLoader_.load();\n\n if (this.mediaTypes_.AUDIO.activePlaylistLoader) {\n this.audioSegmentLoader_.load();\n }\n\n if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) {\n this.subtitleSegmentLoader_.load();\n }\n }\n /**\n * Re-tune playback quality level for the current player\n * conditions without performing destructive actions, like\n * removing already buffered content\n *\n * @private\n * @deprecated\n */\n ;\n\n _proto.smoothQualityChange_ = function smoothQualityChange_(media) {\n if (media === void 0) {\n media = this.selectPlaylist();\n }\n\n this.fastQualityChange_(media);\n }\n /**\n * Re-tune playback quality level for the current player\n * conditions. This method will perform destructive actions like removing\n * already buffered content in order to readjust the currently active\n * playlist quickly. This is good for manual quality changes\n *\n * @private\n */\n ;\n\n _proto.fastQualityChange_ = function fastQualityChange_(media) {\n var _this5 = this;\n\n if (media === void 0) {\n media = this.selectPlaylist();\n }\n\n if (media === this.masterPlaylistLoader_.media()) {\n this.logger_('skipping fastQualityChange because new media is same as old');\n return;\n }\n\n this.switchMedia_(media, 'fast-quality'); // Delete all buffered data to allow an immediate quality switch, then seek to give\n // the browser a kick to remove any cached frames from the previous rendtion (.04 seconds\n // ahead is roughly the minimum that will accomplish this across a variety of content\n // in IE and Edge, but seeking in place is sufficient on all other browsers)\n // Edge/IE bug: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14600375/\n // Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=651904\n\n this.mainSegmentLoader_.resetEverything(function () {\n // Since this is not a typical seek, we avoid the seekTo method which can cause segments\n // from the previously enabled rendition to load before the new playlist has finished loading\n if (videojs.browser.IE_VERSION || videojs.browser.IS_EDGE) {\n _this5.tech_.setCurrentTime(_this5.tech_.currentTime() + 0.04);\n } else {\n _this5.tech_.setCurrentTime(_this5.tech_.currentTime());\n }\n }); // don't need to reset audio as it is reset when media changes\n }\n /**\n * Begin playback.\n */\n ;\n\n _proto.play = function play() {\n if (this.setupFirstPlay()) {\n return;\n }\n\n if (this.tech_.ended()) {\n this.tech_.setCurrentTime(0);\n }\n\n if (this.hasPlayed_) {\n this.load();\n }\n\n var seekable = this.tech_.seekable(); // if the viewer has paused and we fell out of the live window,\n // seek forward to the live point\n\n if (this.tech_.duration() === Infinity) {\n if (this.tech_.currentTime() < seekable.start(0)) {\n return this.tech_.setCurrentTime(seekable.end(seekable.length - 1));\n }\n }\n }\n /**\n * Seek to the latest media position if this is a live video and the\n * player and video are loaded and initialized.\n */\n ;\n\n _proto.setupFirstPlay = function setupFirstPlay() {\n var _this6 = this;\n\n var media = this.masterPlaylistLoader_.media(); // Check that everything is ready to begin buffering for the first call to play\n // If 1) there is no active media\n // 2) the player is paused\n // 3) the first play has already been setup\n // then exit early\n\n if (!media || this.tech_.paused() || this.hasPlayed_) {\n return false;\n } // when the video is a live stream\n\n\n if (!media.endList) {\n var seekable = this.seekable();\n\n if (!seekable.length) {\n // without a seekable range, the player cannot seek to begin buffering at the live\n // point\n return false;\n }\n\n if (videojs.browser.IE_VERSION && this.tech_.readyState() === 0) {\n // IE11 throws an InvalidStateError if you try to set currentTime while the\n // readyState is 0, so it must be delayed until the tech fires loadedmetadata.\n this.tech_.one('loadedmetadata', function () {\n _this6.trigger('firstplay');\n\n _this6.tech_.setCurrentTime(seekable.end(0));\n\n _this6.hasPlayed_ = true;\n });\n return false;\n } // trigger firstplay to inform the source handler to ignore the next seek event\n\n\n this.trigger('firstplay'); // seek to the live point\n\n this.tech_.setCurrentTime(seekable.end(0));\n }\n\n this.hasPlayed_ = true; // we can begin loading now that everything is ready\n\n this.load();\n return true;\n }\n /**\n * handle the sourceopen event on the MediaSource\n *\n * @private\n */\n ;\n\n _proto.handleSourceOpen_ = function handleSourceOpen_() {\n // Only attempt to create the source buffer if none already exist.\n // handleSourceOpen is also called when we are \"re-opening\" a source buffer\n // after `endOfStream` has been called (in response to a seek for instance)\n this.tryToCreateSourceBuffers_(); // if autoplay is enabled, begin playback. This is duplicative of\n // code in video.js but is required because play() must be invoked\n // *after* the media source has opened.\n\n if (this.tech_.autoplay()) {\n var playPromise = this.tech_.play(); // Catch/silence error when a pause interrupts a play request\n // on browsers which return a promise\n\n if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {\n playPromise.then(null, function (e) {});\n }\n }\n\n this.trigger('sourceopen');\n }\n /**\n * handle the sourceended event on the MediaSource\n *\n * @private\n */\n ;\n\n _proto.handleSourceEnded_ = function handleSourceEnded_() {\n if (!this.inbandTextTracks_.metadataTrack_) {\n return;\n }\n\n var cues = this.inbandTextTracks_.metadataTrack_.cues;\n\n if (!cues || !cues.length) {\n return;\n }\n\n var duration = this.duration();\n cues[cues.length - 1].endTime = isNaN(duration) || Math.abs(duration) === Infinity ? Number.MAX_VALUE : duration;\n }\n /**\n * handle the durationchange event on the MediaSource\n *\n * @private\n */\n ;\n\n _proto.handleDurationChange_ = function handleDurationChange_() {\n this.tech_.trigger('durationchange');\n }\n /**\n * Calls endOfStream on the media source when all active stream types have called\n * endOfStream\n *\n * @param {string} streamType\n * Stream type of the segment loader that called endOfStream\n * @private\n */\n ;\n\n _proto.onEndOfStream = function onEndOfStream() {\n var isEndOfStream = this.mainSegmentLoader_.ended_;\n\n if (this.mediaTypes_.AUDIO.activePlaylistLoader) {\n var mainMediaInfo = this.mainSegmentLoader_.getCurrentMediaInfo_(); // if the audio playlist loader exists, then alternate audio is active\n\n if (!mainMediaInfo || mainMediaInfo.hasVideo) {\n // if we do not know if the main segment loader contains video yet or if we\n // definitively know the main segment loader contains video, then we need to wait\n // for both main and audio segment loaders to call endOfStream\n isEndOfStream = isEndOfStream && this.audioSegmentLoader_.ended_;\n } else {\n // otherwise just rely on the audio loader\n isEndOfStream = this.audioSegmentLoader_.ended_;\n }\n }\n\n if (!isEndOfStream) {\n return;\n }\n\n this.stopABRTimer_();\n this.sourceUpdater_.endOfStream();\n }\n /**\n * Check if a playlist has stopped being updated\n *\n * @param {Object} playlist the media playlist object\n * @return {boolean} whether the playlist has stopped being updated or not\n */\n ;\n\n _proto.stuckAtPlaylistEnd_ = function stuckAtPlaylistEnd_(playlist) {\n var seekable = this.seekable();\n\n if (!seekable.length) {\n // playlist doesn't have enough information to determine whether we are stuck\n return false;\n }\n\n var expired = this.syncController_.getExpiredTime(playlist, this.duration());\n\n if (expired === null) {\n return false;\n } // does not use the safe live end to calculate playlist end, since we\n // don't want to say we are stuck while there is still content\n\n\n var absolutePlaylistEnd = Vhs$1.Playlist.playlistEnd(playlist, expired);\n var currentTime = this.tech_.currentTime();\n var buffered = this.tech_.buffered();\n\n if (!buffered.length) {\n // return true if the playhead reached the absolute end of the playlist\n return absolutePlaylistEnd - currentTime <= SAFE_TIME_DELTA;\n }\n\n var bufferedEnd = buffered.end(buffered.length - 1); // return true if there is too little buffer left and buffer has reached absolute\n // end of playlist\n\n return bufferedEnd - currentTime <= SAFE_TIME_DELTA && absolutePlaylistEnd - bufferedEnd <= SAFE_TIME_DELTA;\n }\n /**\n * Blacklists a playlist when an error occurs for a set amount of time\n * making it unavailable for selection by the rendition selection algorithm\n * and then forces a new playlist (rendition) selection.\n *\n * @param {Object=} error an optional error that may include the playlist\n * to blacklist\n * @param {number=} blacklistDuration an optional number of seconds to blacklist the\n * playlist\n */\n ;\n\n _proto.blacklistCurrentPlaylist = function blacklistCurrentPlaylist(error, blacklistDuration) {\n if (error === void 0) {\n error = {};\n }\n\n // If the `error` was generated by the playlist loader, it will contain\n // the playlist we were trying to load (but failed) and that should be\n // blacklisted instead of the currently selected playlist which is likely\n // out-of-date in this scenario\n var currentPlaylist = error.playlist || this.masterPlaylistLoader_.media();\n blacklistDuration = blacklistDuration || error.blacklistDuration || this.blacklistDuration; // If there is no current playlist, then an error occurred while we were\n // trying to load the master OR while we were disposing of the tech\n\n if (!currentPlaylist) {\n this.error = error;\n\n if (this.mediaSource.readyState !== 'open') {\n this.trigger('error');\n } else {\n this.sourceUpdater_.endOfStream('network');\n }\n\n return;\n }\n\n currentPlaylist.playlistErrors_++;\n var playlists = this.masterPlaylistLoader_.master.playlists;\n var enabledPlaylists = playlists.filter(isEnabled);\n var isFinalRendition = enabledPlaylists.length === 1 && enabledPlaylists[0] === currentPlaylist; // Don't blacklist the only playlist unless it was blacklisted\n // forever\n\n if (playlists.length === 1 && blacklistDuration !== Infinity) {\n videojs.log.warn(\"Problem encountered with playlist \" + currentPlaylist.id + \". \" + 'Trying again since it is the only playlist.');\n this.tech_.trigger('retryplaylist'); // if this is a final rendition, we should delay\n\n return this.masterPlaylistLoader_.load(isFinalRendition);\n }\n\n if (isFinalRendition) {\n // Since we're on the final non-blacklisted playlist, and we're about to blacklist\n // it, instead of erring the player or retrying this playlist, clear out the current\n // blacklist. This allows other playlists to be attempted in case any have been\n // fixed.\n var reincluded = false;\n playlists.forEach(function (playlist) {\n // skip current playlist which is about to be blacklisted\n if (playlist === currentPlaylist) {\n return;\n }\n\n var excludeUntil = playlist.excludeUntil; // a playlist cannot be reincluded if it wasn't excluded to begin with.\n\n if (typeof excludeUntil !== 'undefined' && excludeUntil !== Infinity) {\n reincluded = true;\n delete playlist.excludeUntil;\n }\n });\n\n if (reincluded) {\n videojs.log.warn('Removing other playlists from the exclusion list because the last ' + 'rendition is about to be excluded.'); // Technically we are retrying a playlist, in that we are simply retrying a previous\n // playlist. This is needed for users relying on the retryplaylist event to catch a\n // case where the player might be stuck and looping through \"dead\" playlists.\n\n this.tech_.trigger('retryplaylist');\n }\n } // Blacklist this playlist\n\n\n var excludeUntil;\n\n if (currentPlaylist.playlistErrors_ > this.maxPlaylistRetries) {\n excludeUntil = Infinity;\n } else {\n excludeUntil = Date.now() + blacklistDuration * 1000;\n }\n\n currentPlaylist.excludeUntil = excludeUntil;\n\n if (error.reason) {\n currentPlaylist.lastExcludeReason_ = error.reason;\n }\n\n this.tech_.trigger('blacklistplaylist');\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-rendition-blacklisted'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-rendition-blacklisted'\n }); // TODO: should we select a new playlist if this blacklist wasn't for the currentPlaylist?\n // Would be something like media().id !=== currentPlaylist.id and we would need something\n // like `pendingMedia` in playlist loaders to check against that too. This will prevent us\n // from loading a new playlist on any blacklist.\n // Select a new playlist\n\n var nextPlaylist = this.selectPlaylist();\n\n if (!nextPlaylist) {\n this.error = 'Playback cannot continue. No available working or supported playlists.';\n this.trigger('error');\n return;\n }\n\n var logFn = error.internal ? this.logger_ : videojs.log.warn;\n var errorMessage = error.message ? ' ' + error.message : '';\n logFn((error.internal ? 'Internal problem' : 'Problem') + \" encountered with playlist \" + currentPlaylist.id + \".\" + (errorMessage + \" Switching to playlist \" + nextPlaylist.id + \".\")); // if audio group changed reset audio loaders\n\n if (nextPlaylist.attributes.AUDIO !== currentPlaylist.attributes.AUDIO) {\n this.delegateLoaders_('audio', ['abort', 'pause']);\n } // if subtitle group changed reset subtitle loaders\n\n\n if (nextPlaylist.attributes.SUBTITLES !== currentPlaylist.attributes.SUBTITLES) {\n this.delegateLoaders_('subtitle', ['abort', 'pause']);\n }\n\n this.delegateLoaders_('main', ['abort', 'pause']);\n var delayDuration = nextPlaylist.targetDuration / 2 * 1000 || 5 * 1000;\n var shouldDelay = typeof nextPlaylist.lastRequest === 'number' && Date.now() - nextPlaylist.lastRequest <= delayDuration; // delay if it's a final rendition or if the last refresh is sooner than half targetDuration\n\n return this.switchMedia_(nextPlaylist, 'exclude', isFinalRendition || shouldDelay);\n }\n /**\n * Pause all segment/playlist loaders\n */\n ;\n\n _proto.pauseLoading = function pauseLoading() {\n this.delegateLoaders_('all', ['abort', 'pause']);\n this.stopABRTimer_();\n }\n /**\n * Call a set of functions in order on playlist loaders, segment loaders,\n * or both types of loaders.\n *\n * @param {string} filter\n * Filter loaders that should call fnNames using a string. Can be:\n * * all - run on all loaders\n * * audio - run on all audio loaders\n * * subtitle - run on all subtitle loaders\n * * main - run on the main/master loaders\n *\n * @param {Array|string} fnNames\n * A string or array of function names to call.\n */\n ;\n\n _proto.delegateLoaders_ = function delegateLoaders_(filter, fnNames) {\n var _this7 = this;\n\n var loaders = [];\n var dontFilterPlaylist = filter === 'all';\n\n if (dontFilterPlaylist || filter === 'main') {\n loaders.push(this.masterPlaylistLoader_);\n }\n\n var mediaTypes = [];\n\n if (dontFilterPlaylist || filter === 'audio') {\n mediaTypes.push('AUDIO');\n }\n\n if (dontFilterPlaylist || filter === 'subtitle') {\n mediaTypes.push('CLOSED-CAPTIONS');\n mediaTypes.push('SUBTITLES');\n }\n\n mediaTypes.forEach(function (mediaType) {\n var loader = _this7.mediaTypes_[mediaType] && _this7.mediaTypes_[mediaType].activePlaylistLoader;\n\n if (loader) {\n loaders.push(loader);\n }\n });\n ['main', 'audio', 'subtitle'].forEach(function (name) {\n var loader = _this7[name + \"SegmentLoader_\"];\n\n if (loader && (filter === name || filter === 'all')) {\n loaders.push(loader);\n }\n });\n loaders.forEach(function (loader) {\n return fnNames.forEach(function (fnName) {\n if (typeof loader[fnName] === 'function') {\n loader[fnName]();\n }\n });\n });\n }\n /**\n * set the current time on all segment loaders\n *\n * @param {TimeRange} currentTime the current time to set\n * @return {TimeRange} the current time\n */\n ;\n\n _proto.setCurrentTime = function setCurrentTime(currentTime) {\n var buffered = findRange(this.tech_.buffered(), currentTime);\n\n if (!(this.masterPlaylistLoader_ && this.masterPlaylistLoader_.media())) {\n // return immediately if the metadata is not ready yet\n return 0;\n } // it's clearly an edge-case but don't thrown an error if asked to\n // seek within an empty playlist\n\n\n if (!this.masterPlaylistLoader_.media().segments) {\n return 0;\n } // if the seek location is already buffered, continue buffering as usual\n\n\n if (buffered && buffered.length) {\n return currentTime;\n } // cancel outstanding requests so we begin buffering at the new\n // location\n\n\n this.mainSegmentLoader_.resetEverything();\n this.mainSegmentLoader_.abort();\n\n if (this.mediaTypes_.AUDIO.activePlaylistLoader) {\n this.audioSegmentLoader_.resetEverything();\n this.audioSegmentLoader_.abort();\n }\n\n if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) {\n this.subtitleSegmentLoader_.resetEverything();\n this.subtitleSegmentLoader_.abort();\n } // start segment loader loading in case they are paused\n\n\n this.load();\n }\n /**\n * get the current duration\n *\n * @return {TimeRange} the duration\n */\n ;\n\n _proto.duration = function duration() {\n if (!this.masterPlaylistLoader_) {\n return 0;\n }\n\n var media = this.masterPlaylistLoader_.media();\n\n if (!media) {\n // no playlists loaded yet, so can't determine a duration\n return 0;\n } // Don't rely on the media source for duration in the case of a live playlist since\n // setting the native MediaSource's duration to infinity ends up with consequences to\n // seekable behavior. See https://github.com/w3c/media-source/issues/5 for details.\n //\n // This is resolved in the spec by https://github.com/w3c/media-source/pull/92,\n // however, few browsers have support for setLiveSeekableRange()\n // https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/setLiveSeekableRange\n //\n // Until a time when the duration of the media source can be set to infinity, and a\n // seekable range specified across browsers, just return Infinity.\n\n\n if (!media.endList) {\n return Infinity;\n } // Since this is a VOD video, it is safe to rely on the media source's duration (if\n // available). If it's not available, fall back to a playlist-calculated estimate.\n\n\n if (this.mediaSource) {\n return this.mediaSource.duration;\n }\n\n return Vhs$1.Playlist.duration(media);\n }\n /**\n * check the seekable range\n *\n * @return {TimeRange} the seekable range\n */\n ;\n\n _proto.seekable = function seekable() {\n return this.seekable_;\n };\n\n _proto.onSyncInfoUpdate_ = function onSyncInfoUpdate_() {\n var audioSeekable; // TODO check for creation of both source buffers before updating seekable\n //\n // A fix was made to this function where a check for\n // this.sourceUpdater_.hasCreatedSourceBuffers\n // was added to ensure that both source buffers were created before seekable was\n // updated. However, it originally had a bug where it was checking for a true and\n // returning early instead of checking for false. Setting it to check for false to\n // return early though created other issues. A call to play() would check for seekable\n // end without verifying that a seekable range was present. In addition, even checking\n // for that didn't solve some issues, as handleFirstPlay is sometimes worked around\n // due to a media update calling load on the segment loaders, skipping a seek to live,\n // thereby starting live streams at the beginning of the stream rather than at the end.\n //\n // This conditional should be fixed to wait for the creation of two source buffers at\n // the same time as the other sections of code are fixed to properly seek to live and\n // not throw an error due to checking for a seekable end when no seekable range exists.\n //\n // For now, fall back to the older behavior, with the understanding that the seekable\n // range may not be completely correct, leading to a suboptimal initial live point.\n\n if (!this.masterPlaylistLoader_) {\n return;\n }\n\n var media = this.masterPlaylistLoader_.media();\n\n if (!media) {\n return;\n }\n\n var expired = this.syncController_.getExpiredTime(media, this.duration());\n\n if (expired === null) {\n // not enough information to update seekable\n return;\n }\n\n var master = this.masterPlaylistLoader_.master;\n var mainSeekable = Vhs$1.Playlist.seekable(media, expired, Vhs$1.Playlist.liveEdgeDelay(master, media));\n\n if (mainSeekable.length === 0) {\n return;\n }\n\n if (this.mediaTypes_.AUDIO.activePlaylistLoader) {\n media = this.mediaTypes_.AUDIO.activePlaylistLoader.media();\n expired = this.syncController_.getExpiredTime(media, this.duration());\n\n if (expired === null) {\n return;\n }\n\n audioSeekable = Vhs$1.Playlist.seekable(media, expired, Vhs$1.Playlist.liveEdgeDelay(master, media));\n\n if (audioSeekable.length === 0) {\n return;\n }\n }\n\n var oldEnd;\n var oldStart;\n\n if (this.seekable_ && this.seekable_.length) {\n oldEnd = this.seekable_.end(0);\n oldStart = this.seekable_.start(0);\n }\n\n if (!audioSeekable) {\n // seekable has been calculated based on buffering video data so it\n // can be returned directly\n this.seekable_ = mainSeekable;\n } else if (audioSeekable.start(0) > mainSeekable.end(0) || mainSeekable.start(0) > audioSeekable.end(0)) {\n // seekables are pretty far off, rely on main\n this.seekable_ = mainSeekable;\n } else {\n this.seekable_ = videojs.createTimeRanges([[audioSeekable.start(0) > mainSeekable.start(0) ? audioSeekable.start(0) : mainSeekable.start(0), audioSeekable.end(0) < mainSeekable.end(0) ? audioSeekable.end(0) : mainSeekable.end(0)]]);\n } // seekable is the same as last time\n\n\n if (this.seekable_ && this.seekable_.length) {\n if (this.seekable_.end(0) === oldEnd && this.seekable_.start(0) === oldStart) {\n return;\n }\n }\n\n this.logger_(\"seekable updated [\" + printableRange(this.seekable_) + \"]\");\n this.tech_.trigger('seekablechanged');\n }\n /**\n * Update the player duration\n */\n ;\n\n _proto.updateDuration = function updateDuration(isLive) {\n if (this.updateDuration_) {\n this.mediaSource.removeEventListener('sourceopen', this.updateDuration_);\n this.updateDuration_ = null;\n }\n\n if (this.mediaSource.readyState !== 'open') {\n this.updateDuration_ = this.updateDuration.bind(this, isLive);\n this.mediaSource.addEventListener('sourceopen', this.updateDuration_);\n return;\n }\n\n if (isLive) {\n var seekable = this.seekable();\n\n if (!seekable.length) {\n return;\n } // Even in the case of a live playlist, the native MediaSource's duration should not\n // be set to Infinity (even though this would be expected for a live playlist), since\n // setting the native MediaSource's duration to infinity ends up with consequences to\n // seekable behavior. See https://github.com/w3c/media-source/issues/5 for details.\n //\n // This is resolved in the spec by https://github.com/w3c/media-source/pull/92,\n // however, few browsers have support for setLiveSeekableRange()\n // https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/setLiveSeekableRange\n //\n // Until a time when the duration of the media source can be set to infinity, and a\n // seekable range specified across browsers, the duration should be greater than or\n // equal to the last possible seekable value.\n // MediaSource duration starts as NaN\n // It is possible (and probable) that this case will never be reached for many\n // sources, since the MediaSource reports duration as the highest value without\n // accounting for timestamp offset. For example, if the timestamp offset is -100 and\n // we buffered times 0 to 100 with real times of 100 to 200, even though current\n // time will be between 0 and 100, the native media source may report the duration\n // as 200. However, since we report duration separate from the media source (as\n // Infinity), and as long as the native media source duration value is greater than\n // our reported seekable range, seeks will work as expected. The large number as\n // duration for live is actually a strategy used by some players to work around the\n // issue of live seekable ranges cited above.\n\n\n if (isNaN(this.mediaSource.duration) || this.mediaSource.duration < seekable.end(seekable.length - 1)) {\n this.sourceUpdater_.setDuration(seekable.end(seekable.length - 1));\n }\n\n return;\n }\n\n var buffered = this.tech_.buffered();\n var duration = Vhs$1.Playlist.duration(this.masterPlaylistLoader_.media());\n\n if (buffered.length > 0) {\n duration = Math.max(duration, buffered.end(buffered.length - 1));\n }\n\n if (this.mediaSource.duration !== duration) {\n this.sourceUpdater_.setDuration(duration);\n }\n }\n /**\n * dispose of the MasterPlaylistController and everything\n * that it controls\n */\n ;\n\n _proto.dispose = function dispose() {\n var _this8 = this;\n\n this.trigger('dispose');\n this.decrypter_.terminate();\n this.masterPlaylistLoader_.dispose();\n this.mainSegmentLoader_.dispose();\n\n if (this.loadOnPlay_) {\n this.tech_.off('play', this.loadOnPlay_);\n }\n\n ['AUDIO', 'SUBTITLES'].forEach(function (type) {\n var groups = _this8.mediaTypes_[type].groups;\n\n for (var id in groups) {\n groups[id].forEach(function (group) {\n if (group.playlistLoader) {\n group.playlistLoader.dispose();\n }\n });\n }\n });\n this.audioSegmentLoader_.dispose();\n this.subtitleSegmentLoader_.dispose();\n this.sourceUpdater_.dispose();\n this.timelineChangeController_.dispose();\n this.stopABRTimer_();\n\n if (this.updateDuration_) {\n this.mediaSource.removeEventListener('sourceopen', this.updateDuration_);\n }\n\n this.mediaSource.removeEventListener('durationchange', this.handleDurationChange_); // load the media source into the player\n\n this.mediaSource.removeEventListener('sourceopen', this.handleSourceOpen_);\n this.mediaSource.removeEventListener('sourceended', this.handleSourceEnded_);\n this.off();\n }\n /**\n * return the master playlist object if we have one\n *\n * @return {Object} the master playlist object that we parsed\n */\n ;\n\n _proto.master = function master() {\n return this.masterPlaylistLoader_.master;\n }\n /**\n * return the currently selected playlist\n *\n * @return {Object} the currently selected playlist object that we parsed\n */\n ;\n\n _proto.media = function media() {\n // playlist loader will not return media if it has not been fully loaded\n return this.masterPlaylistLoader_.media() || this.initialMedia_;\n };\n\n _proto.areMediaTypesKnown_ = function areMediaTypesKnown_() {\n var usingAudioLoader = !!this.mediaTypes_.AUDIO.activePlaylistLoader;\n var hasMainMediaInfo = !!this.mainSegmentLoader_.getCurrentMediaInfo_(); // if we are not using an audio loader, then we have audio media info\n // otherwise check on the segment loader.\n\n var hasAudioMediaInfo = !usingAudioLoader ? true : !!this.audioSegmentLoader_.getCurrentMediaInfo_(); // one or both loaders has not loaded sufficently to get codecs\n\n if (!hasMainMediaInfo || !hasAudioMediaInfo) {\n return false;\n }\n\n return true;\n };\n\n _proto.getCodecsOrExclude_ = function getCodecsOrExclude_() {\n var _this9 = this;\n\n var media = {\n main: this.mainSegmentLoader_.getCurrentMediaInfo_() || {},\n audio: this.audioSegmentLoader_.getCurrentMediaInfo_() || {}\n }; // set \"main\" media equal to video\n\n media.video = media.main;\n var playlistCodecs = codecsForPlaylist(this.master(), this.media());\n var codecs = {};\n var usingAudioLoader = !!this.mediaTypes_.AUDIO.activePlaylistLoader;\n\n if (media.main.hasVideo) {\n codecs.video = playlistCodecs.video || media.main.videoCodec || DEFAULT_VIDEO_CODEC;\n }\n\n if (media.main.isMuxed) {\n codecs.video += \",\" + (playlistCodecs.audio || media.main.audioCodec || DEFAULT_AUDIO_CODEC);\n }\n\n if (media.main.hasAudio && !media.main.isMuxed || media.audio.hasAudio || usingAudioLoader) {\n codecs.audio = playlistCodecs.audio || media.main.audioCodec || media.audio.audioCodec || DEFAULT_AUDIO_CODEC; // set audio isFmp4 so we use the correct \"supports\" function below\n\n media.audio.isFmp4 = media.main.hasAudio && !media.main.isMuxed ? media.main.isFmp4 : media.audio.isFmp4;\n } // no codecs, no playback.\n\n\n if (!codecs.audio && !codecs.video) {\n this.blacklistCurrentPlaylist({\n playlist: this.media(),\n message: 'Could not determine codecs for playlist.',\n blacklistDuration: Infinity\n });\n return;\n } // fmp4 relies on browser support, while ts relies on muxer support\n\n\n var supportFunction = function supportFunction(isFmp4, codec) {\n return isFmp4 ? browserSupportsCodec(codec) : muxerSupportsCodec(codec);\n };\n\n var unsupportedCodecs = {};\n var unsupportedAudio;\n ['video', 'audio'].forEach(function (type) {\n if (codecs.hasOwnProperty(type) && !supportFunction(media[type].isFmp4, codecs[type])) {\n var supporter = media[type].isFmp4 ? 'browser' : 'muxer';\n unsupportedCodecs[supporter] = unsupportedCodecs[supporter] || [];\n unsupportedCodecs[supporter].push(codecs[type]);\n\n if (type === 'audio') {\n unsupportedAudio = supporter;\n }\n }\n });\n\n if (usingAudioLoader && unsupportedAudio && this.media().attributes.AUDIO) {\n var audioGroup = this.media().attributes.AUDIO;\n this.master().playlists.forEach(function (variant) {\n var variantAudioGroup = variant.attributes && variant.attributes.AUDIO;\n\n if (variantAudioGroup === audioGroup && variant !== _this9.media()) {\n variant.excludeUntil = Infinity;\n }\n });\n this.logger_(\"excluding audio group \" + audioGroup + \" as \" + unsupportedAudio + \" does not support codec(s): \\\"\" + codecs.audio + \"\\\"\");\n } // if we have any unsupported codecs blacklist this playlist.\n\n\n if (Object.keys(unsupportedCodecs).length) {\n var message = Object.keys(unsupportedCodecs).reduce(function (acc, supporter) {\n if (acc) {\n acc += ', ';\n }\n\n acc += supporter + \" does not support codec(s): \\\"\" + unsupportedCodecs[supporter].join(',') + \"\\\"\";\n return acc;\n }, '') + '.';\n this.blacklistCurrentPlaylist({\n playlist: this.media(),\n internal: true,\n message: message,\n blacklistDuration: Infinity\n });\n return;\n } // check if codec switching is happening\n\n\n if (this.sourceUpdater_.hasCreatedSourceBuffers() && !this.sourceUpdater_.canChangeType()) {\n var switchMessages = [];\n ['video', 'audio'].forEach(function (type) {\n var newCodec = (parseCodecs(_this9.sourceUpdater_.codecs[type] || '')[0] || {}).type;\n var oldCodec = (parseCodecs(codecs[type] || '')[0] || {}).type;\n\n if (newCodec && oldCodec && newCodec.toLowerCase() !== oldCodec.toLowerCase()) {\n switchMessages.push(\"\\\"\" + _this9.sourceUpdater_.codecs[type] + \"\\\" -> \\\"\" + codecs[type] + \"\\\"\");\n }\n });\n\n if (switchMessages.length) {\n this.blacklistCurrentPlaylist({\n playlist: this.media(),\n message: \"Codec switching not supported: \" + switchMessages.join(', ') + \".\",\n blacklistDuration: Infinity,\n internal: true\n });\n return;\n }\n } // TODO: when using the muxer shouldn't we just return\n // the codecs that the muxer outputs?\n\n\n return codecs;\n }\n /**\n * Create source buffers and exlude any incompatible renditions.\n *\n * @private\n */\n ;\n\n _proto.tryToCreateSourceBuffers_ = function tryToCreateSourceBuffers_() {\n // media source is not ready yet or sourceBuffers are already\n // created.\n if (this.mediaSource.readyState !== 'open' || this.sourceUpdater_.hasCreatedSourceBuffers()) {\n return;\n }\n\n if (!this.areMediaTypesKnown_()) {\n return;\n }\n\n var codecs = this.getCodecsOrExclude_(); // no codecs means that the playlist was excluded\n\n if (!codecs) {\n return;\n }\n\n this.sourceUpdater_.createSourceBuffers(codecs);\n var codecString = [codecs.video, codecs.audio].filter(Boolean).join(',');\n this.excludeIncompatibleVariants_(codecString);\n }\n /**\n * Excludes playlists with codecs that are unsupported by the muxer and browser.\n */\n ;\n\n _proto.excludeUnsupportedVariants_ = function excludeUnsupportedVariants_() {\n var _this10 = this;\n\n var playlists = this.master().playlists;\n var ids = []; // TODO: why don't we have a property to loop through all\n // playlist? Why did we ever mix indexes and keys?\n\n Object.keys(playlists).forEach(function (key) {\n var variant = playlists[key]; // check if we already processed this playlist.\n\n if (ids.indexOf(variant.id) !== -1) {\n return;\n }\n\n ids.push(variant.id);\n var codecs = codecsForPlaylist(_this10.master, variant);\n var unsupported = [];\n\n if (codecs.audio && !muxerSupportsCodec(codecs.audio) && !browserSupportsCodec(codecs.audio)) {\n unsupported.push(\"audio codec \" + codecs.audio);\n }\n\n if (codecs.video && !muxerSupportsCodec(codecs.video) && !browserSupportsCodec(codecs.video)) {\n unsupported.push(\"video codec \" + codecs.video);\n }\n\n if (codecs.text && codecs.text === 'stpp.ttml.im1t') {\n unsupported.push(\"text codec \" + codecs.text);\n }\n\n if (unsupported.length) {\n variant.excludeUntil = Infinity;\n\n _this10.logger_(\"excluding \" + variant.id + \" for unsupported: \" + unsupported.join(', '));\n }\n });\n }\n /**\n * Blacklist playlists that are known to be codec or\n * stream-incompatible with the SourceBuffer configuration. For\n * instance, Media Source Extensions would cause the video element to\n * stall waiting for video data if you switched from a variant with\n * video and audio to an audio-only one.\n *\n * @param {Object} media a media playlist compatible with the current\n * set of SourceBuffers. Variants in the current master playlist that\n * do not appear to have compatible codec or stream configurations\n * will be excluded from the default playlist selection algorithm\n * indefinitely.\n * @private\n */\n ;\n\n _proto.excludeIncompatibleVariants_ = function excludeIncompatibleVariants_(codecString) {\n var _this11 = this;\n\n var ids = [];\n var playlists = this.master().playlists;\n var codecs = unwrapCodecList(parseCodecs(codecString));\n var codecCount_ = codecCount(codecs);\n var videoDetails = codecs.video && parseCodecs(codecs.video)[0] || null;\n var audioDetails = codecs.audio && parseCodecs(codecs.audio)[0] || null;\n Object.keys(playlists).forEach(function (key) {\n var variant = playlists[key]; // check if we already processed this playlist.\n // or it if it is already excluded forever.\n\n if (ids.indexOf(variant.id) !== -1 || variant.excludeUntil === Infinity) {\n return;\n }\n\n ids.push(variant.id);\n var blacklistReasons = []; // get codecs from the playlist for this variant\n\n var variantCodecs = codecsForPlaylist(_this11.masterPlaylistLoader_.master, variant);\n var variantCodecCount = codecCount(variantCodecs); // if no codecs are listed, we cannot determine that this\n // variant is incompatible. Wait for mux.js to probe\n\n if (!variantCodecs.audio && !variantCodecs.video) {\n return;\n } // TODO: we can support this by removing the\n // old media source and creating a new one, but it will take some work.\n // The number of streams cannot change\n\n\n if (variantCodecCount !== codecCount_) {\n blacklistReasons.push(\"codec count \\\"\" + variantCodecCount + \"\\\" !== \\\"\" + codecCount_ + \"\\\"\");\n } // only exclude playlists by codec change, if codecs cannot switch\n // during playback.\n\n\n if (!_this11.sourceUpdater_.canChangeType()) {\n var variantVideoDetails = variantCodecs.video && parseCodecs(variantCodecs.video)[0] || null;\n var variantAudioDetails = variantCodecs.audio && parseCodecs(variantCodecs.audio)[0] || null; // the video codec cannot change\n\n if (variantVideoDetails && videoDetails && variantVideoDetails.type.toLowerCase() !== videoDetails.type.toLowerCase()) {\n blacklistReasons.push(\"video codec \\\"\" + variantVideoDetails.type + \"\\\" !== \\\"\" + videoDetails.type + \"\\\"\");\n } // the audio codec cannot change\n\n\n if (variantAudioDetails && audioDetails && variantAudioDetails.type.toLowerCase() !== audioDetails.type.toLowerCase()) {\n blacklistReasons.push(\"audio codec \\\"\" + variantAudioDetails.type + \"\\\" !== \\\"\" + audioDetails.type + \"\\\"\");\n }\n }\n\n if (blacklistReasons.length) {\n variant.excludeUntil = Infinity;\n\n _this11.logger_(\"blacklisting \" + variant.id + \": \" + blacklistReasons.join(' && '));\n }\n });\n };\n\n _proto.updateAdCues_ = function updateAdCues_(media) {\n var offset = 0;\n var seekable = this.seekable();\n\n if (seekable.length) {\n offset = seekable.start(0);\n }\n\n updateAdCues(media, this.cueTagsTrack_, offset);\n }\n /**\n * Calculates the desired forward buffer length based on current time\n *\n * @return {number} Desired forward buffer length in seconds\n */\n ;\n\n _proto.goalBufferLength = function goalBufferLength() {\n var currentTime = this.tech_.currentTime();\n var initial = Config.GOAL_BUFFER_LENGTH;\n var rate = Config.GOAL_BUFFER_LENGTH_RATE;\n var max = Math.max(initial, Config.MAX_GOAL_BUFFER_LENGTH);\n return Math.min(initial + currentTime * rate, max);\n }\n /**\n * Calculates the desired buffer low water line based on current time\n *\n * @return {number} Desired buffer low water line in seconds\n */\n ;\n\n _proto.bufferLowWaterLine = function bufferLowWaterLine() {\n var currentTime = this.tech_.currentTime();\n var initial = Config.BUFFER_LOW_WATER_LINE;\n var rate = Config.BUFFER_LOW_WATER_LINE_RATE;\n var max = Math.max(initial, Config.MAX_BUFFER_LOW_WATER_LINE);\n var newMax = Math.max(initial, Config.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE);\n return Math.min(initial + currentTime * rate, this.experimentalBufferBasedABR ? newMax : max);\n };\n\n _proto.bufferHighWaterLine = function bufferHighWaterLine() {\n return Config.BUFFER_HIGH_WATER_LINE;\n };\n\n return MasterPlaylistController;\n}(videojs.EventTarget);\n\n/**\n * Returns a function that acts as the Enable/disable playlist function.\n *\n * @param {PlaylistLoader} loader - The master playlist loader\n * @param {string} playlistID - id of the playlist\n * @param {Function} changePlaylistFn - A function to be called after a\n * playlist's enabled-state has been changed. Will NOT be called if a\n * playlist's enabled-state is unchanged\n * @param {boolean=} enable - Value to set the playlist enabled-state to\n * or if undefined returns the current enabled-state for the playlist\n * @return {Function} Function for setting/getting enabled\n */\n\nvar enableFunction = function enableFunction(loader, playlistID, changePlaylistFn) {\n return function (enable) {\n var playlist = loader.master.playlists[playlistID];\n var incompatible = isIncompatible(playlist);\n var currentlyEnabled = isEnabled(playlist);\n\n if (typeof enable === 'undefined') {\n return currentlyEnabled;\n }\n\n if (enable) {\n delete playlist.disabled;\n } else {\n playlist.disabled = true;\n }\n\n if (enable !== currentlyEnabled && !incompatible) {\n // Ensure the outside world knows about our changes\n changePlaylistFn();\n\n if (enable) {\n loader.trigger('renditionenabled');\n } else {\n loader.trigger('renditiondisabled');\n }\n }\n\n return enable;\n };\n};\n/**\n * The representation object encapsulates the publicly visible information\n * in a media playlist along with a setter/getter-type function (enabled)\n * for changing the enabled-state of a particular playlist entry\n *\n * @class Representation\n */\n\n\nvar Representation = function Representation(vhsHandler, playlist, id) {\n var mpc = vhsHandler.masterPlaylistController_,\n smoothQualityChange = vhsHandler.options_.smoothQualityChange; // Get a reference to a bound version of the quality change function\n\n var changeType = smoothQualityChange ? 'smooth' : 'fast';\n var qualityChangeFunction = mpc[changeType + \"QualityChange_\"].bind(mpc); // some playlist attributes are optional\n\n if (playlist.attributes) {\n var resolution = playlist.attributes.RESOLUTION;\n this.width = resolution && resolution.width;\n this.height = resolution && resolution.height;\n this.bandwidth = playlist.attributes.BANDWIDTH;\n }\n\n this.codecs = codecsForPlaylist(mpc.master(), playlist);\n this.playlist = playlist; // The id is simply the ordinality of the media playlist\n // within the master playlist\n\n this.id = id; // Partially-apply the enableFunction to create a playlist-\n // specific variant\n\n this.enabled = enableFunction(vhsHandler.playlists, playlist.id, qualityChangeFunction);\n};\n/**\n * A mixin function that adds the `representations` api to an instance\n * of the VhsHandler class\n *\n * @param {VhsHandler} vhsHandler - An instance of VhsHandler to add the\n * representation API into\n */\n\n\nvar renditionSelectionMixin = function renditionSelectionMixin(vhsHandler) {\n // Add a single API-specific function to the VhsHandler instance\n vhsHandler.representations = function () {\n var master = vhsHandler.masterPlaylistController_.master();\n var playlists = isAudioOnly(master) ? vhsHandler.masterPlaylistController_.getAudioTrackPlaylists_() : master.playlists;\n\n if (!playlists) {\n return [];\n }\n\n return playlists.filter(function (media) {\n return !isIncompatible(media);\n }).map(function (e, i) {\n return new Representation(vhsHandler, e, e.id);\n });\n };\n};\n\n/**\n * @file playback-watcher.js\n *\n * Playback starts, and now my watch begins. It shall not end until my death. I shall\n * take no wait, hold no uncleared timeouts, father no bad seeks. I shall wear no crowns\n * and win no glory. I shall live and die at my post. I am the corrector of the underflow.\n * I am the watcher of gaps. I am the shield that guards the realms of seekable. I pledge\n * my life and honor to the Playback Watch, for this Player and all the Players to come.\n */\n\nvar timerCancelEvents = ['seeking', 'seeked', 'pause', 'playing', 'error'];\n/**\n * @class PlaybackWatcher\n */\n\nvar PlaybackWatcher = /*#__PURE__*/function () {\n /**\n * Represents an PlaybackWatcher object.\n *\n * @class\n * @param {Object} options an object that includes the tech and settings\n */\n function PlaybackWatcher(options) {\n var _this = this;\n\n this.masterPlaylistController_ = options.masterPlaylistController;\n this.tech_ = options.tech;\n this.seekable = options.seekable;\n this.allowSeeksWithinUnsafeLiveWindow = options.allowSeeksWithinUnsafeLiveWindow;\n this.liveRangeSafeTimeDelta = options.liveRangeSafeTimeDelta;\n this.media = options.media;\n this.consecutiveUpdates = 0;\n this.lastRecordedTime = null;\n this.timer_ = null;\n this.checkCurrentTimeTimeout_ = null;\n this.logger_ = logger('PlaybackWatcher');\n this.logger_('initialize');\n\n var playHandler = function playHandler() {\n return _this.monitorCurrentTime_();\n };\n\n var canPlayHandler = function canPlayHandler() {\n return _this.monitorCurrentTime_();\n };\n\n var waitingHandler = function waitingHandler() {\n return _this.techWaiting_();\n };\n\n var cancelTimerHandler = function cancelTimerHandler() {\n return _this.cancelTimer_();\n };\n\n var mpc = this.masterPlaylistController_;\n var loaderTypes = ['main', 'subtitle', 'audio'];\n var loaderChecks = {};\n loaderTypes.forEach(function (type) {\n loaderChecks[type] = {\n reset: function reset() {\n return _this.resetSegmentDownloads_(type);\n },\n updateend: function updateend() {\n return _this.checkSegmentDownloads_(type);\n }\n };\n mpc[type + \"SegmentLoader_\"].on('appendsdone', loaderChecks[type].updateend); // If a rendition switch happens during a playback stall where the buffer\n // isn't changing we want to reset. We cannot assume that the new rendition\n // will also be stalled, until after new appends.\n\n mpc[type + \"SegmentLoader_\"].on('playlistupdate', loaderChecks[type].reset); // Playback stalls should not be detected right after seeking.\n // This prevents one segment playlists (single vtt or single segment content)\n // from being detected as stalling. As the buffer will not change in those cases, since\n // the buffer is the entire video duration.\n\n _this.tech_.on(['seeked', 'seeking'], loaderChecks[type].reset);\n });\n /**\n * We check if a seek was into a gap through the following steps:\n * 1. We get a seeking event and we do not get a seeked event. This means that\n * a seek was attempted but not completed.\n * 2. We run `fixesBadSeeks_` on segment loader appends. This means that we already\n * removed everything from our buffer and appended a segment, and should be ready\n * to check for gaps.\n */\n\n var setSeekingHandlers = function setSeekingHandlers(fn) {\n ['main', 'audio'].forEach(function (type) {\n mpc[type + \"SegmentLoader_\"][fn]('appended', _this.seekingAppendCheck_);\n });\n };\n\n this.seekingAppendCheck_ = function () {\n if (_this.fixesBadSeeks_()) {\n _this.consecutiveUpdates = 0;\n _this.lastRecordedTime = _this.tech_.currentTime();\n setSeekingHandlers('off');\n }\n };\n\n this.clearSeekingAppendCheck_ = function () {\n return setSeekingHandlers('off');\n };\n\n this.watchForBadSeeking_ = function () {\n _this.clearSeekingAppendCheck_();\n\n setSeekingHandlers('on');\n };\n\n this.tech_.on('seeked', this.clearSeekingAppendCheck_);\n this.tech_.on('seeking', this.watchForBadSeeking_);\n this.tech_.on('waiting', waitingHandler);\n this.tech_.on(timerCancelEvents, cancelTimerHandler);\n this.tech_.on('canplay', canPlayHandler);\n /*\n An edge case exists that results in gaps not being skipped when they exist at the beginning of a stream. This case\n is surfaced in one of two ways:\n 1) The `waiting` event is fired before the player has buffered content, making it impossible\n to find or skip the gap. The `waiting` event is followed by a `play` event. On first play\n we can check if playback is stalled due to a gap, and skip the gap if necessary.\n 2) A source with a gap at the beginning of the stream is loaded programatically while the player\n is in a playing state. To catch this case, it's important that our one-time play listener is setup\n even if the player is in a playing state\n */\n\n this.tech_.one('play', playHandler); // Define the dispose function to clean up our events\n\n this.dispose = function () {\n _this.clearSeekingAppendCheck_();\n\n _this.logger_('dispose');\n\n _this.tech_.off('waiting', waitingHandler);\n\n _this.tech_.off(timerCancelEvents, cancelTimerHandler);\n\n _this.tech_.off('canplay', canPlayHandler);\n\n _this.tech_.off('play', playHandler);\n\n _this.tech_.off('seeking', _this.watchForBadSeeking_);\n\n _this.tech_.off('seeked', _this.clearSeekingAppendCheck_);\n\n loaderTypes.forEach(function (type) {\n mpc[type + \"SegmentLoader_\"].off('appendsdone', loaderChecks[type].updateend);\n mpc[type + \"SegmentLoader_\"].off('playlistupdate', loaderChecks[type].reset);\n\n _this.tech_.off(['seeked', 'seeking'], loaderChecks[type].reset);\n });\n\n if (_this.checkCurrentTimeTimeout_) {\n window$1.clearTimeout(_this.checkCurrentTimeTimeout_);\n }\n\n _this.cancelTimer_();\n };\n }\n /**\n * Periodically check current time to see if playback stopped\n *\n * @private\n */\n\n\n var _proto = PlaybackWatcher.prototype;\n\n _proto.monitorCurrentTime_ = function monitorCurrentTime_() {\n this.checkCurrentTime_();\n\n if (this.checkCurrentTimeTimeout_) {\n window$1.clearTimeout(this.checkCurrentTimeTimeout_);\n } // 42 = 24 fps // 250 is what Webkit uses // FF uses 15\n\n\n this.checkCurrentTimeTimeout_ = window$1.setTimeout(this.monitorCurrentTime_.bind(this), 250);\n }\n /**\n * Reset stalled download stats for a specific type of loader\n *\n * @param {string} type\n * The segment loader type to check.\n *\n * @listens SegmentLoader#playlistupdate\n * @listens Tech#seeking\n * @listens Tech#seeked\n */\n ;\n\n _proto.resetSegmentDownloads_ = function resetSegmentDownloads_(type) {\n var loader = this.masterPlaylistController_[type + \"SegmentLoader_\"];\n\n if (this[type + \"StalledDownloads_\"] > 0) {\n this.logger_(\"resetting possible stalled download count for \" + type + \" loader\");\n }\n\n this[type + \"StalledDownloads_\"] = 0;\n this[type + \"Buffered_\"] = loader.buffered_();\n }\n /**\n * Checks on every segment `appendsdone` to see\n * if segment appends are making progress. If they are not\n * and we are still downloading bytes. We blacklist the playlist.\n *\n * @param {string} type\n * The segment loader type to check.\n *\n * @listens SegmentLoader#appendsdone\n */\n ;\n\n _proto.checkSegmentDownloads_ = function checkSegmentDownloads_(type) {\n var mpc = this.masterPlaylistController_;\n var loader = mpc[type + \"SegmentLoader_\"];\n var buffered = loader.buffered_();\n var isBufferedDifferent = isRangeDifferent(this[type + \"Buffered_\"], buffered);\n this[type + \"Buffered_\"] = buffered; // if another watcher is going to fix the issue or\n // the buffered value for this loader changed\n // appends are working\n\n if (isBufferedDifferent) {\n this.resetSegmentDownloads_(type);\n return;\n }\n\n this[type + \"StalledDownloads_\"]++;\n this.logger_(\"found #\" + this[type + \"StalledDownloads_\"] + \" \" + type + \" appends that did not increase buffer (possible stalled download)\", {\n playlistId: loader.playlist_ && loader.playlist_.id,\n buffered: timeRangesToArray(buffered)\n }); // after 10 possibly stalled appends with no reset, exclude\n\n if (this[type + \"StalledDownloads_\"] < 10) {\n return;\n }\n\n this.logger_(type + \" loader stalled download exclusion\");\n this.resetSegmentDownloads_(type);\n this.tech_.trigger({\n type: 'usage',\n name: \"vhs-\" + type + \"-download-exclusion\"\n });\n\n if (type === 'subtitle') {\n return;\n } // TODO: should we exclude audio tracks rather than main tracks\n // when type is audio?\n\n\n mpc.blacklistCurrentPlaylist({\n message: \"Excessive \" + type + \" segment downloading detected.\"\n }, Infinity);\n }\n /**\n * The purpose of this function is to emulate the \"waiting\" event on\n * browsers that do not emit it when they are waiting for more\n * data to continue playback\n *\n * @private\n */\n ;\n\n _proto.checkCurrentTime_ = function checkCurrentTime_() {\n if (this.tech_.paused() || this.tech_.seeking()) {\n return;\n }\n\n var currentTime = this.tech_.currentTime();\n var buffered = this.tech_.buffered();\n\n if (this.lastRecordedTime === currentTime && (!buffered.length || currentTime + SAFE_TIME_DELTA >= buffered.end(buffered.length - 1))) {\n // If current time is at the end of the final buffered region, then any playback\n // stall is most likely caused by buffering in a low bandwidth environment. The tech\n // should fire a `waiting` event in this scenario, but due to browser and tech\n // inconsistencies. Calling `techWaiting_` here allows us to simulate\n // responding to a native `waiting` event when the tech fails to emit one.\n return this.techWaiting_();\n }\n\n if (this.consecutiveUpdates >= 5 && currentTime === this.lastRecordedTime) {\n this.consecutiveUpdates++;\n this.waiting_();\n } else if (currentTime === this.lastRecordedTime) {\n this.consecutiveUpdates++;\n } else {\n this.consecutiveUpdates = 0;\n this.lastRecordedTime = currentTime;\n }\n }\n /**\n * Cancels any pending timers and resets the 'timeupdate' mechanism\n * designed to detect that we are stalled\n *\n * @private\n */\n ;\n\n _proto.cancelTimer_ = function cancelTimer_() {\n this.consecutiveUpdates = 0;\n\n if (this.timer_) {\n this.logger_('cancelTimer_');\n clearTimeout(this.timer_);\n }\n\n this.timer_ = null;\n }\n /**\n * Fixes situations where there's a bad seek\n *\n * @return {boolean} whether an action was taken to fix the seek\n * @private\n */\n ;\n\n _proto.fixesBadSeeks_ = function fixesBadSeeks_() {\n var seeking = this.tech_.seeking();\n\n if (!seeking) {\n return false;\n } // TODO: It's possible that these seekable checks should be moved out of this function\n // and into a function that runs on seekablechange. It's also possible that we only need\n // afterSeekableWindow as the buffered check at the bottom is good enough to handle before\n // seekable range.\n\n\n var seekable = this.seekable();\n var currentTime = this.tech_.currentTime();\n var isAfterSeekableRange = this.afterSeekableWindow_(seekable, currentTime, this.media(), this.allowSeeksWithinUnsafeLiveWindow);\n var seekTo;\n\n if (isAfterSeekableRange) {\n var seekableEnd = seekable.end(seekable.length - 1); // sync to live point (if VOD, our seekable was updated and we're simply adjusting)\n\n seekTo = seekableEnd;\n }\n\n if (this.beforeSeekableWindow_(seekable, currentTime)) {\n var seekableStart = seekable.start(0); // sync to the beginning of the live window\n // provide a buffer of .1 seconds to handle rounding/imprecise numbers\n\n seekTo = seekableStart + ( // if the playlist is too short and the seekable range is an exact time (can\n // happen in live with a 3 segment playlist), then don't use a time delta\n seekableStart === seekable.end(0) ? 0 : SAFE_TIME_DELTA);\n }\n\n if (typeof seekTo !== 'undefined') {\n this.logger_(\"Trying to seek outside of seekable at time \" + currentTime + \" with \" + (\"seekable range \" + printableRange(seekable) + \". Seeking to \") + (seekTo + \".\"));\n this.tech_.setCurrentTime(seekTo);\n return true;\n }\n\n var sourceUpdater = this.masterPlaylistController_.sourceUpdater_;\n var buffered = this.tech_.buffered();\n var audioBuffered = sourceUpdater.audioBuffer ? sourceUpdater.audioBuffered() : null;\n var videoBuffered = sourceUpdater.videoBuffer ? sourceUpdater.videoBuffered() : null;\n var media = this.media(); // verify that at least two segment durations or one part duration have been\n // appended before checking for a gap.\n\n var minAppendedDuration = media.partTargetDuration ? media.partTargetDuration : (media.targetDuration - TIME_FUDGE_FACTOR) * 2; // verify that at least two segment durations have been\n // appended before checking for a gap.\n\n var bufferedToCheck = [audioBuffered, videoBuffered];\n\n for (var i = 0; i < bufferedToCheck.length; i++) {\n // skip null buffered\n if (!bufferedToCheck[i]) {\n continue;\n }\n\n var timeAhead = timeAheadOf(bufferedToCheck[i], currentTime); // if we are less than two video/audio segment durations or one part\n // duration behind we haven't appended enough to call this a bad seek.\n\n if (timeAhead < minAppendedDuration) {\n return false;\n }\n }\n\n var nextRange = findNextRange(buffered, currentTime); // we have appended enough content, but we don't have anything buffered\n // to seek over the gap\n\n if (nextRange.length === 0) {\n return false;\n }\n\n seekTo = nextRange.start(0) + SAFE_TIME_DELTA;\n this.logger_(\"Buffered region starts (\" + nextRange.start(0) + \") \" + (\" just beyond seek point (\" + currentTime + \"). Seeking to \" + seekTo + \".\"));\n this.tech_.setCurrentTime(seekTo);\n return true;\n }\n /**\n * Handler for situations when we determine the player is waiting.\n *\n * @private\n */\n ;\n\n _proto.waiting_ = function waiting_() {\n if (this.techWaiting_()) {\n return;\n } // All tech waiting checks failed. Use last resort correction\n\n\n var currentTime = this.tech_.currentTime();\n var buffered = this.tech_.buffered();\n var currentRange = findRange(buffered, currentTime); // Sometimes the player can stall for unknown reasons within a contiguous buffered\n // region with no indication that anything is amiss (seen in Firefox). Seeking to\n // currentTime is usually enough to kickstart the player. This checks that the player\n // is currently within a buffered region before attempting a corrective seek.\n // Chrome does not appear to continue `timeupdate` events after a `waiting` event\n // until there is ~ 3 seconds of forward buffer available. PlaybackWatcher should also\n // make sure there is ~3 seconds of forward buffer before taking any corrective action\n // to avoid triggering an `unknownwaiting` event when the network is slow.\n\n if (currentRange.length && currentTime + 3 <= currentRange.end(0)) {\n this.cancelTimer_();\n this.tech_.setCurrentTime(currentTime);\n this.logger_(\"Stopped at \" + currentTime + \" while inside a buffered region \" + (\"[\" + currentRange.start(0) + \" -> \" + currentRange.end(0) + \"]. Attempting to resume \") + 'playback by seeking to the current time.'); // unknown waiting corrections may be useful for monitoring QoS\n\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-unknown-waiting'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-unknown-waiting'\n });\n return;\n }\n }\n /**\n * Handler for situations when the tech fires a `waiting` event\n *\n * @return {boolean}\n * True if an action (or none) was needed to correct the waiting. False if no\n * checks passed\n * @private\n */\n ;\n\n _proto.techWaiting_ = function techWaiting_() {\n var seekable = this.seekable();\n var currentTime = this.tech_.currentTime();\n\n if (this.tech_.seeking() || this.timer_ !== null) {\n // Tech is seeking or already waiting on another action, no action needed\n return true;\n }\n\n if (this.beforeSeekableWindow_(seekable, currentTime)) {\n var livePoint = seekable.end(seekable.length - 1);\n this.logger_(\"Fell out of live window at time \" + currentTime + \". Seeking to \" + (\"live point (seekable end) \" + livePoint));\n this.cancelTimer_();\n this.tech_.setCurrentTime(livePoint); // live window resyncs may be useful for monitoring QoS\n\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-live-resync'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-live-resync'\n });\n return true;\n }\n\n var sourceUpdater = this.tech_.vhs.masterPlaylistController_.sourceUpdater_;\n var buffered = this.tech_.buffered();\n var videoUnderflow = this.videoUnderflow_({\n audioBuffered: sourceUpdater.audioBuffered(),\n videoBuffered: sourceUpdater.videoBuffered(),\n currentTime: currentTime\n });\n\n if (videoUnderflow) {\n // Even though the video underflowed and was stuck in a gap, the audio overplayed\n // the gap, leading currentTime into a buffered range. Seeking to currentTime\n // allows the video to catch up to the audio position without losing any audio\n // (only suffering ~3 seconds of frozen video and a pause in audio playback).\n this.cancelTimer_();\n this.tech_.setCurrentTime(currentTime); // video underflow may be useful for monitoring QoS\n\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-video-underflow'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-video-underflow'\n });\n return true;\n }\n\n var nextRange = findNextRange(buffered, currentTime); // check for gap\n\n if (nextRange.length > 0) {\n var difference = nextRange.start(0) - currentTime;\n this.logger_(\"Stopped at \" + currentTime + \", setting timer for \" + difference + \", seeking \" + (\"to \" + nextRange.start(0)));\n this.cancelTimer_();\n this.timer_ = setTimeout(this.skipTheGap_.bind(this), difference * 1000, currentTime);\n return true;\n } // All checks failed. Returning false to indicate failure to correct waiting\n\n\n return false;\n };\n\n _proto.afterSeekableWindow_ = function afterSeekableWindow_(seekable, currentTime, playlist, allowSeeksWithinUnsafeLiveWindow) {\n if (allowSeeksWithinUnsafeLiveWindow === void 0) {\n allowSeeksWithinUnsafeLiveWindow = false;\n }\n\n if (!seekable.length) {\n // we can't make a solid case if there's no seekable, default to false\n return false;\n }\n\n var allowedEnd = seekable.end(seekable.length - 1) + SAFE_TIME_DELTA;\n var isLive = !playlist.endList;\n\n if (isLive && allowSeeksWithinUnsafeLiveWindow) {\n allowedEnd = seekable.end(seekable.length - 1) + playlist.targetDuration * 3;\n }\n\n if (currentTime > allowedEnd) {\n return true;\n }\n\n return false;\n };\n\n _proto.beforeSeekableWindow_ = function beforeSeekableWindow_(seekable, currentTime) {\n if (seekable.length && // can't fall before 0 and 0 seekable start identifies VOD stream\n seekable.start(0) > 0 && currentTime < seekable.start(0) - this.liveRangeSafeTimeDelta) {\n return true;\n }\n\n return false;\n };\n\n _proto.videoUnderflow_ = function videoUnderflow_(_ref) {\n var videoBuffered = _ref.videoBuffered,\n audioBuffered = _ref.audioBuffered,\n currentTime = _ref.currentTime;\n\n // audio only content will not have video underflow :)\n if (!videoBuffered) {\n return;\n }\n\n var gap; // find a gap in demuxed content.\n\n if (videoBuffered.length && audioBuffered.length) {\n // in Chrome audio will continue to play for ~3s when we run out of video\n // so we have to check that the video buffer did have some buffer in the\n // past.\n var lastVideoRange = findRange(videoBuffered, currentTime - 3);\n var videoRange = findRange(videoBuffered, currentTime);\n var audioRange = findRange(audioBuffered, currentTime);\n\n if (audioRange.length && !videoRange.length && lastVideoRange.length) {\n gap = {\n start: lastVideoRange.end(0),\n end: audioRange.end(0)\n };\n } // find a gap in muxed content.\n\n } else {\n var nextRange = findNextRange(videoBuffered, currentTime); // Even if there is no available next range, there is still a possibility we are\n // stuck in a gap due to video underflow.\n\n if (!nextRange.length) {\n gap = this.gapFromVideoUnderflow_(videoBuffered, currentTime);\n }\n }\n\n if (gap) {\n this.logger_(\"Encountered a gap in video from \" + gap.start + \" to \" + gap.end + \". \" + (\"Seeking to current time \" + currentTime));\n return true;\n }\n\n return false;\n }\n /**\n * Timer callback. If playback still has not proceeded, then we seek\n * to the start of the next buffered region.\n *\n * @private\n */\n ;\n\n _proto.skipTheGap_ = function skipTheGap_(scheduledCurrentTime) {\n var buffered = this.tech_.buffered();\n var currentTime = this.tech_.currentTime();\n var nextRange = findNextRange(buffered, currentTime);\n this.cancelTimer_();\n\n if (nextRange.length === 0 || currentTime !== scheduledCurrentTime) {\n return;\n }\n\n this.logger_('skipTheGap_:', 'currentTime:', currentTime, 'scheduled currentTime:', scheduledCurrentTime, 'nextRange start:', nextRange.start(0)); // only seek if we still have not played\n\n this.tech_.setCurrentTime(nextRange.start(0) + TIME_FUDGE_FACTOR);\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-gap-skip'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-gap-skip'\n });\n };\n\n _proto.gapFromVideoUnderflow_ = function gapFromVideoUnderflow_(buffered, currentTime) {\n // At least in Chrome, if there is a gap in the video buffer, the audio will continue\n // playing for ~3 seconds after the video gap starts. This is done to account for\n // video buffer underflow/underrun (note that this is not done when there is audio\n // buffer underflow/underrun -- in that case the video will stop as soon as it\n // encounters the gap, as audio stalls are more noticeable/jarring to a user than\n // video stalls). The player's time will reflect the playthrough of audio, so the\n // time will appear as if we are in a buffered region, even if we are stuck in a\n // \"gap.\"\n //\n // Example:\n // video buffer: 0 => 10.1, 10.2 => 20\n // audio buffer: 0 => 20\n // overall buffer: 0 => 10.1, 10.2 => 20\n // current time: 13\n //\n // Chrome's video froze at 10 seconds, where the video buffer encountered the gap,\n // however, the audio continued playing until it reached ~3 seconds past the gap\n // (13 seconds), at which point it stops as well. Since current time is past the\n // gap, findNextRange will return no ranges.\n //\n // To check for this issue, we see if there is a gap that starts somewhere within\n // a 3 second range (3 seconds +/- 1 second) back from our current time.\n var gaps = findGaps(buffered);\n\n for (var i = 0; i < gaps.length; i++) {\n var start = gaps.start(i);\n var end = gaps.end(i); // gap is starts no more than 4 seconds back\n\n if (currentTime - start < 4 && currentTime - start > 2) {\n return {\n start: start,\n end: end\n };\n }\n }\n\n return null;\n };\n\n return PlaybackWatcher;\n}();\n\nvar defaultOptions = {\n errorInterval: 30,\n getSource: function getSource(next) {\n var tech = this.tech({\n IWillNotUseThisInPlugins: true\n });\n var sourceObj = tech.currentSource_ || this.currentSource();\n return next(sourceObj);\n }\n};\n/**\n * Main entry point for the plugin\n *\n * @param {Player} player a reference to a videojs Player instance\n * @param {Object} [options] an object with plugin options\n * @private\n */\n\nvar initPlugin = function initPlugin(player, options) {\n var lastCalled = 0;\n var seekTo = 0;\n var localOptions = videojs.mergeOptions(defaultOptions, options);\n player.ready(function () {\n player.trigger({\n type: 'usage',\n name: 'vhs-error-reload-initialized'\n });\n player.trigger({\n type: 'usage',\n name: 'hls-error-reload-initialized'\n });\n });\n /**\n * Player modifications to perform that must wait until `loadedmetadata`\n * has been triggered\n *\n * @private\n */\n\n var loadedMetadataHandler = function loadedMetadataHandler() {\n if (seekTo) {\n player.currentTime(seekTo);\n }\n };\n /**\n * Set the source on the player element, play, and seek if necessary\n *\n * @param {Object} sourceObj An object specifying the source url and mime-type to play\n * @private\n */\n\n\n var setSource = function setSource(sourceObj) {\n if (sourceObj === null || sourceObj === undefined) {\n return;\n }\n\n seekTo = player.duration() !== Infinity && player.currentTime() || 0;\n player.one('loadedmetadata', loadedMetadataHandler);\n player.src(sourceObj);\n player.trigger({\n type: 'usage',\n name: 'vhs-error-reload'\n });\n player.trigger({\n type: 'usage',\n name: 'hls-error-reload'\n });\n player.play();\n };\n /**\n * Attempt to get a source from either the built-in getSource function\n * or a custom function provided via the options\n *\n * @private\n */\n\n\n var errorHandler = function errorHandler() {\n // Do not attempt to reload the source if a source-reload occurred before\n // 'errorInterval' time has elapsed since the last source-reload\n if (Date.now() - lastCalled < localOptions.errorInterval * 1000) {\n player.trigger({\n type: 'usage',\n name: 'vhs-error-reload-canceled'\n });\n player.trigger({\n type: 'usage',\n name: 'hls-error-reload-canceled'\n });\n return;\n }\n\n if (!localOptions.getSource || typeof localOptions.getSource !== 'function') {\n videojs.log.error('ERROR: reloadSourceOnError - The option getSource must be a function!');\n return;\n }\n\n lastCalled = Date.now();\n return localOptions.getSource.call(player, setSource);\n };\n /**\n * Unbind any event handlers that were bound by the plugin\n *\n * @private\n */\n\n\n var cleanupEvents = function cleanupEvents() {\n player.off('loadedmetadata', loadedMetadataHandler);\n player.off('error', errorHandler);\n player.off('dispose', cleanupEvents);\n };\n /**\n * Cleanup before re-initializing the plugin\n *\n * @param {Object} [newOptions] an object with plugin options\n * @private\n */\n\n\n var reinitPlugin = function reinitPlugin(newOptions) {\n cleanupEvents();\n initPlugin(player, newOptions);\n };\n\n player.on('error', errorHandler);\n player.on('dispose', cleanupEvents); // Overwrite the plugin function so that we can correctly cleanup before\n // initializing the plugin\n\n player.reloadSourceOnError = reinitPlugin;\n};\n/**\n * Reload the source when an error is detected as long as there\n * wasn't an error previously within the last 30 seconds\n *\n * @param {Object} [options] an object with plugin options\n */\n\n\nvar reloadSourceOnError = function reloadSourceOnError(options) {\n initPlugin(this, options);\n};\n\nvar version$4 = \"2.13.1\";\n\nvar version$3 = \"6.0.1\";\n\nvar version$2 = \"0.21.0\";\n\nvar version$1 = \"4.7.0\";\n\nvar version = \"3.1.2\";\n\nvar Vhs = {\n PlaylistLoader: PlaylistLoader,\n Playlist: Playlist,\n utils: utils,\n STANDARD_PLAYLIST_SELECTOR: lastBandwidthSelector,\n INITIAL_PLAYLIST_SELECTOR: lowestBitrateCompatibleVariantSelector,\n lastBandwidthSelector: lastBandwidthSelector,\n movingAverageBandwidthSelector: movingAverageBandwidthSelector,\n comparePlaylistBandwidth: comparePlaylistBandwidth,\n comparePlaylistResolution: comparePlaylistResolution,\n xhr: xhrFactory()\n}; // Define getter/setters for config properties\n\nObject.keys(Config).forEach(function (prop) {\n Object.defineProperty(Vhs, prop, {\n get: function get() {\n videojs.log.warn(\"using Vhs.\" + prop + \" is UNSAFE be sure you know what you are doing\");\n return Config[prop];\n },\n set: function set(value) {\n videojs.log.warn(\"using Vhs.\" + prop + \" is UNSAFE be sure you know what you are doing\");\n\n if (typeof value !== 'number' || value < 0) {\n videojs.log.warn(\"value of Vhs.\" + prop + \" must be greater than or equal to 0\");\n return;\n }\n\n Config[prop] = value;\n }\n });\n});\nvar LOCAL_STORAGE_KEY = 'videojs-vhs';\n/**\n * Updates the selectedIndex of the QualityLevelList when a mediachange happens in vhs.\n *\n * @param {QualityLevelList} qualityLevels The QualityLevelList to update.\n * @param {PlaylistLoader} playlistLoader PlaylistLoader containing the new media info.\n * @function handleVhsMediaChange\n */\n\nvar handleVhsMediaChange = function handleVhsMediaChange(qualityLevels, playlistLoader) {\n var newPlaylist = playlistLoader.media();\n var selectedIndex = -1;\n\n for (var i = 0; i < qualityLevels.length; i++) {\n if (qualityLevels[i].id === newPlaylist.id) {\n selectedIndex = i;\n break;\n }\n }\n\n qualityLevels.selectedIndex_ = selectedIndex;\n qualityLevels.trigger({\n selectedIndex: selectedIndex,\n type: 'change'\n });\n};\n/**\n * Adds quality levels to list once playlist metadata is available\n *\n * @param {QualityLevelList} qualityLevels The QualityLevelList to attach events to.\n * @param {Object} vhs Vhs object to listen to for media events.\n * @function handleVhsLoadedMetadata\n */\n\n\nvar handleVhsLoadedMetadata = function handleVhsLoadedMetadata(qualityLevels, vhs) {\n vhs.representations().forEach(function (rep) {\n qualityLevels.addQualityLevel(rep);\n });\n handleVhsMediaChange(qualityLevels, vhs.playlists);\n}; // HLS is a source handler, not a tech. Make sure attempts to use it\n// as one do not cause exceptions.\n\n\nVhs.canPlaySource = function () {\n return videojs.log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\\'s techOrder.');\n};\n\nvar emeKeySystems = function emeKeySystems(keySystemOptions, mainPlaylist, audioPlaylist) {\n if (!keySystemOptions) {\n return keySystemOptions;\n }\n\n var codecs = {};\n\n if (mainPlaylist && mainPlaylist.attributes && mainPlaylist.attributes.CODECS) {\n codecs = unwrapCodecList(parseCodecs(mainPlaylist.attributes.CODECS));\n }\n\n if (audioPlaylist && audioPlaylist.attributes && audioPlaylist.attributes.CODECS) {\n codecs.audio = audioPlaylist.attributes.CODECS;\n }\n\n var videoContentType = getMimeForCodec(codecs.video);\n var audioContentType = getMimeForCodec(codecs.audio); // upsert the content types based on the selected playlist\n\n var keySystemContentTypes = {};\n\n for (var keySystem in keySystemOptions) {\n keySystemContentTypes[keySystem] = {};\n\n if (audioContentType) {\n keySystemContentTypes[keySystem].audioContentType = audioContentType;\n }\n\n if (videoContentType) {\n keySystemContentTypes[keySystem].videoContentType = videoContentType;\n } // Default to using the video playlist's PSSH even though they may be different, as\n // videojs-contrib-eme will only accept one in the options.\n //\n // This shouldn't be an issue for most cases as early intialization will handle all\n // unique PSSH values, and if they aren't, then encrypted events should have the\n // specific information needed for the unique license.\n\n\n if (mainPlaylist.contentProtection && mainPlaylist.contentProtection[keySystem] && mainPlaylist.contentProtection[keySystem].pssh) {\n keySystemContentTypes[keySystem].pssh = mainPlaylist.contentProtection[keySystem].pssh;\n } // videojs-contrib-eme accepts the option of specifying: 'com.some.cdm': 'url'\n // so we need to prevent overwriting the URL entirely\n\n\n if (typeof keySystemOptions[keySystem] === 'string') {\n keySystemContentTypes[keySystem].url = keySystemOptions[keySystem];\n }\n }\n\n return videojs.mergeOptions(keySystemOptions, keySystemContentTypes);\n};\n/**\n * @typedef {Object} KeySystems\n *\n * keySystems configuration for https://github.com/videojs/videojs-contrib-eme\n * Note: not all options are listed here.\n *\n * @property {Uint8Array} [pssh]\n * Protection System Specific Header\n */\n\n/**\n * Goes through all the playlists and collects an array of KeySystems options objects\n * containing each playlist's keySystems and their pssh values, if available.\n *\n * @param {Object[]} playlists\n * The playlists to look through\n * @param {string[]} keySystems\n * The keySystems to collect pssh values for\n *\n * @return {KeySystems[]}\n * An array of KeySystems objects containing available key systems and their\n * pssh values\n */\n\n\nvar getAllPsshKeySystemsOptions = function getAllPsshKeySystemsOptions(playlists, keySystems) {\n return playlists.reduce(function (keySystemsArr, playlist) {\n if (!playlist.contentProtection) {\n return keySystemsArr;\n }\n\n var keySystemsOptions = keySystems.reduce(function (keySystemsObj, keySystem) {\n var keySystemOptions = playlist.contentProtection[keySystem];\n\n if (keySystemOptions && keySystemOptions.pssh) {\n keySystemsObj[keySystem] = {\n pssh: keySystemOptions.pssh\n };\n }\n\n return keySystemsObj;\n }, {});\n\n if (Object.keys(keySystemsOptions).length) {\n keySystemsArr.push(keySystemsOptions);\n }\n\n return keySystemsArr;\n }, []);\n};\n/**\n * Returns a promise that waits for the\n * [eme plugin](https://github.com/videojs/videojs-contrib-eme) to create a key session.\n *\n * Works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 in non-IE11\n * browsers.\n *\n * As per the above ticket, this is particularly important for Chrome, where, if\n * unencrypted content is appended before encrypted content and the key session has not\n * been created, a MEDIA_ERR_DECODE will be thrown once the encrypted content is reached\n * during playback.\n *\n * @param {Object} player\n * The player instance\n * @param {Object[]} sourceKeySystems\n * The key systems options from the player source\n * @param {Object} [audioMedia]\n * The active audio media playlist (optional)\n * @param {Object[]} mainPlaylists\n * The playlists found on the master playlist object\n *\n * @return {Object}\n * Promise that resolves when the key session has been created\n */\n\n\nvar waitForKeySessionCreation = function waitForKeySessionCreation(_ref) {\n var player = _ref.player,\n sourceKeySystems = _ref.sourceKeySystems,\n audioMedia = _ref.audioMedia,\n mainPlaylists = _ref.mainPlaylists;\n\n if (!player.eme.initializeMediaKeys) {\n return Promise.resolve();\n } // TODO should all audio PSSH values be initialized for DRM?\n //\n // All unique video rendition pssh values are initialized for DRM, but here only\n // the initial audio playlist license is initialized. In theory, an encrypted\n // event should be fired if the user switches to an alternative audio playlist\n // where a license is required, but this case hasn't yet been tested. In addition, there\n // may be many alternate audio playlists unlikely to be used (e.g., multiple different\n // languages).\n\n\n var playlists = audioMedia ? mainPlaylists.concat([audioMedia]) : mainPlaylists;\n var keySystemsOptionsArr = getAllPsshKeySystemsOptions(playlists, Object.keys(sourceKeySystems));\n var initializationFinishedPromises = [];\n var keySessionCreatedPromises = []; // Since PSSH values are interpreted as initData, EME will dedupe any duplicates. The\n // only place where it should not be deduped is for ms-prefixed APIs, but the early\n // return for IE11 above, and the existence of modern EME APIs in addition to\n // ms-prefixed APIs on Edge should prevent this from being a concern.\n // initializeMediaKeys also won't use the webkit-prefixed APIs.\n\n keySystemsOptionsArr.forEach(function (keySystemsOptions) {\n keySessionCreatedPromises.push(new Promise(function (resolve, reject) {\n player.tech_.one('keysessioncreated', resolve);\n }));\n initializationFinishedPromises.push(new Promise(function (resolve, reject) {\n player.eme.initializeMediaKeys({\n keySystems: keySystemsOptions\n }, function (err) {\n if (err) {\n reject(err);\n return;\n }\n\n resolve();\n });\n }));\n }); // The reasons Promise.race is chosen over Promise.any:\n //\n // * Promise.any is only available in Safari 14+.\n // * None of these promises are expected to reject. If they do reject, it might be\n // better here for the race to surface the rejection, rather than mask it by using\n // Promise.any.\n\n return Promise.race([// If a session was previously created, these will all finish resolving without\n // creating a new session, otherwise it will take until the end of all license\n // requests, which is why the key session check is used (to make setup much faster).\n Promise.all(initializationFinishedPromises), // Once a single session is created, the browser knows DRM will be used.\n Promise.race(keySessionCreatedPromises)]);\n};\n/**\n * If the [eme](https://github.com/videojs/videojs-contrib-eme) plugin is available, and\n * there are keySystems on the source, sets up source options to prepare the source for\n * eme.\n *\n * @param {Object} player\n * The player instance\n * @param {Object[]} sourceKeySystems\n * The key systems options from the player source\n * @param {Object} media\n * The active media playlist\n * @param {Object} [audioMedia]\n * The active audio media playlist (optional)\n *\n * @return {boolean}\n * Whether or not options were configured and EME is available\n */\n\nvar setupEmeOptions = function setupEmeOptions(_ref2) {\n var player = _ref2.player,\n sourceKeySystems = _ref2.sourceKeySystems,\n media = _ref2.media,\n audioMedia = _ref2.audioMedia;\n var sourceOptions = emeKeySystems(sourceKeySystems, media, audioMedia);\n\n if (!sourceOptions) {\n return false;\n }\n\n player.currentSource().keySystems = sourceOptions; // eme handles the rest of the setup, so if it is missing\n // do nothing.\n\n if (sourceOptions && !player.eme) {\n videojs.log.warn('DRM encrypted source cannot be decrypted without a DRM plugin');\n return false;\n }\n\n return true;\n};\n\nvar getVhsLocalStorage = function getVhsLocalStorage() {\n if (!window$1.localStorage) {\n return null;\n }\n\n var storedObject = window$1.localStorage.getItem(LOCAL_STORAGE_KEY);\n\n if (!storedObject) {\n return null;\n }\n\n try {\n return JSON.parse(storedObject);\n } catch (e) {\n // someone may have tampered with the value\n return null;\n }\n};\n\nvar updateVhsLocalStorage = function updateVhsLocalStorage(options) {\n if (!window$1.localStorage) {\n return false;\n }\n\n var objectToStore = getVhsLocalStorage();\n objectToStore = objectToStore ? videojs.mergeOptions(objectToStore, options) : options;\n\n try {\n window$1.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(objectToStore));\n } catch (e) {\n // Throws if storage is full (e.g., always on iOS 5+ Safari private mode, where\n // storage is set to 0).\n // https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem#Exceptions\n // No need to perform any operation.\n return false;\n }\n\n return objectToStore;\n};\n/**\n * Parses VHS-supported media types from data URIs. See\n * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n * for information on data URIs.\n *\n * @param {string} dataUri\n * The data URI\n *\n * @return {string|Object}\n * The parsed object/string, or the original string if no supported media type\n * was found\n */\n\n\nvar expandDataUri = function expandDataUri(dataUri) {\n if (dataUri.toLowerCase().indexOf('data:application/vnd.videojs.vhs+json,') === 0) {\n return JSON.parse(dataUri.substring(dataUri.indexOf(',') + 1));\n } // no known case for this data URI, return the string as-is\n\n\n return dataUri;\n};\n/**\n * Whether the browser has built-in HLS support.\n */\n\n\nVhs.supportsNativeHls = function () {\n if (!document || !document.createElement) {\n return false;\n }\n\n var video = document.createElement('video'); // native HLS is definitely not supported if HTML5 video isn't\n\n if (!videojs.getTech('Html5').isSupported()) {\n return false;\n } // HLS manifests can go by many mime-types\n\n\n var canPlay = [// Apple santioned\n 'application/vnd.apple.mpegurl', // Apple sanctioned for backwards compatibility\n 'audio/mpegurl', // Very common\n 'audio/x-mpegurl', // Very common\n 'application/x-mpegurl', // Included for completeness\n 'video/x-mpegurl', 'video/mpegurl', 'application/mpegurl'];\n return canPlay.some(function (canItPlay) {\n return /maybe|probably/i.test(video.canPlayType(canItPlay));\n });\n}();\n\nVhs.supportsNativeDash = function () {\n if (!document || !document.createElement || !videojs.getTech('Html5').isSupported()) {\n return false;\n }\n\n return /maybe|probably/i.test(document.createElement('video').canPlayType('application/dash+xml'));\n}();\n\nVhs.supportsTypeNatively = function (type) {\n if (type === 'hls') {\n return Vhs.supportsNativeHls;\n }\n\n if (type === 'dash') {\n return Vhs.supportsNativeDash;\n }\n\n return false;\n};\n/**\n * HLS is a source handler, not a tech. Make sure attempts to use it\n * as one do not cause exceptions.\n */\n\n\nVhs.isSupported = function () {\n return videojs.log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\\'s techOrder.');\n};\n\nvar Component = videojs.getComponent('Component');\n/**\n * The Vhs Handler object, where we orchestrate all of the parts\n * of HLS to interact with video.js\n *\n * @class VhsHandler\n * @extends videojs.Component\n * @param {Object} source the soruce object\n * @param {Tech} tech the parent tech object\n * @param {Object} options optional and required options\n */\n\nvar VhsHandler = /*#__PURE__*/function (_Component) {\n _inheritsLoose(VhsHandler, _Component);\n\n function VhsHandler(source, tech, options) {\n var _this;\n\n _this = _Component.call(this, tech, videojs.mergeOptions(options.hls, options.vhs)) || this;\n\n if (options.hls && Object.keys(options.hls).length) {\n videojs.log.warn('Using hls options is deprecated. Use vhs instead.');\n } // if a tech level `initialBandwidth` option was passed\n // use that over the VHS level `bandwidth` option\n\n\n if (typeof options.initialBandwidth === 'number') {\n _this.options_.bandwidth = options.initialBandwidth;\n }\n\n _this.logger_ = logger('VhsHandler'); // tech.player() is deprecated but setup a reference to HLS for\n // backwards-compatibility\n\n if (tech.options_ && tech.options_.playerId) {\n var _player = videojs(tech.options_.playerId);\n\n if (!_player.hasOwnProperty('hls')) {\n Object.defineProperty(_player, 'hls', {\n get: function get() {\n videojs.log.warn('player.hls is deprecated. Use player.tech().vhs instead.');\n tech.trigger({\n type: 'usage',\n name: 'hls-player-access'\n });\n return _assertThisInitialized(_this);\n },\n configurable: true\n });\n }\n\n if (!_player.hasOwnProperty('vhs')) {\n Object.defineProperty(_player, 'vhs', {\n get: function get() {\n videojs.log.warn('player.vhs is deprecated. Use player.tech().vhs instead.');\n tech.trigger({\n type: 'usage',\n name: 'vhs-player-access'\n });\n return _assertThisInitialized(_this);\n },\n configurable: true\n });\n }\n\n if (!_player.hasOwnProperty('dash')) {\n Object.defineProperty(_player, 'dash', {\n get: function get() {\n videojs.log.warn('player.dash is deprecated. Use player.tech().vhs instead.');\n return _assertThisInitialized(_this);\n },\n configurable: true\n });\n }\n\n _this.player_ = _player;\n }\n\n _this.tech_ = tech;\n _this.source_ = source;\n _this.stats = {};\n _this.ignoreNextSeekingEvent_ = false;\n\n _this.setOptions_();\n\n if (_this.options_.overrideNative && tech.overrideNativeAudioTracks && tech.overrideNativeVideoTracks) {\n tech.overrideNativeAudioTracks(true);\n tech.overrideNativeVideoTracks(true);\n } else if (_this.options_.overrideNative && (tech.featuresNativeVideoTracks || tech.featuresNativeAudioTracks)) {\n // overriding native HLS only works if audio tracks have been emulated\n // error early if we're misconfigured\n throw new Error('Overriding native HLS requires emulated tracks. ' + 'See https://git.io/vMpjB');\n } // listen for fullscreenchange events for this player so that we\n // can adjust our quality selection quickly\n\n\n _this.on(document, ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'], function (event) {\n var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;\n\n if (fullscreenElement && fullscreenElement.contains(_this.tech_.el())) {\n _this.masterPlaylistController_.fastQualityChange_();\n } else {\n // When leaving fullscreen, since the in page pixel dimensions should be smaller\n // than full screen, see if there should be a rendition switch down to preserve\n // bandwidth.\n _this.masterPlaylistController_.checkABR_();\n }\n });\n\n _this.on(_this.tech_, 'seeking', function () {\n if (this.ignoreNextSeekingEvent_) {\n this.ignoreNextSeekingEvent_ = false;\n return;\n }\n\n this.setCurrentTime(this.tech_.currentTime());\n });\n\n _this.on(_this.tech_, 'error', function () {\n // verify that the error was real and we are loaded\n // enough to have mpc loaded.\n if (this.tech_.error() && this.masterPlaylistController_) {\n this.masterPlaylistController_.pauseLoading();\n }\n });\n\n _this.on(_this.tech_, 'play', _this.play);\n\n return _this;\n }\n\n var _proto = VhsHandler.prototype;\n\n _proto.setOptions_ = function setOptions_() {\n var _this2 = this;\n\n // defaults\n this.options_.withCredentials = this.options_.withCredentials || false;\n this.options_.handleManifestRedirects = this.options_.handleManifestRedirects === false ? false : true;\n this.options_.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions === false ? false : true;\n this.options_.useDevicePixelRatio = this.options_.useDevicePixelRatio || false;\n this.options_.smoothQualityChange = this.options_.smoothQualityChange || false;\n this.options_.useBandwidthFromLocalStorage = typeof this.source_.useBandwidthFromLocalStorage !== 'undefined' ? this.source_.useBandwidthFromLocalStorage : this.options_.useBandwidthFromLocalStorage || false;\n this.options_.useNetworkInformationApi = this.options_.useNetworkInformationApi || false;\n this.options_.customTagParsers = this.options_.customTagParsers || [];\n this.options_.customTagMappers = this.options_.customTagMappers || [];\n this.options_.cacheEncryptionKeys = this.options_.cacheEncryptionKeys || false;\n\n if (typeof this.options_.blacklistDuration !== 'number') {\n this.options_.blacklistDuration = 5 * 60;\n }\n\n if (typeof this.options_.bandwidth !== 'number') {\n if (this.options_.useBandwidthFromLocalStorage) {\n var storedObject = getVhsLocalStorage();\n\n if (storedObject && storedObject.bandwidth) {\n this.options_.bandwidth = storedObject.bandwidth;\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-bandwidth-from-local-storage'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-bandwidth-from-local-storage'\n });\n }\n\n if (storedObject && storedObject.throughput) {\n this.options_.throughput = storedObject.throughput;\n this.tech_.trigger({\n type: 'usage',\n name: 'vhs-throughput-from-local-storage'\n });\n this.tech_.trigger({\n type: 'usage',\n name: 'hls-throughput-from-local-storage'\n });\n }\n }\n } // if bandwidth was not set by options or pulled from local storage, start playlist\n // selection at a reasonable bandwidth\n\n\n if (typeof this.options_.bandwidth !== 'number') {\n this.options_.bandwidth = Config.INITIAL_BANDWIDTH;\n } // If the bandwidth number is unchanged from the initial setting\n // then this takes precedence over the enableLowInitialPlaylist option\n\n\n this.options_.enableLowInitialPlaylist = this.options_.enableLowInitialPlaylist && this.options_.bandwidth === Config.INITIAL_BANDWIDTH; // grab options passed to player.src\n\n ['withCredentials', 'useDevicePixelRatio', 'limitRenditionByPlayerDimensions', 'bandwidth', 'smoothQualityChange', 'customTagParsers', 'customTagMappers', 'handleManifestRedirects', 'cacheEncryptionKeys', 'playlistSelector', 'initialPlaylistSelector', 'experimentalBufferBasedABR', 'liveRangeSafeTimeDelta', 'experimentalLLHLS', 'useNetworkInformationApi', 'experimentalExactManifestTimings', 'experimentalLeastPixelDiffSelector'].forEach(function (option) {\n if (typeof _this2.source_[option] !== 'undefined') {\n _this2.options_[option] = _this2.source_[option];\n }\n });\n this.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions;\n this.useDevicePixelRatio = this.options_.useDevicePixelRatio;\n }\n /**\n * called when player.src gets called, handle a new source\n *\n * @param {Object} src the source object to handle\n */\n ;\n\n _proto.src = function src(_src, type) {\n var _this3 = this;\n\n // do nothing if the src is falsey\n if (!_src) {\n return;\n }\n\n this.setOptions_(); // add master playlist controller options\n\n this.options_.src = expandDataUri(this.source_.src);\n this.options_.tech = this.tech_;\n this.options_.externVhs = Vhs;\n this.options_.sourceType = simpleTypeFromSourceType(type); // Whenever we seek internally, we should update the tech\n\n this.options_.seekTo = function (time) {\n _this3.tech_.setCurrentTime(time);\n };\n\n if (this.options_.smoothQualityChange) {\n videojs.log.warn('smoothQualityChange is deprecated and will be removed in the next major version');\n }\n\n this.masterPlaylistController_ = new MasterPlaylistController(this.options_);\n var playbackWatcherOptions = videojs.mergeOptions({\n liveRangeSafeTimeDelta: SAFE_TIME_DELTA\n }, this.options_, {\n seekable: function seekable() {\n return _this3.seekable();\n },\n media: function media() {\n return _this3.masterPlaylistController_.media();\n },\n masterPlaylistController: this.masterPlaylistController_\n });\n this.playbackWatcher_ = new PlaybackWatcher(playbackWatcherOptions);\n this.masterPlaylistController_.on('error', function () {\n var player = videojs.players[_this3.tech_.options_.playerId];\n var error = _this3.masterPlaylistController_.error;\n\n if (typeof error === 'object' && !error.code) {\n error.code = 3;\n } else if (typeof error === 'string') {\n error = {\n message: error,\n code: 3\n };\n }\n\n player.error(error);\n });\n var defaultSelector = this.options_.experimentalBufferBasedABR ? Vhs.movingAverageBandwidthSelector(0.55) : Vhs.STANDARD_PLAYLIST_SELECTOR; // `this` in selectPlaylist should be the VhsHandler for backwards\n // compatibility with < v2\n\n this.masterPlaylistController_.selectPlaylist = this.selectPlaylist ? this.selectPlaylist.bind(this) : defaultSelector.bind(this);\n this.masterPlaylistController_.selectInitialPlaylist = Vhs.INITIAL_PLAYLIST_SELECTOR.bind(this); // re-expose some internal objects for backwards compatibility with < v2\n\n this.playlists = this.masterPlaylistController_.masterPlaylistLoader_;\n this.mediaSource = this.masterPlaylistController_.mediaSource; // Proxy assignment of some properties to the master playlist\n // controller. Using a custom property for backwards compatibility\n // with < v2\n\n Object.defineProperties(this, {\n selectPlaylist: {\n get: function get() {\n return this.masterPlaylistController_.selectPlaylist;\n },\n set: function set(selectPlaylist) {\n this.masterPlaylistController_.selectPlaylist = selectPlaylist.bind(this);\n }\n },\n throughput: {\n get: function get() {\n return this.masterPlaylistController_.mainSegmentLoader_.throughput.rate;\n },\n set: function set(throughput) {\n this.masterPlaylistController_.mainSegmentLoader_.throughput.rate = throughput; // By setting `count` to 1 the throughput value becomes the starting value\n // for the cumulative average\n\n this.masterPlaylistController_.mainSegmentLoader_.throughput.count = 1;\n }\n },\n bandwidth: {\n get: function get() {\n var playerBandwidthEst = this.masterPlaylistController_.mainSegmentLoader_.bandwidth;\n var networkInformation = window$1.navigator.connection || window$1.navigator.mozConnection || window$1.navigator.webkitConnection;\n var tenMbpsAsBitsPerSecond = 10e6;\n\n if (this.options_.useNetworkInformationApi && networkInformation) {\n // downlink returns Mbps\n // https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlink\n var networkInfoBandwidthEstBitsPerSec = networkInformation.downlink * 1000 * 1000; // downlink maxes out at 10 Mbps. In the event that both networkInformationApi and the player\n // estimate a bandwidth greater than 10 Mbps, use the larger of the two estimates to ensure that\n // high quality streams are not filtered out.\n\n if (networkInfoBandwidthEstBitsPerSec >= tenMbpsAsBitsPerSecond && playerBandwidthEst >= tenMbpsAsBitsPerSecond) {\n playerBandwidthEst = Math.max(playerBandwidthEst, networkInfoBandwidthEstBitsPerSec);\n } else {\n playerBandwidthEst = networkInfoBandwidthEstBitsPerSec;\n }\n }\n\n return playerBandwidthEst;\n },\n set: function set(bandwidth) {\n this.masterPlaylistController_.mainSegmentLoader_.bandwidth = bandwidth; // setting the bandwidth manually resets the throughput counter\n // `count` is set to zero that current value of `rate` isn't included\n // in the cumulative average\n\n this.masterPlaylistController_.mainSegmentLoader_.throughput = {\n rate: 0,\n count: 0\n };\n }\n },\n\n /**\n * `systemBandwidth` is a combination of two serial processes bit-rates. The first\n * is the network bitrate provided by `bandwidth` and the second is the bitrate of\n * the entire process after that - decryption, transmuxing, and appending - provided\n * by `throughput`.\n *\n * Since the two process are serial, the overall system bandwidth is given by:\n * sysBandwidth = 1 / (1 / bandwidth + 1 / throughput)\n */\n systemBandwidth: {\n get: function get() {\n var invBandwidth = 1 / (this.bandwidth || 1);\n var invThroughput;\n\n if (this.throughput > 0) {\n invThroughput = 1 / this.throughput;\n } else {\n invThroughput = 0;\n }\n\n var systemBitrate = Math.floor(1 / (invBandwidth + invThroughput));\n return systemBitrate;\n },\n set: function set() {\n videojs.log.error('The \"systemBandwidth\" property is read-only');\n }\n }\n });\n\n if (this.options_.bandwidth) {\n this.bandwidth = this.options_.bandwidth;\n }\n\n if (this.options_.throughput) {\n this.throughput = this.options_.throughput;\n }\n\n Object.defineProperties(this.stats, {\n bandwidth: {\n get: function get() {\n return _this3.bandwidth || 0;\n },\n enumerable: true\n },\n mediaRequests: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaRequests_() || 0;\n },\n enumerable: true\n },\n mediaRequestsAborted: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaRequestsAborted_() || 0;\n },\n enumerable: true\n },\n mediaRequestsTimedout: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaRequestsTimedout_() || 0;\n },\n enumerable: true\n },\n mediaRequestsErrored: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaRequestsErrored_() || 0;\n },\n enumerable: true\n },\n mediaTransferDuration: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaTransferDuration_() || 0;\n },\n enumerable: true\n },\n mediaBytesTransferred: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaBytesTransferred_() || 0;\n },\n enumerable: true\n },\n mediaSecondsLoaded: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaSecondsLoaded_() || 0;\n },\n enumerable: true\n },\n mediaAppends: {\n get: function get() {\n return _this3.masterPlaylistController_.mediaAppends_() || 0;\n },\n enumerable: true\n },\n mainAppendsToLoadedData: {\n get: function get() {\n return _this3.masterPlaylistController_.mainAppendsToLoadedData_() || 0;\n },\n enumerable: true\n },\n audioAppendsToLoadedData: {\n get: function get() {\n return _this3.masterPlaylistController_.audioAppendsToLoadedData_() || 0;\n },\n enumerable: true\n },\n appendsToLoadedData: {\n get: function get() {\n return _this3.masterPlaylistController_.appendsToLoadedData_() || 0;\n },\n enumerable: true\n },\n timeToLoadedData: {\n get: function get() {\n return _this3.masterPlaylistController_.timeToLoadedData_() || 0;\n },\n enumerable: true\n },\n buffered: {\n get: function get() {\n return timeRangesToArray(_this3.tech_.buffered());\n },\n enumerable: true\n },\n currentTime: {\n get: function get() {\n return _this3.tech_.currentTime();\n },\n enumerable: true\n },\n currentSource: {\n get: function get() {\n return _this3.tech_.currentSource_;\n },\n enumerable: true\n },\n currentTech: {\n get: function get() {\n return _this3.tech_.name_;\n },\n enumerable: true\n },\n duration: {\n get: function get() {\n return _this3.tech_.duration();\n },\n enumerable: true\n },\n master: {\n get: function get() {\n return _this3.playlists.master;\n },\n enumerable: true\n },\n playerDimensions: {\n get: function get() {\n return _this3.tech_.currentDimensions();\n },\n enumerable: true\n },\n seekable: {\n get: function get() {\n return timeRangesToArray(_this3.tech_.seekable());\n },\n enumerable: true\n },\n timestamp: {\n get: function get() {\n return Date.now();\n },\n enumerable: true\n },\n videoPlaybackQuality: {\n get: function get() {\n return _this3.tech_.getVideoPlaybackQuality();\n },\n enumerable: true\n }\n });\n this.tech_.one('canplay', this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_));\n this.tech_.on('bandwidthupdate', function () {\n if (_this3.options_.useBandwidthFromLocalStorage) {\n updateVhsLocalStorage({\n bandwidth: _this3.bandwidth,\n throughput: Math.round(_this3.throughput)\n });\n }\n });\n this.masterPlaylistController_.on('selectedinitialmedia', function () {\n // Add the manual rendition mix-in to VhsHandler\n renditionSelectionMixin(_this3);\n });\n this.masterPlaylistController_.sourceUpdater_.on('createdsourcebuffers', function () {\n _this3.setupEme_();\n }); // the bandwidth of the primary segment loader is our best\n // estimate of overall bandwidth\n\n this.on(this.masterPlaylistController_, 'progress', function () {\n this.tech_.trigger('progress');\n }); // In the live case, we need to ignore the very first `seeking` event since\n // that will be the result of the seek-to-live behavior\n\n this.on(this.masterPlaylistController_, 'firstplay', function () {\n this.ignoreNextSeekingEvent_ = true;\n });\n this.setupQualityLevels_(); // do nothing if the tech has been disposed already\n // this can occur if someone sets the src in player.ready(), for instance\n\n if (!this.tech_.el()) {\n return;\n }\n\n this.mediaSourceUrl_ = window$1.URL.createObjectURL(this.masterPlaylistController_.mediaSource);\n this.tech_.src(this.mediaSourceUrl_);\n };\n\n _proto.createKeySessions_ = function createKeySessions_() {\n var _this4 = this;\n\n var audioPlaylistLoader = this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader;\n this.logger_('waiting for EME key session creation');\n waitForKeySessionCreation({\n player: this.player_,\n sourceKeySystems: this.source_.keySystems,\n audioMedia: audioPlaylistLoader && audioPlaylistLoader.media(),\n mainPlaylists: this.playlists.master.playlists\n }).then(function () {\n _this4.logger_('created EME key session');\n\n _this4.masterPlaylistController_.sourceUpdater_.initializedEme();\n }).catch(function (err) {\n _this4.logger_('error while creating EME key session', err);\n\n _this4.player_.error({\n message: 'Failed to initialize media keys for EME',\n code: 3\n });\n });\n };\n\n _proto.handleWaitingForKey_ = function handleWaitingForKey_() {\n // If waitingforkey is fired, it's possible that the data that's necessary to retrieve\n // the key is in the manifest. While this should've happened on initial source load, it\n // may happen again in live streams where the keys change, and the manifest info\n // reflects the update.\n //\n // Because videojs-contrib-eme compares the PSSH data we send to that of PSSH data it's\n // already requested keys for, we don't have to worry about this generating extraneous\n // requests.\n this.logger_('waitingforkey fired, attempting to create any new key sessions');\n this.createKeySessions_();\n }\n /**\n * If necessary and EME is available, sets up EME options and waits for key session\n * creation.\n *\n * This function also updates the source updater so taht it can be used, as for some\n * browsers, EME must be configured before content is appended (if appending unencrypted\n * content before encrypted content).\n */\n ;\n\n _proto.setupEme_ = function setupEme_() {\n var _this5 = this;\n\n var audioPlaylistLoader = this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader;\n var didSetupEmeOptions = setupEmeOptions({\n player: this.player_,\n sourceKeySystems: this.source_.keySystems,\n media: this.playlists.media(),\n audioMedia: audioPlaylistLoader && audioPlaylistLoader.media()\n });\n this.player_.tech_.on('keystatuschange', function (e) {\n if (e.status === 'output-restricted') {\n _this5.masterPlaylistController_.blacklistCurrentPlaylist({\n playlist: _this5.masterPlaylistController_.media(),\n message: \"DRM keystatus changed to \" + e.status + \". Playlist will fail to play. Check for HDCP content.\",\n blacklistDuration: Infinity\n });\n }\n });\n this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this);\n this.player_.tech_.on('waitingforkey', this.handleWaitingForKey_); // In IE11 this is too early to initialize media keys, and IE11 does not support\n // promises.\n\n if (videojs.browser.IE_VERSION === 11 || !didSetupEmeOptions) {\n // If EME options were not set up, we've done all we could to initialize EME.\n this.masterPlaylistController_.sourceUpdater_.initializedEme();\n return;\n }\n\n this.createKeySessions_();\n }\n /**\n * Initializes the quality levels and sets listeners to update them.\n *\n * @method setupQualityLevels_\n * @private\n */\n ;\n\n _proto.setupQualityLevels_ = function setupQualityLevels_() {\n var _this6 = this;\n\n var player = videojs.players[this.tech_.options_.playerId]; // if there isn't a player or there isn't a qualityLevels plugin\n // or qualityLevels_ listeners have already been setup, do nothing.\n\n if (!player || !player.qualityLevels || this.qualityLevels_) {\n return;\n }\n\n this.qualityLevels_ = player.qualityLevels();\n this.masterPlaylistController_.on('selectedinitialmedia', function () {\n handleVhsLoadedMetadata(_this6.qualityLevels_, _this6);\n });\n this.playlists.on('mediachange', function () {\n handleVhsMediaChange(_this6.qualityLevels_, _this6.playlists);\n });\n }\n /**\n * return the version\n */\n ;\n\n VhsHandler.version = function version$5() {\n return {\n '@videojs/http-streaming': version$4,\n 'mux.js': version$3,\n 'mpd-parser': version$2,\n 'm3u8-parser': version$1,\n 'aes-decrypter': version\n };\n }\n /**\n * return the version\n */\n ;\n\n _proto.version = function version() {\n return this.constructor.version();\n };\n\n _proto.canChangeType = function canChangeType() {\n return SourceUpdater.canChangeType();\n }\n /**\n * Begin playing the video.\n */\n ;\n\n _proto.play = function play() {\n this.masterPlaylistController_.play();\n }\n /**\n * a wrapper around the function in MasterPlaylistController\n */\n ;\n\n _proto.setCurrentTime = function setCurrentTime(currentTime) {\n this.masterPlaylistController_.setCurrentTime(currentTime);\n }\n /**\n * a wrapper around the function in MasterPlaylistController\n */\n ;\n\n _proto.duration = function duration() {\n return this.masterPlaylistController_.duration();\n }\n /**\n * a wrapper around the function in MasterPlaylistController\n */\n ;\n\n _proto.seekable = function seekable() {\n return this.masterPlaylistController_.seekable();\n }\n /**\n * Abort all outstanding work and cleanup.\n */\n ;\n\n _proto.dispose = function dispose() {\n if (this.playbackWatcher_) {\n this.playbackWatcher_.dispose();\n }\n\n if (this.masterPlaylistController_) {\n this.masterPlaylistController_.dispose();\n }\n\n if (this.qualityLevels_) {\n this.qualityLevels_.dispose();\n }\n\n if (this.player_) {\n delete this.player_.vhs;\n delete this.player_.dash;\n delete this.player_.hls;\n }\n\n if (this.tech_ && this.tech_.vhs) {\n delete this.tech_.vhs;\n } // don't check this.tech_.hls as it will log a deprecated warning\n\n\n if (this.tech_) {\n delete this.tech_.hls;\n }\n\n if (this.mediaSourceUrl_ && window$1.URL.revokeObjectURL) {\n window$1.URL.revokeObjectURL(this.mediaSourceUrl_);\n this.mediaSourceUrl_ = null;\n }\n\n if (this.tech_) {\n this.tech_.off('waitingforkey', this.handleWaitingForKey_);\n }\n\n _Component.prototype.dispose.call(this);\n };\n\n _proto.convertToProgramTime = function convertToProgramTime(time, callback) {\n return getProgramTime({\n playlist: this.masterPlaylistController_.media(),\n time: time,\n callback: callback\n });\n } // the player must be playing before calling this\n ;\n\n _proto.seekToProgramTime = function seekToProgramTime$1(programTime, callback, pauseAfterSeek, retryCount) {\n if (pauseAfterSeek === void 0) {\n pauseAfterSeek = true;\n }\n\n if (retryCount === void 0) {\n retryCount = 2;\n }\n\n return seekToProgramTime({\n programTime: programTime,\n playlist: this.masterPlaylistController_.media(),\n retryCount: retryCount,\n pauseAfterSeek: pauseAfterSeek,\n seekTo: this.options_.seekTo,\n tech: this.options_.tech,\n callback: callback\n });\n };\n\n return VhsHandler;\n}(Component);\n/**\n * The Source Handler object, which informs video.js what additional\n * MIME types are supported and sets up playback. It is registered\n * automatically to the appropriate tech based on the capabilities of\n * the browser it is running in. It is not necessary to use or modify\n * this object in normal usage.\n */\n\n\nvar VhsSourceHandler = {\n name: 'videojs-http-streaming',\n VERSION: version$4,\n canHandleSource: function canHandleSource(srcObj, options) {\n if (options === void 0) {\n options = {};\n }\n\n var localOptions = videojs.mergeOptions(videojs.options, options);\n return VhsSourceHandler.canPlayType(srcObj.type, localOptions);\n },\n handleSource: function handleSource(source, tech, options) {\n if (options === void 0) {\n options = {};\n }\n\n var localOptions = videojs.mergeOptions(videojs.options, options);\n tech.vhs = new VhsHandler(source, tech, localOptions);\n\n if (!videojs.hasOwnProperty('hls')) {\n Object.defineProperty(tech, 'hls', {\n get: function get() {\n videojs.log.warn('player.tech().hls is deprecated. Use player.tech().vhs instead.');\n return tech.vhs;\n },\n configurable: true\n });\n }\n\n tech.vhs.xhr = xhrFactory();\n tech.vhs.src(source.src, source.type);\n return tech.vhs;\n },\n canPlayType: function canPlayType(type, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _videojs$mergeOptions = videojs.mergeOptions(videojs.options, options),\n _videojs$mergeOptions2 = _videojs$mergeOptions.vhs;\n\n _videojs$mergeOptions2 = _videojs$mergeOptions2 === void 0 ? {} : _videojs$mergeOptions2;\n var _videojs$mergeOptions3 = _videojs$mergeOptions2.overrideNative,\n overrideNative = _videojs$mergeOptions3 === void 0 ? !videojs.browser.IS_ANY_SAFARI : _videojs$mergeOptions3,\n _videojs$mergeOptions4 = _videojs$mergeOptions.hls;\n _videojs$mergeOptions4 = _videojs$mergeOptions4 === void 0 ? {} : _videojs$mergeOptions4;\n var _videojs$mergeOptions5 = _videojs$mergeOptions4.overrideNative,\n legacyOverrideNative = _videojs$mergeOptions5 === void 0 ? false : _videojs$mergeOptions5;\n var supportedType = simpleTypeFromSourceType(type);\n var canUseMsePlayback = supportedType && (!Vhs.supportsTypeNatively(supportedType) || legacyOverrideNative || overrideNative);\n return canUseMsePlayback ? 'maybe' : '';\n }\n};\n/**\n * Check to see if the native MediaSource object exists and supports\n * an MP4 container with both H.264 video and AAC-LC audio.\n *\n * @return {boolean} if native media sources are supported\n */\n\nvar supportsNativeMediaSources = function supportsNativeMediaSources() {\n return browserSupportsCodec('avc1.4d400d,mp4a.40.2');\n}; // register source handlers with the appropriate techs\n\n\nif (supportsNativeMediaSources()) {\n videojs.getTech('Html5').registerSourceHandler(VhsSourceHandler, 0);\n}\n\nvideojs.VhsHandler = VhsHandler;\nObject.defineProperty(videojs, 'HlsHandler', {\n get: function get() {\n videojs.log.warn('videojs.HlsHandler is deprecated. Use videojs.VhsHandler instead.');\n return VhsHandler;\n },\n configurable: true\n});\nvideojs.VhsSourceHandler = VhsSourceHandler;\nObject.defineProperty(videojs, 'HlsSourceHandler', {\n get: function get() {\n videojs.log.warn('videojs.HlsSourceHandler is deprecated. ' + 'Use videojs.VhsSourceHandler instead.');\n return VhsSourceHandler;\n },\n configurable: true\n});\nvideojs.Vhs = Vhs;\nObject.defineProperty(videojs, 'Hls', {\n get: function get() {\n videojs.log.warn('videojs.Hls is deprecated. Use videojs.Vhs instead.');\n return Vhs;\n },\n configurable: true\n});\n\nif (!videojs.use) {\n videojs.registerComponent('Hls', Vhs);\n videojs.registerComponent('Vhs', Vhs);\n}\n\nvideojs.options.vhs = videojs.options.vhs || {};\nvideojs.options.hls = videojs.options.hls || {};\n\nif (!videojs.getPlugin || !videojs.getPlugin('reloadSourceOnError')) {\n var registerPlugin = videojs.registerPlugin || videojs.plugin;\n registerPlugin('reloadSourceOnError', reloadSourceOnError);\n}\n\nexport { LOCAL_STORAGE_KEY, Vhs, VhsHandler, VhsSourceHandler, emeKeySystems, expandDataUri, getAllPsshKeySystemsOptions, setupEmeOptions, waitForKeySessionCreation };\n","var getUint64 = require('../utils/numbers.js').getUint64;\n\nvar parseSidx = function(data) {\n var view = new DataView(data.buffer, data.byteOffset, data.byteLength),\n result = {\n version: data[0],\n flags: new Uint8Array(data.subarray(1, 4)),\n references: [],\n referenceId: view.getUint32(4),\n timescale: view.getUint32(8)\n },\n i = 12;\n\n if (result.version === 0) {\n result.earliestPresentationTime = view.getUint32(i);\n result.firstOffset = view.getUint32(i + 4);\n i += 8;\n } else {\n // read 64 bits\n result.earliestPresentationTime = getUint64(data.subarray(i));\n result.firstOffset = getUint64(data.subarray(i + 8));\n i += 16;\n }\n\n i += 2; // reserved\n\n var referenceCount = view.getUint16(i);\n\n i += 2; // start of references\n\n for (; referenceCount > 0; i += 12, referenceCount--) {\n result.references.push({\n referenceType: (data[i] & 0x80) >>> 7,\n referencedSize: view.getUint32(i) & 0x7FFFFFFF,\n subsegmentDuration: view.getUint32(i + 4),\n startsWithSap: !!(data[i + 8] & 0x80),\n sapType: (data[i + 8] & 0x70) >>> 4,\n sapDeltaTime: view.getUint32(i + 8) & 0x0FFFFFFF\n });\n }\n\n return result;\n};\n\n\nmodule.exports = parseSidx;\n","/**\n * Loops through all supported media groups in master and calls the provided\n * callback for each group\n *\n * @param {Object} master\n * The parsed master manifest object\n * @param {string[]} groups\n * The media groups to call the callback for\n * @param {Function} callback\n * Callback to call for each media group\n */\nexport var forEachMediaGroup = function forEachMediaGroup(master, groups, callback) {\n groups.forEach(function (mediaType) {\n for (var groupKey in master.mediaGroups[mediaType]) {\n for (var labelKey in master.mediaGroups[mediaType][groupKey]) {\n var mediaProperties = master.mediaGroups[mediaType][groupKey][labelKey];\n callback(mediaProperties, mediaType, groupKey, labelKey);\n }\n }\n });\n};","/*! @name mpd-parser @version 0.21.0 @license Apache-2.0 */\nimport resolveUrl from '@videojs/vhs-utils/es/resolve-url';\nimport window from 'global/window';\nimport { forEachMediaGroup } from '@videojs/vhs-utils/es/media-groups';\nimport decodeB64ToUint8Array from '@videojs/vhs-utils/es/decode-b64-to-uint8-array';\nimport { DOMParser } from '@xmldom/xmldom';\n\nvar version = \"0.21.0\";\n\nvar isObject = function isObject(obj) {\n return !!obj && typeof obj === 'object';\n};\n\nvar merge = function merge() {\n for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) {\n objects[_key] = arguments[_key];\n }\n\n return objects.reduce(function (result, source) {\n if (typeof source !== 'object') {\n return result;\n }\n\n Object.keys(source).forEach(function (key) {\n if (Array.isArray(result[key]) && Array.isArray(source[key])) {\n result[key] = result[key].concat(source[key]);\n } else if (isObject(result[key]) && isObject(source[key])) {\n result[key] = merge(result[key], source[key]);\n } else {\n result[key] = source[key];\n }\n });\n return result;\n }, {});\n};\nvar values = function values(o) {\n return Object.keys(o).map(function (k) {\n return o[k];\n });\n};\n\nvar range = function range(start, end) {\n var result = [];\n\n for (var i = start; i < end; i++) {\n result.push(i);\n }\n\n return result;\n};\nvar flatten = function flatten(lists) {\n return lists.reduce(function (x, y) {\n return x.concat(y);\n }, []);\n};\nvar from = function from(list) {\n if (!list.length) {\n return [];\n }\n\n var result = [];\n\n for (var i = 0; i < list.length; i++) {\n result.push(list[i]);\n }\n\n return result;\n};\nvar findIndexes = function findIndexes(l, key) {\n return l.reduce(function (a, e, i) {\n if (e[key]) {\n a.push(i);\n }\n\n return a;\n }, []);\n};\n/**\n * Returns the first index that satisfies the matching function, or -1 if not found.\n *\n * Only necessary because of IE11 support.\n *\n * @param {Array} list - the list to search through\n * @param {Function} matchingFunction - the matching function\n *\n * @return {number} the matching index or -1 if not found\n */\n\nvar findIndex = function findIndex(list, matchingFunction) {\n for (var i = 0; i < list.length; i++) {\n if (matchingFunction(list[i])) {\n return i;\n }\n }\n\n return -1;\n};\n/**\n * Returns a union of the included lists provided each element can be identified by a key.\n *\n * @param {Array} list - list of lists to get the union of\n * @param {Function} keyFunction - the function to use as a key for each element\n *\n * @return {Array} the union of the arrays\n */\n\nvar union = function union(lists, keyFunction) {\n return values(lists.reduce(function (acc, list) {\n list.forEach(function (el) {\n acc[keyFunction(el)] = el;\n });\n return acc;\n }, {}));\n};\n\nvar errors = {\n INVALID_NUMBER_OF_PERIOD: 'INVALID_NUMBER_OF_PERIOD',\n DASH_EMPTY_MANIFEST: 'DASH_EMPTY_MANIFEST',\n DASH_INVALID_XML: 'DASH_INVALID_XML',\n NO_BASE_URL: 'NO_BASE_URL',\n MISSING_SEGMENT_INFORMATION: 'MISSING_SEGMENT_INFORMATION',\n SEGMENT_TIME_UNSPECIFIED: 'SEGMENT_TIME_UNSPECIFIED',\n UNSUPPORTED_UTC_TIMING_SCHEME: 'UNSUPPORTED_UTC_TIMING_SCHEME'\n};\n\n/**\n * @typedef {Object} SingleUri\n * @property {string} uri - relative location of segment\n * @property {string} resolvedUri - resolved location of segment\n * @property {Object} byterange - Object containing information on how to make byte range\n * requests following byte-range-spec per RFC2616.\n * @property {String} byterange.length - length of range request\n * @property {String} byterange.offset - byte offset of range request\n *\n * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1\n */\n\n/**\n * Converts a URLType node (5.3.9.2.3 Table 13) to a segment object\n * that conforms to how m3u8-parser is structured\n *\n * @see https://github.com/videojs/m3u8-parser\n *\n * @param {string} baseUrl - baseUrl provided by nodes\n * @param {string} source - source url for segment\n * @param {string} range - optional range used for range calls,\n * follows RFC 2616, Clause 14.35.1\n * @return {SingleUri} full segment information transformed into a format similar\n * to m3u8-parser\n */\n\nvar urlTypeToSegment = function urlTypeToSegment(_ref) {\n var _ref$baseUrl = _ref.baseUrl,\n baseUrl = _ref$baseUrl === void 0 ? '' : _ref$baseUrl,\n _ref$source = _ref.source,\n source = _ref$source === void 0 ? '' : _ref$source,\n _ref$range = _ref.range,\n range = _ref$range === void 0 ? '' : _ref$range,\n _ref$indexRange = _ref.indexRange,\n indexRange = _ref$indexRange === void 0 ? '' : _ref$indexRange;\n var segment = {\n uri: source,\n resolvedUri: resolveUrl(baseUrl || '', source)\n };\n\n if (range || indexRange) {\n var rangeStr = range ? range : indexRange;\n var ranges = rangeStr.split('-'); // default to parsing this as a BigInt if possible\n\n var startRange = window.BigInt ? window.BigInt(ranges[0]) : parseInt(ranges[0], 10);\n var endRange = window.BigInt ? window.BigInt(ranges[1]) : parseInt(ranges[1], 10); // convert back to a number if less than MAX_SAFE_INTEGER\n\n if (startRange < Number.MAX_SAFE_INTEGER && typeof startRange === 'bigint') {\n startRange = Number(startRange);\n }\n\n if (endRange < Number.MAX_SAFE_INTEGER && typeof endRange === 'bigint') {\n endRange = Number(endRange);\n }\n\n var length;\n\n if (typeof endRange === 'bigint' || typeof startRange === 'bigint') {\n length = window.BigInt(endRange) - window.BigInt(startRange) + window.BigInt(1);\n } else {\n length = endRange - startRange + 1;\n }\n\n if (typeof length === 'bigint' && length < Number.MAX_SAFE_INTEGER) {\n length = Number(length);\n } // byterange should be inclusive according to\n // RFC 2616, Clause 14.35.1\n\n\n segment.byterange = {\n length: length,\n offset: startRange\n };\n }\n\n return segment;\n};\nvar byteRangeToString = function byteRangeToString(byterange) {\n // `endRange` is one less than `offset + length` because the HTTP range\n // header uses inclusive ranges\n var endRange;\n\n if (typeof byterange.offset === 'bigint' || typeof byterange.length === 'bigint') {\n endRange = window.BigInt(byterange.offset) + window.BigInt(byterange.length) - window.BigInt(1);\n } else {\n endRange = byterange.offset + byterange.length - 1;\n }\n\n return byterange.offset + \"-\" + endRange;\n};\n\n/**\n * parse the end number attribue that can be a string\n * number, or undefined.\n *\n * @param {string|number|undefined} endNumber\n * The end number attribute.\n *\n * @return {number|null}\n * The result of parsing the end number.\n */\n\nvar parseEndNumber = function parseEndNumber(endNumber) {\n if (endNumber && typeof endNumber !== 'number') {\n endNumber = parseInt(endNumber, 10);\n }\n\n if (isNaN(endNumber)) {\n return null;\n }\n\n return endNumber;\n};\n/**\n * Functions for calculating the range of available segments in static and dynamic\n * manifests.\n */\n\n\nvar segmentRange = {\n /**\n * Returns the entire range of available segments for a static MPD\n *\n * @param {Object} attributes\n * Inheritied MPD attributes\n * @return {{ start: number, end: number }}\n * The start and end numbers for available segments\n */\n static: function _static(attributes) {\n var duration = attributes.duration,\n _attributes$timescale = attributes.timescale,\n timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale,\n sourceDuration = attributes.sourceDuration,\n periodDuration = attributes.periodDuration;\n var endNumber = parseEndNumber(attributes.endNumber);\n var segmentDuration = duration / timescale;\n\n if (typeof endNumber === 'number') {\n return {\n start: 0,\n end: endNumber\n };\n }\n\n if (typeof periodDuration === 'number') {\n return {\n start: 0,\n end: periodDuration / segmentDuration\n };\n }\n\n return {\n start: 0,\n end: sourceDuration / segmentDuration\n };\n },\n\n /**\n * Returns the current live window range of available segments for a dynamic MPD\n *\n * @param {Object} attributes\n * Inheritied MPD attributes\n * @return {{ start: number, end: number }}\n * The start and end numbers for available segments\n */\n dynamic: function dynamic(attributes) {\n var NOW = attributes.NOW,\n clientOffset = attributes.clientOffset,\n availabilityStartTime = attributes.availabilityStartTime,\n _attributes$timescale2 = attributes.timescale,\n timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2,\n duration = attributes.duration,\n _attributes$periodSta = attributes.periodStart,\n periodStart = _attributes$periodSta === void 0 ? 0 : _attributes$periodSta,\n _attributes$minimumUp = attributes.minimumUpdatePeriod,\n minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp,\n _attributes$timeShift = attributes.timeShiftBufferDepth,\n timeShiftBufferDepth = _attributes$timeShift === void 0 ? Infinity : _attributes$timeShift;\n var endNumber = parseEndNumber(attributes.endNumber); // clientOffset is passed in at the top level of mpd-parser and is an offset calculated\n // after retrieving UTC server time.\n\n var now = (NOW + clientOffset) / 1000; // WC stands for Wall Clock.\n // Convert the period start time to EPOCH.\n\n var periodStartWC = availabilityStartTime + periodStart; // Period end in EPOCH is manifest's retrieval time + time until next update.\n\n var periodEndWC = now + minimumUpdatePeriod;\n var periodDuration = periodEndWC - periodStartWC;\n var segmentCount = Math.ceil(periodDuration * timescale / duration);\n var availableStart = Math.floor((now - periodStartWC - timeShiftBufferDepth) * timescale / duration);\n var availableEnd = Math.floor((now - periodStartWC) * timescale / duration);\n return {\n start: Math.max(0, availableStart),\n end: typeof endNumber === 'number' ? endNumber : Math.min(segmentCount, availableEnd)\n };\n }\n};\n/**\n * Maps a range of numbers to objects with information needed to build the corresponding\n * segment list\n *\n * @name toSegmentsCallback\n * @function\n * @param {number} number\n * Number of the segment\n * @param {number} index\n * Index of the number in the range list\n * @return {{ number: Number, duration: Number, timeline: Number, time: Number }}\n * Object with segment timing and duration info\n */\n\n/**\n * Returns a callback for Array.prototype.map for mapping a range of numbers to\n * information needed to build the segment list.\n *\n * @param {Object} attributes\n * Inherited MPD attributes\n * @return {toSegmentsCallback}\n * Callback map function\n */\n\nvar toSegments = function toSegments(attributes) {\n return function (number) {\n var duration = attributes.duration,\n _attributes$timescale3 = attributes.timescale,\n timescale = _attributes$timescale3 === void 0 ? 1 : _attributes$timescale3,\n periodStart = attributes.periodStart,\n _attributes$startNumb = attributes.startNumber,\n startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb;\n return {\n number: startNumber + number,\n duration: duration / timescale,\n timeline: periodStart,\n time: number * duration\n };\n };\n};\n/**\n * Returns a list of objects containing segment timing and duration info used for\n * building the list of segments. This uses the @duration attribute specified\n * in the MPD manifest to derive the range of segments.\n *\n * @param {Object} attributes\n * Inherited MPD attributes\n * @return {{number: number, duration: number, time: number, timeline: number}[]}\n * List of Objects with segment timing and duration info\n */\n\nvar parseByDuration = function parseByDuration(attributes) {\n var type = attributes.type,\n duration = attributes.duration,\n _attributes$timescale4 = attributes.timescale,\n timescale = _attributes$timescale4 === void 0 ? 1 : _attributes$timescale4,\n periodDuration = attributes.periodDuration,\n sourceDuration = attributes.sourceDuration;\n\n var _segmentRange$type = segmentRange[type](attributes),\n start = _segmentRange$type.start,\n end = _segmentRange$type.end;\n\n var segments = range(start, end).map(toSegments(attributes));\n\n if (type === 'static') {\n var index = segments.length - 1; // section is either a period or the full source\n\n var sectionDuration = typeof periodDuration === 'number' ? periodDuration : sourceDuration; // final segment may be less than full segment duration\n\n segments[index].duration = sectionDuration - duration / timescale * index;\n }\n\n return segments;\n};\n\n/**\n * Translates SegmentBase into a set of segments.\n * (DASH SPEC Section 5.3.9.3.2) contains a set of nodes. Each\n * node should be translated into segment.\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @return {Object.} list of segments\n */\n\nvar segmentsFromBase = function segmentsFromBase(attributes) {\n var baseUrl = attributes.baseUrl,\n _attributes$initializ = attributes.initialization,\n initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ,\n sourceDuration = attributes.sourceDuration,\n _attributes$indexRang = attributes.indexRange,\n indexRange = _attributes$indexRang === void 0 ? '' : _attributes$indexRang,\n periodStart = attributes.periodStart,\n presentationTime = attributes.presentationTime,\n _attributes$number = attributes.number,\n number = _attributes$number === void 0 ? 0 : _attributes$number,\n duration = attributes.duration; // base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1)\n\n if (!baseUrl) {\n throw new Error(errors.NO_BASE_URL);\n }\n\n var initSegment = urlTypeToSegment({\n baseUrl: baseUrl,\n source: initialization.sourceURL,\n range: initialization.range\n });\n var segment = urlTypeToSegment({\n baseUrl: baseUrl,\n source: baseUrl,\n indexRange: indexRange\n });\n segment.map = initSegment; // If there is a duration, use it, otherwise use the given duration of the source\n // (since SegmentBase is only for one total segment)\n\n if (duration) {\n var segmentTimeInfo = parseByDuration(attributes);\n\n if (segmentTimeInfo.length) {\n segment.duration = segmentTimeInfo[0].duration;\n segment.timeline = segmentTimeInfo[0].timeline;\n }\n } else if (sourceDuration) {\n segment.duration = sourceDuration;\n segment.timeline = periodStart;\n } // If presentation time is provided, these segments are being generated by SIDX\n // references, and should use the time provided. For the general case of SegmentBase,\n // there should only be one segment in the period, so its presentation time is the same\n // as its period start.\n\n\n segment.presentationTime = presentationTime || periodStart;\n segment.number = number;\n return [segment];\n};\n/**\n * Given a playlist, a sidx box, and a baseUrl, update the segment list of the playlist\n * according to the sidx information given.\n *\n * playlist.sidx has metadadata about the sidx where-as the sidx param\n * is the parsed sidx box itself.\n *\n * @param {Object} playlist the playlist to update the sidx information for\n * @param {Object} sidx the parsed sidx box\n * @return {Object} the playlist object with the updated sidx information\n */\n\nvar addSidxSegmentsToPlaylist$1 = function addSidxSegmentsToPlaylist(playlist, sidx, baseUrl) {\n // Retain init segment information\n var initSegment = playlist.sidx.map ? playlist.sidx.map : null; // Retain source duration from initial main manifest parsing\n\n var sourceDuration = playlist.sidx.duration; // Retain source timeline\n\n var timeline = playlist.timeline || 0;\n var sidxByteRange = playlist.sidx.byterange;\n var sidxEnd = sidxByteRange.offset + sidxByteRange.length; // Retain timescale of the parsed sidx\n\n var timescale = sidx.timescale; // referenceType 1 refers to other sidx boxes\n\n var mediaReferences = sidx.references.filter(function (r) {\n return r.referenceType !== 1;\n });\n var segments = [];\n var type = playlist.endList ? 'static' : 'dynamic';\n var periodStart = playlist.sidx.timeline;\n var presentationTime = periodStart;\n var number = playlist.mediaSequence || 0; // firstOffset is the offset from the end of the sidx box\n\n var startIndex; // eslint-disable-next-line\n\n if (typeof sidx.firstOffset === 'bigint') {\n startIndex = window.BigInt(sidxEnd) + sidx.firstOffset;\n } else {\n startIndex = sidxEnd + sidx.firstOffset;\n }\n\n for (var i = 0; i < mediaReferences.length; i++) {\n var reference = sidx.references[i]; // size of the referenced (sub)segment\n\n var size = reference.referencedSize; // duration of the referenced (sub)segment, in the timescale\n // this will be converted to seconds when generating segments\n\n var duration = reference.subsegmentDuration; // should be an inclusive range\n\n var endIndex = void 0; // eslint-disable-next-line\n\n if (typeof startIndex === 'bigint') {\n endIndex = startIndex + window.BigInt(size) - window.BigInt(1);\n } else {\n endIndex = startIndex + size - 1;\n }\n\n var indexRange = startIndex + \"-\" + endIndex;\n var attributes = {\n baseUrl: baseUrl,\n timescale: timescale,\n timeline: timeline,\n periodStart: periodStart,\n presentationTime: presentationTime,\n number: number,\n duration: duration,\n sourceDuration: sourceDuration,\n indexRange: indexRange,\n type: type\n };\n var segment = segmentsFromBase(attributes)[0];\n\n if (initSegment) {\n segment.map = initSegment;\n }\n\n segments.push(segment);\n\n if (typeof startIndex === 'bigint') {\n startIndex += window.BigInt(size);\n } else {\n startIndex += size;\n }\n\n presentationTime += duration / timescale;\n number++;\n }\n\n playlist.segments = segments;\n return playlist;\n};\n\nvar SUPPORTED_MEDIA_TYPES = ['AUDIO', 'SUBTITLES']; // allow one 60fps frame as leniency (arbitrarily chosen)\n\nvar TIME_FUDGE = 1 / 60;\n/**\n * Given a list of timelineStarts, combines, dedupes, and sorts them.\n *\n * @param {TimelineStart[]} timelineStarts - list of timeline starts\n *\n * @return {TimelineStart[]} the combined and deduped timeline starts\n */\n\nvar getUniqueTimelineStarts = function getUniqueTimelineStarts(timelineStarts) {\n return union(timelineStarts, function (_ref) {\n var timeline = _ref.timeline;\n return timeline;\n }).sort(function (a, b) {\n return a.timeline > b.timeline ? 1 : -1;\n });\n};\n/**\n * Finds the playlist with the matching NAME attribute.\n *\n * @param {Array} playlists - playlists to search through\n * @param {string} name - the NAME attribute to search for\n *\n * @return {Object|null} the matching playlist object, or null\n */\n\nvar findPlaylistWithName = function findPlaylistWithName(playlists, name) {\n for (var i = 0; i < playlists.length; i++) {\n if (playlists[i].attributes.NAME === name) {\n return playlists[i];\n }\n }\n\n return null;\n};\n/**\n * Gets a flattened array of media group playlists.\n *\n * @param {Object} manifest - the main manifest object\n *\n * @return {Array} the media group playlists\n */\n\nvar getMediaGroupPlaylists = function getMediaGroupPlaylists(manifest) {\n var mediaGroupPlaylists = [];\n forEachMediaGroup(manifest, SUPPORTED_MEDIA_TYPES, function (properties, type, group, label) {\n mediaGroupPlaylists = mediaGroupPlaylists.concat(properties.playlists || []);\n });\n return mediaGroupPlaylists;\n};\n/**\n * Updates the playlist's media sequence numbers.\n *\n * @param {Object} config - options object\n * @param {Object} config.playlist - the playlist to update\n * @param {number} config.mediaSequence - the mediaSequence number to start with\n */\n\nvar updateMediaSequenceForPlaylist = function updateMediaSequenceForPlaylist(_ref2) {\n var playlist = _ref2.playlist,\n mediaSequence = _ref2.mediaSequence;\n playlist.mediaSequence = mediaSequence;\n playlist.segments.forEach(function (segment, index) {\n segment.number = playlist.mediaSequence + index;\n });\n};\n/**\n * Updates the media and discontinuity sequence numbers of newPlaylists given oldPlaylists\n * and a complete list of timeline starts.\n *\n * If no matching playlist is found, only the discontinuity sequence number of the playlist\n * will be updated.\n *\n * Since early available timelines are not supported, at least one segment must be present.\n *\n * @param {Object} config - options object\n * @param {Object[]} oldPlaylists - the old playlists to use as a reference\n * @param {Object[]} newPlaylists - the new playlists to update\n * @param {Object} timelineStarts - all timelineStarts seen in the stream to this point\n */\n\nvar updateSequenceNumbers = function updateSequenceNumbers(_ref3) {\n var oldPlaylists = _ref3.oldPlaylists,\n newPlaylists = _ref3.newPlaylists,\n timelineStarts = _ref3.timelineStarts;\n newPlaylists.forEach(function (playlist) {\n playlist.discontinuitySequence = findIndex(timelineStarts, function (_ref4) {\n var timeline = _ref4.timeline;\n return timeline === playlist.timeline;\n }); // Playlists NAMEs come from DASH Representation IDs, which are mandatory\n // (see ISO_23009-1-2012 5.3.5.2).\n //\n // If the same Representation existed in a prior Period, it will retain the same NAME.\n\n var oldPlaylist = findPlaylistWithName(oldPlaylists, playlist.attributes.NAME);\n\n if (!oldPlaylist) {\n // Since this is a new playlist, the media sequence values can start from 0 without\n // consequence.\n return;\n } // TODO better support for live SIDX\n //\n // As of this writing, mpd-parser does not support multiperiod SIDX (in live or VOD).\n // This is evident by a playlist only having a single SIDX reference. In a multiperiod\n // playlist there would need to be multiple SIDX references. In addition, live SIDX is\n // not supported when the SIDX properties change on refreshes.\n //\n // In the future, if support needs to be added, the merging logic here can be called\n // after SIDX references are resolved. For now, exit early to prevent exceptions being\n // thrown due to undefined references.\n\n\n if (playlist.sidx) {\n return;\n } // Since we don't yet support early available timelines, we don't need to support\n // playlists with no segments.\n\n\n var firstNewSegment = playlist.segments[0];\n var oldMatchingSegmentIndex = findIndex(oldPlaylist.segments, function (oldSegment) {\n return Math.abs(oldSegment.presentationTime - firstNewSegment.presentationTime) < TIME_FUDGE;\n }); // No matching segment from the old playlist means the entire playlist was refreshed.\n // In this case the media sequence should account for this update, and the new segments\n // should be marked as discontinuous from the prior content, since the last prior\n // timeline was removed.\n\n if (oldMatchingSegmentIndex === -1) {\n updateMediaSequenceForPlaylist({\n playlist: playlist,\n mediaSequence: oldPlaylist.mediaSequence + oldPlaylist.segments.length\n });\n playlist.segments[0].discontinuity = true;\n playlist.discontinuityStarts.unshift(0); // No matching segment does not necessarily mean there's missing content.\n //\n // If the new playlist's timeline is the same as the last seen segment's timeline,\n // then a discontinuity can be added to identify that there's potentially missing\n // content. If there's no missing content, the discontinuity should still be rather\n // harmless. It's possible that if segment durations are accurate enough, that the\n // existence of a gap can be determined using the presentation times and durations,\n // but if the segment timing info is off, it may introduce more problems than simply\n // adding the discontinuity.\n //\n // If the new playlist's timeline is different from the last seen segment's timeline,\n // then a discontinuity can be added to identify that this is the first seen segment\n // of a new timeline. However, the logic at the start of this function that\n // determined the disconinuity sequence by timeline index is now off by one (the\n // discontinuity of the newest timeline hasn't yet fallen off the manifest...since\n // we added it), so the disconinuity sequence must be decremented.\n //\n // A period may also have a duration of zero, so the case of no segments is handled\n // here even though we don't yet support early available periods.\n\n if (!oldPlaylist.segments.length && playlist.timeline > oldPlaylist.timeline || oldPlaylist.segments.length && playlist.timeline > oldPlaylist.segments[oldPlaylist.segments.length - 1].timeline) {\n playlist.discontinuitySequence--;\n }\n\n return;\n } // If the first segment matched with a prior segment on a discontinuity (it's matching\n // on the first segment of a period), then the discontinuitySequence shouldn't be the\n // timeline's matching one, but instead should be the one prior, and the first segment\n // of the new manifest should be marked with a discontinuity.\n //\n // The reason for this special case is that discontinuity sequence shows how many\n // discontinuities have fallen off of the playlist, and discontinuities are marked on\n // the first segment of a new \"timeline.\" Because of this, while DASH will retain that\n // Period while the \"timeline\" exists, HLS keeps track of it via the discontinuity\n // sequence, and that first segment is an indicator, but can be removed before that\n // timeline is gone.\n\n\n var oldMatchingSegment = oldPlaylist.segments[oldMatchingSegmentIndex];\n\n if (oldMatchingSegment.discontinuity && !firstNewSegment.discontinuity) {\n firstNewSegment.discontinuity = true;\n playlist.discontinuityStarts.unshift(0);\n playlist.discontinuitySequence--;\n }\n\n updateMediaSequenceForPlaylist({\n playlist: playlist,\n mediaSequence: oldPlaylist.segments[oldMatchingSegmentIndex].number\n });\n });\n};\n/**\n * Given an old parsed manifest object and a new parsed manifest object, updates the\n * sequence and timing values within the new manifest to ensure that it lines up with the\n * old.\n *\n * @param {Array} oldManifest - the old main manifest object\n * @param {Array} newManifest - the new main manifest object\n *\n * @return {Object} the updated new manifest object\n */\n\nvar positionManifestOnTimeline = function positionManifestOnTimeline(_ref5) {\n var oldManifest = _ref5.oldManifest,\n newManifest = _ref5.newManifest;\n // Starting from v4.1.2 of the IOP, section 4.4.3.3 states:\n //\n // \"MPD@availabilityStartTime and Period@start shall not be changed over MPD updates.\"\n //\n // This was added from https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/160\n //\n // Because of this change, and the difficulty of supporting periods with changing start\n // times, periods with changing start times are not supported. This makes the logic much\n // simpler, since periods with the same start time can be considerred the same period\n // across refreshes.\n //\n // To give an example as to the difficulty of handling periods where the start time may\n // change, if a single period manifest is refreshed with another manifest with a single\n // period, and both the start and end times are increased, then the only way to determine\n // if it's a new period or an old one that has changed is to look through the segments of\n // each playlist and determine the presentation time bounds to find a match. In addition,\n // if the period start changed to exceed the old period end, then there would be no\n // match, and it would not be possible to determine whether the refreshed period is a new\n // one or the old one.\n var oldPlaylists = oldManifest.playlists.concat(getMediaGroupPlaylists(oldManifest));\n var newPlaylists = newManifest.playlists.concat(getMediaGroupPlaylists(newManifest)); // Save all seen timelineStarts to the new manifest. Although this potentially means that\n // there's a \"memory leak\" in that it will never stop growing, in reality, only a couple\n // of properties are saved for each seen Period. Even long running live streams won't\n // generate too many Periods, unless the stream is watched for decades. In the future,\n // this can be optimized by mapping to discontinuity sequence numbers for each timeline,\n // but it may not become an issue, and the additional info can be useful for debugging.\n\n newManifest.timelineStarts = getUniqueTimelineStarts([oldManifest.timelineStarts, newManifest.timelineStarts]);\n updateSequenceNumbers({\n oldPlaylists: oldPlaylists,\n newPlaylists: newPlaylists,\n timelineStarts: newManifest.timelineStarts\n });\n return newManifest;\n};\n\nvar generateSidxKey = function generateSidxKey(sidx) {\n return sidx && sidx.uri + '-' + byteRangeToString(sidx.byterange);\n};\n\nvar mergeDiscontiguousPlaylists = function mergeDiscontiguousPlaylists(playlists) {\n var mergedPlaylists = values(playlists.reduce(function (acc, playlist) {\n // assuming playlist IDs are the same across periods\n // TODO: handle multiperiod where representation sets are not the same\n // across periods\n var name = playlist.attributes.id + (playlist.attributes.lang || '');\n\n if (!acc[name]) {\n // First Period\n acc[name] = playlist;\n acc[name].attributes.timelineStarts = [];\n } else {\n // Subsequent Periods\n if (playlist.segments) {\n var _acc$name$segments;\n\n // first segment of subsequent periods signal a discontinuity\n if (playlist.segments[0]) {\n playlist.segments[0].discontinuity = true;\n }\n\n (_acc$name$segments = acc[name].segments).push.apply(_acc$name$segments, playlist.segments);\n } // bubble up contentProtection, this assumes all DRM content\n // has the same contentProtection\n\n\n if (playlist.attributes.contentProtection) {\n acc[name].attributes.contentProtection = playlist.attributes.contentProtection;\n }\n }\n\n acc[name].attributes.timelineStarts.push({\n // Although they represent the same number, it's important to have both to make it\n // compatible with HLS potentially having a similar attribute.\n start: playlist.attributes.periodStart,\n timeline: playlist.attributes.periodStart\n });\n return acc;\n }, {}));\n return mergedPlaylists.map(function (playlist) {\n playlist.discontinuityStarts = findIndexes(playlist.segments || [], 'discontinuity');\n return playlist;\n });\n};\n\nvar addSidxSegmentsToPlaylist = function addSidxSegmentsToPlaylist(playlist, sidxMapping) {\n var sidxKey = generateSidxKey(playlist.sidx);\n var sidxMatch = sidxKey && sidxMapping[sidxKey] && sidxMapping[sidxKey].sidx;\n\n if (sidxMatch) {\n addSidxSegmentsToPlaylist$1(playlist, sidxMatch, playlist.sidx.resolvedUri);\n }\n\n return playlist;\n};\nvar addSidxSegmentsToPlaylists = function addSidxSegmentsToPlaylists(playlists, sidxMapping) {\n if (sidxMapping === void 0) {\n sidxMapping = {};\n }\n\n if (!Object.keys(sidxMapping).length) {\n return playlists;\n }\n\n for (var i in playlists) {\n playlists[i] = addSidxSegmentsToPlaylist(playlists[i], sidxMapping);\n }\n\n return playlists;\n};\nvar formatAudioPlaylist = function formatAudioPlaylist(_ref, isAudioOnly) {\n var _attributes;\n\n var attributes = _ref.attributes,\n segments = _ref.segments,\n sidx = _ref.sidx,\n mediaSequence = _ref.mediaSequence,\n discontinuitySequence = _ref.discontinuitySequence,\n discontinuityStarts = _ref.discontinuityStarts;\n var playlist = {\n attributes: (_attributes = {\n NAME: attributes.id,\n BANDWIDTH: attributes.bandwidth,\n CODECS: attributes.codecs\n }, _attributes['PROGRAM-ID'] = 1, _attributes),\n uri: '',\n endList: attributes.type === 'static',\n timeline: attributes.periodStart,\n resolvedUri: '',\n targetDuration: attributes.duration,\n discontinuitySequence: discontinuitySequence,\n discontinuityStarts: discontinuityStarts,\n timelineStarts: attributes.timelineStarts,\n mediaSequence: mediaSequence,\n segments: segments\n };\n\n if (attributes.contentProtection) {\n playlist.contentProtection = attributes.contentProtection;\n }\n\n if (sidx) {\n playlist.sidx = sidx;\n }\n\n if (isAudioOnly) {\n playlist.attributes.AUDIO = 'audio';\n playlist.attributes.SUBTITLES = 'subs';\n }\n\n return playlist;\n};\nvar formatVttPlaylist = function formatVttPlaylist(_ref2) {\n var _m3u8Attributes;\n\n var attributes = _ref2.attributes,\n segments = _ref2.segments,\n mediaSequence = _ref2.mediaSequence,\n discontinuityStarts = _ref2.discontinuityStarts,\n discontinuitySequence = _ref2.discontinuitySequence;\n\n if (typeof segments === 'undefined') {\n // vtt tracks may use single file in BaseURL\n segments = [{\n uri: attributes.baseUrl,\n timeline: attributes.periodStart,\n resolvedUri: attributes.baseUrl || '',\n duration: attributes.sourceDuration,\n number: 0\n }]; // targetDuration should be the same duration as the only segment\n\n attributes.duration = attributes.sourceDuration;\n }\n\n var m3u8Attributes = (_m3u8Attributes = {\n NAME: attributes.id,\n BANDWIDTH: attributes.bandwidth\n }, _m3u8Attributes['PROGRAM-ID'] = 1, _m3u8Attributes);\n\n if (attributes.codecs) {\n m3u8Attributes.CODECS = attributes.codecs;\n }\n\n return {\n attributes: m3u8Attributes,\n uri: '',\n endList: attributes.type === 'static',\n timeline: attributes.periodStart,\n resolvedUri: attributes.baseUrl || '',\n targetDuration: attributes.duration,\n timelineStarts: attributes.timelineStarts,\n discontinuityStarts: discontinuityStarts,\n discontinuitySequence: discontinuitySequence,\n mediaSequence: mediaSequence,\n segments: segments\n };\n};\nvar organizeAudioPlaylists = function organizeAudioPlaylists(playlists, sidxMapping, isAudioOnly) {\n if (sidxMapping === void 0) {\n sidxMapping = {};\n }\n\n if (isAudioOnly === void 0) {\n isAudioOnly = false;\n }\n\n var mainPlaylist;\n var formattedPlaylists = playlists.reduce(function (a, playlist) {\n var role = playlist.attributes.role && playlist.attributes.role.value || '';\n var language = playlist.attributes.lang || '';\n var label = playlist.attributes.label || 'main';\n\n if (language && !playlist.attributes.label) {\n var roleLabel = role ? \" (\" + role + \")\" : '';\n label = \"\" + playlist.attributes.lang + roleLabel;\n }\n\n if (!a[label]) {\n a[label] = {\n language: language,\n autoselect: true,\n default: role === 'main',\n playlists: [],\n uri: ''\n };\n }\n\n var formatted = addSidxSegmentsToPlaylist(formatAudioPlaylist(playlist, isAudioOnly), sidxMapping);\n a[label].playlists.push(formatted);\n\n if (typeof mainPlaylist === 'undefined' && role === 'main') {\n mainPlaylist = playlist;\n mainPlaylist.default = true;\n }\n\n return a;\n }, {}); // if no playlists have role \"main\", mark the first as main\n\n if (!mainPlaylist) {\n var firstLabel = Object.keys(formattedPlaylists)[0];\n formattedPlaylists[firstLabel].default = true;\n }\n\n return formattedPlaylists;\n};\nvar organizeVttPlaylists = function organizeVttPlaylists(playlists, sidxMapping) {\n if (sidxMapping === void 0) {\n sidxMapping = {};\n }\n\n return playlists.reduce(function (a, playlist) {\n var label = playlist.attributes.lang || 'text';\n\n if (!a[label]) {\n a[label] = {\n language: label,\n default: false,\n autoselect: false,\n playlists: [],\n uri: ''\n };\n }\n\n a[label].playlists.push(addSidxSegmentsToPlaylist(formatVttPlaylist(playlist), sidxMapping));\n return a;\n }, {});\n};\n\nvar organizeCaptionServices = function organizeCaptionServices(captionServices) {\n return captionServices.reduce(function (svcObj, svc) {\n if (!svc) {\n return svcObj;\n }\n\n svc.forEach(function (service) {\n var channel = service.channel,\n language = service.language;\n svcObj[language] = {\n autoselect: false,\n default: false,\n instreamId: channel,\n language: language\n };\n\n if (service.hasOwnProperty('aspectRatio')) {\n svcObj[language].aspectRatio = service.aspectRatio;\n }\n\n if (service.hasOwnProperty('easyReader')) {\n svcObj[language].easyReader = service.easyReader;\n }\n\n if (service.hasOwnProperty('3D')) {\n svcObj[language]['3D'] = service['3D'];\n }\n });\n return svcObj;\n }, {});\n};\n\nvar formatVideoPlaylist = function formatVideoPlaylist(_ref3) {\n var _attributes2;\n\n var attributes = _ref3.attributes,\n segments = _ref3.segments,\n sidx = _ref3.sidx,\n discontinuityStarts = _ref3.discontinuityStarts;\n var playlist = {\n attributes: (_attributes2 = {\n NAME: attributes.id,\n AUDIO: 'audio',\n SUBTITLES: 'subs',\n RESOLUTION: {\n width: attributes.width,\n height: attributes.height\n },\n CODECS: attributes.codecs,\n BANDWIDTH: attributes.bandwidth\n }, _attributes2['PROGRAM-ID'] = 1, _attributes2),\n uri: '',\n endList: attributes.type === 'static',\n timeline: attributes.periodStart,\n resolvedUri: '',\n targetDuration: attributes.duration,\n discontinuityStarts: discontinuityStarts,\n timelineStarts: attributes.timelineStarts,\n segments: segments\n };\n\n if (attributes.contentProtection) {\n playlist.contentProtection = attributes.contentProtection;\n }\n\n if (sidx) {\n playlist.sidx = sidx;\n }\n\n return playlist;\n};\n\nvar videoOnly = function videoOnly(_ref4) {\n var attributes = _ref4.attributes;\n return attributes.mimeType === 'video/mp4' || attributes.mimeType === 'video/webm' || attributes.contentType === 'video';\n};\n\nvar audioOnly = function audioOnly(_ref5) {\n var attributes = _ref5.attributes;\n return attributes.mimeType === 'audio/mp4' || attributes.mimeType === 'audio/webm' || attributes.contentType === 'audio';\n};\n\nvar vttOnly = function vttOnly(_ref6) {\n var attributes = _ref6.attributes;\n return attributes.mimeType === 'text/vtt' || attributes.contentType === 'text';\n};\n/**\n * Contains start and timeline properties denoting a timeline start. For DASH, these will\n * be the same number.\n *\n * @typedef {Object} TimelineStart\n * @property {number} start - the start time of the timeline\n * @property {number} timeline - the timeline number\n */\n\n/**\n * Adds appropriate media and discontinuity sequence values to the segments and playlists.\n *\n * Throughout mpd-parser, the `number` attribute is used in relation to `startNumber`, a\n * DASH specific attribute used in constructing segment URI's from templates. However, from\n * an HLS perspective, the `number` attribute on a segment would be its `mediaSequence`\n * value, which should start at the original media sequence value (or 0) and increment by 1\n * for each segment thereafter. Since DASH's `startNumber` values are independent per\n * period, it doesn't make sense to use it for `number`. Instead, assume everything starts\n * from a 0 mediaSequence value and increment from there.\n *\n * Note that VHS currently doesn't use the `number` property, but it can be helpful for\n * debugging and making sense of the manifest.\n *\n * For live playlists, to account for values increasing in manifests when periods are\n * removed on refreshes, merging logic should be used to update the numbers to their\n * appropriate values (to ensure they're sequential and increasing).\n *\n * @param {Object[]} playlists - the playlists to update\n * @param {TimelineStart[]} timelineStarts - the timeline starts for the manifest\n */\n\n\nvar addMediaSequenceValues = function addMediaSequenceValues(playlists, timelineStarts) {\n // increment all segments sequentially\n playlists.forEach(function (playlist) {\n playlist.mediaSequence = 0;\n playlist.discontinuitySequence = findIndex(timelineStarts, function (_ref7) {\n var timeline = _ref7.timeline;\n return timeline === playlist.timeline;\n });\n\n if (!playlist.segments) {\n return;\n }\n\n playlist.segments.forEach(function (segment, index) {\n segment.number = index;\n });\n });\n};\n/**\n * Given a media group object, flattens all playlists within the media group into a single\n * array.\n *\n * @param {Object} mediaGroupObject - the media group object\n *\n * @return {Object[]}\n * The media group playlists\n */\n\nvar flattenMediaGroupPlaylists = function flattenMediaGroupPlaylists(mediaGroupObject) {\n if (!mediaGroupObject) {\n return [];\n }\n\n return Object.keys(mediaGroupObject).reduce(function (acc, label) {\n var labelContents = mediaGroupObject[label];\n return acc.concat(labelContents.playlists);\n }, []);\n};\nvar toM3u8 = function toM3u8(_ref8) {\n var _mediaGroups;\n\n var dashPlaylists = _ref8.dashPlaylists,\n locations = _ref8.locations,\n _ref8$sidxMapping = _ref8.sidxMapping,\n sidxMapping = _ref8$sidxMapping === void 0 ? {} : _ref8$sidxMapping,\n previousManifest = _ref8.previousManifest;\n\n if (!dashPlaylists.length) {\n return {};\n } // grab all main manifest attributes\n\n\n var _dashPlaylists$0$attr = dashPlaylists[0].attributes,\n duration = _dashPlaylists$0$attr.sourceDuration,\n type = _dashPlaylists$0$attr.type,\n suggestedPresentationDelay = _dashPlaylists$0$attr.suggestedPresentationDelay,\n minimumUpdatePeriod = _dashPlaylists$0$attr.minimumUpdatePeriod;\n var videoPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(videoOnly)).map(formatVideoPlaylist);\n var audioPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(audioOnly));\n var vttPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(vttOnly));\n var captions = dashPlaylists.map(function (playlist) {\n return playlist.attributes.captionServices;\n }).filter(Boolean);\n var manifest = {\n allowCache: true,\n discontinuityStarts: [],\n segments: [],\n endList: true,\n mediaGroups: (_mediaGroups = {\n AUDIO: {},\n VIDEO: {}\n }, _mediaGroups['CLOSED-CAPTIONS'] = {}, _mediaGroups.SUBTITLES = {}, _mediaGroups),\n uri: '',\n duration: duration,\n playlists: addSidxSegmentsToPlaylists(videoPlaylists, sidxMapping)\n };\n\n if (minimumUpdatePeriod >= 0) {\n manifest.minimumUpdatePeriod = minimumUpdatePeriod * 1000;\n }\n\n if (locations) {\n manifest.locations = locations;\n }\n\n if (type === 'dynamic') {\n manifest.suggestedPresentationDelay = suggestedPresentationDelay;\n }\n\n var isAudioOnly = manifest.playlists.length === 0;\n var organizedAudioGroup = audioPlaylists.length ? organizeAudioPlaylists(audioPlaylists, sidxMapping, isAudioOnly) : null;\n var organizedVttGroup = vttPlaylists.length ? organizeVttPlaylists(vttPlaylists, sidxMapping) : null;\n var formattedPlaylists = videoPlaylists.concat(flattenMediaGroupPlaylists(organizedAudioGroup), flattenMediaGroupPlaylists(organizedVttGroup));\n var playlistTimelineStarts = formattedPlaylists.map(function (_ref9) {\n var timelineStarts = _ref9.timelineStarts;\n return timelineStarts;\n });\n manifest.timelineStarts = getUniqueTimelineStarts(playlistTimelineStarts);\n addMediaSequenceValues(formattedPlaylists, manifest.timelineStarts);\n\n if (organizedAudioGroup) {\n manifest.mediaGroups.AUDIO.audio = organizedAudioGroup;\n }\n\n if (organizedVttGroup) {\n manifest.mediaGroups.SUBTITLES.subs = organizedVttGroup;\n }\n\n if (captions.length) {\n manifest.mediaGroups['CLOSED-CAPTIONS'].cc = organizeCaptionServices(captions);\n }\n\n if (previousManifest) {\n return positionManifestOnTimeline({\n oldManifest: previousManifest,\n newManifest: manifest\n });\n }\n\n return manifest;\n};\n\n/**\n * Calculates the R (repetition) value for a live stream (for the final segment\n * in a manifest where the r value is negative 1)\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {number} time\n * current time (typically the total time up until the final segment)\n * @param {number} duration\n * duration property for the given \n *\n * @return {number}\n * R value to reach the end of the given period\n */\nvar getLiveRValue = function getLiveRValue(attributes, time, duration) {\n var NOW = attributes.NOW,\n clientOffset = attributes.clientOffset,\n availabilityStartTime = attributes.availabilityStartTime,\n _attributes$timescale = attributes.timescale,\n timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale,\n _attributes$periodSta = attributes.periodStart,\n periodStart = _attributes$periodSta === void 0 ? 0 : _attributes$periodSta,\n _attributes$minimumUp = attributes.minimumUpdatePeriod,\n minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp;\n var now = (NOW + clientOffset) / 1000;\n var periodStartWC = availabilityStartTime + periodStart;\n var periodEndWC = now + minimumUpdatePeriod;\n var periodDuration = periodEndWC - periodStartWC;\n return Math.ceil((periodDuration * timescale - time) / duration);\n};\n/**\n * Uses information provided by SegmentTemplate.SegmentTimeline to determine segment\n * timing and duration\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {Object[]} segmentTimeline\n * List of objects representing the attributes of each S element contained within\n *\n * @return {{number: number, duration: number, time: number, timeline: number}[]}\n * List of Objects with segment timing and duration info\n */\n\n\nvar parseByTimeline = function parseByTimeline(attributes, segmentTimeline) {\n var type = attributes.type,\n _attributes$minimumUp2 = attributes.minimumUpdatePeriod,\n minimumUpdatePeriod = _attributes$minimumUp2 === void 0 ? 0 : _attributes$minimumUp2,\n _attributes$media = attributes.media,\n media = _attributes$media === void 0 ? '' : _attributes$media,\n sourceDuration = attributes.sourceDuration,\n _attributes$timescale2 = attributes.timescale,\n timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2,\n _attributes$startNumb = attributes.startNumber,\n startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb,\n timeline = attributes.periodStart;\n var segments = [];\n var time = -1;\n\n for (var sIndex = 0; sIndex < segmentTimeline.length; sIndex++) {\n var S = segmentTimeline[sIndex];\n var duration = S.d;\n var repeat = S.r || 0;\n var segmentTime = S.t || 0;\n\n if (time < 0) {\n // first segment\n time = segmentTime;\n }\n\n if (segmentTime && segmentTime > time) {\n // discontinuity\n // TODO: How to handle this type of discontinuity\n // timeline++ here would treat it like HLS discontuity and content would\n // get appended without gap\n // E.G.\n // \n // \n // \n // \n // would have $Time$ values of [0, 1, 2, 5]\n // should this be appened at time positions [0, 1, 2, 3],(#EXT-X-DISCONTINUITY)\n // or [0, 1, 2, gap, gap, 5]? (#EXT-X-GAP)\n // does the value of sourceDuration consider this when calculating arbitrary\n // negative @r repeat value?\n // E.G. Same elements as above with this added at the end\n // \n // with a sourceDuration of 10\n // Would the 2 gaps be included in the time duration calculations resulting in\n // 8 segments with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9] or 10 segments\n // with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9, 10, 11] ?\n time = segmentTime;\n }\n\n var count = void 0;\n\n if (repeat < 0) {\n var nextS = sIndex + 1;\n\n if (nextS === segmentTimeline.length) {\n // last segment\n if (type === 'dynamic' && minimumUpdatePeriod > 0 && media.indexOf('$Number$') > 0) {\n count = getLiveRValue(attributes, time, duration);\n } else {\n // TODO: This may be incorrect depending on conclusion of TODO above\n count = (sourceDuration * timescale - time) / duration;\n }\n } else {\n count = (segmentTimeline[nextS].t - time) / duration;\n }\n } else {\n count = repeat + 1;\n }\n\n var end = startNumber + segments.length + count;\n var number = startNumber + segments.length;\n\n while (number < end) {\n segments.push({\n number: number,\n duration: duration / timescale,\n time: time,\n timeline: timeline\n });\n time += duration;\n number++;\n }\n }\n\n return segments;\n};\n\nvar identifierPattern = /\\$([A-z]*)(?:(%0)([0-9]+)d)?\\$/g;\n/**\n * Replaces template identifiers with corresponding values. To be used as the callback\n * for String.prototype.replace\n *\n * @name replaceCallback\n * @function\n * @param {string} match\n * Entire match of identifier\n * @param {string} identifier\n * Name of matched identifier\n * @param {string} format\n * Format tag string. Its presence indicates that padding is expected\n * @param {string} width\n * Desired length of the replaced value. Values less than this width shall be left\n * zero padded\n * @return {string}\n * Replacement for the matched identifier\n */\n\n/**\n * Returns a function to be used as a callback for String.prototype.replace to replace\n * template identifiers\n *\n * @param {Obect} values\n * Object containing values that shall be used to replace known identifiers\n * @param {number} values.RepresentationID\n * Value of the Representation@id attribute\n * @param {number} values.Number\n * Number of the corresponding segment\n * @param {number} values.Bandwidth\n * Value of the Representation@bandwidth attribute.\n * @param {number} values.Time\n * Timestamp value of the corresponding segment\n * @return {replaceCallback}\n * Callback to be used with String.prototype.replace to replace identifiers\n */\n\nvar identifierReplacement = function identifierReplacement(values) {\n return function (match, identifier, format, width) {\n if (match === '$$') {\n // escape sequence\n return '$';\n }\n\n if (typeof values[identifier] === 'undefined') {\n return match;\n }\n\n var value = '' + values[identifier];\n\n if (identifier === 'RepresentationID') {\n // Format tag shall not be present with RepresentationID\n return value;\n }\n\n if (!format) {\n width = 1;\n } else {\n width = parseInt(width, 10);\n }\n\n if (value.length >= width) {\n return value;\n }\n\n return \"\" + new Array(width - value.length + 1).join('0') + value;\n };\n};\n/**\n * Constructs a segment url from a template string\n *\n * @param {string} url\n * Template string to construct url from\n * @param {Obect} values\n * Object containing values that shall be used to replace known identifiers\n * @param {number} values.RepresentationID\n * Value of the Representation@id attribute\n * @param {number} values.Number\n * Number of the corresponding segment\n * @param {number} values.Bandwidth\n * Value of the Representation@bandwidth attribute.\n * @param {number} values.Time\n * Timestamp value of the corresponding segment\n * @return {string}\n * Segment url with identifiers replaced\n */\n\nvar constructTemplateUrl = function constructTemplateUrl(url, values) {\n return url.replace(identifierPattern, identifierReplacement(values));\n};\n/**\n * Generates a list of objects containing timing and duration information about each\n * segment needed to generate segment uris and the complete segment object\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {Object[]|undefined} segmentTimeline\n * List of objects representing the attributes of each S element contained within\n * the SegmentTimeline element\n * @return {{number: number, duration: number, time: number, timeline: number}[]}\n * List of Objects with segment timing and duration info\n */\n\nvar parseTemplateInfo = function parseTemplateInfo(attributes, segmentTimeline) {\n if (!attributes.duration && !segmentTimeline) {\n // if neither @duration or SegmentTimeline are present, then there shall be exactly\n // one media segment\n return [{\n number: attributes.startNumber || 1,\n duration: attributes.sourceDuration,\n time: 0,\n timeline: attributes.periodStart\n }];\n }\n\n if (attributes.duration) {\n return parseByDuration(attributes);\n }\n\n return parseByTimeline(attributes, segmentTimeline);\n};\n/**\n * Generates a list of segments using information provided by the SegmentTemplate element\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {Object[]|undefined} segmentTimeline\n * List of objects representing the attributes of each S element contained within\n * the SegmentTimeline element\n * @return {Object[]}\n * List of segment objects\n */\n\nvar segmentsFromTemplate = function segmentsFromTemplate(attributes, segmentTimeline) {\n var templateValues = {\n RepresentationID: attributes.id,\n Bandwidth: attributes.bandwidth || 0\n };\n var _attributes$initializ = attributes.initialization,\n initialization = _attributes$initializ === void 0 ? {\n sourceURL: '',\n range: ''\n } : _attributes$initializ;\n var mapSegment = urlTypeToSegment({\n baseUrl: attributes.baseUrl,\n source: constructTemplateUrl(initialization.sourceURL, templateValues),\n range: initialization.range\n });\n var segments = parseTemplateInfo(attributes, segmentTimeline);\n return segments.map(function (segment) {\n templateValues.Number = segment.number;\n templateValues.Time = segment.time;\n var uri = constructTemplateUrl(attributes.media || '', templateValues); // See DASH spec section 5.3.9.2.2\n // - if timescale isn't present on any level, default to 1.\n\n var timescale = attributes.timescale || 1; // - if presentationTimeOffset isn't present on any level, default to 0\n\n var presentationTimeOffset = attributes.presentationTimeOffset || 0;\n var presentationTime = // Even if the @t attribute is not specified for the segment, segment.time is\n // calculated in mpd-parser prior to this, so it's assumed to be available.\n attributes.periodStart + (segment.time - presentationTimeOffset) / timescale;\n var map = {\n uri: uri,\n timeline: segment.timeline,\n duration: segment.duration,\n resolvedUri: resolveUrl(attributes.baseUrl || '', uri),\n map: mapSegment,\n number: segment.number,\n presentationTime: presentationTime\n };\n return map;\n });\n};\n\n/**\n * Converts a (of type URLType from the DASH spec 5.3.9.2 Table 14)\n * to an object that matches the output of a segment in videojs/mpd-parser\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {Object} segmentUrl\n * node to translate into a segment object\n * @return {Object} translated segment object\n */\n\nvar SegmentURLToSegmentObject = function SegmentURLToSegmentObject(attributes, segmentUrl) {\n var baseUrl = attributes.baseUrl,\n _attributes$initializ = attributes.initialization,\n initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ;\n var initSegment = urlTypeToSegment({\n baseUrl: baseUrl,\n source: initialization.sourceURL,\n range: initialization.range\n });\n var segment = urlTypeToSegment({\n baseUrl: baseUrl,\n source: segmentUrl.media,\n range: segmentUrl.mediaRange\n });\n segment.map = initSegment;\n return segment;\n};\n/**\n * Generates a list of segments using information provided by the SegmentList element\n * SegmentList (DASH SPEC Section 5.3.9.3.2) contains a set of nodes. Each\n * node should be translated into segment.\n *\n * @param {Object} attributes\n * Object containing all inherited attributes from parent elements with attribute\n * names as keys\n * @param {Object[]|undefined} segmentTimeline\n * List of objects representing the attributes of each S element contained within\n * the SegmentTimeline element\n * @return {Object.} list of segments\n */\n\n\nvar segmentsFromList = function segmentsFromList(attributes, segmentTimeline) {\n var duration = attributes.duration,\n _attributes$segmentUr = attributes.segmentUrls,\n segmentUrls = _attributes$segmentUr === void 0 ? [] : _attributes$segmentUr,\n periodStart = attributes.periodStart; // Per spec (5.3.9.2.1) no way to determine segment duration OR\n // if both SegmentTimeline and @duration are defined, it is outside of spec.\n\n if (!duration && !segmentTimeline || duration && segmentTimeline) {\n throw new Error(errors.SEGMENT_TIME_UNSPECIFIED);\n }\n\n var segmentUrlMap = segmentUrls.map(function (segmentUrlObject) {\n return SegmentURLToSegmentObject(attributes, segmentUrlObject);\n });\n var segmentTimeInfo;\n\n if (duration) {\n segmentTimeInfo = parseByDuration(attributes);\n }\n\n if (segmentTimeline) {\n segmentTimeInfo = parseByTimeline(attributes, segmentTimeline);\n }\n\n var segments = segmentTimeInfo.map(function (segmentTime, index) {\n if (segmentUrlMap[index]) {\n var segment = segmentUrlMap[index]; // See DASH spec section 5.3.9.2.2\n // - if timescale isn't present on any level, default to 1.\n\n var timescale = attributes.timescale || 1; // - if presentationTimeOffset isn't present on any level, default to 0\n\n var presentationTimeOffset = attributes.presentationTimeOffset || 0;\n segment.timeline = segmentTime.timeline;\n segment.duration = segmentTime.duration;\n segment.number = segmentTime.number;\n segment.presentationTime = periodStart + (segmentTime.time - presentationTimeOffset) / timescale;\n return segment;\n } // Since we're mapping we should get rid of any blank segments (in case\n // the given SegmentTimeline is handling for more elements than we have\n // SegmentURLs for).\n\n }).filter(function (segment) {\n return segment;\n });\n return segments;\n};\n\nvar generateSegments = function generateSegments(_ref) {\n var attributes = _ref.attributes,\n segmentInfo = _ref.segmentInfo;\n var segmentAttributes;\n var segmentsFn;\n\n if (segmentInfo.template) {\n segmentsFn = segmentsFromTemplate;\n segmentAttributes = merge(attributes, segmentInfo.template);\n } else if (segmentInfo.base) {\n segmentsFn = segmentsFromBase;\n segmentAttributes = merge(attributes, segmentInfo.base);\n } else if (segmentInfo.list) {\n segmentsFn = segmentsFromList;\n segmentAttributes = merge(attributes, segmentInfo.list);\n }\n\n var segmentsInfo = {\n attributes: attributes\n };\n\n if (!segmentsFn) {\n return segmentsInfo;\n }\n\n var segments = segmentsFn(segmentAttributes, segmentInfo.segmentTimeline); // The @duration attribute will be used to determin the playlist's targetDuration which\n // must be in seconds. Since we've generated the segment list, we no longer need\n // @duration to be in @timescale units, so we can convert it here.\n\n if (segmentAttributes.duration) {\n var _segmentAttributes = segmentAttributes,\n duration = _segmentAttributes.duration,\n _segmentAttributes$ti = _segmentAttributes.timescale,\n timescale = _segmentAttributes$ti === void 0 ? 1 : _segmentAttributes$ti;\n segmentAttributes.duration = duration / timescale;\n } else if (segments.length) {\n // if there is no @duration attribute, use the largest segment duration as\n // as target duration\n segmentAttributes.duration = segments.reduce(function (max, segment) {\n return Math.max(max, Math.ceil(segment.duration));\n }, 0);\n } else {\n segmentAttributes.duration = 0;\n }\n\n segmentsInfo.attributes = segmentAttributes;\n segmentsInfo.segments = segments; // This is a sidx box without actual segment information\n\n if (segmentInfo.base && segmentAttributes.indexRange) {\n segmentsInfo.sidx = segments[0];\n segmentsInfo.segments = [];\n }\n\n return segmentsInfo;\n};\nvar toPlaylists = function toPlaylists(representations) {\n return representations.map(generateSegments);\n};\n\nvar findChildren = function findChildren(element, name) {\n return from(element.childNodes).filter(function (_ref) {\n var tagName = _ref.tagName;\n return tagName === name;\n });\n};\nvar getContent = function getContent(element) {\n return element.textContent.trim();\n};\n\nvar parseDuration = function parseDuration(str) {\n var SECONDS_IN_YEAR = 365 * 24 * 60 * 60;\n var SECONDS_IN_MONTH = 30 * 24 * 60 * 60;\n var SECONDS_IN_DAY = 24 * 60 * 60;\n var SECONDS_IN_HOUR = 60 * 60;\n var SECONDS_IN_MIN = 60; // P10Y10M10DT10H10M10.1S\n\n var durationRegex = /P(?:(\\d*)Y)?(?:(\\d*)M)?(?:(\\d*)D)?(?:T(?:(\\d*)H)?(?:(\\d*)M)?(?:([\\d.]*)S)?)?/;\n var match = durationRegex.exec(str);\n\n if (!match) {\n return 0;\n }\n\n var _match$slice = match.slice(1),\n year = _match$slice[0],\n month = _match$slice[1],\n day = _match$slice[2],\n hour = _match$slice[3],\n minute = _match$slice[4],\n second = _match$slice[5];\n\n return parseFloat(year || 0) * SECONDS_IN_YEAR + parseFloat(month || 0) * SECONDS_IN_MONTH + parseFloat(day || 0) * SECONDS_IN_DAY + parseFloat(hour || 0) * SECONDS_IN_HOUR + parseFloat(minute || 0) * SECONDS_IN_MIN + parseFloat(second || 0);\n};\nvar parseDate = function parseDate(str) {\n // Date format without timezone according to ISO 8601\n // YYY-MM-DDThh:mm:ss.ssssss\n var dateRegex = /^\\d+-\\d+-\\d+T\\d+:\\d+:\\d+(\\.\\d+)?$/; // If the date string does not specifiy a timezone, we must specifiy UTC. This is\n // expressed by ending with 'Z'\n\n if (dateRegex.test(str)) {\n str += 'Z';\n }\n\n return Date.parse(str);\n};\n\nvar parsers = {\n /**\n * Specifies the duration of the entire Media Presentation. Format is a duration string\n * as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The duration in seconds\n */\n mediaPresentationDuration: function mediaPresentationDuration(value) {\n return parseDuration(value);\n },\n\n /**\n * Specifies the Segment availability start time for all Segments referred to in this\n * MPD. For a dynamic manifest, it specifies the anchor for the earliest availability\n * time. Format is a date string as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The date as seconds from unix epoch\n */\n availabilityStartTime: function availabilityStartTime(value) {\n return parseDate(value) / 1000;\n },\n\n /**\n * Specifies the smallest period between potential changes to the MPD. Format is a\n * duration string as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The duration in seconds\n */\n minimumUpdatePeriod: function minimumUpdatePeriod(value) {\n return parseDuration(value);\n },\n\n /**\n * Specifies the suggested presentation delay. Format is a\n * duration string as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The duration in seconds\n */\n suggestedPresentationDelay: function suggestedPresentationDelay(value) {\n return parseDuration(value);\n },\n\n /**\n * specifices the type of mpd. Can be either \"static\" or \"dynamic\"\n *\n * @param {string} value\n * value of attribute as a string\n *\n * @return {string}\n * The type as a string\n */\n type: function type(value) {\n return value;\n },\n\n /**\n * Specifies the duration of the smallest time shifting buffer for any Representation\n * in the MPD. Format is a duration string as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The duration in seconds\n */\n timeShiftBufferDepth: function timeShiftBufferDepth(value) {\n return parseDuration(value);\n },\n\n /**\n * Specifies the PeriodStart time of the Period relative to the availabilityStarttime.\n * Format is a duration string as specified in ISO 8601\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The duration in seconds\n */\n start: function start(value) {\n return parseDuration(value);\n },\n\n /**\n * Specifies the width of the visual presentation\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed width\n */\n width: function width(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the height of the visual presentation\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed height\n */\n height: function height(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the bitrate of the representation\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed bandwidth\n */\n bandwidth: function bandwidth(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the number of the first Media Segment in this Representation in the Period\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed number\n */\n startNumber: function startNumber(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the timescale in units per seconds\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed timescale\n */\n timescale: function timescale(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the presentationTimeOffset.\n *\n * @param {string} value\n * value of the attribute as a string\n *\n * @return {number}\n * The parsed presentationTimeOffset\n */\n presentationTimeOffset: function presentationTimeOffset(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the constant approximate Segment duration\n * NOTE: The element also contains an @duration attribute. This duration\n * specifies the duration of the Period. This attribute is currently not\n * supported by the rest of the parser, however we still check for it to prevent\n * errors.\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed duration\n */\n duration: function duration(value) {\n var parsedValue = parseInt(value, 10);\n\n if (isNaN(parsedValue)) {\n return parseDuration(value);\n }\n\n return parsedValue;\n },\n\n /**\n * Specifies the Segment duration, in units of the value of the @timescale.\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed duration\n */\n d: function d(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the MPD start time, in @timescale units, the first Segment in the series\n * starts relative to the beginning of the Period\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed time\n */\n t: function t(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Specifies the repeat count of the number of following contiguous Segments with the\n * same duration expressed by the value of @d\n *\n * @param {string} value\n * value of attribute as a string\n * @return {number}\n * The parsed number\n */\n r: function r(value) {\n return parseInt(value, 10);\n },\n\n /**\n * Default parser for all other attributes. Acts as a no-op and just returns the value\n * as a string\n *\n * @param {string} value\n * value of attribute as a string\n * @return {string}\n * Unparsed value\n */\n DEFAULT: function DEFAULT(value) {\n return value;\n }\n};\n/**\n * Gets all the attributes and values of the provided node, parses attributes with known\n * types, and returns an object with attribute names mapped to values.\n *\n * @param {Node} el\n * The node to parse attributes from\n * @return {Object}\n * Object with all attributes of el parsed\n */\n\nvar parseAttributes = function parseAttributes(el) {\n if (!(el && el.attributes)) {\n return {};\n }\n\n return from(el.attributes).reduce(function (a, e) {\n var parseFn = parsers[e.name] || parsers.DEFAULT;\n a[e.name] = parseFn(e.value);\n return a;\n }, {});\n};\n\nvar keySystemsMap = {\n 'urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b': 'org.w3.clearkey',\n 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed': 'com.widevine.alpha',\n 'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95': 'com.microsoft.playready',\n 'urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb': 'com.adobe.primetime'\n};\n/**\n * Builds a list of urls that is the product of the reference urls and BaseURL values\n *\n * @param {string[]} referenceUrls\n * List of reference urls to resolve to\n * @param {Node[]} baseUrlElements\n * List of BaseURL nodes from the mpd\n * @return {string[]}\n * List of resolved urls\n */\n\nvar buildBaseUrls = function buildBaseUrls(referenceUrls, baseUrlElements) {\n if (!baseUrlElements.length) {\n return referenceUrls;\n }\n\n return flatten(referenceUrls.map(function (reference) {\n return baseUrlElements.map(function (baseUrlElement) {\n return resolveUrl(reference, getContent(baseUrlElement));\n });\n }));\n};\n/**\n * Contains all Segment information for its containing AdaptationSet\n *\n * @typedef {Object} SegmentInformation\n * @property {Object|undefined} template\n * Contains the attributes for the SegmentTemplate node\n * @property {Object[]|undefined} segmentTimeline\n * Contains a list of atrributes for each S node within the SegmentTimeline node\n * @property {Object|undefined} list\n * Contains the attributes for the SegmentList node\n * @property {Object|undefined} base\n * Contains the attributes for the SegmentBase node\n */\n\n/**\n * Returns all available Segment information contained within the AdaptationSet node\n *\n * @param {Node} adaptationSet\n * The AdaptationSet node to get Segment information from\n * @return {SegmentInformation}\n * The Segment information contained within the provided AdaptationSet\n */\n\nvar getSegmentInformation = function getSegmentInformation(adaptationSet) {\n var segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0];\n var segmentList = findChildren(adaptationSet, 'SegmentList')[0];\n var segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL').map(function (s) {\n return merge({\n tag: 'SegmentURL'\n }, parseAttributes(s));\n });\n var segmentBase = findChildren(adaptationSet, 'SegmentBase')[0];\n var segmentTimelineParentNode = segmentList || segmentTemplate;\n var segmentTimeline = segmentTimelineParentNode && findChildren(segmentTimelineParentNode, 'SegmentTimeline')[0];\n var segmentInitializationParentNode = segmentList || segmentBase || segmentTemplate;\n var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; // SegmentTemplate is handled slightly differently, since it can have both\n // @initialization and an node. @initialization can be templated,\n // while the node can have a url and range specified. If the has\n // both @initialization and an subelement we opt to override with\n // the node, as this interaction is not defined in the spec.\n\n var template = segmentTemplate && parseAttributes(segmentTemplate);\n\n if (template && segmentInitialization) {\n template.initialization = segmentInitialization && parseAttributes(segmentInitialization);\n } else if (template && template.initialization) {\n // If it is @initialization we convert it to an object since this is the format that\n // later functions will rely on for the initialization segment. This is only valid\n // for \n template.initialization = {\n sourceURL: template.initialization\n };\n }\n\n var segmentInfo = {\n template: template,\n segmentTimeline: segmentTimeline && findChildren(segmentTimeline, 'S').map(function (s) {\n return parseAttributes(s);\n }),\n list: segmentList && merge(parseAttributes(segmentList), {\n segmentUrls: segmentUrls,\n initialization: parseAttributes(segmentInitialization)\n }),\n base: segmentBase && merge(parseAttributes(segmentBase), {\n initialization: parseAttributes(segmentInitialization)\n })\n };\n Object.keys(segmentInfo).forEach(function (key) {\n if (!segmentInfo[key]) {\n delete segmentInfo[key];\n }\n });\n return segmentInfo;\n};\n/**\n * Contains Segment information and attributes needed to construct a Playlist object\n * from a Representation\n *\n * @typedef {Object} RepresentationInformation\n * @property {SegmentInformation} segmentInfo\n * Segment information for this Representation\n * @property {Object} attributes\n * Inherited attributes for this Representation\n */\n\n/**\n * Maps a Representation node to an object containing Segment information and attributes\n *\n * @name inheritBaseUrlsCallback\n * @function\n * @param {Node} representation\n * Representation node from the mpd\n * @return {RepresentationInformation}\n * Representation information needed to construct a Playlist object\n */\n\n/**\n * Returns a callback for Array.prototype.map for mapping Representation nodes to\n * Segment information and attributes using inherited BaseURL nodes.\n *\n * @param {Object} adaptationSetAttributes\n * Contains attributes inherited by the AdaptationSet\n * @param {string[]} adaptationSetBaseUrls\n * Contains list of resolved base urls inherited by the AdaptationSet\n * @param {SegmentInformation} adaptationSetSegmentInfo\n * Contains Segment information for the AdaptationSet\n * @return {inheritBaseUrlsCallback}\n * Callback map function\n */\n\nvar inheritBaseUrls = function inheritBaseUrls(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) {\n return function (representation) {\n var repBaseUrlElements = findChildren(representation, 'BaseURL');\n var repBaseUrls = buildBaseUrls(adaptationSetBaseUrls, repBaseUrlElements);\n var attributes = merge(adaptationSetAttributes, parseAttributes(representation));\n var representationSegmentInfo = getSegmentInformation(representation);\n return repBaseUrls.map(function (baseUrl) {\n return {\n segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo),\n attributes: merge(attributes, {\n baseUrl: baseUrl\n })\n };\n });\n };\n};\n/**\n * Tranforms a series of content protection nodes to\n * an object containing pssh data by key system\n *\n * @param {Node[]} contentProtectionNodes\n * Content protection nodes\n * @return {Object}\n * Object containing pssh data by key system\n */\n\nvar generateKeySystemInformation = function generateKeySystemInformation(contentProtectionNodes) {\n return contentProtectionNodes.reduce(function (acc, node) {\n var attributes = parseAttributes(node);\n var keySystem = keySystemsMap[attributes.schemeIdUri];\n\n if (keySystem) {\n acc[keySystem] = {\n attributes: attributes\n };\n var psshNode = findChildren(node, 'cenc:pssh')[0];\n\n if (psshNode) {\n var pssh = getContent(psshNode);\n var psshBuffer = pssh && decodeB64ToUint8Array(pssh);\n acc[keySystem].pssh = psshBuffer;\n }\n }\n\n return acc;\n }, {});\n}; // defined in ANSI_SCTE 214-1 2016\n\n\nvar parseCaptionServiceMetadata = function parseCaptionServiceMetadata(service) {\n // 608 captions\n if (service.schemeIdUri === 'urn:scte:dash:cc:cea-608:2015') {\n var values = typeof service.value !== 'string' ? [] : service.value.split(';');\n return values.map(function (value) {\n var channel;\n var language; // default language to value\n\n language = value;\n\n if (/^CC\\d=/.test(value)) {\n var _value$split = value.split('=');\n\n channel = _value$split[0];\n language = _value$split[1];\n } else if (/^CC\\d$/.test(value)) {\n channel = value;\n }\n\n return {\n channel: channel,\n language: language\n };\n });\n } else if (service.schemeIdUri === 'urn:scte:dash:cc:cea-708:2015') {\n var _values = typeof service.value !== 'string' ? [] : service.value.split(';');\n\n return _values.map(function (value) {\n var flags = {\n // service or channel number 1-63\n 'channel': undefined,\n // language is a 3ALPHA per ISO 639.2/B\n // field is required\n 'language': undefined,\n // BIT 1/0 or ?\n // default value is 1, meaning 16:9 aspect ratio, 0 is 4:3, ? is unknown\n 'aspectRatio': 1,\n // BIT 1/0\n // easy reader flag indicated the text is tailed to the needs of beginning readers\n // default 0, or off\n 'easyReader': 0,\n // BIT 1/0\n // If 3d metadata is present (CEA-708.1) then 1\n // default 0\n '3D': 0\n };\n\n if (/=/.test(value)) {\n var _value$split2 = value.split('='),\n channel = _value$split2[0],\n _value$split2$ = _value$split2[1],\n opts = _value$split2$ === void 0 ? '' : _value$split2$;\n\n flags.channel = channel;\n flags.language = value;\n opts.split(',').forEach(function (opt) {\n var _opt$split = opt.split(':'),\n name = _opt$split[0],\n val = _opt$split[1];\n\n if (name === 'lang') {\n flags.language = val; // er for easyReadery\n } else if (name === 'er') {\n flags.easyReader = Number(val); // war for wide aspect ratio\n } else if (name === 'war') {\n flags.aspectRatio = Number(val);\n } else if (name === '3D') {\n flags['3D'] = Number(val);\n }\n });\n } else {\n flags.language = value;\n }\n\n if (flags.channel) {\n flags.channel = 'SERVICE' + flags.channel;\n }\n\n return flags;\n });\n }\n};\n/**\n * Maps an AdaptationSet node to a list of Representation information objects\n *\n * @name toRepresentationsCallback\n * @function\n * @param {Node} adaptationSet\n * AdaptationSet node from the mpd\n * @return {RepresentationInformation[]}\n * List of objects containing Representaion information\n */\n\n/**\n * Returns a callback for Array.prototype.map for mapping AdaptationSet nodes to a list of\n * Representation information objects\n *\n * @param {Object} periodAttributes\n * Contains attributes inherited by the Period\n * @param {string[]} periodBaseUrls\n * Contains list of resolved base urls inherited by the Period\n * @param {string[]} periodSegmentInfo\n * Contains Segment Information at the period level\n * @return {toRepresentationsCallback}\n * Callback map function\n */\n\nvar toRepresentations = function toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo) {\n return function (adaptationSet) {\n var adaptationSetAttributes = parseAttributes(adaptationSet);\n var adaptationSetBaseUrls = buildBaseUrls(periodBaseUrls, findChildren(adaptationSet, 'BaseURL'));\n var role = findChildren(adaptationSet, 'Role')[0];\n var roleAttributes = {\n role: parseAttributes(role)\n };\n var attrs = merge(periodAttributes, adaptationSetAttributes, roleAttributes);\n var accessibility = findChildren(adaptationSet, 'Accessibility')[0];\n var captionServices = parseCaptionServiceMetadata(parseAttributes(accessibility));\n\n if (captionServices) {\n attrs = merge(attrs, {\n captionServices: captionServices\n });\n }\n\n var label = findChildren(adaptationSet, 'Label')[0];\n\n if (label && label.childNodes.length) {\n var labelVal = label.childNodes[0].nodeValue.trim();\n attrs = merge(attrs, {\n label: labelVal\n });\n }\n\n var contentProtection = generateKeySystemInformation(findChildren(adaptationSet, 'ContentProtection'));\n\n if (Object.keys(contentProtection).length) {\n attrs = merge(attrs, {\n contentProtection: contentProtection\n });\n }\n\n var segmentInfo = getSegmentInformation(adaptationSet);\n var representations = findChildren(adaptationSet, 'Representation');\n var adaptationSetSegmentInfo = merge(periodSegmentInfo, segmentInfo);\n return flatten(representations.map(inheritBaseUrls(attrs, adaptationSetBaseUrls, adaptationSetSegmentInfo)));\n };\n};\n/**\n * Contains all period information for mapping nodes onto adaptation sets.\n *\n * @typedef {Object} PeriodInformation\n * @property {Node} period.node\n * Period node from the mpd\n * @property {Object} period.attributes\n * Parsed period attributes from node plus any added\n */\n\n/**\n * Maps a PeriodInformation object to a list of Representation information objects for all\n * AdaptationSet nodes contained within the Period.\n *\n * @name toAdaptationSetsCallback\n * @function\n * @param {PeriodInformation} period\n * Period object containing necessary period information\n * @param {number} periodStart\n * Start time of the Period within the mpd\n * @return {RepresentationInformation[]}\n * List of objects containing Representaion information\n */\n\n/**\n * Returns a callback for Array.prototype.map for mapping Period nodes to a list of\n * Representation information objects\n *\n * @param {Object} mpdAttributes\n * Contains attributes inherited by the mpd\n * @param {string[]} mpdBaseUrls\n * Contains list of resolved base urls inherited by the mpd\n * @return {toAdaptationSetsCallback}\n * Callback map function\n */\n\nvar toAdaptationSets = function toAdaptationSets(mpdAttributes, mpdBaseUrls) {\n return function (period, index) {\n var periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period.node, 'BaseURL'));\n var periodAttributes = merge(mpdAttributes, {\n periodStart: period.attributes.start\n });\n\n if (typeof period.attributes.duration === 'number') {\n periodAttributes.periodDuration = period.attributes.duration;\n }\n\n var adaptationSets = findChildren(period.node, 'AdaptationSet');\n var periodSegmentInfo = getSegmentInformation(period.node);\n return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo)));\n };\n};\n/**\n * Gets Period@start property for a given period.\n *\n * @param {Object} options\n * Options object\n * @param {Object} options.attributes\n * Period attributes\n * @param {Object} [options.priorPeriodAttributes]\n * Prior period attributes (if prior period is available)\n * @param {string} options.mpdType\n * The MPD@type these periods came from\n * @return {number|null}\n * The period start, or null if it's an early available period or error\n */\n\nvar getPeriodStart = function getPeriodStart(_ref) {\n var attributes = _ref.attributes,\n priorPeriodAttributes = _ref.priorPeriodAttributes,\n mpdType = _ref.mpdType;\n\n // Summary of period start time calculation from DASH spec section 5.3.2.1\n //\n // A period's start is the first period's start + time elapsed after playing all\n // prior periods to this one. Periods continue one after the other in time (without\n // gaps) until the end of the presentation.\n //\n // The value of Period@start should be:\n // 1. if Period@start is present: value of Period@start\n // 2. if previous period exists and it has @duration: previous Period@start +\n // previous Period@duration\n // 3. if this is first period and MPD@type is 'static': 0\n // 4. in all other cases, consider the period an \"early available period\" (note: not\n // currently supported)\n // (1)\n if (typeof attributes.start === 'number') {\n return attributes.start;\n } // (2)\n\n\n if (priorPeriodAttributes && typeof priorPeriodAttributes.start === 'number' && typeof priorPeriodAttributes.duration === 'number') {\n return priorPeriodAttributes.start + priorPeriodAttributes.duration;\n } // (3)\n\n\n if (!priorPeriodAttributes && mpdType === 'static') {\n return 0;\n } // (4)\n // There is currently no logic for calculating the Period@start value if there is\n // no Period@start or prior Period@start and Period@duration available. This is not made\n // explicit by the DASH interop guidelines or the DASH spec, however, since there's\n // nothing about any other resolution strategies, it's implied. Thus, this case should\n // be considered an early available period, or error, and null should suffice for both\n // of those cases.\n\n\n return null;\n};\n/**\n * Traverses the mpd xml tree to generate a list of Representation information objects\n * that have inherited attributes from parent nodes\n *\n * @param {Node} mpd\n * The root node of the mpd\n * @param {Object} options\n * Available options for inheritAttributes\n * @param {string} options.manifestUri\n * The uri source of the mpd\n * @param {number} options.NOW\n * Current time per DASH IOP. Default is current time in ms since epoch\n * @param {number} options.clientOffset\n * Client time difference from NOW (in milliseconds)\n * @return {RepresentationInformation[]}\n * List of objects containing Representation information\n */\n\nvar inheritAttributes = function inheritAttributes(mpd, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$manifestUri = _options.manifestUri,\n manifestUri = _options$manifestUri === void 0 ? '' : _options$manifestUri,\n _options$NOW = _options.NOW,\n NOW = _options$NOW === void 0 ? Date.now() : _options$NOW,\n _options$clientOffset = _options.clientOffset,\n clientOffset = _options$clientOffset === void 0 ? 0 : _options$clientOffset;\n var periodNodes = findChildren(mpd, 'Period');\n\n if (!periodNodes.length) {\n throw new Error(errors.INVALID_NUMBER_OF_PERIOD);\n }\n\n var locations = findChildren(mpd, 'Location');\n var mpdAttributes = parseAttributes(mpd);\n var mpdBaseUrls = buildBaseUrls([manifestUri], findChildren(mpd, 'BaseURL')); // See DASH spec section 5.3.1.2, Semantics of MPD element. Default type to 'static'.\n\n mpdAttributes.type = mpdAttributes.type || 'static';\n mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0;\n mpdAttributes.NOW = NOW;\n mpdAttributes.clientOffset = clientOffset;\n\n if (locations.length) {\n mpdAttributes.locations = locations.map(getContent);\n }\n\n var periods = []; // Since toAdaptationSets acts on individual periods right now, the simplest approach to\n // adding properties that require looking at prior periods is to parse attributes and add\n // missing ones before toAdaptationSets is called. If more such properties are added, it\n // may be better to refactor toAdaptationSets.\n\n periodNodes.forEach(function (node, index) {\n var attributes = parseAttributes(node); // Use the last modified prior period, as it may contain added information necessary\n // for this period.\n\n var priorPeriod = periods[index - 1];\n attributes.start = getPeriodStart({\n attributes: attributes,\n priorPeriodAttributes: priorPeriod ? priorPeriod.attributes : null,\n mpdType: mpdAttributes.type\n });\n periods.push({\n node: node,\n attributes: attributes\n });\n });\n return {\n locations: mpdAttributes.locations,\n representationInfo: flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls)))\n };\n};\n\nvar stringToMpdXml = function stringToMpdXml(manifestString) {\n if (manifestString === '') {\n throw new Error(errors.DASH_EMPTY_MANIFEST);\n }\n\n var parser = new DOMParser();\n var xml;\n var mpd;\n\n try {\n xml = parser.parseFromString(manifestString, 'application/xml');\n mpd = xml && xml.documentElement.tagName === 'MPD' ? xml.documentElement : null;\n } catch (e) {// ie 11 throwsw on invalid xml\n }\n\n if (!mpd || mpd && mpd.getElementsByTagName('parsererror').length > 0) {\n throw new Error(errors.DASH_INVALID_XML);\n }\n\n return mpd;\n};\n\n/**\n * Parses the manifest for a UTCTiming node, returning the nodes attributes if found\n *\n * @param {string} mpd\n * XML string of the MPD manifest\n * @return {Object|null}\n * Attributes of UTCTiming node specified in the manifest. Null if none found\n */\n\nvar parseUTCTimingScheme = function parseUTCTimingScheme(mpd) {\n var UTCTimingNode = findChildren(mpd, 'UTCTiming')[0];\n\n if (!UTCTimingNode) {\n return null;\n }\n\n var attributes = parseAttributes(UTCTimingNode);\n\n switch (attributes.schemeIdUri) {\n case 'urn:mpeg:dash:utc:http-head:2014':\n case 'urn:mpeg:dash:utc:http-head:2012':\n attributes.method = 'HEAD';\n break;\n\n case 'urn:mpeg:dash:utc:http-xsdate:2014':\n case 'urn:mpeg:dash:utc:http-iso:2014':\n case 'urn:mpeg:dash:utc:http-xsdate:2012':\n case 'urn:mpeg:dash:utc:http-iso:2012':\n attributes.method = 'GET';\n break;\n\n case 'urn:mpeg:dash:utc:direct:2014':\n case 'urn:mpeg:dash:utc:direct:2012':\n attributes.method = 'DIRECT';\n attributes.value = Date.parse(attributes.value);\n break;\n\n case 'urn:mpeg:dash:utc:http-ntp:2014':\n case 'urn:mpeg:dash:utc:ntp:2014':\n case 'urn:mpeg:dash:utc:sntp:2014':\n default:\n throw new Error(errors.UNSUPPORTED_UTC_TIMING_SCHEME);\n }\n\n return attributes;\n};\n\nvar VERSION = version;\n/*\n * Given a DASH manifest string and options, parses the DASH manifest into an object in the\n * form outputed by m3u8-parser and accepted by videojs/http-streaming.\n *\n * For live DASH manifests, if `previousManifest` is provided in options, then the newly\n * parsed DASH manifest will have its media sequence and discontinuity sequence values\n * updated to reflect its position relative to the prior manifest.\n *\n * @param {string} manifestString - the DASH manifest as a string\n * @param {options} [options] - any options\n *\n * @return {Object} the manifest object\n */\n\nvar parse = function parse(manifestString, options) {\n if (options === void 0) {\n options = {};\n }\n\n var parsedManifestInfo = inheritAttributes(stringToMpdXml(manifestString), options);\n var playlists = toPlaylists(parsedManifestInfo.representationInfo);\n return toM3u8({\n dashPlaylists: playlists,\n locations: parsedManifestInfo.locations,\n sidxMapping: options.sidxMapping,\n previousManifest: options.previousManifest\n });\n};\n/**\n * Parses the manifest for a UTCTiming node, returning the nodes attributes if found\n *\n * @param {string} manifestString\n * XML string of the MPD manifest\n * @return {Object|null}\n * Attributes of UTCTiming node specified in the manifest. Null if none found\n */\n\n\nvar parseUTCTiming = function parseUTCTiming(manifestString) {\n return parseUTCTimingScheme(stringToMpdXml(manifestString));\n};\n\nexport { VERSION, addSidxSegmentsToPlaylist$1 as addSidxSegmentsToPlaylist, generateSidxKey, inheritAttributes, parse, parseUTCTiming, stringToMpdXml, toM3u8, toPlaylists };\n"],"sourceRoot":""}