mirror of
https://github.com/datarhei/ffmpeg
synced 2025-12-24 13:08:07 +08:00
Update patches
This commit is contained in:
@@ -16,7 +16,7 @@ jobs:
|
||||
os: ubuntu
|
||||
os_version: "24.04"
|
||||
platforms: linux/amd64
|
||||
cuda_version: "12.8.0"
|
||||
cuda_version: "12.8.1"
|
||||
ffnvcodec_version: "12.2.72.0"
|
||||
ffmpeg_version: "7.1.1"
|
||||
steps:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
From 763304129a1fb2e347c870b1250b90a696ee4317 Mon Sep 17 00:00:00 2001
|
||||
From 014b594a77161a7b4ffb5d63846547bb176fe6ba Mon Sep 17 00:00:00 2001
|
||||
From: Ingo Oppermann <ingo@datarhei.com>
|
||||
Date: Mon, 20 Jan 2025 17:32:20 +0100
|
||||
Subject: [PATCH v3] hls (7.1.0)
|
||||
Date: Wed, 22 Oct 2025 17:28:57 +0200
|
||||
Subject: [PATCH v2] hls (7.1.1)
|
||||
|
||||
---
|
||||
README.HLS.md | 48 +++++++++++++++++++++++++++
|
||||
libavformat/hlsenc.c | 79 ++++++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 125 insertions(+), 2 deletions(-)
|
||||
README.HLS.md | 48 ++++++++++++++++++++
|
||||
libavformat/hlsenc.c | 104 +++++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 149 insertions(+), 3 deletions(-)
|
||||
create mode 100644 README.HLS.md
|
||||
|
||||
diff --git a/README.HLS.md b/README.HLS.md
|
||||
@@ -64,10 +64,18 @@ index 00000000..5462338b
|
||||
+
|
||||
+In the command, the `-var_stream_map` option had the value `v:0,a:0 v:1,a:1`.
|
||||
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
|
||||
index 1e932b7b..11a3f0dd 100644
|
||||
index 081d91f7..14fa5480 100644
|
||||
--- a/libavformat/hlsenc.c
|
||||
+++ b/libavformat/hlsenc.c
|
||||
@@ -125,6 +125,7 @@ typedef struct VariantStream {
|
||||
@@ -109,6 +109,7 @@ typedef enum HLSFlags {
|
||||
HLS_PERIODIC_REKEY = (1 << 12),
|
||||
HLS_INDEPENDENT_SEGMENTS = (1 << 13),
|
||||
HLS_I_FRAMES_ONLY = (1 << 14),
|
||||
+ HLS_ADJUST_SEQUENCE = (1 << 15),
|
||||
} HLSFlags;
|
||||
|
||||
typedef enum {
|
||||
@@ -125,6 +126,7 @@ typedef struct VariantStream {
|
||||
AVIOContext *out;
|
||||
AVIOContext *out_single_file;
|
||||
int packets_written;
|
||||
@@ -75,7 +83,7 @@ index 1e932b7b..11a3f0dd 100644
|
||||
int init_range_length;
|
||||
uint8_t *temp_buffer;
|
||||
uint8_t *init_buffer;
|
||||
@@ -139,6 +140,8 @@ typedef struct VariantStream {
|
||||
@@ -139,6 +141,8 @@ typedef struct VariantStream {
|
||||
double dpp; // duration per packet
|
||||
int64_t start_pts;
|
||||
int64_t end_pts;
|
||||
@@ -84,7 +92,16 @@ index 1e932b7b..11a3f0dd 100644
|
||||
int64_t video_lastpos;
|
||||
int64_t video_keyframe_pos;
|
||||
int64_t video_keyframe_size;
|
||||
@@ -1507,6 +1510,16 @@ static int create_master_playlist(AVFormatContext *s,
|
||||
@@ -1503,12 +1507,28 @@ static int create_master_playlist(AVFormatContext *s,
|
||||
if (final) {
|
||||
bandwidth = vs->max_bitrate;
|
||||
avg_bandwidth = vs->avg_bitrate;
|
||||
+ if (avg_bandwidth < 0) {
|
||||
+ avg_bandwidth = 0;
|
||||
+ }
|
||||
} else {
|
||||
bandwidth = 0;
|
||||
if (vid_st)
|
||||
bandwidth += get_stream_bit_rate(vid_st);
|
||||
if (aud_st)
|
||||
bandwidth += get_stream_bit_rate(aud_st);
|
||||
@@ -92,6 +109,9 @@ index 1e932b7b..11a3f0dd 100644
|
||||
+ if (bandwidth == 0) {
|
||||
+ // Estimate bandwidth
|
||||
+ bandwidth = (int)round((double)vs->bytes_written / (av_q2d(AV_TIME_BASE_Q) * (vs->scaled_cur_pts - vs->scaled_start_pts)) * 8);
|
||||
+ if (bandwidth < 0) {
|
||||
+ bandwidth = 0;
|
||||
+ }
|
||||
+
|
||||
+ // Reset counters
|
||||
+ vs->bytes_written = 0;
|
||||
@@ -101,7 +121,33 @@ index 1e932b7b..11a3f0dd 100644
|
||||
bandwidth += bandwidth / 10;
|
||||
}
|
||||
|
||||
@@ -2475,6 +2488,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
@@ -2439,7 +2459,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
HLSContext *hls = s->priv_data;
|
||||
AVFormatContext *oc = NULL;
|
||||
AVStream *st = s->streams[pkt->stream_index];
|
||||
- int64_t end_pts = 0;
|
||||
+ int64_t end_pts = 0, max_sequence = 0;
|
||||
int is_ref_pkt = 1;
|
||||
int ret = 0, can_split = 1, i, j;
|
||||
int stream_index = 0;
|
||||
@@ -2449,6 +2469,16 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
VariantStream *vs = NULL;
|
||||
char *old_filename = NULL;
|
||||
|
||||
+ if (hls->flags & HLS_ADJUST_SEQUENCE) {
|
||||
+ for (i = 0; i < hls->nb_varstreams; i++) {
|
||||
+ vs = &hls->var_streams[i];
|
||||
+
|
||||
+ if (vs->sequence > max_sequence) {
|
||||
+ max_sequence = vs->sequence;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < hls->nb_varstreams; i++) {
|
||||
int subtitle_streams = 0;
|
||||
vs = &hls->var_streams[i];
|
||||
@@ -2477,6 +2507,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
@@ -121,7 +167,7 @@ index 1e932b7b..11a3f0dd 100644
|
||||
end_pts = hls->recording_time * vs->number;
|
||||
|
||||
if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
|
||||
@@ -2523,8 +2549,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
@@ -2525,8 +2568,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
}
|
||||
|
||||
can_split = can_split && (pkt->pts - vs->end_pts > 0);
|
||||
@@ -132,7 +178,19 @@ index 1e932b7b..11a3f0dd 100644
|
||||
int64_t new_start_pos;
|
||||
int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
|
||||
double cur_duration;
|
||||
@@ -2700,6 +2726,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
@@ -2643,6 +2686,11 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
|
||||
cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
|
||||
ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
|
||||
+ if ((hls->flags & HLS_ADJUST_SEQUENCE) && vs->sequence < max_sequence) {
|
||||
+ av_log(s, AV_LOG_WARNING, "fixing sequence number of variant %s.\n", vs->m3u8_name);
|
||||
+ vs->sequence = max_sequence + 1;
|
||||
+ vs->discontinuity = 1;
|
||||
+ }
|
||||
vs->end_pts = pkt->pts;
|
||||
vs->duration = 0;
|
||||
if (ret < 0) {
|
||||
@@ -2702,6 +2750,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
}
|
||||
|
||||
vs->packets_written++;
|
||||
@@ -140,7 +198,7 @@ index 1e932b7b..11a3f0dd 100644
|
||||
if (oc->pb) {
|
||||
ret = ff_write_chained(oc, stream_index, pkt, s, 0);
|
||||
vs->video_keyframe_size += pkt->size;
|
||||
@@ -2888,6 +2915,49 @@ failed:
|
||||
@@ -2890,6 +2939,49 @@ failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -190,7 +248,7 @@ index 1e932b7b..11a3f0dd 100644
|
||||
|
||||
static int hls_init(AVFormatContext *s)
|
||||
{
|
||||
@@ -2995,6 +3065,8 @@ static int hls_init(AVFormatContext *s)
|
||||
@@ -2997,6 +3089,8 @@ static int hls_init(AVFormatContext *s)
|
||||
vs->sequence = hls->start_sequence;
|
||||
vs->start_pts = AV_NOPTS_VALUE;
|
||||
vs->end_pts = AV_NOPTS_VALUE;
|
||||
@@ -199,7 +257,7 @@ index 1e932b7b..11a3f0dd 100644
|
||||
vs->current_segment_final_filename_fmt[0] = '\0';
|
||||
vs->initial_prog_date_time = initial_program_date_time;
|
||||
|
||||
@@ -3137,6 +3209,9 @@ static int hls_init(AVFormatContext *s)
|
||||
@@ -3139,6 +3233,9 @@ static int hls_init(AVFormatContext *s)
|
||||
vs->number++;
|
||||
}
|
||||
|
||||
@@ -209,8 +267,16 @@ index 1e932b7b..11a3f0dd 100644
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3183,6 +3280,7 @@ static const AVOption options[] = {
|
||||
{"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, .unit = "flags"},
|
||||
{"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
|
||||
{"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, .unit = "flags"},
|
||||
+ {"adjust_sequence", "adjust sequence numbers of variants if they diverge", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_ADJUST_SEQUENCE }, 0, UINT_MAX, E, .unit = "flags"},
|
||||
{"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
|
||||
{"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
|
||||
{"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, .unit = "pl_type" },
|
||||
|
||||
base-commit: e1601d14100f6c7d088eba676d9555118ca94931
|
||||
base-commit: c526666f8869a5fffb04fbfeb862cde13338b001
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
2.50.1 (Apple Git-155)
|
||||
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
From 70ca589dd67895bb87b403d97f899d08f9999b08 Mon Sep 17 00:00:00 2001
|
||||
From 399e6b27c4b308352554d3ef84329c854330fe83 Mon Sep 17 00:00:00 2001
|
||||
From: Ingo Oppermann <ingo@datarhei.com>
|
||||
Date: Wed, 8 Jan 2025 13:29:22 +0100
|
||||
Subject: [PATCH v2] progress (7.1.0)
|
||||
Date: Thu, 21 Aug 2025 11:42:34 +0200
|
||||
Subject: [PATCH v1] progress (7.1.1)
|
||||
|
||||
---
|
||||
README.PROGRESS.md | 759 ++++++++++++++++++++++++++++++++++++++++
|
||||
README.PROGRESS.md | 759 ++++++++++++++++++++++++++++++++++
|
||||
fftools/Makefile | 1 +
|
||||
fftools/ffmpeg.c | 35 +-
|
||||
fftools/ffmpeg.h | 1 +
|
||||
fftools/ffmpeg_demux.c | 149 +++-----
|
||||
fftools/ffmpeg_demux.h | 163 +++++++++
|
||||
fftools/ffmpeg_demux.c | 149 ++-----
|
||||
fftools/ffmpeg_demux.h | 163 ++++++++
|
||||
fftools/ffmpeg_filter.c | 10 +-
|
||||
fftools/ffmpeg_json.c | 668 +++++++++++++++++++++++++++++++++++
|
||||
fftools/ffmpeg_json.c | 888 ++++++++++++++++++++++++++++++++++++++++
|
||||
fftools/ffmpeg_json.h | 16 +
|
||||
fftools/ffmpeg_mux.c | 50 ++-
|
||||
fftools/ffmpeg_mux.h | 19 +-
|
||||
fftools/ffmpeg_opt.c | 6 +
|
||||
12 files changed, 1763 insertions(+), 114 deletions(-)
|
||||
fftools/ffmpeg_sched.c | 6 +-
|
||||
libavformat/fifo.c | 7 +
|
||||
libavformat/tee.c | 15 +-
|
||||
15 files changed, 2006 insertions(+), 119 deletions(-)
|
||||
create mode 100644 README.PROGRESS.md
|
||||
create mode 100644 fftools/ffmpeg_demux.h
|
||||
create mode 100644 fftools/ffmpeg_json.c
|
||||
@@ -1246,7 +1249,7 @@ index 00000000..709aba7a
|
||||
+#endif /* FFTOOLS_FFMPEG_DEMUX_H */
|
||||
\ No newline at end of file
|
||||
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
|
||||
index 7ec328e0..814b5761 100644
|
||||
index 38c7676a..b2e68bd1 100644
|
||||
--- a/fftools/ffmpeg_filter.c
|
||||
+++ b/fftools/ffmpeg_filter.c
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -1274,7 +1277,7 @@ index 7ec328e0..814b5761 100644
|
||||
av_freep(&fgp->nb_threads);
|
||||
|
||||
av_frame_free(&fgp->frame);
|
||||
@@ -2019,6 +2023,10 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
|
||||
@@ -2024,6 +2028,10 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1288,7 @@ index 7ec328e0..814b5761 100644
|
||||
return 0;
|
||||
fail:
|
||||
cleanup_filtergraph(fg, fgt);
|
||||
@@ -2917,7 +2925,7 @@ static void fg_thread_uninit(FilterGraphThread *fgt)
|
||||
@@ -2922,7 +2930,7 @@ static void fg_thread_uninit(FilterGraphThread *fgt)
|
||||
av_freep(&fgt->eof_in);
|
||||
av_freep(&fgt->eof_out);
|
||||
|
||||
@@ -1296,10 +1299,10 @@ index 7ec328e0..814b5761 100644
|
||||
}
|
||||
diff --git a/fftools/ffmpeg_json.c b/fftools/ffmpeg_json.c
|
||||
new file mode 100644
|
||||
index 00000000..b63110e1
|
||||
index 00000000..381e2566
|
||||
--- /dev/null
|
||||
+++ b/fftools/ffmpeg_json.c
|
||||
@@ -0,0 +1,668 @@
|
||||
@@ -0,0 +1,888 @@
|
||||
+#include <stdint.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
@@ -1322,6 +1325,56 @@ index 00000000..b63110e1
|
||||
+#include "libavformat/internal.h"
|
||||
+#include "libavcodec/avcodec.h"
|
||||
+
|
||||
+static void append_disposition(AVBPrint *buf, int disposition)
|
||||
+{
|
||||
+ av_bprintf(buf, "\"disposition\":[");
|
||||
+
|
||||
+ if (disposition & AV_DISPOSITION_DEFAULT)
|
||||
+ av_bprintf(buf, "\"default\",");
|
||||
+ if (disposition & AV_DISPOSITION_DUB)
|
||||
+ av_bprintf(buf, "\"dub\",");
|
||||
+ if (disposition & AV_DISPOSITION_ORIGINAL)
|
||||
+ av_bprintf(buf, "\"original\",");
|
||||
+ if (disposition & AV_DISPOSITION_COMMENT)
|
||||
+ av_bprintf(buf, "\"comment\",");
|
||||
+ if (disposition & AV_DISPOSITION_LYRICS)
|
||||
+ av_bprintf(buf, "\"lyrics\",");
|
||||
+ if (disposition & AV_DISPOSITION_KARAOKE)
|
||||
+ av_bprintf(buf, "\"karaoke\",");
|
||||
+ if (disposition & AV_DISPOSITION_FORCED)
|
||||
+ av_bprintf(buf, "\"forced\",");
|
||||
+ if (disposition & AV_DISPOSITION_HEARING_IMPAIRED)
|
||||
+ av_bprintf(buf, "\"hearing impaired\",");
|
||||
+ if (disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
|
||||
+ av_bprintf(buf, "\"visual impaired\",");
|
||||
+ if (disposition & AV_DISPOSITION_CLEAN_EFFECTS)
|
||||
+ av_bprintf(buf, "\"clean effects\",");
|
||||
+ if (disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||
+ av_bprintf(buf, "\"attached pic\",");
|
||||
+ if (disposition & AV_DISPOSITION_TIMED_THUMBNAILS)
|
||||
+ av_bprintf(buf, "\"timed thumbnails\",");
|
||||
+ if (disposition & AV_DISPOSITION_CAPTIONS)
|
||||
+ av_bprintf(buf, "\"captions\",");
|
||||
+ if (disposition & AV_DISPOSITION_DESCRIPTIONS)
|
||||
+ av_bprintf(buf, "\"descriptions\",");
|
||||
+ if (disposition & AV_DISPOSITION_METADATA)
|
||||
+ av_bprintf(buf, "\"metadata\",");
|
||||
+ if (disposition & AV_DISPOSITION_DEPENDENT)
|
||||
+ av_bprintf(buf, "\"dependent\",");
|
||||
+ if (disposition & AV_DISPOSITION_STILL_IMAGE)
|
||||
+ av_bprintf(buf, "\"still image\",");
|
||||
+ if (disposition & AV_DISPOSITION_NON_DIEGETIC)
|
||||
+ av_bprintf(buf, "\"non-diegetic\",");
|
||||
+ if (disposition & AV_DISPOSITION_MULTILAYER)
|
||||
+ av_bprintf(buf, "\"multilayer\",");
|
||||
+
|
||||
+ if(buf->str[buf->len-1] == ',') {
|
||||
+ buf->len--;
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, "]");
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Print all inputs in JSON format
|
||||
+ */
|
||||
@@ -1371,10 +1424,11 @@ index 00000000..b63110e1
|
||||
+ avcodec_get_name(st->codecpar->codec_id),
|
||||
+ st->codecpar->bit_rate / 1000);
|
||||
+ av_bprintf(&buf,
|
||||
+ "\"duration_sec\":%f,\"language\":\"%s\",\"profile\":%d,\"level\":%d",
|
||||
+ "\"duration_sec\":%f,\"language\":\"%s\",\"profile\":%d,\"level\":%d,",
|
||||
+ duration,
|
||||
+ lang != NULL ? lang->value : "und",
|
||||
+ st->codecpar->profile, st->codecpar->level);
|
||||
+ append_disposition(&buf, st->disposition);
|
||||
+
|
||||
+ av_free(url);
|
||||
+
|
||||
@@ -1423,6 +1477,99 @@ index 00000000..b63110e1
|
||||
+ av_bprint_finalize(&buf, NULL);
|
||||
+}
|
||||
+
|
||||
+typedef enum SlaveFailurePolicy {
|
||||
+ ON_SLAVE_FAILURE_ABORT = 1,
|
||||
+ ON_SLAVE_FAILURE_IGNORE = 2
|
||||
+} SlaveFailurePolicy;
|
||||
+
|
||||
+typedef struct TeeSlave {
|
||||
+ AVFormatContext *avf;
|
||||
+ AVBSFContext **bsfs;
|
||||
+ SlaveFailurePolicy on_fail;
|
||||
+ int use_fifo;
|
||||
+ AVDictionary *fifo_options;
|
||||
+ int *stream_map;
|
||||
+ int header_written;
|
||||
+ char *id;
|
||||
+ char *filename;
|
||||
+} TeeSlave;
|
||||
+
|
||||
+typedef struct TeeContext {
|
||||
+ const AVClass *class;
|
||||
+ unsigned nb_slaves;
|
||||
+ unsigned nb_alive;
|
||||
+ TeeSlave *slaves;
|
||||
+} TeeContext;
|
||||
+
|
||||
+/**
|
||||
+ * Append all tee outputs for a context in JSON format
|
||||
+ *
|
||||
+ * @param buf The AVBPrint buffer to which the JSON output will be appended.
|
||||
+ * @param ofctx The AVFormatContext for the output, which contains the TeeContext.
|
||||
+ */
|
||||
+static void append_outputs_tee(AVBPrint *buf, AVFormatContext *ofctx)
|
||||
+{
|
||||
+ TeeContext *tc;
|
||||
+ const char *format_name, *base_format;
|
||||
+ char *address;
|
||||
+
|
||||
+ tc = (TeeContext *)ofctx->priv_data;
|
||||
+ if (!tc || tc->nb_slaves == 0 || !tc->slaves) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, ",\"tee\":[");
|
||||
+
|
||||
+ for (unsigned int i = 0; i < tc->nb_slaves; i++) {
|
||||
+ uint8_t *fifo_fmt_opt = NULL;
|
||||
+ TeeSlave *slave = &tc->slaves[i];
|
||||
+ AVFormatContext *slave_ctx = slave->avf;
|
||||
+
|
||||
+ format_name = "";
|
||||
+
|
||||
+ if (slave_ctx && slave_ctx->oformat) {
|
||||
+ base_format = slave_ctx->oformat->name ? slave_ctx->oformat->name : "";
|
||||
+ format_name = base_format;
|
||||
+
|
||||
+ fifo_fmt_opt = NULL;
|
||||
+ if (strcmp(base_format, "fifo") == 0) {
|
||||
+ uint8_t *fifo_fmt_opt = NULL;
|
||||
+
|
||||
+ if (av_opt_get(slave_ctx->priv_data, "fifo_format", AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &fifo_fmt_opt) >= 0) {
|
||||
+ if(fifo_fmt_opt && fifo_fmt_opt[0] != '\0') {
|
||||
+ format_name = (const char *)fifo_fmt_opt;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ address = NULL;
|
||||
+ if (av_escape(&address,
|
||||
+ slave->filename ? slave->filename : "",
|
||||
+ "\\\"",
|
||||
+ AV_ESCAPE_MODE_BACKSLASH,
|
||||
+ AV_UTF8_FLAG_ACCEPT_ALL) < 0) {
|
||||
+ address = av_strdup("-");
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, "{\"id\":\"%s\",\"address\":\"%s\",\"format\":\"%s\",\"fifo_enabled\":%s}",
|
||||
+ slave->id ? slave->id : "", address, format_name, slave->use_fifo == 1 ? "true" : "false");
|
||||
+
|
||||
+ av_free(address);
|
||||
+ if (fifo_fmt_opt) {
|
||||
+ av_free(fifo_fmt_opt);
|
||||
+ }
|
||||
+
|
||||
+ if (i < tc->nb_slaves - 1) {
|
||||
+ av_bprintf(buf, ",");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, "]");
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Print all outputs in JSON format
|
||||
+ */
|
||||
@@ -1465,13 +1612,14 @@ index 00000000..b63110e1
|
||||
+ ",",
|
||||
+ av_get_media_type_string(st->codecpar->codec_type),
|
||||
+ avcodec_get_name(st->codecpar->codec_id),
|
||||
+ !ost->enc ? "copy" : "unknown",
|
||||
+ ost->enc_ctx ? (ost->enc_ctx->codec ? ost->enc_ctx->codec->name : "unknown") : "copy",
|
||||
+ st->codecpar->bit_rate / 1000);
|
||||
+ av_bprintf(&buf,
|
||||
+ "\"duration_sec\":%f,\"language\":\"%s\",\"profile\":%d,\"level\":%d",
|
||||
+ "\"duration_sec\":%f,\"language\":\"%s\",\"profile\":%d,\"level\":%d,",
|
||||
+ 0.0,
|
||||
+ lang != NULL ? lang->value : "und",
|
||||
+ st->codecpar->profile, st->codecpar->level);
|
||||
+ append_disposition(&buf, st->disposition);
|
||||
+
|
||||
+ av_free(url);
|
||||
+
|
||||
@@ -1499,6 +1647,10 @@ index 00000000..b63110e1
|
||||
+ st->codecpar->ch_layout.nb_channels);
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(ctx->oformat->name, "tee")) {
|
||||
+ append_outputs_tee(&buf, ctx);
|
||||
+ }
|
||||
+
|
||||
+ if(ost_iter(ost) == NULL) {
|
||||
+ av_bprintf(&buf, "}");
|
||||
+ } else {
|
||||
@@ -1521,6 +1673,70 @@ index 00000000..b63110e1
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+typedef struct FifoContext {
|
||||
+ const AVClass *class;
|
||||
+ AVFormatContext *avf;
|
||||
+
|
||||
+ uint64_t total_recovery_attempts;
|
||||
+ int status; // 0 = alive, 1 = restarting, 2 = failed
|
||||
+} FifoContext;
|
||||
+
|
||||
+/**
|
||||
+ * Append all tee outputs to output in JSON format
|
||||
+ *
|
||||
+ * @param buf The AVBPrint buffer to which the JSON output will be appended.
|
||||
+ * @param ofc The AVFormatContext for the output, which contains the TeeContext.
|
||||
+ */
|
||||
+static void append_progress_tee(AVBPrint *buf, AVFormatContext *ofctx)
|
||||
+{
|
||||
+ TeeContext *tc;
|
||||
+
|
||||
+ tc = (TeeContext *)ofctx->priv_data;
|
||||
+ if (!tc || tc->nb_slaves == 0 || !tc->slaves) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, ",\"tee\":[");
|
||||
+
|
||||
+ for (unsigned int i = 0; i < tc->nb_slaves; i++) {
|
||||
+ const char *tee_state = "failed", *fifo_state = "";
|
||||
+ uint64_t total_recovery_attempts = 0;
|
||||
+ TeeSlave *slave = &tc->slaves[i];
|
||||
+ AVFormatContext *slave_ctx = slave->avf;
|
||||
+
|
||||
+ if(slave_ctx && slave_ctx->oformat) {
|
||||
+ tee_state = (slave_ctx->pb && slave_ctx->pb->error < 0) ? "failed" : "running";
|
||||
+
|
||||
+ if (!strcmp(slave_ctx->oformat->name, "fifo")) {
|
||||
+ FifoContext *fifo_ctx = (FifoContext *)slave_ctx->priv_data;
|
||||
+
|
||||
+ switch(fifo_ctx->status) {
|
||||
+ case 0: fifo_state = "running"; break;
|
||||
+ case 1: fifo_state = "restarting"; break;
|
||||
+ case 2: fifo_state = "failed"; break;
|
||||
+ default: fifo_state = "";
|
||||
+ }
|
||||
+
|
||||
+ total_recovery_attempts = fifo_ctx->total_recovery_attempts;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf,
|
||||
+ "{\"state\":\"%s\",\"fifo_recovery_attempts_total\":%"PRIu64",\"fifo_state\":\"%s\"}",
|
||||
+ tee_state,
|
||||
+ total_recovery_attempts,
|
||||
+ fifo_state);
|
||||
+
|
||||
+ if (i < tc->nb_slaves - 1) {
|
||||
+ av_bprintf(buf, ",");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ av_bprintf(buf, "]");
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Print progress report in JSON format
|
||||
+ *
|
||||
@@ -1593,7 +1809,10 @@ index 00000000..b63110e1
|
||||
+
|
||||
+ av_bprintf(&buf, "\"outputs\":[");
|
||||
+ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
+ MuxStream *ms = ms_from_ost(ost);
|
||||
+ MuxStream *ms = ms_from_ost(ost);
|
||||
+ OutputFile *of = output_files[ost->file->index];
|
||||
+ Muxer *mux = mux_from_of(of);
|
||||
+ AVFormatContext *ctx = mux ? mux->fc : NULL;
|
||||
+
|
||||
+ q = -1;
|
||||
+ if(ost->enc) {
|
||||
@@ -1639,6 +1858,10 @@ index 00000000..b63110e1
|
||||
+ av_bprintf(&buf, "\"size_kb\":%.0f,\"size_bytes\":%" PRIu64 ",", stream_size / 1024.0, stream_size);
|
||||
+ av_bprintf(&buf, "\"extradata_size_bytes\":%d", 0);
|
||||
+
|
||||
+ if (ctx && ctx->oformat && !strcmp(ctx->oformat->name, "tee")) {
|
||||
+ append_progress_tee(&buf, ctx);
|
||||
+ }
|
||||
+
|
||||
+ if(ost_iter(ost) == NULL) {
|
||||
+ av_bprintf(&buf, "}");
|
||||
+ } else {
|
||||
@@ -1733,7 +1956,7 @@ index 00000000..b63110e1
|
||||
+ avfilter_pad_get_name(link->srcpad, 0),
|
||||
+ avfilter_pad_get_name(link->dstpad, 0));
|
||||
+ av_bprintf(buf,
|
||||
+ "\"timebase\": \"%d/%d\",",
|
||||
+ "\"timebase\":\"%d/%d\",",
|
||||
+ link->time_base.num,
|
||||
+ link->time_base.den);
|
||||
+
|
||||
@@ -2128,8 +2351,140 @@ index f639a1cf..cb893874 100644
|
||||
{ "stats_period", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
|
||||
{ .func_arg = opt_stats_period },
|
||||
"set the period at which ffmpeg updates stats and -progress output", "time" },
|
||||
diff --git a/fftools/ffmpeg_sched.c b/fftools/ffmpeg_sched.c
|
||||
index ef0b6e28..6dc61923 100644
|
||||
--- a/fftools/ffmpeg_sched.c
|
||||
+++ b/fftools/ffmpeg_sched.c
|
||||
@@ -444,7 +444,7 @@ static void task_init(Scheduler *sch, SchTask *task, enum SchedulerNodeType type
|
||||
|
||||
static int64_t trailing_dts(const Scheduler *sch, int count_finished)
|
||||
{
|
||||
- int64_t min_dts = INT64_MAX;
|
||||
+ int64_t max_dts = INT64_MIN;
|
||||
|
||||
for (unsigned i = 0; i < sch->nb_mux; i++) {
|
||||
const SchMux *mux = &sch->mux[i];
|
||||
@@ -457,11 +457,11 @@ static int64_t trailing_dts(const Scheduler *sch, int count_finished)
|
||||
if (ms->last_dts == AV_NOPTS_VALUE)
|
||||
return AV_NOPTS_VALUE;
|
||||
|
||||
- min_dts = FFMIN(min_dts, ms->last_dts);
|
||||
+ max_dts = FFMAX(max_dts, ms->last_dts);
|
||||
}
|
||||
}
|
||||
|
||||
- return min_dts == INT64_MAX ? AV_NOPTS_VALUE : min_dts;
|
||||
+ return max_dts == INT64_MIN ? AV_NOPTS_VALUE : max_dts;
|
||||
}
|
||||
|
||||
void sch_free(Scheduler **psch)
|
||||
diff --git a/libavformat/fifo.c b/libavformat/fifo.c
|
||||
index 23e4149a..259f9fe6 100644
|
||||
--- a/libavformat/fifo.c
|
||||
+++ b/libavformat/fifo.c
|
||||
@@ -38,6 +38,9 @@ typedef struct FifoContext {
|
||||
const AVClass *class;
|
||||
AVFormatContext *avf;
|
||||
|
||||
+ uint64_t total_recovery_attempts;
|
||||
+ int status; // 0 = running, 1 = restarting, 2 = failed
|
||||
+
|
||||
char *format;
|
||||
AVDictionary *format_options;
|
||||
|
||||
@@ -362,6 +365,8 @@ static int fifo_thread_attempt_recovery(FifoThreadContext *ctx, FifoMessage *msg
|
||||
}
|
||||
|
||||
ctx->recovery_nr++;
|
||||
+ fifo->total_recovery_attempts++;
|
||||
+ fifo->status = 1;
|
||||
|
||||
if (fifo->max_recovery_attempts) {
|
||||
av_log(avf, AV_LOG_VERBOSE, "Recovery attempt #%d/%d\n",
|
||||
@@ -379,11 +384,13 @@ static int fifo_thread_attempt_recovery(FifoThreadContext *ctx, FifoMessage *msg
|
||||
if (is_recoverable(fifo, ret)) {
|
||||
return fifo_thread_process_recovery_failure(ctx, pkt, ret);
|
||||
} else {
|
||||
+ fifo->status = 2; // failed
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
av_log(avf, AV_LOG_INFO, "Recovery successful\n");
|
||||
ctx->recovery_nr = 0;
|
||||
+ fifo->status = 0; // running
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/libavformat/tee.c b/libavformat/tee.c
|
||||
index 1a2a8ead..6fb753f0 100644
|
||||
--- a/libavformat/tee.c
|
||||
+++ b/libavformat/tee.c
|
||||
@@ -49,6 +49,9 @@ typedef struct {
|
||||
* disabled output streams are set to -1 */
|
||||
int *stream_map;
|
||||
int header_written;
|
||||
+
|
||||
+ char *id;
|
||||
+ char *filename;
|
||||
} TeeSlave;
|
||||
|
||||
typedef struct TeeContext {
|
||||
@@ -135,6 +138,8 @@ static int close_slave(TeeSlave *tee_slave)
|
||||
}
|
||||
av_freep(&tee_slave->stream_map);
|
||||
av_freep(&tee_slave->bsfs);
|
||||
+ av_freep(&tee_slave->id);
|
||||
+ av_freep(&tee_slave->filename);
|
||||
|
||||
ff_format_io_close(avf, &avf->pb);
|
||||
avformat_free_context(avf);
|
||||
@@ -157,8 +162,8 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
||||
int ret;
|
||||
AVDictionary *options = NULL, *bsf_options = NULL;
|
||||
const AVDictionaryEntry *entry;
|
||||
- char *filename;
|
||||
- char *format = NULL, *select = NULL;
|
||||
+ char *filename = NULL;
|
||||
+ char *format = NULL, *select = NULL, *id = NULL;
|
||||
AVFormatContext *avf2 = NULL;
|
||||
int stream_count;
|
||||
int fullret;
|
||||
@@ -185,6 +190,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
||||
} while (0)
|
||||
|
||||
STEAL_OPTION("f", format);
|
||||
+ STEAL_OPTION("id", id);
|
||||
STEAL_OPTION("select", select);
|
||||
PROCESS_OPTION("onfail",
|
||||
parse_slave_failure_policy_option(value, tee_slave),
|
||||
@@ -203,6 +209,9 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
||||
av_dict_set(&options, entry->key, NULL, 0);
|
||||
}
|
||||
|
||||
+ tee_slave->filename = av_strdup(filename);
|
||||
+ tee_slave->id = av_strdup(id);
|
||||
+
|
||||
if (tee_slave->use_fifo) {
|
||||
|
||||
if (options) {
|
||||
@@ -233,6 +242,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
||||
tee_slave->use_fifo ? "fifo" :format, filename);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
+
|
||||
tee_slave->avf = avf2;
|
||||
av_dict_copy(&avf2->metadata, avf->metadata, 0);
|
||||
avf2->opaque = avf->opaque;
|
||||
@@ -398,6 +408,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
||||
|
||||
end:
|
||||
av_free(format);
|
||||
+ av_free(id);
|
||||
av_free(select);
|
||||
av_dict_free(&options);
|
||||
av_dict_free(&bsf_options);
|
||||
|
||||
base-commit: e1601d14100f6c7d088eba676d9555118ca94931
|
||||
base-commit: c526666f8869a5fffb04fbfeb862cde13338b001
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user