static void adjust_write_index(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVIOContext *pb = s->pb; int64_t pts; //int64_t orig_write_index = ffm->write_index; int64_t pos_min, pos_max; int64_t pts_start; int64_t ptr = avio_tell(pb); pos_min = 0; pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE; pts_start = get_dts(s, pos_min); pts = get_dts(s, pos_max); if (pts - 100000 > pts_start) goto end; ffm->write_index = FFM_PACKET_SIZE; pts_start = get_dts(s, pos_min); pts = get_dts(s, pos_max); if (pts - 100000 <= pts_start) { while (1) { int64_t newpos; int64_t newpts; newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE; if (newpos == pos_min) break; newpts = get_dts(s, newpos); if (newpts - 100000 <= pts) { pos_max = newpos; pts = newpts; } else { pos_min = newpos; } } ffm->write_index += pos_max; } end: avio_seek(pb, ptr, SEEK_SET); }
/* seek to a given time in the file. The file read pointer is positioned at or before pts. XXX: the following code is quite approximative */ 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) */ 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); /* 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; }
void nut_write_frame_reorder(nut_context_tt * nut, const nut_packet_tt * p, const uint8_t * buf) { stream_context_tt * s = &nut->sc[p->stream]; if (nut->stream_count < 2) { // do nothing nut_write_frame(nut, p, buf); return; } s->num_packets++; s->packets = nut->alloc->realloc(s->packets, s->num_packets * sizeof(reorder_packet_tt)); s->packets[s->num_packets - 1].p = *p; s->packets[s->num_packets - 1].dts = get_dts(s->sh.decode_delay, s->reorder_pts_cache, p->pts); s->packets[s->num_packets - 1].buf = nut->alloc->malloc(p->len); // FIXME memcpy(s->packets[s->num_packets - 1].buf, buf, p->len); flushcheck_frames(nut); }