/// <summary> /// Select the next media bit rate using the minimum value from /// 2 criterias: /// <para> /// Condition 1) The bit rate selected must allow the buffer /// fullness to grow at least N times faster than the measured /// download bandwidth /// </para> /// <para> /// Condition 2) Using a fraction of the current buffer /// fullness, and a fraction of the past download bandwidth /// (network bit rate), find the highest bit rate encoding at /// which we can download to get as close as possible to the /// current target speed content download /// </para> /// <para> /// Condition 3) If in place, will not let the bit rate speed /// change be larger than 1 step /// </para> /// <para> /// NOTE speed content download is defined for a given stream /// bit rate (actually the bytes size) and network bit rate, /// as the amount of seconds worth of content that we can /// download per wall clock second /// </para> /// </summary> /// <param name="networkMediaInfo">the network media info to query</param> /// <param name="chunkDuration">the duration of the last chunk</param> /// <returns>the next bitrate to use</returns> private ulong GetNextBitRateUsingBandwidth(NetworkMediaInfo networkMediaInfo, double chunkDuration) { // If we are using a locked bit rate then our job is easy if (networkMediaInfo.LockedBitRate >= 0) { return networkMediaInfo.BitratesInfo[networkMediaInfo.LockedBitRate].NominalBitrate; } // Condition 1 ulong bitRateCond1 = (ulong)(networkMediaInfo.DownloadBandwidthWindow.CurrentKernel / networkMediaInfo.RelativeContentDownloadSpeed); // Condition 2 ulong bitRateCond2 = (ulong) (networkMediaInfo.DownloadBandwidthWindow.CurrentKernel * networkMediaInfo.BufferFullnessWindow.CurrentKernel * (sm_NetworkHeuristicsParams.DownloadBandwidthFraction * sm_NetworkHeuristicsParams.BufferFullnessFraction / chunkDuration)); ulong bitRateFinal = bitRateCond2 < bitRateCond1 ? bitRateCond2 : bitRateCond1; // Condition 3 ulong bitRateCond3 = ulong.MaxValue; // Only limit bitrate changes to one step at // a time (condition 3) if (networkMediaInfo.IsLimitBitrateSteps == true) { int bitRateIndex = networkMediaInfo.FindBitRateIndex(networkMediaInfo.PreviousBitrate) + 1; bitRateCond3 = networkMediaInfo.FindClosestBitrateByIndex(bitRateIndex); if (bitRateCond3 < bitRateFinal) { bitRateFinal = bitRateCond3; } } NhTrace("INFO", networkMediaInfo.StreamId, "C1({0}):{1} C2:{2} C3:{3} final:{4}", networkMediaInfo.RelativeContentDownloadSpeed, bitRateCond1, bitRateCond2, bitRateCond3, bitRateFinal); return bitRateFinal; }
/// <summary> /// Return the bit rate 1 step above (step > 0) or 1 step /// below (step less than 0) the current one /// </summary> /// <param name="networkMediaInfo">The nextwork media info to query</param> /// <param name="step">Increse/decrease bit rate in "step" steps</param> /// <returns>next bitrate, in bps</returns> private static ulong GetNextBitRate(NetworkMediaInfo networkMediaInfo, int step) { if (networkMediaInfo.LockedBitRate >= 0) { return networkMediaInfo.BitratesInfo[networkMediaInfo.LockedBitRate].NominalBitrate; } int index = 0; for (; index < networkMediaInfo.BitratesInfo.Length; index++) { if (networkMediaInfo.PreviousBitrate == networkMediaInfo.BitratesInfo[index].NominalBitrate) { break; } } index += step; return networkMediaInfo.FindClosestBitrateByIndex(index); }