From 666ba7be8878a401c1e7fedd6dd7f56c9e049e14 Mon Sep 17 00:00:00 2001
From: "Dr. Alan Barclay" <alan@escribe.co.uk>
Date: Sun, 17 Dec 2017 19:24:44 +0000
Subject: [PATCH] Adding mkdir option for img2enc.

---
 libavformat/avformat.h |  7 +++++++
 libavformat/hlsenc.c   | 33 ---------------------------------
 libavformat/img2enc.c  |  8 ++++++++
 libavformat/utils.c    | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 4f2798a871..8e76fb3349 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -2990,6 +2990,13 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
 AVRational av_stream_get_codec_timebase(const AVStream *st);
 
 /**
+ * Make the specified directory.
+ *
+ * @param path  path for directory
+ */
+int mkdir_p(const char *path);
+
+/**
  * @}
  */
 
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index dd09739651..8523916d98 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -205,39 +205,6 @@ typedef struct HLSContext {
     int http_persistent;
 } HLSContext;
 
-static int mkdir_p(const char *path) {
-    int ret = 0;
-    char *temp = av_strdup(path);
-    char *pos = temp;
-    char tmp_ch = '\0';
-
-    if (!path || !temp) {
-        return -1;
-    }
-
-    if (!strncmp(temp, "/", 1) || !strncmp(temp, "\\", 1)) {
-        pos++;
-    } else if (!strncmp(temp, "./", 2) || !strncmp(temp, ".\\", 2)) {
-        pos += 2;
-    }
-
-    for ( ; *pos != '\0'; ++pos) {
-        if (*pos == '/' || *pos == '\\') {
-            tmp_ch = *pos;
-            *pos = '\0';
-            ret = mkdir(temp, 0755);
-            *pos = tmp_ch;
-        }
-    }
-
-    if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) {
-        ret = mkdir(temp, 0755);
-    }
-
-    av_free(temp);
-    return ret;
-}
-
 static int is_http_proto(char *filename) {
     const char *proto = avio_find_protocol_name(filename);
     return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index b680676bff..d037719ca1 100644
--- a/libavformat/img2enc.c
+++ b/libavformat/img2enc.c
@@ -42,6 +42,7 @@ typedef struct VideoMuxData {
     char target[4][1024];
     int update;
     int use_strftime;
+    int use_mkdir;
     int frame_pts;
     const char *muxer;
     int use_rename;
@@ -114,6 +115,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
                    img->img_number, img->path);
             return AVERROR(EINVAL);
         }
+        if (img->use_mkdir) {
+            char *temp_filename = av_strdup(filename);
+            const char *temp_path = av_dirname(temp_filename);
+            mkdir_p(temp_path);
+            av_free(temp_filename);
+        }
         for (i = 0; i < 4; i++) {
             snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename);
             av_strlcpy(img->target[i], filename, sizeof(img->target[i]));
@@ -212,6 +219,7 @@ static const AVOption muxoptions[] = {
     { "update",       "continuously overwrite one file", OFFSET(update),  AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0,       1, ENC },
     { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT,  { .i64 = 1 }, 0, INT_MAX, ENC },
     { "strftime",     "use strftime for filename", OFFSET(use_strftime),  AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
+    { "mkdir",        "make sub-dirs as required", OFFSET(use_mkdir),  AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
     { "frame_pts",    "use current frame pts for filename", OFFSET(frame_pts),  AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
     { "atomic_writing", "write files atomically (using temporary files and renames)", OFFSET(use_rename), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
     { NULL },
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 84e49208b8..3f32cc9e18 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -5606,3 +5606,36 @@ FF_ENABLE_DEPRECATION_WARNINGS
     return st->internal->avctx->time_base;
 #endif
 }
+
+int mkdir_p(const char *path) {
+    int ret = 0;
+    char *temp = av_strdup(path);
+    char *pos = temp;
+    char tmp_ch = '\0';
+
+    if (!path || !temp) {
+        return -1;
+    }
+
+    if (!strncmp(temp, "/", 1) || !strncmp(temp, "\\", 1)) {
+        pos++;
+    } else if (!strncmp(temp, "./", 2) || !strncmp(temp, ".\\", 2)) {
+        pos += 2;
+    }
+
+    for ( ; *pos != '\0'; ++pos) {
+        if (*pos == '/' || *pos == '\\') {
+            tmp_ch = *pos;
+            *pos = '\0';
+            ret = mkdir(temp, 0755);
+            *pos = tmp_ch;
+        }
+    }
+
+    if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) {
+        ret = mkdir(temp, 0755);
+    }
+
+    av_free(temp);
+    return ret;
+}
-- 
2.11.0

