diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c8cba72006..4881174632 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -290,6 +290,7 @@ enum DecoderFlags {
 #if FFMPEG_OPT_TOP
     DECODER_FLAG_TOP_FIELD_FIRST  = (1 << 3),
 #endif
+    DECODER_FLAG_SEND_END_TS      = (1 << 4),
 };
 
 typedef struct DecoderOpts {
@@ -756,8 +757,11 @@ AVBufferRef *hw_device_for_filter(void);
 /**
  * @param dec_opts Dictionary filled with decoder options. Its ownership
  *                 is transferred to the decoder.
+ *
+ * @retval ">=0" non-negative scheduler index on success
+ * @retval "<0"  an error code on failure
  */
-int dec_open(Decoder **pdec, Scheduler *sch, unsigned sch_idx,
+int dec_open(Decoder **pdec, Scheduler *sch,
              AVDictionary **dec_opts, const DecoderOpts *o);
 void dec_free(Decoder **pdec);
 
@@ -847,7 +851,6 @@ const char *opt_match_per_type_str(const SpecifierOptList *sol,
                                    char mediatype);
 
 void *muxer_thread(void *arg);
-void *decoder_thread(void *arg);
 void *encoder_thread(void *arg);
 
 #endif /* FFTOOLS_FFMPEG_H */
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index 3610256f31..57017faa59 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -645,10 +645,9 @@ fail:
     return AVERROR(ENOMEM);
 }
 
-void *decoder_thread(void *arg)
+static void *decoder_thread(void *arg)
 {
-    InputStream *ist = arg;
-    DecoderPriv  *dp = dp_from_dec(ist->decoder);
+    DecoderPriv  *dp = arg;
     DecThreadContext dt;
     int ret = 0, input_status = 0;
 
@@ -692,7 +691,7 @@ void *decoder_thread(void *arg)
                 break;
 
             /* report last frame duration to the scheduler */
-            if (ist->dec->type == AVMEDIA_TYPE_AUDIO) {
+            if (dp->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
                 dt.pkt->pts       = dp->last_frame_pts + dp->last_frame_duration_est;
                 dt.pkt->time_base = dp->last_frame_tb;
             }
@@ -940,7 +939,7 @@ static const AVClass dec_class = {
     .item_name                 = dec_item_name,
 };
 
-int dec_open(Decoder **pdec, Scheduler *sch, unsigned sch_idx,
+int dec_open(Decoder **pdec, Scheduler *sch,
              AVDictionary **dec_opts, const DecoderOpts *o)
 {
     DecoderPriv *dp;
@@ -953,8 +952,11 @@ int dec_open(Decoder **pdec, Scheduler *sch, unsigned sch_idx,
     if (ret < 0)
         return ret;
 
+    ret = sch_add_dec(sch, decoder_thread, dp, o->flags & DECODER_FLAG_SEND_END_TS);
+    if (ret < 0)
+        return ret;
     dp->sch     = sch;
-    dp->sch_idx = sch_idx;
+    dp->sch_idx = ret;
 
     dp->flags      = o->flags;
     dp->dec.class  = &dec_class;
@@ -1036,7 +1038,7 @@ int dec_open(Decoder **pdec, Scheduler *sch, unsigned sch_idx,
 
     *pdec = &dp->dec;
 
-    return 0;
+    return dp->sch_idx;
 fail:
     dec_free((Decoder**)dp);
     return ret;
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 5178bcbce4..0ccb05b1d0 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -895,18 +895,9 @@ static int ist_use(InputStream *ist, int decoding_needed)
     if (decoding_needed && ds->sch_idx_dec < 0) {
         int is_audio = ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
 
-        ret = sch_add_dec(d->sch, decoder_thread, ist, d->loop && is_audio);
-        if (ret < 0)
-            return ret;
-        ds->sch_idx_dec = ret;
-
-        ret = sch_connect(d->sch, SCH_DSTREAM(d->f.index, ds->sch_idx_stream),
-                                  SCH_DEC(ds->sch_idx_dec));
-        if (ret < 0)
-            return ret;
-
         ds->dec_opts.flags = (!!ist->fix_sub_duration * DECODER_FLAG_FIX_SUB_DURATION) |
-                             (!!(d->f.ctx->iformat->flags & AVFMT_NOTIMESTAMPS) * DECODER_FLAG_TS_UNRELIABLE)
+                             (!!(d->f.ctx->iformat->flags & AVFMT_NOTIMESTAMPS) * DECODER_FLAG_TS_UNRELIABLE) |
+                             (!!(d->loop && is_audio) * DECODER_FLAG_SEND_END_TS)
 #if FFMPEG_OPT_TOP
                              | ((ist->top_field_first >= 0) * DECODER_FLAG_TOP_FIELD_FIRST)
 #endif
@@ -935,10 +926,16 @@ static int ist_use(InputStream *ist, int decoding_needed)
 
         ds->dec_opts.log_parent = ist;
 
-        ret = dec_open(&ist->decoder, d->sch, ds->sch_idx_dec,
+        ret = dec_open(&ist->decoder, d->sch,
                        &ist->decoder_opts, &ds->dec_opts);
         if (ret < 0)
             return ret;
+        ds->sch_idx_dec = ret;
+
+        ret = sch_connect(d->sch, SCH_DSTREAM(d->f.index, ds->sch_idx_stream),
+                                  SCH_DEC(ds->sch_idx_dec));
+        if (ret < 0)
+            return ret;
 
         d->have_audio_dec |= is_audio;
     }
