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 49c5757e97..bf41a44f1f 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; }