* [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder
@ 2022-11-12 0:39 Peter Ross
2022-11-12 15:33 ` James Almer
2022-11-12 16:42 ` Michael Niedermayer
0 siblings, 2 replies; 3+ messages in thread
From: Peter Ross @ 2022-11-12 0:39 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1.1: Type: text/plain, Size: 18336 bytes --]
Partially fixes ticket #798
---
sample: https://trac.ffmpeg.org/raw-attachment/ticket/798/DaDa_CMP.avi
configure | 1 +
doc/general_contents.texi | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/codec_desc.c | 7 +
libavcodec/codec_id.h | 1 +
libavcodec/leaddata.h | 62 ++++++++
libavcodec/leaddec.c | 290 ++++++++++++++++++++++++++++++++++++++
libavformat/riff.c | 1 +
9 files changed, 365 insertions(+)
create mode 100644 libavcodec/leaddata.h
create mode 100644 libavcodec/leaddec.c
diff --git a/configure b/configure
index e6470dc03b..56af100e94 100755
--- a/configure
+++ b/configure
@@ -2861,6 +2861,7 @@ ipu_decoder_select="mpegvideodec"
jpegls_decoder_select="mjpeg_decoder"
jv_decoder_select="blockdsp"
lagarith_decoder_select="llviddsp"
+lead_decoder_select="idctdsp jpegtables"
ljpeg_encoder_select="jpegtables"
lscr_decoder_select="inflate_wrapper"
magicyuv_decoder_select="llviddsp"
diff --git a/doc/general_contents.texi b/doc/general_contents.texi
index 8399fcb6b7..6832055316 100644
--- a/doc/general_contents.texi
+++ b/doc/general_contents.texi
@@ -987,6 +987,7 @@ following image formats are supported:
@item Lagarith @tab @tab X
@item LCL (LossLess Codec Library) MSZH @tab @tab X
@item LCL (LossLess Codec Library) ZLIB @tab E @tab E
+@item LEAD MCMP @tab @tab X
@item LOCO @tab @tab X
@item LucasArts SANM/Smush @tab @tab X
@tab Used in LucasArts games / SMUSH animations.
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 94dc75a1b2..aa99eba7b7 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -463,6 +463,7 @@ OBJS-$(CONFIG_JV_DECODER) += jvdec.o
OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
+OBJS-$(CONFIG_LEAD_DECODER) += leaddec.o jpegquanttables.o
OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o
OBJS-$(CONFIG_LOCO_DECODER) += loco.o
OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec3bc6e1..4b96443946 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -187,6 +187,7 @@ extern const FFCodec ff_jv_decoder;
extern const FFCodec ff_kgv1_decoder;
extern const FFCodec ff_kmvc_decoder;
extern const FFCodec ff_lagarith_decoder;
+extern const FFCodec ff_lead_decoder;
extern const FFCodec ff_ljpeg_encoder;
extern const FFCodec ff_loco_decoder;
extern const FFCodec ff_lscr_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 24a0433dba..9a1720f615 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1923,6 +1923,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("ViewQuest VQC"),
.props = AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_LEAD,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "lead",
+ .long_name = NULL_IF_CONFIG_SMALL("LEAD MCMP"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
/* various PCM "codecs" */
{
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index f436a2b624..31c590278e 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -320,6 +320,7 @@ enum AVCodecID {
AV_CODEC_ID_WBMP,
AV_CODEC_ID_MEDIA100,
AV_CODEC_ID_VQC,
+ AV_CODEC_ID_LEAD,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
diff --git a/libavcodec/leaddata.h b/libavcodec/leaddata.h
new file mode 100644
index 0000000000..525b582cf7
--- /dev/null
+++ b/libavcodec/leaddata.h
@@ -0,0 +1,62 @@
+/*
+ * LEAD MCMP decoder tables
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_LEADDATA_H
+#define AVCODEC_LEADDATA_H
+
+#include <stdint.h>
+
+static const uint8_t luma_dc_len[]={
+ 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9
+};
+
+static const uint8_t chroma_dc_len[]={
+ 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const uint8_t luma_ac_len[]={
+ 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8,
+ 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11,
+ 12, 12, 12, 12, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16
+};
+
+static const uint8_t chroma_ac_len[]={
+ 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 12, 12, 12, 12, 14, 15, 15, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16
+};
+
+#endif /* AVCODEC_LEADDATA_H */
diff --git a/libavcodec/leaddec.c b/libavcodec/leaddec.c
new file mode 100644
index 0000000000..3bda06458a
--- /dev/null
+++ b/libavcodec/leaddec.c
@@ -0,0 +1,290 @@
+/*
+ * LEAD MCMP decoder
+ *
+ * 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 "avcodec.h"
+#include "codec_internal.h"
+#include "copy_block.h"
+#include "decode.h"
+#include "get_bits.h"
+#include "idctdsp.h"
+#include "jpegquanttables.h"
+#include "jpegtables.h"
+#include "leaddata.h"
+#include "libavutil/thread.h"
+
+#define LUMA_DC_BITS 9
+#define CHROMA_DC_BITS 11
+#define LUMA_AC_BITS 10
+#define CHROMA_AC_BITS 10
+
+static VLC luma_dc_vlc;
+static VLC chroma_dc_vlc;
+static VLC luma_ac_vlc;
+static VLC chroma_ac_vlc;
+
+static av_cold void lead_init_static_data(void)
+{
+ INIT_VLC_STATIC_FROM_LENGTHS(&luma_dc_vlc, LUMA_DC_BITS, FF_ARRAY_ELEMS(luma_dc_len),
+ luma_dc_len, 1,
+ 0, 0, 0,
+ 0, 0, 1 << LUMA_DC_BITS);
+ INIT_VLC_STATIC_FROM_LENGTHS(&chroma_dc_vlc, CHROMA_DC_BITS, FF_ARRAY_ELEMS(chroma_dc_len),
+ chroma_dc_len, 1,
+ 0, 0, 0,
+ 0, 0, 1 << CHROMA_DC_BITS);
+ INIT_VLC_STATIC_FROM_LENGTHS(&luma_ac_vlc, LUMA_AC_BITS, FF_ARRAY_ELEMS(luma_ac_len),
+ luma_ac_len, 1,
+ ff_mjpeg_val_ac_luminance, 1, 1,
+ 0, 0, 1160);
+ INIT_VLC_STATIC_FROM_LENGTHS(&chroma_ac_vlc, CHROMA_AC_BITS, FF_ARRAY_ELEMS(chroma_ac_len),
+ chroma_ac_len, 1,
+ ff_mjpeg_val_ac_chrominance, 1, 1,
+ 0, 0, 1160);
+}
+
+typedef struct LeadContext {
+ uint8_t *bitstream_buf;
+ unsigned int bitstream_buf_size;
+ IDCTDSPContext idsp;
+ uint8_t permutated_scantable[64];
+} LeadContext;
+
+static av_cold int lead_decode_init(AVCodecContext * avctx)
+{
+ static AVOnce init_static_once = AV_ONCE_INIT;
+ LeadContext *s = avctx->priv_data;
+
+ if (avctx->extradata_size < 20)
+ return AVERROR_INVALIDDATA;
+
+ ff_idctdsp_init(&s->idsp, avctx);
+ ff_permute_scantable(s->permutated_scantable, ff_zigzag_direct, s->idsp.idct_permutation);
+
+ ff_thread_once(&init_static_once, lead_init_static_data);
+
+ return 0;
+}
+
+static void calc_dequant(uint16_t * dequant, const uint8_t * quant_tbl, int q)
+{
+ for (int i = 0; i < 64; i++)
+ dequant[i] = av_clip(q * quant_tbl[ff_zigzag_direct[i]] / 50, 2, 32767);
+}
+
+static int decode_block(LeadContext * s, GetBitContext * gb,
+ const VLCElem * dc_table, int dc_bits, const VLCElem * ac_table, int ac_bits,
+ int16_t * dc_pred, const uint16_t * dequant,
+ uint8_t * dst, int stride)
+{
+ int16_t block[64];
+ int size;
+
+ memset(block, 0, sizeof(block));
+
+ size = get_vlc2(gb, dc_table, dc_bits, 1);
+ if (size < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (size)
+ *dc_pred += get_xbits(gb, size);
+
+ block[0] = (1 << 10) + *dc_pred * dequant[0];
+
+ for (int i = 1; i < 64; i++) {
+ int symbol = get_vlc2(gb, ac_table, ac_bits, 2);
+ if (size < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (!symbol)
+ break;
+
+ i += symbol >> 4;
+ if (i >= 64)
+ return AVERROR_INVALIDDATA;
+
+ size = symbol & 0xF;
+ if (size)
+ block[s->permutated_scantable[i]] = get_xbits(gb, size) * dequant[i];
+ }
+
+ s->idsp.idct_put(dst, stride, block);
+ return 0;
+}
+
+static int lead_decode_frame(AVCodecContext *avctx, AVFrame * frame,
+ int * got_frame, AVPacket * avpkt)
+{
+ LeadContext *s = avctx->priv_data;
+ const uint8_t * buf = avpkt->data;
+ int ret, format, yuv20p_half = 0, fields = 1, q, size;
+ GetBitContext gb;
+ int16_t dc_pred[3] = {0, 0, 0};
+ uint16_t dequant[2][64];
+
+ if (avpkt->size < 8)
+ return AVERROR_INVALIDDATA;
+
+ format = AV_RL16(buf + 4);
+ switch(format) {
+ case 0x1000:
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+ break;
+ case 0x2000:
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+ break;
+ case 0x2006:
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+ fields = 2;
+ break;
+ case 0x8000:
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+ yuv20p_half = 1;
+ break;
+ default:
+ avpriv_request_sample(avctx, "unsupported format 0x%x", format);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ q = AV_RL16(buf + 6);
+ calc_dequant(dequant[0], ff_mjpeg_std_luminance_quant_tbl, q);
+ calc_dequant(dequant[1], ff_mjpeg_std_chrominance_quant_tbl, q);
+
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ frame->key_frame = 1;
+ frame->pict_type = AV_PICTURE_TYPE_I;
+
+ av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size, avpkt->size - 8);
+ if (!s->bitstream_buf)
+ return AVERROR(ENOMEM);
+
+ size = 0;
+ for (int i = 8; i < avpkt->size; i++) {
+ int src = buf[i] ^ 0x80;
+ s->bitstream_buf[size++] = src;
+ if (src == 0xFF && i + 1 < avpkt->size && (buf[i + 1] ^ 0x80) == 0x00)
+ i++;
+ }
+
+ init_get_bits8(&gb, s->bitstream_buf, size);
+
+ if (yuv20p_half) {
+ for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
+ for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
+ for (int b = 0; b < 4; b++) {
+ const VLCElem * dc_vlc = b < 2 ? luma_dc_vlc.table : chroma_dc_vlc.table;
+ int dc_bits = b < 2 ? LUMA_DC_BITS : CHROMA_DC_BITS;
+ const VLCElem * ac_vlc = b < 2 ? luma_ac_vlc.table : chroma_ac_vlc.table;
+ int ac_bits = b < 2 ? LUMA_AC_BITS : CHROMA_AC_BITS;
+ int plane = b < 2 ? 0 : b - 1;
+ int x, y;
+
+ if (b < 2) {
+ y = 16*mb_y + 8*(b >> 1);
+ x = 16*mb_x + 8*(b & 1);
+ } else {
+ y = 8*mb_y;
+ x = 8*mb_x;
+ }
+
+ ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
+ dc_pred + plane, dequant[!(b < 4)],
+ frame->data[plane] + y*frame->linesize[plane] + x,
+ (b < 2 ? 2 : 1) * frame->linesize[plane]);
+ if (ret < 0)
+ return ret;
+
+ if (b < 2)
+ copy_block8(frame->data[plane] + (y + 1)*frame->linesize[plane] + x,
+ frame->data[plane] + y*frame->linesize[plane] + x,
+ 2*frame->linesize[plane], 2*frame->linesize[plane], 8);
+ }
+ } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
+ for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
+ for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
+ for (int b = 0; b < 6; b++) {
+ const VLCElem * dc_vlc = b < 4 ? luma_dc_vlc.table : chroma_dc_vlc.table;
+ int dc_bits = b < 4 ? LUMA_DC_BITS : CHROMA_DC_BITS;
+ const VLCElem * ac_vlc = b < 4 ? luma_ac_vlc.table : chroma_ac_vlc.table;
+ int ac_bits = b < 4 ? LUMA_AC_BITS : CHROMA_AC_BITS;
+ int plane = b < 4 ? 0 : b - 3;
+ int x, y;
+
+ if (b < 4) {
+ y = 16*mb_y + 8*(b>>1);
+ x = 16*mb_x + 8*(b&1);
+ } else {
+ y = 8*mb_y;
+ x = 8*mb_x;
+ }
+
+ ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
+ dc_pred + plane, dequant[!(b < 4)],
+ frame->data[plane] + y*frame->linesize[plane] + x,
+ frame->linesize[plane]);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+ for (int f = 0; f < fields; f++)
+ for (int j = 0; j < avctx->height / fields / 8; j++)
+ for (int i = 0; i < avctx->width / 8; i++)
+ for (int plane = 0; plane < 3; plane++) {
+ const VLCElem * dc_vlc = !plane ? luma_dc_vlc.table : chroma_dc_vlc.table;
+ int dc_bits = !plane ? LUMA_DC_BITS : CHROMA_DC_BITS;
+ const VLCElem * ac_vlc = !plane ? luma_ac_vlc.table : chroma_ac_vlc.table;
+ int ac_bits = !plane ? LUMA_AC_BITS : CHROMA_AC_BITS;
+
+ ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
+ dc_pred + plane, dequant[!!plane],
+ frame->data[plane] + (f + 8*j*fields)*frame->linesize[plane] + 8*i,
+ fields * frame->linesize[plane]);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ *got_frame = 1;
+
+ return avpkt->size;
+}
+
+static av_cold int lead_decode_end(AVCodecContext * avctx)
+{
+ LeadContext *s = avctx->priv_data;
+
+ av_freep(&s->bitstream_buf);
+
+ return 0;
+}
+
+const FFCodec ff_lead_decoder = {
+ .p.name = "lead",
+ CODEC_LONG_NAME("LEAD MCMP"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_LEAD,
+ .priv_data_size = sizeof(LeadContext),
+ .init = lead_decode_init,
+ .close = lead_decode_end,
+ FF_CODEC_DECODE_CB(lead_decode_frame),
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 7319406b39..8401ae3668 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_LEAD, MKTAG('L', 'E', 'A', 'D') },
{ AV_CODEC_ID_NONE, 0 }
};
--
2.35.1
-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder
2022-11-12 0:39 [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder Peter Ross
@ 2022-11-12 15:33 ` James Almer
2022-11-12 16:42 ` Michael Niedermayer
1 sibling, 0 replies; 3+ messages in thread
From: James Almer @ 2022-11-12 15:33 UTC (permalink / raw)
To: ffmpeg-devel
On 11/11/2022 9:39 PM, Peter Ross wrote:
> +static int lead_decode_frame(AVCodecContext *avctx, AVFrame * frame,
> + int * got_frame, AVPacket * avpkt)
> +{
> + LeadContext *s = avctx->priv_data;
> + const uint8_t * buf = avpkt->data;
> + int ret, format, yuv20p_half = 0, fields = 1, q, size;
> + GetBitContext gb;
> + int16_t dc_pred[3] = {0, 0, 0};
> + uint16_t dequant[2][64];
> +
> + if (avpkt->size < 8)
> + return AVERROR_INVALIDDATA;
> +
> + format = AV_RL16(buf + 4);
> + switch(format) {
> + case 0x1000:
> + avctx->pix_fmt = AV_PIX_FMT_YUV420P;
> + break;
> + case 0x2000:
> + avctx->pix_fmt = AV_PIX_FMT_YUV444P;
> + break;
> + case 0x2006:
> + avctx->pix_fmt = AV_PIX_FMT_YUV444P;
> + fields = 2;
> + break;
> + case 0x8000:
> + avctx->pix_fmt = AV_PIX_FMT_YUV420P;
> + yuv20p_half = 1;
nit: maybe do
switch(format) {
case 0x8000:
yuv20p_half = 1;
// fall-through
case 0x1000:
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
break;
> + break;
> + default:
> + avpriv_request_sample(avctx, "unsupported format 0x%x", format);
> + return AVERROR_PATCHWELCOME;
> + }
> +
> + q = AV_RL16(buf + 6);
> + calc_dequant(dequant[0], ff_mjpeg_std_luminance_quant_tbl, q);
> + calc_dequant(dequant[1], ff_mjpeg_std_chrominance_quant_tbl, q);
> +
> + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> + return ret;
> +
> + frame->key_frame = 1;
> + frame->pict_type = AV_PICTURE_TYPE_I;
Shouldn't the codec have the prop AV_CODEC_PROP_INTRA_ONLY then? Or do
some formats not yet supported have inter frames?
[...]
> + if (yuv20p_half) {
> + for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
> + for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
> + for (int b = 0; b < 4; b++) {
> + const VLCElem * dc_vlc = b < 2 ? luma_dc_vlc.table : chroma_dc_vlc.table;
> + int dc_bits = b < 2 ? LUMA_DC_BITS : CHROMA_DC_BITS;
> + const VLCElem * ac_vlc = b < 2 ? luma_ac_vlc.table : chroma_ac_vlc.table;
> + int ac_bits = b < 2 ? LUMA_AC_BITS : CHROMA_AC_BITS;
> + int plane = b < 2 ? 0 : b - 1;
> + int x, y;
> +
> + if (b < 2) {
> + y = 16*mb_y + 8*(b >> 1);
> + x = 16*mb_x + 8*(b & 1);
> + } else {
> + y = 8*mb_y;
> + x = 8*mb_x;
> + }
> +
> + ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
> + dc_pred + plane, dequant[!(b < 4)],
> + frame->data[plane] + y*frame->linesize[plane] + x,
> + (b < 2 ? 2 : 1) * frame->linesize[plane]);
> + if (ret < 0)
> + return ret;
> +
> + if (b < 2)
> + copy_block8(frame->data[plane] + (y + 1)*frame->linesize[plane] + x,
> + frame->data[plane] + y*frame->linesize[plane] + x,
> + 2*frame->linesize[plane], 2*frame->linesize[plane], 8);
> + }
> + } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
> + for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
> + for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
> + for (int b = 0; b < 6; b++) {
> + const VLCElem * dc_vlc = b < 4 ? luma_dc_vlc.table : chroma_dc_vlc.table;
> + int dc_bits = b < 4 ? LUMA_DC_BITS : CHROMA_DC_BITS;
> + const VLCElem * ac_vlc = b < 4 ? luma_ac_vlc.table : chroma_ac_vlc.table;
> + int ac_bits = b < 4 ? LUMA_AC_BITS : CHROMA_AC_BITS;
> + int plane = b < 4 ? 0 : b - 3;
> + int x, y;
> +
> + if (b < 4) {
> + y = 16*mb_y + 8*(b>>1);
> + x = 16*mb_x + 8*(b&1);
> + } else {
> + y = 8*mb_y;
> + x = 8*mb_x;
> + }
> +
> + ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
> + dc_pred + plane, dequant[!(b < 4)],
> + frame->data[plane] + y*frame->linesize[plane] + x,
> + frame->linesize[plane]);
> + if (ret < 0)
> + return ret;
> + }
You should be able to combine these two blocks, doing things like b < (4
>> yuv20p_half), b - (3 >> yuv20p_half) and such.
_______________________________________________
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".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder
2022-11-12 0:39 [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder Peter Ross
2022-11-12 15:33 ` James Almer
@ 2022-11-12 16:42 ` Michael Niedermayer
1 sibling, 0 replies; 3+ messages in thread
From: Michael Niedermayer @ 2022-11-12 16:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2681 bytes --]
On Sat, Nov 12, 2022 at 11:39:19AM +1100, Peter Ross wrote:
> Partially fixes ticket #798
> ---
>
> sample: https://trac.ffmpeg.org/raw-attachment/ticket/798/DaDa_CMP.avi
[...]
> +static av_cold int lead_decode_init(AVCodecContext * avctx)
> +{
> + static AVOnce init_static_once = AV_ONCE_INIT;
> + LeadContext *s = avctx->priv_data;
> +
> + if (avctx->extradata_size < 20)
> + return AVERROR_INVALIDDATA;
> +
> + ff_idctdsp_init(&s->idsp, avctx);
> + ff_permute_scantable(s->permutated_scantable, ff_zigzag_direct, s->idsp.idct_permutation);
> +
> + ff_thread_once(&init_static_once, lead_init_static_data);
> +
> + return 0;
> +}
> +
> +static void calc_dequant(uint16_t * dequant, const uint8_t * quant_tbl, int q)
> +{
> + for (int i = 0; i < 64; i++)
> + dequant[i] = av_clip(q * quant_tbl[ff_zigzag_direct[i]] / 50, 2, 32767);
> +}
> +
> +static int decode_block(LeadContext * s, GetBitContext * gb,
> + const VLCElem * dc_table, int dc_bits, const VLCElem * ac_table, int ac_bits,
> + int16_t * dc_pred, const uint16_t * dequant,
> + uint8_t * dst, int stride)
> +{
> + int16_t block[64];
> + int size;
> +
> + memset(block, 0, sizeof(block));
clear_block()
> +
> + size = get_vlc2(gb, dc_table, dc_bits, 1);
> + if (size < 0)
> + return AVERROR_INVALIDDATA;
> +
> + if (size)
> + *dc_pred += get_xbits(gb, size);
> +
> + block[0] = (1 << 10) + *dc_pred * dequant[0];
> +
> + for (int i = 1; i < 64; i++) {
> + int symbol = get_vlc2(gb, ac_table, ac_bits, 2);
> + if (size < 0)
i think you want to check symbol here
also if you want you could probably map the unused vlcs to things causing the i>=64 check to fail later
to avoid a 2nd check but its probably not worth the work for this codec
> + return AVERROR_INVALIDDATA;
> +
> + if (!symbol)
> + break;
> +
> + i += symbol >> 4;
> + if (i >= 64)
> + return AVERROR_INVALIDDATA;
> +
> + size = symbol & 0xF;
> + if (size)
> + block[s->permutated_scantable[i]] = get_xbits(gb, size) * dequant[i];
> + }
> +
> + s->idsp.idct_put(dst, stride, block);
void (*idct_put)(uint8_t *dest /* align 8 */,
ptrdiff_t line_size, int16_t *block /* align 16 */);
block needs to be aligned to 16 bytes
[...]
thx
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Never trust a computer, one day, it may think you are the virus. -- Compn
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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".
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-11-12 16:42 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-12 0:39 [FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder Peter Ross
2022-11-12 15:33 ` James Almer
2022-11-12 16:42 ` Michael Niedermayer
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