Hi All,

Please would someone with an interest in img2enc take a look at my revised patches for a minor feature addition and consider committing it to the main line for me.

Example:
ffmpeg -i ~/trailer.mp4 -strftime 1 -mkdir 1 %Y/%m/%d/out_%H-%M-%S.jpg

Without the new mkdir option, this command will fail if the directory hierarchy for the jpg files does not already exist, which can be difficult to predict for time-stamped directories.

This patch adds a mkdir option to img2enc which invites it to make whatever directory hierarchy is necessary for each output file. When used in conjunction with the strftime then the jpg files will be located in a newly created (time-stamped) directory as processing progresses.

My typical usage scenario is capturing a long-running live video feed (perhaps time-lapsed) and storing the resulting images in a time-stamped directory hierarchy fashion, rather than as a numbered sequence of files in a single directory.

If you look at the code you will see that only a half dozen lines of code were required in img2enc. The function for creating directories already existed in hlsenc.c but I've moved into utils.c as I presumed that was a more generic location for it.

All comments appreciated.

Thanks ad Regards,
Alan.


On 17/12/17 22:46, Carl Eugen Hoyos wrote:
2017-12-17 23:41 GMT+01:00 Dr Alan Barclay <a...@escribe.co.uk>:

Please would someone with an interest in img2enc take a look
at my minor feature addition and consider committing it to the
main line for me.
To be acceptable, the patch has to be split in two and please
move the definition into internal.h

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

---
 libavformat/hlsenc.c   | 35 +----------------------------------
 libavformat/internal.h |  7 +++++++
 libavformat/utils.c    | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index bbc2742dc7..633ddc309e 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -208,39 +208,6 @@ typedef struct HLSContext {
     AVIOContext *sub_m3u8_out;
 } 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;
@@ -1407,7 +1374,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs)
                     return AVERROR(ENOMEM);
                 }
                 dir = av_dirname(fn_copy);
-                if (mkdir_p(dir) == -1 && errno != EEXIST) {
+                if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
                     av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
                     av_free(fn_copy);
                     return AVERROR(errno);
diff --git a/libavformat/internal.h b/libavformat/internal.h
index e76ac12371..f471019a45 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -551,6 +551,13 @@ static inline int ff_rename(const char *oldpath, const char *newpath, void *logc
 }
 
 /**
+ * Make the specified directory.
+ *
+ * @param path  path for directory
+ */
+int ff_mkdir_p(const char *path);
+
+/**
  * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end
  * which is always set to 0.
  *
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 84e49208b8..aac58010b2 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 ff_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

---
 libavformat/img2enc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index b680676bff..a8ee064396 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);
+            ff_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 },
-- 
2.11.0

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

Reply via email to