diff mbox series

[FFmpeg-devel,v3] avformat/segment: add -strftime_mkdir option

Message ID 20221010114020.2104415-1-george@sx.gl
State New
Headers show
Series [FFmpeg-devel,v3] avformat/segment: add -strftime_mkdir option | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

George-Cristian Jiglau Oct. 10, 2022, 11:40 a.m. UTC
This enables automatically creating directories for strftime-formatted
segment names.

Signed-off-by: George-Cristian Jiglau <george@sx.gl>
---
 doc/muxers.texi       |  4 ++++
 libavformat/segment.c | 15 +++++++++++++++
 2 files changed, 19 insertions(+)
diff mbox series

Patch

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 4edbb22b00..5695bc66ae 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -2445,6 +2445,10 @@  segments to write. If this is selected, the output segment name must
 contain a @code{strftime} function template. Default value is
 @code{0}.
 
+@item strftime_mkdir @var{1|0}
+Used together with -strftime, it will create all subdirectories of the
+expanded segment name. Default value is @code{0}.
+
 @item break_non_keyframes @var{1|0}
 If enabled, allow segments to start on frames other than keyframes. This
 improves behavior on some players when the time between keyframes is
diff --git a/libavformat/segment.c b/libavformat/segment.c
index c904e20708..f75c7228f1 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -94,6 +94,7 @@  typedef struct SegmentContext {
     AVIOContext *list_pb;  ///< list file put-byte context
     int64_t time;          ///< segment duration
     int use_strftime;      ///< flag to expand filename with strftime
+    int use_strftime_mkdir; ///< flag to mkdir dirname in strftime filename
     int increment_tc;      ///< flag to increment timecode if found
 
     char *times_str;       ///< segment times specification string
@@ -203,6 +204,19 @@  static int set_segment_filename(AVFormatContext *s)
             av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
             return AVERROR(EINVAL);
         }
+        if (seg->use_strftime_mkdir) {
+            const char *dir;
+            char *fn_copy = av_strdup(oc->url);
+            if (!fn_copy)
+                return AVERROR(ENOMEM);
+            dir = av_dirname(fn_copy);
+            if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
+                av_log(oc, AV_LOG_ERROR, "Could not create directory %s with strftime_mkdir\n", dir);
+                av_freep(&fn_copy);
+                return AVERROR(errno);
+            }
+            av_freep(&fn_copy);
+        }
     } else if (av_get_frame_filename(buf, sizeof(buf),
                                      s->url, seg->segment_idx) < 0) {
         av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->url);
@@ -1038,6 +1052,7 @@  static const AVOption options[] = {
     { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
     { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
     { "strftime",          "set filename expansion with strftime at segment creation", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+    { "strftime_mkdir",    "create directory components in strftime-generated filename", OFFSET(use_strftime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
     { "increment_tc", "increment timecode between each segment", OFFSET(increment_tc), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
     { "break_non_keyframes", "allow breaking segments on non-keyframes", OFFSET(break_non_keyframes), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },