Skip to content

Commit 7e9f916

Browse files
vrocheVltnrch
authored andcommitted
Molotov patches
* hlsenc lower verbosity * aacdec log debug * add ism_offset option to offset fragment start times * add audio_track_timescale option * always write an stss box in CMAF mode * Molotov JSON syslog option
1 parent db69d06 commit 7e9f916

File tree

9 files changed

+179
-12
lines changed

9 files changed

+179
-12
lines changed

Changelog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
Entries are sorted chronologically from oldest to youngest within each release,
22
releases are sorted from youngest to oldest.
33

4+
version 7.1.1-mtv:
5+
- Molotov patches
6+
47
version 7.1.1:
58
avformat/hls: Partially revert "reduce default max reload to 3"
69
avformat/mov: (v4) fix get_eia608_packet

fftools/opt_common.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,3 +1489,34 @@ int show_sinks(void *optctx, const char *opt, const char *arg)
14891489
return ret;
14901490
}
14911491
#endif /* CONFIG_AVDEVICE */
1492+
1493+
int opt_syslog(void *optctx, const char *opt, const char *arg)
1494+
{
1495+
int ret = 0;
1496+
char *key, *val;
1497+
char *ident = NULL;
1498+
AVDictionary *entries = NULL;
1499+
1500+
while (arg && *arg) {
1501+
if ((ret = av_opt_get_key_value(&arg, "=", ":", 0, &key, &val)) < 0) {
1502+
av_log(NULL, AV_LOG_ERROR,
1503+
"Failed to parse syslog key/value: %s\n",
1504+
av_err2str(ret));
1505+
return ret;
1506+
}
1507+
// syslog ident
1508+
if (!strcmp(key, "ident")) {
1509+
if (ident)
1510+
av_free(ident);
1511+
ident = val;
1512+
av_free(key);
1513+
} else {
1514+
av_dict_set(&entries, key, val, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
1515+
}
1516+
1517+
if (*arg)
1518+
arg++;
1519+
}
1520+
1521+
return av_log_set_syslog(ident, entries);
1522+
}

fftools/opt_common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ int opt_cpuflags(void *optctx, const char *opt, const char *arg);
196196
*/
197197
int opt_cpucount(void *optctx, const char *opt, const char *arg);
198198

199+
/**
200+
* Set the syslog JSON log.
201+
*/
202+
int opt_syslog(void *optctx, const char *opt, const char *arg);
203+
199204
#define CMDUTILS_COMMON_OPTIONS \
200205
{ "L", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_license }, "show license" }, \
201206
{ "h", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
@@ -226,6 +231,7 @@ int opt_cpucount(void *optctx, const char *opt, const char *arg);
226231
{ "cpuflags", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
227232
{ "cpucount", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \
228233
{ "hide_banner", OPT_TYPE_BOOL, OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
234+
{ "syslog", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_syslog }, "set json syslog logging", "syslog" }, \
229235
CMDUTILS_COMMON_OPTIONS_AVDEVICE \
230236

231237
#endif /* FFTOOLS_OPT_COMMON_H */

libavcodec/aac/aacdec_latm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
9393
ac->oc[1].m4ac.chan_config != m4ac->chan_config) {
9494

9595
if (latmctx->initialized) {
96-
av_log(avctx, AV_LOG_INFO, "audio config changed (sample_rate=%d, chan_config=%d)\n",
96+
av_log(avctx, AV_LOG_DEBUG, "audio config changed (sample_rate=%d, chan_config=%d)\n",
9797
m4ac->sample_rate, m4ac->chan_config);
9898
} else {
9999
av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n");

libavformat/hlsenc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2517,7 +2517,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
25172517
if (pkt->duration) {
25182518
vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
25192519
} else {
2520-
av_log(s, AV_LOG_WARNING, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
2520+
av_log(s, AV_LOG_VERBOSE, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
25212521
pkt->stream_index, pkt->pts);
25222522
vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
25232523
}

libavformat/movenc.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ static const AVOption options[] = {
125125
{ "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
126126
{ "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, .unit = "prft"},
127127
{ "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
128+
{ "ism_offset", "Offset to the ISM fragment start times", offsetof(MOVMuxContext, ism_offset), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM},
129+
{ "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
130+
{ "audio_track_timescale", "set timescale of all audio tracks", offsetof(MOVMuxContext, audio_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
128131
{ NULL },
129132
};
130133

@@ -3200,6 +3203,10 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext
32003203
track->par->codec_tag == MKTAG('r','t','p',' ')) &&
32013204
track->has_keyframes && track->has_keyframes < track->entry)
32023205
mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
3206+
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
3207+
mov->flags & FF_MOV_FLAG_CMAF &&
3208+
!track->has_keyframes)
3209+
mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
32033210
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable)
32043211
mov_write_sdtp_tag(pb, track);
32053212
if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
@@ -5321,7 +5328,8 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov,
53215328
return update_size(pb, pos);
53225329
}
53235330

5324-
static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
5331+
static int mov_write_tfxd_tag(AVIOContext *pb, MOVMuxContext *mov,
5332+
MOVTrack *track)
53255333
{
53265334
int64_t pos = avio_tell(pb);
53275335
static const uint8_t uuid[] = {
@@ -5334,7 +5342,7 @@ static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track)
53345342
avio_write(pb, uuid, AV_UUID_LEN);
53355343
avio_w8(pb, 1);
53365344
avio_wb24(pb, 0);
5337-
avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts);
5345+
avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts + mov->ism_offset);
53385346
avio_wb64(pb, track->end_pts -
53395347
(track->cluster[0].dts + track->cluster[0].cts));
53405348

@@ -5413,7 +5421,7 @@ static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
54135421
info->size = size;
54145422
// Try to recreate the original pts for the first packet
54155423
// from the fields we have stored
5416-
info->time = track->cluster[0].dts + track->cluster[0].cts;
5424+
info->time = track->cluster[0].dts + track->cluster[0].cts + mov->ism_offset;
54175425
info->duration = track->end_pts -
54185426
(track->cluster[0].dts + track->cluster[0].cts);
54195427
// If the pts is less than zero, we will have trimmed
@@ -5443,15 +5451,16 @@ static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max)
54435451
}
54445452
}
54455453

5446-
static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
5454+
static int mov_write_tfdt_tag(AVIOContext *pb, MOVMuxContext *mov,
5455+
MOVTrack *track)
54475456
{
54485457
int64_t pos = avio_tell(pb);
54495458

54505459
avio_wb32(pb, 0); /* size */
54515460
ffio_wfourcc(pb, "tfdt");
54525461
avio_w8(pb, 1); /* version */
54535462
avio_wb24(pb, 0);
5454-
avio_wb64(pb, track->cluster[0].dts - track->start_dts);
5463+
avio_wb64(pb, track->cluster[0].dts - track->start_dts + mov->ism_offset);
54555464
return update_size(pb, pos);
54565465
}
54575466

@@ -5466,7 +5475,7 @@ static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
54665475

54675476
mov_write_tfhd_tag(pb, mov, track, moof_offset);
54685477
if (mov->mode != MODE_ISM)
5469-
mov_write_tfdt_tag(pb, track);
5478+
mov_write_tfdt_tag(pb, mov, track);
54705479
for (i = 1; i < track->entry; i++) {
54715480
if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) {
54725481
mov_write_trun_tag(pb, mov, track, moof_size, start, i);
@@ -5475,7 +5484,7 @@ static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov,
54755484
}
54765485
mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry);
54775486
if (mov->mode == MODE_ISM) {
5478-
mov_write_tfxd_tag(pb, track);
5487+
mov_write_tfxd_tag(pb, mov, track);
54795488

54805489
if (mov->ism_lookahead) {
54815490
int size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
@@ -7946,7 +7955,13 @@ static int mov_init(AVFormatContext *s)
79467955
return AVERROR(ENOMEM);
79477956
}
79487957
} else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
7949-
track->timescale = st->codecpar->sample_rate;
7958+
if (mov->audio_track_timescale) {
7959+
track->timescale = mov->audio_track_timescale;
7960+
if (mov->mode == MODE_ISM && mov->audio_track_timescale != 10000000)
7961+
av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n");
7962+
} else {
7963+
track->timescale = st->codecpar->sample_rate;
7964+
}
79507965
if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
79517966
av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
79527967
track->audio_vbr = 1;
@@ -8038,8 +8053,10 @@ static int mov_init(AVFormatContext *s)
80388053
doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale
80398054
for video tracks, so if user-set, it isn't overwritten */
80408055
if (mov->mode == MODE_ISM &&
8041-
(st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
8042-
(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
8056+
((st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
8057+
st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) ||
8058+
(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->audio_track_timescale) ||
8059+
(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) {
80438060
track->timescale = 10000000;
80448061
}
80458062

libavformat/movenc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,11 @@ typedef struct MOVMuxContext {
216216
int max_fragment_size;
217217
int ism_lookahead;
218218
AVIOContext *mdat_buf;
219+
int64_t ism_offset;
219220
int first_trun;
220221

221222
int video_track_timescale;
223+
int audio_track_timescale;
222224

223225
int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise
224226
int64_t reserved_header_pos;

libavutil/log.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,101 @@ void avpriv_report_missing_feature(void *avc, const char *msg, ...)
495495
missing_feature_sample(0, avc, msg, argument_list);
496496
va_end(argument_list);
497497
}
498+
499+
#ifdef _WIN32
500+
501+
int av_log_set_syslog(const char* /*ident*/, AVDictionary* /*entries*/)
502+
{
503+
av_log(NULL, AV_LOG_FATAL, "Syslog is not implemented on this platform\n");
504+
505+
return AVERROR(EINVAL);
506+
}
507+
508+
#else
509+
510+
#include <syslog.h>
511+
512+
static const struct { int av_level; int syslog_level; } syslog_levels[] = {
513+
{ AV_LOG_PANIC , LOG_ERR },
514+
{ AV_LOG_FATAL , LOG_ERR },
515+
{ AV_LOG_ERROR , LOG_ERR },
516+
{ AV_LOG_WARNING, LOG_WARNING },
517+
{ AV_LOG_INFO , LOG_INFO },
518+
{ AV_LOG_VERBOSE, LOG_DEBUG },
519+
{ AV_LOG_DEBUG , LOG_DEBUG },
520+
{ AV_LOG_TRACE , LOG_DEBUG },
521+
};
522+
523+
static AVDictionary *syslog_entries = NULL;
524+
525+
static void av_bprint_json_string(AVBPrint *dstbuf, const char *src)
526+
{
527+
av_bprint_chars(dstbuf, '"', 1);
528+
for (; *src; src++) {
529+
// Keep only printable characters
530+
if ('\x1f' < *src & *src < '\x7f') {
531+
// Escape '"' and '\'
532+
if (strchr("\"\\", *src))
533+
av_bprint_chars(dstbuf, '\\', 1);
534+
av_bprint_chars(dstbuf, *src, 1);
535+
}
536+
}
537+
av_bprint_chars(dstbuf, '"', 1);
538+
}
539+
540+
static void av_log_syslog_callback(void* ptr, int level, const char* fmt, va_list vl)
541+
{
542+
AVBPrint line, msg;
543+
AVClass* avc = ptr ? *(AVClass**)ptr : NULL;
544+
int syslog_level = LOG_INFO;
545+
AVDictionaryEntry *entry = NULL;
546+
547+
// Level
548+
if (level > av_log_level)
549+
return;
550+
for (int i = 0; i < FF_ARRAY_ELEMS(syslog_levels); i++) {
551+
if (syslog_levels[i].av_level == level) {
552+
syslog_level = syslog_levels[i].syslog_level;
553+
break;
554+
}
555+
}
556+
// Prepare buf
557+
av_bprint_init(&line, 0, AV_BPRINT_SIZE_AUTOMATIC);
558+
av_bprint_init(&msg, 0, AV_BPRINT_SIZE_AUTOMATIC);
559+
// Prepare log message
560+
if (avc) {
561+
av_bprintf(&msg, "[%s @ %p] ", avc->item_name(ptr), ptr);
562+
}
563+
av_vbprintf(&msg, fmt, vl);
564+
// Prepare JSON
565+
if (strlen(msg.str)) {
566+
av_bprintf(&line, "{\"message\":");
567+
av_bprint_json_string(&line, msg.str);
568+
for (int i = 0; i < av_dict_count(syslog_entries); i++) {
569+
entry = av_dict_get(syslog_entries, "", entry, AV_DICT_IGNORE_SUFFIX);
570+
av_bprint_chars(&line, ',', 1);
571+
av_bprint_json_string(&line, entry->key);
572+
av_bprint_chars(&line, ':', 1);
573+
av_bprint_json_string(&line, entry->value);
574+
}
575+
av_bprint_chars(&line, '}', 1);
576+
// Log
577+
syslog(syslog_level, "%s", line.str);
578+
}
579+
// Clean
580+
av_bprint_finalize(&line, NULL);
581+
av_bprint_finalize(&msg, NULL);
582+
}
583+
584+
int av_log_set_syslog(const char* ident, AVDictionary* entries)
585+
{
586+
syslog_entries = entries;
587+
588+
openlog(ident, LOG_PID, LOG_USER | LOG_SYSLOG);
589+
590+
av_log_set_callback(&av_log_syslog_callback);
591+
592+
return 0;
593+
}
594+
595+
#endif

libavutil/log.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <stdarg.h>
2525
#include "attributes.h"
2626
#include "version.h"
27+
#include "dict.h"
2728

2829
typedef enum {
2930
AV_CLASS_CATEGORY_NA = 0,
@@ -380,6 +381,15 @@ int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl,
380381
void av_log_set_flags(int arg);
381382
int av_log_get_flags(void);
382383

384+
/**
385+
* Set syslog JSON log.
386+
*
387+
* @param[in] ident openlog ident param, can be NULL.
388+
* @param[in] entries pointer to a dictionary struct. These entries are
389+
* added to each log, can be NULL.
390+
*/
391+
int av_log_set_syslog(const char* ident, AVDictionary* entries);
392+
383393
/**
384394
* @}
385395
*/

0 commit comments

Comments
 (0)