[FFmpeg-devel] [PATCH 2/4] avformat/hlsenc: added segment filename template

Christian Suloway csuloway at row44.com
Mon Dec 1 19:55:29 CET 2014


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

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index e13f438..0a48919 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -33,7 +33,7 @@
 #include "internal.h"
 
 typedef struct HLSSegment {
-    char filename[1024];
+    char *filename;
     double duration; /* in seconds */
     int64_t pos;
     int64_t size;
@@ -73,14 +73,23 @@ typedef struct HLSContext {
     HLSSegment *segments;
     HLSSegment *last_segment;
 
+    char *dirname;
     char *basename;
     char *baseurl;
     char *format_options_str;
     AVDictionary *format_options;
 
+    char *segment_filename;
+
     AVIOContext *pb;
 } HLSContext;
 
+static void hls_free_segment(HLSSegment *en)
+{
+    av_freep(&en->filename);
+    av_freep(&en);
+}
+
 static int hls_mux_init(AVFormatContext *s)
 {
     HLSContext *hls = s->priv_data;
@@ -119,7 +128,9 @@ static int hls_append_segment(HLSContext *hls, double duration, int64_t pos,
     if (!en)
         return AVERROR(ENOMEM);
 
-    av_strlcpy(en->filename, av_basename(hls->avf->filename), sizeof(en->filename));
+    en->filename = av_strdup(hls->avf->filename);
+    if (!en->filename)
+        return AVERROR(ENOMEM);
 
     en->duration = duration;
     en->pos      = pos;
@@ -136,7 +147,7 @@ static int hls_append_segment(HLSContext *hls, double duration, int64_t pos,
     if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
         en = hls->segments;
         hls->segments = en->next;
-        av_free(en);
+        hls_free_segment(en);
     } else
         hls->nb_entries++;
 
@@ -152,7 +163,7 @@ static void hls_free_segments(HLSContext *hls)
     while(p) {
         en = p;
         p = p->next;
-        av_free(en);
+        hls_free_segment(en);
     }
 }
 
@@ -186,6 +197,7 @@ static int hls_window(AVFormatContext *s, int last)
            sequence);
 
     for (en = hls->segments; en; en = en->next) {
+
         avio_printf(hls->pb, "#EXTINF:%f,\n", en->duration);
         if (hls->flags & HLS_SINGLE_FILE)
              avio_printf(hls->pb, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
@@ -208,6 +220,8 @@ static int hls_start(AVFormatContext *s)
     HLSContext *c = s->priv_data;
     AVFormatContext *oc = c->avf;
     int err = 0;
+    int filename_size;
+    char *filename;
 
     if (c->flags & HLS_SINGLE_FILE)
         av_strlcpy(oc->filename, c->basename,
@@ -220,8 +234,18 @@ static int hls_start(AVFormatContext *s)
         }
     c->number++;
 
-    if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, NULL)) < 0)
+    filename_size = strlen(c->dirname) + strlen(oc->filename) + 1;
+    filename = av_malloc(filename_size);
+    if (!filename)
+        return AVERROR(ENOMEM);
+    *filename = '\0';
+    av_strlcat(filename, c->dirname, filename_size);
+    av_strlcat(filename, oc->filename, filename_size);
+
+    err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
+                     &s->interrupt_callback, NULL);
+    av_free(filename);
+    if (err < 0)
         return err;
 
     if (oc->oformat->priv_class && oc->priv_data)
@@ -237,15 +261,13 @@ 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;
+    char *basename;
 
     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 +292,45 @@ static int hls_write_header(AVFormatContext *s)
         goto fail;
     }
 
-    hls->basename = av_malloc(basename_size);
-
-    if (!hls->basename) {
+    hls->dirname = av_strdup(s->filename);
+    if (!hls->dirname) {
         ret = AVERROR(ENOMEM);
         goto fail;
     }
 
-    strcpy(hls->basename, s->filename);
+    basename = (char *)av_basename(hls->dirname);
 
-    p = strrchr(hls->basename, '.');
+    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";
 
-    if (p)
-        *p = '\0';
+        basename_size = strlen(basename) + strlen(pattern) + 1;
+        hls->basename = av_malloc(basename_size);
+        if (!hls->basename) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        av_strlcpy(hls->basename, basename, basename_size);
+        p = strrchr(hls->basename, '.');
+        if (p)
+            *p = '\0';
+        av_strlcat(hls->basename, pattern, basename_size);
+    }
 
-    av_strlcat(hls->basename, pattern, basename_size);
+    *basename = '\0';
 
     if ((ret = hls_mux_init(s)) < 0)
         goto fail;
@@ -309,6 +355,7 @@ fail:
 
     av_dict_free(&options);
     if (ret) {
+        av_free(hls->dirname);
         av_free(hls->basename);
         if (hls->avf)
             avformat_free_context(hls->avf);
@@ -396,7 +443,10 @@ static int hls_write_trailer(struct AVFormatContext *s)
     hls_window(s, 1);
 
     hls_free_segments(hls);
+    av_free(hls->dirname);
+
     avio_close(hls->pb);
+
     return 0;
 }
 
@@ -412,6 +462,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