Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ on:
type: boolean
default: false
required: false
schedule:
- cron: '0 12 * * *'
# schedule:
# - cron: '0 12 * * *'

env:
DOCKER_BUILDKIT: 1
Expand Down
1 change: 1 addition & 0 deletions addins/4.4.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/4.4"
PATCHES_DIR="patches/ffmpeg/older"
1 change: 1 addition & 0 deletions addins/5.0.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/5.0"
PATCHES_DIR="patches/ffmpeg/older"
1 change: 1 addition & 0 deletions addins/5.1.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/5.1"
PATCHES_DIR="patches/ffmpeg/older"
1 change: 1 addition & 0 deletions addins/6.0.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/6.0"
PATCHES_DIR="patches/ffmpeg/older"
1 change: 1 addition & 0 deletions addins/6.1.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/6.1"
PATCHES_DIR="patches/ffmpeg/older"
1 change: 1 addition & 0 deletions addins/7.0.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/7.0"
PATCHES_DIR="patches/ffmpeg/v7"
3 changes: 2 additions & 1 deletion addins/7.1.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/bash
GIT_BRANCH="release/7.1"
GIT_BRANCH="descript/7.1"
PATCHES_DIR="patches/ffmpeg/v7.1"
5 changes: 3 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ fi
rm -rf ffbuild
mkdir ffbuild

FFMPEG_REPO="${FFMPEG_REPO:-https://github.com/FFmpeg/FFmpeg.git}"
FFMPEG_REPO="${FFMPEG_REPO:-https://github.com/descriptinc/FFmpeg.git}"
FFMPEG_REPO="${FFMPEG_REPO_OVERRIDE:-$FFMPEG_REPO}"
GIT_BRANCH="${GIT_BRANCH:-master}"
GIT_BRANCH="${GIT_BRANCH_OVERRIDE:-$GIT_BRANCH}"
PATCHES_DIR="$PWD/${PATCHES_DIR:-patches/ffmpeg/v7}"

BUILD_SCRIPT="$(mktemp)"
trap "rm -f -- '$BUILD_SCRIPT'" EXIT
Expand All @@ -46,7 +47,7 @@ EOF

[[ -t 1 ]] && TTY_ARG="-t" || TTY_ARG=""

docker run --rm -i $TTY_ARG "${UIDARGS[@]}" -v "$PWD/ffbuild":/ffbuild -v "$BUILD_SCRIPT":/build.sh "$IMAGE" bash /build.sh
docker run --rm -i $TTY_ARG "${UIDARGS[@]}" -v "$PWD/ffbuild":/ffbuild -v "$BUILD_SCRIPT":/build.sh -v "$PATCHES_DIR":/patches "$IMAGE" bash /build.sh

if [[ -n "$FFBUILD_OUTPUT_DIR" ]]; then
mkdir -p "$FFBUILD_OUTPUT_DIR"
Expand Down
80 changes: 80 additions & 0 deletions patches/ffmpeg/older/001-ffmpeg-add-force-cfr-flag.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 25604e05a5..fedd4d4308 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -282,6 +282,9 @@ typedef struct OptionsContext {
int nb_enc_stats_post_fmt;
SpecifierOpt *mux_stats_fmt;
int nb_mux_stats_fmt;
+ SpecifierOpt *force_cfr;
+ int nb_force_cfr;
+
} OptionsContext;

typedef struct InputFilter {
@@ -416,6 +419,7 @@ typedef struct InputFile {
int64_t ts_offset;
int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */
int64_t recording_time;
+ double force_cfr;

/* streams that ffmpeg is aware of;
* there may be extra streams in ctx that are not mapped to an InputStream
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 350f233ab7..2c1e1a1d3e 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1589,6 +1589,9 @@ int ifile_open(const OptionsContext *o, const char *filename)
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->accurate_seek = o->accurate_seek;
+ if (o->force_cfr) {
+ f->force_cfr = o->force_cfr[o->nb_force_cfr-1].u.dbl;
+ }
d->loop = o->loop;
d->duration = 0;
d->time_base = (AVRational){ 1, 1 };
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index c738fc3397..b4527aba09 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1483,13 +1483,23 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
return ret;
}

- snprintf(name, sizeof(name), "trim_in_%d_%d",
- ist->file_index, ist->index);
if (copy_ts) {
tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time;
if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE)
tsoffset += f->ctx->start_time;
}
+
+ if (f->force_cfr > 0) {
+ char fps_buf[20];
+ snprintf(fps_buf,sizeof(fps_buf),"%0.4f",f->force_cfr);
+ ret = insert_filter(&last_filter, &pad_idx, "fps", fps_buf);
+ if (ret < 0)
+ goto fail;
+ }
+
+ snprintf(name, sizeof(name), "trim_in_%d_%d",
+ ist->file_index, ist->index);
+
ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ?
AV_NOPTS_VALUE : tsoffset, f->recording_time,
&last_filter, &pad_idx, name);
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 304471dd03..0a8f461493 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1850,6 +1850,9 @@ const OptionDef options[] = {
"initialise hardware device", "args" },
{ "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_hw_device },
"set hardware device used when filtering", "device" },
+ { "force_cfr", OPT_VIDEO | HAS_ARG | OPT_DOUBLE | OPT_SPEC |
+ OPT_INPUT, { .off = OFFSET(force_cfr) },
+ "set frame rate (Hz value, fraction or abbreviation)", "rate" },

{ NULL, },
};
106 changes: 106 additions & 0 deletions patches/ffmpeg/v7.1/001-ffmpeg-add-force-cfr-flag.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 733d551fa4..06474f1b3c 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -176,6 +176,7 @@ typedef struct OptionsContext {
SpecifierOptList hwaccel_output_formats;
SpecifierOptList autorotate;
SpecifierOptList apply_cropping;
+ SpecifierOptList force_cfr;

/* output options */
StreamMap *stream_maps;
@@ -276,6 +277,9 @@ typedef struct InputFilterOptions {
* accurate */
AVRational framerate;

+ /* convert input stream to CFR at this framerate before inserting additional filters */
+ AVRational force_cfr;
+
unsigned crop_top;
unsigned crop_bottom;
unsigned crop_left;
@@ -451,6 +455,9 @@ typedef struct InputStream {

/* framerate forced with -r */
AVRational framerate;
+
+ /* convert input stream to CFR at this framerate before inserting additional filters */
+ AVRational force_cfr;
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 13aef15eab..9c500b7936 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1032,6 +1032,10 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple,
(opts->crop_top | opts->crop_bottom | opts->crop_left | opts->crop_right))
opts->flags |= IFILTER_FLAG_CROP;
}
+ if (ist->force_cfr.num > 0 && ist->force_cfr.den > 0) {
+ opts->force_cfr = ist->force_cfr;
+ opts->flags |= IFILTER_FLAG_CFR;
+ }
} else if (ist->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
/* Compute the size of the canvas for the subtitles stream.
If the subtitles codecpar has set a size, use it. Otherwise use the
@@ -1241,7 +1245,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
AVCodecParameters *par = st->codecpar;
DemuxStream *ds;
InputStream *ist;
- const char *framerate = NULL, *hwaccel_device = NULL;
+ const char *framerate = NULL, *hwaccel_device = NULL, *forcecfr = NULL;
const char *hwaccel = NULL;
const char *apply_cropping = NULL;
const char *hwaccel_output_format = NULL;
@@ -1437,6 +1441,15 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
}
}

+ opt_match_per_stream_str(ist, &o->force_cfr, ic, st, &forcecfr);
+ if (forcecfr) {
+ ret = av_parse_video_rate(&ist->force_cfr, forcecfr);
+ if (ret < 0) {
+ av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", forcecfr);
+ return ret;
+ }
+ }
+
#if FFMPEG_OPT_TOP
ist->top_field_first = -1;
opt_match_per_stream_int(ist, &o->top_field_first, ic, st, &ist->top_field_first);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 38c7676a7e..62dd23ebe4 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1781,6 +1781,15 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
ifp->displaymatrix_applied = 1;
}

+ if (ifp->opts.force_cfr.num > 0 && ifp->opts.force_cfr.den > 0) {
+ char force_cfr_buf[64];
+ snprintf(force_cfr_buf, sizeof(force_cfr_buf), "%d/%d",
+ ifp->opts.force_cfr.num, ifp->opts.force_cfr.den);
+ ret = insert_filter(&last_filter, &pad_idx, "fps", force_cfr_buf);
+ if (ret < 0)
+ return ret;
+ }
+
snprintf(name, sizeof(name), "trim_in_%s", ifp->opts.name);
ret = insert_trim(ifp->opts.trim_start_us, ifp->opts.trim_end_us,
&last_filter, &pad_idx, name);
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index f639a1cf0a..ce5aabcb59 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2033,5 +2033,9 @@ const OptionDef options[] = {
"set video sync method globally; deprecated, use -fps_mode", "" },
#endif

+ { "force_cfr", OPT_TYPE_STRING, OPT_VIDEO | OPT_EXPERT | OPT_PERSTREAM | OPT_INPUT,
+ { .off = OFFSET(force_cfr) },
+ "set frame rate (Hz value, fraction or abbreviation)", "force_cfr" },
+
{ NULL, },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
diff --git a/libavformat/mov.c b/libavformat/mov.c
index ff32d4160e..38109d8eb5 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -87,6 +87,7 @@ static int mov_read_mfra(MOVContext *c, AVIOContext *f);
static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
int count, int duration);
+static int mov_switch_root(AVFormatContext *s, int64_t target, int index);

static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
unsigned len, const char *key)
@@ -1638,6 +1639,7 @@ static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
MOVFragmentStreamInfo * frag_stream_info;
MOVStreamContext *sc = dst_st->priv_data;
int64_t timestamp;
+ int stream_present;
int i, j;

// If the stream is referenced by any sidx, limit the search
@@ -1653,6 +1655,26 @@ static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
return frag_stream_info->sidx_pts;
}

+ // Check if the requested stream is present in the fragment
+ stream_present = 0;
+ for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
+ if (dst_st->id != frag_index->item[index].stream_info[i].id)
+ continue;
+ if ( get_stream_info_time(&frag_index->item[index].stream_info[i]) != AV_NOPTS_VALUE) {
+ stream_present = 1;
+ break;
+ }
+ if ( mov_switch_root(s,-1,index) < 0)
+ return AV_NOPTS_VALUE;
+ if ( get_stream_info_time(&frag_index->item[index].stream_info[i]) != AV_NOPTS_VALUE) {
+ stream_present = 1;
+ break;
+ }
+ }
+
+ if (!stream_present)
+ return AV_NOPTS_VALUE;
+
for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
AVStream *frag_stream = NULL;
frag_stream_info = &frag_index->item[index].stream_info[i];
Loading