History

ffmpeg: add per-stream input option drop_changed

This is a replacement in ffmpeg for the deprecated avcodec flag AV_CODEC_FLAG_DROPCHANGED. This option is meant to be used when the filtergraph should not be reinited upon input parameter changes as that leads to loss of state in the filtergraph potentially leading to broken or aborted output, e.g. inserting of silence with first_pts specified in aresample. Generally useful to avoid corrupted yet decodable packets in live streaming inputs. This option when enabled takes precedence over reinit_filters

Gyan Doshi committed 1 year ago

Commit cbbc9271 parent 323cb8c5 files · +36 −1Browse files

Unified · Split

5 files
  1. doc/ffmpeg.texi +6 −0
  2. fftools/ffmpeg.h +2 −0
  3. fftools/ffmpeg_demux.c +14 −1
  4. fftools/ffmpeg_filter.c +11 −0
  5. fftools/ffmpeg_opt.c +3 −0
doc/ffmpeg.texi+6−0
@@ -1373,6 +1373,12 @@ The properties where a change triggers reinitialization are, · 1372 unmodified lines
13731373 for video, frame resolution or pixel format;
13741374 for audio, sample format, sample rate, channel count or channel layout.
13751375
1376+@item -drop_changed[:@var{stream_specifier}] @var{integer} (@emph{input,per-stream})
1377+This boolean option determines whether a frame with differing frame parameters mid-stream
1378+gets dropped instead of leading to filtergraph reinitialization, as that would lead to loss
1379+of filter state. Generally useful to avoid corrupted yet decodable packets in live streaming
1380+inputs. Default is false.
1381+
13761382 @item -filter_threads @var{nb_threads} (@emph{global})
13771383 Defines how many threads are used to process a filter pipeline. Each pipeline
13781384 will produce a thread pool with this many threads available for parallel processing.
fftools/ffmpeg.h+2−0
@@ -232,6 +232,7 @@ typedef struct OptionsContext { · 231 unmodified lines
232232 SpecifierOptList filter_scripts;
233233 #endif
234234 SpecifierOptList reinit_filters;
235+ SpecifierOptList drop_changed;
235236 SpecifierOptList fix_sub_duration;
236237 SpecifierOptList fix_sub_duration_heartbeat;
237238 SpecifierOptList canvas_sizes;
@@ -262,6 +263,7 @@ enum IFilterFlags { · 24 unmodified lines
262263 IFILTER_FLAG_REINIT = (1 << 1),
263264 IFILTER_FLAG_CFR = (1 << 2),
264265 IFILTER_FLAG_CROP = (1 << 3),
266+ IFILTER_FLAG_DROPCHANGED = (1 << 4),
265267 };
266268
267269 typedef struct InputFilterOptions {
fftools/ffmpeg_demux.c+14−1
@@ -67,6 +67,7 @@ typedef struct DemuxStream { · 66 unmodified lines
6767 int reinit_filters;
6868 int autorotate;
6969 int apply_cropping;
70+ int drop_changed;
7071
7172
7273 int wrap_correction_done;
@@ -1099,7 +1100,8 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple, · 1026 unmodified lines
10991100 return AVERROR(ENOMEM);
11001101
11011102 opts->flags |= IFILTER_FLAG_AUTOROTATE * !!(ds->autorotate) |
1102− IFILTER_FLAG_REINIT * !!(ds->reinit_filters);
1103+ IFILTER_FLAG_REINIT * !!(ds->reinit_filters) |
1104+ IFILTER_FLAG_DROPCHANGED* !!(ds->drop_changed);
11031105
11041106 return 0;
11051107 }
@@ -1410,6 +1412,17 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona · 304 unmodified lines
14101412 ds->reinit_filters = -1;
14111413 opt_match_per_stream_int(ist, &o->reinit_filters, ic, st, &ds->reinit_filters);
14121414
1415+ ds->drop_changed = 0;
1416+ opt_match_per_stream_int(ist, &o->drop_changed, ic, st, &ds->drop_changed);
1417+
1418+ if (ds->drop_changed && ds->reinit_filters) {
1419+ if (ds->reinit_filters > 0) {
1420+ av_log(ist, AV_LOG_ERROR, "drop_changed and reinit_filters both enabled. These are mutually exclusive.\n");
1421+ return AVERROR(EINVAL);
1422+ }
1423+ ds->reinit_filters = 0;
1424+ }
1425+
14131426 ist->user_set_discard = AVDISCARD_NONE;
14141427
14151428 if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ||
fftools/ffmpeg_filter.c+11−0
@@ -126,6 +126,8 @@ typedef struct InputFilterPriv { · 125 unmodified lines
126126
127127 int eof;
128128 int bound;
129+ int drop_warned;
130+ uint64_t nb_dropped;
129131
130132 // parameters configured for this input
131133 int format;
@@ -2898,6 +2900,13 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, · 2766 unmodified lines
28982900 } else if (ifp->downmixinfo_present)
28992901 need_reinit |= DOWNMIX_CHANGED;
29002902
2903+ if (need_reinit && (ifp->opts.flags & IFILTER_FLAG_DROPCHANGED)) {
2904+ ifp->nb_dropped++;
2905+ av_log_once(fg, AV_LOG_WARNING, AV_LOG_DEBUG, &ifp->drop_warned, "Avoiding reinit; dropping frame pts: %s bound for %s\n", av_ts2str(frame->pts), ifilter->name);
2906+ av_frame_unref(frame);
2907+ return 0;
2908+ }
2909+
29012910 if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph)
29022911 need_reinit = 0;
29032912
@@ -3140,6 +3149,8 @@ read_frames: · 236 unmodified lines
31403149 ret = read_frames(fg, &fgt, fgt.frame);
31413150 if (ret == AVERROR_EOF) {
31423151 av_log(fg, AV_LOG_VERBOSE, "All consumers returned EOF\n");
3152+ if (ifp->opts.flags & IFILTER_FLAG_DROPCHANGED)
3153+ av_log(fg, AV_LOG_INFO, "Total changed input frames dropped : %"PRId64"\n", ifp->nb_dropped);
31433154 break;
31443155 } else if (ret < 0) {
31453156 av_log(fg, AV_LOG_ERROR, "Error sending frames to consumers: %s\n",
fftools/ffmpeg_opt.c+3−0
@@ -1718,6 +1718,9 @@ const OptionDef options[] = { · 1717 unmodified lines
17181718 { "reinit_filter", OPT_TYPE_INT, OPT_PERSTREAM | OPT_INPUT | OPT_EXPERT,
17191719 { .off = OFFSET(reinit_filters) },
17201720 "reinit filtergraph on input parameter changes", "" },
1721+ { "drop_changed", OPT_TYPE_INT, OPT_PERSTREAM | OPT_INPUT | OPT_EXPERT,
1722+ { .off = OFFSET(drop_changed) },
1723+ "drop frame instead of reiniting filtergraph on input parameter changes", "" },
17211724 { "filter_complex", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
17221725 { .func_arg = opt_filter_complex },
17231726 "create a complex filtergraph", "graph_description" },

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t