History

avcodec: LEAD MCMP decoder

Partially fixes ticket #798

Peter Ross committed 4 years ago

Commit 10869cd1 parent f084e9b11 files · +350 −2Browse files

Unified · Split

11 files
  1. Changelog +3 −0
  2. configure +1 −0
  3. doc/general_contents.texi +1 −0
  4. libavcodec/Makefile +1 −0
  5. libavcodec/allcodecs.c +1 −0
  6. libavcodec/codec_desc.c +7 −0
  7. libavcodec/codec_id.h +1 −0
  8. libavcodec/leaddata.h +62 −0
  9. libavcodec/leaddec.c +270 −0
  10. libavcodec/version.h +2 −2
  11. libavformat/riff.c +1 −0
Changelog+3−0
@@ -1,6 +1,9 @@
11 Entries are sorted chronologically from oldest to youngest within each release,
22 releases are sorted from youngest to oldest.
33
4+version <next>:
5+- LEAD MCMP decoder
6+
47 version 6.1:
58 - libaribcaption decoder
69 - Playdate video decoder and demuxer
configure+1−0
@@ -2887,6 +2887,7 @@ ipu_decoder_select="mpegvideodec" · 2886 unmodified lines
28872887 jpegls_decoder_select="mjpeg_decoder"
28882888 jv_decoder_select="blockdsp"
28892889 lagarith_decoder_select="llviddsp"
2890+lead_decoder_select="idctdsp jpegtables"
28902891 ljpeg_encoder_select="jpegtables"
28912892 lscr_decoder_select="inflate_wrapper"
28922893 magicyuv_decoder_select="llviddsp"
doc/general_contents.texi+1−0
@@ -997,6 +997,7 @@ following image formats are supported: · 996 unmodified lines
997997 @item Lagarith @tab @tab X
998998 @item LCL (LossLess Codec Library) MSZH @tab @tab X
999999 @item LCL (LossLess Codec Library) ZLIB @tab E @tab E
1000+@item LEAD MCMP @tab @tab X
10001001 @item LOCO @tab @tab X
10011002 @item LucasArts SANM/Smush @tab @tab X
10021003 @tab Used in LucasArts games / SMUSH animations.
libavcodec/Makefile+1−0
@@ -479,6 +479,7 @@ OBJS-$(CONFIG_JV_DECODER) += jvdec.o · 478 unmodified lines
479479 OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
480480 OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
481481 OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
482+OBJS-$(CONFIG_LEAD_DECODER) += leaddec.o jpegquanttables.o
482483 OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o
483484 OBJS-$(CONFIG_LOCO_DECODER) += loco.o
484485 OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o
libavcodec/allcodecs.c+1−0
@@ -188,6 +188,7 @@ extern const FFCodec ff_jv_decoder; · 187 unmodified lines
188188 extern const FFCodec ff_kgv1_decoder;
189189 extern const FFCodec ff_kmvc_decoder;
190190 extern const FFCodec ff_lagarith_decoder;
191+extern const FFCodec ff_lead_decoder;
191192 extern const FFCodec ff_ljpeg_encoder;
192193 extern const FFCodec ff_loco_decoder;
193194 extern const FFCodec ff_lscr_decoder;
libavcodec/codec_desc.c+7−0
@@ -1960,6 +1960,13 @@ static const AVCodecDescriptor codec_descriptors[] = { · 1959 unmodified lines
19601960 .long_name = NULL_IF_CONFIG_SMALL("vMix Video"),
19611961 .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
19621962 },
1963+ {
1964+ .id = AV_CODEC_ID_LEAD,
1965+ .type = AVMEDIA_TYPE_VIDEO,
1966+ .name = "lead",
1967+ .long_name = NULL_IF_CONFIG_SMALL("LEAD MCMP"),
1968+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
1969+ },
19631970
19641971 /* various PCM "codecs" */
19651972 {
libavcodec/codec_id.h+1−0
@@ -324,6 +324,7 @@ enum AVCodecID { · 323 unmodified lines
324324 AV_CODEC_ID_EVC,
325325 AV_CODEC_ID_RTV1,
326326 AV_CODEC_ID_VMIX,
327+ AV_CODEC_ID_LEAD,
327328
328329 /* various PCM "codecs" */
329330 AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
libavcodec/leaddata.h+62−0
@@ -0,0 +1,62 @@
1+/*
2+ * LEAD MCMP decoder tables
3+ *
4+ * This file is part of FFmpeg.
5+ *
6+ * FFmpeg is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU Lesser General Public
8+ * License as published by the Free Software Foundation; either
9+ * version 2.1 of the License, or (at your option) any later version.
10+ *
11+ * FFmpeg is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+ * Lesser General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU Lesser General Public
17+ * License along with FFmpeg; if not, write to the Free Software
18+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+#ifndef AVCODEC_LEADDATA_H
22+#define AVCODEC_LEADDATA_H
23+
24+#include <stdint.h>
25+
26+static const uint8_t luma_dc_len[]={
27+ 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9
28+};
29+
30+static const uint8_t chroma_dc_len[]={
31+ 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
32+};
33+
34+static const uint8_t luma_ac_len[]={
35+ 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8,
36+ 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11,
37+ 12, 12, 12, 12, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
38+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
39+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
40+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
41+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
42+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
43+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
44+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
45+ 16, 16
46+};
47+
48+static const uint8_t chroma_ac_len[]={
49+ 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
50+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
51+ 11, 11, 11, 11, 12, 12, 12, 12, 14, 15, 15, 16, 16, 16, 16, 16,
52+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
53+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
54+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
55+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
56+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
57+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
58+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
59+ 16, 16
60+};
61+
62+#endif /* AVCODEC_LEADDATA_H */
libavcodec/leaddec.c+270−0
@@ -0,0 +1,270 @@
1+/*
2+ * LEAD MCMP decoder
3+ *
4+ * Copyright (c) 2023 Peter Ross
5+ *
6+ * This file is part of FFmpeg.
7+ *
8+ * FFmpeg is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU Lesser General Public
10+ * License as published by the Free Software Foundation; either
11+ * version 2.1 of the License, or (at your option) any later version.
12+ *
13+ * FFmpeg is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+ * Lesser General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU Lesser General Public
19+ * License along with FFmpeg; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+ */
22+
23+#include "avcodec.h"
24+#include "blockdsp.h"
25+#include "codec_internal.h"
26+#include "copy_block.h"
27+#include "decode.h"
28+#include "get_bits.h"
29+#include "idctdsp.h"
30+#include "jpegquanttables.h"
31+#include "jpegtables.h"
32+#include "leaddata.h"
33+#include "libavutil/mem_internal.h"
34+#include "libavutil/thread.h"
35+
36+#define LUMA_DC_BITS 9
37+#define CHROMA_DC_BITS 11
38+#define LUMA_AC_BITS 10
39+#define CHROMA_AC_BITS 10
40+
41+static VLC luma_dc_vlc;
42+static VLC chroma_dc_vlc;
43+static VLC luma_ac_vlc;
44+static VLC chroma_ac_vlc;
45+
46+static av_cold void lead_init_static_data(void)
47+{
48+ VLC_INIT_STATIC_FROM_LENGTHS(&luma_dc_vlc, LUMA_DC_BITS, FF_ARRAY_ELEMS(luma_dc_len),
49+ luma_dc_len, 1,
50+ 0, 0, 0,
51+ 0, 0, 1 << LUMA_DC_BITS);
52+ VLC_INIT_STATIC_FROM_LENGTHS(&chroma_dc_vlc, CHROMA_DC_BITS, FF_ARRAY_ELEMS(chroma_dc_len),
53+ chroma_dc_len, 1,
54+ 0, 0, 0,
55+ 0, 0, 1 << CHROMA_DC_BITS);
56+ VLC_INIT_STATIC_FROM_LENGTHS(&luma_ac_vlc, LUMA_AC_BITS, FF_ARRAY_ELEMS(luma_ac_len),
57+ luma_ac_len, 1,
58+ ff_mjpeg_val_ac_luminance, 1, 1,
59+ 0, 0, 1160);
60+ VLC_INIT_STATIC_FROM_LENGTHS(&chroma_ac_vlc, CHROMA_AC_BITS, FF_ARRAY_ELEMS(chroma_ac_len),
61+ chroma_ac_len, 1,
62+ ff_mjpeg_val_ac_chrominance, 1, 1,
63+ 0, 0, 1160);
64+}
65+
66+typedef struct LeadContext {
67+ uint8_t *bitstream_buf;
68+ unsigned int bitstream_buf_size;
69+ BlockDSPContext bdsp;
70+ IDCTDSPContext idsp;
71+ uint8_t permutated_scantable[64];
72+} LeadContext;
73+
74+static av_cold int lead_decode_init(AVCodecContext * avctx)
75+{
76+ static AVOnce init_static_once = AV_ONCE_INIT;
77+ LeadContext *s = avctx->priv_data;
78+
79+ if (avctx->extradata_size < 20)
80+ return AVERROR_INVALIDDATA;
81+
82+ ff_blockdsp_init(&s->bdsp);
83+ ff_idctdsp_init(&s->idsp, avctx);
84+ ff_permute_scantable(s->permutated_scantable, ff_zigzag_direct, s->idsp.idct_permutation);
85+
86+ ff_thread_once(&init_static_once, lead_init_static_data);
87+
88+ return 0;
89+}
90+
91+static void calc_dequant(uint16_t * dequant, const uint8_t * quant_tbl, int q)
92+{
93+ for (int i = 0; i < 64; i++)
94+ dequant[i] = av_clip(q * quant_tbl[ff_zigzag_direct[i]] / 50, 2, 32767);
95+}
96+
97+static int decode_block(LeadContext * s, GetBitContext * gb,
98+ const VLCElem * dc_table, int dc_bits, const VLCElem * ac_table, int ac_bits,
99+ int16_t * dc_pred, const uint16_t * dequant,
100+ uint8_t * dst, int stride)
101+{
102+ DECLARE_ALIGNED(32, int16_t, block)[64];
103+ int size;
104+
105+ s->bdsp.clear_block(block);
106+
107+ size = get_vlc2(gb, dc_table, dc_bits, 1);
108+ if (size < 0)
109+ return AVERROR_INVALIDDATA;
110+
111+ if (size)
112+ *dc_pred += get_xbits(gb, size);
113+
114+ block[0] = (1 << 10) + *dc_pred * dequant[0];
115+
116+ for (int i = 1; i < 64; i++) {
117+ int symbol = get_vlc2(gb, ac_table, ac_bits, 2);
118+ if (symbol < 0)
119+ return AVERROR_INVALIDDATA;
120+
121+ if (!symbol)
122+ break;
123+
124+ i += symbol >> 4;
125+ if (i >= 64)
126+ return AVERROR_INVALIDDATA;
127+
128+ size = symbol & 0xF;
129+ if (size)
130+ block[s->permutated_scantable[i]] = get_xbits(gb, size) * dequant[i];
131+ }
132+
133+ s->idsp.idct_put(dst, stride, block);
134+ return 0;
135+}
136+
137+static int lead_decode_frame(AVCodecContext *avctx, AVFrame * frame,
138+ int * got_frame, AVPacket * avpkt)
139+{
140+ LeadContext *s = avctx->priv_data;
141+ const uint8_t * buf = avpkt->data;
142+ int ret, format, yuv20p_half = 0, fields = 1, q, size;
143+ GetBitContext gb;
144+ int16_t dc_pred[3] = {0, 0, 0};
145+ uint16_t dequant[2][64];
146+
147+ if (avpkt->size < 8)
148+ return AVERROR_INVALIDDATA;
149+
150+ format = AV_RL16(buf + 4);
151+ switch(format) {
152+ case 0x8000:
153+ yuv20p_half = 1;
154+ // fall-through
155+ case 0x1000:
156+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
157+ break;
158+ case 0x2000:
159+ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
160+ break;
161+ case 0x2006:
162+ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
163+ fields = 2;
164+ break;
165+ default:
166+ avpriv_request_sample(avctx, "unsupported format 0x%x", format);
167+ return AVERROR_PATCHWELCOME;
168+ }
169+
170+ q = AV_RL16(buf + 6);
171+ calc_dequant(dequant[0], ff_mjpeg_std_luminance_quant_tbl, q);
172+ calc_dequant(dequant[1], ff_mjpeg_std_chrominance_quant_tbl, q);
173+
174+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
175+ return ret;
176+
177+ frame->flags |= AV_FRAME_FLAG_KEY;
178+ frame->pict_type = AV_PICTURE_TYPE_I;
179+
180+ av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size, avpkt->size - 8);
181+ if (!s->bitstream_buf)
182+ return AVERROR(ENOMEM);
183+
184+ size = 0;
185+ for (int i = 8; i < avpkt->size; i++) {
186+ int src = buf[i] ^ 0x80;
187+ s->bitstream_buf[size++] = src;
188+ if (src == 0xFF && i + 1 < avpkt->size && (buf[i + 1] ^ 0x80) == 0x00)
189+ i++;
190+ }
191+
192+ init_get_bits8(&gb, s->bitstream_buf, size);
193+
194+ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
195+ for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
196+ for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
197+ for (int b = 0; b < (yuv20p_half ? 4 : 6); b++) {
198+ int luma_block = yuv20p_half ? 2 : 4;
199+ const VLCElem * dc_vlc = b < luma_block ? luma_dc_vlc.table : chroma_dc_vlc.table;
200+ int dc_bits = b < luma_block ? LUMA_DC_BITS : CHROMA_DC_BITS;
201+ const VLCElem * ac_vlc = b < luma_block ? luma_ac_vlc.table : chroma_ac_vlc.table;
202+ int ac_bits = b < luma_block ? LUMA_AC_BITS : CHROMA_AC_BITS;
203+ int plane = b < luma_block ? 0 : b - (yuv20p_half ? 1 : 3);
204+ int x, y;
205+
206+ if (b < luma_block) {
207+ y = 16*mb_y + 8*(b >> 1);
208+ x = 16*mb_x + 8*(b & 1);
209+ } else {
210+ y = 8*mb_y;
211+ x = 8*mb_x;
212+ }
213+
214+ ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
215+ dc_pred + plane, dequant[!(b < 4)],
216+ frame->data[plane] + y*frame->linesize[plane] + x,
217+ (yuv20p_half && b < 2 ? 2 : 1) * frame->linesize[plane]);
218+ if (ret < 0)
219+ return ret;
220+
221+ if (yuv20p_half && b < 2)
222+ copy_block8(frame->data[plane] + (y + 1)*frame->linesize[plane] + x,
223+ frame->data[plane] + y*frame->linesize[plane] + x,
224+ 2*frame->linesize[plane], 2*frame->linesize[plane], 8);
225+ }
226+ } else {
227+ for (int f = 0; f < fields; f++)
228+ for (int j = 0; j < avctx->height / fields / 8; j++)
229+ for (int i = 0; i < avctx->width / 8; i++)
230+ for (int plane = 0; plane < 3; plane++) {
231+ const VLCElem * dc_vlc = !plane ? luma_dc_vlc.table : chroma_dc_vlc.table;
232+ int dc_bits = !plane ? LUMA_DC_BITS : CHROMA_DC_BITS;
233+ const VLCElem * ac_vlc = !plane ? luma_ac_vlc.table : chroma_ac_vlc.table;
234+ int ac_bits = !plane ? LUMA_AC_BITS : CHROMA_AC_BITS;
235+
236+ ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
237+ dc_pred + plane, dequant[!!plane],
238+ frame->data[plane] + (f + 8*j*fields)*frame->linesize[plane] + 8*i,
239+ fields * frame->linesize[plane]);
240+ if (ret < 0)
241+ return ret;
242+ }
243+ }
244+
245+ *got_frame = 1;
246+
247+ return avpkt->size;
248+}
249+
250+static av_cold int lead_decode_end(AVCodecContext * avctx)
251+{
252+ LeadContext *s = avctx->priv_data;
253+
254+ av_freep(&s->bitstream_buf);
255+
256+ return 0;
257+}
258+
259+const FFCodec ff_lead_decoder = {
260+ .p.name = "lead",
261+ CODEC_LONG_NAME("LEAD MCMP"),
262+ .p.type = AVMEDIA_TYPE_VIDEO,
263+ .p.id = AV_CODEC_ID_LEAD,
264+ .priv_data_size = sizeof(LeadContext),
265+ .init = lead_decode_init,
266+ .close = lead_decode_end,
267+ FF_CODEC_DECODE_CB(lead_decode_frame),
268+ .p.capabilities = AV_CODEC_CAP_DR1,
269+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
270+};
libavcodec/version.h+2−2
@@ -29,8 +29,8 @@ · 28 unmodified lines
2929
3030 #include "version_major.h"
3131
32−#define LIBAVCODEC_VERSION_MINOR 32
33−#define LIBAVCODEC_VERSION_MICRO 102
32+#define LIBAVCODEC_VERSION_MINOR 33
33+#define LIBAVCODEC_VERSION_MICRO 100
3434
3535 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
3636 LIBAVCODEC_VERSION_MINOR, \
libavformat/riff.c+1−0
@@ -505,6 +505,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { · 504 unmodified lines
505505 { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') },
506506 { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') },
507507 { AV_CODEC_ID_VMIX, MKTAG('V', 'M', 'X', '1') },
508+ { AV_CODEC_ID_LEAD, MKTAG('L', 'E', 'A', 'D') },
508509 { AV_CODEC_ID_NONE, 0 }
509510 };
510511

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t