From patchwork Sun Oct 20 23:09:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Ross X-Patchwork-Id: 52427 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:143:b0:48e:c0f8:d0de with SMTP id h3csp2294803vqi; Sun, 20 Oct 2024 16:10:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVtFlIeAnyaBXcMEehz8D6Am82Gx4X2TzdV2W7siVv/kokdTQMMcbcuUDhN1OxbVVl4zoGKy4euN27VawJXhGqL@gmail.com X-Google-Smtp-Source: AGHT+IHect02OT3Ojd6nHCqRs6y+jSFLv5/wfVt6I4497MWTidx3xQDmeAiD4M+1vDeUrxc+xkUL X-Received: by 2002:a5d:4d03:0:b0:37d:476d:2d58 with SMTP id ffacd0b85a97d-37eb47693bamr5649705f8f.45.1729465820510; Sun, 20 Oct 2024 16:10:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1729465820; cv=none; d=google.com; s=arc-20240605; b=MVKUu66o2nCUE6dOYL+fWSCv8z5+S7A0wbFxHNdBolHSYAEQAFKeSxpbPSM1mBKkuA kkCY5GcDBvoDzRKxMVbnwriKnQ5rBg6J9gCazUVJk2xzr+8qeCmX+9vIkFaf9x52TcQs l8RKpljLZCgIf/N1/KNlznMnWpHICA0WSdh5UrK6y3DfEPpyzrCxADO3gdi7JLsTBRst GHwy7vTFgUjLJVsWWvPcFtQ1zXl8U0jr/utrTExjKnDIjXHA/54JKkJoCpr+v9qQXHV5 GdLCFYDL7177R2MFnPbmxuG+Q2gNgZMIY52/9NkOlKJJVrveNP+ySqOt1jsVUcxxwxDR 8+Xg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:to:from:date:delivered-to; bh=QkrBLGA2oycyPgcXamtZ9hF+BE0/r4Tja99PRqS10yQ=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=QleqBtjqVBnLIhQKoFA8teqaD/19VpPCfIBuASJpOW65mqNl9hAAlGw4KRXqBGnlqg PjKwr7Tl8sEJ55nkoXheBFtvi6R2w3fvFdRb14vHMcXXedVNNmjTHL9Ye9d6FY3vrf9+ mxQyN4MjcVbxGHF/pFR+sgz/s9pAFu4nnY18ltR88dsk4T8bsccbYPCn35x3K6MRvJzo QjyFVOiVMsa5QZ5iq3Xf/eRK0xFVZBMMJXWVP0RiSFx9k1D6gVxhYrtY9wcaxQ09KLin zJdkSg0opNyrZ5Aqezz48Fm4bUo9HYf3Aoug4JB89aZFiS5oHQ/FALpEE5b2mWZm4tcm XloQ==; dara=google.com 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 4fb4d7f45d1cf-5cb66e75827si1657697a12.669.2024.10.20.16.10.20; Sun, 20 Oct 2024 16:10:20 -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 A394768DB42; Mon, 21 Oct 2024 02:10:16 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mx.sdf.org (mx.sdf.org [205.166.94.24]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 939A068DA2C for ; Mon, 21 Oct 2024 02:10:09 +0300 (EEST) Received: from cd86a1ccc5d60b065a17e49d95f5a343 ([1.145.225.84]) (authenticated (0 bits)) by mx.sdf.org (8.18.1/8.14.3) with ESMTPSA id 49KN9NcJ001214 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits) verified NO) for ; Sun, 20 Oct 2024 23:10:05 GMT Date: Mon, 21 Oct 2024 10:09:17 +1100 From: Peter Ross To: ffmpeg-devel@ffmpeg.org Message-ID: <0fe07f647411e7a9f089cf23dd9615ea7487d52f.1729465724.git.pross@xvid.org> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avcodec/eatgq: decode motion vector macroblocks 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: fTeBlh46LMTh --- sample: https://discmaster.textfiles.com/file/22091/SSERVCD_50A.bin/DEMOS/NBA97/NBA97.EXE/WESTERN.UV libavcodec/codec_desc.c | 2 +- libavcodec/eatgq.c | 50 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 9ea94facba..6924a00e79 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -905,7 +905,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .type = AVMEDIA_TYPE_VIDEO, .name = "tgq", .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TQI, diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index d326c05390..a52e512c86 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -36,12 +36,14 @@ #include "avcodec.h" #include "bytestream.h" #include "codec_internal.h" +#include "copy_block.h" #include "decode.h" #include "eaidct.h" #include "get_bits.h" typedef struct TgqContext { AVCodecContext *avctx; + AVFrame *last_frame; int width, height; int qtable[64]; DECLARE_ALIGNED(16, int16_t, block)[6][64]; @@ -53,6 +55,9 @@ static av_cold int tgq_decode_init(AVCodecContext *avctx) s->avctx = avctx; avctx->framerate = (AVRational){ 15, 1 }; avctx->pix_fmt = AV_PIX_FMT_YUV420P; + s->last_frame = av_frame_alloc(); + if (!s->last_frame) + return AVERROR(ENOMEM); return 0; } @@ -173,7 +178,29 @@ static int tgq_decode_mb(TgqContext *s, GetByteContext *gbyte, tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y); bytestream2_skip(gbyte, mode); } else { - if (mode == 3) { + if (mode == 1) { + int x, y; + int mv = bytestream2_get_byte(gbyte); + int mv_x = mv >> 4; + int mv_y = mv & 0x0F; + if (mv_x >= 8) mv_x -= 16; + if (mv_y >= 8) mv_y -= 16; + x = mb_x * 16 - mv_x; + y = mb_y * 16 - mv_y; + if (x < 0 || x + 16 > s->width || y < 0 || y + 16 > s->height) { + av_log(s->avctx, AV_LOG_ERROR, "invalid motion vector\n"); + return -1; + } + copy_block16(frame->data[0] + (mb_y * 16 * frame->linesize[0]) + mb_x * 16, + s->last_frame->data[0] + y * s->last_frame->linesize[0] + x, + frame->linesize[0], s->last_frame->linesize[0], 16); + for (int p = 1; p < 3; p++) + copy_block8(frame->data[p] + (mb_y * 8 * frame->linesize[p]) + mb_x * 8, + s->last_frame->data[p] + (y >> 1) * s->last_frame->linesize[p] + (x >> 1), + frame->linesize[p], s->last_frame->linesize[p], 8); + frame->flags &= ~AV_FRAME_FLAG_KEY; + return 0; + } else if (mode == 3) { memset(dc, bytestream2_get_byte(gbyte), 4); dc[4] = bytestream2_get_byte(gbyte); dc[5] = bytestream2_get_byte(gbyte); @@ -228,9 +255,12 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, s->height = bytestream2_get_le16u(&gbyte); } - ret = ff_set_dimensions(s->avctx, s->width, s->height); - if (ret < 0) - return ret; + if (s->avctx->width != s->width || s->avctx->height != s->height) { + av_frame_unref(s->last_frame); + ret = ff_set_dimensions(s->avctx, s->width, s->height); + if (ret < 0) + return ret; + } tgq_calculate_qtable(s, bytestream2_get_byteu(&gbyte)); bytestream2_skipu(&gbyte, 3); @@ -238,16 +268,27 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; + frame->flags |= AV_FRAME_FLAG_KEY; for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++) if (tgq_decode_mb(s, &gbyte, frame, y, x) < 0) return AVERROR_INVALIDDATA; + if ((ret = av_frame_replace(s->last_frame, frame)) < 0) + return ret; + *got_frame = 1; return avpkt->size; } +static av_cold int tgq_decode_close(AVCodecContext *avctx) +{ + TgqContext *s = avctx->priv_data; + av_frame_free(&s->last_frame); + return 0; +} + const FFCodec ff_eatgq_decoder = { .p.name = "eatgq", CODEC_LONG_NAME("Electronic Arts TGQ video"), @@ -255,6 +296,7 @@ const FFCodec ff_eatgq_decoder = { .p.id = AV_CODEC_ID_TGQ, .priv_data_size = sizeof(TgqContext), .init = tgq_decode_init, + .close = tgq_decode_close, FF_CODEC_DECODE_CB(tgq_decode_frame), .p.capabilities = AV_CODEC_CAP_DR1, };