static void UpdatePositionMap(frm_pos_map_t &posMap, QString mapfile, ProgramInfo *pginfo) { if (pginfo && mapfile.isEmpty()) { pginfo->ClearPositionMap(MARK_KEYFRAME); pginfo->ClearPositionMap(MARK_GOP_START); pginfo->SavePositionMap(posMap, MARK_GOP_BYFRAME); } else if (!mapfile.isEmpty()) { FILE *mapfh = fopen(mapfile.toLocal8Bit().constData(), "w"); if (!mapfh) { LOG(VB_GENERAL, LOG_ERR, QString("Could not open map file '%1'") .arg(mapfile) + ENO); return; } frm_pos_map_t::const_iterator it; fprintf (mapfh, "Type: %d\n", MARK_GOP_BYFRAME); for (it = posMap.begin(); it != posMap.end(); ++it) fprintf(mapfh, "%lld %lld\n", (unsigned long long)it.key(), (unsigned long long)*it); fclose(mapfh); } }
// Linearly interpolate the value for a given key in the map. If the // key is outside the range of keys in the map, linearly extrapolate // using the fallback ratio. uint64_t DecoderBase::TranslatePosition(const frm_pos_map_t &map, long long key, float fallback_ratio) { uint64_t key1, key2; uint64_t val1, val2; frm_pos_map_t::const_iterator lower = map.lowerBound(key); // QMap::lowerBound() finds a key >= the given key. We want one // <= the given key, so back up one element upon > condition. if (lower != map.begin() && (lower == map.end() || lower.key() > key)) --lower; if (lower == map.end() || lower.key() > key) { key1 = 0; val1 = 0; LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("TranslatePosition(key=%1): extrapolating to (0,0)") .arg(key)); } else { key1 = lower.key(); val1 = lower.value(); } // Find the next key >= the given key. QMap::lowerBound() is // precisely correct in this case. frm_pos_map_t::const_iterator upper = map.lowerBound(key); if (upper == map.end()) { // Extrapolate from (key1,val1) based on fallback_ratio key2 = key; val2 = val1 + fallback_ratio * (key2 - key1) + 0.5; LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("TranslatePosition(key=%1, ratio=%2): " "extrapolating to (%3,%4)") .arg(key).arg(fallback_ratio).arg(key2).arg(val2)); return val2; } else { key2 = upper.key(); val2 = upper.value(); } if (key1 == key2) // this happens for an exact keyframe match return val2; // can also set key2 = key1 + 1 avoid dividing by zero return val1 + (double) (key - key1) * (val2 - val1) / (key2 - key1) + 0.5; }