3 * Copyright (c) 2012 Konstantin Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "libavutil/intreadwrite.h"
33 #include "bytestream.h"
53 static const uint8_t luma_quant
[64] = {
54 8, 6, 5, 8, 12, 20, 26, 31,
55 6, 6, 7, 10, 13, 29, 30, 28,
56 7, 7, 8, 12, 20, 29, 35, 28,
57 7, 9, 11, 15, 26, 44, 40, 31,
58 9, 11, 19, 28, 34, 55, 52, 39,
59 12, 18, 28, 32, 41, 52, 57, 46,
60 25, 32, 39, 44, 52, 61, 60, 51,
61 36, 46, 48, 49, 56, 50, 52, 50
64 static const uint8_t chroma_quant
[64] = {
65 9, 9, 12, 24, 50, 50, 50, 50,
66 9, 11, 13, 33, 50, 50, 50, 50,
67 12, 13, 28, 50, 50, 50, 50, 50,
68 24, 33, 50, 50, 50, 50, 50, 50,
69 50, 50, 50, 50, 50, 50, 50, 50,
70 50, 50, 50, 50, 50, 50, 50, 50,
71 50, 50, 50, 50, 50, 50, 50, 50,
72 50, 50, 50, 50, 50, 50, 50, 50,
75 typedef struct JPGContext
{
80 VLC dc_vlc
[2], ac_vlc
[2];
82 DECLARE_ALIGNED(16, int16_t, block
)[6][64];
87 typedef struct G2MContext
{
92 int width
, height
, bpp
;
93 int orig_width
, orig_height
;
94 int tile_width
, tile_height
;
95 int tiles_x
, tiles_y
, tile_x
, tile_y
;
100 int framebuf_stride
, old_width
, old_height
;
102 uint8_t *synth_tile
, *jpeg_tile
;
103 int tile_stride
, old_tile_w
, old_tile_h
;
105 uint8_t *kempf_buf
, *kempf_flags
;
110 int cursor_w
, cursor_h
, cursor_x
, cursor_y
;
111 int cursor_hot_x
, cursor_hot_y
;
114 static av_cold
int build_vlc(VLC
*vlc
, const uint8_t *bits_table
,
115 const uint8_t *val_table
, int nb_codes
,
118 uint8_t huff_size
[256] = { 0 };
119 uint16_t huff_code
[256];
120 uint16_t huff_sym
[256];
123 ff_mjpeg_build_huffman_codes(huff_size
, huff_code
, bits_table
, val_table
);
125 for (i
= 0; i
< 256; i
++)
126 huff_sym
[i
] = i
+ 16 * is_ac
;
129 huff_sym
[0] = 16 * 256;
131 return ff_init_vlc_sparse(vlc
, 9, nb_codes
, huff_size
, 1, 1,
132 huff_code
, 2, 2, huff_sym
, 2, 2, 0);
135 static av_cold
int jpg_init(AVCodecContext
*avctx
, JPGContext
*c
)
139 ret
= build_vlc(&c
->dc_vlc
[0], avpriv_mjpeg_bits_dc_luminance
,
140 avpriv_mjpeg_val_dc
, 12, 0);
143 ret
= build_vlc(&c
->dc_vlc
[1], avpriv_mjpeg_bits_dc_chrominance
,
144 avpriv_mjpeg_val_dc
, 12, 0);
147 ret
= build_vlc(&c
->ac_vlc
[0], avpriv_mjpeg_bits_ac_luminance
,
148 avpriv_mjpeg_val_ac_luminance
, 251, 1);
151 ret
= build_vlc(&c
->ac_vlc
[1], avpriv_mjpeg_bits_ac_chrominance
,
152 avpriv_mjpeg_val_ac_chrominance
, 251, 1);
156 ff_blockdsp_init(&c
->bdsp
, avctx
);
157 ff_idctdsp_init(&c
->idsp
, avctx
);
158 ff_init_scantable(c
->idsp
.idct_permutation
, &c
->scantable
,
164 static av_cold
void jpg_free_context(JPGContext
*ctx
)
168 for (i
= 0; i
< 2; i
++) {
169 ff_free_vlc(&ctx
->dc_vlc
[i
]);
170 ff_free_vlc(&ctx
->ac_vlc
[i
]);
176 static void jpg_unescape(const uint8_t *src
, int src_size
,
177 uint8_t *dst
, int *dst_size
)
179 const uint8_t *src_end
= src
+ src_size
;
180 uint8_t *dst_start
= dst
;
182 while (src
< src_end
) {
187 if (x
== 0xFF && !*src
)
190 *dst_size
= dst
- dst_start
;
193 static int jpg_decode_block(JPGContext
*c
, GetBitContext
*gb
,
194 int plane
, int16_t *block
)
197 const int is_chroma
= !!plane
;
198 const uint8_t *qmat
= is_chroma
? chroma_quant
: luma_quant
;
200 c
->bdsp
.clear_block(block
);
201 dc
= get_vlc2(gb
, c
->dc_vlc
[is_chroma
].table
, 9, 3);
203 return AVERROR_INVALIDDATA
;
205 dc
= get_xbits(gb
, dc
);
206 dc
= dc
* qmat
[0] + c
->prev_dc
[plane
];
208 c
->prev_dc
[plane
] = dc
;
212 val
= get_vlc2(gb
, c
->ac_vlc
[is_chroma
].table
, 9, 3);
214 return AVERROR_INVALIDDATA
;
218 return val
? AVERROR_INVALIDDATA
: 0;
222 val
= get_xbits(gb
, nbits
);
223 val
*= qmat
[ff_zigzag_direct
[pos
]];
224 block
[c
->scantable
.permutated
[pos
]] = val
;
230 static inline void yuv2rgb(uint8_t *out
, int Y
, int U
, int V
)
232 out
[0] = av_clip_uint8(Y
+ ( 91881 * V
+ 32768 >> 16));
233 out
[1] = av_clip_uint8(Y
+ (-22554 * U
- 46802 * V
+ 32768 >> 16));
234 out
[2] = av_clip_uint8(Y
+ (116130 * U
+ 32768 >> 16));
237 static int jpg_decode_data(JPGContext
*c
, int width
, int height
,
238 const uint8_t *src
, int src_size
,
239 uint8_t *dst
, int dst_stride
,
240 const uint8_t *mask
, int mask_stride
, int num_mbs
,
244 int mb_w
, mb_h
, mb_x
, mb_y
, i
, j
;
249 if ((ret
= av_reallocp(&c
->buf
,
250 src_size
+ FF_INPUT_BUFFER_PADDING_SIZE
)) < 0)
252 jpg_unescape(src
, src_size
, c
->buf
, &unesc_size
);
253 memset(c
->buf
+ unesc_size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
254 init_get_bits(&gb
, c
->buf
, unesc_size
* 8);
256 width
= FFALIGN(width
, 16);
258 mb_h
= (height
+ 15) >> 4;
261 num_mbs
= mb_w
* mb_h
* 4;
263 for (i
= 0; i
< 3; i
++)
264 c
->prev_dc
[i
] = 1024;
266 c
->bdsp
.clear_blocks(c
->block
[0]);
267 for (mb_y
= 0; mb_y
< mb_h
; mb_y
++) {
268 for (mb_x
= 0; mb_x
< mb_w
; mb_x
++) {
269 if (mask
&& !mask
[mb_x
* 2] && !mask
[mb_x
* 2 + 1] &&
270 !mask
[mb_x
* 2 + mask_stride
] &&
271 !mask
[mb_x
* 2 + 1 + mask_stride
]) {
275 for (j
= 0; j
< 2; j
++) {
276 for (i
= 0; i
< 2; i
++) {
277 if (mask
&& !mask
[mb_x
* 2 + i
+ j
* mask_stride
])
280 if ((ret
= jpg_decode_block(c
, &gb
, 0,
281 c
->block
[i
+ j
* 2])) != 0)
283 c
->idsp
.idct(c
->block
[i
+ j
* 2]);
286 for (i
= 1; i
< 3; i
++) {
287 if ((ret
= jpg_decode_block(c
, &gb
, i
, c
->block
[i
+ 3])) != 0)
289 c
->idsp
.idct(c
->block
[i
+ 3]);
292 for (j
= 0; j
< 16; j
++) {
293 uint8_t *out
= dst
+ bx
* 3 + (by
+ j
) * dst_stride
;
294 for (i
= 0; i
< 16; i
++) {
297 Y
= c
->block
[(j
>> 3) * 2 + (i
>> 3)][(i
& 7) + (j
& 7) * 8];
298 U
= c
->block
[4 ^ swapuv
][(i
>> 1) + (j
>> 1) * 8] - 128;
299 V
= c
->block
[5 ^ swapuv
][(i
>> 1) + (j
>> 1) * 8] - 128;
300 yuv2rgb(out
+ i
* 3, Y
, U
, V
);
311 mask
+= mask_stride
* 2;
317 static void kempf_restore_buf(const uint8_t *src
, int len
,
318 uint8_t *dst
, int stride
,
319 const uint8_t *jpeg_tile
, int tile_stride
,
320 int width
, int height
,
321 const uint8_t *pal
, int npal
, int tidx
)
326 init_get_bits(&gb
, src
, len
* 8);
328 if (npal
<= 2) nb
= 1;
329 else if (npal
<= 4) nb
= 2;
330 else if (npal
<= 16) nb
= 4;
333 for (j
= 0; j
< height
; j
++, dst
+= stride
, jpeg_tile
+= tile_stride
) {
334 if (get_bits(&gb
, 8))
336 for (i
= 0; i
< width
; i
++) {
337 col
= get_bits(&gb
, nb
);
339 memcpy(dst
+ i
* 3, pal
+ col
* 3, 3);
341 memcpy(dst
+ i
* 3, jpeg_tile
+ i
* 3, 3);
346 static int kempf_decode_tile(G2MContext
*c
, int tile_x
, int tile_y
,
347 const uint8_t *src
, int src_size
)
350 int hdr
, zsize
, npal
, tidx
= -1, ret
;
352 const uint8_t *src_end
= src
+ src_size
;
353 uint8_t pal
[768], transp
[3];
354 uLongf dlen
= (c
->tile_width
+ 1) * c
->tile_height
;
356 int nblocks
, cblocks
, bstride
;
357 int bits
, bitbuf
, coded
;
358 uint8_t *dst
= c
->framebuf
+ tile_x
* c
->tile_width
* 3 +
359 tile_y
* c
->tile_height
* c
->framebuf_stride
;
362 return AVERROR_INVALIDDATA
;
364 width
= FFMIN(c
->width
- tile_x
* c
->tile_width
, c
->tile_width
);
365 height
= FFMIN(c
->height
- tile_y
* c
->tile_height
, c
->tile_height
);
371 memcpy(transp
, src
, 3);
373 for (j
= 0; j
< height
; j
++, dst
+= c
->framebuf_stride
)
374 for (i
= 0; i
< width
; i
++)
375 memcpy(dst
+ i
* 3, transp
, 3);
377 } else if (sub_type
== 1) {
378 return jpg_decode_data(&c
->jc
, width
, height
, src
, src_end
- src
,
379 dst
, c
->framebuf_stride
, NULL
, 0, 0, 0);
383 memcpy(transp
, src
, 3);
387 if (src_end
- src
< npal
* 3)
388 return AVERROR_INVALIDDATA
;
389 memcpy(pal
, src
, npal
* 3);
392 for (i
= 0; i
< npal
; i
++) {
393 if (!memcmp(pal
+ i
* 3, transp
, 3)) {
400 if (src_end
- src
< 2)
402 zsize
= (src
[0] << 8) | src
[1];
405 if (src_end
- src
< zsize
+ (sub_type
!= 2))
406 return AVERROR_INVALIDDATA
;
408 ret
= uncompress(c
->kempf_buf
, &dlen
, src
, zsize
);
410 return AVERROR_INVALIDDATA
;
414 kempf_restore_buf(c
->kempf_buf
, dlen
, dst
, c
->framebuf_stride
,
415 NULL
, 0, width
, height
, pal
, npal
, tidx
);
419 nblocks
= *src
++ + 1;
421 bstride
= FFALIGN(width
, 16) >> 3;
422 // blocks are coded LSB and we need normal bitreader for JPEG data
424 for (i
= 0; i
< (FFALIGN(height
, 16) >> 4); i
++) {
425 for (j
= 0; j
< (FFALIGN(width
, 16) >> 4); j
++) {
428 return AVERROR_INVALIDDATA
;
436 if (cblocks
> nblocks
)
437 return AVERROR_INVALIDDATA
;
438 c
->kempf_flags
[j
* 2 + i
* 2 * bstride
] =
439 c
->kempf_flags
[j
* 2 + 1 + i
* 2 * bstride
] =
440 c
->kempf_flags
[j
* 2 + (i
* 2 + 1) * bstride
] =
441 c
->kempf_flags
[j
* 2 + 1 + (i
* 2 + 1) * bstride
] = coded
;
445 memset(c
->jpeg_tile
, 0, c
->tile_stride
* height
);
446 jpg_decode_data(&c
->jc
, width
, height
, src
, src_end
- src
,
447 c
->jpeg_tile
, c
->tile_stride
,
448 c
->kempf_flags
, bstride
, nblocks
* 4, 0);
450 kempf_restore_buf(c
->kempf_buf
, dlen
, dst
, c
->framebuf_stride
,
451 c
->jpeg_tile
, c
->tile_stride
,
452 width
, height
, pal
, npal
, tidx
);
457 static int g2m_init_buffers(G2MContext
*c
)
461 if (!c
->framebuf
|| c
->old_width
< c
->width
|| c
->old_height
< c
->height
) {
462 c
->framebuf_stride
= FFALIGN(c
->width
+ 15, 16) * 3;
463 aligned_height
= c
->height
+ 15;
464 av_free(c
->framebuf
);
465 c
->framebuf
= av_mallocz(c
->framebuf_stride
* aligned_height
);
467 return AVERROR(ENOMEM
);
469 if (!c
->synth_tile
|| !c
->jpeg_tile
||
470 c
->old_tile_w
< c
->tile_width
||
471 c
->old_tile_h
< c
->tile_height
) {
472 c
->tile_stride
= FFALIGN(c
->tile_width
, 16) * 3;
473 aligned_height
= FFALIGN(c
->tile_height
, 16);
474 av_free(c
->synth_tile
);
475 av_free(c
->jpeg_tile
);
476 av_free(c
->kempf_buf
);
477 av_free(c
->kempf_flags
);
478 c
->synth_tile
= av_mallocz(c
->tile_stride
* aligned_height
);
479 c
->jpeg_tile
= av_mallocz(c
->tile_stride
* aligned_height
);
480 c
->kempf_buf
= av_mallocz((c
->tile_width
+ 1) * aligned_height
481 + FF_INPUT_BUFFER_PADDING_SIZE
);
482 c
->kempf_flags
= av_mallocz( c
->tile_width
* aligned_height
);
483 if (!c
->synth_tile
|| !c
->jpeg_tile
||
484 !c
->kempf_buf
|| !c
->kempf_flags
)
485 return AVERROR(ENOMEM
);
491 static int g2m_load_cursor(AVCodecContext
*avctx
, G2MContext
*c
,
497 uint32_t cur_size
, cursor_w
, cursor_h
, cursor_stride
;
498 uint32_t cursor_hot_x
, cursor_hot_y
;
501 cur_size
= bytestream2_get_be32(gb
);
502 cursor_w
= bytestream2_get_byte(gb
);
503 cursor_h
= bytestream2_get_byte(gb
);
504 cursor_hot_x
= bytestream2_get_byte(gb
);
505 cursor_hot_y
= bytestream2_get_byte(gb
);
506 cursor_fmt
= bytestream2_get_byte(gb
);
508 cursor_stride
= FFALIGN(cursor_w
, cursor_fmt
==1 ? 32 : 1) * 4;
510 if (cursor_w
< 1 || cursor_w
> 256 ||
511 cursor_h
< 1 || cursor_h
> 256) {
512 av_log(avctx
, AV_LOG_ERROR
, "Invalid cursor dimensions %"PRIu32
"x%"PRIu32
"\n",
514 return AVERROR_INVALIDDATA
;
516 if (cursor_hot_x
> cursor_w
|| cursor_hot_y
> cursor_h
) {
517 av_log(avctx
, AV_LOG_WARNING
, "Invalid hotspot position %"PRIu32
",%"PRIu32
"\n",
518 cursor_hot_x
, cursor_hot_y
);
519 cursor_hot_x
= FFMIN(cursor_hot_x
, cursor_w
- 1);
520 cursor_hot_y
= FFMIN(cursor_hot_y
, cursor_h
- 1);
522 if (cur_size
- 9 > bytestream2_get_bytes_left(gb
) ||
523 c
->cursor_w
* c
->cursor_h
/ 4 > cur_size
) {
524 av_log(avctx
, AV_LOG_ERROR
, "Invalid cursor data size %"PRIu32
"/%u\n",
525 cur_size
, bytestream2_get_bytes_left(gb
));
526 return AVERROR_INVALIDDATA
;
528 if (cursor_fmt
!= 1 && cursor_fmt
!= 32) {
529 avpriv_report_missing_feature(avctx
, "Cursor format %d",
531 return AVERROR_PATCHWELCOME
;
534 if ((err
= av_reallocp(&c
->cursor
, cursor_stride
* cursor_h
)) < 0) {
535 av_log(avctx
, AV_LOG_ERROR
, "Cannot allocate cursor buffer\n");
539 c
->cursor_w
= cursor_w
;
540 c
->cursor_h
= cursor_h
;
541 c
->cursor_hot_x
= cursor_hot_x
;
542 c
->cursor_hot_y
= cursor_hot_y
;
543 c
->cursor_fmt
= cursor_fmt
;
544 c
->cursor_stride
= cursor_stride
;
547 switch (c
->cursor_fmt
) {
548 case 1: // old monochrome
549 for (j
= 0; j
< c
->cursor_h
; j
++) {
550 for (i
= 0; i
< c
->cursor_w
; i
+= 32) {
551 bits
= bytestream2_get_be32(gb
);
552 for (k
= 0; k
< 32; k
++) {
553 dst
[0] = !!(bits
& 0x80000000);
561 for (j
= 0; j
< c
->cursor_h
; j
++) {
562 for (i
= 0; i
< c
->cursor_w
; i
+= 32) {
563 bits
= bytestream2_get_be32(gb
);
564 for (k
= 0; k
< 32; k
++) {
565 int mask_bit
= !!(bits
& 0x80000000);
566 switch (dst
[0] * 2 + mask_bit
) {
591 case 32: // full colour
592 /* skip monochrome version of the cursor and decode RGBA instead */
593 bytestream2_skip(gb
, c
->cursor_h
* (FFALIGN(c
->cursor_w
, 32) >> 3));
594 for (j
= 0; j
< c
->cursor_h
; j
++) {
595 for (i
= 0; i
< c
->cursor_w
; i
++) {
596 int val
= bytestream2_get_be32(gb
);
605 return AVERROR_PATCHWELCOME
;
610 #define APPLY_ALPHA(src, new, alpha) \
611 src = (src * (256 - alpha) + new * alpha) >> 8
613 static void g2m_paint_cursor(G2MContext
*c
, uint8_t *dst
, int stride
)
617 const uint8_t *cursor
;
622 x
= c
->cursor_x
- c
->cursor_hot_x
;
623 y
= c
->cursor_y
- c
->cursor_hot_y
;
629 if (x
+ w
> c
->width
)
631 if (y
+ h
> c
->height
)
641 cursor
+= -y
* c
->cursor_stride
;
648 for (j
= 0; j
< h
; j
++) {
649 for (i
= 0; i
< w
; i
++) {
650 uint8_t alpha
= cursor
[i
* 4];
651 APPLY_ALPHA(dst
[i
* 3 + 0], cursor
[i
* 4 + 1], alpha
);
652 APPLY_ALPHA(dst
[i
* 3 + 1], cursor
[i
* 4 + 2], alpha
);
653 APPLY_ALPHA(dst
[i
* 3 + 2], cursor
[i
* 4 + 3], alpha
);
656 cursor
+= c
->cursor_stride
;
660 static int g2m_decode_frame(AVCodecContext
*avctx
, void *data
,
661 int *got_picture_ptr
, AVPacket
*avpkt
)
663 const uint8_t *buf
= avpkt
->data
;
664 int buf_size
= avpkt
->size
;
665 G2MContext
*c
= avctx
->priv_data
;
667 GetByteContext bc
, tbc
;
670 uint32_t chunk_size
, r_mask
, g_mask
, b_mask
;
671 int chunk_type
, chunk_start
;
676 av_log(avctx
, AV_LOG_ERROR
,
677 "Frame should have at least 12 bytes, got %d instead\n",
679 return AVERROR_INVALIDDATA
;
682 bytestream2_init(&bc
, buf
, buf_size
);
684 magic
= bytestream2_get_be32(&bc
);
685 if ((magic
& ~0xF) != MKBETAG('G', '2', 'M', '0') ||
686 (magic
& 0xF) < 2 || (magic
& 0xF) > 5) {
687 av_log(avctx
, AV_LOG_ERROR
, "Wrong magic %08X\n", magic
);
688 return AVERROR_INVALIDDATA
;
691 if ((magic
& 0xF) < 4) {
692 av_log(avctx
, AV_LOG_ERROR
, "G2M2 and G2M3 are not yet supported\n");
693 return AVERROR(ENOSYS
);
696 while (bytestream2_get_bytes_left(&bc
) > 5) {
697 chunk_size
= bytestream2_get_le32(&bc
) - 1;
698 chunk_type
= bytestream2_get_byte(&bc
);
699 chunk_start
= bytestream2_tell(&bc
);
700 if (chunk_size
> bytestream2_get_bytes_left(&bc
)) {
701 av_log(avctx
, AV_LOG_ERROR
, "Invalid chunk size %"PRIu32
" type %02X\n",
702 chunk_size
, chunk_type
);
705 switch (chunk_type
) {
709 if (chunk_size
< 21) {
710 av_log(avctx
, AV_LOG_ERROR
, "Invalid display info size %"PRIu32
"\n",
714 c
->width
= bytestream2_get_be32(&bc
);
715 c
->height
= bytestream2_get_be32(&bc
);
716 if (c
->width
< 16 || c
->width
> c
->orig_width
||
717 c
->height
< 16 || c
->height
> c
->orig_height
) {
718 av_log(avctx
, AV_LOG_ERROR
,
719 "Invalid frame dimensions %dx%d\n",
720 c
->width
, c
->height
);
721 ret
= AVERROR_INVALIDDATA
;
724 if (c
->width
!= avctx
->width
|| c
->height
!= avctx
->height
) {
725 ret
= ff_set_dimensions(avctx
, c
->width
, c
->height
);
729 c
->compression
= bytestream2_get_be32(&bc
);
730 if (c
->compression
!= 2 && c
->compression
!= 3) {
731 av_log(avctx
, AV_LOG_ERROR
,
732 "Unknown compression method %d\n",
734 ret
= AVERROR_PATCHWELCOME
;
737 c
->tile_width
= bytestream2_get_be32(&bc
);
738 c
->tile_height
= bytestream2_get_be32(&bc
);
739 if (c
->tile_width
<= 0 || c
->tile_height
<= 0 ||
740 ((c
->tile_width
| c
->tile_height
) & 0xF) ||
741 c
->tile_width
* 4LL * c
->tile_height
>= INT_MAX
743 av_log(avctx
, AV_LOG_ERROR
,
744 "Invalid tile dimensions %dx%d\n",
745 c
->tile_width
, c
->tile_height
);
746 ret
= AVERROR_INVALIDDATA
;
749 c
->tiles_x
= (c
->width
+ c
->tile_width
- 1) / c
->tile_width
;
750 c
->tiles_y
= (c
->height
+ c
->tile_height
- 1) / c
->tile_height
;
751 c
->bpp
= bytestream2_get_byte(&bc
);
753 if (bytestream2_get_bytes_left(&bc
) < 16 ||
754 (chunk_size
- 21) < 16) {
755 av_log(avctx
, AV_LOG_ERROR
,
756 "Display info: missing bitmasks!\n");
757 ret
= AVERROR_INVALIDDATA
;
760 r_mask
= bytestream2_get_be32(&bc
);
761 g_mask
= bytestream2_get_be32(&bc
);
762 b_mask
= bytestream2_get_be32(&bc
);
763 if (r_mask
!= 0xFF0000 || g_mask
!= 0xFF00 || b_mask
!= 0xFF) {
764 av_log(avctx
, AV_LOG_ERROR
,
765 "Invalid or unsupported bitmasks: R=%"PRIX32
", G=%"PRIX32
", B=%"PRIX32
"\n",
766 r_mask
, g_mask
, b_mask
);
767 ret
= AVERROR_PATCHWELCOME
;
771 avpriv_request_sample(avctx
, "bpp=%d", c
->bpp
);
772 ret
= AVERROR_PATCHWELCOME
;
775 if (g2m_init_buffers(c
)) {
776 ret
= AVERROR(ENOMEM
);
782 if (!c
->tiles_x
|| !c
->tiles_y
) {
783 av_log(avctx
, AV_LOG_WARNING
,
784 "No display info - skipping tile\n");
787 if (chunk_size
< 2) {
788 av_log(avctx
, AV_LOG_ERROR
, "Invalid tile data size %"PRIu32
"\n",
792 c
->tile_x
= bytestream2_get_byte(&bc
);
793 c
->tile_y
= bytestream2_get_byte(&bc
);
794 if (c
->tile_x
>= c
->tiles_x
|| c
->tile_y
>= c
->tiles_y
) {
795 av_log(avctx
, AV_LOG_ERROR
,
796 "Invalid tile pos %d,%d (in %dx%d grid)\n",
797 c
->tile_x
, c
->tile_y
, c
->tiles_x
, c
->tiles_y
);
801 switch (c
->compression
) {
803 av_log(avctx
, AV_LOG_ERROR
,
804 "ePIC j-b compression is not implemented yet\n");
805 return AVERROR(ENOSYS
);
806 case COMPR_KEMPF_J_B
:
807 ret
= kempf_decode_tile(c
, c
->tile_x
, c
->tile_y
,
808 buf
+ bytestream2_tell(&bc
),
812 if (ret
&& c
->framebuf
)
813 av_log(avctx
, AV_LOG_ERROR
, "Error decoding tile %d,%d\n",
814 c
->tile_x
, c
->tile_y
);
817 if (chunk_size
< 5) {
818 av_log(avctx
, AV_LOG_ERROR
, "Invalid cursor pos size %"PRIu32
"\n",
822 c
->cursor_x
= bytestream2_get_be16(&bc
);
823 c
->cursor_y
= bytestream2_get_be16(&bc
);
826 if (chunk_size
< 8) {
827 av_log(avctx
, AV_LOG_ERROR
, "Invalid cursor data size %"PRIu32
"\n",
831 bytestream2_init(&tbc
, buf
+ bytestream2_tell(&bc
),
833 g2m_load_cursor(avctx
, c
, &tbc
);
839 av_log(avctx
, AV_LOG_WARNING
, "Skipping chunk type %02d\n",
843 /* navigate to next chunk */
844 bytestream2_skip(&bc
, chunk_start
+ chunk_size
- bytestream2_tell(&bc
));
849 if (c
->width
&& c
->height
&& c
->framebuf
) {
850 if ((ret
= ff_get_buffer(avctx
, pic
, 0)) < 0)
853 pic
->key_frame
= got_header
;
854 pic
->pict_type
= got_header
? AV_PICTURE_TYPE_I
: AV_PICTURE_TYPE_P
;
856 for (i
= 0; i
< avctx
->height
; i
++)
857 memcpy(pic
->data
[0] + i
* pic
->linesize
[0],
858 c
->framebuf
+ i
* c
->framebuf_stride
,
860 g2m_paint_cursor(c
, pic
->data
[0], pic
->linesize
[0]);
862 *got_picture_ptr
= 1;
875 static av_cold
int g2m_decode_init(AVCodecContext
*avctx
)
877 G2MContext
*const c
= avctx
->priv_data
;
880 if ((ret
= jpg_init(avctx
, &c
->jc
)) != 0) {
881 av_log(avctx
, AV_LOG_ERROR
, "Cannot initialise VLCs\n");
882 jpg_free_context(&c
->jc
);
883 return AVERROR(ENOMEM
);
886 avctx
->pix_fmt
= AV_PIX_FMT_RGB24
;
888 // store original sizes and check against those if resize happens
889 c
->orig_width
= avctx
->width
;
890 c
->orig_height
= avctx
->height
;
895 static av_cold
int g2m_decode_end(AVCodecContext
*avctx
)
897 G2MContext
*const c
= avctx
->priv_data
;
899 jpg_free_context(&c
->jc
);
901 av_freep(&c
->kempf_buf
);
902 av_freep(&c
->kempf_flags
);
903 av_freep(&c
->synth_tile
);
904 av_freep(&c
->jpeg_tile
);
905 av_freep(&c
->cursor
);
906 av_freep(&c
->framebuf
);
911 AVCodec ff_g2m_decoder
= {
913 .long_name
= NULL_IF_CONFIG_SMALL("Go2Meeting"),
914 .type
= AVMEDIA_TYPE_VIDEO
,
915 .id
= AV_CODEC_ID_G2M
,
916 .priv_data_size
= sizeof(G2MContext
),
917 .init
= g2m_decode_init
,
918 .close
= g2m_decode_end
,
919 .decode
= g2m_decode_frame
,
920 .capabilities
= CODEC_CAP_DR1
,