|
|
|
@ -42,6 +42,85 @@ static void report_new_stream(InputFile *file, const AVPacket *pkt) |
|
|
|
|
file->nb_streams_warn = pkt->stream_index + 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// set duration to max(tmp, duration) in a proper time base and return duration's time_base
|
|
|
|
|
static AVRational duration_max(int64_t tmp, int64_t *duration, AVRational tmp_time_base, |
|
|
|
|
AVRational time_base) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
if (!*duration) { |
|
|
|
|
*duration = tmp; |
|
|
|
|
return tmp_time_base; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = av_compare_ts(*duration, time_base, tmp, tmp_time_base); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
*duration = tmp; |
|
|
|
|
return tmp_time_base; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return time_base; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int seek_to_start(InputFile *ifile, AVFormatContext *is) |
|
|
|
|
{ |
|
|
|
|
InputStream *ist; |
|
|
|
|
AVCodecContext *avctx; |
|
|
|
|
int i, ret, has_audio = 0; |
|
|
|
|
int64_t duration = 0; |
|
|
|
|
|
|
|
|
|
ret = avformat_seek_file(is, -1, INT64_MIN, is->start_time, is->start_time, 0); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ifile->nb_streams; i++) { |
|
|
|
|
ist = input_streams[ifile->ist_index + i]; |
|
|
|
|
avctx = ist->dec_ctx; |
|
|
|
|
|
|
|
|
|
/* duration is the length of the last frame in a stream
|
|
|
|
|
* when audio stream is present we don't care about |
|
|
|
|
* last video frame length because it's not defined exactly */ |
|
|
|
|
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) |
|
|
|
|
has_audio = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ifile->nb_streams; i++) { |
|
|
|
|
ist = input_streams[ifile->ist_index + i]; |
|
|
|
|
avctx = ist->dec_ctx; |
|
|
|
|
|
|
|
|
|
if (has_audio) { |
|
|
|
|
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) { |
|
|
|
|
AVRational sample_rate = {1, avctx->sample_rate}; |
|
|
|
|
|
|
|
|
|
duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base); |
|
|
|
|
} else { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (ist->framerate.num) { |
|
|
|
|
duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); |
|
|
|
|
} else if (ist->st->avg_frame_rate.num) { |
|
|
|
|
duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); |
|
|
|
|
} else { |
|
|
|
|
duration = 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!ifile->duration) |
|
|
|
|
ifile->time_base = ist->st->time_base; |
|
|
|
|
/* the total duration of the stream, max_pts - min_pts is
|
|
|
|
|
* the duration of the stream without the last frame */ |
|
|
|
|
if (ist->max_pts > ist->min_pts && ist->max_pts - (uint64_t)ist->min_pts < INT64_MAX - duration) |
|
|
|
|
duration += ist->max_pts - ist->min_pts; |
|
|
|
|
ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base, |
|
|
|
|
ifile->time_base); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ifile->loop > 0) |
|
|
|
|
ifile->loop--; |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void *input_thread(void *arg) |
|
|
|
|
{ |
|
|
|
|
InputFile *f = arg; |
|
|
|
|