From patchwork Sat Jul 18 00:19:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 21155 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 188A5446CD2 for ; Sat, 18 Jul 2020 03:26:33 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E698368B6FC; Sat, 18 Jul 2020 03:26:32 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lj1-f193.google.com (mail-lj1-f193.google.com [209.85.208.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2602168B675 for ; Sat, 18 Jul 2020 03:26:26 +0300 (EEST) Received: by mail-lj1-f193.google.com with SMTP id h19so14611431ljg.13 for ; Fri, 17 Jul 2020 17:26:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FM8sAdH7fXpcOLEMD1CnoXqWbBMzKEiL9qGnYSXKoww=; b=lLIV6/bM34RZokBlsC1gvI548vTSOmVc/dHLy82JhrSYteJl4K4GNPU4FUBwED8xek C2iavq7ys/n/38Xo/qwWciDVDkOEzxNoznxn4/Pieg3Igj/hvVfKMNnaxSOmP3yY3LTh 9MHBlVunGcWRdu7rpracgssSVj8N935IdwjVOYq9BpfvRqXrpTMTeaViviBizf+ufcTq HkJJpsQg7UTdf04YONs1g3Ig1j4boDfX+KhmdGtaE5zlvMaOW93+eQJyv5fLOBqp31eC pecgmX7gGoYLJ1/ywyzHcg2G0VKHrldFj/OpC5ElatbyUkFpluyjedvcNYlHPK7mk3Df WUZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FM8sAdH7fXpcOLEMD1CnoXqWbBMzKEiL9qGnYSXKoww=; b=KQm/8HQSqXQlptJGQZ1jA/WRlaY73yyEKkzccLlId3qGkpvFexbv+Tln30yj45n0VU tlCYjPYfTaStvF09DnlrfRCaPjnBFUQkSLmDJ43+fqeGG6xT2ijYQSJ7KCC3HwdX+0pR z5LvoGPivEUpqj5/k+W1S+1FsM5vwwJKttSueoifvlyOwXSWaEOsJrzuEzg6VM8mH8Ra 0S2pwEP0p4jRSlfIjFmFFd689fMYkRONZwR7RbgZPqzorQIJAZUno1wDj82MZ0lLFoL0 cZIGuQ7E0roQzueCWoazjvgXTP5FOXAxj5iz9qdnqhWAarCKLE0nYs9O5s56/6fOObEW 8yJw== X-Gm-Message-State: AOAM5330jN+tR/NX2jWDZVZQJsTOgrYF2naXBKV/iLTsIrDoy5ZALWzu Hu+Pvk9t0xJglcgNexJKSPYYOfhx X-Google-Smtp-Source: ABdhPJzZAKgaIN1tCEVlWaaM0Iswx37+V6u4LGc+HzDUTKfFF5q4Ub3DDmW7KgEIsH4gxm7cIHzvjg== X-Received: by 2002:a05:6402:787:: with SMTP id d7mr11406835edy.46.1595031575831; Fri, 17 Jul 2020 17:19:35 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc10296.dynamic.kabel-deutschland.de. [188.193.2.150]) by smtp.gmail.com with ESMTPSA id y7sm9299001ejd.73.2020.07.17.17.19.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jul 2020 17:19:35 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 18 Jul 2020 02:19:19 +0200 Message-Id: <20200718001928.10603-1-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200718000636.2167-1-andreas.rheinhardt@gmail.com> References: <20200718000636.2167-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 02/11] avformat/webmdashenc: Avoid allocations, fix memleak 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: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" When using the WebM DASH Manifest muxer, every stream of each adaptation set has to contain a metadata entry containing the filename of the source file. In case of live stream manifests, said filename has to conform to a pattern of _.. These pieces are used to create the other strings that are actually output. Up until now, these other strings would be allocated, used once and then freed directly after usage. This commit changes this: The function that allocated and assembled these strings now returns pointers to the '_' and '.' delimiters and so that the caller can easily pick substrings from it without needing to copy the string. Avoiding allocations also fixes a memleak: One of the allocated strings would leak upon a subsequent allocation failure. Signed-off-by: Andreas Rheinhardt --- libavformat/webmdashenc.c | 94 ++++++++++++--------------------------- 1 file changed, 28 insertions(+), 66 deletions(-) diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c index 3eefd6df8b..a9edcf73b8 100644 --- a/libavformat/webmdashenc.c +++ b/libavformat/webmdashenc.c @@ -260,65 +260,24 @@ static void free_adaptation_sets(AVFormatContext *s) { } /* - * Parses a live header filename and computes the representation id, - * initialization pattern and the media pattern. Pass NULL if you don't want to - * compute any of those 3. Returns 0 on success and non-zero on failure. + * Parses a live header filename and returns the position of the '_' and '.' + * delimiting and . * * Name of the header file should conform to the following pattern: * _.hdr where can be * anything. The chunks should be named according to the following pattern: * __.chk */ -static int parse_filename(char *filename, char **representation_id, - char **initialization_pattern, char **media_pattern) { - char *underscore_pos = NULL; - char *period_pos = NULL; - char *filename_str = av_strdup(filename); - int ret = 0; - - if (!filename_str) { - ret = AVERROR(ENOMEM); - goto end; - } - underscore_pos = strrchr(filename_str, '_'); - if (!underscore_pos) { - ret = AVERROR_INVALIDDATA; - goto end; - } - period_pos = strchr(++underscore_pos, '.'); - if (!period_pos) { - ret = AVERROR_INVALIDDATA; - goto end; - } - *(underscore_pos - 1) = 0; - if (representation_id) { - *representation_id = av_malloc(period_pos - underscore_pos + 1); - if (!(*representation_id)) { - ret = AVERROR(ENOMEM); - goto end; - } - av_strlcpy(*representation_id, underscore_pos, period_pos - underscore_pos + 1); - } - if (initialization_pattern) { - *initialization_pattern = av_asprintf("%s_$RepresentationID$.hdr", - filename_str); - if (!(*initialization_pattern)) { - ret = AVERROR(ENOMEM); - goto end; - } - } - if (media_pattern) { - *media_pattern = av_asprintf("%s_$RepresentationID$_$Number$.chk", - filename_str); - if (!(*media_pattern)) { - ret = AVERROR(ENOMEM); - goto end; - } - } - -end: - av_freep(&filename_str); - return ret; +static int split_filename(char *filename, char **underscore_pos, + char **period_pos) +{ + *underscore_pos = strrchr(filename, '_'); + if (!*underscore_pos) + return AVERROR(EINVAL); + *period_pos = strchr(*underscore_pos, '.'); + if (!*period_pos) + return AVERROR(EINVAL); + return 0; } /* @@ -377,46 +336,49 @@ static int write_adaptation_set(AVFormatContext *s, int as_index) if (w->is_live) { AVDictionaryEntry *filename = av_dict_get(s->streams[as->streams[0]]->metadata, FILENAME, NULL, 0); - char *initialization_pattern = NULL; - char *media_pattern = NULL; + char *underscore_pos, *period_pos; int ret; if (!filename) return AVERROR(EINVAL); - ret = parse_filename(filename->value, NULL, &initialization_pattern, - &media_pattern); + ret = split_filename(filename->value, &underscore_pos, &period_pos); if (ret) return ret; + *underscore_pos = '\0'; avio_printf(s->pb, "\n", par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); avio_printf(s->pb, "pb, " timescale=\"1000\""); avio_printf(s->pb, " duration=\"%d\"", w->chunk_duration); - avio_printf(s->pb, " media=\"%s\"", media_pattern); + avio_printf(s->pb, " media=\"%s_$RepresentationID$_$Number$.chk\"", + filename->value); avio_printf(s->pb, " startNumber=\"%d\"", w->chunk_start_index); - avio_printf(s->pb, " initialization=\"%s\"", initialization_pattern); + avio_printf(s->pb, " initialization=\"%s_$RepresentationID$.hdr\"", + filename->value); avio_printf(s->pb, "/>\n"); - av_free(initialization_pattern); - av_free(media_pattern); + *underscore_pos = '_'; } for (i = 0; i < as->nb_streams; i++) { - char *representation_id = NULL; + char buf[25], *representation_id = buf, *underscore_pos, *period_pos; int ret; if (w->is_live) { AVDictionaryEntry *filename = av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0); if (!filename) return AVERROR(EINVAL); - if (ret = parse_filename(filename->value, &representation_id, NULL, NULL)) + ret = split_filename(filename->value, &underscore_pos, &period_pos); + if (ret < 0) return ret; + representation_id = underscore_pos + 1; + *period_pos = '\0'; } else { - representation_id = av_asprintf("%d", w->representation_id++); - if (!representation_id) return AVERROR(ENOMEM); + snprintf(buf, sizeof(buf), "%d", w->representation_id++); } ret = write_representation(s, s->streams[as->streams[i]], representation_id, !width_in_as, !height_in_as, !sample_rate_in_as); - av_free(representation_id); if (ret) return ret; + if (w->is_live) + *period_pos = '.'; } avio_printf(s->pb, "\n"); return 0;