Browse code

Go2Webinar decoder

Kostya Shishkov authored on 2013/02/26 05:38:25
Showing 10 changed files
... ...
@@ -23,6 +23,7 @@ version 10:
23 23
 - support for slice multithreading in libavfilter
24 24
 - VC-1 interlaced B-frame support
25 25
 - support for WavPack muxing (raw and in Matroska)
26
+- Go2Webinar decoder
26 27
 
27 28
 
28 29
 version 9:
... ...
@@ -1575,6 +1575,7 @@ flv_decoder_select="h263_decoder"
1575 1575
 flv_encoder_select="h263_encoder"
1576 1576
 fourxm_decoder_select="dsputil"
1577 1577
 fraps_decoder_select="dsputil huffman"
1578
+g2m_decoder_select="dsputil zlib"
1578 1579
 h261_decoder_select="error_resilience mpegvideo"
1579 1580
 h261_encoder_select="aandcttables mpegvideoenc"
1580 1581
 h263_decoder_select="error_resilience h263_parser mpegvideo"
... ...
@@ -507,6 +507,8 @@ following image formats are supported:
507 507
     @tab Sorenson H.263 used in Flash
508 508
 @item Forward Uncompressed   @tab     @tab  X
509 509
 @item Fraps                  @tab     @tab  X
510
+@item Go2Webinar             @tab     @tab  X
511
+    @tab fourcc: G2M4
510 512
 @item H.261                  @tab  X  @tab  X
511 513
 @item H.263 / H.263-1996     @tab  X  @tab  X
512 514
 @item H.263+ / H.263-1998 / H.263 version 2  @tab  X  @tab  X
... ...
@@ -177,6 +177,7 @@ OBJS-$(CONFIG_FLIC_DECODER)            += flicvideo.o
177 177
 OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
178 178
 OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o
179 179
 OBJS-$(CONFIG_FRWU_DECODER)            += frwu.o
180
+OBJS-$(CONFIG_G2M_DECODER)             += g2meet.o mjpeg.o
180 181
 OBJS-$(CONFIG_G723_1_DECODER)          += g723_1.o acelp_vectors.o \
181 182
                                           celp_filters.o
182 183
 OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
... ...
@@ -146,6 +146,7 @@ void avcodec_register_all(void)
146 146
     REGISTER_DECODER(FOURXM,            fourxm);
147 147
     REGISTER_DECODER(FRAPS,             fraps);
148 148
     REGISTER_DECODER(FRWU,              frwu);
149
+    REGISTER_DECODER(G2M,               g2m);
149 150
     REGISTER_ENCDEC (GIF,               gif);
150 151
     REGISTER_ENCDEC (H261,              h261);
151 152
     REGISTER_ENCDEC (H263,              h263);
... ...
@@ -270,6 +270,7 @@ enum AVCodecID {
270 270
     AV_CODEC_ID_VP9,
271 271
     AV_CODEC_ID_AIC,
272 272
     AV_CODEC_ID_ESCAPE130,
273
+    AV_CODEC_ID_G2M,
273 274
 
274 275
     /* various PCM "codecs" */
275 276
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
... ...
@@ -1221,6 +1221,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
1221 1221
         .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
1222 1222
         .props     = AV_CODEC_PROP_LOSSY,
1223 1223
     },
1224
+    {
1225
+        .id        = AV_CODEC_ID_G2M,
1226
+        .type      = AVMEDIA_TYPE_VIDEO,
1227
+        .name      = "g2m",
1228
+        .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"),
1229
+        .props     = AV_CODEC_PROP_LOSSY,
1230
+    },
1224 1231
 
1225 1232
     /* various PCM "codecs" */
1226 1233
     {
1227 1234
new file mode 100644
... ...
@@ -0,0 +1,825 @@
0
+/*
1
+ * Go2Webinar decoder
2
+ * Copyright (c) 2012 Konstantin Shishkov
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav 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
+ * Libav 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 Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * Go2Webinar decoder
24
+ */
25
+
26
+#include <zlib.h>
27
+
28
+#include "libavutil/intreadwrite.h"
29
+#include "avcodec.h"
30
+#include "bytestream.h"
31
+#include "dsputil.h"
32
+#include "get_bits.h"
33
+#include "internal.h"
34
+#include "mjpeg.h"
35
+
36
+enum ChunkType {
37
+    FRAME_INFO = 0xC8,
38
+    TILE_DATA,
39
+    CURSOR_POS,
40
+    CURSOR_SHAPE,
41
+    CHUNK_CC,
42
+    CHUNK_CD
43
+};
44
+
45
+enum Compression {
46
+    COMPR_EPIC_J_B = 2,
47
+    COMPR_KEMPF_J_B,
48
+};
49
+
50
+static const uint8_t luma_quant[64] = {
51
+     8,  6,  5,  8, 12, 20, 26, 31,
52
+     6,  6,  7, 10, 13, 29, 30, 28,
53
+     7,  7,  8, 12, 20, 29, 35, 28,
54
+     7,  9, 11, 15, 26, 44, 40, 31,
55
+     9, 11, 19, 28, 34, 55, 52, 39,
56
+    12, 18, 28, 32, 41, 52, 57, 46,
57
+    25, 32, 39, 44, 52, 61, 60, 51,
58
+    36, 46, 48, 49, 56, 50, 52, 50
59
+};
60
+
61
+static const uint8_t chroma_quant[64] = {
62
+     9,  9, 12, 24, 50, 50, 50, 50,
63
+     9, 11, 13, 33, 50, 50, 50, 50,
64
+    12, 13, 28, 50, 50, 50, 50, 50,
65
+    24, 33, 50, 50, 50, 50, 50, 50,
66
+    50, 50, 50, 50, 50, 50, 50, 50,
67
+    50, 50, 50, 50, 50, 50, 50, 50,
68
+    50, 50, 50, 50, 50, 50, 50, 50,
69
+    50, 50, 50, 50, 50, 50, 50, 50,
70
+};
71
+
72
+typedef struct JPGContext {
73
+    DSPContext dsp;
74
+    ScanTable  scantable;
75
+
76
+    VLC        dc_vlc[2], ac_vlc[2];
77
+    int        prev_dc[3];
78
+    DECLARE_ALIGNED(16, int16_t, block)[6][64];
79
+
80
+    uint8_t    *buf;
81
+} JPGContext;
82
+
83
+typedef struct G2MContext {
84
+    JPGContext jc;
85
+    int        version;
86
+
87
+    int        compression;
88
+    int        width, height, bpp;
89
+    int        tile_width, tile_height;
90
+    int        tiles_x, tiles_y, tile_x, tile_y;
91
+
92
+    int        got_header;
93
+
94
+    uint8_t    *framebuf;
95
+    int        framebuf_stride, old_width, old_height;
96
+
97
+    uint8_t    *synth_tile, *jpeg_tile;
98
+    int        tile_stride, old_tile_w, old_tile_h;
99
+
100
+    uint8_t    *kempf_buf, *kempf_flags;
101
+
102
+    uint8_t    *cursor;
103
+    int        cursor_stride;
104
+    int        cursor_fmt;
105
+    int        cursor_w, cursor_h, cursor_x, cursor_y;
106
+    int        cursor_hot_x, cursor_hot_y;
107
+} G2MContext;
108
+
109
+static av_cold int build_vlc(VLC *vlc, const uint8_t *bits_table,
110
+                             const uint8_t *val_table, int nb_codes,
111
+                             int is_ac)
112
+{
113
+    uint8_t  huff_size[256] = { 0 };
114
+    uint16_t huff_code[256];
115
+    uint16_t huff_sym[256];
116
+    int i;
117
+
118
+    ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
119
+
120
+    for (i = 0; i < 256; i++)
121
+        huff_sym[i] = i + 16 * is_ac;
122
+
123
+    if (is_ac)
124
+        huff_sym[0] = 16 * 256;
125
+
126
+    return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1,
127
+                              huff_code, 2, 2, huff_sym, 2, 2, 0);
128
+}
129
+
130
+static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c)
131
+{
132
+    int ret;
133
+
134
+    ret = build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance,
135
+                    avpriv_mjpeg_val_dc, 12, 0);
136
+    if (ret)
137
+        return ret;
138
+    ret = build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance,
139
+                    avpriv_mjpeg_val_dc, 12, 0);
140
+    if (ret)
141
+        return ret;
142
+    ret = build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance,
143
+                    avpriv_mjpeg_val_ac_luminance, 251, 1);
144
+    if (ret)
145
+        return ret;
146
+    ret = build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance,
147
+                    avpriv_mjpeg_val_ac_chrominance, 251, 1);
148
+    if (ret)
149
+        return ret;
150
+
151
+    ff_dsputil_init(&c->dsp, avctx);
152
+    ff_init_scantable(c->dsp.idct_permutation, &c->scantable,
153
+                      ff_zigzag_direct);
154
+
155
+    return 0;
156
+}
157
+
158
+static av_cold void jpg_free_context(JPGContext *ctx)
159
+{
160
+    int i;
161
+
162
+    for (i = 0; i < 2; i++) {
163
+        ff_free_vlc(&ctx->dc_vlc[i]);
164
+        ff_free_vlc(&ctx->ac_vlc[i]);
165
+    }
166
+
167
+    av_freep(&ctx->buf);
168
+}
169
+
170
+static void jpg_unescape(const uint8_t *src, int src_size,
171
+                         uint8_t *dst, int *dst_size)
172
+{
173
+    const uint8_t *src_end = src + src_size;
174
+    uint8_t *dst_start = dst;
175
+
176
+    while (src < src_end) {
177
+        uint8_t x = *src++;
178
+
179
+        *dst++ = x;
180
+
181
+        if (x == 0xFF && !*src)
182
+            src++;
183
+    }
184
+    *dst_size = dst - dst_start;
185
+}
186
+
187
+static int jpg_decode_block(JPGContext *c, GetBitContext *gb,
188
+                            int plane, int16_t *block)
189
+{
190
+    int dc, val, pos;
191
+    const int is_chroma = !!plane;
192
+    const uint8_t *qmat = is_chroma ? chroma_quant : luma_quant;
193
+
194
+    c->dsp.clear_block(block);
195
+    dc = get_vlc2(gb, c->dc_vlc[is_chroma].table, 9, 3);
196
+    if (dc < 0)
197
+        return AVERROR_INVALIDDATA;
198
+    if (dc)
199
+        dc = get_xbits(gb, dc);
200
+    dc = dc * qmat[0] + c->prev_dc[plane];
201
+    block[0] = dc;
202
+    c->prev_dc[plane] = dc;
203
+
204
+    pos = 0;
205
+    while (pos < 63) {
206
+        val = get_vlc2(gb, c->ac_vlc[is_chroma].table, 9, 3);
207
+        if (val < 0)
208
+            return AVERROR_INVALIDDATA;
209
+        pos += val >> 4;
210
+        val &= 0xF;
211
+        if (pos > 63)
212
+            return val ? AVERROR_INVALIDDATA : 0;
213
+        if (val) {
214
+            int nbits = val;
215
+
216
+            val = get_xbits(gb, nbits);
217
+            val *= qmat[ff_zigzag_direct[pos]];
218
+            block[c->scantable.permutated[pos]] = val;
219
+        }
220
+    }
221
+    return 0;
222
+}
223
+
224
+static inline void yuv2rgb(uint8_t *out, int Y, int U, int V)
225
+{
226
+    out[0] = av_clip_uint8(Y + (             91881 * V + 32768 >> 16));
227
+    out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
228
+    out[2] = av_clip_uint8(Y + (116130 * U             + 32768 >> 16));
229
+}
230
+
231
+static int jpg_decode_data(JPGContext *c, int width, int height,
232
+                           const uint8_t *src, int src_size,
233
+                           uint8_t *dst, int dst_stride,
234
+                           const uint8_t *mask, int mask_stride, int num_mbs,
235
+                           int swapuv)
236
+{
237
+    GetBitContext gb;
238
+    uint8_t *tmp;
239
+    int mb_w, mb_h, mb_x, mb_y, i, j;
240
+    int bx, by;
241
+    int unesc_size;
242
+    int ret;
243
+
244
+    tmp = av_realloc(c->buf, src_size + FF_INPUT_BUFFER_PADDING_SIZE);
245
+    if (!tmp)
246
+        return AVERROR(ENOMEM);
247
+    c->buf = tmp;
248
+    jpg_unescape(src, src_size, c->buf, &unesc_size);
249
+    memset(c->buf + unesc_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
250
+    init_get_bits(&gb, c->buf, unesc_size * 8);
251
+
252
+    width = FFALIGN(width, 16);
253
+    mb_w  =  width        >> 4;
254
+    mb_h  = (height + 15) >> 4;
255
+
256
+    if (!num_mbs)
257
+        num_mbs = mb_w * mb_h;
258
+
259
+    for (i = 0; i < 3; i++)
260
+        c->prev_dc[i] = 1024;
261
+    bx = by = 0;
262
+    for (mb_y = 0; mb_y < mb_h; mb_y++) {
263
+        for (mb_x = 0; mb_x < mb_w; mb_x++) {
264
+            if (mask && !mask[mb_x]) {
265
+                bx += 16;
266
+                continue;
267
+            }
268
+            for (j = 0; j < 2; j++) {
269
+                for (i = 0; i < 2; i++) {
270
+                    if ((ret = jpg_decode_block(c, &gb, 0,
271
+                                                c->block[i + j * 2])) != 0)
272
+                        return ret;
273
+                    c->dsp.idct(c->block[i + j * 2]);
274
+                }
275
+            }
276
+            for (i = 1; i < 3; i++) {
277
+                if ((ret = jpg_decode_block(c, &gb, i, c->block[i + 3])) != 0)
278
+                    return ret;
279
+                c->dsp.idct(c->block[i + 3]);
280
+            }
281
+
282
+            for (j = 0; j < 16; j++) {
283
+                uint8_t *out = dst + bx * 3 + (by + j) * dst_stride;
284
+                for (i = 0; i < 16; i++) {
285
+                    int Y, U, V;
286
+
287
+                    Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8];
288
+                    U = c->block[4 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
289
+                    V = c->block[5 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
290
+                    yuv2rgb(out + i * 3, Y, U, V);
291
+                }
292
+            }
293
+
294
+            if (!--num_mbs)
295
+                return 0;
296
+            bx += 16;
297
+        }
298
+        bx  = 0;
299
+        by += 16;
300
+        if (mask)
301
+            mask += mask_stride;
302
+    }
303
+
304
+    return 0;
305
+}
306
+
307
+static void kempf_restore_buf(const uint8_t *src, int len,
308
+                              uint8_t *dst, int stride,
309
+                              const uint8_t *jpeg_tile, int tile_stride,
310
+                              int width, int height,
311
+                              const uint8_t *pal, int npal, int tidx)
312
+{
313
+    GetBitContext gb;
314
+    int i, j, nb, col;
315
+
316
+    init_get_bits(&gb, src, len * 8);
317
+
318
+    if (npal <= 2)       nb = 1;
319
+    else if (npal <= 4)  nb = 2;
320
+    else if (npal <= 16) nb = 4;
321
+    else                 nb = 8;
322
+
323
+    for (j = 0; j < height; j++, dst += stride, jpeg_tile += tile_stride) {
324
+        if (get_bits(&gb, 8))
325
+            continue;
326
+        for (i = 0; i < width; i++) {
327
+            col = get_bits(&gb, nb);
328
+            if (col != tidx)
329
+                memcpy(dst + i * 3, pal + col * 3, 3);
330
+            else
331
+                memcpy(dst + i * 3, jpeg_tile + i * 3, 3);
332
+        }
333
+    }
334
+}
335
+
336
+static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y,
337
+                             const uint8_t *src, int src_size)
338
+{
339
+    int width, height;
340
+    int hdr, zsize, npal, tidx = -1, ret;
341
+    int i, j;
342
+    const uint8_t *src_end = src + src_size;
343
+    uint8_t pal[768], transp[3];
344
+    uLongf dlen = (c->tile_width + 1) * c->tile_height;
345
+    int sub_type;
346
+    int nblocks, cblocks, bstride;
347
+    int bits, bitbuf, coded;
348
+    uint8_t *dst = c->framebuf + tile_x * c->tile_width * 3 +
349
+                   tile_y * c->tile_height * c->framebuf_stride;
350
+
351
+    if (src_size < 2)
352
+        return AVERROR_INVALIDDATA;
353
+
354
+    width  = FFMIN(c->width  - tile_x * c->tile_width,  c->tile_width);
355
+    height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height);
356
+
357
+    hdr = *src++;
358
+    sub_type = hdr >> 5;
359
+    if (sub_type == 0) {
360
+        int j;
361
+        memcpy(transp, src, 3);
362
+        src += 3;
363
+        for (j = 0; j < height; j++, dst += c->framebuf_stride)
364
+            for (i = 0; i < width; i++)
365
+                memcpy(dst + i * 3, transp, 3);
366
+        return 0;
367
+    } else if (sub_type == 1) {
368
+        return jpg_decode_data(&c->jc, width, height, src, src_end - src,
369
+                               dst, c->framebuf_stride, NULL, 0, 0, 0);
370
+    }
371
+
372
+    if (sub_type != 2) {
373
+        memcpy(transp, src, 3);
374
+        src += 3;
375
+    }
376
+    npal = *src++ + 1;
377
+    memcpy(pal, src, npal * 3); src += npal * 3;
378
+    if (sub_type != 2) {
379
+        for (i = 0; i < npal; i++) {
380
+            if (!memcmp(pal + i * 3, transp, 3)) {
381
+               tidx = i;
382
+               break;
383
+            }
384
+        }
385
+    }
386
+
387
+    if (src_end - src < 2)
388
+        return 0;
389
+    zsize = (src[0] << 8) | src[1]; src += 2;
390
+
391
+    if (src_end - src < zsize)
392
+        return AVERROR_INVALIDDATA;
393
+
394
+    ret = uncompress(c->kempf_buf, &dlen, src, zsize);
395
+    if (ret)
396
+        return AVERROR_INVALIDDATA;
397
+    src += zsize;
398
+
399
+    if (sub_type == 2) {
400
+        kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,
401
+                          NULL, 0, width, height, pal, npal, tidx);
402
+        return 0;
403
+    }
404
+
405
+    nblocks = *src++ + 1;
406
+    cblocks = 0;
407
+    bstride = FFALIGN(width, 16) >> 4;
408
+    // blocks are coded LSB and we need normal bitreader for JPEG data
409
+    bits = 0;
410
+    for (i = 0; i < (FFALIGN(height, 16) >> 4); i++) {
411
+        for (j = 0; j < (FFALIGN(width, 16) >> 4); j++) {
412
+            if (!bits) {
413
+                bitbuf = *src++;
414
+                bits   = 8;
415
+            }
416
+            coded = bitbuf & 1;
417
+            bits--;
418
+            bitbuf >>= 1;
419
+            cblocks += coded;
420
+            if (cblocks > nblocks)
421
+                return AVERROR_INVALIDDATA;
422
+            c->kempf_flags[j + i * bstride] = coded;
423
+        }
424
+    }
425
+
426
+    memset(c->jpeg_tile, 0, c->tile_stride * height);
427
+    jpg_decode_data(&c->jc, width, height, src, src_end - src,
428
+                    c->jpeg_tile, c->tile_stride,
429
+                    c->kempf_flags, bstride, nblocks, 0);
430
+
431
+    kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,
432
+                      c->jpeg_tile, c->tile_stride,
433
+                      width, height, pal, npal, tidx);
434
+
435
+    return 0;
436
+}
437
+
438
+static int g2m_init_buffers(G2MContext *c)
439
+{
440
+    int aligned_height;
441
+
442
+    if (!c->framebuf || c->old_width < c->width || c->height < c->height) {
443
+        c->framebuf_stride = FFALIGN(c->width * 3, 16);
444
+        aligned_height     = FFALIGN(c->height,    16);
445
+        av_free(c->framebuf);
446
+        c->framebuf = av_mallocz(c->framebuf_stride * aligned_height);
447
+        if (!c->framebuf)
448
+            return AVERROR(ENOMEM);
449
+    }
450
+    if (!c->synth_tile || !c->jpeg_tile ||
451
+        c->old_tile_w < c->tile_width ||
452
+        c->old_tile_h < c->tile_height) {
453
+        c->tile_stride = FFALIGN(c->tile_width * 3, 16);
454
+        aligned_height = FFALIGN(c->tile_height,    16);
455
+        av_free(c->synth_tile);
456
+        av_free(c->jpeg_tile);
457
+        c->synth_tile  = av_mallocz(c->tile_stride      * aligned_height);
458
+        c->jpeg_tile   = av_mallocz(c->tile_stride      * aligned_height);
459
+        c->kempf_buf   = av_mallocz((c->tile_width + 1) * aligned_height
460
+                                    + FF_INPUT_BUFFER_PADDING_SIZE);
461
+        c->kempf_flags = av_mallocz( c->tile_width      * aligned_height);
462
+        if (!c->synth_tile || !c->jpeg_tile ||
463
+            !c->kempf_buf || !c->kempf_flags)
464
+            return AVERROR(ENOMEM);
465
+    }
466
+
467
+    return 0;
468
+}
469
+
470
+static int g2m_load_cursor(G2MContext *c, GetByteContext *gb)
471
+{
472
+    int i, j, k;
473
+    uint8_t *dst;
474
+    uint32_t bits;
475
+
476
+    c->cursor_stride = c->cursor_w * 4;
477
+    c->cursor        = av_realloc(c->cursor, c->cursor_stride * c->cursor_h);
478
+    if (!c->cursor)
479
+        return AVERROR(ENOMEM);
480
+
481
+    dst = c->cursor;
482
+    switch (c->cursor_fmt) {
483
+    case 1: // old monochrome
484
+        for (j = 0; j < c->cursor_h; j++) {
485
+            for (i = 0; i < c->cursor_w; i += 32) {
486
+                bits = bytestream2_get_be32(gb);
487
+                for (k = 0; k < 32; k++) {
488
+                    dst[0] = !!(bits & 0x80000000);
489
+                    dst += 4;
490
+                    bits <<= 1;
491
+                }
492
+            }
493
+        }
494
+
495
+        dst = c->cursor;
496
+        for (j = 0; j < c->cursor_h; j++) {
497
+            for (i = 0; i < c->cursor_w; i += 32) {
498
+                bits = bytestream2_get_be32(gb);
499
+                for (k = 0; k < 32; k++) {
500
+                    int mask_bit = !!(bits & 0x80000000);
501
+                    switch (dst[0] * 2 + mask_bit) {
502
+                    case 0:
503
+                        dst[0] = 0xFF; dst[1] = 0x00;
504
+                        dst[2] = 0x00; dst[3] = 0x00;
505
+                        break;
506
+                    case 1:
507
+                        dst[0] = 0xFF; dst[1] = 0xFF;
508
+                        dst[2] = 0xFF; dst[3] = 0xFF;
509
+                        break;
510
+                    default:
511
+                        dst[0] = 0x00; dst[1] = 0x00;
512
+                        dst[2] = 0x00; dst[3] = 0x00;
513
+                    }
514
+                    dst += 4;
515
+                    bits <<= 1;
516
+                }
517
+            }
518
+        }
519
+        break;
520
+    case 32: // full colour
521
+        /* skip monochrome version of the cursor and decode RGBA instead */
522
+        bytestream2_skip(gb, c->cursor_h * (FFALIGN(c->cursor_w, 32) >> 3));
523
+        for (j = 0; j < c->cursor_h; j++) {
524
+            for (i = 0; i < c->cursor_w; i++) {
525
+                int val = bytestream2_get_be32(gb);
526
+                *dst++ = val >>  0;
527
+                *dst++ = val >>  8;
528
+                *dst++ = val >> 16;
529
+                *dst++ = val >> 24;
530
+            }
531
+        }
532
+        break;
533
+    default:
534
+        return AVERROR_PATCHWELCOME;
535
+    }
536
+    return 0;
537
+}
538
+
539
+#define APPLY_ALPHA(src, new, alpha) \
540
+    src = (src * (256 - alpha) + new * alpha) >> 8
541
+
542
+static void g2m_paint_cursor(G2MContext *c, uint8_t *dst, int stride)
543
+{
544
+    int i, j;
545
+    int x, y, w, h;
546
+    const uint8_t *cursor;
547
+
548
+    if (!c->cursor)
549
+        return;
550
+
551
+    x = c->cursor_x - c->cursor_hot_x;
552
+    y = c->cursor_y - c->cursor_hot_y;
553
+
554
+    cursor = c->cursor;
555
+    w      = c->cursor_w;
556
+    h      = c->cursor_h;
557
+
558
+    if (x + w > c->width)
559
+        w = c->width - x;
560
+    if (y + h > c->height)
561
+        h = c->height - y;
562
+    if (x < 0) {
563
+        w      +=  x;
564
+        cursor += -x * 4;
565
+    } else {
566
+        dst    +=  x * 3;
567
+    }
568
+    if (y < 0) {
569
+        h      +=  y;
570
+        cursor += -y * c->cursor_stride;
571
+    } else {
572
+        dst    +=  y * stride;
573
+    }
574
+    if (w < 0 || h < 0)
575
+        return;
576
+
577
+    for (j = 0; j < h; j++) {
578
+        for (i = 0; i < w; i++) {
579
+            uint8_t alpha = cursor[i * 4];
580
+            APPLY_ALPHA(dst[i * 3 + 0], cursor[i * 4 + 1], alpha);
581
+            APPLY_ALPHA(dst[i * 3 + 1], cursor[i * 4 + 2], alpha);
582
+            APPLY_ALPHA(dst[i * 3 + 2], cursor[i * 4 + 3], alpha);
583
+        }
584
+        dst    += stride;
585
+        cursor += c->cursor_stride;
586
+    }
587
+}
588
+
589
+static int g2m_decode_frame(AVCodecContext *avctx, void *data,
590
+                            int *got_picture_ptr, AVPacket *avpkt)
591
+{
592
+    const uint8_t *buf = avpkt->data;
593
+    int buf_size = avpkt->size;
594
+    G2MContext *c = avctx->priv_data;
595
+    AVFrame *pic = data;
596
+    GetByteContext bc, tbc;
597
+    int magic;
598
+    int got_header = 0;
599
+    uint32_t chunk_size, cur_size;
600
+    int chunk_type;
601
+    int i;
602
+    int ret;
603
+
604
+    if (buf_size < 12) {
605
+        av_log(avctx, AV_LOG_ERROR,
606
+               "Frame should have at least 12 bytes, got %d instead\n",
607
+               buf_size);
608
+        return AVERROR_INVALIDDATA;
609
+    }
610
+
611
+    bytestream2_init(&bc, buf, buf_size);
612
+
613
+    magic = bytestream2_get_be32(&bc);
614
+    if ((magic & ~0xF) != MKBETAG('G', '2', 'M', '0') ||
615
+        (magic & 0xF) < 2 || (magic & 0xF) > 4) {
616
+        av_log(avctx, AV_LOG_ERROR, "Wrong magic %08X\n", magic);
617
+        return AVERROR_INVALIDDATA;
618
+    }
619
+
620
+    if ((magic & 0xF) != 4) {
621
+        av_log(avctx, AV_LOG_ERROR, "G2M2 and G2M3 are not yet supported\n");
622
+        return AVERROR(ENOSYS);
623
+    }
624
+
625
+    while (bytestream2_get_bytes_left(&bc) > 5) {
626
+        chunk_size = bytestream2_get_le32(&bc) - 1;
627
+        chunk_type = bytestream2_get_byte(&bc);
628
+        if (chunk_size > bytestream2_get_bytes_left(&bc)) {
629
+            av_log(avctx, AV_LOG_ERROR, "Invalid chunk size %d type %02X\n",
630
+                   chunk_size, chunk_type);
631
+            break;
632
+        }
633
+        switch (chunk_type) {
634
+        case FRAME_INFO:
635
+            c->got_header = 0;
636
+            if (chunk_size < 21) {
637
+                av_log(avctx, AV_LOG_ERROR, "Invalid frame info size %d\n",
638
+                       chunk_size);
639
+                break;
640
+            }
641
+            c->width  = bytestream2_get_be32(&bc);
642
+            c->height = bytestream2_get_be32(&bc);
643
+            if (c->width  < 16 || c->width  > avctx->width ||
644
+                c->height < 16 || c->height > avctx->height) {
645
+                av_log(avctx, AV_LOG_ERROR,
646
+                       "Invalid frame dimensions %dx%d\n",
647
+                       c->width, c->height);
648
+                c->width = c->height = 0;
649
+                bytestream2_skip(&bc, bytestream2_get_bytes_left(&bc));
650
+            }
651
+            if (c->width != avctx->width || c->height != avctx->height)
652
+                avcodec_set_dimensions(avctx, c->width, c->height);
653
+            c->compression = bytestream2_get_be32(&bc);
654
+            if (c->compression != 2 && c->compression != 3) {
655
+                av_log(avctx, AV_LOG_ERROR,
656
+                       "Unknown compression method %d\n",
657
+                       c->compression);
658
+                return AVERROR_PATCHWELCOME;
659
+            }
660
+            c->tile_width  = bytestream2_get_be32(&bc);
661
+            c->tile_height = bytestream2_get_be32(&bc);
662
+            if (!c->tile_width || !c->tile_height) {
663
+                av_log(avctx, AV_LOG_ERROR,
664
+                       "Invalid tile dimensions %dx%d\n",
665
+                       c->tile_width, c->tile_height);
666
+                return AVERROR_INVALIDDATA;
667
+            }
668
+            c->tiles_x = (c->width  + c->tile_width  - 1) / c->tile_width;
669
+            c->tiles_y = (c->height + c->tile_height - 1) / c->tile_height;
670
+            c->bpp = bytestream2_get_byte(&bc);
671
+            chunk_size -= 21;
672
+            bytestream2_skip(&bc, chunk_size);
673
+            if (g2m_init_buffers(c))
674
+                return AVERROR(ENOMEM);
675
+            got_header = 1;
676
+            break;
677
+        case TILE_DATA:
678
+            if (!c->tiles_x || !c->tiles_y) {
679
+                av_log(avctx, AV_LOG_WARNING,
680
+                       "No frame header - skipping tile\n");
681
+                bytestream2_skip(&bc, bytestream2_get_bytes_left(&bc));
682
+                break;
683
+            }
684
+            if (chunk_size < 2) {
685
+                av_log(avctx, AV_LOG_ERROR, "Invalid tile data size %d\n",
686
+                       chunk_size);
687
+                break;
688
+            }
689
+            c->tile_x = bytestream2_get_byte(&bc);
690
+            c->tile_y = bytestream2_get_byte(&bc);
691
+            if (c->tile_x >= c->tiles_x || c->tile_y >= c->tiles_y) {
692
+                av_log(avctx, AV_LOG_ERROR,
693
+                       "Invalid tile pos %d,%d (in %dx%d grid)\n",
694
+                       c->tile_x, c->tile_y, c->tiles_x, c->tiles_y);
695
+                break;
696
+            }
697
+            chunk_size -= 2;
698
+            ret = 0;
699
+            switch (c->compression) {
700
+            case COMPR_EPIC_J_B:
701
+                av_log(avctx, AV_LOG_ERROR,
702
+                       "ePIC j-b compression is not implemented yet\n");
703
+                return AVERROR(ENOSYS);
704
+            case COMPR_KEMPF_J_B:
705
+                ret = kempf_decode_tile(c, c->tile_x, c->tile_y,
706
+                                        buf + bytestream2_tell(&bc),
707
+                                        chunk_size);
708
+                break;
709
+            }
710
+            if (ret && c->framebuf)
711
+                av_log(avctx, AV_LOG_ERROR, "Error decoding tile %d,%d\n",
712
+                       c->tile_x, c->tile_y);
713
+            bytestream2_skip(&bc, chunk_size);
714
+            break;
715
+        case CURSOR_POS:
716
+            if (chunk_size < 5) {
717
+                av_log(avctx, AV_LOG_ERROR, "Invalid cursor pos size %d\n",
718
+                       chunk_size);
719
+                break;
720
+            }
721
+            c->cursor_x = bytestream2_get_be16(&bc);
722
+            c->cursor_y = bytestream2_get_be16(&bc);
723
+            bytestream2_skip(&bc, chunk_size - 4);
724
+            break;
725
+        case CURSOR_SHAPE:
726
+            if (chunk_size < 8) {
727
+                av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n",
728
+                       chunk_size);
729
+                break;
730
+            }
731
+            bytestream2_init(&tbc, buf + bytestream2_tell(&bc),
732
+                             chunk_size - 4);
733
+            cur_size        = bytestream2_get_be32(&tbc);
734
+            c->cursor_w     = bytestream2_get_byte(&tbc);
735
+            c->cursor_h     = bytestream2_get_byte(&tbc);
736
+            c->cursor_hot_x = bytestream2_get_byte(&tbc);
737
+            c->cursor_hot_y = bytestream2_get_byte(&tbc);
738
+            c->cursor_fmt   = bytestream2_get_byte(&tbc);
739
+            if (cur_size >= chunk_size ||
740
+                c->cursor_w * c->cursor_h / 4 > cur_size) {
741
+                av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n",
742
+                       chunk_size);
743
+                break;
744
+            }
745
+            g2m_load_cursor(c, &tbc);
746
+            bytestream2_skip(&bc, chunk_size);
747
+            break;
748
+        case CHUNK_CC:
749
+        case CHUNK_CD:
750
+            bytestream2_skip(&bc, chunk_size);
751
+            break;
752
+        default:
753
+            av_log(avctx, AV_LOG_WARNING, "Skipping chunk type %02X\n",
754
+                   chunk_type);
755
+            bytestream2_skip(&bc, chunk_size);
756
+        }
757
+    }
758
+    if (got_header)
759
+        c->got_header = 1;
760
+
761
+    if (c->width && c->height) {
762
+        if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) {
763
+            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
764
+            return ret;
765
+        }
766
+
767
+        pic->key_frame = got_header;
768
+        pic->pict_type = got_header ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
769
+
770
+        for (i = 0; i < avctx->height; i++)
771
+            memcpy(pic->data[0] + i * pic->linesize[0],
772
+                   c->framebuf  + i * c->framebuf_stride,
773
+                   c->width * 3);
774
+        g2m_paint_cursor(c, pic->data[0], pic->linesize[0]);
775
+
776
+        *got_picture_ptr = 1;
777
+    }
778
+
779
+    return buf_size;
780
+}
781
+
782
+static av_cold int g2m_decode_init(AVCodecContext *avctx)
783
+{
784
+    G2MContext * const c = avctx->priv_data;
785
+    int ret;
786
+
787
+    if ((ret = jpg_init(avctx, &c->jc)) != 0) {
788
+        av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n");
789
+        jpg_free_context(&c->jc);
790
+        return AVERROR(ENOMEM);
791
+    }
792
+
793
+    avctx->pix_fmt     = PIX_FMT_RGB24;
794
+
795
+    return 0;
796
+}
797
+
798
+static av_cold int g2m_decode_end(AVCodecContext *avctx)
799
+{
800
+    G2MContext * const c = avctx->priv_data;
801
+
802
+    jpg_free_context(&c->jc);
803
+
804
+    av_freep(&c->kempf_buf);
805
+    av_freep(&c->kempf_flags);
806
+    av_freep(&c->synth_tile);
807
+    av_freep(&c->jpeg_tile);
808
+    av_freep(&c->cursor);
809
+    av_freep(&c->framebuf);
810
+
811
+    return 0;
812
+}
813
+
814
+AVCodec ff_g2m_decoder = {
815
+    .name           = "g2m",
816
+    .long_name      = NULL_IF_CONFIG_SMALL("Go2Meeting"),
817
+    .type           = AVMEDIA_TYPE_VIDEO,
818
+    .id             = AV_CODEC_ID_G2M,
819
+    .priv_data_size = sizeof(G2MContext),
820
+    .init           = g2m_decode_init,
821
+    .close          = g2m_decode_end,
822
+    .decode         = g2m_decode_frame,
823
+    .capabilities   = CODEC_CAP_DR1,
824
+};
... ...
@@ -27,8 +27,8 @@
27 27
  */
28 28
 
29 29
 #define LIBAVCODEC_VERSION_MAJOR 55
30
-#define LIBAVCODEC_VERSION_MINOR  7
31
-#define LIBAVCODEC_VERSION_MICRO  2
30
+#define LIBAVCODEC_VERSION_MINOR  8
31
+#define LIBAVCODEC_VERSION_MICRO  0
32 32
 
33 33
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
34 34
                                                LIBAVCODEC_VERSION_MINOR, \
... ...
@@ -312,6 +312,9 @@ const AVCodecTag ff_codec_bmp_tags[] = {
312 312
     { AV_CODEC_ID_CLLC,         MKTAG('C', 'L', 'L', 'C') },
313 313
     { AV_CODEC_ID_MSS2,         MKTAG('M', 'S', 'S', '2') },
314 314
     { AV_CODEC_ID_SVQ3,         MKTAG('S', 'V', 'Q', '3') },
315
+    { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '2') },
316
+    { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '3') },
317
+    { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '4') },
315 318
     { AV_CODEC_ID_NONE,         0 }
316 319
 };
317 320