static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags) { FFMContext *ffm = s->priv_data; int64_t pos_min, pos_max, pos; int64_t pts_min, pts_max, pts; double pos1; av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); /* find the position using linear interpolation (better than dichotomy in typical cases) */ if (ffm->write_index && ffm->write_index < ffm->file_size) { if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) { pos_min = FFM_PACKET_SIZE; pos_max = ffm->write_index - FFM_PACKET_SIZE; } else { pos_min = ffm->write_index; pos_max = ffm->file_size - FFM_PACKET_SIZE; } } else { pos_min = FFM_PACKET_SIZE; pos_max = ffm->file_size - FFM_PACKET_SIZE; } while (pos_min <= pos_max) { pts_min = get_dts(s, pos_min); pts_max = get_dts(s, pos_max); if (pts_min > wanted_pts || pts_max <= wanted_pts) { pos = pts_min > wanted_pts ? pos_min : pos_max; goto found; } /* linear interpolation */ pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) / (double)(pts_max - pts_min); pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE; if (pos <= pos_min) pos = pos_min; else if (pos >= pos_max) pos = pos_max; pts = get_dts(s, pos); /* check if we are lucky */ if (pts == wanted_pts) { goto found; } else if (pts > wanted_pts) { pos_max = pos - FFM_PACKET_SIZE; } else { pos_min = pos + FFM_PACKET_SIZE; } } pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; found: if (ffm_seek1(s, pos) < 0) return -1; /* reset read state */ ffm->read_state = READ_HEADER; ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->first_packet = 1; return 0; }