#define AUDIO_INBUF_SIZE 0x10000
#define VIDEO_REFILL_THRESH 0
#define AUDIO_REFILL_THRESH 0x1000
+#define AUDIO_MIN_FRAME_SZ 128
Mutex FFMPEG::fflock("FFMPEG::fflock");
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);
+ int ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame, 0);
if( ret < 0 )
eprintf(_("av_buffersrc_add_frame_flags failed\n"));
return ret;
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( nudge != AV_NOPTS_VALUE ) tstmp += nudge;
+ 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.
}
int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags);
#else
- int ret = av_seek_frame(fmt_ctx, idx, 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 ) {
channel0 = channels = 0;
sample_rate = 0;
mbsz = 0;
+ frame_sz = AUDIO_MIN_FRAME_SZ;
length = 0;
resample_context = 0;
swr_ichs = swr_ifmt = swr_irate = 0;
}
if( mbsz < len ) mbsz = len;
int64_t end_pos = pos + len;
- int ret = 0;
- for( int i=0; ret>=0 && !flushed && curr_pos<end_pos && i<MAX_RETRY; ++i ) {
+ int ret = 0, i = len / frame_sz + MAX_RETRY;
+ while( ret>=0 && !flushed && curr_pos<end_pos && --i>=0 ) {
ret = read_frame(frame);
- if( ret > 0 ) {
+ if( ret > 0 && frame->nb_samples > 0 ) {
init_swr(frame->channels, frame->format, frame->sample_rate);
load_history(&frame->extended_data[0], frame->nb_samples);
curr_pos += frame->nb_samples;
fprintf(stderr, "FFVideoStream::load: av_frame_alloc failed\n");
return -1;
}
- for( int i=0; ret>=0 && !flushed && curr_pos<=pos && i<MAX_RETRY; ++i ) {
+ int i = MAX_RETRY + pos - curr_pos;
+ while( ret>=0 && !flushed && curr_pos<=pos && --i>=0 ) {
ret = read_frame(frame);
if( ret > 0 ) ++curr_pos;
}
if( st->start_time == AV_NOPTS_VALUE ) continue;
int vidx = ffvideo.size();
while( --vidx >= 0 && ffvideo[vidx]->fidx != i );
- if( vidx >= 0 && ffvideo[vidx]->nudge != AV_NOPTS_VALUE ) continue;
+ if( vidx < 0 ) continue;
+ if( ffvideo[vidx]->nudge != AV_NOPTS_VALUE ) continue;
if( vstart_time < st->start_time )
vstart_time = st->start_time;
break; }
if( st->start_time == AV_NOPTS_VALUE ) continue;
int aidx = ffaudio.size();
while( --aidx >= 0 && ffaudio[aidx]->fidx != i );
- if( aidx >= 0 && ffaudio[aidx]->nudge != AV_NOPTS_VALUE ) continue;
+ if( aidx < 0 ) continue;
+ if( ffaudio[aidx]->frame_sz < avpar->frame_size )
+ ffaudio[aidx]->frame_sz = avpar->frame_size;
+ if( ffaudio[aidx]->nudge != AV_NOPTS_VALUE ) continue;
if( astart_time < st->start_time )
astart_time = st->start_time;
break; }