summaryrefslogtreecommitdiff
path: root/fftools/ffmpeg.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2022-03-22 10:41:55 +0100
committerAnton Khirnov <anton@khirnov.net>2022-08-08 16:20:58 +0200
commitaae9de0cb2887e6e0bbfda6ffdf85ab77d3390f0 (patch)
treec60b785b4dd5485c5d3df0aaa61c4c9c5b7ec602 /fftools/ffmpeg.c
parentb99462cd277e593b84c578fc4f9b9b33db98a83a (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.c61
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) {