From patchwork Thu Sep 6 15:02:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Julien Gaulmin X-Patchwork-Id: 10266 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:12c4:0:0:0:0:0 with SMTP id 65-v6csp1792820jap; Fri, 7 Sep 2018 09:58:18 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdbj4Fn5tJ5ImtO0XZEkBEhkOdaVbymNYroFJeH/Z27fAsgaQDYXhBlWXcAwosLF7cXKA9LE X-Received: by 2002:a1c:5e48:: with SMTP id s69-v6mr5803020wmb.19.1536339498594; Fri, 07 Sep 2018 09:58:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536339498; cv=none; d=google.com; s=arc-20160816; b=VmSqRsYQiTQZgh285r7BX0NyIaNtzi5XPd00JzqiAanEqgg0XNglqFPPO/61XL2ElU 1jYa+CiARWZ2mrPdW6Y4x/XXdmfgGPbpLA7iFsmYywPM9cQxpZNxl8TiUOIdKuJ9mX6A Ii9o2BchaM/wKOaFuZvGmJDypnr24FksHSRA2S88SeveXos+6inVffrGWFv9fsSdVSVD K1DFAStrgWKk7SJz/E0jz+Qu00i4XulDl3QksYlLFoibb11Av8Xj0Ih7NQ2lCuC6o/Rk d/2zQ19fXKJUcA4SyDMvYLqt6/shCVABsfIeoSb9k7jwk7gX/ChilmdTbaOv3W8vT8sz SJvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :in-reply-to:mime-version:user-agent:date:message-id:organization :from:references:to:delivered-to; bh=K75sbnpDDoXa3ei5SypQPSIV4EIk+j7SR0BrS48oKxw=; b=ZhshxCoyCg6reAQzeLr7xx9Q4idyM1aNrXLNZBrw9KKLE6SCSYmgFscRtff0EjLYFo /yl4DnM19kjXeVuI2IXxNgcQEMtYqk6OKvlJd59p3yhsUtt1pPuKRZLjxk56XdNFIy0P Sn5DdmvEtkhkuPjEwq5sNTKDNPewE0QX4xXdyyLRGNcD1Pg4HlhOOuNfrzkDJUiwR2Sl 5LXV0+4oC21Cw/hQqeNq5eKqYs8qBwgHFWsONHnJw9tgjMBICUVjbAWhvnh921u3lKOZ 82E9C4M3OsXwsZhsj47heOrCcnJ9bCKFhlFmVxpRHUQ6R20GcDrgMyRFo/9h80NaY6QR 8aVA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v17-v6si8365279wrp.279.2018.09.07.09.58.17; Fri, 07 Sep 2018 09:58:18 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 47CFF68A154; Fri, 7 Sep 2018 19:58:08 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 89C7A689EFA for ; Thu, 6 Sep 2018 18:02:22 +0300 (EEST) X-Originating-IP: 78.203.83.2 Received: from 4G-SRV1 (free.4g-technology.eu [78.203.83.2]) (Authenticated sender: staff@4g-technology.eu) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 40D96FF81A; Thu, 6 Sep 2018 15:02:29 +0000 (UTC) Received: from [192.168.100.103] by 4G-SRV1 with esmtp (Exim 4.72) (envelope-from ) id 1fxvng-0002ey-OQ; Thu, 06 Sep 2018 17:02:28 +0200 To: ffmpeg-devel@ffmpeg.org References: <21754b81-89e9-a6e1-6f01-78d4acd0b8e6@unixsol.org> From: Julien Gaulmin Organization: 4G Technology Message-ID: Date: Thu, 6 Sep 2018 17:02:28 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <21754b81-89e9-a6e1-6f01-78d4acd0b8e6@unixsol.org> X-Mailman-Approved-At: Fri, 07 Sep 2018 19:58:07 +0300 X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: Re: [FFmpeg-devel] segment: Create missing directories X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Georgi Chorbadzhiyski Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" I find this patch very useful. Here is a version against master as recommended by Ricardo. Works well for me. Thanks Georgi. Le 20/02/2018 à 12:17, Georgi Chorbadzhiyski a écrit : > The attached patch allows segment muxer to be used for file archiving by > allowing it to automatically create the output directories. For example the > following should work as expected: > > ffmpeg > ...input_params... > -f segment \ > -segment_atclocktime 1 \ > -segment_time 5 \ > -write_empty_segments 1 \ > -segment_format_options movflags=+faststart \ > -strftime 1 output_directory/mychannel/%Y/%m/%d/%H/%M/mychannel-%s-%Y%m%d-%H%M%S.mp4 > > The patch is against ffmpeg-3.3.6 diff --git a/libavformat/segment.c b/libavformat/segment.c index 7fb4dc7d21..f6b9ea8b89 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -26,6 +26,7 @@ #include #include +#include #include "avformat.h" #include "avio_internal.h" @@ -230,6 +231,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; @@ -251,6 +295,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->url)) < 0) + return err; + if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url); return err; @@ -281,6 +328,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); @@ -750,6 +801,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->url)) < 0) + return ret; + if ((ret = s->io_open(s, &oc->pb, seg->header_filename ? seg->header_filename : oc->url, AVIO_FLAG_WRITE, NULL)) < 0) {