From patchwork Wed Mar 30 20:32:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 35092 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c05:b0:7a:e998:b410 with SMTP id bw5csp1011523pzb; Wed, 30 Mar 2022 13:33:39 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxyaGYtb/CKBe1NNsRR5vmBrtRKmagUAuk2saUtPIEb7K2fDz1iCC8SmV27oDcGFNy8ilH8 X-Received: by 2002:a05:6402:270f:b0:419:5b71:3493 with SMTP id y15-20020a056402270f00b004195b713493mr12877850edd.72.1648672419703; Wed, 30 Mar 2022 13:33:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648672419; cv=none; d=google.com; s=arc-20160816; b=ioUxReQS5uYTguWEdPvQgGmxoDzoBkzUV98dzTKiFmjLBT3hkC2NO5QQ1BZNFCEGju xJuuB2YA+Bjc6Vradfs/y7QR7f3SpqTidf6qdNIFWHh/NBuXDqbpKx6tudwq891dIZm0 MVzMTCMWDe34tmMf7SboD0JVGw8R/iu+Jd/0ToqpOCOD1CJcHVwmLqGpFoSjmI2RIs2G j0tx+XaKFec5BzKru0uIeOITmkRqBnQX9skuF2nWCLKg50xhK62O7sjZNayEDVf/c6mV IEYaVJfuG1ABsaB/Q2cbWjnsEWoybqv4mXVNHYyJwxyRxzg9NJgIjezZ6nUh90SMBwNV XRew== 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:references:in-reply-to :message-id:date:to:from:delivered-to; bh=aV5T8vdIaG6PUQOXndzUXQTqlxu4tuwGh2afTXsb3dQ=; b=hpf6Zaioy9iq/TVQw64gOgvw+UNgyWYwJ1FxYD22QPxbty/mHAQEvoxHCOm2aglH2Z v5P36GLXCUmPcR1ITJSqVUG6nsjGmIy0R1Atc93+16VIvSVHQC2wi8ef1Wg2WUE67MOZ a5R5k/++M2B/uq2HX3fpXCThg2MC22Af8bORJ52vb5kqkL3KeM+yHinjvTjGdvMWtajc 2tmU+Ffu5R74cYm+QMY8KEUonKFkyvEVgStMveCCd+PDb10/s70Sa04B3NRXscskDJoY 7tYshkxE5TQ5vMGLg1tzc05ECMuDmDTWDOsZcE2hHMHI+s0ZHsfwrVaxUCU6NVS8oXLv +iVA== 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 t1-20020aa7d4c1000000b0041958583258si21768254edr.500.2022.03.30.13.33.38; Wed, 30 Mar 2022 13:33:39 -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 11B3668B28C; Wed, 30 Mar 2022 23:32:32 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5F30868B2A1 for ; Wed, 30 Mar 2022 23:32:25 +0300 (EEST) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id EC62EE6BB6; Wed, 30 Mar 2022 22:32:25 +0200 (CEST) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id kxVfUvUFhBS7; Wed, 30 Mar 2022 22:32:23 +0200 (CEST) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 2FB39E6DDE; Wed, 30 Mar 2022 22:32:22 +0200 (CEST) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Wed, 30 Mar 2022 22:32:04 +0200 Message-Id: <20220330203205.25937-7-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220330203205.25937-1-cus@passwd.hu> References: <20220330203205.25937-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 7/8] avcodec/vbnenc: add VBN encoder 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: Marton Balint Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: VInhGJUT9T7j Signed-off-by: Marton Balint --- Changelog | 2 +- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/vbnenc.c | 173 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavformat/img2enc.c | 2 +- libavformat/version.h | 4 +- 8 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 libavcodec/vbnenc.c diff --git a/Changelog b/Changelog index 7bad88dabc..c3fbba5221 100644 --- a/Changelog +++ b/Changelog @@ -6,7 +6,7 @@ version 5.1: - dropped obsolete XvMC hwaccel - pcm-bluray encoder - DFPWM audio encoder/decoder and raw muxer/demuxer -- Vizrt Binary Image decoder +- Vizrt Binary Image encoder/decoder version 5.0: diff --git a/configure b/configure index 90c99ff85e..9c8965852b 100755 --- a/configure +++ b/configure @@ -2960,6 +2960,7 @@ utvideo_decoder_select="bswapdsp llviddsp" utvideo_encoder_select="bswapdsp huffman llvidencdsp" vble_decoder_select="llviddsp" vbn_decoder_select="texturedsp" +vbn_encoder_select="texturedspenc" vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideodec vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 90700085b8..90f46035d9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -709,6 +709,7 @@ OBJS-$(CONFIG_V410_DECODER) += v410dec.o OBJS-$(CONFIG_V410_ENCODER) += v410enc.o OBJS-$(CONFIG_VB_DECODER) += vb.o OBJS-$(CONFIG_VBN_DECODER) += vbndec.o +OBJS-$(CONFIG_VBN_ENCODER) += vbnenc.o OBJS-$(CONFIG_VBLE_DECODER) += vble.o OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o \ vc1_mc.o vc1_pred.o vc1.o vc1data.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f0a7ea7fd4..585918da93 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -347,6 +347,7 @@ extern const FFCodec ff_v408_decoder; extern const FFCodec ff_v410_encoder; extern const FFCodec ff_v410_decoder; extern const FFCodec ff_vb_decoder; +extern const FFCodec ff_vbn_encoder; extern const FFCodec ff_vbn_decoder; extern const FFCodec ff_vble_decoder; extern const FFCodec ff_vc1_decoder; diff --git a/libavcodec/vbnenc.c b/libavcodec/vbnenc.c new file mode 100644 index 0000000000..51f618c7d9 --- /dev/null +++ b/libavcodec/vbnenc.c @@ -0,0 +1,173 @@ +/* + * Vizrt Binary Image encoder + * + * 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 + */ + +/** + * @file + * Vizrt Binary Image encoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "encode.h" +#include "texturedsp.h" +#include "vbn.h" + +#include "libavutil/imgutils.h" +#include "libavutil/frame.h" +#include "libavutil/opt.h" + +typedef struct VBNContext { + AVClass *class; + TextureDSPContext dxtc; + PutByteContext pb; + int format; + TextureDSPThreadContext enc; +} VBNContext; + +static int vbn_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + VBNContext *ctx = avctx->priv_data; + PutByteContext *pb = &ctx->pb; + int ret; + ptrdiff_t linesize; + int64_t pkt_size; + + ret = av_image_check_size2(frame->width, frame->height, INT_MAX, frame->format, 0, avctx); + if (ret < 0) + return ret; + + if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) { + if (frame->width % TEXTURE_BLOCK_W || frame->height % TEXTURE_BLOCK_H) { + av_log(avctx, AV_LOG_ERROR, "Video size %dx%d is not multiple of 4\n", frame->width, frame->height); + return AVERROR(EINVAL); + } + if (frame->format != AV_PIX_FMT_RGBA) { + av_log(avctx, AV_LOG_ERROR, "DXT formats only support RGBA pixel format\n"); + return AVERROR(EINVAL); + } + ctx->enc.raw_ratio = 16; + ctx->enc.slice_count = av_clip(avctx->thread_count, 1, avctx->height / TEXTURE_BLOCK_H); + } + + switch (ctx->format) { + case VBN_FORMAT_DXT1: + linesize = frame->width / 2; + ctx->enc.tex_funct = ctx->dxtc.dxt1_block; + ctx->enc.tex_ratio = 8; + break; + case VBN_FORMAT_DXT5: + linesize = frame->width; + ctx->enc.tex_funct = ctx->dxtc.dxt5_block; + ctx->enc.tex_ratio = 16; + break; + case VBN_FORMAT_RAW: + linesize = av_image_get_linesize(frame->format, frame->width, 0); + if (linesize < 0) + return linesize; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid format %02X\n", ctx->format); + return AVERROR(EINVAL); + } + + pkt_size = VBN_HEADER_SIZE + linesize * frame->height; + if (pkt_size > INT_MAX) + return AVERROR(EINVAL); + + if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0) + return ret; + + memset(pkt->data, 0, VBN_HEADER_SIZE); + bytestream2_init_writer(pb, pkt->data, pkt_size); + bytestream2_put_le32(pb, VBN_MAGIC); + bytestream2_put_le32(pb, VBN_MAJOR); + bytestream2_put_le32(pb, VBN_MINOR); + bytestream2_put_le32(pb, frame->width); + bytestream2_put_le32(pb, frame->height); + bytestream2_put_le32(pb, frame->format == AV_PIX_FMT_RGBA ? 4 : 3); + bytestream2_put_le32(pb, ctx->format); + bytestream2_put_le32(pb, frame->format == AV_PIX_FMT_RGBA ? VBN_PIX_RGBA : VBN_PIX_RGB); + bytestream2_put_le32(pb, 0); // mipmaps + bytestream2_put_le32(pb, pkt_size - VBN_HEADER_SIZE); + bytestream2_seek_p(pb, 64, SEEK_SET); + bytestream2_put_le32(pb, pkt_size - VBN_HEADER_SIZE); + + if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) { + ctx->enc.frame_data.in = (frame->height - 1) * frame->linesize[0] + frame->data[0]; + ctx->enc.stride = -frame->linesize[0]; + ctx->enc.tex_data.out = pkt->data + VBN_HEADER_SIZE; + avctx->execute2(avctx, ff_texturedsp_compress_thread, &ctx->enc, NULL, ctx->enc.slice_count); + } else { + uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1); + av_image_copy_plane(pkt->data + VBN_HEADER_SIZE, linesize, flipped, -frame->linesize[0], linesize, frame->height); + } + + *got_packet = 1; + return 0; +} + +static av_cold int vbn_init(AVCodecContext *avctx) +{ + VBNContext *ctx = avctx->priv_data; + ff_texturedspenc_init(&ctx->dxtc); + return 0; +} + +static av_cold int vbn_close(AVCodecContext *avctx) +{ + return 0; +} + +#define OFFSET(x) offsetof(VBNContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "format", "Texture format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = VBN_FORMAT_DXT5 }, VBN_FORMAT_RAW, VBN_FORMAT_DXT5, FLAGS, "format" }, + { "raw", "RAW texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_RAW }, 0, 0, FLAGS, "format" }, + { "dxt1", "DXT1 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT1 }, 0, 0, FLAGS, "format" }, + { "dxt5", "DXT5 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT5 }, 0, 0, FLAGS, "format" }, + { NULL }, +}; + +static const AVClass vbnenc_class = { + .class_name = "VBN encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_vbn_encoder = { + .p.name = "vbn", + .p.long_name = NULL_IF_CONFIG_SMALL("Vizrt Binary Image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VBN, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS, + .p.priv_class = &vbnenc_class, + .init = vbn_init, + .encode2 = vbn_encode, + .close = vbn_close, + .priv_data_size = sizeof(VBNContext), + .p.pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE, + }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a744e7469f..26ee41eb1f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 25 +#define LIBAVCODEC_VERSION_MINOR 26 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 9b3b8741c8..ae351963d9 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -265,7 +265,7 @@ const AVOutputFormat ff_image2_muxer = { .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), .extensions = "bmp,dpx,exr,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,png," "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24," - "sunras,xbm,xface,pix,y", + "sunras,vbn,xbm,xface,pix,y", .priv_data_size = sizeof(VideoMuxData), .video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, diff --git a/libavformat/version.h b/libavformat/version.h index f4a26c2870..683184d5da 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 20 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 21 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \