From patchwork Sat Apr 9 13:36:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Tomas_H=C3=A4rdin?= X-Patchwork-Id: 35238 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:671c:b0:7c:62c8:b2d1 with SMTP id q28csp129632pzh; Sat, 9 Apr 2022 06:36:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxYzOvw2FjGgzmTH0de5CyHB9WXeSBvgo93YcCQ4b2Jsgi5RZpFjVv+BpVw1xfnsmN1ALE/ X-Received: by 2002:a05:6402:254e:b0:418:d759:dc48 with SMTP id l14-20020a056402254e00b00418d759dc48mr24539221edb.104.1649511381720; Sat, 09 Apr 2022 06:36:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649511381; cv=none; d=google.com; s=arc-20160816; b=AbIYBYne4+9a3uAbJFdBqhM7l25UTpH3DEwRIij68mQxaRq1JnKvHHViixL5nhCCMj M2EccJGlpFGzc13f14B0FAzM3GAghKA/vaaRCFWPXZAdxqROlTXk3z5paWrIVDNRgoHu qQmQt1WMMLBMD3fc6LcBkQvI70hQyO1MkGYad03BxyXfX/fLTMOIqzUDC1QtdsrMSZPb Swj/UeqT+Rnz70VaTaxknScq24Xcexjfp4rpARuEAdDBPXQKI9u6trD7ExlvqzAYa+xt JvyHu/AqiY+bRKzN6LRs6UkAmjv5LJhxgwtMhGCFdcTGwoa94BQmTVBYQA+pgWTL/XZ5 GFMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:user-agent:references:in-reply-to:date:to:from :message-id:dkim-signature:dkim-signature:delivered-to; bh=qn0hz2c8hiSQwFPr9+aRugn4jbAmEn01auAaPS5DeQY=; b=gbhtwh4YP3kmd41hRQtEsO48xoNEZS7y/e9ByJgkOE7Jqqz2zSHul5lCmdkkCF6ANU fzJjbyaSoWw0LRKTBkF9nXPoeHWQi9/XPprlsSjby+HHOrSJfsSpqAU367dmR+wLebF7 Kokp3nDw74itURk0h0r/oHkl9ozO0ly+50Rry9WG2NI1Leiff2u6Pu31oEZmagmbJc98 AJBJ3tktrWpdxwjnHRlfLuxMCaHHzWL1bUaYtO4pBdm9jIA1zuQRNLN7AdYIC5e6G9uW njEIPM//tos4dmLnmItv3NnDJUvWhTlv4AlGnwqp7VpwBhD+s0GY3PQfVI16AXCj83m6 nYxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=WThH0z7m; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=yrBrxc43; 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=NONE dis=NONE) header.from=acc.umu.se Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id gh2-20020a170906e08200b006e014febbe6si1717911ejb.1009.2022.04.09.06.36.13; Sat, 09 Apr 2022 06:36:21 -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=@acc.umu.se header.s=mail1 header.b=WThH0z7m; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=yrBrxc43; 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=NONE dis=NONE) header.from=acc.umu.se Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 216AD68B2E8; Sat, 9 Apr 2022 16:36:11 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail.acc.umu.se (mail.acc.umu.se [130.239.18.156]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0B5F768B026 for ; Sat, 9 Apr 2022 16:36:05 +0300 (EEST) Received: from localhost (localhost.localdomain [127.0.0.1]) by amavisd-new (Postfix) with ESMTP id 82B6A44B90 for ; Sat, 9 Apr 2022 15:36:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=acc.umu.se; s=mail1; t=1649511364; bh=soc3eKKHZfWapB+keRx0IeyCrLxjFrUQIi08WfL6Bw8=; h=Subject:From:To:Date:In-Reply-To:References:From; b=WThH0z7mHoLQBmhe26cbm026Vsz4nbAw/1UlBectkpFRfi5JJ6/81QerE0JG94y+Y cFZDQuThe2qq/44eDTPotQd0zuifinUhoQp2vG0EUe4YAxT4iYN9cwVHGUAh9+qjWI it03wvLSOOgv2qtljysUm+MgvsSN5mK91nt9ZVz47PEM+YKYxYlsU1Ep65lJwkYR+c Q+ugZgv+PG0Vx5xkMb66LRp/ZWsPeu/xxYmakdT22rjAQwPXbn5hUU+uXAt2UsAy2D 2/tK+T3CaPLqMVBw++gq2D4iDNIccH86vIZapIj4xLdAT6vrhqv7gxVG6VYxn+UPqb 4CRrICzGXV39Q== Received: from [192.168.1.244] (213-67-66-101-no2430.tbcn.telia.com [213.67.66.101]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: tjoppen) by mail.acc.umu.se (Postfix) with ESMTPSA id 7F53E44B8F for ; Sat, 9 Apr 2022 15:36:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=acc.umu.se; s=mail1; t=1649511363; bh=soc3eKKHZfWapB+keRx0IeyCrLxjFrUQIi08WfL6Bw8=; h=Subject:From:To:Date:In-Reply-To:References:From; b=yrBrxc43ooKqT5Eb4lWXp8NBx/u5PVEfg+lgOEBbVhY6+uYXKL3IkyGpX+bnIehnd QUtFy2L5XPfmMqJKgM1lx6Eo0QZ85hsl7/hP+CIz9lt36RGHMHQW/zefZHthLBmn5F 4ldSNPXpG2AMeVIUaVq/I/b4cqnR0MCDk8L6/NE4YAvpcDUXKE0I0436Y2JwHMnBBc 6jciR7r4pWYasp79OySBT1YU3Kh+Flws/ny0xeM9tGP/JVfnwb734ZtZg7MNNS0c/8 Tj4kUoFeRvvwj8S8ryFNdsP6Ewf3sq3yOTTYTvNRzR5B7EK0psn7MCMcDfKfST5CoP An7BjyYqXTvAA== Message-ID: From: Tomas =?iso-8859-1?q?H=E4rdin?= To: FFmpeg development discussions and patches Date: Sat, 09 Apr 2022 15:36:02 +0200 In-Reply-To: References: User-Agent: Evolution 3.38.3-1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] libavcodec/cinepakenc: Mark no-skip frames as keyframes 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: VK3EMYe0YRt5 From 442bf0fbba4e13aa7d05ff5c30b07d4c94a8182c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Sat, 9 Apr 2022 14:38:47 +0200 Subject: [PATCH 2/3] libavcodec/cinepakenc: Mark no-skip frames as keyframes Reset curframe whenever we generate a keyframe. Use -g instead of -keyint_min. --- libavcodec/cinepakenc.c | 50 +++++++++++++++++++--------- tests/ref/vsynth/vsynth1-cinepak | 8 ++--- tests/ref/vsynth/vsynth2-cinepak | 8 ++--- tests/ref/vsynth/vsynth_lena-cinepak | 6 ++-- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 8b32c02780..6cfe8de200 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -113,7 +113,7 @@ typedef struct CinepakEncContext { enum AVPixelFormat pix_fmt; int w, h; int frame_buf_size; - int curframe, keyint; + int curframe; AVLFG randctx; uint64_t lambda; int *codebook_input; @@ -215,7 +215,6 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) s->h = avctx->height; s->frame_buf_size = frame_buf_size; s->curframe = 0; - s->keyint = avctx->keyint_min; s->pix_fmt = avctx->pix_fmt; // set up AVFrames @@ -835,8 +834,7 @@ static void calculate_skip_errors(CinepakEncContext *s, int h, } } -static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, - unsigned char *buf, int strip_size) +static void write_strip_keyframe(unsigned char *buf, int keyframe) { // actually we are exclusively using intra strip coding (how much can we win // otherwise? how to choose which part of a codebook to update?), @@ -844,6 +842,12 @@ static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, // (besides, the logic here used to be inverted: ) // buf[0] = keyframe ? 0x11: 0x10; buf[0] = keyframe ? 0x10 : 0x11; +} + +static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, + unsigned char *buf, int strip_size) +{ + write_strip_keyframe(buf, keyframe); AV_WB24(&buf[1], strip_size + STRIP_HEADER_SIZE); // AV_WB16(&buf[4], y); /* using absolute y values works -- rl */ AV_WB16(&buf[4], 0); /* using relative values works as well -- rl */ @@ -857,7 +861,7 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, uint8_t *last_data[4], int last_linesize[4], uint8_t *data[4], int linesize[4], uint8_t *scratch_data[4], int scratch_linesize[4], - unsigned char *buf, int64_t *best_score) + unsigned char *buf, int64_t *best_score, int *no_skip) { int64_t score = 0; int best_size = 0; @@ -973,6 +977,9 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, scratch_data, scratch_linesize, last_data, last_linesize, &info, s->strip_buf + STRIP_HEADER_SIZE); + // in theory we could have MODE_MC without ENC_SKIP, + // but MODE_V1_V4 will always be more efficient + *no_skip = info.mode != MODE_MC; write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); } @@ -999,13 +1006,13 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, } static int rd_frame(CinepakEncContext *s, const AVFrame *frame, - int isakeyframe, unsigned char *buf, int buf_size) + int isakeyframe, unsigned char *buf, int buf_size, int *got_keyframe) { int num_strips, strip, i, y, nexty, size, temp_size, best_size; uint8_t *last_data [4], *data [4], *scratch_data [4]; int last_linesize[4], linesize[4], scratch_linesize[4]; int64_t best_score = 0, score, score_temp; - int best_nstrips; + int best_nstrips, best_strip_offsets[MAX_STRIPS]; if (s->pix_fmt == AV_PIX_FMT_RGB24) { int x; @@ -1064,12 +1071,15 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, // would be nice but quite certainly incompatible with vintage players: // support encoding zero strips (meaning skip the whole frame) for (num_strips = s->min_strips; num_strips <= s->max_strips && num_strips <= s->h / MB_SIZE; num_strips++) { + int strip_offsets[MAX_STRIPS]; + int all_no_skip = 1; score = 0; size = 0; for (y = 0, strip = 1; y < s->h; strip++, y = nexty) { - int strip_height; + int strip_height, no_skip; + strip_offsets[strip-1] = size + CVID_HEADER_SIZE; nexty = strip * s->h / num_strips; // <= s->h // make nexty the next multiple of 4 if not already there if (nexty & 3) @@ -1099,21 +1109,24 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, if ((temp_size = rd_strip(s, y, strip_height, isakeyframe, last_data, last_linesize, data, linesize, scratch_data, scratch_linesize, - s->frame_buf + size + CVID_HEADER_SIZE, - &score_temp)) < 0) + s->frame_buf + strip_offsets[strip-1], + &score_temp, &no_skip)) < 0) return temp_size; score += score_temp; size += temp_size; + all_no_skip &= no_skip; } if (best_score == 0 || score < best_score) { best_score = score; - best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, isakeyframe); + best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, all_no_skip); FFSWAP(AVFrame *, s->best_frame, s->scratch_frame); memcpy(buf, s->frame_buf, best_size); best_nstrips = num_strips; + *got_keyframe = all_no_skip; // no skip MBs in any strip -> keyframe + memcpy(best_strip_offsets, strip_offsets, sizeof(strip_offsets)); } // avoid trying too many strip numbers without a real reason // (this makes the processing of the very first frame faster) @@ -1121,6 +1134,11 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, break; } + // update strip headers + for (i = 0; i < best_nstrips; i++) { + write_strip_keyframe(s->frame_buf + best_strip_offsets[i], *got_keyframe); + } + // let the number of strips slowly adapt to the changes in the contents, // compared to full bruteforcing every time this will occasionally lead // to some r/d performance loss but makes encoding up to several times faster @@ -1151,21 +1169,23 @@ static int cinepak_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { CinepakEncContext *s = avctx->priv_data; - int ret; + int ret, got_keyframe; s->lambda = frame->quality ? frame->quality - 1 : 2 * FF_LAMBDA_SCALE; if ((ret = ff_alloc_packet(avctx, pkt, s->frame_buf_size)) < 0) return ret; - ret = rd_frame(s, frame, (s->curframe == 0), pkt->data, s->frame_buf_size); + ret = rd_frame(s, frame, (s->curframe == 0), pkt->data, s->frame_buf_size, &got_keyframe); pkt->size = ret; - if (s->curframe == 0) + if (got_keyframe) { pkt->flags |= AV_PKT_FLAG_KEY; + s->curframe = 0; + } *got_packet = 1; FFSWAP(AVFrame *, s->last_frame, s->best_frame); - if (++s->curframe >= s->keyint) + if (++s->curframe >= avctx->gop_size) s->curframe = 0; return 0; diff --git a/tests/ref/vsynth/vsynth1-cinepak b/tests/ref/vsynth/vsynth1-cinepak index e47ae26b6d..7cb33220e7 100644 --- a/tests/ref/vsynth/vsynth1-cinepak +++ b/tests/ref/vsynth/vsynth1-cinepak @@ -1,4 +1,4 @@ -cd28e47a6ac396240a3fee69f15625d1 *tests/data/fate/vsynth1-cinepak.avi -408616 tests/data/fate/vsynth1-cinepak.avi -e74066a028c708f467272884ecd3f7d3 *tests/data/fate/vsynth1-cinepak.out.rawvideo -stddev: 61.38 PSNR: 12.37 MAXDIFF: 225 bytes: 7603200/ 921600 +6b9b4d2b32854fd8b0f84ee4d76b1fed *tests/data/fate/vsynth1-cinepak.avi +408910 tests/data/fate/vsynth1-cinepak.avi +4acdcc3e664d12facbcefc389079cfa6 *tests/data/fate/vsynth1-cinepak.out.rawvideo +stddev: 61.38 PSNR: 12.37 MAXDIFF: 223 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth2-cinepak b/tests/ref/vsynth/vsynth2-cinepak index 835de78d16..72b8794116 100644 --- a/tests/ref/vsynth/vsynth2-cinepak +++ b/tests/ref/vsynth/vsynth2-cinepak @@ -1,4 +1,4 @@ -663a2804f421709208c76f6e34e7bea5 *tests/data/fate/vsynth2-cinepak.avi -400402 tests/data/fate/vsynth2-cinepak.avi -2c761c3c8cda083eb8f54b2df72b257b *tests/data/fate/vsynth2-cinepak.out.rawvideo -stddev: 80.96 PSNR: 9.96 MAXDIFF: 227 bytes: 7603200/ 921600 +675d6a4370c315dc53c219a9271be4c6 *tests/data/fate/vsynth2-cinepak.avi +400720 tests/data/fate/vsynth2-cinepak.avi +cbf6900b882b484bc531f9b4799c226e *tests/data/fate/vsynth2-cinepak.out.rawvideo +stddev: 80.96 PSNR: 9.96 MAXDIFF: 229 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth_lena-cinepak b/tests/ref/vsynth/vsynth_lena-cinepak index 6b021673a0..c9cb2cfaba 100644 --- a/tests/ref/vsynth/vsynth_lena-cinepak +++ b/tests/ref/vsynth/vsynth_lena-cinepak @@ -1,4 +1,4 @@ -a9ea19eb0d239a53af8630d5bc4167d0 *tests/data/fate/vsynth_lena-cinepak.avi -407574 tests/data/fate/vsynth_lena-cinepak.avi -e32d4103194665d2ea0f46d5cdd0cdf2 *tests/data/fate/vsynth_lena-cinepak.out.rawvideo +a79f907fecb95c8a5b5de670ccda215b *tests/data/fate/vsynth_lena-cinepak.avi +407952 tests/data/fate/vsynth_lena-cinepak.avi +2664cdff5f14508e891477b498cc840e *tests/data/fate/vsynth_lena-cinepak.out.rawvideo stddev: 58.10 PSNR: 12.85 MAXDIFF: 185 bytes: 7603200/ 921600 -- 2.30.2