diff mbox series

[FFmpeg-devel,2/4] avformat/hlsenc: Add strftime_prog for using PROGRAM-DATE-TIME in the segment filename

Message ID 20231027035941.23491-2-davejohansen@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/4] avformat/hlsenc: Add init_program_date_time so start time can be specified | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

David Johansen Oct. 27, 2023, 3:59 a.m. UTC
---
 libavformat/hlsenc.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 5dfff6b2b6..24a0304f78 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -159,6 +159,7 @@  typedef struct VariantStream {
     char *m3u8_name;
 
     double initial_prog_date_time;
+    double curr_prog_date_time;
     char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
 
     char *fmp4_init_filename;
@@ -208,6 +209,7 @@  typedef struct HLSContext {
 
     int use_localtime;      ///< flag to expand filename with localtime
     int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
+    int use_localtime_prog; ///< flag to expand filename with prog date time
     int allowcache;
     int64_t recording_time;
     int64_t max_seg_size; // every segment file max size
@@ -259,10 +261,9 @@  typedef struct HLSContext {
     int has_video_m3u8; /* has video stream m3u8 list */
 } HLSContext;
 
-static int strftime_expand(const char *fmt, char **dest)
+static int strftime_expand_time_t(const char *fmt, const time_t *value, char **dest)
 {
     int r = 1;
-    time_t now0;
     struct tm *tm, tmpbuf;
     char *buf;
 
@@ -270,8 +271,7 @@  static int strftime_expand(const char *fmt, char **dest)
     if (!buf)
         return AVERROR(ENOMEM);
 
-    time(&now0);
-    tm = localtime_r(&now0, &tmpbuf);
+    tm = localtime_r(value, &tmpbuf);
     r = strftime(buf, MAX_URL_SIZE, fmt, tm);
     if (!r) {
         av_free(buf);
@@ -282,6 +282,19 @@  static int strftime_expand(const char *fmt, char **dest)
     return r;
 }
 
+static int strftime_expand(const char *fmt, char **dest)
+{
+    time_t now0;
+    time(&now0);
+    return strftime_expand_time_t(fmt, &now0, dest);
+}
+
+static int strftime_expand_prog(const char *fmt, const double prog_date_time, char **dest)
+{
+    time_t value = (time_t)prog_date_time;
+    return strftime_expand_time_t(fmt, &value, dest);
+}
+
 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename,
                           AVDictionary **options)
 {
@@ -1721,7 +1734,11 @@  static int hls_start(AVFormatContext *s, VariantStream *vs)
             int r;
             char *expanded = NULL;
 
-            r = strftime_expand(vs->basename, &expanded);
+            if (c->use_localtime_prog) {
+                r = strftime_expand_prog(vs->basename, vs->curr_prog_date_time, &expanded);
+            } else {
+                r = strftime_expand(vs->basename, &expanded);
+            }
             if (r < 0) {
                 av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
                 return r;
@@ -2615,6 +2632,7 @@  static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
         if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) {
             double 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);
+            vs->curr_prog_date_time += cur_duration;
             vs->end_pts = pkt->pts;
             vs->duration = 0;
             if (ret < 0) {
@@ -2971,6 +2989,7 @@  static int hls_init(AVFormatContext *s)
         vs->end_pts   = AV_NOPTS_VALUE;
         vs->current_segment_final_filename_fmt[0] = '\0';
         vs->initial_prog_date_time = initial_program_date_time;
+        vs->curr_prog_date_time = initial_program_date_time;
 
         for (j = 0; j < vs->nb_streams; j++) {
             vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
@@ -3038,7 +3057,11 @@  static int hls_init(AVFormatContext *s)
                     int r;
                     char *expanded = NULL;
 
-                    r = strftime_expand(vs->fmp4_init_filename, &expanded);
+                    if (hls->use_localtime_prog) {
+                        r = strftime_expand_prog(vs->fmp4_init_filename, vs->curr_prog_date_time, &expanded);
+                    } else {
+                        r = strftime_expand(vs->fmp4_init_filename, &expanded);
+                    }
                     if (r < 0) {
                         av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
                         return r;
@@ -3158,6 +3181,7 @@  static const AVOption options[] = {
     {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, "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 },
+    {"strftime_prog", "set filename expanish with program date time", OFFSET(use_localtime_prog), 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, "pl_type" },
     {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
     {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },