[FFmpeg-devel] [PATCH] avformat/hlsenc: added segment filename option

Christian Suloway csuloway at row44.com
Fri Dec 5 18:06:19 CET 2014


This option allows segment filenames to be specified. Unless -hls_flags
single_file is enabled the filename is used as a string format with the
segment number.

Example:
ffmpeg -f lavfi -i testsrc -c:v h264 -map 0 -hls_segment_filename
bar%03d.ts foo.m3u8

Signed-off-by: Christian Suloway <csuloway at globaleagleent.com>`
---
 libavformat/hlsenc.c | 46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index e13f438..59392c5 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -59,6 +59,7 @@ typedef struct HLSContext {
     int max_nb_segments;   // Set by a private option.
     int  wrap;             // Set by a private option.
     uint32_t flags;        // enum HLSFlags
+    char *segment_filename;
 
     int allowcache;
     int64_t recording_time;
@@ -237,15 +238,12 @@ static int hls_write_header(AVFormatContext *s)
     char *p;
     const char *pattern = "%d.ts";
     AVDictionary *options = NULL;
-    int basename_size = strlen(s->filename) + strlen(pattern) + 1;
+    int basename_size;
 
     hls->sequence       = hls->start_sequence;
     hls->recording_time = hls->time * AV_TIME_BASE;
     hls->start_pts      = AV_NOPTS_VALUE;
 
-    if (hls->flags & HLS_SINGLE_FILE)
-        pattern = ".ts";
-
     if (hls->format_options_str) {
         ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
         if (ret < 0) {
@@ -270,21 +268,36 @@ static int hls_write_header(AVFormatContext *s)
         goto fail;
     }
 
-    hls->basename = av_malloc(basename_size);
-
-    if (!hls->basename) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    strcpy(hls->basename, s->filename);
+    if (hls->segment_filename) {
+        hls->basename = av_strdup(av_basename(hls->segment_filename));
+        if (!hls->basename) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        if (strlen(hls->basename) != strlen(hls->segment_filename)) {
+            av_log(hls, AV_LOG_ERROR, "invalid segment filename %s\n",
+                                      hls->segment_filename);
+            ret = AVERROR(EINVAL);
+            goto fail;
+        }
+    } else {
+        if (hls->flags & HLS_SINGLE_FILE)
+            pattern = ".ts";
 
-    p = strrchr(hls->basename, '.');
+        basename_size = strlen(s->filename) + strlen(pattern) + 1;
+        hls->basename = av_malloc(basename_size);
+        if (!hls->basename) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
 
-    if (p)
-        *p = '\0';
+        strlcpy(hls->basename, s->filename, basename_size);
 
-    av_strlcat(hls->basename, pattern, basename_size);
+        p = strrchr(hls->basename, '.');
+        if (p)
+            *p = '\0';
+        av_strlcat(hls->basename, pattern, basename_size);
+    }
 
     if ((ret = hls_mux_init(s)) < 0)
         goto fail;
@@ -412,6 +425,7 @@ static const AVOption options[] = {
     {"hls_base_url",  "url to prepend to each playlist entry",   OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E},
     {"hls_flags",     "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
     {"single_file",   "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX,   E, "flags"},
+    {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename),   AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
 
     { NULL },
 };
-- 
1.9.3 (Apple Git-50)



More information about the ffmpeg-devel mailing list