Merge commit '5a0e953c2465be9d449d5f523c3d3e2b886910b2'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 13 Mar 2015 21:48:54 +0000 (22:48 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 13 Mar 2015 21:48:54 +0000 (22:48 +0100)
* commit '5a0e953c2465be9d449d5f523c3d3e2b886910b2':
  mjpeg: Mark decoder family as thread safe

Conflicts:
libavcodec/mjpegbdec.c
libavcodec/mjpegdec.c
libavcodec/mxpegdec.c
libavcodec/sp5xdec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/jpeglsdec.c
libavcodec/mjpegbdec.c
libavcodec/mjpegdec.c
libavcodec/mxpegdec.c
libavcodec/sp5xdec.c

diff --combined libavcodec/jpeglsdec.c
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2003 Michael Niedermayer
   * Copyright (c) 2006 Konstantin Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -28,6 -28,7 +28,7 @@@
  #include "avcodec.h"
  #include "get_bits.h"
  #include "golomb.h"
+ #include "internal.h"
  #include "mathops.h"
  #include "mjpeg.h"
  #include "mjpegdec.h"
@@@ -39,7 -40,7 +40,7 @@@
   * (or test broken JPEG-LS decoder) and slow down ordinary decoding a bit.
   *
   * There is no Golomb code with length >= 32 bits possible, so check and
 - * avoid situation of 32 zeros, Libav Golomb decoder is painfully slow
 + * avoid situation of 32 zeros, FFmpeg Golomb decoder is painfully slow
   * on this errors.
   */
  //#define JLS_BROKEN
  int ff_jpegls_decode_lse(MJpegDecodeContext *s)
  {
      int id;
 +    int tid, wt, maxtab, i, j;
  
 -    skip_bits(&s->gb, 16);  /* length: FIXME: verify field validity */
 +    int len = get_bits(&s->gb, 16);
      id = get_bits(&s->gb, 8);
  
      switch (id) {
      case 1:
 +        if (len < 13)
 +            return AVERROR_INVALIDDATA;
 +
          s->maxval = get_bits(&s->gb, 16);
          s->t1     = get_bits(&s->gb, 16);
          s->t2     = get_bits(&s->gb, 16);
          s->t3     = get_bits(&s->gb, 16);
          s->reset  = get_bits(&s->gb, 16);
  
 +        if(s->avctx->debug & FF_DEBUG_PICT_INFO) {
 +            av_log(s->avctx, AV_LOG_DEBUG, "Coding parameters maxval:%d T1:%d T2:%d T3:%d reset:%d\n",
 +                   s->maxval, s->t1, s->t2, s->t3, s->reset);
 +        }
 +
  //        ff_jpegls_reset_coding_parameters(s, 0);
          //FIXME quant table?
          break;
      case 2:
 +        s->palette_index = 0;
      case 3:
 -        av_log(s->avctx, AV_LOG_ERROR, "palette not supported\n");
 -        return AVERROR(ENOSYS);
 +        tid= get_bits(&s->gb, 8);
 +        wt = get_bits(&s->gb, 8);
 +
 +        if (len < 5)
 +            return AVERROR_INVALIDDATA;
 +
 +        if (wt < 1 || wt > MAX_COMPONENTS) {
 +            avpriv_request_sample(s->avctx, "wt %d", wt);
 +            return AVERROR_PATCHWELCOME;
 +        }
 +
 +        if (!s->maxval)
 +            maxtab = 255;
 +        else if ((5 + wt*(s->maxval+1)) < 65535)
 +            maxtab = s->maxval;
 +        else
 +            maxtab = 65530/wt - 1;
 +
 +        if(s->avctx->debug & FF_DEBUG_PICT_INFO) {
 +            av_log(s->avctx, AV_LOG_DEBUG, "LSE palette %d tid:%d wt:%d maxtab:%d\n", id, tid, wt, maxtab);
 +        }
 +        if (maxtab >= 256) {
 +            avpriv_request_sample(s->avctx, ">8bit palette");
 +            return AVERROR_PATCHWELCOME;
 +        }
 +        maxtab = FFMIN(maxtab, (len - 5) / wt + s->palette_index);
 +
 +        if (s->palette_index > maxtab)
 +            return AVERROR_INVALIDDATA;
 +
 +        if ((s->avctx->pix_fmt == AV_PIX_FMT_GRAY8 || s->avctx->pix_fmt == AV_PIX_FMT_PAL8) &&
 +            (s->picture_ptr->format == AV_PIX_FMT_GRAY8 || s->picture_ptr->format == AV_PIX_FMT_PAL8)) {
 +            uint32_t *pal = (uint32_t *)s->picture_ptr->data[1];
 +            s->picture_ptr->format =
 +            s->avctx->pix_fmt = AV_PIX_FMT_PAL8;
 +            for (i=s->palette_index; i<=maxtab; i++) {
 +                pal[i] = 0;
 +                for (j=0; j<wt; j++) {
 +                    pal[i] |= get_bits(&s->gb, 8) << (8*(wt-j-1));
 +                }
 +            }
 +            s->palette_index = i;
 +        }
 +        break;
      case 4:
 -        av_log(s->avctx, AV_LOG_ERROR, "oversize image not supported\n");
 +        avpriv_request_sample(s->avctx, "oversize image");
          return AVERROR(ENOSYS);
      default:
          av_log(s->avctx, AV_LOG_ERROR, "invalid id %d\n", id);
@@@ -200,8 -149,6 +201,8 @@@ static inline int ls_get_code_runterm(G
          ret = ret >> 1;
      }
  
 +    if(FFABS(ret) > 0xFFFF)
 +        return -0x10000;
      /* update state */
      state->A[Q] += FFABS(ret) - RItype;
      ret         *= state->twonear;
@@@ -261,19 -208,11 +262,19 @@@ static inline void ls_decode_line(JLSSt
              r = ff_log2_run[state->run_index[comp]];
              if (r)
                  r = get_bits_long(&s->gb, r);
 +            if (x + r * stride > w) {
 +                r = (w - x) / stride;
 +            }
              for (i = 0; i < r; i++) {
                  W(dst, x, Ra);
                  x += stride;
              }
  
 +            if (x >= w) {
 +                av_log(NULL, AV_LOG_ERROR, "run overflow\n");
 +                return;
 +            }
 +
              /* decode run termination value */
              Rb     = R(last, x);
              RItype = (FFABS(Ra - Rb) <= state->near) ? 1 : 0;
@@@ -359,23 -298,21 +360,23 @@@ int ff_jpegls_decode_picture(MJpegDecod
      else
          shift = point_transform + (16 - s->bits);
  
 -    av_dlog(s->avctx,
 -            "JPEG-LS params: %ix%i NEAR=%i MV=%i T(%i,%i,%i) "
 -            "RESET=%i, LIMIT=%i, qbpp=%i, RANGE=%i\n",
 -            s->width, s->height, state->near, state->maxval,
 -            state->T1, state->T2, state->T3,
 -            state->reset, state->limit, state->qbpp, state->range);
 -    av_dlog(s->avctx, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n",
 -            ilv, point_transform, s->bits, s->cur_scan);
 +    if (s->avctx->debug & FF_DEBUG_PICT_INFO) {
 +        av_log(s->avctx, AV_LOG_DEBUG,
 +               "JPEG-LS params: %ix%i NEAR=%i MV=%i T(%i,%i,%i) "
 +               "RESET=%i, LIMIT=%i, qbpp=%i, RANGE=%i\n",
 +                s->width, s->height, state->near, state->maxval,
 +                state->T1, state->T2, state->T3,
 +                state->reset, state->limit, state->qbpp, state->range);
 +        av_log(s->avctx, AV_LOG_DEBUG, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n",
 +                ilv, point_transform, s->bits, s->cur_scan);
 +    }
      if (ilv == 0) { /* separate planes */
          if (s->cur_scan > s->nb_components) {
              ret = AVERROR_INVALIDDATA;
              goto end;
          }
 -        off    = s->cur_scan - 1;
          stride = (s->nb_components > 1) ? 3 : 1;
 +        off    = av_clip(s->cur_scan - 1, 0, stride - 1);
          width  = s->width * stride;
          cur   += off;
          for (i = 0; i < s->height; i++) {
      } else if (ilv == 1) { /* line interleaving */
          int j;
          int Rc[3] = { 0, 0, 0 };
 +        stride = (s->nb_components > 1) ? 3 : 1;
          memset(cur, 0, s->picture_ptr->linesize[0]);
 -        width = s->width * 3;
 +        width = s->width * stride;
          for (i = 0; i < s->height; i++) {
 -            for (j = 0; j < 3; j++) {
 +            for (j = 0; j < stride; j++) {
                  ls_decode_line(state, s, last + j, cur + j,
 -                               Rc[j], width, 3, j, 8);
 +                               Rc[j], width, stride, j, 8);
                  Rc[j] = last[j];
  
                  if (s->restart_interval && !--s->restart_count) {
          goto end;
      }
  
 +    if (s->xfrm && s->nb_components == 3) {
 +        int x, w;
 +
 +        w = s->width * s->nb_components;
 +
 +        if (s->bits <= 8) {
 +            uint8_t *src = s->picture_ptr->data[0];
 +
 +            for (i = 0; i < s->height; i++) {
 +                switch(s->xfrm) {
 +                case 1:
 +                    for (x = off; x < w; x += 3) {
 +                        src[x  ] += src[x+1] + 128;
 +                        src[x+2] += src[x+1] + 128;
 +                    }
 +                    break;
 +                case 2:
 +                    for (x = off; x < w; x += 3) {
 +                        src[x  ] += src[x+1] + 128;
 +                        src[x+2] += ((src[x  ] + src[x+1])>>1) + 128;
 +                    }
 +                    break;
 +                case 3:
 +                    for (x = off; x < w; x += 3) {
 +                        int g = src[x+0] - ((src[x+2]+src[x+1])>>2) + 64;
 +                        src[x+0] = src[x+2] + g + 128;
 +                        src[x+2] = src[x+1] + g + 128;
 +                        src[x+1] = g;
 +                    }
 +                    break;
 +                case 4:
 +                    for (x = off; x < w; x += 3) {
 +                        int r    = src[x+0] - ((                       359 * (src[x+2]-128) + 490) >> 8);
 +                        int g    = src[x+0] - (( 88 * (src[x+1]-128) - 183 * (src[x+2]-128) +  30) >> 8);
 +                        int b    = src[x+0] + ((454 * (src[x+1]-128)                        + 574) >> 8);
 +                        src[x+0] = av_clip_uint8(r);
 +                        src[x+1] = av_clip_uint8(g);
 +                        src[x+2] = av_clip_uint8(b);
 +                    }
 +                    break;
 +                }
 +                src += s->picture_ptr->linesize[0];
 +            }
 +        }else
 +            avpriv_report_missing_feature(s->avctx, "16bit xfrm");
 +    }
 +
      if (shift) { /* we need to do point transform or normalize samples */
          int x, w;
  
@@@ -508,4 -397,5 +509,5 @@@ AVCodec ff_jpegls_decoder = 
      .close          = ff_mjpeg_decode_end,
      .decode         = ff_mjpeg_decode_frame,
      .capabilities   = CODEC_CAP_DR1,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
diff --combined libavcodec/mjpegbdec.c
@@@ -2,20 -2,20 +2,20 @@@
   * Apple MJPEG-B decoder
   * Copyright (c) 2002 Alex Beregszaszi
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -27,6 -27,7 +27,7 @@@
  #include <inttypes.h>
  
  #include "avcodec.h"
+ #include "internal.h"
  #include "mjpeg.h"
  #include "mjpegdec.h"
  
@@@ -54,7 -55,6 +55,7 @@@ static int mjpegb_decode_frame(AVCodecC
  
      buf_ptr = buf;
      buf_end = buf + buf_size;
 +    s->got_picture = 0;
  
  read_header:
      /* reset on every SOI */
                        8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs));
          s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16));
          s->start_code = SOS;
 -        if (ff_mjpeg_decode_sos(s, NULL, NULL) < 0 &&
 +        if (ff_mjpeg_decode_sos(s, NULL, 0, NULL) < 0 &&
              (avctx->err_recognition & AV_EF_EXPLODE))
            return AVERROR_INVALIDDATA;
      }
          if (s->bottom_field != s->interlace_polarity && second_field_offs)
          {
              buf_ptr = buf + second_field_offs;
 -            second_field_offs = 0;
              goto read_header;
              }
      }
  
      //XXX FIXME factorize, this looks very similar to the EOI code
  
 +    if(!s->got_picture) {
 +        av_log(avctx, AV_LOG_WARNING, "no picture\n");
 +        return buf_size;
 +    }
 +
      if ((ret = av_frame_ref(data, s->picture_ptr)) < 0)
          return ret;
      *got_frame = 1;
@@@ -166,5 -162,5 +167,6 @@@ AVCodec ff_mjpegb_decoder = 
      .close          = ff_mjpeg_decode_end,
      .decode         = mjpegb_decode_frame,
      .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
diff --combined libavcodec/mjpegdec.c
@@@ -8,20 -8,20 +8,20 @@@
   * aspecting, new decode_frame mechanism and apple mjpeg-b support
   *                                  by Alex Beregszaszi
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
   * MJPEG decoder.
   */
  
 -#include <assert.h>
 -
  #include "libavutil/imgutils.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/opt.h"
  #include "avcodec.h"
  #include "blockdsp.h"
 +#include "copy_block.h"
  #include "idctdsp.h"
  #include "internal.h"
  #include "mjpeg.h"
  #include "mjpegdec.h"
  #include "jpeglsdec.h"
 +#include "tiff.h"
 +#include "exif.h"
 +#include "bytestream.h"
  
  
  static int build_vlc(VLC *vlc, const uint8_t *bits_table,
@@@ -55,7 -52,7 +55,7 @@@
      uint16_t huff_sym[256];
      int i;
  
 -    assert(nb_codes <= 256);
 +    av_assert0(nb_codes <= 256);
  
      ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
  
@@@ -85,17 -82,6 +85,17 @@@ static void build_basic_mjpeg_vlc(MJpeg
                avpriv_mjpeg_val_ac_chrominance, 251, 0, 0);
  }
  
 +static void parse_avid(MJpegDecodeContext *s, uint8_t *buf, int len)
 +{
 +    s->buggy_avid = 1;
 +    if (len > 14 && buf[12] == 1) /* 1 - NTSC */
 +        s->interlace_polarity = 1;
 +    if (len > 14 && buf[12] == 2) /* 2 - PAL */
 +        s->interlace_polarity = 0;
 +    if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 +        av_log(s->avctx, AV_LOG_INFO, "AVID: len:%d %d\n", len, len > 14 ? buf[12] : -1);
 +}
 +
  av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
  {
      MJpegDecodeContext *s = avctx->priv_data;
      s->buffer        = NULL;
      s->start_code    = -1;
      s->first_picture = 1;
 +    s->got_picture   = 0;
      s->org_height    = avctx->coded_height;
      avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
      avctx->colorspace = AVCOL_SPC_BT470BG;
      build_basic_mjpeg_vlc(s);
  
      if (s->extern_huff) {
 -        int ret;
 -        av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n");
 +        av_log(avctx, AV_LOG_INFO, "using external huffman table\n");
          init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size * 8);
 -        if ((ret = ff_mjpeg_decode_dht(s))) {
 +        if (ff_mjpeg_decode_dht(s)) {
              av_log(avctx, AV_LOG_ERROR,
 -                   "mjpeg: error using external huffman table\n");
 -            return ret;
 +                   "error using external huffman table, switching back to internal\n");
 +            build_basic_mjpeg_vlc(s);
          }
      }
      if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */
          s->interlace_polarity = 1;           /* bottom field first */
 -        av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
 +        av_log(avctx, AV_LOG_DEBUG, "bottom field first\n");
 +    } else if (avctx->field_order == AV_FIELD_UNKNOWN) {
 +        if (avctx->codec_tag == AV_RL32("MJPG"))
 +            s->interlace_polarity = 1;
 +    }
 +
 +    if (   avctx->extradata_size > 8
 +        && AV_RL32(avctx->extradata) == 0x2C
 +        && AV_RL32(avctx->extradata+4) == 0x18) {
 +        parse_avid(s, avctx->extradata, avctx->extradata_size);
      }
 +
      if (avctx->codec->id == AV_CODEC_ID_AMV)
          s->flipped = 1;
  
@@@ -162,10 -138,10 +162,10 @@@ int ff_mjpeg_decode_dqt(MJpegDecodeCont
      len = get_bits(&s->gb, 16) - 2;
  
      while (len >= 65) {
 -        /* only 8 bit precision handled */
 -        if (get_bits(&s->gb, 4) != 0) {
 -            av_log(s->avctx, AV_LOG_ERROR, "dqt: 16bit precision\n");
 -            return -1;
 +        int pr = get_bits(&s->gb, 4);
 +        if (pr > 1) {
 +            av_log(s->avctx, AV_LOG_ERROR, "dqt: invalid precision\n");
 +            return AVERROR_INVALIDDATA;
          }
          index = get_bits(&s->gb, 4);
          if (index >= 4)
          /* read quant table */
          for (i = 0; i < 64; i++) {
              j = s->scantable.permutated[i];
 -            s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
 +            s->quant_matrixes[index][j] = get_bits(&s->gb, pr ? 16 : 8);
          }
  
          // XXX FIXME finetune, and perhaps add dc too
@@@ -244,40 -220,27 +244,40 @@@ int ff_mjpeg_decode_dht(MJpegDecodeCont
  
  int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
  {
 +    int len, nb_components, i, width, height, bits, ret;
 +    unsigned pix_fmt_id;
      int h_count[MAX_COMPONENTS] = { 0 };
      int v_count[MAX_COMPONENTS] = { 0 };
 -    int len, nb_components, i, width, height, bits, pix_fmt_id, ret;
 +
 +    s->cur_scan = 0;
 +    s->upscale_h = s->upscale_v = 0;
  
      /* XXX: verify len field validity */
      len     = get_bits(&s->gb, 16);
 +    s->avctx->bits_per_raw_sample =
      bits    = get_bits(&s->gb, 8);
  
 +    if (bits > 16 || bits < 1) {
 +        av_log(s->avctx, AV_LOG_ERROR, "bits %d is invalid\n", bits);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      if (s->pegasus_rct)
          bits = 9;
      if (bits == 9 && !s->pegasus_rct)
          s->rct  = 1;    // FIXME ugly
  
 -    if (bits != 8 && !s->lossless) {
 -        av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n");
 +    if(s->lossless && s->avctx->lowres){
 +        av_log(s->avctx, AV_LOG_ERROR, "lowres is not possible with lossless jpeg\n");
          return -1;
      }
  
      height = get_bits(&s->gb, 16);
      width  = get_bits(&s->gb, 16);
  
 +    if (s->avctx->codec_id == AV_CODEC_ID_AMV && (height&15))
 +        avpriv_request_sample(s->avctx, "non mod 16 height AMV\n");
 +
      // HACK for odd_height.mov
      if (s->interlaced && s->width == width && s->height == height + 1)
          height= s->height;
          if (v_count[i] > s->v_max)
              s->v_max = v_count[i];
          s->quant_index[i] = get_bits(&s->gb, 8);
 -        if (s->quant_index[i] >= 4)
 +        if (s->quant_index[i] >= 4) {
 +            av_log(s->avctx, AV_LOG_ERROR, "quant_index is invalid\n");
              return AVERROR_INVALIDDATA;
 +        }
          if (!h_count[i] || !v_count[i]) {
              av_log(s->avctx, AV_LOG_ERROR,
                     "Invalid sampling factor in component %d %d:%d\n",
          return AVERROR_PATCHWELCOME;
      }
  
 -    if (s->v_max == 1 && s->h_max == 1 && s->lossless == 1)
 -        s->rgb = 1;
  
      /* if different size, realloc/alloc picture */
      if (width != s->width || height != s->height || bits != s->bits ||
          memcmp(s->h_count, h_count, sizeof(h_count))                ||
          memcmp(s->v_count, v_count, sizeof(v_count))) {
 +
          s->width      = width;
          s->height     = height;
          s->bits       = bits;
          memcpy(s->h_count, h_count, sizeof(h_count));
          memcpy(s->v_count, v_count, sizeof(v_count));
          s->interlaced = 0;
 +        s->got_picture = 0;
  
          /* test interlaced mode */
          if (s->first_picture   &&
          s->first_picture = 0;
      }
  
 -    if (!(s->interlaced && (s->bottom_field == !s->interlace_polarity))) {
 +    if (s->got_picture && s->interlaced && (s->bottom_field == !s->interlace_polarity)) {
 +        if (s->progressive) {
 +            avpriv_request_sample(s->avctx, "progressively coded interlaced picture");
 +            return AVERROR_INVALIDDATA;
 +        }
 +    } else{
 +        if (s->v_max == 1 && s->h_max == 1 && s->lossless==1 && (nb_components==3 || nb_components==4))
 +            s->rgb = 1;
 +        else if (!s->lossless)
 +            s->rgb = 0;
      /* XXX: not complete test ! */
 -    pix_fmt_id = (s->h_count[0] << 28) | (s->v_count[0] << 24) |
 +    pix_fmt_id = ((unsigned)s->h_count[0] << 28) | (s->v_count[0] << 24) |
                   (s->h_count[1] << 20) | (s->v_count[1] << 16) |
                   (s->h_count[2] << 12) | (s->v_count[2] <<  8) |
                   (s->h_count[3] <<  4) |  s->v_count[3];
      if (!(pix_fmt_id & 0x0D0D0D0D))
          pix_fmt_id -= (pix_fmt_id & 0x0F0F0F0F) >> 1;
  
 +    for (i = 0; i < 8; i++) {
 +        int j = 6 + (i&1) - (i&6);
 +        int is = (pix_fmt_id >> (4*i)) & 0xF;
 +        int js = (pix_fmt_id >> (4*j)) & 0xF;
 +
 +        if (is == 1 && js != 2 && (i < 2 || i > 5))
 +            js = (pix_fmt_id >> ( 8 + 4*(i&1))) & 0xF;
 +        if (is == 1 && js != 2 && (i < 2 || i > 5))
 +            js = (pix_fmt_id >> (16 + 4*(i&1))) & 0xF;
 +
 +        if (is == 1 && js == 2) {
 +            if (i & 1) s->upscale_h |= 1 << (j/2);
 +            else       s->upscale_v |= 1 << (j/2);
 +        }
 +    }
 +
      switch (pix_fmt_id) {
      case 0x11111100:
          if (s->rgb)
 -            s->avctx->pix_fmt = AV_PIX_FMT_BGRA;
 +            s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48;
          else {
 -            s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
 +            if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
 +                s->avctx->pix_fmt = s->bits <= 8 ? AV_PIX_FMT_GBRP : AV_PIX_FMT_GBRP16;
 +            } else {
 +                if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
 +                else              s->avctx->pix_fmt = AV_PIX_FMT_YUV444P16;
              s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +            }
          }
 -        assert(s->nb_components == 3);
 +        av_assert0(s->nb_components == 3);
 +        break;
 +    case 0x11111111:
 +        if (s->rgb)
 +            s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_ABGR : AV_PIX_FMT_RGBA64;
 +        else {
 +            if (s->adobe_transform == 0 && s->bits <= 8) {
 +                s->avctx->pix_fmt = AV_PIX_FMT_GBRAP;
 +            } else {
 +                s->avctx->pix_fmt = s->bits <= 8 ? AV_PIX_FMT_YUVA444P : AV_PIX_FMT_YUVA444P16;
 +                s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +            }
 +        }
 +        av_assert0(s->nb_components == 4);
 +        break;
 +    case 0x22111122:
 +    case 0x22111111:
 +        if (s->adobe_transform == 0 && s->bits <= 8) {
 +            s->avctx->pix_fmt = AV_PIX_FMT_GBRAP;
 +            s->upscale_v |= 6;
 +            s->upscale_h |= 6;
 +        } else if (s->adobe_transform == 2 && s->bits <= 8) {
 +            s->avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
 +            s->upscale_v |= 6;
 +            s->upscale_h |= 6;
 +            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        } else {
 +            if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
 +            else              s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
 +            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        }
 +        av_assert0(s->nb_components == 4);
 +        break;
 +    case 0x12121100:
 +    case 0x22122100:
 +    case 0x21211100:
 +    case 0x22211200:
 +        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
 +        else
 +            goto unk_pixfmt;
 +        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        break;
 +    case 0x22221100:
 +    case 0x22112200:
 +    case 0x11222200:
 +        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
 +        else
 +            goto unk_pixfmt;
 +        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
          break;
      case 0x11000000:
 -        s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
 +    case 0x13000000:
 +    case 0x14000000:
 +    case 0x31000000:
 +    case 0x33000000:
 +    case 0x34000000:
 +    case 0x41000000:
 +    case 0x43000000:
 +    case 0x44000000:
 +        if(s->bits <= 8)
 +            s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
 +        else
 +            s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
          break;
      case 0x12111100:
 -        s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
 -        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +    case 0x14121200:
 +    case 0x14111100:
 +    case 0x22211100:
 +    case 0x22112100:
 +        if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
 +            if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP;
 +            else
 +                goto unk_pixfmt;
 +            s->upscale_v |= 3;
 +        } else {
 +            if (pix_fmt_id == 0x14111100)
 +                s->upscale_v |= 6;
 +            if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
 +            else
 +                goto unk_pixfmt;
 +            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        }
          break;
      case 0x21111100:
 -        s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
 +        if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
 +            if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP;
 +            else
 +                goto unk_pixfmt;
 +            s->upscale_h |= 3;
 +        } else {
 +            if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
 +            else              s->avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
 +            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        }
 +        break;
 +    case 0x22121100:
 +    case 0x22111200:
 +        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
 +        else
 +            goto unk_pixfmt;
          s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
          break;
      case 0x22111100:
 -        s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P;
 +    case 0x42111100:
 +    case 0x24111100:
 +        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P;
 +        else              s->avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
 +        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
 +        if (pix_fmt_id == 0x42111100) {
 +            if (s->bits > 8)
 +                goto unk_pixfmt;
 +            s->upscale_h = 6;
 +        } else if (pix_fmt_id == 0x24111100) {
 +            if (s->bits > 8)
 +                goto unk_pixfmt;
 +            s->upscale_v = 6;
 +        }
 +        break;
 +    case 0x41111100:
 +        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV411P : AV_PIX_FMT_YUVJ411P;
 +        else
 +            goto unk_pixfmt;
          s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
          break;
      default:
 -        av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id);
 +unk_pixfmt:
 +        av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x bits:%d\n", pix_fmt_id, s->bits);
 +        s->upscale_h = s->upscale_v = 0;
 +        return AVERROR_PATCHWELCOME;
 +    }
 +    if ((s->upscale_h || s->upscale_v) && s->avctx->lowres) {
 +        av_log(s->avctx, AV_LOG_ERROR, "lowres not supported for weird subsampling\n");
          return AVERROR_PATCHWELCOME;
      }
      if (s->ls) {
 -        if (s->nb_components > 1)
 +        s->upscale_h = s->upscale_v = 0;
 +        if (s->nb_components == 3) {
              s->avctx->pix_fmt = AV_PIX_FMT_RGB24;
 +        } else if (s->nb_components != 1) {
 +            av_log(s->avctx, AV_LOG_ERROR, "Unsupported number of components %d\n", s->nb_components);
 +            return AVERROR_PATCHWELCOME;
 +        } else if (s->palette_index && s->bits <= 8)
 +            s->avctx->pix_fmt = AV_PIX_FMT_PAL8;
          else if (s->bits <= 8)
              s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
          else
      }
  
      av_frame_unref(s->picture_ptr);
 -    if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) {
 -        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +    if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0)
          return -1;
 -    }
      s->picture_ptr->pict_type = AV_PICTURE_TYPE_I;
      s->picture_ptr->key_frame = 1;
      s->got_picture            = 1;
  
 -    for (i = 0; i < 3; i++)
 +    for (i = 0; i < 4; i++)
          s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced;
  
      av_dlog(s->avctx, "%d %d %d %d %d %d\n",
          av_log(s->avctx, AV_LOG_DEBUG, "decode_sof0: error, len(%d) mismatch\n", len);
      }
  
 +    if (s->rgb && !s->lossless && !s->ls) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Unsupported coding and pixel format combination\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
      /* totally blank picture as progressive JPEG will only add details to it */
      if (s->progressive) {
          int bw = (width  + s->h_max * 8 - 1) / (s->h_max * 8);
              int size = bw * bh * s->h_count[i] * s->v_count[i];
              av_freep(&s->blocks[i]);
              av_freep(&s->last_nnz[i]);
 -            s->blocks[i]       = av_malloc(size * sizeof(**s->blocks));
 -            s->last_nnz[i]     = av_mallocz(size * sizeof(**s->last_nnz));
 +            s->blocks[i]       = av_mallocz_array(size, sizeof(**s->blocks));
 +            s->last_nnz[i]     = av_mallocz_array(size, sizeof(**s->last_nnz));
 +            if (!s->blocks[i] || !s->last_nnz[i])
 +                return AVERROR(ENOMEM);
              s->block_stride[i] = bw * s->h_count[i];
          }
          memset(s->coefs_finished, 0, sizeof(s->coefs_finished));
@@@ -623,11 -430,11 +623,11 @@@ static inline int mjpeg_decode_dc(MJpeg
  {
      int code;
      code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2);
 -    if (code < 0) {
 +    if (code < 0 || code > 16) {
          av_log(s->avctx, AV_LOG_WARNING,
                 "mjpeg_decode_dc: bad vlc: %d:%d (%p)\n",
                 0, dc_index, &s->vlcs[0][dc_index]);
 -        return 0xffff;
 +        return 0xfffff;
      }
  
      if (code)
@@@ -644,7 -451,7 +644,7 @@@ static int decode_block(MJpegDecodeCont
  
      /* DC coef */
      val = mjpeg_decode_dc(s, dc_index);
 -    if (val == 0xffff) {
 +    if (val == 0xfffff) {
          av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
          return AVERROR_INVALIDDATA;
      }
@@@ -692,7 -499,7 +692,7 @@@ static int decode_dc_progressive(MJpegD
      int val;
      s->bdsp.clear_block(block);
      val = mjpeg_decode_dc(s, dc_index);
 -    if (val == 0xffff) {
 +    if (val == 0xfffff) {
          av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
          return AVERROR_INVALIDDATA;
      }
@@@ -866,101 -673,46 +866,101 @@@ static int decode_block_refinement(MJpe
  #undef REFINE_BIT
  #undef ZERO_RUN
  
 -static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor,
 -                                 int point_transform)
 +static int handle_rstn(MJpegDecodeContext *s, int nb_components)
 +{
 +    int i;
 +    int reset = 0;
 +
 +    if (s->restart_interval) {
 +        s->restart_count--;
 +        if(s->restart_count == 0 && s->avctx->codec_id == AV_CODEC_ID_THP){
 +            align_get_bits(&s->gb);
 +            for (i = 0; i < nb_components; i++) /* reset dc */
 +                s->last_dc[i] = (4 << s->bits);
 +        }
 +
 +        i = 8 + ((-get_bits_count(&s->gb)) & 7);
 +        /* skip RSTn */
 +        if (s->restart_count == 0) {
 +            if(   show_bits(&s->gb, i) == (1 << i) - 1
 +               || show_bits(&s->gb, i) == 0xFF) {
 +                int pos = get_bits_count(&s->gb);
 +                align_get_bits(&s->gb);
 +                while (get_bits_left(&s->gb) >= 8 && show_bits(&s->gb, 8) == 0xFF)
 +                    skip_bits(&s->gb, 8);
 +                if (get_bits_left(&s->gb) >= 8 && (get_bits(&s->gb, 8) & 0xF8) == 0xD0) {
 +                    for (i = 0; i < nb_components; i++) /* reset dc */
 +                        s->last_dc[i] = (4 << s->bits);
 +                    reset = 1;
 +                } else
 +                    skip_bits_long(&s->gb, pos - get_bits_count(&s->gb));
 +            }
 +        }
 +    }
 +    return reset;
 +}
 +
 +static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform)
  {
      int i, mb_x, mb_y;
      uint16_t (*buffer)[4];
 -    int left[3], top[3], topleft[3];
 +    int left[4], top[4], topleft[4];
      const int linesize = s->linesize[0];
 -    const int mask     = (1 << s->bits) - 1;
 +    const int mask     = ((1 << s->bits) - 1) << point_transform;
 +    int resync_mb_y = 0;
 +    int resync_mb_x = 0;
 +
 +    if (s->nb_components != 3 && s->nb_components != 4)
 +        return AVERROR_INVALIDDATA;
 +    if (s->v_max != 1 || s->h_max != 1 || !s->lossless)
 +        return AVERROR_INVALIDDATA;
 +
 +
 +    s->restart_count = s->restart_interval;
  
      av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size,
                     (unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0]));
      buffer = s->ljpeg_buffer;
  
 -    for (i = 0; i < 3; i++)
 -        buffer[0][i] = 1 << (s->bits + point_transform - 1);
 +    for (i = 0; i < 4; i++)
 +        buffer[0][i] = 1 << (s->bits - 1);
  
      for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
 -        const int modified_predictor = mb_y ? predictor : 1;
          uint8_t *ptr = s->picture_ptr->data[0] + (linesize * mb_y);
  
          if (s->interlaced && s->bottom_field)
              ptr += linesize >> 1;
  
 -        for (i = 0; i < 3; i++)
 +        for (i = 0; i < 4; i++)
              top[i] = left[i] = topleft[i] = buffer[0][i];
  
          for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -            if (s->restart_interval && !s->restart_count)
 +            int modified_predictor = predictor;
 +
 +            if (s->restart_interval && !s->restart_count){
                  s->restart_count = s->restart_interval;
 +                resync_mb_x = mb_x;
 +                resync_mb_y = mb_y;
 +                for(i=0; i<4; i++)
 +                    top[i] = left[i]= topleft[i]= 1 << (s->bits - 1);
 +            }
 +            if (mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || !mb_x)
 +                modified_predictor = 1;
  
 -            for (i = 0; i < 3; i++) {
 -                int pred;
 +            for (i=0;i<nb_components;i++) {
 +                int pred, dc;
  
                  topleft[i] = top[i];
                  top[i]     = buffer[mb_x][i];
  
                  PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
  
 +                dc = mjpeg_decode_dc(s, s->dc_index[i]);
 +                if(dc == 0xFFFFF)
 +                    return -1;
 +
                  left[i] = buffer[mb_x][i] =
 -                    mask & (pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform));
 +                    mask & (pred + (dc << point_transform));
              }
  
              if (s->restart_interval && !--s->restart_count) {
                  skip_bits(&s->gb, 16); /* skip RSTn */
              }
          }
 -
 -        if (s->rct) {
 +        if (s->nb_components == 4) {
 +            for(i=0; i<nb_components; i++) {
 +                int c= s->comp_index[i];
 +                if (s->bits <= 8) {
 +                    for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
 +                        ptr[4*mb_x+3-c] = buffer[mb_x][i];
 +                    }
 +                } else if(s->bits == 9) {
 +                    return AVERROR_PATCHWELCOME;
 +                } else {
 +                    for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
 +                        ((uint16_t*)ptr)[4*mb_x+c] = buffer[mb_x][i];
 +                    }
 +                }
 +            }
 +        } else if (s->rct) {
              for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -                ptr[4 * mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200) >> 2);
 -                ptr[4 * mb_x + 0] = buffer[mb_x][1] + ptr[4 * mb_x + 1];
 -                ptr[4 * mb_x + 2] = buffer[mb_x][2] + ptr[4 * mb_x + 1];
 +                ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200) >> 2);
 +                ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1];
 +                ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1];
              }
          } else if (s->pegasus_rct) {
              for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -                ptr[4 * mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2]) >> 2);
 -                ptr[4 * mb_x + 0] = buffer[mb_x][1] + ptr[4 * mb_x + 1];
 -                ptr[4 * mb_x + 2] = buffer[mb_x][2] + ptr[4 * mb_x + 1];
 +                ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2]) >> 2);
 +                ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1];
 +                ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1];
              }
          } else {
 -            for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -                ptr[4 * mb_x + 0] = buffer[mb_x][2];
 -                ptr[4 * mb_x + 1] = buffer[mb_x][1];
 -                ptr[4 * mb_x + 2] = buffer[mb_x][0];
 +            for(i=0; i<nb_components; i++) {
 +                int c= s->comp_index[i];
 +                if (s->bits <= 8) {
 +                    for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
 +                        ptr[3*mb_x+2-c] = buffer[mb_x][i];
 +                    }
 +                } else if(s->bits == 9) {
 +                    return AVERROR_PATCHWELCOME;
 +                } else {
 +                    for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
 +                        ((uint16_t*)ptr)[3*mb_x+2-c] = buffer[mb_x][i];
 +                    }
 +                }
              }
          }
      }
  static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor,
                                   int point_transform, int nb_components)
  {
 -    int i, mb_x, mb_y;
 +    int i, mb_x, mb_y, mask;
 +    int bits= (s->bits+7)&~7;
 +    int resync_mb_y = 0;
 +    int resync_mb_x = 0;
 +
 +    point_transform += bits - s->bits;
 +    mask = ((1 << s->bits) - 1) << point_transform;
 +
 +    av_assert0(nb_components>=1 && nb_components<=4);
  
      for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
          for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -            if (s->restart_interval && !s->restart_count)
 +            if (s->restart_interval && !s->restart_count){
                  s->restart_count = s->restart_interval;
 +                resync_mb_x = mb_x;
 +                resync_mb_y = mb_y;
 +            }
  
 -            if (mb_x == 0 || mb_y == 0 || s->interlaced) {
 +            if(!mb_x || mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || s->interlaced){
 +                int toprow  = mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x;
 +                int leftcol = !mb_x || mb_y == resync_mb_y && mb_x == resync_mb_x;
                  for (i = 0; i < nb_components; i++) {
                      uint8_t *ptr;
 +                    uint16_t *ptr16;
                      int n, h, v, x, y, c, j, linesize;
 -                    n        = s->nb_blocks[i];
 -                    c        = s->comp_index[i];
 -                    h        = s->h_scount[i];
 -                    v        = s->v_scount[i];
 -                    x        = 0;
 -                    y        = 0;
 -                    linesize = s->linesize[c];
 -
 -                    for (j = 0; j < n; j++) {
 -                        int pred;
 -                        // FIXME optimize this crap
 -                        ptr = s->picture_ptr->data[c] +
 -                              (linesize * (v * mb_y + y)) +
 -                              (h * mb_x + x);
 -                        if (y == 0 && mb_y == 0) {
 -                            if (x == 0 && mb_x == 0)
 -                                pred = 128 << point_transform;
 -                            else
 -                                pred = ptr[-1];
 -                        } else {
 -                            if (x == 0 && mb_x == 0)
 -                                pred = ptr[-linesize];
 -                            else
 -                                PREDICT(pred, ptr[-linesize - 1],
 -                                        ptr[-linesize], ptr[-1], predictor);
 -                       }
 +                    n = s->nb_blocks[i];
 +                    c = s->comp_index[i];
 +                    h = s->h_scount[i];
 +                    v = s->v_scount[i];
 +                    x = 0;
 +                    y = 0;
 +                    linesize= s->linesize[c];
 +
 +                    if(bits>8) linesize /= 2;
 +
 +                    for(j=0; j<n; j++) {
 +                        int pred, dc;
 +
 +                        dc = mjpeg_decode_dc(s, s->dc_index[i]);
 +                        if(dc == 0xFFFFF)
 +                            return -1;
 +                        if(bits<=8){
 +                        ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
 +                        if(y==0 && toprow){
 +                            if(x==0 && leftcol){
 +                                pred= 1 << (bits - 1);
 +                            }else{
 +                                pred= ptr[-1];
 +                            }
 +                        }else{
 +                            if(x==0 && leftcol){
 +                                pred= ptr[-linesize];
 +                            }else{
 +                                PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
 +                            }
 +                        }
  
                          if (s->interlaced && s->bottom_field)
                              ptr += linesize >> 1;
 -                        *ptr = pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
 +                        pred &= mask;
 +                        *ptr= pred + (dc << point_transform);
 +                        }else{
 +                            ptr16 = (uint16_t*)(s->picture_ptr->data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap
 +                            if(y==0 && toprow){
 +                                if(x==0 && leftcol){
 +                                    pred= 1 << (bits - 1);
 +                                }else{
 +                                    pred= ptr16[-1];
 +                                }
 +                            }else{
 +                                if(x==0 && leftcol){
 +                                    pred= ptr16[-linesize];
 +                                }else{
 +                                    PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor);
 +                                }
 +                            }
  
 +                            if (s->interlaced && s->bottom_field)
 +                                ptr16 += linesize >> 1;
 +                            pred &= mask;
 +                            *ptr16= pred + (dc << point_transform);
 +                        }
                          if (++x == h) {
                              x = 0;
                              y++;
              } else {
                  for (i = 0; i < nb_components; i++) {
                      uint8_t *ptr;
 -                    int n, h, v, x, y, c, j, linesize;
 +                    uint16_t *ptr16;
 +                    int n, h, v, x, y, c, j, linesize, dc;
                      n        = s->nb_blocks[i];
                      c        = s->comp_index[i];
                      h        = s->h_scount[i];
                      y        = 0;
                      linesize = s->linesize[c];
  
 +                    if(bits>8) linesize /= 2;
 +
                      for (j = 0; j < n; j++) {
                          int pred;
  
 -                        // FIXME optimize this crap
 -                        ptr = s->picture_ptr->data[c] +
 +                        dc = mjpeg_decode_dc(s, s->dc_index[i]);
 +                        if(dc == 0xFFFFF)
 +                            return -1;
 +                        if(bits<=8){
 +                            ptr = s->picture_ptr->data[c] +
                                (linesize * (v * mb_y + y)) +
 -                              (h * mb_x + x);
 -                        PREDICT(pred, ptr[-linesize - 1],
 -                                ptr[-linesize], ptr[-1], predictor);
 -                        *ptr = pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
 +                              (h * mb_x + x); //FIXME optimize this crap
 +                            PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
 +
 +                            pred &= mask;
 +                            *ptr = pred + (dc << point_transform);
 +                        }else{
 +                            ptr16 = (uint16_t*)(s->picture_ptr->data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap
 +                            PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor);
 +
 +                            pred &= mask;
 +                            *ptr16= pred + (dc << point_transform);
 +                        }
 +
                          if (++x == h) {
                              x = 0;
                              y++;
      return 0;
  }
  
 +static av_always_inline void mjpeg_copy_block(MJpegDecodeContext *s,
 +                                              uint8_t *dst, const uint8_t *src,
 +                                              int linesize, int lowres)
 +{
 +    switch (lowres) {
 +    case 0: s->hdsp.put_pixels_tab[1][0](dst, src, linesize, 8);
 +        break;
 +    case 1: copy_block4(dst, src, linesize, linesize, 4);
 +        break;
 +    case 2: copy_block2(dst, src, linesize, linesize, 2);
 +        break;
 +    case 3: *dst = *src;
 +        break;
 +    }
 +}
 +
 +static void shift_output(MJpegDecodeContext *s, uint8_t *ptr, int linesize)
 +{
 +    int block_x, block_y;
 +    int size = 8 >> s->avctx->lowres;
 +    if (s->bits > 8) {
 +        for (block_y=0; block_y<size; block_y++)
 +            for (block_x=0; block_x<size; block_x++)
 +                *(uint16_t*)(ptr + 2*block_x + block_y*linesize) <<= 16 - s->bits;
 +    } else {
 +        for (block_y=0; block_y<size; block_y++)
 +            for (block_x=0; block_x<size; block_x++)
 +                *(ptr + block_x + block_y*linesize) <<= 8 - s->bits;
 +    }
 +}
 +
  static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
                               int Al, const uint8_t *mb_bitmask,
 +                             int mb_bitmask_size,
                               const AVFrame *reference)
  {
      int i, mb_x, mb_y;
      uint8_t *data[MAX_COMPONENTS];
      const uint8_t *reference_data[MAX_COMPONENTS];
      int linesize[MAX_COMPONENTS];
 -    GetBitContext mb_bitmask_gb;
 +    GetBitContext mb_bitmask_gb = {0}; // initialize to silence gcc warning
 +    int bytes_per_pixel = 1 + (s->bits > 8);
  
 -    if (mb_bitmask)
 +    if (mb_bitmask) {
 +        if (mb_bitmask_size != (s->mb_width * s->mb_height + 7)>>3) {
 +            av_log(s->avctx, AV_LOG_ERROR, "mb_bitmask_size mismatches\n");
 +            return AVERROR_INVALIDDATA;
 +        }
          init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height);
 +    }
 +
 +    s->restart_count = 0;
  
      for (i = 0; i < nb_components; i++) {
          int c   = s->comp_index[i];
                  x = 0;
                  y = 0;
                  for (j = 0; j < n; j++) {
 -                    block_offset = ((linesize[c] * (v * mb_y + y) * 8) +
 -                                    (h * mb_x + x) * 8);
 +                    block_offset = (((linesize[c] * (v * mb_y + y) * 8) +
 +                                     (h * mb_x + x) * 8 * bytes_per_pixel) >> s->avctx->lowres);
  
                      if (s->interlaced && s->bottom_field)
                          block_offset += linesize[c] >> 1;
 -                    ptr = data[c] + block_offset;
 +                    if (   8*(h * mb_x + x) < s->width
 +                        && 8*(v * mb_y + y) < s->height) {
 +                        ptr = data[c] + block_offset;
 +                    } else
 +                        ptr = NULL;
                      if (!s->progressive) {
 -                        if (copy_mb)
 -                            s->hdsp.put_pixels_tab[1][0](ptr,
 -                                reference_data[c] + block_offset,
 -                                linesize[c], 8);
 -                        else {
 +                        if (copy_mb) {
 +                            if (ptr)
 +                                mjpeg_copy_block(s, ptr, reference_data[c] + block_offset,
 +                                                linesize[c], s->avctx->lowres);
 +
 +                        } else {
                              s->bdsp.clear_block(s->block);
                              if (decode_block(s, s->block, i,
                                               s->dc_index[i], s->ac_index[i],
 -                                             s->quant_matrixes[s->quant_index[c]]) < 0) {
 +                                             s->quant_matrixes[s->quant_sindex[i]]) < 0) {
                                  av_log(s->avctx, AV_LOG_ERROR,
                                         "error y=%d x=%d\n", mb_y, mb_x);
                                  return AVERROR_INVALIDDATA;
                              }
 -                            s->idsp.idct_put(ptr, linesize[c], s->block);
 +                            if (ptr) {
 +                                s->idsp.idct_put(ptr, linesize[c], s->block);
 +                                if (s->bits & 7)
 +                                    shift_output(s, ptr, linesize[c]);
 +                            }
                          }
                      } else {
                          int block_idx  = s->block_stride[c] * (v * mb_y + y) +
                          int16_t *block = s->blocks[c][block_idx];
                          if (Ah)
                              block[0] += get_bits1(&s->gb) *
 -                                        s->quant_matrixes[s->quant_index[c]][0] << Al;
 +                                        s->quant_matrixes[s->quant_sindex[i]][0] << Al;
                          else if (decode_dc_progressive(s, block, i, s->dc_index[i],
 -                                                       s->quant_matrixes[s->quant_index[c]],
 +                                                       s->quant_matrixes[s->quant_sindex[i]],
                                                         Al) < 0) {
                              av_log(s->avctx, AV_LOG_ERROR,
                                     "error y=%d x=%d\n", mb_y, mb_x);
                  }
              }
  
 -            if (s->restart_interval) {
 -                s->restart_count--;
 -                i = 8 + ((-get_bits_count(&s->gb)) & 7);
 -                /* skip RSTn */
 -                if (show_bits(&s->gb, i) == (1 << i) - 1) {
 -                    int pos = get_bits_count(&s->gb);
 -                    align_get_bits(&s->gb);
 -                    while (get_bits_left(&s->gb) >= 8 && show_bits(&s->gb, 8) == 0xFF)
 -                        skip_bits(&s->gb, 8);
 -                    if ((get_bits(&s->gb, 8) & 0xF8) == 0xD0) {
 -                        for (i = 0; i < nb_components; i++) /* reset dc */
 -                            s->last_dc[i] = 1024;
 -                    } else
 -                        skip_bits_long(&s->gb, pos - get_bits_count(&s->gb));
 -                }
 -            }
 +            handle_rstn(s, nb_components);
          }
      }
      return 0;
  }
  
  static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
 -                                            int se, int Ah, int Al,
 -                                            const uint8_t *mb_bitmask,
 -                                            const AVFrame *reference)
 +                                            int se, int Ah, int Al)
  {
      int mb_x, mb_y;
      int EOBRUN = 0;
      int c = s->comp_index[0];
      uint8_t *data = s->picture_ptr->data[c];
 -    const uint8_t *reference_data = reference ? reference->data[c] : NULL;
      int linesize  = s->linesize[c];
      int last_scan = 0;
 -    int16_t *quant_matrix = s->quant_matrixes[s->quant_index[c]];
 -    GetBitContext mb_bitmask_gb;
 +    int16_t *quant_matrix = s->quant_matrixes[s->quant_sindex[0]];
 +    int bytes_per_pixel = 1 + (s->bits > 8);
  
 -    if (ss < 0  || ss >= 64 ||
 -        se < ss || se >= 64 ||
 -        Ah < 0  || Al < 0)
 +    av_assert0(ss>=0 && Ah>=0 && Al>=0);
 +    if (se < ss || se > 63) {
 +        av_log(s->avctx, AV_LOG_ERROR, "SS/SE %d/%d is invalid\n", ss, se);
          return AVERROR_INVALIDDATA;
 -
 -    if (mb_bitmask)
 -        init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height);
 +    }
  
      if (!Al) {
          // s->coefs_finished is a bitmask for coefficients coded
          // ss and se are parameters telling start and end coefficients
 -        s->coefs_finished[c] |= (~0ULL >> (63 - (se - ss))) << ss;
 +        s->coefs_finished[c] |= (2ULL << se) - (1ULL << ss);
          last_scan = !~s->coefs_finished[c];
      }
  
 -    if (s->interlaced && s->bottom_field) {
 -        int offset      = linesize >> 1;
 -        data           += offset;
 -        reference_data += offset;
 -    }
 +    if (s->interlaced && s->bottom_field)
 +        data += linesize >> 1;
 +
 +    s->restart_count = 0;
  
      for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
 -        int block_offset = mb_y * linesize * 8;
 -        uint8_t *ptr     = data + block_offset;
 +        uint8_t *ptr     = data + (mb_y * linesize * 8 >> s->avctx->lowres);
          int block_idx    = mb_y * s->block_stride[c];
          int16_t (*block)[64] = &s->blocks[c][block_idx];
          uint8_t *last_nnz    = &s->last_nnz[c][block_idx];
          for (mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) {
 -            const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb);
 -
 -            if (!copy_mb) {
                  int ret;
 +                if (s->restart_interval && !s->restart_count)
 +                    s->restart_count = s->restart_interval;
 +
                  if (Ah)
                      ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0],
                                                    quant_matrix, ss, se, Al, &EOBRUN);
                             "error y=%d x=%d\n", mb_y, mb_x);
                      return AVERROR_INVALIDDATA;
                  }
 -            }
  
              if (last_scan) {
 -                if (copy_mb) {
 -                    s->hdsp.put_pixels_tab[1][0](ptr,
 -                                                 reference_data + block_offset,
 -                                                 linesize, 8);
 -                } else {
                      s->idsp.idct_put(ptr, linesize, *block);
 -                    ptr += 8;
 -                }
 +                    if (s->bits & 7)
 +                        shift_output(s, ptr, linesize);
 +                    ptr += bytes_per_pixel*8 >> s->avctx->lowres;
              }
 +            if (handle_rstn(s, 0))
 +                EOBRUN = 0;
          }
      }
      return 0;
  }
  
  int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
 -                        const AVFrame *reference)
 +                        int mb_bitmask_size, const AVFrame *reference)
  {
      int len, nb_components, i, h, v, predictor, point_transform;
      int index, id, ret;
      const int block_size = s->lossless ? 1 : 8;
      int ilv, prev_shift;
  
 +    if (!s->got_picture) {
 +        av_log(s->avctx, AV_LOG_WARNING,
 +                "Can not process SOS before SOF, skipping\n");
 +        return -1;
 +    }
 +
 +    av_assert0(s->picture_ptr->data[0]);
      /* XXX: verify len field validity */
      len = get_bits(&s->gb, 16);
      nb_components = get_bits(&s->gb, 8);
              && nb_components == 3 && s->nb_components == 3 && i)
              index = 3 - i;
  
 -        s->comp_index[i] = index;
 -
 +        s->quant_sindex[i] = s->quant_index[index];
          s->nb_blocks[i] = s->h_count[index] * s->v_count[index];
          s->h_scount[i]  = s->h_count[index];
          s->v_scount[i]  = s->v_count[index];
  
 +        if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)
 +            index = (i+2)%3;
 +        if(nb_components == 1 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)
 +            index = (index+2)%3;
 +
 +        s->comp_index[i] = index;
 +
          s->dc_index[i] = get_bits(&s->gb, 4);
          s->ac_index[i] = get_bits(&s->gb, 4);
  
          if (s->dc_index[i] <  0 || s->ac_index[i] < 0 ||
              s->dc_index[i] >= 4 || s->ac_index[i] >= 4)
              goto out_of_range;
 -        if (!s->vlcs[0][s->dc_index[i]].table ||
 -            !s->vlcs[1][s->ac_index[i]].table)
 +        if (!s->vlcs[0][s->dc_index[i]].table || !(s->progressive ? s->vlcs[2][s->ac_index[0]].table : s->vlcs[1][s->ac_index[i]].table))
              goto out_of_range;
      }
  
      predictor = get_bits(&s->gb, 8);       /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */
      ilv = get_bits(&s->gb, 8);             /* JPEG Se / JPEG-LS ILV */
 -    prev_shift      = get_bits(&s->gb, 4); /* Ah */
 -    point_transform = get_bits(&s->gb, 4); /* Al */
 +    if(s->avctx->codec_tag != AV_RL32("CJPG")){
 +        prev_shift      = get_bits(&s->gb, 4); /* Ah */
 +        point_transform = get_bits(&s->gb, 4); /* Al */
 +    }else
 +        prev_shift = point_transform = 0;
  
      if (nb_components > 1) {
          /* interleaved stream */
      }
  
      if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 -        av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d %s\n",
 +        av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d skip:%d %s comp:%d\n",
                 s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "",
 -               predictor, point_transform, ilv, s->bits,
 -               s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""));
 +               predictor, point_transform, ilv, s->bits, s->mjpb_skiptosod,
 +               s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""), nb_components);
  
  
      /* mjpeg-b can have padding bytes between sos and image data, skip them */
  
  next_field:
      for (i = 0; i < nb_components; i++)
 -        s->last_dc[i] = 1024;
 +        s->last_dc[i] = (4 << s->bits);
  
      if (s->lossless) {
 +        av_assert0(s->picture_ptr == s->picture);
          if (CONFIG_JPEGLS_DECODER && s->ls) {
  //            for () {
  //            reset_ls_coding_parameters(s, 0);
                  return ret;
          } else {
              if (s->rgb) {
 -                if ((ret = ljpeg_decode_rgb_scan(s, predictor,
 -                                                 point_transform)) < 0)
 +                if ((ret = ljpeg_decode_rgb_scan(s, nb_components, predictor, point_transform)) < 0)
                      return ret;
              } else {
                  if ((ret = ljpeg_decode_yuv_scan(s, predictor,
          }
      } else {
          if (s->progressive && predictor) {
 +            av_assert0(s->picture_ptr == s->picture);
              if ((ret = mjpeg_decode_scan_progressive_ac(s, predictor,
                                                          ilv, prev_shift,
 -                                                        point_transform,
 -                                                        mb_bitmask,
 -                                                        reference)) < 0)
 +                                                        point_transform)) < 0)
                  return ret;
          } else {
              if ((ret = mjpeg_decode_scan(s, nb_components,
                                           prev_shift, point_transform,
 -                                         mb_bitmask, reference)) < 0)
 +                                         mb_bitmask, mb_bitmask_size, reference)) < 0)
                  return ret;
          }
      }
          GetBitContext bak = s->gb;
          align_get_bits(&bak);
          if (show_bits(&bak, 16) == 0xFFD1) {
 -            av_dlog(s->avctx, "AVRn interlaced picture marker found\n");
 +            av_log(s->avctx, AV_LOG_DEBUG, "AVRn interlaced picture marker found\n");
              s->gb = bak;
              skip_bits(&s->gb, 16);
              s->bottom_field ^= 1;
@@@ -1548,24 -1184,22 +1548,24 @@@ static int mjpeg_decode_app(MJpegDecode
      int len, id, i;
  
      len = get_bits(&s->gb, 16);
 -    if (len < 5)
 +    if (len < 6)
          return AVERROR_INVALIDDATA;
      if (8 * len > get_bits_left(&s->gb))
          return AVERROR_INVALIDDATA;
  
      id   = get_bits_long(&s->gb, 32);
 -    id   = av_be2ne32(id);
      len -= 6;
  
 -    if (s->avctx->debug & FF_DEBUG_STARTCODE)
 -        av_log(s->avctx, AV_LOG_DEBUG, "APPx %8X\n", id);
 +    if (s->avctx->debug & FF_DEBUG_STARTCODE) {
 +        char id_str[32];
 +        av_get_codec_tag_string(id_str, sizeof(id_str), av_bswap32(id));
 +        av_log(s->avctx, AV_LOG_DEBUG, "APPx (%s / %8X) len=%d\n", id_str, id, len);
 +    }
  
      /* Buggy AVID, it puts EOI only at every 10th frame. */
      /* Also, this fourcc is used by non-avid files too, it holds some
         information, but it's always present in AVID-created files. */
 -    if (id == AV_RL32("AVI1")) {
 +    if (id == AV_RB32("AVI1")) {
          /* structure:
              4bytes      AVI1
              1bytes      polarity
              4bytes      field_size
              4bytes      field_size_less_padding
          */
 -        s->buggy_avid = 1;
 -        i = get_bits(&s->gb, 8);
 -        if (i == 2)
 -            s->bottom_field = 1;
 -        else if (i == 1)
 -            s->bottom_field = 0;
 +            s->buggy_avid = 1;
 +        i = get_bits(&s->gb, 8); len--;
 +        av_log(s->avctx, AV_LOG_DEBUG, "polarity %d\n", i);
  #if 0
          skip_bits(&s->gb, 8);
          skip_bits(&s->gb, 32);
  
  //    len -= 2;
  
 -    if (id == AV_RL32("JFIF")) {
 +    if (id == AV_RB32("JFIF")) {
          int t_w, t_h, v1, v2;
          skip_bits(&s->gb, 8); /* the trailing zero-byte */
          v1 = get_bits(&s->gb, 8);
          goto out;
      }
  
 -    if (id == AV_RL32("Adob") && (get_bits(&s->gb, 8) == 'e')) {
 -        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 -            av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n");
 +    if (id == AV_RB32("Adob") && (get_bits(&s->gb, 8) == 'e')) {
          skip_bits(&s->gb, 16); /* version */
          skip_bits(&s->gb, 16); /* flags0 */
          skip_bits(&s->gb, 16); /* flags1 */
 -        skip_bits(&s->gb,  8); /* transform */
 +        s->adobe_transform = get_bits(&s->gb,  8);
 +        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 +            av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found, transform=%d\n", s->adobe_transform);
          len -= 7;
          goto out;
      }
  
 -    if (id == AV_RL32("LJIF")) {
 +    if (id == AV_RB32("LJIF")) {
 +        int rgb = s->rgb;
 +        int pegasus_rct = s->pegasus_rct;
          if (s->avctx->debug & FF_DEBUG_PICT_INFO)
              av_log(s->avctx, AV_LOG_INFO,
                     "Pegasus lossless jpeg header found\n");
          skip_bits(&s->gb, 16); /* version ? */
 -        skip_bits(&s->gb, 16); /* unknwon always 0? */
 -        skip_bits(&s->gb, 16); /* unknwon always 0? */
 -        skip_bits(&s->gb, 16); /* unknwon always 0? */
 -        switch (get_bits(&s->gb, 8)) {
 +        skip_bits(&s->gb, 16); /* unknown always 0? */
 +        skip_bits(&s->gb, 16); /* unknown always 0? */
 +        skip_bits(&s->gb, 16); /* unknown always 0? */
 +        switch (i=get_bits(&s->gb, 8)) {
          case 1:
 -            s->rgb         = 1;
 -            s->pegasus_rct = 0;
 +            rgb         = 1;
 +            pegasus_rct = 0;
              break;
          case 2:
 -            s->rgb         = 1;
 -            s->pegasus_rct = 1;
 +            rgb         = 1;
 +            pegasus_rct = 1;
              break;
          default:
 -            av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n");
 +            av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace %d\n", i);
          }
 +
          len -= 9;
 +        if (s->got_picture)
 +            if (rgb != s->rgb || pegasus_rct != s->pegasus_rct) {
 +                av_log(s->avctx, AV_LOG_WARNING, "Mismatching LJIF tag\n");
 +                goto out;
 +            }
 +
 +        s->rgb = rgb;
 +        s->pegasus_rct = pegasus_rct;
 +
 +        goto out;
 +    }
 +    if (id == AV_RL32("colr") && len > 0) {
 +        s->colr = get_bits(&s->gb, 8);
 +        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 +            av_log(s->avctx, AV_LOG_INFO, "COLR %d\n", s->colr);
 +        len --;
 +        goto out;
 +    }
 +    if (id == AV_RL32("xfrm") && len > 0) {
 +        s->xfrm = get_bits(&s->gb, 8);
 +        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 +            av_log(s->avctx, AV_LOG_INFO, "XFRM %d\n", s->xfrm);
 +        len --;
 +        goto out;
 +    }
 +
 +    /* JPS extension by VRex */
 +    if (s->start_code == APP3 && id == AV_RB32("_JPS") && len >= 10) {
 +        int flags, layout, type;
 +        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 +            av_log(s->avctx, AV_LOG_INFO, "_JPSJPS_\n");
 +
 +        skip_bits(&s->gb, 32); len -= 4;  /* JPS_ */
 +        skip_bits(&s->gb, 16); len -= 2;  /* block length */
 +        skip_bits(&s->gb, 8);             /* reserved */
 +        flags  = get_bits(&s->gb, 8);
 +        layout = get_bits(&s->gb, 8);
 +        type   = get_bits(&s->gb, 8);
 +        len -= 4;
 +
 +        s->stereo3d = av_stereo3d_alloc();
 +        if (!s->stereo3d) {
 +            goto out;
 +        }
 +        if (type == 0) {
 +            s->stereo3d->type = AV_STEREO3D_2D;
 +        } else if (type == 1) {
 +            switch (layout) {
 +            case 0x01:
 +                s->stereo3d->type = AV_STEREO3D_LINES;
 +                break;
 +            case 0x02:
 +                s->stereo3d->type = AV_STEREO3D_SIDEBYSIDE;
 +                break;
 +            case 0x03:
 +                s->stereo3d->type = AV_STEREO3D_TOPBOTTOM;
 +                break;
 +            }
 +            if (!(flags & 0x04)) {
 +                s->stereo3d->flags = AV_STEREO3D_FLAG_INVERT;
 +            }
 +        }
 +        goto out;
 +    }
 +
 +    /* EXIF metadata */
 +    if (s->start_code == APP1 && id == AV_RB32("Exif") && len >= 2) {
 +        GetByteContext gbytes;
 +        int ret, le, ifd_offset, bytes_read;
 +        const uint8_t *aligned;
 +
 +        skip_bits(&s->gb, 16); // skip padding
 +        len -= 2;
 +
 +        // init byte wise reading
 +        aligned = align_get_bits(&s->gb);
 +        bytestream2_init(&gbytes, aligned, len);
 +
 +        // read TIFF header
 +        ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
 +        if (ret) {
 +            av_log(s->avctx, AV_LOG_ERROR, "mjpeg: invalid TIFF header in EXIF data\n");
 +        } else {
 +            bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
 +
 +            // read 0th IFD and store the metadata
 +            // (return values > 0 indicate the presence of subimage metadata)
 +            ret = avpriv_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata);
 +            if (ret < 0) {
 +                av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n");
 +            }
 +        }
 +
 +        bytes_read = bytestream2_tell(&gbytes);
 +        skip_bits(&s->gb, bytes_read << 3);
 +        len -= bytes_read;
 +
          goto out;
      }
  
      /* Apple MJPEG-A */
      if ((s->start_code == APP1) && (len > (0x28 - 8))) {
          id   = get_bits_long(&s->gb, 32);
 -        id   = av_be2ne32(id);
          len -= 4;
          /* Apple MJPEG-A */
 -        if (id == AV_RL32("mjpg")) {
 +        if (id == AV_RB32("mjpg")) {
  #if 0
              skip_bits(&s->gb, 32); /* field size */
              skip_bits(&s->gb, 32); /* pad field size */
@@@ -1798,15 -1336,15 +1798,15 @@@ static int mjpeg_decode_com(MJpegDecode
                  cbuf[i] = 0;
  
              if (s->avctx->debug & FF_DEBUG_PICT_INFO)
 -                av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf);
 +                av_log(s->avctx, AV_LOG_INFO, "comment: '%s'\n", cbuf);
  
              /* buggy avid, it puts EOI only at every 10th frame */
 -            if (!strcmp(cbuf, "AVID")) {
 -                s->buggy_avid = 1;
 +            if (!strncmp(cbuf, "AVID", 4)) {
 +                parse_avid(s, cbuf, len);
              } else if (!strcmp(cbuf, "CS=ITU601"))
                  s->cs_itu601 = 1;
 -            else if ((len > 20 && !strncmp(cbuf, "Intel(R) JPEG Library", 21)) ||
 -                     (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
 +            else if ((!strncmp(cbuf, "Intel(R) JPEG Library, version 1", 32) && s->avctx->codec_tag) ||
 +                     (!strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
                  s->flipped = 1;
  
              av_free(cbuf);
@@@ -1823,19 -1361,22 +1823,19 @@@ static int find_marker(const uint8_t **
      const uint8_t *buf_ptr;
      unsigned int v, v2;
      int val;
 -#ifdef DEBUG
      int skipped = 0;
 -#endif
  
      buf_ptr = *pbuf_ptr;
 -    while (buf_ptr < buf_end) {
 +    while (buf_end - buf_ptr > 1) {
          v  = *buf_ptr++;
          v2 = *buf_ptr;
          if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
              val = *buf_ptr++;
              goto found;
          }
 -#ifdef DEBUG
          skipped++;
 -#endif
      }
 +    buf_ptr = buf_end;
      val = -1;
  found:
      av_dlog(NULL, "find_marker skipped %d bytes\n", skipped);
@@@ -1881,7 -1422,7 +1881,7 @@@ int ff_mjpeg_find_marker(MJpegDecodeCon
          memset(s->buffer + *unescaped_buf_size, 0,
                 FF_INPUT_BUFFER_PADDING_SIZE);
  
 -        av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",
 +        av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %"PTRDIFF_SPECIFIER" bytes\n",
                 (buf_end - *buf_ptr) - (dst - s->buffer));
      } else if (start_code == SOS && s->ls) {
          const uint8_t *src = *buf_ptr;
          int t = 0, b = 0;
          PutBitContext pb;
  
 -        s->cur_scan++;
 -
          /* find marker */
          while (src + t < buf_end) {
              uint8_t x = src[t++];
                  while ((src + t < buf_end) && x == 0xff)
                      x = src[t++];
                  if (x & 0x80) {
 -                    t -= 2;
 +                    t -= FFMIN(2, t);
                      break;
                  }
              }
              put_bits(&pb, 8, x);
              if (x == 0xFF) {
                  x = src[b++];
 +                if (x & 0x80) {
 +                    av_log(s->avctx, AV_LOG_WARNING, "Invalid escape sequence\n");
 +                    x &= 0x7f;
 +                }
                  put_bits(&pb, 7, x);
                  bit_count--;
              }
@@@ -1942,17 -1481,11 +1942,17 @@@ int ff_mjpeg_decode_frame(AVCodecContex
      MJpegDecodeContext *s = avctx->priv_data;
      const uint8_t *buf_end, *buf_ptr;
      const uint8_t *unescaped_buf_ptr;
 +    int hshift, vshift;
      int unescaped_buf_size;
      int start_code;
 +    int i, index;
      int ret = 0;
 +    int is16bit;
 +
 +    av_dict_free(&s->exif_metadata);
 +    av_freep(&s->stereo3d);
 +    s->adobe_transform = -1;
  
 -    s->got_picture = 0; // picture from previous image can not be reused
      buf_ptr = buf;
      buf_end = buf + buf_size;
      while (buf_ptr < buf_end) {
                                            &unescaped_buf_size);
          /* EOF */
          if (start_code < 0) {
 -            goto the_end;
 +            break;
          } else if (unescaped_buf_size > INT_MAX / 8) {
              av_log(avctx, AV_LOG_ERROR,
                     "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n",
                     start_code, unescaped_buf_size, buf_size);
              return AVERROR_INVALIDDATA;
          }
 -
 -        av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n",
 +        av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n",
                 start_code, buf_end - buf_ptr);
  
 -        ret = init_get_bits(&s->gb, unescaped_buf_ptr,
 -                            unescaped_buf_size * 8);
 -        if (ret < 0)
 -            return ret;
 +        ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size);
 +
 +        if (ret < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "invalid buffer\n");
 +            goto fail;
 +        }
  
          s->start_code = start_code;
          if (s->avctx->debug & FF_DEBUG_STARTCODE)
          else if (start_code == COM)
              mjpeg_decode_com(s);
  
 +        ret = -1;
 +
          if (!CONFIG_JPEGLS_DECODER &&
              (start_code == SOF48 || start_code == LSE)) {
              av_log(avctx, AV_LOG_ERROR, "JPEG-LS support not enabled.\n");
          case DHT:
              if ((ret = ff_mjpeg_decode_dht(s)) < 0) {
                  av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n");
 -                return ret;
 +                goto fail;
              }
              break;
          case SOF0:
              s->ls          = 0;
              s->progressive = 0;
              if ((ret = ff_mjpeg_decode_sof(s)) < 0)
 -                return ret;
 +                goto fail;
              break;
          case SOF2:
              s->lossless    = 0;
              s->ls          = 0;
              s->progressive = 1;
              if ((ret = ff_mjpeg_decode_sof(s)) < 0)
 -                return ret;
 +                goto fail;
              break;
          case SOF3:
              s->lossless    = 1;
              s->ls          = 0;
              s->progressive = 0;
              if ((ret = ff_mjpeg_decode_sof(s)) < 0)
 -                return ret;
 +                goto fail;
              break;
          case SOF48:
              s->lossless    = 1;
              s->ls          = 1;
              s->progressive = 0;
              if ((ret = ff_mjpeg_decode_sof(s)) < 0)
 -                return ret;
 +                goto fail;
              break;
          case LSE:
              if (!CONFIG_JPEGLS_DECODER ||
                  (ret = ff_jpegls_decode_lse(s)) < 0)
 -                return ret;
 +                goto fail;
              break;
          case EOI:
 -            s->cur_scan = 0;
 -            if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
 -                break;
  eoi_parser:
 +            s->cur_scan = 0;
              if (!s->got_picture) {
                  av_log(avctx, AV_LOG_WARNING,
                         "Found EOI before any SOF, ignoring\n");
                  s->bottom_field ^= 1;
                  /* if not bottom field, do not output image yet */
                  if (s->bottom_field == !s->interlace_polarity)
 -                    goto not_the_end;
 +                    break;
              }
              if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0)
                  return ret;
 -            if (s->flipped) {
 -                int i;
 -                for (i = 0; frame->data[i]; i++) {
 -                    int h = frame->height >> ((i == 1 || i == 2) ?
 -                                              s->pix_desc->log2_chroma_h : 0);
 -                    frame->data[i] += frame->linesize[i] * (h - 1);
 -                    frame->linesize[i] *= -1;
 -                }
 -            }
              *got_frame = 1;
 +            s->got_picture = 0;
 +
 +            if (!s->lossless) {
 +                int qp = FFMAX3(s->qscale[0],
 +                                s->qscale[1],
 +                                s->qscale[2]);
 +                int qpw = (s->width + 15) / 16;
 +                AVBufferRef *qp_table_buf = av_buffer_alloc(qpw);
 +                if (qp_table_buf) {
 +                    memset(qp_table_buf->data, qp, qpw);
 +                    av_frame_set_qp_table(data, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1);
 +                }
  
 -            if (!s->lossless &&
 -                avctx->debug & FF_DEBUG_QP) {
 -                av_log(avctx, AV_LOG_DEBUG,
 -                       "QP: %d\n", FFMAX3(s->qscale[0],
 -                                          s->qscale[1],
 -                                          s->qscale[2]));
 +                if(avctx->debug & FF_DEBUG_QP)
 +                    av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp);
              }
  
              goto the_end;
          case SOS:
 -            if (!s->got_picture) {
 -                av_log(avctx, AV_LOG_WARNING,
 -                       "Can not process SOS before SOF, skipping\n");
 -                break;
 -                }
 -            if ((ret = ff_mjpeg_decode_sos(s, NULL, NULL)) < 0 &&
 +            s->cur_scan++;
 +            if ((ret = ff_mjpeg_decode_sos(s, NULL, 0, NULL)) < 0 &&
                  (avctx->err_recognition & AV_EF_EXPLODE))
 -                return ret;
 -            /* buggy avid puts EOI every 10-20th frame */
 -            /* if restart period is over process EOI */
 -            if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
 -                goto eoi_parser;
 +                goto fail;
              break;
          case DRI:
              mjpeg_decode_dri(s);
              break;
          }
  
 -not_the_end:
          /* eof process start code */
          buf_ptr += (get_bits_count(&s->gb) + 7) / 8;
          av_log(avctx, AV_LOG_DEBUG,
                 "marker parser used %d bytes (%d bits)\n",
                 (get_bits_count(&s->gb) + 7) / 8, get_bits_count(&s->gb));
      }
 -    if (s->got_picture) {
 +    if (s->got_picture && s->cur_scan) {
          av_log(avctx, AV_LOG_WARNING, "EOI missing, emulating\n");
          goto eoi_parser;
      }
      av_log(avctx, AV_LOG_FATAL, "No JPEG data found in image\n");
      return AVERROR_INVALIDDATA;
 +fail:
 +    s->got_picture = 0;
 +    return ret;
  the_end:
 -    av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %td bytes\n",
 +
 +    is16bit = av_pix_fmt_desc_get(s->avctx->pix_fmt)->comp[0].step_minus1;
 +
 +    if (s->upscale_h) {
 +        int p;
 +        av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV444P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVJ440P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV440P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA444P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVJ420P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV420P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV420P16||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P16||
 +                   avctx->pix_fmt == AV_PIX_FMT_GBRP     ||
 +                   avctx->pix_fmt == AV_PIX_FMT_GBRAP
 +                  );
 +        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
 +        for (p = 0; p<4; p++) {
 +            uint8_t *line = s->picture_ptr->data[p];
 +            int w = s->width;
 +            int h = s->height;
 +            if (!(s->upscale_h & (1<<p)))
 +                continue;
 +            if (p==1 || p==2) {
 +                w = FF_CEIL_RSHIFT(w, hshift);
 +                h = FF_CEIL_RSHIFT(h, vshift);
 +            }
 +            if (s->upscale_v & (1<<p))
 +                h = (h+1)>>1;
 +            av_assert0(w > 0);
 +            for (i = 0; i < h; i++) {
 +                if (is16bit) ((uint16_t*)line)[w - 1] = ((uint16_t*)line)[(w - 1) / 2];
 +                else                      line[w - 1] = line[(w - 1) / 2];
 +                for (index = w - 2; index > 0; index--) {
 +                    if (is16bit)
 +                        ((uint16_t*)line)[index] = (((uint16_t*)line)[index / 2] + ((uint16_t*)line)[(index + 1) / 2]) >> 1;
 +                    else
 +                        line[index] = (line[index / 2] + line[(index + 1) / 2]) >> 1;
 +                }
 +                line += s->linesize[p];
 +            }
 +        }
 +    }
 +    if (s->upscale_v) {
 +        int p;
 +        av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV444P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVJ422P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV422P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVJ420P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV420P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUV440P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVJ440P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA444P ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P  ||
 +                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P16||
 +                   avctx->pix_fmt == AV_PIX_FMT_GBRP     ||
 +                   avctx->pix_fmt == AV_PIX_FMT_GBRAP
 +                   );
 +        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
 +        for (p = 0; p < 4; p++) {
 +            uint8_t *dst;
 +            int w = s->width;
 +            int h = s->height;
 +            if (!(s->upscale_v & (1<<p)))
 +                continue;
 +            if (p==1 || p==2) {
 +                w = FF_CEIL_RSHIFT(w, hshift);
 +                h = FF_CEIL_RSHIFT(h, vshift);
 +            }
 +            dst = &((uint8_t *)s->picture_ptr->data[p])[(h - 1) * s->linesize[p]];
 +            for (i = h - 1; i; i--) {
 +                uint8_t *src1 = &((uint8_t *)s->picture_ptr->data[p])[i / 2 * s->linesize[p]];
 +                uint8_t *src2 = &((uint8_t *)s->picture_ptr->data[p])[(i + 1) / 2 * s->linesize[p]];
 +                if (src1 == src2 || i == h - 1) {
 +                    memcpy(dst, src1, w);
 +                } else {
 +                    for (index = 0; index < w; index++)
 +                        dst[index] = (src1[index] + src2[index]) >> 1;
 +                }
 +                dst -= s->linesize[p];
 +            }
 +        }
 +    }
 +    if (s->flipped) {
 +        int j;
 +        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
 +        for (index=0; index<4; index++) {
 +            uint8_t *dst = s->picture_ptr->data[index];
 +            int w = s->picture_ptr->width;
 +            int h = s->picture_ptr->height;
 +            if(index && index<3){
 +                w = FF_CEIL_RSHIFT(w, hshift);
 +                h = FF_CEIL_RSHIFT(h, vshift);
 +            }
 +            if(dst){
 +                uint8_t *dst2 = dst + s->picture_ptr->linesize[index]*(h-1);
 +                for (i=0; i<h/2; i++) {
 +                    for (j=0; j<w; j++)
 +                        FFSWAP(int, dst[j], dst2[j]);
 +                    dst  += s->picture_ptr->linesize[index];
 +                    dst2 -= s->picture_ptr->linesize[index];
 +                }
 +            }
 +        }
 +    }
 +    if (s->adobe_transform == 0 && s->avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
 +        int w = s->picture_ptr->width;
 +        int h = s->picture_ptr->height;
 +        for (i=0; i<h; i++) {
 +            int j;
 +            uint8_t *dst[4];
 +            for (index=0; index<4; index++) {
 +                dst[index] =   s->picture_ptr->data[index]
 +                             + s->picture_ptr->linesize[index]*i;
 +            }
 +            for (j=0; j<w; j++) {
 +                int k = dst[3][j];
 +                int r = dst[0][j] * k;
 +                int g = dst[1][j] * k;
 +                int b = dst[2][j] * k;
 +                dst[0][j] = g*257 >> 16;
 +                dst[1][j] = b*257 >> 16;
 +                dst[2][j] = r*257 >> 16;
 +                dst[3][j] = 255;
 +            }
 +        }
 +    }
 +    if (s->adobe_transform == 2 && s->avctx->pix_fmt == AV_PIX_FMT_YUVA444P) {
 +        int w = s->picture_ptr->width;
 +        int h = s->picture_ptr->height;
 +        for (i=0; i<h; i++) {
 +            int j;
 +            uint8_t *dst[4];
 +            for (index=0; index<4; index++) {
 +                dst[index] =   s->picture_ptr->data[index]
 +                             + s->picture_ptr->linesize[index]*i;
 +            }
 +            for (j=0; j<w; j++) {
 +                int k = dst[3][j];
 +                int r = (255 - dst[0][j]) * k;
 +                int g = (128 - dst[1][j]) * k;
 +                int b = (128 - dst[2][j]) * k;
 +                dst[0][j] = r*257 >> 16;
 +                dst[1][j] = (g*257 >> 16) + 128;
 +                dst[2][j] = (b*257 >> 16) + 128;
 +                dst[3][j] = 255;
 +            }
 +        }
 +    }
 +
 +    if (s->stereo3d) {
 +        AVStereo3D *stereo = av_stereo3d_create_side_data(data);
 +        if (stereo) {
 +            stereo->type  = s->stereo3d->type;
 +            stereo->flags = s->stereo3d->flags;
 +        }
 +        av_freep(&s->stereo3d);
 +    }
 +
 +    av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0);
 +    av_dict_free(&s->exif_metadata);
 +
 +    av_log(avctx, AV_LOG_DEBUG, "decode frame unused %"PTRDIFF_SPECIFIER" bytes\n",
             buf_end - buf_ptr);
  //  return buf_end - buf_ptr;
      return buf_ptr - buf;
@@@ -2302,18 -1676,13 +2302,18 @@@ av_cold int ff_mjpeg_decode_end(AVCodec
      MJpegDecodeContext *s = avctx->priv_data;
      int i, j;
  
 +    if (s->interlaced && s->bottom_field == !s->interlace_polarity && s->got_picture && !avctx->frame_number) {
 +        av_log(avctx, AV_LOG_INFO, "Single field\n");
 +    }
 +
      if (s->picture) {
          av_frame_free(&s->picture);
          s->picture_ptr = NULL;
      } else if (s->picture_ptr)
          av_frame_unref(s->picture_ptr);
  
 -    av_free(s->buffer);
 +    av_freep(&s->buffer);
 +    av_freep(&s->stereo3d);
      av_freep(&s->ljpeg_buffer);
      s->ljpeg_buffer_size = 0;
  
          av_freep(&s->blocks[i]);
          av_freep(&s->last_nnz[i]);
      }
 +    av_dict_free(&s->exif_metadata);
      return 0;
  }
  
 +static void decode_flush(AVCodecContext *avctx)
 +{
 +    MJpegDecodeContext *s = avctx->priv_data;
 +    s->got_picture = 0;
 +}
 +
 +#if CONFIG_MJPEG_DECODER
  #define OFFSET(x) offsetof(MJpegDecodeContext, x)
  #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  static const AVOption options[] = {
@@@ -2360,13 -1721,11 +2360,14 @@@ AVCodec ff_mjpeg_decoder = 
      .init           = ff_mjpeg_decode_init,
      .close          = ff_mjpeg_decode_end,
      .decode         = ff_mjpeg_decode_frame,
 +    .flush          = decode_flush,
      .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
      .priv_class     = &mjpegdec_class,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
 -
 +#endif
 +#if CONFIG_THP_DECODER
  AVCodec ff_thp_decoder = {
      .name           = "thp",
      .long_name      = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"),
      .init           = ff_mjpeg_decode_init,
      .close          = ff_mjpeg_decode_end,
      .decode         = ff_mjpeg_decode_frame,
 +    .flush          = decode_flush,
      .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
 +#endif
diff --combined libavcodec/mxpegdec.c
@@@ -2,20 -2,20 +2,20 @@@
   * MxPEG decoder
   * Copyright (c) 2011 Anatoly Nenashev
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -54,7 -54,6 +54,7 @@@ static av_cold int mxpeg_decode_end(AVC
      for (i = 0; i < 2; ++i)
          av_frame_free(&s->picture[i]);
  
 +    s->bitmask_size = 0;
      av_freep(&s->mxm_bitmask);
      av_freep(&s->completion_bitmask);
  
@@@ -106,7 -105,6 +106,7 @@@ static int mxpeg_decode_mxm(MXpegDecode
      }
  
      if (s->bitmask_size != bitmask_size) {
 +        s->bitmask_size = 0;
          av_freep(&s->mxm_bitmask);
          s->mxm_bitmask = av_malloc(bitmask_size);
          if (!s->mxm_bitmask) {
@@@ -274,9 -272,11 +274,9 @@@ static int mxpeg_decode_frame(AVCodecCo
                      }
                      /* use stored SOF data to allocate current picture */
                      av_frame_unref(jpg->picture_ptr);
 -                    if (ff_get_buffer(avctx, jpg->picture_ptr,
 -                                      AV_GET_BUFFER_FLAG_REF) < 0) {
 -                        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -                        return AVERROR(ENOMEM);
 -                    }
 +                    if ((ret = ff_get_buffer(avctx, jpg->picture_ptr,
 +                                             AV_GET_BUFFER_FLAG_REF)) < 0)
 +                        return ret;
                      jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_P;
                      jpg->picture_ptr->key_frame = 0;
                      jpg->got_picture = 1;
  
                      /* allocate dummy reference picture if needed */
                      if (!reference_ptr->data[0] &&
 -                        ff_get_buffer(avctx, reference_ptr,
 -                                      AV_GET_BUFFER_FLAG_REF) < 0) {
 -                        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -                        return AVERROR(ENOMEM);
 -                    }
 +                        (ret = ff_get_buffer(avctx, reference_ptr,
 +                                             AV_GET_BUFFER_FLAG_REF)) < 0)
 +                        return ret;
  
 -                    ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr);
 +                    ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, s->bitmask_size, reference_ptr);
                      if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
                          return ret;
                  } else {
 -                    ret = ff_mjpeg_decode_sos(jpg, NULL, NULL);
 +                    ret = ff_mjpeg_decode_sos(jpg, NULL, 0, NULL);
                      if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
                          return ret;
                  }
@@@ -344,5 -346,5 +344,6 @@@ AVCodec ff_mxpeg_decoder = 
      .close          = mxpeg_decode_end,
      .decode         = mxpeg_decode_frame,
      .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
diff --combined libavcodec/sp5xdec.c
@@@ -2,20 -2,20 +2,20 @@@
   * Sunplus JPEG decoder (SP5X)
   * Copyright (c) 2003 Alex Beregszaszi
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -25,6 -25,7 +25,7 @@@
   */
  
  #include "avcodec.h"
+ #include "internal.h"
  #include "mjpeg.h"
  #include "mjpegdec.h"
  #include "sp5x.h"
@@@ -72,7 -73,7 +73,7 @@@ static int sp5x_decode_frame(AVCodecCon
          for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++)
              recoded[j++] = buf[i];
      else
 -    for (i = 14; i < buf_size && j < buf_size+1024-2; i++)
 +    for (i = 14; i < buf_size && j < buf_size+1024-3; i++)
      {
          recoded[j++] = buf[i];
          if (buf[i] == 0xff)
  
      av_free(recoded);
  
 -    return i;
 +    return i < 0 ? i : avpkt->size;
  }
  
 +#if CONFIG_SP5X_DECODER
  AVCodec ff_sp5x_decoder = {
      .name           = "sp5x",
      .long_name      = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"),
      .close          = ff_mjpeg_decode_end,
      .decode         = sp5x_decode_frame,
      .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
 -
 +#endif
 +#if CONFIG_AMV_DECODER
  AVCodec ff_amv_decoder = {
      .name           = "amv",
      .long_name      = NULL_IF_CONFIG_SMALL("AMV Video"),
      .init           = ff_mjpeg_decode_init,
      .close          = ff_mjpeg_decode_end,
      .decode         = sp5x_decode_frame,
 +    .max_lowres     = 3,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
  };
 +#endif