From patchwork Sun Jun 4 14:03:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 41976 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c51c:b0:10c:5e6f:955f with SMTP id gm28csp2490981pzb; Sun, 4 Jun 2023 07:03:43 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4KdTIc2DWiGoTEHHrq7IoGC1elyFtpAA2W8xEZ93zVVVtXCYa2Zo5qPAY2TVOjIXnWPv+p X-Received: by 2002:a17:907:e9f:b0:96f:d154:54f7 with SMTP id ho31-20020a1709070e9f00b0096fd15454f7mr4048102ejc.42.1685887422491; Sun, 04 Jun 2023 07:03:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685887422; cv=none; d=google.com; s=arc-20160816; b=AT1yk+/kTVjoC6UpX+l3G3qpnanSygndTA2CKGRY5kRFEboj4aRbot8epqY9tlWTif 5p7h55eyqJEHkvZ2aJ+fyh/f5ARY6CtNAKZuMFVEfVD49UbVHxpQhW93aG/Bdqp2on24 Z11K0QhqG0R+KEaCWAEDKB6v5dYDicAGC3GC+5xEk5aMuUq7rF4JPD6PU6Wy1Zf98Zln Kfy6xTiVHYVCfZ7scyYA6rs73rAsAWROAr+F6EYb5N0zAf7FweDWSVMr2robupwp2PB0 DeH0zJCrVOnrR6KyRXJhyFGDy6zOXSrfHkslD82yMdw+IiZEvuEQuELDczm9dQb+RKh5 mX1w== 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:to :message-id:date:from:mime-version:dkim-signature:delivered-to; bh=1rbOciuEbmeK9WTvKqEAlq3FU+wW9oZr1jv8QET+iAw=; b=OajLAHwMooJhCRvFHzGRlE59AppS7uBH0FvbyHhtrZuMME6S0Q6kBHpIwh/bLS4nMT 2owQeDj42WrsKHinRAx34cCwPjPauk6yqD9StLdOX+YdyoAjEzEynuEkGkJGN8h7g9iD Mub6KhecB7m+WIHkt3pCioW7IHlRc/gMRRuo9qxlu4Le8Jx6Q9Iw4UMX1egicLr07lNT hErczCxJbVhHXP5RONA8+pn4dIs8N6JS8tJDwVxfpJSk4H8mn4qMDRXWU5zt1SyzMQAQ zZFDz6b+B2QXHWyBo8n6xzgWqsA2SQNbSyzV1YOCsFbVbaD3KKHfmQX2r1+nnFyzk6Iy Pvxg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=k6FZCGgW; 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 q19-20020a1709060e5300b00969c8607ef5si3421787eji.1038.2023.06.04.07.03.39; Sun, 04 Jun 2023 07:03:42 -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=20221208 header.b=k6FZCGgW; 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 BA44068C309; Sun, 4 Jun 2023 17:03:35 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f46.google.com (mail-qv1-f46.google.com [209.85.219.46]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0D2C668C309 for ; Sun, 4 Jun 2023 17:03:28 +0300 (EEST) Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-6237faa8677so28630246d6.1 for ; Sun, 04 Jun 2023 07:03:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685887407; x=1688479407; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=X/YxO2sbP5Q801tDTiQgQcab99NKdnn+IYy6UcTOmgc=; b=k6FZCGgWNgU7O4rgjcT4822fLgNzw40l3HnG8PiyfyGqRtxHcGAaKXHWZ9cv4v4u3T rGoogozEQ/12pdRyfPO4tf/oG+og1mhTOlw3hkosL6NXDi8GBVC6lWeg6AF38hi7hn1u MJ/5nS33MZf416fgaZNd4zuoCbYJed21pnuOMST2oywp37f8DLrQ1FGQKWvuMilCYaWj I3GNMeZOkfbSFUuFmLRLtsyScM1Lfcj02KGgaAmee8t/sEwvJHN0KOxmaE3uvd3mR66k Od2xiYol0aT/DrhHt5Aze8Ies4L6Tg2Oi4P7vYG2qGI9NXq0DxznqZayYgIoecaoLkd4 HmlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685887407; x=1688479407; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=X/YxO2sbP5Q801tDTiQgQcab99NKdnn+IYy6UcTOmgc=; b=K7EmzqTlfX/sWNS3DPZUgz6ZhaLVI7PhQ1Py9keoXgkFVud7AJVlPFj/GRlVKFpINz 0vANo9Oe7tT0UyjliXPAzP8TGUM6xAgXO0OnOUFTGKAO2E/9nIQk3NxBaRGM43Y3etT1 10VfNpl6zk+Zno3G1D/BE1uf2KKgcQb932If7JacZd9I2L7DwXA8AMX7yHqjpZnwFKle jz5hOHPf5y3p9m3q4cc5cFTJ2yQGcTlNmuataU80muWeI4Vn9hrB+8G6F+HW6Yhr9KZf TG43c+x/g4TDmkFhnOJlgnf/8QX67TZLCZoC5hPy+/gLYAjnUK2QddDUA3W06ljWAdg3 aU8Q== X-Gm-Message-State: AC+VfDwteIBqn7nLFE3qHlMyPjTTkz8Qr7Tn1T93BVQ4cmYK69P0U9rJ 8JCsmQP27eh0/8DR3R7GA1ICPjcBH83QSVy/5pgFeq/H X-Received: by 2002:a05:6214:c4c:b0:5e3:d150:3163 with SMTP id r12-20020a0562140c4c00b005e3d1503163mr6004546qvj.20.1685887406624; Sun, 04 Jun 2023 07:03:26 -0700 (PDT) MIME-Version: 1.0 From: Paul B Mahol Date: Sun, 4 Jun 2023 16:03:12 +0200 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: [FFmpeg-devel] [PATCH] avcodec: add RTV1 decoder 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: LDICwsqRWVMR Attached. From cdd867aa1c88fa8b89dfe473ae0e2caf69c74313 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 3 Jun 2023 12:29:25 +0200 Subject: [PATCH] avcodec: add RTV1 decoder Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/rtv1.c | 141 ++++++++++++++++++++++++++++++++++++++++ libavformat/riff.c | 1 + 6 files changed, 152 insertions(+) create mode 100644 libavcodec/rtv1.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9aacc1d477..87a8b90037 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -643,6 +643,7 @@ OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o OBJS-$(CONFIG_RPZA_DECODER) += rpza.o OBJS-$(CONFIG_RPZA_ENCODER) += rpzaenc.o OBJS-$(CONFIG_RSCC_DECODER) += rscc.o +OBJS-$(CONFIG_RTV1_DECODER) += rtv1.o OBJS-$(CONFIG_RV10_DECODER) += rv10.o OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o OBJS-$(CONFIG_RV20_DECODER) += rv10.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 184bb8521f..a98c300da4 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -295,6 +295,7 @@ extern const FFCodec ff_roq_decoder; extern const FFCodec ff_rpza_encoder; extern const FFCodec ff_rpza_decoder; extern const FFCodec ff_rscc_decoder; +extern const FFCodec ff_rtv1_decoder; extern const FFCodec ff_rv10_encoder; extern const FFCodec ff_rv10_decoder; extern const FFCodec ff_rv20_encoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 310ed66415..41293a78dc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1946,6 +1946,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, .profiles = NULL_IF_CONFIG_SMALL(ff_evc_profiles), }, + { + .id = AV_CODEC_ID_RTV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rtv1", + .long_name = NULL_IF_CONFIG_SMALL("RTV1 (RivaTuner Video)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 9f621afff0..9a78cfabe2 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -322,6 +322,7 @@ enum AVCodecID { AV_CODEC_ID_VQC, AV_CODEC_ID_PDV, AV_CODEC_ID_EVC, + AV_CODEC_ID_RTV1, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/rtv1.c b/libavcodec/rtv1.c new file mode 100644 index 0000000000..953f915c83 --- /dev/null +++ b/libavcodec/rtv1.c @@ -0,0 +1,141 @@ +/* + * RTV1 decoder + * Copyright (c) 2023 Paul B Mahol + * + * 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 +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "decode.h" +#include "texturedsp.h" +#include "thread.h" + +static int decode_rtv1(GetByteContext *gb, uint8_t *dst, int linesize, + int width, int height, int flag, + int (*dxt1_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)) +{ + uint8_t block[8] = { 0 }; + int run = 0; + + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width * 4; x += 16) { + int mode = 0; + + if (run && --run > 0) { + dxt1_block(dst + x, linesize, block); + } else { + int a, b; + + if (bytestream2_get_bytes_left(gb) < 4) + break; + + a = bytestream2_get_le16u(gb); + b = bytestream2_get_le16u(gb); + if (a == b && flag) { + AV_WL32(block + 4, 0); + } else if (a == 1 && b == 0xffff) { + mode = 1; + } else if (b && a == 0) { + run = b; + } else { + AV_WL16(block, a); + AV_WL16(block + 2, b); + AV_WL32(block + 4, bytestream2_get_le32(gb)); + } + if (run && !mode) { + dxt1_block(dst + x, linesize, block); + } else if (!mode) { + AV_WL16(block, a); + AV_WL16(block + 2, b); + dxt1_block(dst + x, linesize, block); + } else { + if (bytestream2_get_bytes_left(gb) < 12 * 4) + break; + + for (int by = 0; by < 4; by++) { + for (int bx = 0; bx < 4; bx++) + AV_WL32(dst + x + bx * 4 + by * linesize, bytestream2_get_le24u(gb)); + } + } + } + } + + dst += linesize * 4; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) +{ + int ret, width, height, flags; + TextureDSPContext dsp; + GetByteContext gb; + ptrdiff_t linesize; + uint8_t *dst; + + if (avpkt->size < 22) + return AVERROR_INVALIDDATA; + + ff_texturedsp_init(&dsp); + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + if (bytestream2_get_le32(&gb) != MKTAG('D','X','T','1')) + return AVERROR_INVALIDDATA; + flags = bytestream2_get_le32(&gb); + + width = bytestream2_get_le32(&gb); + height = bytestream2_get_le32(&gb); + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + + avctx->coded_width = FFALIGN(avctx->width, 4); + avctx->coded_height = FFALIGN(avctx->height, 4); + avctx->pix_fmt = AV_PIX_FMT_BGR0; + + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) + return ret; + + dst = p->data[0] + p->linesize[0] * (avctx->coded_height - 1); + linesize = -p->linesize[0]; + + decode_rtv1(&gb, dst, linesize, width, height, flags, dsp.dxt1_block); + + p->pict_type = AV_PICTURE_TYPE_I; + p->flags |= AV_FRAME_FLAG_KEY; + + *got_frame = 1; + + return avpkt->size; +} + +const FFCodec ff_rtv1_decoder = { + .p.name = "rtv1", + CODEC_LONG_NAME("RTV1 (RivaTuner Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RTV1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +}; diff --git a/libavformat/riff.c b/libavformat/riff.c index 7319406b39..4279071159 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -501,6 +501,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_NOTCHLC, MKTAG('n', 'l', 'c', '1') }, { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '1') }, { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') }, + { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') }, { AV_CODEC_ID_NONE, 0 } }; -- 2.39.1