/// <summary> /// return the fragment information for the first fragment in the FRT whose fragment number /// is greater than or equal to fragment id. special cases: /// /// if fragmentId is in a gap, the first fragment after the gap will be returned. /// if fragmentId is in a skip, the first fragment after the skip will be returned. /// if fragmentId is before the first fragment-duration-pair, the first fragment will be returned. /// if fragmentId is after the last fragment-duration-pair, it will be assumed to exist. /// (in other words, the live point is ignored). /// /// if there are no valid entries in the FRT, returns null. this is the only situation that returns null. /// </summary> public FragmentAccessInformation getFragmentWithIdGreq(uint fragmentId) { FragmentDurationPair desiredFdp = null; uint desiredFragmentId = 0; forEachInterval(delegate(FragmentDurationPair fdp, bool isLast, uint startFragmentId, uint endFragmentId, uint startTime, uint endTime) { if (fragmentId < startFragmentId) { // before the given interval desiredFdp = fdp; desiredFragmentId = startFragmentId; return(false); // stop iterating } else if (isLast) { // catch all in the last entry desiredFdp = fdp; desiredFragmentId = fragmentId; return(false); } else if (fragmentId < endFragmentId) { // between the start and end of this interval desiredFdp = fdp; desiredFragmentId = fragmentId; return(false); // stop iterating } else { // beyond this interval, but not the last entry return(true); // keep iterating } }); if (desiredFdp == null) { // no fragment entries case return(null); } if (desiredFragmentId < desiredFdp.firstFragment) { // probably won't ever hit this // just make sure that we're before the start desiredFragmentId = desiredFdp.firstFragment; } FragmentAccessInformation fai = new FragmentAccessInformation(); fai.fragId = desiredFragmentId; fai.fragDuration = desiredFdp.duration; fai.fragmentEndTime = (uint)desiredFdp.durationAccrued + (desiredFragmentId - desiredFdp.firstFragment + 1) * desiredFdp.duration; return(fai); }
/// <summary> /// return the fragment information for the first fragment in the FRT that contains a time /// greater than or equal to fragment time. special cases: /// /// if time is in a gap, the first fragment after the gap will be returned. /// if time is in a skip, the first fragment after the skip will be returned. /// if time is before the first fragment-duration-pair, the first fragment will be returned. /// if time is after the last fragment-duration-pair, it will be assumed to exist. /// (in other words, the live point is ignored). /// /// if there are no valid entries in the FRT, returns null. this is the only situation that returns null. /// </summary> public FragmentAccessInformation getFragmentWithTimeGreq(uint fragmentTime) { FragmentDurationPair desiredFdp = null; uint desiredFragmentStartTime = 0; forEachInterval(delegate(FragmentDurationPair fdp, bool isLast, uint startFragmentId, uint endFragmentId, uint startTime, uint endTime) { if (fragmentTime < startTime) { // before the given interval desiredFdp = fdp; desiredFragmentStartTime = startTime; return(false); // stop iterating } else if (isLast) { // catch all in the last entry desiredFdp = fdp; desiredFragmentStartTime = fragmentTime; return(false); } else if (fragmentTime < endTime) { // between the start and end of this interval desiredFdp = fdp; desiredFragmentStartTime = fragmentTime; return(false); // stop iterating } else { // beyond this interval, but not the last entry return(true); // keep iterating } }); if (desiredFdp == null) { // no fragment entries case return(null); } uint desiredFragmentId = calculateFragmentId(desiredFdp, desiredFragmentStartTime); FragmentAccessInformation fai = new FragmentAccessInformation(); fai.fragId = desiredFragmentId; fai.fragDuration = desiredFdp.duration; fai.fragmentEndTime = (uint)desiredFdp.durationAccrued + (desiredFragmentId - desiredFdp.firstFragment + 1) * desiredFdp.duration; return(fai); }
private FragmentAccessInformation getNextValidFragment(int startIdx) { FragmentAccessInformation fai = null; for (int i = startIdx; i < fragmentDurationPairs.Count; i++) { FragmentDurationPair fdp = fragmentDurationPairs[i]; if (fdp.duration > 0) { fai = new FragmentAccessInformation(); fai.fragId = fdp.firstFragment; fai.fragDuration = fdp.duration; fai.fragmentEndTime = (uint)fdp.durationAccrued + fdp.duration; break; } } return(fai); }
/// <summary> /// Given a fragment id, check whether the current fragment is valid or a discontinuity. /// If the latter, skip to the nearest fragment and return the new fragment id. /// /// return the Id of the fragment that is valid. /// </summary> public FragmentAccessInformation validateFragment(uint fragId, ulong totalDuration, bool live = false) { int size = fragmentDurationPairs.Count - 1; FragmentAccessInformation fai = null; uint timeResidue, timeDistance, fragStartTime; for (int i = 0; i < size; i++) { FragmentDurationPair curFdp = fragmentDurationPairs[i]; FragmentDurationPair nextFdp = fragmentDurationPairs[i + 1]; if ((curFdp.firstFragment <= fragId) && (fragId < nextFdp.firstFragment)) { if (curFdp.duration <= 0) { fai = getNextValidFragment(i + 1); } else { fai = new FragmentAccessInformation(); fai.fragId = fragId; fai.fragDuration = curFdp.duration; fai.fragmentEndTime = (uint)curFdp.durationAccrued + curFdp.duration * (fragId - curFdp.firstFragment + 1); } break; } else if ((curFdp.firstFragment <= fragId) && endOfStreamEntry(nextFdp)) { if (curFdp.duration > 0) { timeResidue = (uint)(totalDuration - curFdp.durationAccrued); timeDistance = (fragId - curFdp.firstFragment + 1) * curFdp.duration; fragStartTime = (fragId - curFdp.firstFragment) * curFdp.duration; if (timeResidue > fragStartTime) { if (!live || ((fragStartTime + curFdp.duration + curFdp.durationAccrued) <= totalDuration)) { fai = new FragmentAccessInformation(); fai.fragId = fragId; fai.fragDuration = curFdp.duration; if (timeResidue >= timeDistance) { fai.fragmentEndTime = (uint)curFdp.durationAccrued + timeDistance; } else { fai.fragmentEndTime = (uint)curFdp.durationAccrued + timeResidue; } break; } } } } } if (fai == null) { FragmentDurationPair lastFdp = fragmentDurationPairs[size]; if (lastFdp.duration > 0 && fragId >= lastFdp.firstFragment) { timeResidue = (uint)(totalDuration - lastFdp.durationAccrued); timeDistance = (fragId - lastFdp.firstFragment + 1) * lastFdp.duration; fragStartTime = (fragId - lastFdp.firstFragment) * lastFdp.duration; if (timeResidue > fragStartTime) { if (!live || ((fragStartTime + lastFdp.duration + lastFdp.durationAccrued) <= totalDuration)) { fai = new FragmentAccessInformation(); fai.fragId = fragId; fai.fragDuration = lastFdp.duration; if (timeResidue >= timeDistance) { fai.fragmentEndTime = (uint)lastFdp.durationAccrued + timeDistance; } else { fai.fragmentEndTime = (uint)lastFdp.durationAccrued + timeResidue; } } } } } return(fai); }