diff options
author | Anton Khirnov <anton@khirnov.net> | 2022-03-22 10:41:55 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2022-08-08 16:20:58 +0200 |
commit | aae9de0cb2887e6e0bbfda6ffdf85ab77d3390f0 (patch) | |
tree | c60b785b4dd5485c5d3df0aaa61c4c9c5b7ec602 /fftools/ffmpeg.c | |
parent | b99462cd277e593b84c578fc4f9b9b33db98a83a (diff) |
fftools/ffmpeg: move -stream_loop handling to the demuxer thread
-stream_loop is currently handled by destroying the demuxer thread,
seeking, then recreating it anew. This is very messy and conflicts with
the future goal of moving each major ffmpeg component into its own
thread.
Handle -stream_loop directly in the demuxer thread. Looping requires the
demuxer to know the duration of the file, which takes into account the
duration of the last decoded audio frame (if any). Use a thread message
queue to communicate this information from the main thread to the
demuxer thread.
Diffstat (limited to 'fftools/ffmpeg.c')
-rw-r--r-- | fftools/ffmpeg.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6cd92a71c1..5019a4b287 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3628,6 +3628,37 @@ static void reset_eagain(void) output_streams[i]->unavailable = 0; } +static void decode_flush(InputFile *ifile) +{ + for (int i = 0; i < ifile->nb_streams; i++) { + InputStream *ist = input_streams[ifile->ist_index + i]; + int ret; + + if (!ist->processing_needed) + continue; + + do { + ret = process_input_packet(ist, NULL, 1); + } while (ret > 0); + + if (ist->decoding_needed) { + /* report last frame duration to the demuxer thread */ + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + LastFrameDuration dur; + + dur.stream_idx = i; + dur.duration = av_rescale_q(ist->nb_samples, + (AVRational){ 1, ist->dec_ctx->sample_rate}, + ist->st->time_base); + + av_thread_message_queue_send(ifile->audio_duration_queue, &dur, 0); + } + + avcodec_flush_buffers(ist->dec_ctx); + } + } +} + /* * Return * - 0 -- one packet was read and processed @@ -3641,7 +3672,7 @@ static int process_input(int file_index) AVFormatContext *is; InputStream *ist; AVPacket *pkt; - int ret, thread_ret, i, j; + int ret, i, j; int64_t duration; int64_t pkt_dts; int disable_discontinuity_correction = copy_ts; @@ -3653,30 +3684,10 @@ static int process_input(int file_index) ifile->eagain = 1; return ret; } - if (ret < 0 && ifile->loop) { - for (i = 0; i < ifile->nb_streams; i++) { - ist = input_streams[ifile->ist_index + i]; - if (ist->processing_needed) { - ret = process_input_packet(ist, NULL, 1); - if (ret>0) - return 0; - if (ist->decoding_needed) - avcodec_flush_buffers(ist->dec_ctx); - } - } - free_input_thread(file_index); - ret = seek_to_start(ifile, is); - thread_ret = init_input_thread(file_index); - if (thread_ret < 0) - return thread_ret; - if (ret < 0) - av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n"); - else - ret = ifile_get_packet(ifile, &pkt); - if (ret == AVERROR(EAGAIN)) { - ifile->eagain = 1; - return ret; - } + if (ret == 1) { + /* the input file is looped: flush the decoders */ + decode_flush(ifile); + return AVERROR(EAGAIN); } if (ret < 0) { if (ret != AVERROR_EOF) { |