X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=dcbb49c63d4eeee18333df5bbacac178112e0d39;hb=9304882bd349ce15be054efb7cdcf69a0829f0f9;hp=f79a240ef5c844d091070f205e3dd68e1a799ee5;hpb=58d99c74e65066486dbebf7e1cb3087e7de1c92b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index f79a240e..dcbb49c6 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -395,12 +395,11 @@ int FFStream::decode(AVFrame *frame) int FFStream::load_filter(AVFrame *frame) { + av_frame_unref(frame); int ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF); - if( ret < 0 ) { - av_frame_unref(frame); + if( ret < 0 ) eprintf(_("av_buffersrc_add_frame_flags failed\n")); - } return ret; } @@ -418,6 +417,7 @@ int FFStream::read_filter(AVFrame *frame) int FFStream::read_frame(AVFrame *frame) { + av_frame_unref(frame); if( !filter_graph || !buffersrc_ctx || !buffersink_ctx ) return decode(frame); if( !fframe && !(fframe=av_frame_alloc()) ) { @@ -491,7 +491,6 @@ int FFStream::flush() int FFStream::seek(int64_t no, double rate) { - int64_t tstmp = -INT64_MAX+1; // default ffmpeg native seek int npkts = 1; int64_t pos = no, pkt_pos = -1; @@ -509,11 +508,24 @@ int FFStream::seek(int64_t no, double rate) } } if( pos == curr_pos ) return 0; - if( pos > 0 && st->time_base.num > 0 ) { - double secs = pos / rate; - tstmp = secs * st->time_base.den / st->time_base.num; - if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; - } + double secs = pos < 0 ? 0. : pos / rate; + AVRational time_base = st->time_base; + int64_t tstmp = time_base.num > 0 ? secs * time_base.den/time_base.num : 0; + if( !tstmp ) { + if( st->nb_index_entries > 0 ) tstmp = st->index_entries[0].timestamp; + else if( st->start_time != AV_NOPTS_VALUE ) tstmp = st->start_time; + else if( st->first_dts != AV_NOPTS_VALUE ) tstmp = st->first_dts; + else tstmp = INT64_MIN+1; + } + else if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; + int idx = st->index; +#if 0 +// seek all streams using the default timebase. +// this is how ffmpeg and ffplay work. stream seeks are less tested. + tstmp = av_rescale_q(tstmp, time_base, AV_TIME_BASE_Q); + idx = -1; +#endif + avcodec_flush_buffers(avctx); avformat_flush(fmt_ctx); #if 0 @@ -523,9 +535,11 @@ int FFStream::seek(int64_t no, double rate) seek = pkt_pos; flags = AVSEEK_FLAG_BYTE; } - int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags); + int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags); #else - int ret = av_seek_frame(fmt_ctx, st->index, tstmp, AVSEEK_FLAG_ANY); +// finds the first index frame below the target time + int flags = AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY; + int ret = av_seek_frame(fmt_ctx, idx, tstmp, flags); #endif int retry = MAX_RETRY; while( ret >= 0 ) { @@ -559,7 +573,7 @@ int FFStream::seek(int64_t no, double rate) if( ret < 0 ) { printf("** seek fail %jd, %jd\n", pos, tstmp); seeked = need_packet = 0; - st_eof(flushed=1); + st_eof(flushed=1); return -1; } //printf("seeked pos = %ld, %ld\n", pos, tstmp); @@ -725,6 +739,7 @@ int FFAudioStream::load(int64_t pos, int len) init_swr(frame->channels, frame->format, frame->sample_rate); load_history(&frame->extended_data[0], frame->nb_samples); curr_pos += frame->nb_samples; + i = 0; } } if( end_pos > curr_pos ) { @@ -854,7 +869,7 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos) } for( int i=0; ret>=0 && !flushed && curr_pos<=pos && i 0 ) ++curr_pos; + if( ret > 0 ) { ++curr_pos; i = 0; } } if( frame->format == AV_PIX_FMT_NONE || frame->width <= 0 || frame->height <= 0 ) ret = -1;