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

-- 
Georgi Chorbadzhiyski | http://georgi.unixsol.org/ | http://github.com/gfto/
From d3ba01f86900f3eae2bc4308a62d8c7c43c145c6 Mon Sep 17 00:00:00 2001
From: Georgi Chorbadzhiyski <g...@unixsol.org>
Date: Sun, 18 Feb 2018 18:10:33 +0200
Subject: [PATCH] segment: Create missing directories

---
 libavformat/segment.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/libavformat/segment.c b/libavformat/segment.c
index 8ec3653..2d90ef2 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -28,6 +28,7 @@
 
 #include <float.h>
 #include <time.h>
+#include <unistd.h>
 
 #include "avformat.h"
 #include "avio_internal.h"
@@ -226,6 +227,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;
@@ -247,6 +291,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->filename)) < 0)
+        return err;
+
     if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 
0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
         return err;
@@ -277,6 +324,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);
@@ -746,6 +797,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->filename)) < 0)
+            return ret;
+
         if ((ret = s->io_open(s, &oc->pb,
                               seg->header_filename ? seg->header_filename : 
oc->filename,
                               AVIO_FLAG_WRITE, NULL)) < 0) {
-- 
2.9.0

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

Reply via email to