[FFmpeg-devel] [PATCH] libavformat/hlsenc: Add option to correct subtitles duration in webvtt subtitles
Vladimir Kharchevin
vkharchevin at gmail.com
Mon Dec 9 13:24:01 EET 2024
When importing text subtitles from libzvbi_teletext stream the duration of subtitle
frames is -1 by default or fixed value per codec setting.
For hls webvtt stream it makes disappear time always 1193:02:47.295 for every subtitle.
Suggested to add hls option fix_teletext_durations to fix this behavior and set subtitle
duration to the next subtitle packet time.
Signed-off-by: Vladimir Kharchevin <vkharchevin at gmail.com>
---
libavformat/hlsenc.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 6148685f40..2e67790482 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -109,6 +109,7 @@ typedef enum HLSFlags {
HLS_PERIODIC_REKEY = (1 << 12),
HLS_INDEPENDENT_SEGMENTS = (1 << 13),
HLS_I_FRAMES_ONLY = (1 << 14),
+ HLS_FIX_TELETEXT_DURATIONS = (1 << 14),
} HLSFlags;
typedef enum {
@@ -165,6 +166,8 @@ typedef struct VariantStream {
char *vtt_m3u8_name;
char *m3u8_name;
+ AVPacket *vtt_prev_pkt;
+
double initial_prog_date_time;
char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
@@ -2559,6 +2562,29 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
}
}
+ if((hls->flags & HLS_FIX_TELETEXT_DURATIONS) &&
+ st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ if(!vs->vtt_prev_pkt) {
+ /**
+ * due to some types difference between basic types and codec and formats
+ * it transforms into uint32_t and assigned then to uint64_t
+ * so it becomes a positive integer value finally instead of -1.
+ * Fix duration to not have first phrase on the screen forever
+ * because of disappear time 1193:02:47.295
+ */
+ if(pkt->duration == (uint32_t)-1) {
+ pkt->duration = 0;
+ }
+ vs->vtt_prev_pkt = av_packet_clone(pkt);
+ } else {
+ AVPacket *temp;
+ vs->vtt_prev_pkt->duration = pkt->pts - vs->vtt_prev_pkt->pts;
+ temp = av_packet_clone(pkt);
+ pkt = vs->vtt_prev_pkt;
+ vs->vtt_prev_pkt = temp;
+ }
+ }
+
can_split = can_split && (pkt->pts - vs->end_pts > 0);
if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base,
end_pts, AV_TIME_BASE_Q) >= 0) {
@@ -2749,6 +2775,12 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
ret = 0;
}
+ /* free previously cloned packet */
+ if((hls->flags & HLS_FIX_TELETEXT_DURATIONS) &&
+ st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ if(vs->vtt_prev_pkt)
+ av_packet_unref(pkt);
+ }
return ret;
}
@@ -2767,6 +2799,9 @@ static void hls_deinit(AVFormatContext *s)
av_freep(&vs->vtt_basename);
av_freep(&vs->vtt_m3u8_name);
+ if(vs->vtt_prev_pkt)
+ av_packet_free(&vs->vtt_prev_pkt);
+
avformat_free_context(vs->vtt_avf);
avformat_free_context(vs->avf);
if (hls->resend_init_file)
@@ -3035,6 +3070,8 @@ static int hls_init(AVFormatContext *s)
vs->current_segment_final_filename_fmt[0] = '\0';
vs->initial_prog_date_time = initial_program_date_time;
+ vs->vtt_prev_pkt = NULL;
+
for (j = 0; j < vs->nb_streams; j++) {
vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
/* Get one video stream to reference for split segments
@@ -3218,6 +3255,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"},
+ {"fix_teletext_durations", "Calculate durations for teletext subtitle frames", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_FIX_TELETEXT_DURATIONS}, 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" },
--
2.43.0
More information about the ffmpeg-devel
mailing list