3 * Copyright (c) 2016 Paul B Mahol
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/pixdesc.h"
28 #include "bitstream.h"
29 #include "bytestream.h"
30 #include "huffyuvdsp.h"
35 typedef struct Slice
{
40 typedef enum Prediction
{
46 typedef struct HuffEntry
{
52 typedef struct MagicYUVContext
{
56 int planes
; // number of encoded planes in bitstream
57 int decorrelate
; // postprocessing work
58 int interlaced
; // video is interlaced
59 uint8_t *buf
; // pointer to AVPacket->data
62 Slice
*slices
[4]; // slice bitstream positions for each plane
63 unsigned int slices_size
[4]; // slice sizes for each plane
64 uint8_t len
[4][256]; // table of code lengths for each plane
65 VLC vlc
[4]; // VLC for each plane
66 HuffYUVDSPContext hdsp
;
69 static int huff_cmp_len(const void *a
, const void *b
)
71 const HuffEntry
*aa
= a
, *bb
= b
;
72 return (aa
->len
- bb
->len
) * 256 + aa
->sym
- bb
->sym
;
75 static int huff_build(VLC
*vlc
, uint8_t *len
)
84 for (i
= 0; i
< 256; i
++) {
88 qsort(he
, 256, sizeof(HuffEntry
), huff_cmp_len
);
91 for (i
= 255; i
>= 0; i
--) {
92 codes
[i
] = code
>> (32 - he
[i
].len
);
95 code
+= 0x80000000u
>> (he
[i
].len
- 1);
99 return ff_init_vlc_sparse(vlc
, FFMIN(he
[255].len
, 12), 256,
100 bits
, sizeof(*bits
), sizeof(*bits
),
101 codes
, sizeof(*codes
), sizeof(*codes
),
102 syms
, sizeof(*syms
), sizeof(*syms
), 0);
105 static int magy_decode_slice(AVCodecContext
*avctx
, void *tdata
,
108 MagicYUVContext
*s
= avctx
->priv_data
;
109 int interlaced
= s
->interlaced
;
115 for (i
= 0; i
< s
->planes
; i
++) {
116 int left
, lefttop
, top
;
117 int height
= AV_CEIL_RSHIFT(FFMIN(s
->slice_height
, avctx
->height
- j
* s
->slice_height
), s
->vshift
[i
]);
118 int width
= AV_CEIL_RSHIFT(avctx
->width
, s
->hshift
[i
]);
119 int sheight
= AV_CEIL_RSHIFT(s
->slice_height
, s
->vshift
[i
]);
120 ptrdiff_t fake_stride
= p
->linesize
[i
] * (1 + interlaced
);
121 ptrdiff_t stride
= p
->linesize
[i
];
123 int ret
= bitstream_init8(&bc
, s
->buf
+ s
->slices
[i
][j
].start
,
124 s
->slices
[i
][j
].size
);
129 flags
= bitstream_read(&bc
, 8);
130 pred
= bitstream_read(&bc
, 8);
132 dst
= p
->data
[i
] + j
* sheight
* stride
;
134 for (k
= 0; k
< height
; k
++) {
135 for (x
= 0; x
< width
; x
++)
136 dst
[x
] = bitstream_read(&bc
, 8);
141 for (k
= 0; k
< height
; k
++) {
142 for (x
= 0; x
< width
; x
++) {
144 if (bitstream_bits_left(&bc
) <= 0)
145 return AVERROR_INVALIDDATA
;
147 pix
= bitstream_read_vlc(&bc
, s
->vlc
[i
].table
, s
->vlc
[i
].bits
, 3);
149 return AVERROR_INVALIDDATA
;
159 dst
= p
->data
[i
] + j
* sheight
* stride
;
160 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
163 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
166 for (k
= 1 + interlaced
; k
< height
; k
++) {
167 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, dst
[-fake_stride
]);
172 dst
= p
->data
[i
] + j
* sheight
* stride
;
173 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
177 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
181 for (k
= 1 + interlaced
; k
< height
; k
++) {
182 top
= dst
[-fake_stride
];
185 for (x
= 1; x
< width
; x
++) {
186 top
= dst
[x
- fake_stride
];
187 lefttop
= dst
[x
- (fake_stride
+ 1)];
188 left
+= top
- lefttop
+ dst
[x
];
195 dst
= p
->data
[i
] + j
* sheight
* stride
;
196 lefttop
= left
= dst
[0];
197 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
200 lefttop
= left
= dst
[0];
201 s
->hdsp
.add_hfyu_left_pred(dst
, dst
, width
, 0);
204 for (k
= 1 + interlaced
; k
< height
; k
++) {
205 s
->hdsp
.add_hfyu_median_pred(dst
, dst
- fake_stride
,
206 dst
, width
, &left
, &lefttop
);
207 lefttop
= left
= dst
[0];
212 avpriv_request_sample(avctx
, "Unknown prediction: %d", pred
);
216 if (s
->decorrelate
) {
217 int height
= FFMIN(s
->slice_height
, avctx
->height
- j
* s
->slice_height
);
218 int width
= avctx
->width
;
219 uint8_t *b
= p
->data
[0] + j
* s
->slice_height
* p
->linesize
[0];
220 uint8_t *g
= p
->data
[1] + j
* s
->slice_height
* p
->linesize
[1];
221 uint8_t *r
= p
->data
[2] + j
* s
->slice_height
* p
->linesize
[2];
223 for (i
= 0; i
< height
; i
++) {
224 s
->hdsp
.add_bytes(b
, g
, width
);
225 s
->hdsp
.add_bytes(r
, g
, width
);
235 static int magy_decode_frame(AVCodecContext
*avctx
, void *data
,
236 int *got_frame
, AVPacket
*avpkt
)
238 MagicYUVContext
*s
= avctx
->priv_data
;
239 ThreadFrame frame
= { .f
= data
};
241 GetByteContext gbyte
;
243 uint32_t first_offset
, offset
, next_offset
, header_size
, slice_width
;
244 int width
, height
, format
, version
, table_size
;
247 bytestream2_init(&gbyte
, avpkt
->data
, avpkt
->size
);
248 if (bytestream2_get_le32(&gbyte
) != MKTAG('M', 'A', 'G', 'Y'))
249 return AVERROR_INVALIDDATA
;
251 header_size
= bytestream2_get_le32(&gbyte
);
252 if (header_size
< 32 || header_size
>= avpkt
->size
) {
253 av_log(avctx
, AV_LOG_ERROR
,
254 "header or packet too small %"PRIu32
"\n", header_size
);
255 return AVERROR_INVALIDDATA
;
258 version
= bytestream2_get_byte(&gbyte
);
260 avpriv_request_sample(avctx
, "Version %d", version
);
261 return AVERROR_PATCHWELCOME
;
270 format
= bytestream2_get_byte(&gbyte
);
273 avctx
->pix_fmt
= AV_PIX_FMT_GBRP
;
277 avctx
->pix_fmt
= AV_PIX_FMT_GBRAP
;
281 avctx
->pix_fmt
= AV_PIX_FMT_YUV444P
;
284 avctx
->pix_fmt
= AV_PIX_FMT_YUV422P
;
289 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
296 avctx
->pix_fmt
= AV_PIX_FMT_YUVA444P
;
299 avctx
->pix_fmt
= AV_PIX_FMT_GRAY8
;
302 avpriv_request_sample(avctx
, "Format 0x%X", format
);
303 return AVERROR_PATCHWELCOME
;
305 s
->planes
= av_pix_fmt_count_planes(avctx
->pix_fmt
);
307 bytestream2_skip(&gbyte
, 2);
308 s
->interlaced
= !!(bytestream2_get_byte(&gbyte
) & 2);
309 bytestream2_skip(&gbyte
, 3);
311 width
= bytestream2_get_le32(&gbyte
);
312 height
= bytestream2_get_le32(&gbyte
);
313 ret
= ff_set_dimensions(avctx
, width
, height
);
317 slice_width
= bytestream2_get_le32(&gbyte
);
318 if (slice_width
!= width
) {
319 avpriv_request_sample(avctx
, "Slice width %"PRIu32
, slice_width
);
320 return AVERROR_PATCHWELCOME
;
322 s
->slice_height
= bytestream2_get_le32(&gbyte
);
323 if (s
->slice_height
<= 0 || s
->slice_height
> INT_MAX
- height
) {
324 av_log(avctx
, AV_LOG_ERROR
,
325 "invalid slice height: %d\n", s
->slice_height
);
326 return AVERROR_INVALIDDATA
;
329 bytestream2_skip(&gbyte
, 4);
331 s
->nb_slices
= (height
+ s
->slice_height
- 1) / s
->slice_height
;
332 if (s
->nb_slices
> INT_MAX
/ sizeof(Slice
)) {
333 av_log(avctx
, AV_LOG_ERROR
,
334 "invalid number of slices: %d\n", s
->nb_slices
);
335 return AVERROR_INVALIDDATA
;
338 for (i
= 0; i
< s
->planes
; i
++) {
339 av_fast_malloc(&s
->slices
[i
], &s
->slices_size
[i
], s
->nb_slices
* sizeof(Slice
));
341 return AVERROR(ENOMEM
);
343 offset
= bytestream2_get_le32(&gbyte
);
344 if (offset
>= avpkt
->size
- header_size
)
345 return AVERROR_INVALIDDATA
;
348 first_offset
= offset
;
350 for (j
= 0; j
< s
->nb_slices
- 1; j
++) {
351 s
->slices
[i
][j
].start
= offset
+ header_size
;
353 next_offset
= bytestream2_get_le32(&gbyte
);
354 if (next_offset
<= offset
|| next_offset
>= avpkt
->size
- header_size
)
355 return AVERROR_INVALIDDATA
;
357 s
->slices
[i
][j
].size
= next_offset
- offset
;
358 offset
= next_offset
;
361 s
->slices
[i
][j
].start
= offset
+ header_size
;
362 s
->slices
[i
][j
].size
= avpkt
->size
- s
->slices
[i
][j
].start
;
365 if (bytestream2_get_byte(&gbyte
) != s
->planes
)
366 return AVERROR_INVALIDDATA
;
368 bytestream2_skip(&gbyte
, s
->nb_slices
* s
->planes
);
370 table_size
= header_size
+ first_offset
- bytestream2_tell(&gbyte
);
372 return AVERROR_INVALIDDATA
;
374 ret
= bitstream_init8(&bc
, avpkt
->data
+ bytestream2_tell(&gbyte
), table_size
);
378 memset(s
->len
, 0, sizeof(s
->len
));
380 while (bitstream_bits_left(&bc
) >= 8) {
381 int b
= bitstream_read(&bc
, 4);
382 int x
= bitstream_read(&bc
, 4);
383 int l
= bitstream_read(&bc
, b
) + 1;
385 for (k
= 0; k
< l
; k
++)
387 s
->len
[i
][j
+ k
] = x
;
392 if (huff_build(&s
->vlc
[i
], s
->len
[i
])) {
393 av_log(avctx
, AV_LOG_ERROR
, "Cannot build Huffman codes\n");
394 return AVERROR_INVALIDDATA
;
397 if (i
== s
->planes
) {
400 } else if (j
> 256) {
401 return AVERROR_INVALIDDATA
;
405 if (i
!= s
->planes
) {
406 av_log(avctx
, AV_LOG_ERROR
, "Huffman tables too short\n");
407 return AVERROR_INVALIDDATA
;
410 p
->pict_type
= AV_PICTURE_TYPE_I
;
413 if ((ret
= ff_thread_get_buffer(avctx
, &frame
, 0)) < 0)
416 s
->buf
= avpkt
->data
;
418 avctx
->execute2(avctx
, magy_decode_slice
, NULL
, NULL
, s
->nb_slices
);
420 if (avctx
->pix_fmt
== AV_PIX_FMT_GBRP
||
421 avctx
->pix_fmt
== AV_PIX_FMT_GBRAP
) {
422 FFSWAP(uint8_t*, p
->data
[0], p
->data
[1]);
423 FFSWAP(int, p
->linesize
[0], p
->linesize
[1]);
432 static int magy_init_thread_copy(AVCodecContext
*avctx
)
434 MagicYUVContext
*s
= avctx
->priv_data
;
437 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->slices
); i
++) {
439 s
->slices_size
[i
] = 0;
446 static av_cold
int magy_decode_init(AVCodecContext
*avctx
)
448 MagicYUVContext
*s
= avctx
->priv_data
;
449 ff_huffyuvdsp_init(&s
->hdsp
);
453 static av_cold
int magy_decode_end(AVCodecContext
*avctx
)
455 MagicYUVContext
* const s
= avctx
->priv_data
;
458 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->slices
); i
++) {
459 av_freep(&s
->slices
[i
]);
460 s
->slices_size
[i
] = 0;
461 ff_free_vlc(&s
->vlc
[i
]);
467 AVCodec ff_magicyuv_decoder
= {
469 .long_name
= NULL_IF_CONFIG_SMALL("MagicYUV video"),
470 .type
= AVMEDIA_TYPE_VIDEO
,
471 .id
= AV_CODEC_ID_MAGICYUV
,
472 .priv_data_size
= sizeof(MagicYUVContext
),
473 .init
= magy_decode_init
,
474 .init_thread_copy
= ONLY_IF_THREADS_ENABLED(magy_init_thread_copy
),
475 .close
= magy_decode_end
,
476 .decode
= magy_decode_frame
,
477 .capabilities
= AV_CODEC_CAP_DR1
|
478 AV_CODEC_CAP_FRAME_THREADS
|
479 AV_CODEC_CAP_SLICE_THREADS
,
480 .caps_internal
= FF_CODEC_CAP_INIT_THREADSAFE
,