From: Marton Balint <cus@passwd.hu> To: ffmpeg-devel@ffmpeg.org Cc: Marton Balint <cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 7/8] avcodec/vbnenc: add VBN encoder Date: Wed, 30 Mar 2022 22:32:04 +0200 Message-ID: <20220330203205.25937-7-cus@passwd.hu> (raw) In-Reply-To: <20220330203205.25937-1-cus@passwd.hu> Signed-off-by: Marton Balint <cus@passwd.hu> --- 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, \ -- 2.31.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-03-30 20:33 UTC|newest] Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-03-30 20:31 [FFmpeg-devel] [PATCH 1/8] fate/filter-refcmp-*: make refcmp_metadata fail on empty input Marton Balint 2022-03-30 20:31 ` [FFmpeg-devel] [PATCH 2/8] avcodec/texturedsp: add TextureDSPThreadContext for common decode/encode function Marton Balint 2022-03-30 20:32 ` [FFmpeg-devel] [PATCH 3/8] avcodec/dds: use the common texture dsp decode function Marton Balint 2022-03-30 20:32 ` [FFmpeg-devel] [PATCH 4/8] avcodec/hapdec: use the common texturedsp " Marton Balint 2022-03-30 20:32 ` [FFmpeg-devel] [PATCH 5/8] avcodec/hapenc: use the common texturedsp encode function Marton Balint 2022-03-30 20:32 ` [FFmpeg-devel] [PATCH 6/8] avcodec/vbndec: add VBN decoder Marton Balint 2022-03-30 20:32 ` Marton Balint [this message] 2022-03-30 20:32 ` [FFmpeg-devel] [PATCH 8/8] fate: add fate tests for VBN encoder and decoder Marton Balint 2022-04-09 22:46 ` Marton Balint 2022-03-31 7:38 ` [FFmpeg-devel] [PATCH 1/8] fate/filter-refcmp-*: make refcmp_metadata fail on empty input Tobias Rapp 2022-03-31 21:30 ` [FFmpeg-devel] [PATCH v2 1/8] fate/filter-refcmp-*: make refcmp_metadata fail on empty or truncated input Marton Balint 2022-04-01 6:26 ` Tobias Rapp
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220330203205.25937-7-cus@passwd.hu \ --to=cus@passwd.hu \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git