Merge commit '2d66a58ccde05e764594bd7e5f0f9244634d0b2c'
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 3 Jun 2013 10:42:31 +0000 (12:42 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 3 Jun 2013 10:47:26 +0000 (12:47 +0200)
* commit '2d66a58ccde05e764594bd7e5f0f9244634d0b2c':
  Go2Webinar decoder

Conflicts:
Changelog
configure
libavcodec/avcodec.h
libavcodec/codec_desc.c
libavcodec/version.h
libavformat/riff.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Changelog
configure
doc/general.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/codec_desc.c
libavcodec/g2meet.c
libavcodec/utils.c
libavcodec/version.h
libavformat/riff.c

diff --cc Changelog
+++ b/Changelog
  Entries are sorted chronologically from oldest to youngest within each release,
  releases are sorted from youngest to oldest.
  
 -version 10:
 -- av_strnstr
 -- support ID3v2 tags in ASF files
 +version <next>:
 +- curves filter
  - reference-counting for AVFrame and AVPacket data
 -- avconv now fails when input options are used for output file
 +- ffmpeg now fails when input options are used for output file
    or vice versa
 -- new avconv options -filter_script and -filter_complex_script, which allow a
 +- support for Monkey's Audio versions from 3.93
 +- perms and aperms filters
 +- audio filtering support in ffplay
 +- 10% faster aac encoding on x86 and MIPS
 +- sine audio filter source
 +- WebP demuxing and decoding support
 +- new ffmpeg options -filter_script and -filter_complex_script, which allow a
    filtergraph description to be read from a file
 +- OpenCL support
 +- audio phaser filter
 +- separatefields filter
 +- libquvi demuxer
  - uniform options syntax across all filters
 +- telecine filter
  - new interlace filter
 -- JPEG 2000 decoder
 -- new asetpts filter (same as setpts, but for audio)
 -- new trim and atrim filters
 -- avconv -t and -ss (output-only) options are now sample-accurate when
 +- smptehdbars source
 +- inverse telecine filters (fieldmatch and decimate)
 +- colorbalance filter
 +- colorchannelmixer filter
 +- The matroska demuxer can now output proper verbatim ASS packets. It will
 +  become the default at the next libavformat major bump.
 +- decent native animated GIF encoding
 +- asetrate filter
 +- interleave filter
 +- timeline editing with filters
 +- vidstabdetect and vidstabtransform filters for video stabilization using
 +  the vid.stab library
 +- astats filter
 +- trim and atrim filters
 +- ffmpeg -t and -ss (output-only) options are now sample-accurate when
    transcoding audio
  - Matroska muxer can now put the index at the beginning of the file.
 -- avconv -deinterlace option removed, the yadif filter should be used instead
 +- extractplanes filter
 +- avectorscope filter
 +- ADPCM DTK decoder
 +- ADP demuxer
 +- RSD demuxer
 +- RedSpark demuxer
 +- ADPCM IMA Radical decoder
 +- zmq filters
 +- DCT denoiser filter (dctdnoiz)
 +- Wavelet denoiser filter ported from libmpcodecs as owdenoise (formerly "ow")
  - Apple Intermediate Codec decoder
  - Escape 130 video decoder
 +- FTP protocol support
 +- V4L2 output device
 +- 3D LUT filter (lut3d)
 +- SMPTE 302M audio encoder
  - support for slice multithreading in libavfilter
 +- Hald CLUT support (generation and filtering)
  - VC-1 interlaced B-frame support
  - support for WavPack muxing (raw and in Matroska)
 +- XVideo output device
 +- vignette filter
 +- True Audio (TTA) encoder
+ - Go2Webinar decoder
  
  
 -version 9:
 -- av_basename and av_dirname
 -- adobe and limelight publisher authentication in RTMP
 +version 1.2:
 +
  - VDPAU hardware acceleration through normal hwaccel
  - SRTP support
 -
 -
 -version 9_beta3:
 -- ashowinfo audio filter
 +- Error diffusion dither in Swscale
 +- Chained Ogg support
 +- Theora Midstream reconfiguration support
 +- EVRC decoder
 +- audio fade filter
 +- filtering audio with unknown channel layout
 +- allpass, bass, bandpass, bandreject, biquad, equalizer, highpass, lowpass
 +  and treble audio filter
 +- improved showspectrum filter, with multichannel support and sox-like colors
 +- histogram filter
 +- tee muxer
 +- il filter ported from libmpcodecs
 +- support ID3v2 tags in ASF files
 +- encrypted TTA stream decoding support
 +- RF64 support in WAV muxer
 +- noise filter ported from libmpcodecs
 +- Subtitles character encoding conversion
 +- blend filter
 +- stereo3d filter ported from libmpcodecs
 +
 +
 +version 1.1:
 +
 +- stream disposition information printing in ffprobe
 +- filter for loudness analysis following EBU R128
 +- Opus encoder using libopus
 +- ffprobe -select_streams option
 +- Pinnacle TARGA CineWave YUV16 decoder
 +- TAK demuxer, decoder and parser
 +- DTS-HD demuxer
 +- remove -same_quant, it hasn't worked for years
 +- FFM2 support
 +- X-Face image encoder and decoder
  - 24-bit FLAC encoding
 -- audio volume filter
 -- deprecated the avconv -vol option. the volume filter is to be used instead.
  - multi-channel ALAC encoding up to 7.1
 -- TAK demuxer, parser, and decoder
 -- adaptive frame-level multithreading for H.264
 -
 -
 -version 9_beta2:
  - metadata (INFO tag) support in WAV muxer
 +- subtitles raw text decoder
  - support for building DLLs using MSVC
 -- remove avserver daemon mode
 +- LVF demuxer
 +- ffescape tool
 +- metadata (info chunk) support in CAF muxer
 +- field filter ported from libmpcodecs
 +- AVR demuxer
 +- geq filter ported from libmpcodecs
 +- remove ffserver daemon mode
 +- AST muxer/demuxer
 +- new expansion syntax for drawtext
 +- BRender PIX image decoder
 +- ffprobe -show_entries option
 +- ffprobe -sections option
 +- ADPCM IMA Dialogic decoder
 +- BRSTM demuxer
 +- animated GIF decoder and demuxer
 +- PVF demuxer
 +- subtitles filter
 +- IRCAM muxer/demuxer
 +- Paris Audio File demuxer
 +- Virtual concatenation demuxer
 +- VobSub demuxer
 +- JSON captions for TED talks decoding support
 +- SOX Resampler support in libswresample
 +- aselect filter
 +- SGI RLE 8-bit decoder
 +- Silicon Graphics Motion Video Compressor 1 & 2 decoder
 +- Silicon Graphics Movie demuxer
 +- apad filter
 +- Resolution & pixel format change support with multithreading for H.264
 +- documentation split into per-component manuals
 +- pp (postproc) filter ported from MPlayer
 +- NIST Sphere demuxer
 +- MPL2, VPlayer, MPlayer, AQTitle, PJS and SubViewer v1 subtitles demuxers and decoders
 +- Sony Wave64 muxer
 +- adobe and limelight publisher authentication in RTMP
 +- data: URI scheme
  - support building on the Plan 9 operating system
 -- ffv1: support version 1.3
 +- kerndeint filter ported from MPlayer
 +- histeq filter ported from VirtualDub
 +- Megalux Frame demuxer
 +- 012v decoder
 +- Improved AVC Intra decoding support
  
  
 -version 9_beta1:
 +version 1.0:
  
 -- XWD encoder and decoder
 -- Support for fragmentation in the mov/mp4 muxer
 -- ISMV (Smooth Streaming) muxer
 -- CDXL demuxer and decoder
 -- Apple ProRes encoder
 -- Sun Rasterfile Encoder
 -- remove libpostproc
 -- ID3v2 attached pictures reading and writing
 -- WMA Lossless decoder
 -- XBM encoder
 -- RealAudio Lossless decoder
 -- ZeroCodec decoder
 -- drop support for avconv without libavfilter
 -- add libavresample audio conversion library
 -- audio filters support in libavfilter and avconv
 -- add fps filter
 -- audio split filter
 -- audio mix filter
 -- avprobe output is now standard INI or JSON. The old format can still
 -  be used with -of old.
 +- INI and flat output in ffprobe
 +- Scene detection in libavfilter
  - Indeo Audio decoder
  - channelsplit audio filter
 +- setnsamples audio filter
 +- atempo filter
 +- ffprobe -show_data option
  - RTMPT protocol support
  - iLBC encoding/decoding via libilbc
  - Microsoft Screen 1 decoder
diff --cc configure
+++ b/configure
@@@ -1771,7 -1575,7 +1771,8 @@@ flv_decoder_select="h263_decoder
  flv_encoder_select="h263_encoder"
  fourxm_decoder_select="dsputil"
  fraps_decoder_select="dsputil huffman"
+ g2m_decoder_select="dsputil zlib"
 +g729_decoder_select="dsputil"
  h261_decoder_select="error_resilience mpegvideo"
  h261_encoder_select="aandcttables mpegvideoenc"
  h263_decoder_select="error_resilience h263_parser mpegvideo"
Simple merge
@@@ -208,10 -177,9 +208,11 @@@ OBJS-$(CONFIG_FLIC_DECODER)            
  OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
  OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o
  OBJS-$(CONFIG_FRWU_DECODER)            += frwu.o
+ OBJS-$(CONFIG_G2M_DECODER)             += g2meet.o mjpeg.o
  OBJS-$(CONFIG_G723_1_DECODER)          += g723_1.o acelp_vectors.o \
 -                                          celp_filters.o
 +                                          celp_filters.o celp_math.o
 +OBJS-$(CONFIG_G723_1_ENCODER)          += g723_1.o acelp_vectors.o celp_math.o
 +OBJS-$(CONFIG_G729_DECODER)            += g729dec.o lsp.o celp_math.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
  OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
  OBJS-$(CONFIG_GIF_ENCODER)             += gif.o lzwenc.o
  OBJS-$(CONFIG_GSM_DECODER)             += gsmdec.o gsmdec_data.o msgsmdec.o
Simple merge
@@@ -271,33 -269,8 +271,34 @@@ enum AVCodecID 
      AV_CODEC_ID_MSS2,
      AV_CODEC_ID_VP9,
      AV_CODEC_ID_AIC,
 -    AV_CODEC_ID_ESCAPE130,
 -    AV_CODEC_ID_G2M,
 +    AV_CODEC_ID_ESCAPE130_DEPRECATED,
++    AV_CODEC_ID_G2M_DEPRECATED,
 +
 +    AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'),
 +    AV_CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'),
 +    AV_CODEC_ID_ESCAPE130  = MKBETAG('E','1','3','0'),
 +    AV_CODEC_ID_EXR        = MKBETAG('0','E','X','R'),
 +    AV_CODEC_ID_AVRP       = MKBETAG('A','V','R','P'),
 +
 +    AV_CODEC_ID_012V       = MKBETAG('0','1','2','V'),
 +    AV_CODEC_ID_G2M        = MKBETAG( 0 ,'G','2','M'),
 +    AV_CODEC_ID_AVUI       = MKBETAG('A','V','U','I'),
 +    AV_CODEC_ID_AYUV       = MKBETAG('A','Y','U','V'),
 +    AV_CODEC_ID_TARGA_Y216 = MKBETAG('T','2','1','6'),
 +    AV_CODEC_ID_V308       = MKBETAG('V','3','0','8'),
 +    AV_CODEC_ID_V408       = MKBETAG('V','4','0','8'),
 +    AV_CODEC_ID_YUV4       = MKBETAG('Y','U','V','4'),
 +    AV_CODEC_ID_SANM       = MKBETAG('S','A','N','M'),
 +    AV_CODEC_ID_PAF_VIDEO  = MKBETAG('P','A','F','V'),
 +    AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
 +    AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
 +    AV_CODEC_ID_XFACE      = MKBETAG('X','F','A','C'),
 +    AV_CODEC_ID_SGIRLE     = MKBETAG('S','G','I','R'),
 +    AV_CODEC_ID_MVC1       = MKBETAG('M','V','C','1'),
 +    AV_CODEC_ID_MVC2       = MKBETAG('M','V','C','2'),
 +    AV_CODEC_ID_SNOW       = MKBETAG('S','N','O','W'),
 +    AV_CODEC_ID_WEBP       = MKBETAG('W','E','B','P'),
 +    AV_CODEC_ID_SMVJPEG    = MKBETAG('S','M','V','J'),
  
      /* various PCM "codecs" */
      AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
@@@ -1269,122 -1222,12 +1269,123 @@@ static const AVCodecDescriptor codec_de
          .props     = AV_CODEC_PROP_LOSSY,
      },
      {
-         .id        = AV_CODEC_ID_G2M,
-         .type      = AVMEDIA_TYPE_VIDEO,
-         .name      = "g2m",
-         .long_name = NULL_IF_CONFIG_SMALL("GoToMeeting"),
-     },
-     {
 +        .id        = AV_CODEC_ID_EXR,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "exr",
 +        .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
 +                     AV_CODEC_PROP_LOSSLESS,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_AVRP,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "avrp",
 +        .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_012V,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "012v",
 +        .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_AVUI,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "avui",
 +        .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_AYUV,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "ayuv",
 +        .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_TARGA_Y216,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "targa_y216",
 +        .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_V308,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "v308",
 +        .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_V408,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "v408",
 +        .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_YUV4,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "yuv4",
 +        .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_SANM,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "sanm",
 +        .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"),
 +        .props     = AV_CODEC_PROP_LOSSY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_PAF_VIDEO,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "paf_video",
 +        .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"),
 +        .props     = AV_CODEC_PROP_LOSSY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_AVRN,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "avrn",
 +        .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"),
 +    },
 +    {
 +        .id        = AV_CODEC_ID_CPIA,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "cpia",
 +        .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"),
 +    },
 +    {
 +        .id        = AV_CODEC_ID_XFACE,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "xface",
 +        .long_name = NULL_IF_CONFIG_SMALL("X-face image"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_BRENDER_PIX,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "brender_pix",
 +        .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"),
 +        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
 +    },
 +    {
 +        .id        = AV_CODEC_ID_SMVJPEG,
 +        .type      = AVMEDIA_TYPE_VIDEO,
 +        .name      = "smv",
 +        .long_name = NULL_IF_CONFIG_SMALL("Sigmatel Motion Video"),
 +    },
 +
++    {
+         .id        = AV_CODEC_ID_G2M,
+         .type      = AVMEDIA_TYPE_VIDEO,
+         .name      = "g2m",
+         .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"),
+         .props     = AV_CODEC_PROP_LOSSY,
+     },
  
      /* various PCM "codecs" */
      {
index 0000000,72c062c..51ec5bb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,825 +1,825 @@@
 - * This file is part of Libav.
+ /*
+  * Go2Webinar decoder
+  * Copyright (c) 2012 Konstantin Shishkov
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ /**
+  * @file
+  * Go2Webinar decoder
+  */
+ #include <zlib.h>
+ #include "libavutil/intreadwrite.h"
+ #include "avcodec.h"
+ #include "bytestream.h"
+ #include "dsputil.h"
+ #include "get_bits.h"
+ #include "internal.h"
+ #include "mjpeg.h"
+ enum ChunkType {
+     FRAME_INFO = 0xC8,
+     TILE_DATA,
+     CURSOR_POS,
+     CURSOR_SHAPE,
+     CHUNK_CC,
+     CHUNK_CD
+ };
+ enum Compression {
+     COMPR_EPIC_J_B = 2,
+     COMPR_KEMPF_J_B,
+ };
+ static const uint8_t luma_quant[64] = {
+      8,  6,  5,  8, 12, 20, 26, 31,
+      6,  6,  7, 10, 13, 29, 30, 28,
+      7,  7,  8, 12, 20, 29, 35, 28,
+      7,  9, 11, 15, 26, 44, 40, 31,
+      9, 11, 19, 28, 34, 55, 52, 39,
+     12, 18, 28, 32, 41, 52, 57, 46,
+     25, 32, 39, 44, 52, 61, 60, 51,
+     36, 46, 48, 49, 56, 50, 52, 50
+ };
+ static const uint8_t chroma_quant[64] = {
+      9,  9, 12, 24, 50, 50, 50, 50,
+      9, 11, 13, 33, 50, 50, 50, 50,
+     12, 13, 28, 50, 50, 50, 50, 50,
+     24, 33, 50, 50, 50, 50, 50, 50,
+     50, 50, 50, 50, 50, 50, 50, 50,
+     50, 50, 50, 50, 50, 50, 50, 50,
+     50, 50, 50, 50, 50, 50, 50, 50,
+     50, 50, 50, 50, 50, 50, 50, 50,
+ };
+ typedef struct JPGContext {
+     DSPContext dsp;
+     ScanTable  scantable;
+     VLC        dc_vlc[2], ac_vlc[2];
+     int        prev_dc[3];
+     DECLARE_ALIGNED(16, int16_t, block)[6][64];
+     uint8_t    *buf;
+ } JPGContext;
+ typedef struct G2MContext {
+     JPGContext jc;
+     int        version;
+     int        compression;
+     int        width, height, bpp;
+     int        tile_width, tile_height;
+     int        tiles_x, tiles_y, tile_x, tile_y;
+     int        got_header;
+     uint8_t    *framebuf;
+     int        framebuf_stride, old_width, old_height;
+     uint8_t    *synth_tile, *jpeg_tile;
+     int        tile_stride, old_tile_w, old_tile_h;
+     uint8_t    *kempf_buf, *kempf_flags;
+     uint8_t    *cursor;
+     int        cursor_stride;
+     int        cursor_fmt;
+     int        cursor_w, cursor_h, cursor_x, cursor_y;
+     int        cursor_hot_x, cursor_hot_y;
+ } G2MContext;
+ static av_cold int build_vlc(VLC *vlc, const uint8_t *bits_table,
+                              const uint8_t *val_table, int nb_codes,
+                              int is_ac)
+ {
+     uint8_t  huff_size[256] = { 0 };
+     uint16_t huff_code[256];
+     uint16_t huff_sym[256];
+     int i;
+     ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
+     for (i = 0; i < 256; i++)
+         huff_sym[i] = i + 16 * is_ac;
+     if (is_ac)
+         huff_sym[0] = 16 * 256;
+     return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1,
+                               huff_code, 2, 2, huff_sym, 2, 2, 0);
+ }
+ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c)
+ {
+     int ret;
+     ret = build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance,
+                     avpriv_mjpeg_val_dc, 12, 0);
+     if (ret)
+         return ret;
+     ret = build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance,
+                     avpriv_mjpeg_val_dc, 12, 0);
+     if (ret)
+         return ret;
+     ret = build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance,
+                     avpriv_mjpeg_val_ac_luminance, 251, 1);
+     if (ret)
+         return ret;
+     ret = build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance,
+                     avpriv_mjpeg_val_ac_chrominance, 251, 1);
+     if (ret)
+         return ret;
+     ff_dsputil_init(&c->dsp, avctx);
+     ff_init_scantable(c->dsp.idct_permutation, &c->scantable,
+                       ff_zigzag_direct);
+     return 0;
+ }
+ static av_cold void jpg_free_context(JPGContext *ctx)
+ {
+     int i;
+     for (i = 0; i < 2; i++) {
+         ff_free_vlc(&ctx->dc_vlc[i]);
+         ff_free_vlc(&ctx->ac_vlc[i]);
+     }
+     av_freep(&ctx->buf);
+ }
+ static void jpg_unescape(const uint8_t *src, int src_size,
+                          uint8_t *dst, int *dst_size)
+ {
+     const uint8_t *src_end = src + src_size;
+     uint8_t *dst_start = dst;
+     while (src < src_end) {
+         uint8_t x = *src++;
+         *dst++ = x;
+         if (x == 0xFF && !*src)
+             src++;
+     }
+     *dst_size = dst - dst_start;
+ }
+ static int jpg_decode_block(JPGContext *c, GetBitContext *gb,
+                             int plane, int16_t *block)
+ {
+     int dc, val, pos;
+     const int is_chroma = !!plane;
+     const uint8_t *qmat = is_chroma ? chroma_quant : luma_quant;
+     c->dsp.clear_block(block);
+     dc = get_vlc2(gb, c->dc_vlc[is_chroma].table, 9, 3);
+     if (dc < 0)
+         return AVERROR_INVALIDDATA;
+     if (dc)
+         dc = get_xbits(gb, dc);
+     dc = dc * qmat[0] + c->prev_dc[plane];
+     block[0] = dc;
+     c->prev_dc[plane] = dc;
+     pos = 0;
+     while (pos < 63) {
+         val = get_vlc2(gb, c->ac_vlc[is_chroma].table, 9, 3);
+         if (val < 0)
+             return AVERROR_INVALIDDATA;
+         pos += val >> 4;
+         val &= 0xF;
+         if (pos > 63)
+             return val ? AVERROR_INVALIDDATA : 0;
+         if (val) {
+             int nbits = val;
+             val = get_xbits(gb, nbits);
+             val *= qmat[ff_zigzag_direct[pos]];
+             block[c->scantable.permutated[pos]] = val;
+         }
+     }
+     return 0;
+ }
+ static inline void yuv2rgb(uint8_t *out, int Y, int U, int V)
+ {
+     out[0] = av_clip_uint8(Y + (             91881 * V + 32768 >> 16));
+     out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
+     out[2] = av_clip_uint8(Y + (116130 * U             + 32768 >> 16));
+ }
+ static int jpg_decode_data(JPGContext *c, int width, int height,
+                            const uint8_t *src, int src_size,
+                            uint8_t *dst, int dst_stride,
+                            const uint8_t *mask, int mask_stride, int num_mbs,
+                            int swapuv)
+ {
+     GetBitContext gb;
+     uint8_t *tmp;
+     int mb_w, mb_h, mb_x, mb_y, i, j;
+     int bx, by;
+     int unesc_size;
+     int ret;
+     tmp = av_realloc(c->buf, src_size + FF_INPUT_BUFFER_PADDING_SIZE);
+     if (!tmp)
+         return AVERROR(ENOMEM);
+     c->buf = tmp;
+     jpg_unescape(src, src_size, c->buf, &unesc_size);
+     memset(c->buf + unesc_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+     init_get_bits(&gb, c->buf, unesc_size * 8);
+     width = FFALIGN(width, 16);
+     mb_w  =  width        >> 4;
+     mb_h  = (height + 15) >> 4;
+     if (!num_mbs)
+         num_mbs = mb_w * mb_h;
+     for (i = 0; i < 3; i++)
+         c->prev_dc[i] = 1024;
+     bx = by = 0;
+     for (mb_y = 0; mb_y < mb_h; mb_y++) {
+         for (mb_x = 0; mb_x < mb_w; mb_x++) {
+             if (mask && !mask[mb_x]) {
+                 bx += 16;
+                 continue;
+             }
+             for (j = 0; j < 2; j++) {
+                 for (i = 0; i < 2; i++) {
+                     if ((ret = jpg_decode_block(c, &gb, 0,
+                                                 c->block[i + j * 2])) != 0)
+                         return ret;
+                     c->dsp.idct(c->block[i + j * 2]);
+                 }
+             }
+             for (i = 1; i < 3; i++) {
+                 if ((ret = jpg_decode_block(c, &gb, i, c->block[i + 3])) != 0)
+                     return ret;
+                 c->dsp.idct(c->block[i + 3]);
+             }
+             for (j = 0; j < 16; j++) {
+                 uint8_t *out = dst + bx * 3 + (by + j) * dst_stride;
+                 for (i = 0; i < 16; i++) {
+                     int Y, U, V;
+                     Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8];
+                     U = c->block[4 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
+                     V = c->block[5 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
+                     yuv2rgb(out + i * 3, Y, U, V);
+                 }
+             }
+             if (!--num_mbs)
+                 return 0;
+             bx += 16;
+         }
+         bx  = 0;
+         by += 16;
+         if (mask)
+             mask += mask_stride;
+     }
+     return 0;
+ }
+ static void kempf_restore_buf(const uint8_t *src, int len,
+                               uint8_t *dst, int stride,
+                               const uint8_t *jpeg_tile, int tile_stride,
+                               int width, int height,
+                               const uint8_t *pal, int npal, int tidx)
+ {
+     GetBitContext gb;
+     int i, j, nb, col;
+     init_get_bits(&gb, src, len * 8);
+     if (npal <= 2)       nb = 1;
+     else if (npal <= 4)  nb = 2;
+     else if (npal <= 16) nb = 4;
+     else                 nb = 8;
+     for (j = 0; j < height; j++, dst += stride, jpeg_tile += tile_stride) {
+         if (get_bits(&gb, 8))
+             continue;
+         for (i = 0; i < width; i++) {
+             col = get_bits(&gb, nb);
+             if (col != tidx)
+                 memcpy(dst + i * 3, pal + col * 3, 3);
+             else
+                 memcpy(dst + i * 3, jpeg_tile + i * 3, 3);
+         }
+     }
+ }
+ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y,
+                              const uint8_t *src, int src_size)
+ {
+     int width, height;
+     int hdr, zsize, npal, tidx = -1, ret;
+     int i, j;
+     const uint8_t *src_end = src + src_size;
+     uint8_t pal[768], transp[3];
+     uLongf dlen = (c->tile_width + 1) * c->tile_height;
+     int sub_type;
+     int nblocks, cblocks, bstride;
+     int bits, bitbuf, coded;
+     uint8_t *dst = c->framebuf + tile_x * c->tile_width * 3 +
+                    tile_y * c->tile_height * c->framebuf_stride;
+     if (src_size < 2)
+         return AVERROR_INVALIDDATA;
+     width  = FFMIN(c->width  - tile_x * c->tile_width,  c->tile_width);
+     height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height);
+     hdr = *src++;
+     sub_type = hdr >> 5;
+     if (sub_type == 0) {
+         int j;
+         memcpy(transp, src, 3);
+         src += 3;
+         for (j = 0; j < height; j++, dst += c->framebuf_stride)
+             for (i = 0; i < width; i++)
+                 memcpy(dst + i * 3, transp, 3);
+         return 0;
+     } else if (sub_type == 1) {
+         return jpg_decode_data(&c->jc, width, height, src, src_end - src,
+                                dst, c->framebuf_stride, NULL, 0, 0, 0);
+     }
+     if (sub_type != 2) {
+         memcpy(transp, src, 3);
+         src += 3;
+     }
+     npal = *src++ + 1;
+     memcpy(pal, src, npal * 3); src += npal * 3;
+     if (sub_type != 2) {
+         for (i = 0; i < npal; i++) {
+             if (!memcmp(pal + i * 3, transp, 3)) {
+                tidx = i;
+                break;
+             }
+         }
+     }
+     if (src_end - src < 2)
+         return 0;
+     zsize = (src[0] << 8) | src[1]; src += 2;
+     if (src_end - src < zsize)
+         return AVERROR_INVALIDDATA;
+     ret = uncompress(c->kempf_buf, &dlen, src, zsize);
+     if (ret)
+         return AVERROR_INVALIDDATA;
+     src += zsize;
+     if (sub_type == 2) {
+         kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,
+                           NULL, 0, width, height, pal, npal, tidx);
+         return 0;
+     }
+     nblocks = *src++ + 1;
+     cblocks = 0;
+     bstride = FFALIGN(width, 16) >> 4;
+     // blocks are coded LSB and we need normal bitreader for JPEG data
+     bits = 0;
+     for (i = 0; i < (FFALIGN(height, 16) >> 4); i++) {
+         for (j = 0; j < (FFALIGN(width, 16) >> 4); j++) {
+             if (!bits) {
+                 bitbuf = *src++;
+                 bits   = 8;
+             }
+             coded = bitbuf & 1;
+             bits--;
+             bitbuf >>= 1;
+             cblocks += coded;
+             if (cblocks > nblocks)
+                 return AVERROR_INVALIDDATA;
+             c->kempf_flags[j + i * bstride] = coded;
+         }
+     }
+     memset(c->jpeg_tile, 0, c->tile_stride * height);
+     jpg_decode_data(&c->jc, width, height, src, src_end - src,
+                     c->jpeg_tile, c->tile_stride,
+                     c->kempf_flags, bstride, nblocks, 0);
+     kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,
+                       c->jpeg_tile, c->tile_stride,
+                       width, height, pal, npal, tidx);
+     return 0;
+ }
+ static int g2m_init_buffers(G2MContext *c)
+ {
+     int aligned_height;
+     if (!c->framebuf || c->old_width < c->width || c->height < c->height) {
+         c->framebuf_stride = FFALIGN(c->width * 3, 16);
+         aligned_height     = FFALIGN(c->height,    16);
+         av_free(c->framebuf);
+         c->framebuf = av_mallocz(c->framebuf_stride * aligned_height);
+         if (!c->framebuf)
+             return AVERROR(ENOMEM);
+     }
+     if (!c->synth_tile || !c->jpeg_tile ||
+         c->old_tile_w < c->tile_width ||
+         c->old_tile_h < c->tile_height) {
+         c->tile_stride = FFALIGN(c->tile_width * 3, 16);
+         aligned_height = FFALIGN(c->tile_height,    16);
+         av_free(c->synth_tile);
+         av_free(c->jpeg_tile);
+         c->synth_tile  = av_mallocz(c->tile_stride      * aligned_height);
+         c->jpeg_tile   = av_mallocz(c->tile_stride      * aligned_height);
+         c->kempf_buf   = av_mallocz((c->tile_width + 1) * aligned_height
+                                     + FF_INPUT_BUFFER_PADDING_SIZE);
+         c->kempf_flags = av_mallocz( c->tile_width      * aligned_height);
+         if (!c->synth_tile || !c->jpeg_tile ||
+             !c->kempf_buf || !c->kempf_flags)
+             return AVERROR(ENOMEM);
+     }
+     return 0;
+ }
+ static int g2m_load_cursor(G2MContext *c, GetByteContext *gb)
+ {
+     int i, j, k;
+     uint8_t *dst;
+     uint32_t bits;
+     c->cursor_stride = c->cursor_w * 4;
+     c->cursor        = av_realloc(c->cursor, c->cursor_stride * c->cursor_h);
+     if (!c->cursor)
+         return AVERROR(ENOMEM);
+     dst = c->cursor;
+     switch (c->cursor_fmt) {
+     case 1: // old monochrome
+         for (j = 0; j < c->cursor_h; j++) {
+             for (i = 0; i < c->cursor_w; i += 32) {
+                 bits = bytestream2_get_be32(gb);
+                 for (k = 0; k < 32; k++) {
+                     dst[0] = !!(bits & 0x80000000);
+                     dst += 4;
+                     bits <<= 1;
+                 }
+             }
+         }
+         dst = c->cursor;
+         for (j = 0; j < c->cursor_h; j++) {
+             for (i = 0; i < c->cursor_w; i += 32) {
+                 bits = bytestream2_get_be32(gb);
+                 for (k = 0; k < 32; k++) {
+                     int mask_bit = !!(bits & 0x80000000);
+                     switch (dst[0] * 2 + mask_bit) {
+                     case 0:
+                         dst[0] = 0xFF; dst[1] = 0x00;
+                         dst[2] = 0x00; dst[3] = 0x00;
+                         break;
+                     case 1:
+                         dst[0] = 0xFF; dst[1] = 0xFF;
+                         dst[2] = 0xFF; dst[3] = 0xFF;
+                         break;
+                     default:
+                         dst[0] = 0x00; dst[1] = 0x00;
+                         dst[2] = 0x00; dst[3] = 0x00;
+                     }
+                     dst += 4;
+                     bits <<= 1;
+                 }
+             }
+         }
+         break;
+     case 32: // full colour
+         /* skip monochrome version of the cursor and decode RGBA instead */
+         bytestream2_skip(gb, c->cursor_h * (FFALIGN(c->cursor_w, 32) >> 3));
+         for (j = 0; j < c->cursor_h; j++) {
+             for (i = 0; i < c->cursor_w; i++) {
+                 int val = bytestream2_get_be32(gb);
+                 *dst++ = val >>  0;
+                 *dst++ = val >>  8;
+                 *dst++ = val >> 16;
+                 *dst++ = val >> 24;
+             }
+         }
+         break;
+     default:
+         return AVERROR_PATCHWELCOME;
+     }
+     return 0;
+ }
+ #define APPLY_ALPHA(src, new, alpha) \
+     src = (src * (256 - alpha) + new * alpha) >> 8
+ static void g2m_paint_cursor(G2MContext *c, uint8_t *dst, int stride)
+ {
+     int i, j;
+     int x, y, w, h;
+     const uint8_t *cursor;
+     if (!c->cursor)
+         return;
+     x = c->cursor_x - c->cursor_hot_x;
+     y = c->cursor_y - c->cursor_hot_y;
+     cursor = c->cursor;
+     w      = c->cursor_w;
+     h      = c->cursor_h;
+     if (x + w > c->width)
+         w = c->width - x;
+     if (y + h > c->height)
+         h = c->height - y;
+     if (x < 0) {
+         w      +=  x;
+         cursor += -x * 4;
+     } else {
+         dst    +=  x * 3;
+     }
+     if (y < 0) {
+         h      +=  y;
+         cursor += -y * c->cursor_stride;
+     } else {
+         dst    +=  y * stride;
+     }
+     if (w < 0 || h < 0)
+         return;
+     for (j = 0; j < h; j++) {
+         for (i = 0; i < w; i++) {
+             uint8_t alpha = cursor[i * 4];
+             APPLY_ALPHA(dst[i * 3 + 0], cursor[i * 4 + 1], alpha);
+             APPLY_ALPHA(dst[i * 3 + 1], cursor[i * 4 + 2], alpha);
+             APPLY_ALPHA(dst[i * 3 + 2], cursor[i * 4 + 3], alpha);
+         }
+         dst    += stride;
+         cursor += c->cursor_stride;
+     }
+ }
+ static int g2m_decode_frame(AVCodecContext *avctx, void *data,
+                             int *got_picture_ptr, AVPacket *avpkt)
+ {
+     const uint8_t *buf = avpkt->data;
+     int buf_size = avpkt->size;
+     G2MContext *c = avctx->priv_data;
+     AVFrame *pic = data;
+     GetByteContext bc, tbc;
+     int magic;
+     int got_header = 0;
+     uint32_t chunk_size, cur_size;
+     int chunk_type;
+     int i;
+     int ret;
+     if (buf_size < 12) {
+         av_log(avctx, AV_LOG_ERROR,
+                "Frame should have at least 12 bytes, got %d instead\n",
+                buf_size);
+         return AVERROR_INVALIDDATA;
+     }
+     bytestream2_init(&bc, buf, buf_size);
+     magic = bytestream2_get_be32(&bc);
+     if ((magic & ~0xF) != MKBETAG('G', '2', 'M', '0') ||
+         (magic & 0xF) < 2 || (magic & 0xF) > 4) {
+         av_log(avctx, AV_LOG_ERROR, "Wrong magic %08X\n", magic);
+         return AVERROR_INVALIDDATA;
+     }
+     if ((magic & 0xF) != 4) {
+         av_log(avctx, AV_LOG_ERROR, "G2M2 and G2M3 are not yet supported\n");
+         return AVERROR(ENOSYS);
+     }
+     while (bytestream2_get_bytes_left(&bc) > 5) {
+         chunk_size = bytestream2_get_le32(&bc) - 1;
+         chunk_type = bytestream2_get_byte(&bc);
+         if (chunk_size > bytestream2_get_bytes_left(&bc)) {
+             av_log(avctx, AV_LOG_ERROR, "Invalid chunk size %d type %02X\n",
+                    chunk_size, chunk_type);
+             break;
+         }
+         switch (chunk_type) {
+         case FRAME_INFO:
+             c->got_header = 0;
+             if (chunk_size < 21) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid frame info size %d\n",
+                        chunk_size);
+                 break;
+             }
+             c->width  = bytestream2_get_be32(&bc);
+             c->height = bytestream2_get_be32(&bc);
+             if (c->width  < 16 || c->width  > avctx->width ||
+                 c->height < 16 || c->height > avctx->height) {
+                 av_log(avctx, AV_LOG_ERROR,
+                        "Invalid frame dimensions %dx%d\n",
+                        c->width, c->height);
+                 c->width = c->height = 0;
+                 bytestream2_skip(&bc, bytestream2_get_bytes_left(&bc));
+             }
+             if (c->width != avctx->width || c->height != avctx->height)
+                 avcodec_set_dimensions(avctx, c->width, c->height);
+             c->compression = bytestream2_get_be32(&bc);
+             if (c->compression != 2 && c->compression != 3) {
+                 av_log(avctx, AV_LOG_ERROR,
+                        "Unknown compression method %d\n",
+                        c->compression);
+                 return AVERROR_PATCHWELCOME;
+             }
+             c->tile_width  = bytestream2_get_be32(&bc);
+             c->tile_height = bytestream2_get_be32(&bc);
+             if (!c->tile_width || !c->tile_height) {
+                 av_log(avctx, AV_LOG_ERROR,
+                        "Invalid tile dimensions %dx%d\n",
+                        c->tile_width, c->tile_height);
+                 return AVERROR_INVALIDDATA;
+             }
+             c->tiles_x = (c->width  + c->tile_width  - 1) / c->tile_width;
+             c->tiles_y = (c->height + c->tile_height - 1) / c->tile_height;
+             c->bpp = bytestream2_get_byte(&bc);
+             chunk_size -= 21;
+             bytestream2_skip(&bc, chunk_size);
+             if (g2m_init_buffers(c))
+                 return AVERROR(ENOMEM);
+             got_header = 1;
+             break;
+         case TILE_DATA:
+             if (!c->tiles_x || !c->tiles_y) {
+                 av_log(avctx, AV_LOG_WARNING,
+                        "No frame header - skipping tile\n");
+                 bytestream2_skip(&bc, bytestream2_get_bytes_left(&bc));
+                 break;
+             }
+             if (chunk_size < 2) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid tile data size %d\n",
+                        chunk_size);
+                 break;
+             }
+             c->tile_x = bytestream2_get_byte(&bc);
+             c->tile_y = bytestream2_get_byte(&bc);
+             if (c->tile_x >= c->tiles_x || c->tile_y >= c->tiles_y) {
+                 av_log(avctx, AV_LOG_ERROR,
+                        "Invalid tile pos %d,%d (in %dx%d grid)\n",
+                        c->tile_x, c->tile_y, c->tiles_x, c->tiles_y);
+                 break;
+             }
+             chunk_size -= 2;
+             ret = 0;
+             switch (c->compression) {
+             case COMPR_EPIC_J_B:
+                 av_log(avctx, AV_LOG_ERROR,
+                        "ePIC j-b compression is not implemented yet\n");
+                 return AVERROR(ENOSYS);
+             case COMPR_KEMPF_J_B:
+                 ret = kempf_decode_tile(c, c->tile_x, c->tile_y,
+                                         buf + bytestream2_tell(&bc),
+                                         chunk_size);
+                 break;
+             }
+             if (ret && c->framebuf)
+                 av_log(avctx, AV_LOG_ERROR, "Error decoding tile %d,%d\n",
+                        c->tile_x, c->tile_y);
+             bytestream2_skip(&bc, chunk_size);
+             break;
+         case CURSOR_POS:
+             if (chunk_size < 5) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid cursor pos size %d\n",
+                        chunk_size);
+                 break;
+             }
+             c->cursor_x = bytestream2_get_be16(&bc);
+             c->cursor_y = bytestream2_get_be16(&bc);
+             bytestream2_skip(&bc, chunk_size - 4);
+             break;
+         case CURSOR_SHAPE:
+             if (chunk_size < 8) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n",
+                        chunk_size);
+                 break;
+             }
+             bytestream2_init(&tbc, buf + bytestream2_tell(&bc),
+                              chunk_size - 4);
+             cur_size        = bytestream2_get_be32(&tbc);
+             c->cursor_w     = bytestream2_get_byte(&tbc);
+             c->cursor_h     = bytestream2_get_byte(&tbc);
+             c->cursor_hot_x = bytestream2_get_byte(&tbc);
+             c->cursor_hot_y = bytestream2_get_byte(&tbc);
+             c->cursor_fmt   = bytestream2_get_byte(&tbc);
+             if (cur_size >= chunk_size ||
+                 c->cursor_w * c->cursor_h / 4 > cur_size) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n",
+                        chunk_size);
+                 break;
+             }
+             g2m_load_cursor(c, &tbc);
+             bytestream2_skip(&bc, chunk_size);
+             break;
+         case CHUNK_CC:
+         case CHUNK_CD:
+             bytestream2_skip(&bc, chunk_size);
+             break;
+         default:
+             av_log(avctx, AV_LOG_WARNING, "Skipping chunk type %02X\n",
+                    chunk_type);
+             bytestream2_skip(&bc, chunk_size);
+         }
+     }
+     if (got_header)
+         c->got_header = 1;
+     if (c->width && c->height) {
+         if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) {
+             av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+             return ret;
+         }
+         pic->key_frame = got_header;
+         pic->pict_type = got_header ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+         for (i = 0; i < avctx->height; i++)
+             memcpy(pic->data[0] + i * pic->linesize[0],
+                    c->framebuf  + i * c->framebuf_stride,
+                    c->width * 3);
+         g2m_paint_cursor(c, pic->data[0], pic->linesize[0]);
+         *got_picture_ptr = 1;
+     }
+     return buf_size;
+ }
+ static av_cold int g2m_decode_init(AVCodecContext *avctx)
+ {
+     G2MContext * const c = avctx->priv_data;
+     int ret;
+     if ((ret = jpg_init(avctx, &c->jc)) != 0) {
+         av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n");
+         jpg_free_context(&c->jc);
+         return AVERROR(ENOMEM);
+     }
+     avctx->pix_fmt     = PIX_FMT_RGB24;
+     return 0;
+ }
+ static av_cold int g2m_decode_end(AVCodecContext *avctx)
+ {
+     G2MContext * const c = avctx->priv_data;
+     jpg_free_context(&c->jc);
+     av_freep(&c->kempf_buf);
+     av_freep(&c->kempf_flags);
+     av_freep(&c->synth_tile);
+     av_freep(&c->jpeg_tile);
+     av_freep(&c->cursor);
+     av_freep(&c->framebuf);
+     return 0;
+ }
+ AVCodec ff_g2m_decoder = {
+     .name           = "g2m",
+     .long_name      = NULL_IF_CONFIG_SMALL("Go2Meeting"),
+     .type           = AVMEDIA_TYPE_VIDEO,
+     .id             = AV_CODEC_ID_G2M,
+     .priv_data_size = sizeof(G2MContext),
+     .init           = g2m_decode_init,
+     .close          = g2m_decode_end,
+     .decode         = g2m_decode_frame,
+     .capabilities   = CODEC_CAP_DR1,
+ };
@@@ -2398,19 -1560,6 +2398,20 @@@ av_cold int avcodec_close(AVCodecContex
      return 0;
  }
  
 +static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id)
 +{
 +    switch(id){
 +        //This is for future deprecatec codec ids, its empty since
 +        //last major bump but will fill up again over time, please don't remove it
 +//         case AV_CODEC_ID_UTVIDEO_DEPRECATED: return AV_CODEC_ID_UTVIDEO;
 +        case AV_CODEC_ID_OPUS_DEPRECATED: return AV_CODEC_ID_OPUS;
 +        case AV_CODEC_ID_TAK_DEPRECATED : return AV_CODEC_ID_TAK;
 +        case AV_CODEC_ID_ESCAPE130_DEPRECATED : return AV_CODEC_ID_ESCAPE130;
++        case AV_CODEC_ID_G2M_DEPRECATED : return AV_CODEC_ID_G2M;
 +        default                         : return id;
 +    }
 +}
 +
  static AVCodec *find_encdec(enum AVCodecID id, int encoder)
  {
      AVCodec *p, *experimental = NULL;
   * Libavcodec version macros.
   */
  
 +#include "libavutil/avutil.h"
 +
  #define LIBAVCODEC_VERSION_MAJOR 55
- #define LIBAVCODEC_VERSION_MINOR  14
 -#define LIBAVCODEC_VERSION_MINOR  8
 -#define LIBAVCODEC_VERSION_MICRO  0
++#define LIBAVCODEC_VERSION_MINOR  15
 +#define LIBAVCODEC_VERSION_MICRO 100
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                 LIBAVCODEC_VERSION_MINOR, \
@@@ -325,10 -298,6 +325,7 @@@ const AVCodecTag ff_codec_bmp_tags[] = 
      { AV_CODEC_ID_DPX,          MKTAG('d', 'p', 'x', ' ') },
      { AV_CODEC_ID_KGV1,         MKTAG('K', 'G', 'V', '1') },
      { AV_CODEC_ID_LAGARITH,     MKTAG('L', 'A', 'G', 'S') },
-     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '2') },
-     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '3') },
-     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '4') },
 +    { AV_CODEC_ID_AMV,          MKTAG('A', 'M', 'V', 'F') },
      { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'R', 'A') },
      { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'R', 'G') },
      { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'Y', '0') },
      { AV_CODEC_ID_CLLC,         MKTAG('C', 'L', 'L', 'C') },
      { AV_CODEC_ID_MSS2,         MKTAG('M', 'S', 'S', '2') },
      { AV_CODEC_ID_SVQ3,         MKTAG('S', 'V', 'Q', '3') },
 +    { AV_CODEC_ID_012V,         MKTAG('0', '1', '2', 'v') },
 +    { AV_CODEC_ID_012V,         MKTAG('a', '1', '2', 'v') },
+     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '2') },
+     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '3') },
+     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '4') },
      { AV_CODEC_ID_NONE,         0 }
  };