diff --git a/package/ffmpeg/patches/ffmpeg-4.4-discon.patch b/package/ffmpeg/patches/ffmpeg-4.4-discon.patch new file mode 100644 index 00000000..6748065d --- /dev/null +++ b/package/ffmpeg/patches/ffmpeg-4.4-discon.patch @@ -0,0 +1,124 @@ +diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c +index 46bb014..00268c6 100644 +--- a/fftools/ffmpeg.c ++++ b/fftools/ffmpeg.c +@@ -4516,7 +4516,7 @@ static int process_input(int file_index) + if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || + ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && + pkt_dts != AV_NOPTS_VALUE && ist->next_dts == AV_NOPTS_VALUE && !copy_ts +- && (is->iformat->flags & AVFMT_TS_DISCONT) && ifile->last_ts != AV_NOPTS_VALUE) { ++ && (is->iformat->flags & AVFMT_TS_DISCONT) && ifile->last_ts != AV_NOPTS_VALUE && !force_dts_monotonicity) { + int64_t delta = pkt_dts - ifile->last_ts; + if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE || + delta > 1LL*dts_delta_threshold*AV_TIME_BASE){ +@@ -4554,7 +4554,7 @@ static int process_input(int file_index) + if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || + ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && + pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && +- !disable_discontinuity_correction) { ++ !disable_discontinuity_correction && !force_dts_monotonicity) { + int64_t delta = pkt_dts - ist->next_dts; + if (is->iformat->flags & AVFMT_TS_DISCONT) { + if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE || +@@ -4592,6 +4592,43 @@ static int process_input(int file_index) + if (pkt->dts != AV_NOPTS_VALUE) + ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); + ++ if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || ++ ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && ++ (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE) && ++ force_dts_monotonicity) { ++ int64_t ff_pts_error = 0; ++ int64_t ff_dts_error = 0; ++ int64_t ff_dts_threshold = av_rescale_q(dts_monotonicity_threshold, AV_TIME_BASE_Q, ist->st->time_base); ++ ++ // adjust the incoming packet by the accumulated monotonicity error ++ if (pkt->pts != AV_NOPTS_VALUE) { ++ pkt->pts += ifile->ff_timestamp_monotonicity_offset; ++ if (ist->next_pts != AV_NOPTS_VALUE) { ++ ff_pts_error = av_rescale_q(ist->next_pts, AV_TIME_BASE_Q, ist->st->time_base) - pkt->pts; ++ } ++ } ++ if (pkt->dts != AV_NOPTS_VALUE) { ++ pkt->dts += ifile->ff_timestamp_monotonicity_offset; ++ if (ist->next_dts != AV_NOPTS_VALUE) { ++ ff_dts_error = av_rescale_q(ist->next_dts, AV_TIME_BASE_Q, ist->st->time_base) - pkt->dts; ++ } ++ } ++ ++ if (ff_dts_error > 0 || ff_dts_error < (-ff_dts_threshold) || ff_pts_error < (-ff_dts_threshold)) { ++ if (pkt->dts == AV_NOPTS_VALUE /*|| ist->next_dts != AV_NOPTS_VALUE*/) { ++ pkt->pts += ff_pts_error; ++ ifile->ff_timestamp_monotonicity_offset += ff_pts_error; ++ av_log(is, AV_LOG_INFO, "Incoming PTS error %"PRId64", offsetting subsequent timestamps by %"PRId64" to correct\n", ff_pts_error, ifile->ff_timestamp_monotonicity_offset); ++ } ++ else { ++ pkt->pts += ff_dts_error; ++ pkt->dts += ff_dts_error; ++ ifile->ff_timestamp_monotonicity_offset += ff_dts_error; ++ av_log(is, AV_LOG_INFO, "Incoming DTS error %"PRId64", offsetting subsequent timestamps by %"PRId64" to correct\n", ff_dts_error, ifile->ff_timestamp_monotonicity_offset); ++ } ++ } ++ } ++ + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", + ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), +diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h +index 606f2af..87775d4 100644 +--- a/fftools/ffmpeg.h ++++ b/fftools/ffmpeg.h +@@ -428,6 +428,10 @@ typedef struct InputFile { + int joined; /* the thread has been joined */ + int thread_queue_size; /* maximum number of queued packets */ + #endif ++ ++ // A value added to inbound timestamps to prevent them from going "backward" in cases such as HLS discontinuities ++ int64_t ff_timestamp_monotonicity_offset; ++ + } InputFile; + + enum forced_keyframes_const { +@@ -605,6 +609,9 @@ extern float audio_drift_threshold; + extern float dts_delta_threshold; + extern float dts_error_threshold; + ++extern int dts_monotonicity_threshold; ++extern int force_dts_monotonicity; ++ + extern int audio_volume; + extern int audio_sync_method; + extern int video_sync_method; +diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c +index 807e783..8389bce 100644 +--- a/fftools/ffmpeg_opt.c ++++ b/fftools/ffmpeg_opt.c +@@ -151,6 +151,9 @@ float audio_drift_threshold = 0.1; + float dts_delta_threshold = 10; + float dts_error_threshold = 3600*30; + ++int dts_monotonicity_threshold = AV_TIME_BASE; ++int force_dts_monotonicity = 0; ++ + int audio_volume = 256; + int audio_sync_method = 0; + int video_sync_method = VSYNC_AUTO; +@@ -1274,6 +1277,7 @@ static int open_input_file(OptionsContext *o, const char *filename) + f->recording_time = o->recording_time; + f->input_ts_offset = o->input_ts_offset; + f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp); ++ f->ff_timestamp_monotonicity_offset = 0; + f->nb_streams = ic->nb_streams; + f->rate_emu = o->rate_emu; + f->accurate_seek = o->accurate_seek; +@@ -3538,6 +3542,10 @@ const OptionDef options[] = { + { "apad", OPT_STRING | HAS_ARG | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(apad) }, + "audio pad", "" }, ++ { "force_dts_monotonicity", OPT_BOOL | OPT_EXPERT, { &force_dts_monotonicity }, ++ "correct dts monotonicity errors" }, ++ { "dts_monotonicity_threshold", HAS_ARG | OPT_INT | OPT_EXPERT, { &dts_monotonicity_threshold }, ++ "dts correction threshold for forward jumps", "microseconds" }, + { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_delta_threshold }, + "timestamp discontinuity delta threshold", "threshold" }, + { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_error_threshold },