I find this patch very useful. Here is a version against master as
recommended by Ricardo.

Works well for me. Thanks Georgi.

Le 20/02/2018 à 12:17, Georgi Chorbadzhiyski a écrit :
> The attached patch allows segment muxer to be used for file archiving by
> allowing it to automatically create the output directories. For example the
> following should work as expected:
> 
> ffmpeg
>   ...input_params...
>   -f segment \
>      -segment_atclocktime 1 \
>      -segment_time 5 \
>      -write_empty_segments 1 \
>      -segment_format_options movflags=+faststart \
>      -strftime 1 
> output_directory/mychannel/%Y/%m/%d/%H/%M/mychannel-%s-%Y%m%d-%H%M%S.mp4
> 
> The patch is against ffmpeg-3.3.6

-- 
Julien GAULMIN <julien.gaul...@4g-technology.eu>
diff --git a/libavformat/segment.c b/libavformat/segment.c
index 7fb4dc7d21..f6b9ea8b89 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -26,6 +26,7 @@
 
 #include <float.h>
 #include <time.h>
+#include <unistd.h>
 
 #include "avformat.h"
 #include "avio_internal.h"
@@ -230,6 +231,49 @@ static int set_segment_filename(AVFormatContext *s)
     return 0;
 }
 
+/* Note: This modifies *dir */
+static int create_dir(char *dir, mode_t mode) {
+    int ret = 0;
+    unsigned int i, dlen;
+    /* Shortcut, there are no deep directories */
+    if (strchr(dir, '/') == NULL)
+        return mkdir(dir, mode);
+    dlen = strlen(dir);
+    /* Skip first char (it can be /) */
+    for (i = 1; i < dlen; i++) {
+        if (dir[i] != '/')
+            continue;
+        dir[i] = '\0';
+        ret = mkdir(dir, mode);
+        dir[i] = '/';
+        if (ret < 0 && errno != EEXIST)
+            goto OUT;
+    }
+    ret = mkdir(dir, mode);
+OUT:
+    return ret;
+}
+
+static int segment_create_directory(AVFormatContext *oc, char *filename) {
+    char *dir, *fname;
+    /* Do nothing when the filename is URL */
+    if (strstr(filename, "://") != NULL)
+        return 0;
+    fname = av_strdup(filename);
+    if (!fname)
+        return AVERROR(ENOMEM);
+    dir = (char *)av_dirname(fname);
+    if (access(dir, W_OK) != F_OK)
+        av_log(oc, AV_LOG_INFO, "Create directory %s\n", dir);
+    if (create_dir(dir, 0777) == -1 && errno != EEXIST) {
+        av_log(oc, AV_LOG_ERROR, "Could not create directory %s\n", dir);
+        av_free(fname);
+        return AVERROR(errno);
+    }
+    av_free(fname);
+    return 0;
+}
+
 static int segment_start(AVFormatContext *s, int write_header)
 {
     SegmentContext *seg = s->priv_data;
@@ -251,6 +295,9 @@ static int segment_start(AVFormatContext *s, int write_header)
     if ((err = set_segment_filename(s)) < 0)
         return err;
 
+    if ((err = segment_create_directory(s, oc->url)) < 0)
+        return err;
+
     if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url);
         return err;
@@ -281,6 +328,10 @@ static int segment_list_open(AVFormatContext *s)
     int ret;
 
     snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
+
+    if ((ret = segment_create_directory(s, seg->temp_list_filename)) < 0)
+        return ret;
+
     ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
@@ -750,6 +801,9 @@ static int seg_init(AVFormatContext *s)
     oc = seg->avf;
 
     if (seg->write_header_trailer) {
+        if ((ret = segment_create_directory(s, seg->header_filename ? seg->header_filename : oc->url)) < 0)
+            return ret;
+
         if ((ret = s->io_open(s, &oc->pb,
                               seg->header_filename ? seg->header_filename : oc->url,
                               AVIO_FLAG_WRITE, NULL)) < 0) {

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to