From patchwork Mon Jun 21 15:28:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Mi X-Patchwork-Id: 28590 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2042:0:0:0:0 with SMTP id z2csp2072815iod; Mon, 21 Jun 2021 08:29:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyVX3/08+YTASFjnsC573QMd8eX3G5loLdk+e85AiDk4F+7QQP1Fk6Q+Lo3dhtnBy64uPIV X-Received: by 2002:a17:906:ce4f:: with SMTP id se15mr17268820ejb.232.1624289343155; Mon, 21 Jun 2021 08:29:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1624289343; cv=none; d=google.com; s=arc-20160816; b=nQ+pFNl7RArGMG8E0Pbj8jhuvzi9y+RWGVMgPmiA+2C/fpCtTTzdg0JvB13JF4IyLn M6kPe5z7pBbWNKk3dFJUiSI3PBv01rPP7r8r8wiIOi+hQ9RnXbIDYEO+HXQltj072OxR +560kDUr7/5L36ItimvESqn71roBTZK+YGhTAJGFCVpNVN46tbWZXPITZkYvlfo0/dBq EmTSFvGQkjq5Y4SrGWr8NKd1yaQQjdWE0ga99eeIUZCJQSaBzeBTuOpb8fXTUNhNMitu crIE9AMOtdtnB1OJZVDHoeFpWp7m6gQfMrs9UgrnCH/IboZorxRJymCZ1ddCYiKrsGou xdmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=yZPC+YnrsZXaGf+Tzant1JGGmypgtyji70r72nFllkI=; b=hVTR1ELyhhA0eUY3Ht+eVoje3oQfv+kwP7fLZcqp6hprtysEQM8VV2ZETEu2ZRDJ5A H44dIIlF+dbESskU3y7FbdABvhUoMbTe0oCsDYeVLFbpxK3Iw/qnwUem368EtPc2D1pb eyWidnN/ag1ZsMixodD0q0KOn1+UBnGDo2VBWaHuiyxM2s0e9Y7vgwNuba3vMvq1jv2N Bc+CMWCv2iV+lS+6tHxlDJcmIwkYCYAaOerFAziJqi+VylAPKk4lbjGDvPQvfMANKLSz p5m3BZq3SbXJ5DyKbYeZKsp41a2weKp5sVC/DZpBIcC0PBzREXy+yX+wJACBwM/X2Psh HDkA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=CINklBVk; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id w23si17551445edt.12.2021.06.21.08.29.00; Mon, 21 Jun 2021 08:29:03 -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; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=CINklBVk; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 18E4068094F; Mon, 21 Jun 2021 18:28:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2341468094F for ; Mon, 21 Jun 2021 18:28:50 +0300 (EEST) Received: by mail-qv1-f53.google.com with SMTP id if15so7632058qvb.2 for ; Mon, 21 Jun 2021 08:28:50 -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:mime-version :content-transfer-encoding; bh=xnKmAKSioBLgsViPUTZEVgGjm+TF5sotwbcZdlilK1A=; b=CINklBVk5z6xB5vT/AItUrmdtdQDDplhij9vyJ2xNSBLjo/3WhvkE+U30ivSlGNjQ6 AxklzYVNVu/7wR858K/tuvG/xXm5Gjee++fBBvWLSYkOPWbqRuKQAZy1TSyUOHjBgd4c 0FwDltllk1svGSSDaZBtXlvi7JBFqFatVBSElc7Pc5W4YVugFpgkPhuOCHnTuHu3XTcV UVfaQqYnP1chRQ3C02YkuaoG3otvoQ70knrbPklricv1pA4psJp9hEZ0M27VQkK7zmeU kc/f4tf63IRen4M6Xd3ArX8wD6M15f0NItwAol8SOXylsklLa2dRPKAIZatbBr5Z/XvM K4Ng== 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:mime-version :content-transfer-encoding; bh=xnKmAKSioBLgsViPUTZEVgGjm+TF5sotwbcZdlilK1A=; b=S8dhWMSbFZlWHL11eFSaucvjaT7D567xctRj3zlQopRSfEU+njRXY3hZ/AjkPBocVh jCB31A2E+5gOySzDTogqqVOvSUjVcx8UFaNe+s0KxStGy4H8dF8gqbsdgoXVV8z6fK9+ BlnGfeCUOvudxLAs4CVyWsV28Jg1NVQ4y0DgmaD3szlBxv+yrBHVDFpW/zAFrGWs5Ify 3WZWAELA7jou0Qa3TWUCr+KKxBaAlTq/NNxdyNKoEUSoVsnTvtBroq1pk0m508xRl0QF qApAmu9OcZXt+w81PWa/Wn6PzG9Eh0vmsxX+W8zatu2K61NlK7TqrhMo7e1QbsuvZ1HB fQJQ== X-Gm-Message-State: AOAM533osnMm65lgz9AF2VxFB/5gp5tUkuwudhbofy3gdX+/1sBP4jDB 6W05YqVaJK/lFlwP8sDrIYtm38p22sly1A== X-Received: by 2002:ad4:5909:: with SMTP id ez9mr2222586qvb.58.1624289327669; Mon, 21 Jun 2021 08:28:47 -0700 (PDT) Received: from devtest-vm.localdomain (cpefcecda48c248-cm64777d599360.cpe.net.cable.rogers.com. [174.116.34.163]) by smtp.gmail.com with ESMTPSA id q184sm9528620qkd.35.2021.06.21.08.28.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Jun 2021 08:28:47 -0700 (PDT) From: Alex Mi To: ffmpeg-devel@ffmpeg.org Date: Mon, 21 Jun 2021 11:28:02 -0400 Message-Id: <20210621152802.56953-1-magixx2006@gmail.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avformat/av_get_frame_filename2: Add timecode image extract option X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Alex Mi , marcus@compuccino.com Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: cqYOLkgw2qq/ From: Marcus Johansson Added the option to extract images with timecode as token The '%t' parameter is now supported for for images sequences just like the '%d' param When using '%t', images will have HH.MM.SS.XXX appended. Minor changes were made to the code by Marcus Johansson. See https://trac.ffmpeg.org/ticket/1452 for more details Signed-off-by: Alex Mi --- doc/muxers.texi | 3 +++ libavformat/avformat.h | 3 ++- libavformat/img2enc.c | 8 +++++--- libavformat/utils.c | 31 +++++++++++++++++++++++++++---- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index e77055e7ef..91997bd4fa 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1384,6 +1384,9 @@ If the pattern contains "%d" or "%0@var{N}d", the first filename of the file list specified will contain the number 1, all the following numbers will be sequential. +The pattern can also contain "%t" which writes out the timestamp of the +frame in the format "HH.mm.ss.fff" + The pattern may contain a suffix which is used to automatically determine the format of the image files to write. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index cd7b0d941c..513de9e477 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2602,10 +2602,11 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame timestamp in seconds * @return 0 if OK, -1 on format error */ int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts); int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 7b5133d300..55dca272ea 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -131,9 +131,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb[4] = {0}; char filename[1024]; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *stream = s->streams[ pkt->stream_index ]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int ret, i; int nb_renames = 0; + int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q); AVDictionary *options = NULL; if (img->update) { @@ -148,13 +150,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } } else if (img->frame_pts) { - if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE, 0) < 0) { av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); return AVERROR(EINVAL); } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, - img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + img->img_number, 0, + ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s'. " diff --git a/libavformat/utils.c b/libavformat/utils.c index 0df14682a4..d2e7cb7d34 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4589,15 +4589,17 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts) return (sec * 1000000) + usec; } -int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) +int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags, int64_t ts) { const char *p; char *q, buf1[20], c; - int nd, len, percentd_found; + int nd, len, percentd_found, percentt_found; + int hours, mins, secs, ms; q = buf; p = path; percentd_found = 0; + percentt_found = 0; for (;;) { c = *p++; if (c == '\0') @@ -4629,6 +4631,27 @@ int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number memcpy(q, buf1, len); q += len; break; + case 't': + if (percentd_found) + goto fail; + if (ts < 0) + goto fail; + percentt_found = 1; + ms = (ts/1000)%1000; + ts /= AV_TIME_BASE; + secs = ts % 60; + ts /= 60; + mins = ts % 60; + ts /= 60; + hours = ts; + snprintf(buf1, sizeof(buf1), + "%02d.%02d.%02d.%03d", hours, mins, secs, ms); + len = strlen(buf1); + if ((q - buf + len) > buf_size - 1) + goto fail; + memcpy(q, buf1, len); + q += len; + break; default: goto fail; } @@ -4638,7 +4661,7 @@ addchar: *q++ = c; } } - if (!percentd_found) + if (!(percentd_found || percentt_found)) goto fail; *q = '\0'; return 0; @@ -4649,7 +4672,7 @@ fail: int av_get_frame_filename(char *buf, int buf_size, const char *path, int number) { - return av_get_frame_filename2(buf, buf_size, path, number, 0); + return av_get_frame_filename2(buf, buf_size, path, number, 0, 0); } void av_url_split(char *proto, int proto_size,