BaseRepresentation * NearOptimalAdaptationLogic::getNextQualityIndex( BaseAdaptationSet *adaptSet, RepresentationSelector &selector, float gammaP, mtime_t VD, mtime_t Q ) { BaseRepresentation *ret = NULL; BaseRepresentation *prev = NULL; float argmax; for(BaseRepresentation *rep = selector.lowest(adaptSet); rep && rep != prev; rep = selector.higher(adaptSet, rep)) { float arg = ( VD * (getUtility(rep) + gammaP) - Q ) / rep->getBandwidth(); if(ret == NULL || argmax <= arg) { ret = rep; argmax = arg; } prev = rep; } return ret; }
BaseRepresentation *PredictiveAdaptationLogic::getNextRepresentation(BaseAdaptationSet *adaptSet, BaseRepresentation *prevRep) { RepresentationSelector selector(maxwidth, maxheight); BaseRepresentation *rep; vlc_mutex_lock(&lock); std::map<ID, PredictiveStats>::iterator it = streams.find(adaptSet->getID()); if(it == streams.end()) { rep = selector.highest(adaptSet); } else { PredictiveStats &stats = (*it).second; double f_buffering_level = (double)stats.buffering_level / stats.buffering_target; double f_min_buffering_level = f_buffering_level; unsigned i_max_bitrate = 0; if(streams.size() > 1) { std::map<ID, PredictiveStats>::const_iterator it2 = streams.begin(); for(; it2 != streams.end(); ++it2) { if(it2 == it) continue; const PredictiveStats &other = (*it2).second; f_min_buffering_level = std::min((double)other.buffering_level / other.buffering_target, f_min_buffering_level); i_max_bitrate = std::max(i_max_bitrate, other.last_download_rate); } } if(stats.starting()) { rep = selector.highest(adaptSet); } else { const unsigned i_available_bw = getAvailableBw(i_max_bitrate, prevRep); if(!prevRep) { rep = selector.select(adaptSet, i_available_bw); } else if(f_buffering_level > 0.8) { rep = selector.select(adaptSet, std::max((uint64_t) i_available_bw, (uint64_t) prevRep->getBandwidth())); } else if(f_buffering_level > 0.5) { rep = prevRep; } else { if(f_buffering_level > 2 * stats.last_duration) { rep = selector.lower(adaptSet, prevRep); } else { rep = selector.select(adaptSet, i_available_bw * f_buffering_level); } } } BwDebug( for(it=streams.begin(); it != streams.end(); ++it) { const PredictiveStats &s = (*it).second; msg_Info(p_obj, "Stream %s buffering level %.2f%", (*it).first.str().c_str(), (double) s.buffering_level / s.buffering_target); } ); BwDebug( if( rep != prevRep ) msg_Info(p_obj, "Stream %s new bandwidth usage %zu KiB/s", adaptSet->getID().str().c_str(), rep->getBandwidth() / 8000); );