Line | Branch | Exec | Source |
---|---|---|---|
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.h" | ||
34 | #include "libavutil/mem_internal.h" | ||
35 | #include "libavutil/thread.h" | ||
36 | |||
37 | #define LUMA_DC_BITS 9 | ||
38 | #define CHROMA_DC_BITS 11 | ||
39 | #define LUMA_AC_BITS 10 | ||
40 | #define CHROMA_AC_BITS 10 | ||
41 | |||
42 | static VLCElem luma_dc_vlc[1 << LUMA_DC_BITS]; | ||
43 | static VLCElem chroma_dc_vlc[1 << CHROMA_DC_BITS]; | ||
44 | static VLCElem luma_ac_vlc[1160]; | ||
45 | static VLCElem chroma_ac_vlc[1160]; | ||
46 | |||
47 | 4 | static av_cold void lead_init_static_data(void) | |
48 | { | ||
49 | 4 | VLC_INIT_STATIC_TABLE_FROM_LENGTHS(luma_dc_vlc, LUMA_DC_BITS, FF_ARRAY_ELEMS(luma_dc_len), | |
50 | luma_dc_len, 1, | ||
51 | NULL, 0, 0, | ||
52 | 0, 0); | ||
53 | 4 | VLC_INIT_STATIC_TABLE_FROM_LENGTHS(chroma_dc_vlc, CHROMA_DC_BITS, FF_ARRAY_ELEMS(chroma_dc_len), | |
54 | chroma_dc_len, 1, | ||
55 | NULL, 0, 0, | ||
56 | 0, 0); | ||
57 | 4 | VLC_INIT_STATIC_TABLE_FROM_LENGTHS(luma_ac_vlc, LUMA_AC_BITS, FF_ARRAY_ELEMS(luma_ac_len), | |
58 | luma_ac_len, 1, | ||
59 | ff_mjpeg_val_ac_luminance, 1, 1, | ||
60 | 0, 0); | ||
61 | 4 | VLC_INIT_STATIC_TABLE_FROM_LENGTHS(chroma_ac_vlc, CHROMA_AC_BITS, FF_ARRAY_ELEMS(chroma_ac_len), | |
62 | chroma_ac_len, 1, | ||
63 | ff_mjpeg_val_ac_chrominance, 1, 1, | ||
64 | 0, 0); | ||
65 | 4 | } | |
66 | |||
67 | typedef struct LeadContext { | ||
68 | uint8_t *bitstream_buf; | ||
69 | unsigned int bitstream_buf_size; | ||
70 | BlockDSPContext bdsp; | ||
71 | IDCTDSPContext idsp; | ||
72 | uint8_t permutated_scantable[64]; | ||
73 | } LeadContext; | ||
74 | |||
75 | 8 | static av_cold int lead_decode_init(AVCodecContext * avctx) | |
76 | { | ||
77 | static AVOnce init_static_once = AV_ONCE_INIT; | ||
78 | 8 | LeadContext *s = avctx->priv_data; | |
79 | |||
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (avctx->extradata_size < 20) |
81 | ✗ | return AVERROR_INVALIDDATA; | |
82 | |||
83 | 8 | ff_blockdsp_init(&s->bdsp); | |
84 | 8 | ff_idctdsp_init(&s->idsp, avctx); | |
85 | 8 | ff_permute_scantable(s->permutated_scantable, ff_zigzag_direct, s->idsp.idct_permutation); | |
86 | |||
87 | 8 | ff_thread_once(&init_static_once, lead_init_static_data); | |
88 | |||
89 | 8 | return 0; | |
90 | } | ||
91 | |||
92 | 16 | static void calc_dequant(uint16_t * dequant, const uint8_t * quant_tbl, int q) | |
93 | { | ||
94 |
2/2✓ Branch 0 taken 1024 times.
✓ Branch 1 taken 16 times.
|
1040 | for (int i = 0; i < 64; i++) |
95 | 1024 | dequant[i] = av_clip(q * quant_tbl[ff_zigzag_direct[i]] / 50, 2, 32767); | |
96 | 16 | } | |
97 | |||
98 | 21936 | static int decode_block(LeadContext * s, GetBitContext * gb, | |
99 | const VLCElem * dc_table, int dc_bits, const VLCElem * ac_table, int ac_bits, | ||
100 | int16_t * dc_pred, const uint16_t * dequant, | ||
101 | uint8_t * dst, int stride) | ||
102 | { | ||
103 | DECLARE_ALIGNED(32, int16_t, block)[64]; | ||
104 | int size; | ||
105 | |||
106 | 21936 | s->bdsp.clear_block(block); | |
107 | |||
108 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21936 times.
|
21936 | if (get_bits_left(gb) <= 0) |
109 | ✗ | return AVERROR_INVALIDDATA; | |
110 | |||
111 | 21936 | size = get_vlc2(gb, dc_table, dc_bits, 1); | |
112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21936 times.
|
21936 | if (size < 0) |
113 | ✗ | return AVERROR_INVALIDDATA; | |
114 | |||
115 |
2/2✓ Branch 0 taken 16492 times.
✓ Branch 1 taken 5444 times.
|
21936 | if (size) |
116 | 16492 | *dc_pred += get_xbits(gb, size); | |
117 | |||
118 | 21936 | block[0] = (1 << 10) + *dc_pred * dequant[0]; | |
119 | |||
120 |
2/2✓ Branch 0 taken 188020 times.
✓ Branch 1 taken 100 times.
|
188120 | for (int i = 1; i < 64; i++) { |
121 | 188020 | int symbol = get_vlc2(gb, ac_table, ac_bits, 2); | |
122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 188020 times.
|
188020 | if (symbol < 0) |
123 | ✗ | return AVERROR_INVALIDDATA; | |
124 | |||
125 |
2/2✓ Branch 0 taken 21836 times.
✓ Branch 1 taken 166184 times.
|
188020 | if (!symbol) |
126 | 21836 | break; | |
127 | |||
128 | 166184 | i += symbol >> 4; | |
129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 166184 times.
|
166184 | if (i >= 64) |
130 | ✗ | return AVERROR_INVALIDDATA; | |
131 | |||
132 | 166184 | size = symbol & 0xF; | |
133 |
2/2✓ Branch 0 taken 165806 times.
✓ Branch 1 taken 378 times.
|
166184 | if (size) |
134 | 165806 | block[s->permutated_scantable[i]] = get_xbits(gb, size) * dequant[i]; | |
135 | } | ||
136 | |||
137 | 21936 | s->idsp.idct_put(dst, stride, block); | |
138 | 21936 | return 0; | |
139 | } | ||
140 | |||
141 | 8 | static int lead_decode_frame(AVCodecContext *avctx, AVFrame * frame, | |
142 | int * got_frame, AVPacket * avpkt) | ||
143 | { | ||
144 | 8 | LeadContext *s = avctx->priv_data; | |
145 | 8 | const uint8_t * buf = avpkt->data; | |
146 | 8 | int ret, format, zero = 0, yuv20p_half = 0, fields = 1, q, size; | |
147 | GetBitContext gb; | ||
148 | 8 | int16_t dc_pred[3] = {0, 0, 0}; | |
149 | uint16_t dequant[2][64]; | ||
150 | |||
151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (avpkt->size < 8) |
152 | ✗ | return AVERROR_INVALIDDATA; | |
153 | |||
154 | 8 | format = AV_RL16(buf + 4); | |
155 |
4/7✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
8 | switch(format) { |
156 | 2 | case 0x0: | |
157 | 2 | zero = 1; | |
158 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
159 | 2 | break; | |
160 | 2 | case 0x6: | |
161 | case 0x8000: | ||
162 | 2 | yuv20p_half = 1; | |
163 | // fall-through | ||
164 | 4 | case 0x1000: | |
165 | 4 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
166 | 4 | break; | |
167 | ✗ | case 0x1006: | |
168 | ✗ | fields = 2; | |
169 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
170 | ✗ | break; | |
171 | ✗ | case 0x2000: | |
172 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV444P; | |
173 | ✗ | break; | |
174 | 2 | case 0x2006: | |
175 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV444P; | |
176 | 2 | fields = 2; | |
177 | 2 | break; | |
178 | ✗ | default: | |
179 | ✗ | avpriv_request_sample(avctx, "unsupported format 0x%x", format); | |
180 | ✗ | return AVERROR_PATCHWELCOME; | |
181 | } | ||
182 | |||
183 | 8 | q = AV_RL16(buf + 6); | |
184 | 8 | calc_dequant(dequant[0], ff_mjpeg_std_luminance_quant_tbl, q); | |
185 | 8 | calc_dequant(dequant[1], ff_mjpeg_std_chrominance_quant_tbl, q); | |
186 | |||
187 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
188 | ✗ | return ret; | |
189 | |||
190 | 8 | av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size, avpkt->size - 8); | |
191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!s->bitstream_buf) |
192 | ✗ | return AVERROR(ENOMEM); | |
193 | |||
194 | 8 | size = 0; | |
195 |
2/2✓ Branch 0 taken 175058 times.
✓ Branch 1 taken 8 times.
|
175066 | for (int i = 8; i < avpkt->size; i++) { |
196 | 175058 | int src = buf[i] ^ 0x80; | |
197 | 175058 | s->bitstream_buf[size++] = src; | |
198 |
4/6✓ Branch 0 taken 2554 times.
✓ Branch 1 taken 172504 times.
✓ Branch 2 taken 2554 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2554 times.
✗ Branch 5 not taken.
|
175058 | if (src == 0xFF && i + 1 < avpkt->size && (buf[i + 1] ^ 0x80) == 0x00) |
199 | 2554 | i++; | |
200 | } | ||
201 | |||
202 | 8 | ret = init_get_bits8(&gb, s->bitstream_buf, size); | |
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (ret < 0) |
204 | ✗ | return ret; | |
205 | |||
206 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
|
8 | if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && zero) { |
207 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2 times.
|
74 | for (int mb_y = 0; mb_y < avctx->height / 8; mb_y++) |
208 |
2/2✓ Branch 0 taken 1584 times.
✓ Branch 1 taken 72 times.
|
1656 | for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++) |
209 |
2/2✓ Branch 0 taken 6336 times.
✓ Branch 1 taken 1584 times.
|
7920 | for (int b = 0; b < 4; b++) { |
210 | 6336 | int luma_block = 2; | |
211 |
2/2✓ Branch 0 taken 3168 times.
✓ Branch 1 taken 3168 times.
|
6336 | const VLCElem * dc_vlc = b < luma_block ? luma_dc_vlc : chroma_dc_vlc; |
212 |
2/2✓ Branch 0 taken 3168 times.
✓ Branch 1 taken 3168 times.
|
6336 | int dc_bits = b < luma_block ? LUMA_DC_BITS : CHROMA_DC_BITS; |
213 |
2/2✓ Branch 0 taken 3168 times.
✓ Branch 1 taken 3168 times.
|
6336 | const VLCElem * ac_vlc = b < luma_block ? luma_ac_vlc : chroma_ac_vlc; |
214 | 6336 | int ac_bits = b < luma_block ? LUMA_AC_BITS : CHROMA_AC_BITS; | |
215 |
2/2✓ Branch 0 taken 3168 times.
✓ Branch 1 taken 3168 times.
|
6336 | int plane = b < luma_block ? 0 : b - 1; |
216 | int x, y, yclip; | ||
217 | |||
218 |
2/2✓ Branch 0 taken 3168 times.
✓ Branch 1 taken 3168 times.
|
6336 | if (b < luma_block) { |
219 | 3168 | y = 8*mb_y + 8*(b >> 1); | |
220 | 3168 | x = 16*mb_x + 8*(b & 1); | |
221 | 3168 | yclip = 0; | |
222 | } else { | ||
223 | 3168 | y = 4*mb_y; | |
224 | 3168 | x = 8*mb_x; | |
225 | 3168 | yclip = y + 8 >= avctx->height / 2; | |
226 | } | ||
227 | |||
228 |
2/2✓ Branch 0 taken 176 times.
✓ Branch 1 taken 6160 times.
|
6336 | if (yclip) { |
229 | uint8_t tmp[64]; | ||
230 | 176 | ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits, | |
231 | 176 | dc_pred + plane, dequant[!(b < 4)], tmp, 8); | |
232 |
4/4✓ Branch 0 taken 1144 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 1056 times.
✓ Branch 3 taken 88 times.
|
1232 | for (int yy = 0; yy < 8 && y + yy < avctx->height / 2; yy++) |
233 | 1056 | memcpy(frame->data[plane] + (y+yy)*frame->linesize[plane] + x, tmp + yy, 8); | |
234 | } else { | ||
235 | 6160 | ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits, | |
236 | 6160 | dc_pred + plane, dequant[!(b < 4)], | |
237 | 6160 | frame->data[plane] + y*frame->linesize[plane] + x, | |
238 | frame->linesize[plane]); | ||
239 | } | ||
240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6336 times.
|
6336 | if (ret < 0) |
241 | ✗ | return ret; | |
242 | } | ||
243 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { |
244 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (int f = 0; f < fields; f++) |
245 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 4 times.
|
74 | for (int mb_y = 0; mb_y < (avctx->height + 15) / 16 / fields; mb_y++) |
246 |
2/2✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 70 times.
|
1870 | for (int mb_x = 0; mb_x < (avctx->width + 15) / 16; mb_x++) |
247 |
4/4✓ Branch 0 taken 6000 times.
✓ Branch 1 taken 4200 times.
✓ Branch 2 taken 8400 times.
✓ Branch 3 taken 1800 times.
|
10200 | for (int b = 0; b < (yuv20p_half ? 4 : 6); b++) { |
248 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
|
8400 | int luma_block = yuv20p_half ? 2 : 4; |
249 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
|
8400 | const VLCElem * dc_vlc = b < luma_block ? luma_dc_vlc : chroma_dc_vlc; |
250 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
|
8400 | int dc_bits = b < luma_block ? LUMA_DC_BITS : CHROMA_DC_BITS; |
251 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
|
8400 | const VLCElem * ac_vlc = b < luma_block ? luma_ac_vlc : chroma_ac_vlc; |
252 | 8400 | int ac_bits = b < luma_block ? LUMA_AC_BITS : CHROMA_AC_BITS; | |
253 |
4/4✓ Branch 0 taken 3600 times.
✓ Branch 1 taken 4800 times.
✓ Branch 2 taken 2400 times.
✓ Branch 3 taken 1200 times.
|
8400 | int plane = b < luma_block ? 0 : b - (yuv20p_half ? 1 : 3); |
254 | int x, y; | ||
255 | |||
256 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
|
8400 | if (b < luma_block) { |
257 | 4800 | y = 16*mb_y + 8*(b >> 1); | |
258 | 4800 | x = 16*mb_x + 8*(b & 1); | |
259 | } else { | ||
260 | 3600 | y = 8*mb_y; | |
261 | 3600 | x = 8*mb_x; | |
262 | } | ||
263 | |||
264 | 8400 | ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits, | |
265 | 8400 | dc_pred + plane, dequant[!(b < 4)], | |
266 | 8400 | frame->data[plane] + (f + y*fields)*frame->linesize[plane] + x, | |
267 |
4/4✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
✓ Branch 2 taken 2400 times.
✓ Branch 3 taken 2400 times.
|
8400 | (yuv20p_half && b < 2 ? 2 : 1) * fields * frame->linesize[plane]); |
268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8400 times.
|
8400 | if (ret < 0) |
269 | ✗ | return ret; | |
270 | |||
271 |
4/4✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 3600 times.
✓ Branch 2 taken 2400 times.
✓ Branch 3 taken 2400 times.
|
8400 | if (yuv20p_half && b < 2) |
272 | 2400 | copy_block8(frame->data[plane] + (y + 1)*frame->linesize[plane] + x, | |
273 | 2400 | frame->data[plane] + y*frame->linesize[plane] + x, | |
274 | 2400 | 2*frame->linesize[plane], 2*frame->linesize[plane], 8); | |
275 | } | ||
276 | } else { | ||
277 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | for (int f = 0; f < fields; f++) |
278 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
|
64 | for (int j = 0; j < (avctx->height + 7) / fields / 8; j++) |
279 |
2/2✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 60 times.
|
2460 | for (int i = 0; i < (avctx->width + 7) / 8; i++) |
280 |
2/2✓ Branch 0 taken 7200 times.
✓ Branch 1 taken 2400 times.
|
9600 | for (int plane = 0; plane < 3; plane++) { |
281 |
2/2✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 4800 times.
|
7200 | const VLCElem * dc_vlc = !plane ? luma_dc_vlc : chroma_dc_vlc; |
282 |
2/2✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 4800 times.
|
7200 | int dc_bits = !plane ? LUMA_DC_BITS : CHROMA_DC_BITS; |
283 |
2/2✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 4800 times.
|
7200 | const VLCElem * ac_vlc = !plane ? luma_ac_vlc : chroma_ac_vlc; |
284 | 7200 | int ac_bits = !plane ? LUMA_AC_BITS : CHROMA_AC_BITS; | |
285 | |||
286 | 7200 | ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits, | |
287 | 7200 | dc_pred + plane, dequant[!!plane], | |
288 | 7200 | frame->data[plane] + (f + 8*j*fields)*frame->linesize[plane] + 8*i, | |
289 | 7200 | fields * frame->linesize[plane]); | |
290 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7200 times.
|
7200 | if (ret < 0) |
291 | ✗ | return ret; | |
292 | } | ||
293 | } | ||
294 | |||
295 | 8 | *got_frame = 1; | |
296 | |||
297 | 8 | return avpkt->size; | |
298 | } | ||
299 | |||
300 | 8 | static av_cold int lead_decode_end(AVCodecContext * avctx) | |
301 | { | ||
302 | 8 | LeadContext *s = avctx->priv_data; | |
303 | |||
304 | 8 | av_freep(&s->bitstream_buf); | |
305 | |||
306 | 8 | return 0; | |
307 | } | ||
308 | |||
309 | const FFCodec ff_lead_decoder = { | ||
310 | .p.name = "lead", | ||
311 | CODEC_LONG_NAME("LEAD MCMP"), | ||
312 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
313 | .p.id = AV_CODEC_ID_LEAD, | ||
314 | .priv_data_size = sizeof(LeadContext), | ||
315 | .init = lead_decode_init, | ||
316 | .close = lead_decode_end, | ||
317 | FF_CODEC_DECODE_CB(lead_decode_frame), | ||
318 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
319 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
320 | }; | ||
321 |