Hi All,
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.
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.
>From 666ba7be8878a401c1e7fedd6dd7f56c9e049e14 Mon Sep 17 00:00:00 2001
From: "Dr. Alan Barclay" <a...@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
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel