@@ -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) {