Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /** * Level Helper class, providing methods dealing with playlist sliding and drift */ import { logger } from '../utils/logger'; export function updatePTS (fragments, fromIdx, toIdx) { let fragFrom = fragments[fromIdx], fragTo = fragments[toIdx], fragToPTS = fragTo.startPTS; // if we know startPTS[toIdx] if (!isNaN(fragToPTS)) { // update fragment duration. // it helps to fix drifts between playlist reported duration and fragment real duration if (toIdx > fromIdx) { fragFrom.duration = fragToPTS - fragFrom.start; if (fragFrom.duration < 0) logger.warn(`negative duration computed for frag ${fragFrom.sn},level ${fragFrom.level}, there should be some duration drift between playlist and fragment!`); } else { fragTo.duration = fragFrom.start - fragToPTS; if (fragTo.duration < 0) logger.warn(`negative duration computed for frag ${fragTo.sn},level ${fragTo.level}, there should be some duration drift between playlist and fragment!`); } } else { // we dont know startPTS[toIdx] if (toIdx > fromIdx) fragTo.start = fragFrom.start + fragFrom.duration; else fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0); } } export function updateFragPTSDTS (details, frag, startPTS, endPTS, startDTS, endDTS) { // update frag PTS/DTS let maxStartPTS = startPTS; if (!isNaN(frag.startPTS)) { // delta PTS between audio and video let deltaPTS = Math.abs(frag.startPTS - startPTS); if (isNaN(frag.deltaPTS)) frag.deltaPTS = deltaPTS; else frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS); maxStartPTS = Math.max(startPTS, frag.startPTS); startPTS = Math.min(startPTS, frag.startPTS); endPTS = Math.max(endPTS, frag.endPTS); startDTS = Math.min(startDTS, frag.startDTS); endDTS = Math.max(endDTS, frag.endDTS); } const drift = startPTS - frag.start; frag.start = frag.startPTS = startPTS; frag.maxStartPTS = maxStartPTS; frag.endPTS = endPTS; frag.startDTS = startDTS; frag.endDTS = endDTS; frag.duration = endPTS - startPTS; const sn = frag.sn; // exit if sn out of range if (!details || sn < details.startSN || sn > details.endSN) return 0; let fragIdx, fragments, i; fragIdx = sn - details.startSN; fragments = details.fragments; // update frag reference in fragments array // rationale is that fragments array might not contain this frag object. // this will happpen if playlist has been refreshed between frag loading and call to updateFragPTSDTS() // if we don't update frag, we won't be able to propagate PTS info on the playlist // resulting in invalid sliding computation fragments[fragIdx] = frag; // adjust fragment PTS/duration from seqnum-1 to frag 0 for (i = fragIdx; i > 0; i--) updatePTS(fragments, i, i - 1); // adjust fragment PTS/duration from seqnum to last frag for (i = fragIdx; i < fragments.length - 1; i++) updatePTS(fragments, i, i + 1); details.PTSKnown = true; // logger.log(` frag start/end:${startPTS.toFixed(3)}/${endPTS.toFixed(3)}`); return drift; } export function mergeDetails (oldDetails, newDetails) { let start = Math.max(oldDetails.startSN, newDetails.startSN) - newDetails.startSN, end = Math.min(oldDetails.endSN, newDetails.endSN) - newDetails.startSN, delta = newDetails.startSN - oldDetails.startSN, oldfragments = oldDetails.fragments, newfragments = newDetails.fragments, ccOffset = 0, PTSFrag; // potentially retrieve cached initsegment if (newDetails.initSegment && oldDetails.initSegment) newDetails.initSegment = oldDetails.initSegment; // check if old/new playlists have fragments in common if (end < start) { newDetails.PTSKnown = false; return; } // loop through overlapping SN and update startPTS , cc, and duration if any found for (var i = start; i <= end; i++) { let oldFrag = oldfragments[delta + i], newFrag = newfragments[i]; if (newFrag && oldFrag) { ccOffset = oldFrag.cc - newFrag.cc; if (!isNaN(oldFrag.startPTS)) { newFrag.start = newFrag.startPTS = oldFrag.startPTS; newFrag.endPTS = oldFrag.endPTS; newFrag.duration = oldFrag.duration; newFrag.backtracked = oldFrag.backtracked; newFrag.dropped = oldFrag.dropped; PTSFrag = newFrag; } } } if (ccOffset) { logger.log('discontinuity sliding from playlist, take drift into account'); for (i = 0; i < newfragments.length; i++) newfragments[i].cc += ccOffset; } // if at least one fragment contains PTS info, recompute PTS information for all fragments if (PTSFrag) { updateFragPTSDTS(newDetails, PTSFrag, PTSFrag.startPTS, PTSFrag.endPTS, PTSFrag.startDTS, PTSFrag.endDTS); } else { // ensure that delta is within oldfragments range // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) // in that case we also need to adjust start offset of all fragments if (delta >= 0 && delta < oldfragments.length) { // adjust start by sliding offset let sliding = oldfragments[delta].start; for (i = 0; i < newfragments.length; i++) newfragments[i].start += sliding; } } // if we are here, it means we have fragments overlapping between // old and new level. reliable PTS info is thus relying on old level newDetails.PTSKnown = oldDetails.PTSKnown; } |