From patchwork Wed May 1 14:13:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moritz Barsnick X-Patchwork-Id: 12957 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 3590E446FA9 for ; Wed, 1 May 2019 17:13:29 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 16A0668AA86; Wed, 1 May 2019 17:13:29 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout.gmx.net (mout.gmx.net [212.227.17.21]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4BDEE68AA84 for ; Wed, 1 May 2019 17:13:22 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1556720001; bh=GXU/utsoT4Jzq4SzSKKwezdeCo8OMZv4yI5kcN9D6fM=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date; b=BwgVYv9irOjqCA41XDM4aeLU61XvnXTIKh37pTzxvN4Yqc4xRuVR1R0cuHWc6hFF8 /V2MnFIjY/h1ReLbHkMnxJ6wEWLL/BFNC7YAgE+EgECS1HNkll2sKroTQsaqtOMY0r V2aTzEEoqRUqmFMI63lNbw20EcF4r9Cdzxo9B5VM= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from goodtimes.fritz.box ([89.182.224.147]) by mail.gmx.com (mrgmx104 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MTRMi-1hBy7J2XSm-00TkM5; Wed, 01 May 2019 16:13:21 +0200 From: Moritz Barsnick To: FFmpeg development discussions and patches Date: Wed, 1 May 2019 16:13:16 +0200 Message-Id: <20190501141316.24367-1-barsnick@gmx.net> X-Mailer: git-send-email 2.14.5 X-Provags-ID: V03:K1:/sqoqxkuK81Kqhvi5gzT4WEyoyXx/g1PtcXswUZKYdjWpteScPp 9DHjTE234l0Zdgk8PNt2iNEJ4zlS5PXnokV9IQ8Gk8LPNI7yLA8UfY84I06QXYGqtCo9/p2 36oM2mqFKS5K8DsrWJjfr0Y70/ohrLcfYgDMhHfFEXSwannzyHCe1RhfAlEqWV7GbMgDg9/ fmJe8VOWUOh9NBbDcE//g== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:aYWInu3kKko=:fMl7EBE6hi6R1Pg3HC3vhq aorF7D1xSR0PHB6gTplR0j/mmfBgjAq8+7fDdPZ23kQEp3o1opYSMvL+4SsjCg6IYqTk9tLfc 950ylW6dCg7DOw9S7tifMDAPXswfOR9fcDpIbFFsjx90g51WYOIfCdKPc3+qu/yDBPZpPXQ8p EY2DNqMBYgcimK5kC4jcIK86O4yTounIZatrIwMbTLdoGXrzSJGry7Qvhp2WWGQTpeKeMXkVv JEprmG8AZPPqdZS/adxT/32jj+BLyoCB94aUEyulEgBJdlz+sHX1r3cr+U03LlRzzcRMg0TfO ckFT10JLkCOuHBla2NtTJjLqGDeo9/Zsh93sE8IE7sPjh+ntlKZAeNrk13c51hgGW6LSJilmj 14WRCwP1oW9zKROL1lGQvIqsqKYQET38In0yFIYLCZzNpVfzVoUq2zWw4zk6zdmHXpWeVin4O dpvNMLwEei8tVTJAlZQVYtf3I/hUdb8pYPhHohApnDbJ40iFNeID970Q4LoIecE19+483H6P7 AIHwmYXpQQ0z4NvZg+5RK1iZyhEWmKJdT6eXmVcHP/uCwr349/CpK3PnbafzFlEm7CcZJvNVb snJY0l7X1yxneleFHprTlnkDSzQO9ZQSXJOYWlMCkVa+bBhngrcs7TatGPBBssCwuinvdHT0+ QK1Jmq1LwqEcviVlqpjiwp5v5likBVrgY9vZAyqXuKcC1qzrAitTU6I9EaivXisEKHpDSVRgg XIoYZ1Rf0hjVzmGb59q+zjr6F80mpwfZTML5u843+e/mJo3BJvUHik9jaojPVOvNRytQ+4yGA ghlv51iOW/I06XfsGIwJssCWPgGNcGwVIOyUr12ymR6IZ1vh89qBL6+dKudBt++awHioXsdZI RG0/KCDtY1v33Tqvlmz07ysVpoIYK6X+4T3BOI5DNocYvXRgwmN4U6FBMbu87x Subject: [FFmpeg-devel] [PATCH v2] avcodec: add realtime bitstream filter 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: Moritz Barsnick MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Works for video and audio streams. Similar to the "-re" option in ffmpeg, but unlike that option does not only work for input files, and is not only implemented for the command line tool. This filter is available through the libraries, and unlike the "realtime" filter also works when using the "copy" encoder. Implementation mostly taken from libavfilter/f_realtime.c. --- doc/bitstream_filters.texi | 24 +++++++++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/realtime_bsf.c | 93 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 libavcodec/realtime_bsf.c -- 2.14.5 diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 25bbf8372b..18ddb2e52b 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -599,6 +599,30 @@ Set Rec709 colorspace for each frame of the file ffmpeg -i INPUT -c copy -bsf:v prores_metadata=color_primaries=bt709:color_trc=bt709:colorspace=bt709 output.mov @end example +@section realtime + +Slow down output processing to match real time approximately. + +This bitstream filter will pause the filtering for a variable amount of time +to match the output rate with the input timestamps. It is similar to the +@option{re} option to @code{ffmpeg}. + +It accepts the following options: + +@table @option +@item limit +Time limit for the pauses. Any pause longer than that will be considered +a timestamp discontinuity and reset the timer. Default is 2 seconds. +@item speed +Speed factor for processing. The value must be a float larger than zero. +Values larger than 1.0 will result in faster than realtime processing, +smaller will slow processing down. The @var{limit} is automatically adapted +accordingly. Default is 1.0. + +A processing speed faster than what is possible without this bitstream +filter cannot be achieved. +@end table + @section remove_extra Remove extradata from packets. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f37135fc07..83f143922f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1094,6 +1094,7 @@ OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o +OBJS-$(CONFIG_REALTIME_BSF) += realtime_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 463003966a..741a240380 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -49,6 +49,7 @@ extern const AVBitStreamFilter ff_mov2textsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_prores_metadata_bsf; +extern const AVBitStreamFilter ff_realtime_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_trace_headers_bsf; diff --git a/libavcodec/realtime_bsf.c b/libavcodec/realtime_bsf.c new file mode 100644 index 0000000000..b9abda90a4 --- /dev/null +++ b/libavcodec/realtime_bsf.c @@ -0,0 +1,93 @@ +/* + * Realtime filter + * Copyright (c) 2015 Nicolas George + * Copyright (c) 2018 Moritz Barsnick + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/time.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "bsf.h" +#include + +typedef struct RealtimeContext { + const AVClass *class; + int64_t delta; + int64_t limit; + double speed; + unsigned inited; +} RealtimeContext; + +static int realtime_filter(AVBSFContext *bsf, AVPacket *pkt) +{ + int ret; + RealtimeContext *ctx = bsf->priv_data; + + ret = ff_bsf_get_packet_ref(bsf, pkt); + if (ret < 0) + return ret; + + if (pkt->pts != AV_NOPTS_VALUE) { + int64_t pts = av_rescale_q(pkt->pts, bsf->time_base_in, AV_TIME_BASE_Q) / ctx->speed; + int64_t now = av_gettime_relative(); + int64_t sleep = pts - now + ctx->delta; + if (!ctx->inited) { + ctx->inited = 1; + sleep = 0; + ctx->delta = now - pts; + } + if (FFABS(sleep) > ctx->limit / ctx->speed) { + av_log(ctx, AV_LOG_WARNING, + "time discontinuity detected: %"PRIi64" us, resetting\n", + sleep); + sleep = 0; + ctx->delta = now - pts; + } + if (sleep > 0) { + av_log(ctx, AV_LOG_DEBUG, "sleeping %"PRIi64" us\n", sleep); + for (; sleep > 600000000; sleep -= 600000000) + av_usleep(600000000); + av_usleep(sleep); + } + } + + return 0; +} + +#define OFFSET(x) offsetof(RealtimeContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_BSF_PARAM) +static const AVOption options[] = { + { "limit", "sleep time limit", OFFSET(limit), AV_OPT_TYPE_DURATION, { .i64 = 2000000 }, 0, INT64_MAX, FLAGS }, + { "speed", "speed factor", OFFSET(speed), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, DBL_MIN, DBL_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass realtime_class = { + .class_name = "realtime_bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVBitStreamFilter ff_realtime_bsf = { + .name = "realtime", + .priv_data_size = sizeof(RealtimeContext), + .priv_class = &realtime_class, + .filter = realtime_filter, +};