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 @@
1Entries are sorted chronologically from oldest to youngest within each release,1Entries are sorted chronologically from oldest to youngest within each release,
2releases are sorted from youngest to oldest.2releases are sorted from youngest to oldest.
3 3
4version <next>:
5- LEAD MCMP decoder
6
4version 6.1:7version 6.1:
5- libaribcaption decoder8- libaribcaption decoder
6- Playdate video decoder and demuxer9- Playdate video decoder and demuxer
configure+1−0
@@ -2887,6 +2887,7 @@ ipu_decoder_select="mpegvideodec" · 2886 unmodified lines
2887jpegls_decoder_select="mjpeg_decoder"2887jpegls_decoder_select="mjpeg_decoder"
2888jv_decoder_select="blockdsp"2888jv_decoder_select="blockdsp"
2889lagarith_decoder_select="llviddsp"2889lagarith_decoder_select="llviddsp"
2890lead_decoder_select="idctdsp jpegtables"
2890ljpeg_encoder_select="jpegtables"2891ljpeg_encoder_select="jpegtables"
2891lscr_decoder_select="inflate_wrapper"2892lscr_decoder_select="inflate_wrapper"
2892magicyuv_decoder_select="llviddsp"2893magicyuv_decoder_select="llviddsp"
doc/general_contents.texi+1−0
@@ -997,6 +997,7 @@ following image formats are supported: · 996 unmodified lines
997@item Lagarith @tab @tab X997@item Lagarith @tab @tab X
998@item LCL (LossLess Codec Library) MSZH @tab @tab X998@item LCL (LossLess Codec Library) MSZH @tab @tab X
999@item LCL (LossLess Codec Library) ZLIB @tab E @tab E999@item LCL (LossLess Codec Library) ZLIB @tab E @tab E
1000@item LEAD MCMP @tab @tab X
1000@item LOCO @tab @tab X1001@item LOCO @tab @tab X
1001@item LucasArts SANM/Smush @tab @tab X1002@item LucasArts SANM/Smush @tab @tab X
1002 @tab Used in LucasArts games / SMUSH animations.1003 @tab Used in LucasArts games / SMUSH animations.
libavcodec/Makefile+1−0
@@ -479,6 +479,7 @@ OBJS-$(CONFIG_JV_DECODER) += jvdec.o · 478 unmodified lines
479OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o479OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
480OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o480OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
481OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o481OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
482OBJS-$(CONFIG_LEAD_DECODER) += leaddec.o jpegquanttables.o
482OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o483OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o
483OBJS-$(CONFIG_LOCO_DECODER) += loco.o484OBJS-$(CONFIG_LOCO_DECODER) += loco.o
484OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o485OBJS-$(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
188extern const FFCodec ff_kgv1_decoder;188extern const FFCodec ff_kgv1_decoder;
189extern const FFCodec ff_kmvc_decoder;189extern const FFCodec ff_kmvc_decoder;
190extern const FFCodec ff_lagarith_decoder;190extern const FFCodec ff_lagarith_decoder;
191extern const FFCodec ff_lead_decoder;
191extern const FFCodec ff_ljpeg_encoder;192extern const FFCodec ff_ljpeg_encoder;
192extern const FFCodec ff_loco_decoder;193extern const FFCodec ff_loco_decoder;
193extern const FFCodec ff_lscr_decoder;194extern const FFCodec ff_lscr_decoder;
libavcodec/codec_desc.c+7−0
@@ -1960,6 +1960,13 @@ static const AVCodecDescriptor codec_descriptors[] = { · 1959 unmodified lines
1960 .long_name = NULL_IF_CONFIG_SMALL("vMix Video"),1960 .long_name = NULL_IF_CONFIG_SMALL("vMix Video"),
1961 .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,1961 .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
1962 },1962 },
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 },
1963 1970
1964 /* various PCM "codecs" */1971 /* various PCM "codecs" */
1965 {1972 {
libavcodec/codec_id.h+1−0
@@ -324,6 +324,7 @@ enum AVCodecID { · 323 unmodified lines
324 AV_CODEC_ID_EVC,324 AV_CODEC_ID_EVC,
325 AV_CODEC_ID_RTV1,325 AV_CODEC_ID_RTV1,
326 AV_CODEC_ID_VMIX,326 AV_CODEC_ID_VMIX,
327 AV_CODEC_ID_LEAD,
327 328
328 /* various PCM "codecs" */329 /* various PCM "codecs" */
329 AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs330 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
26static const uint8_t luma_dc_len[]={
27 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9
28};
29
30static const uint8_t chroma_dc_len[]={
31 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
32};
33
34static 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
48static 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
41static VLC luma_dc_vlc;
42static VLC chroma_dc_vlc;
43static VLC luma_ac_vlc;
44static VLC chroma_ac_vlc;
45
46static 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
66typedef 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
74static 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
91static 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
97static 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
137static 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
250static 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
259const 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
29 29
30#include "version_major.h"30#include "version_major.h"
31 31
32#define LIBAVCODEC_VERSION_MINOR 3232#define LIBAVCODEC_VERSION_MINOR 33
33#define LIBAVCODEC_VERSION_MICRO 10233#define LIBAVCODEC_VERSION_MICRO 100
34 34
35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
36 LIBAVCODEC_VERSION_MINOR, \36 LIBAVCODEC_VERSION_MINOR, \
libavformat/riff.c+1−0
@@ -505,6 +505,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { · 504 unmodified lines
505 { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') },505 { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') },
506 { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') },506 { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') },
507 { AV_CODEC_ID_VMIX, MKTAG('V', 'M', 'X', '1') },507 { AV_CODEC_ID_VMIX, MKTAG('V', 'M', 'X', '1') },
508 { AV_CODEC_ID_LEAD, MKTAG('L', 'E', 'A', 'D') },
508 { AV_CODEC_ID_NONE, 0 }509 { AV_CODEC_ID_NONE, 0 }
509};510};
510 511

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