]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mjpegdec.c
Add function to export EDGE_WIDTH from libavcodec.
[ffmpeg] / libavcodec / mjpegdec.c
index dc0b4eba2962789f30234ff4f31125a0f42791c9..9b930e5bfd7087c4e8ee664d268f1c9eba5026dd 100644 (file)
@@ -1,9 +1,13 @@
 /*
  * MJPEG decoder
- * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2000, 2001 Fabrice Bellard
  * Copyright (c) 2003 Alex Beregszaszi
  * Copyright (c) 2003-2004 Michael Niedermayer
  *
+ * Support for external huffman table, various fixes (AVID workaround),
+ * aspecting, new decode_frame mechanism and apple mjpeg-b support
+ *                                  by Alex Beregszaszi
+ *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
  * You should have received a copy of the GNU Lesser General Public
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Support for external huffman table, various fixes (AVID workaround),
- * aspecting, new decode_frame mechanism and apple mjpeg-b support
- *                                  by Alex Beregszaszi
  */
 
 /**
- * @file mjpegdec.c
+ * @file libavcodec/mjpegdec.c
  * MJPEG decoder.
  */
 
 #include "avcodec.h"
 #include "dsputil.h"
 #include "mjpeg.h"
+#include "mjpegdec.h"
 #include "jpeglsdec.h"
 
 
-static int mjpeg_decode_dht(MJpegDecodeContext *s);
-
 static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table,
                       int nb_codes, int use_static, int is_ac)
 {
@@ -63,7 +62,18 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_tab
     return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);
 }
 
-static int mjpeg_decode_init(AVCodecContext *avctx)
+static void build_basic_mjpeg_vlc(MJpegDecodeContext * s) {
+    build_vlc(&s->vlcs[0][0], ff_mjpeg_bits_dc_luminance,
+              ff_mjpeg_val_dc, 12, 0, 0);
+    build_vlc(&s->vlcs[0][1], ff_mjpeg_bits_dc_chrominance,
+              ff_mjpeg_val_dc, 12, 0, 0);
+    build_vlc(&s->vlcs[1][0], ff_mjpeg_bits_ac_luminance,
+              ff_mjpeg_val_ac_luminance, 251, 0, 1);
+    build_vlc(&s->vlcs[1][1], ff_mjpeg_bits_ac_chrominance,
+              ff_mjpeg_val_ac_chrominance, 251, 0, 1);
+}
+
+av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
 {
     MJpegDecodeContext *s = avctx->priv_data;
 
@@ -75,22 +85,18 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
     s->start_code = -1;
     s->first_picture = 1;
     s->org_height = avctx->coded_height;
+    avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
 
-    build_vlc(&s->vlcs[0][0], ff_mjpeg_bits_dc_luminance,
-              ff_mjpeg_val_dc_luminance, 12, 0, 0);
-    build_vlc(&s->vlcs[0][1], ff_mjpeg_bits_dc_chrominance,
-              ff_mjpeg_val_dc_chrominance, 12, 0, 0);
-    build_vlc(&s->vlcs[1][0], ff_mjpeg_bits_ac_luminance,
-              ff_mjpeg_val_ac_luminance, 251, 0, 1);
-    build_vlc(&s->vlcs[1][1], ff_mjpeg_bits_ac_chrominance,
-              ff_mjpeg_val_ac_chrominance, 251, 0, 1);
+    build_basic_mjpeg_vlc(s);
 
     if (avctx->flags & CODEC_FLAG_EXTERN_HUFF)
     {
         av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n");
         init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
-        mjpeg_decode_dht(s);
-        /* should check for error - but dunno */
+        if (ff_mjpeg_decode_dht(s)) {
+            av_log(avctx, AV_LOG_ERROR, "mjpeg: error using external huffman table, switching back to internal\n");
+            build_basic_mjpeg_vlc(s);
+        }
     }
     if (avctx->extradata_size > 9 &&
         AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) {
@@ -99,13 +105,15 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
             av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
         }
     }
+    if (avctx->codec->id == CODEC_ID_AMV)
+        s->flipped = 1;
 
     return 0;
 }
 
 
 /* quantize tables */
-static int mjpeg_decode_dqt(MJpegDecodeContext *s)
+int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
 {
     int len, index, i, j;
 
@@ -140,7 +148,7 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s)
 }
 
 /* decode huffman tables and build VLC decoders */
-static int mjpeg_decode_dht(MJpegDecodeContext *s)
+int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
 {
     int len, index, i, class, n, v, code_max;
     uint8_t bits_table[17];
@@ -186,7 +194,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s)
     return 0;
 }
 
-static int mjpeg_decode_sof(MJpegDecodeContext *s)
+int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
 {
     int len, nb_components, i, width, height, pix_fmt_id;
 
@@ -279,28 +287,40 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         return 0;
 
     /* XXX: not complete test ! */
-    pix_fmt_id = (s->h_count[0] << 20) | (s->v_count[0] << 16) |
-                 (s->h_count[1] << 12) | (s->v_count[1] <<  8) |
-                 (s->h_count[2] <<  4) |  s->v_count[2];
+    pix_fmt_id = (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];
     av_log(s->avctx, AV_LOG_DEBUG, "pix fmt id %x\n", pix_fmt_id);
+    //NOTE we do not allocate pictures large enough for the possible padding of h/v_count being 4
+    if(!(pix_fmt_id & 0xD0D0D0D0))
+        pix_fmt_id-= (pix_fmt_id & 0xF0F0F0F0)>>1;
+    if(!(pix_fmt_id & 0x0D0D0D0D))
+        pix_fmt_id-= (pix_fmt_id & 0x0F0F0F0F)>>1;
+
     switch(pix_fmt_id){
-    case 0x222222:
-    case 0x111111:
+    case 0x11111100:
         if(s->rgb){
-            s->avctx->pix_fmt = PIX_FMT_RGB32;
-        }else if(s->nb_components==3)
+            s->avctx->pix_fmt = PIX_FMT_BGRA;
+        }else
             s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P;
-        else
-            s->avctx->pix_fmt = PIX_FMT_GRAY8;
+        assert(s->nb_components==3);
+        break;
+    case 0x11000000:
+        s->avctx->pix_fmt = PIX_FMT_GRAY8;
+        break;
+    case 0x12111100:
+        s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV440P : PIX_FMT_YUVJ440P;
         break;
-    case 0x211111:
-    case 0x221212:
+    case 0x21111100:
         s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P;
         break;
-    default:
-    case 0x221111:
+    case 0x22111100:
         s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P;
         break;
+    default:
+        av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id);
+        return -1;
     }
     if(s->ls){
         if(s->nb_components > 1)
@@ -319,8 +339,9 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return -1;
     }
-    s->picture.pict_type= I_TYPE;
+    s->picture.pict_type= FF_I_TYPE;
     s->picture.key_frame= 1;
+    s->got_picture = 1;
 
     for(i=0; i<3; i++){
         s->linesize[i]= s->picture.linesize[i] << s->interlaced;
@@ -335,9 +356,17 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
 
     /* totally blank picture as progressive JPEG will only add details to it */
     if(s->progressive){
-        memset(s->picture.data[0], 0, s->picture.linesize[0] * s->height);
-        memset(s->picture.data[1], 0, s->picture.linesize[1] * s->height >> (s->v_max - s->v_count[1]));
-        memset(s->picture.data[2], 0, s->picture.linesize[2] * s->height >> (s->v_max - s->v_count[2]));
+        int bw = (width  + s->h_max*8-1) / (s->h_max*8);
+        int bh = (height + s->v_max*8-1) / (s->v_max*8);
+        for(i=0; i<s->nb_components; i++) {
+            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->block_stride[i] = bw * s->h_count[i];
+        }
+        memset(s->coefs_finished, 0, sizeof(s->coefs_finished));
     }
     return 0;
 }
@@ -416,27 +445,29 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
     return 0;
 }
 
+static int decode_dc_progressive(MJpegDecodeContext *s, DCTELEM *block, int component,
+                                 int dc_index, int16_t *quant_matrix, int Al)
+{
+    int val;
+    s->dsp.clear_block(block);
+    val = mjpeg_decode_dc(s, dc_index);
+    if (val == 0xffff) {
+        av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
+        return -1;
+    }
+    val = (val * quant_matrix[0] << Al) + s->last_dc[component];
+    s->last_dc[component] = val;
+    block[0] = val;
+    return 0;
+}
+
 /* decode block and dequantize - progressive JPEG version */
-static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block,
-                        int component, int dc_index, int ac_index, int16_t *quant_matrix,
-                        int ss, int se, int Ah, int Al, int *EOBRUN)
+static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block, uint8_t *last_nnz,
+                                    int ac_index, int16_t *quant_matrix,
+                                    int ss, int se, int Al, int *EOBRUN)
 {
     int code, i, j, level, val, run;
 
-    /* DC coef */
-    if(!ss){
-        val = mjpeg_decode_dc(s, dc_index);
-        if (val == 0xffff) {
-            av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
-            return -1;
-        }
-        val = (val * quant_matrix[0] << Al) + s->last_dc[component];
-    }else
-        val = 0;
-    s->last_dc[component] = val;
-    block[0] = val;
-    if(!se) return 0;
-    /* AC coefs */
     if(*EOBRUN){
         (*EOBRUN)--;
         return 0;
@@ -489,19 +520,110 @@ static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block,
         }
     }
     CLOSE_READER(re, &s->gb)}
+    if(i > *last_nnz)
+        *last_nnz = i;
+    return 0;
+}
+
+#define REFINE_BIT(j) {\
+    UPDATE_CACHE(re, &s->gb);\
+    sign = block[j]>>15;\
+    block[j] += SHOW_UBITS(re, &s->gb, 1) * ((quant_matrix[j]^sign)-sign) << Al;\
+    LAST_SKIP_BITS(re, &s->gb, 1);\
+}
+
+#define ZERO_RUN \
+for(;;i++) {\
+    if(i > last) {\
+        i += run;\
+        if(i > se) {\
+            av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);\
+            return -1;\
+        }\
+        break;\
+    }\
+    j = s->scantable.permutated[i];\
+    if(block[j])\
+        REFINE_BIT(j)\
+    else if(run-- == 0)\
+        break;\
+}
+
+/* decode block and dequantize - progressive JPEG refinement pass */
+static int decode_block_refinement(MJpegDecodeContext *s, DCTELEM *block, uint8_t *last_nnz,
+                        int ac_index, int16_t *quant_matrix,
+                        int ss, int se, int Al, int *EOBRUN)
+{
+    int code, i=ss, j, sign, val, run;
+    int last = FFMIN(se, *last_nnz);
+
+    OPEN_READER(re, &s->gb);
+    if(*EOBRUN)
+        (*EOBRUN)--;
+    else {
+        for(;;i++) {
+            UPDATE_CACHE(re, &s->gb);
+            GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2)
+            /* Progressive JPEG use AC coeffs from zero and this decoder sets offset 16 by default */
+            code -= 16;
+            if(code & 0xF) {
+                run = ((unsigned) code) >> 4;
+                UPDATE_CACHE(re, &s->gb);
+                val = SHOW_UBITS(re, &s->gb, 1);
+                LAST_SKIP_BITS(re, &s->gb, 1);
+                ZERO_RUN;
+                j = s->scantable.permutated[i];
+                val--;
+                block[j] = ((quant_matrix[j]^val)-val) << Al;
+                if(i == se) {
+                    if(i > *last_nnz)
+                        *last_nnz = i;
+                    CLOSE_READER(re, &s->gb)
+                    return 0;
+                }
+            }else{
+                run = ((unsigned) code) >> 4;
+                if(run == 0xF){
+                    ZERO_RUN;
+                }else{
+                    val = run;
+                    run = (1 << run);
+                    if(val) {
+                        UPDATE_CACHE(re, &s->gb);
+                        run += SHOW_UBITS(re, &s->gb, val);
+                        LAST_SKIP_BITS(re, &s->gb, val);
+                    }
+                    *EOBRUN = run - 1;
+                    break;
+                }
+            }
+        }
+
+        if(i > *last_nnz)
+            *last_nnz = i;
+    }
+
+    for(;i<=last;i++) {
+        j = s->scantable.permutated[i];
+        if(block[j])
+            REFINE_BIT(j)
+    }
+    CLOSE_READER(re, &s->gb);
 
     return 0;
 }
+#undef REFINE_BIT
+#undef ZERO_RUN
 
 static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
     int i, mb_x, mb_y;
-    uint16_t buffer[32768][4];
+    uint16_t (*buffer)[4];
     int left[3], top[3], topleft[3];
     const int linesize= s->linesize[0];
     const int mask= (1<<s->bits)-1;
 
-    if((unsigned)s->mb_width > 32768) //dynamic alloc
-        return -1;
+    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);
@@ -552,9 +674,9 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point
             }
         }else{
             for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
-                ptr[4*mb_x+0] = buffer[mb_x][0];
+                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][2];
+                ptr[4*mb_x+2] = buffer[mb_x][0];
             }
         }
     }
@@ -644,11 +766,27 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point
     return 0;
 }
 
-static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, int se, int Ah, int Al){
+static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, int Al){
     int i, mb_x, mb_y;
-    int EOBRUN = 0;
+    uint8_t* data[MAX_COMPONENTS];
+    int linesize[MAX_COMPONENTS];
+
+    if(s->flipped && s->avctx->flags & CODEC_FLAG_EMU_EDGE) {
+        av_log(s->avctx, AV_LOG_ERROR, "Can not flip image with CODEC_FLAG_EMU_EDGE set!\n");
+        s->flipped = 0;
+    }
+    for(i=0; i < nb_components; i++) {
+        int c = s->comp_index[i];
+        data[c] = s->picture.data[c];
+        linesize[c]=s->linesize[c];
+        s->coefs_finished[c] |= 1;
+        if(s->flipped) {
+            //picture should be flipped upside-down for this codec
+            data[c] += (linesize[c] * (s->v_scount[i] * (8 * s->mb_height -((s->height/s->v_max)&7)) - 1 ));
+            linesize[c] *= -1;
+        }
+    }
 
-    if(Ah) return 0; /* TODO decode refinement planes too */
     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)
@@ -664,39 +802,40 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i
                 x = 0;
                 y = 0;
                 for(j=0;j<n;j++) {
-                    memset(s->block, 0, sizeof(s->block));
-                    if (!s->progressive && decode_block(s, s->block, i,
+                    ptr = data[c] +
+                        (((linesize[c] * (v * mb_y + y) * 8) +
+                        (h * mb_x + x) * 8) >> s->avctx->lowres);
+                    if(s->interlaced && s->bottom_field)
+                        ptr += linesize[c] >> 1;
+                    if(!s->progressive) {
+                        s->dsp.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) {
-                        av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
-                        return -1;
-                    }
-                    if (s->progressive && decode_block_progressive(s, s->block, i,
-                                     s->dc_index[i], s->ac_index[i],
-                                     s->quant_matrixes[ s->quant_index[c] ], ss, se, Ah, Al, &EOBRUN) < 0) {
-                        av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
-                        return -1;
+                            av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
+                            return -1;
+                        }
+                        s->dsp.idct_put(ptr, linesize[c], s->block);
+                    } else {
+                        int block_idx = s->block_stride[c] * (v * mb_y + y) + (h * mb_x + x);
+                        DCTELEM *block = s->blocks[c][block_idx];
+                        if(Ah)
+                            block[0] += get_bits1(&s->gb) * s->quant_matrixes[ s->quant_index[c] ][0] << Al;
+                        else if(decode_dc_progressive(s, block, i, s->dc_index[i], s->quant_matrixes[ s->quant_index[c] ], Al) < 0) {
+                            av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
+                            return -1;
+                        }
                     }
 //                    av_log(s->avctx, AV_LOG_DEBUG, "mb: %d %d processed\n", mb_y, mb_x);
-                    ptr = s->picture.data[c] +
-                        (((s->linesize[c] * (v * mb_y + y) * 8) +
-                        (h * mb_x + x) * 8) >> s->avctx->lowres);
-                    if (s->interlaced && s->bottom_field)
-                        ptr += s->linesize[c] >> 1;
 //av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8);
-                    if(!s->progressive)
-                        s->dsp.idct_put(ptr, s->linesize[c], s->block);
-                    else
-                        s->dsp.idct_add(ptr, s->linesize[c], s->block);
                     if (++x == h) {
                         x = 0;
                         y++;
                     }
                 }
             }
-            /* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
-            if (s->restart_interval && (s->restart_interval < 1350) &&
-                !--s->restart_count) {
+
+            if (s->restart_interval && !--s->restart_count) {
                 align_get_bits(&s->gb);
                 skip_bits(&s->gb, 16); /* skip RSTn */
                 for (i=0; i<nb_components; i++) /* reset dc */
@@ -707,23 +846,68 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, i
     return 0;
 }
 
-static int mjpeg_decode_sos(MJpegDecodeContext *s)
+static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, 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.data[c];
+    int linesize = s->linesize[c];
+    int last_scan = 0;
+    int16_t *quant_matrix = s->quant_matrixes[ s->quant_index[c] ];
+
+    if(!Al) {
+        s->coefs_finished[c] |= (1LL<<(se+1))-(1LL<<ss);
+        last_scan = !~s->coefs_finished[c];
+    }
+
+    if(s->interlaced && s->bottom_field)
+        data += linesize >> 1;
+
+    for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
+        uint8_t *ptr = data + (mb_y*linesize*8 >> s->avctx->lowres);
+        int block_idx = mb_y * s->block_stride[c];
+        DCTELEM (*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++) {
+            int ret;
+            if(Ah)
+                ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0],
+                                              quant_matrix, ss, se, Al, &EOBRUN);
+            else
+                ret = decode_block_progressive(s, *block, last_nnz, s->ac_index[0],
+                                               quant_matrix, ss, se, Al, &EOBRUN);
+            if(ret < 0) {
+                av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
+                return -1;
+            }
+            if(last_scan) {
+                s->dsp.idct_put(ptr, linesize, *block);
+                ptr += 8 >> s->avctx->lowres;
+            }
+        }
+    }
+    return 0;
+}
+
+int ff_mjpeg_decode_sos(MJpegDecodeContext *s)
 {
     int len, nb_components, i, h, v, predictor, point_transform;
-    int vmax, hmax, index, id;
+    int index, id;
     const int block_size= s->lossless ? 1 : 8;
     int ilv, prev_shift;
 
     /* XXX: verify len field validity */
     len = get_bits(&s->gb, 16);
     nb_components = get_bits(&s->gb, 8);
+    if (nb_components == 0 || nb_components > MAX_COMPONENTS){
+        av_log(s->avctx, AV_LOG_ERROR, "decode_sos: nb_components (%d) unsupported\n", nb_components);
+        return -1;
+    }
     if (len != 6+2*nb_components)
     {
         av_log(s->avctx, AV_LOG_ERROR, "decode_sos: invalid len (%d)\n", len);
         return -1;
     }
-    vmax = 0;
-    hmax = 0;
     for(i=0;i<nb_components;i++) {
         id = get_bits(&s->gb, 8) - 1;
         av_log(s->avctx, AV_LOG_DEBUG, "component: %d\n", id);
@@ -736,6 +920,10 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
             av_log(s->avctx, AV_LOG_ERROR, "decode_sos: index(%d) out of components\n", index);
             return -1;
         }
+        /* Metasoft MJPEG codec has Cb and Cr swapped */
+        if (s->avctx->codec_tag == MKTAG('M', 'T', 'S', 'J')
+            && nb_components == 3 && s->nb_components == 3 && i)
+            index = 3 - i;
 
         s->comp_index[i] = index;
 
@@ -749,24 +937,8 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
         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 0 //buggy
-        switch(s->start_code)
-        {
-            case SOF0:
-                if (dc_index[i] > 1 || ac_index[i] > 1)
-                    goto out_of_range;
-                break;
-            case SOF1:
-            case SOF2:
-                if (dc_index[i] > 3 || ac_index[i] > 3)
-                    goto out_of_range;
-                break;
-            case SOF3:
-                if (dc_index[i] > 3 || ac_index[i] != 0)
-                    goto out_of_range;
-                break;
-        }
-#endif
+        if (!s->vlcs[0][s->dc_index[i]].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 */
@@ -792,7 +964,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
     }
 
     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", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "",
+        av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d %s\n", s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "",
                predictor, point_transform, ilv, s->bits,
                s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""));
 
@@ -802,11 +974,12 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
         skip_bits(&s->gb, 8);
 
     if(s->lossless){
-        if(s->ls){
+        if(CONFIG_JPEGLS_DECODER && s->ls){
 //            for(){
 //            reset_ls_coding_parameters(s, 0);
 
-            ff_jpegls_decode_picture(s, predictor, point_transform, ilv);
+            if(ff_jpegls_decode_picture(s, predictor, point_transform, ilv) < 0)
+                return -1;
         }else{
             if(s->rgb){
                 if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0)
@@ -817,8 +990,13 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
             }
         }
     }else{
-        if(mjpeg_decode_scan(s, nb_components, predictor, ilv, prev_shift, point_transform) < 0)
-            return -1;
+        if(s->progressive && predictor) {
+            if(mjpeg_decode_scan_progressive_ac(s, predictor, ilv, prev_shift, point_transform) < 0)
+                return -1;
+        } else {
+            if(mjpeg_decode_scan(s, nb_components, prev_shift, point_transform) < 0)
+                return -1;
+        }
     }
     emms_c();
     return 0;
@@ -859,7 +1037,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     /* buggy AVID, it puts EOI only at every 10th frame */
     /* also this fourcc is used by non-avid files too, it holds some
        informations, but it's always present in AVID creates files */
-    if (id == ff_get_fourcc("AVI1"))
+    if (id == AV_RL32("AVI1"))
     {
         /* structure:
             4bytes      AVI1
@@ -887,7 +1065,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
 
 //    len -= 2;
 
-    if (id == ff_get_fourcc("JFIF"))
+    if (id == AV_RL32("JFIF"))
     {
         int t_w, t_h, v1, v2;
         skip_bits(&s->gb, 8); /* the trailing zero-byte */
@@ -917,7 +1095,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
         goto out;
     }
 
-    if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e'))
+    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");
@@ -929,7 +1107,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
         goto out;
     }
 
-    if (id == ff_get_fourcc("LJIF")){
+    if (id == AV_RL32("LJIF")){
         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 ? */
@@ -958,7 +1136,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
         id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
         id = be2me_32(id);
         len -= 4;
-        if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */
+        if (id == AV_RL32("mjpg")) /* Apple MJPEG-A */
         {
 #if 0
             skip_bits(&s->gb, 32); /* field size */
@@ -1012,6 +1190,10 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
             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))){
+                s->flipped = 1;
+            }
 
             av_free(cbuf);
         }
@@ -1045,9 +1227,9 @@ static int valid_marker_list[] =
 
 /* return the 8 bit start code value and update the search
    state. Return -1 if no start code found */
-static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
+static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
 {
-    uint8_t *buf_ptr;
+    const uint8_t *buf_ptr;
     unsigned int v, v2;
     int val;
 #ifdef DEBUG
@@ -1068,22 +1250,23 @@ static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
     }
     val = -1;
 found:
-#ifdef DEBUG
-    av_log(NULL, AV_LOG_VERBOSE, "find_marker skipped %d bytes\n", skipped);
-#endif
+    dprintf(NULL, "find_marker skipped %d bytes\n", skipped);
     *pbuf_ptr = buf_ptr;
     return val;
 }
 
-static int mjpeg_decode_frame(AVCodecContext *avctx,
+int ff_mjpeg_decode_frame(AVCodecContext *avctx,
                               void *data, int *data_size,
-                              uint8_t *buf, int buf_size)
+                              AVPacket *avpkt)
 {
+    const uint8_t *buf = avpkt->data;
+    int buf_size = avpkt->size;
     MJpegDecodeContext *s = avctx->priv_data;
-    uint8_t *buf_end, *buf_ptr;
+    const uint8_t *buf_end, *buf_ptr;
     int start_code;
     AVFrame *picture = data;
 
+    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) {
@@ -1094,7 +1277,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
             if (start_code < 0) {
                 goto the_end;
             } else {
-                av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%d\n", start_code, buf_end - buf_ptr);
+                av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr);
 
                 if ((buf_end - buf_ptr) > s->buffer_size)
                 {
@@ -1108,7 +1291,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                 /* unescape buffer of SOS, use special treatment for JPEG-LS */
                 if (start_code == SOS && !s->ls)
                 {
-                    uint8_t *src = buf_ptr;
+                    const uint8_t *src = buf_ptr;
                     uint8_t *dst = s->buffer;
 
                     while (src<buf_end)
@@ -1131,11 +1314,11 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                     }
                     init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8);
 
-                    av_log(avctx, AV_LOG_DEBUG, "escaping removed %d bytes\n",
+                    av_log(avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",
                            (buf_end - buf_ptr) - (dst - s->buffer));
                 }
                 else if(start_code == SOS && s->ls){
-                    uint8_t *src = buf_ptr;
+                    const uint8_t *src = buf_ptr;
                     uint8_t *dst = s->buffer;
                     int bit_count = 0;
                     int t = 0, b = 0;
@@ -1200,44 +1383,45 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                     /* nothing to do on SOI */
                     break;
                 case DQT:
-                    mjpeg_decode_dqt(s);
+                    ff_mjpeg_decode_dqt(s);
                     break;
                 case DHT:
-                    if(mjpeg_decode_dht(s) < 0){
+                    if(ff_mjpeg_decode_dht(s) < 0){
                         av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n");
                         return -1;
                     }
                     break;
                 case SOF0:
+                case SOF1:
                     s->lossless=0;
                     s->ls=0;
                     s->progressive=0;
-                    if (mjpeg_decode_sof(s) < 0)
+                    if (ff_mjpeg_decode_sof(s) < 0)
                         return -1;
                     break;
                 case SOF2:
                     s->lossless=0;
                     s->ls=0;
                     s->progressive=1;
-                    if (mjpeg_decode_sof(s) < 0)
+                    if (ff_mjpeg_decode_sof(s) < 0)
                         return -1;
                     break;
                 case SOF3:
                     s->lossless=1;
                     s->ls=0;
                     s->progressive=0;
-                    if (mjpeg_decode_sof(s) < 0)
+                    if (ff_mjpeg_decode_sof(s) < 0)
                         return -1;
                     break;
                 case SOF48:
                     s->lossless=1;
                     s->ls=1;
                     s->progressive=0;
-                    if (mjpeg_decode_sof(s) < 0)
+                    if (ff_mjpeg_decode_sof(s) < 0)
                         return -1;
                     break;
                 case LSE:
-                    if (ff_jpegls_decode_lse(s) < 0)
+                    if (!CONFIG_JPEGLS_DECODER || ff_jpegls_decode_lse(s) < 0)
                         return -1;
                     break;
                 case EOI:
@@ -1245,6 +1429,10 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                     if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
                         break;
 eoi_parser:
+                    if (!s->got_picture) {
+                        av_log(avctx, AV_LOG_WARNING, "Found EOI before any SOF, ignoring\n");
+                        break;
+                    }
                     {
                         if (s->interlaced) {
                             s->bottom_field ^= 1;
@@ -1256,7 +1444,7 @@ eoi_parser:
                         *data_size = sizeof(AVFrame);
 
                         if(!s->lossless){
-                            picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
+                            picture->quality= FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]);
                             picture->qstride= 0;
                             picture->qscale_table= s->qscale_table;
                             memset(picture->qscale_table, picture->quality, (s->width+15)/16);
@@ -1269,7 +1457,11 @@ eoi_parser:
                     }
                     break;
                 case SOS:
-                    mjpeg_decode_sos(s);
+                    if (!s->got_picture) {
+                        av_log(avctx, AV_LOG_WARNING, "Can not process SOS before SOF, skipping\n");
+                        break;
+                    }
+                    ff_mjpeg_decode_sos(s);
                     /* buggy avid puts EOI every 10-20th frame */
                     /* if restart period is over process EOI */
                     if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
@@ -1278,7 +1470,6 @@ eoi_parser:
                 case DRI:
                     mjpeg_decode_dri(s);
                     break;
-                case SOF1:
                 case SOF5:
                 case SOF6:
                 case SOF7:
@@ -1304,337 +1495,66 @@ not_the_end:
             }
         }
     }
+    if (s->got_picture) {
+        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 -1;
 the_end:
-    av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr);
+    av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %td bytes\n", buf_end - buf_ptr);
 //    return buf_end - buf_ptr;
     return buf_ptr - buf;
 }
 
-static int mjpegb_decode_frame(AVCodecContext *avctx,
-                              void *data, int *data_size,
-                              uint8_t *buf, int buf_size)
-{
-    MJpegDecodeContext *s = avctx->priv_data;
-    uint8_t *buf_end, *buf_ptr;
-    AVFrame *picture = data;
-    GetBitContext hgb; /* for the header */
-    uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
-    uint32_t field_size, sod_offs;
-
-    buf_ptr = buf;
-    buf_end = buf + buf_size;
-
-read_header:
-    /* reset on every SOI */
-    s->restart_interval = 0;
-    s->restart_count = 0;
-    s->mjpb_skiptosod = 0;
-
-    init_get_bits(&hgb, buf_ptr, /*buf_size*/(buf_end - buf_ptr)*8);
-
-    skip_bits(&hgb, 32); /* reserved zeros */
-
-    if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g'))
-    {
-        av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n");
-        return 0;
-    }
-
-    field_size = get_bits_long(&hgb, 32); /* field size */
-    av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size);
-    skip_bits(&hgb, 32); /* padded field size */
-    second_field_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs);
-
-    dqt_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs);
-    if (dqt_offs)
-    {
-        init_get_bits(&s->gb, buf+dqt_offs, (buf_end - (buf+dqt_offs))*8);
-        s->start_code = DQT;
-        mjpeg_decode_dqt(s);
-    }
-
-    dht_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs);
-    if (dht_offs)
-    {
-        init_get_bits(&s->gb, buf+dht_offs, (buf_end - (buf+dht_offs))*8);
-        s->start_code = DHT;
-        mjpeg_decode_dht(s);
-    }
-
-    sof_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs);
-    if (sof_offs)
-    {
-        init_get_bits(&s->gb, buf+sof_offs, (buf_end - (buf+sof_offs))*8);
-        s->start_code = SOF0;
-        if (mjpeg_decode_sof(s) < 0)
-            return -1;
-    }
-
-    sos_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs);
-    sod_offs = get_bits_long(&hgb, 32);
-    av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs);
-    if (sos_offs)
-    {
-//        init_get_bits(&s->gb, buf+sos_offs, (buf_end - (buf+sos_offs))*8);
-        init_get_bits(&s->gb, buf+sos_offs, field_size*8);
-        s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16));
-        s->start_code = SOS;
-        mjpeg_decode_sos(s);
-    }
-
-    if (s->interlaced) {
-        s->bottom_field ^= 1;
-        /* if not bottom field, do not output image yet */
-        if (s->bottom_field && 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
-
-    *picture= s->picture;
-    *data_size = sizeof(AVFrame);
-
-    if(!s->lossless){
-        picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
-        picture->qstride= 0;
-        picture->qscale_table= s->qscale_table;
-        memset(picture->qscale_table, picture->quality, (s->width+15)/16);
-        if(avctx->debug & FF_DEBUG_QP)
-            av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
-        picture->quality*= FF_QP2LAMBDA;
-    }
-
-    return buf_ptr - buf;
-}
-
-#include "sp5x.h"
-
-static int sp5x_decode_frame(AVCodecContext *avctx,
-                              void *data, int *data_size,
-                              uint8_t *buf, int buf_size)
-{
-#if 0
-    MJpegDecodeContext *s = avctx->priv_data;
-#endif
-    const int qscale = 5;
-    uint8_t *buf_ptr, *buf_end, *recoded;
-    int i = 0, j = 0;
-
-    if (!avctx->width || !avctx->height)
-        return -1;
-
-    buf_ptr = buf;
-    buf_end = buf + buf_size;
-
-#if 1
-    recoded = av_mallocz(buf_size + 1024);
-    if (!recoded)
-        return -1;
-
-    /* SOI */
-    recoded[j++] = 0xFF;
-    recoded[j++] = 0xD8;
-
-    memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt));
-    memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64);
-    memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64);
-    j += sizeof(sp5x_data_dqt);
-
-    memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht));
-    j += sizeof(sp5x_data_dht);
-
-    memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof));
-    recoded[j+5] = (avctx->coded_height >> 8) & 0xFF;
-    recoded[j+6] = avctx->coded_height & 0xFF;
-    recoded[j+7] = (avctx->coded_width >> 8) & 0xFF;
-    recoded[j+8] = avctx->coded_width & 0xFF;
-    j += sizeof(sp5x_data_sof);
-
-    memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos));
-    j += sizeof(sp5x_data_sos);
-
-    for (i = 14; i < buf_size && j < buf_size+1024-2; i++)
-    {
-        recoded[j++] = buf[i];
-        if (buf[i] == 0xff)
-            recoded[j++] = 0;
-    }
-
-    /* EOI */
-    recoded[j++] = 0xFF;
-    recoded[j++] = 0xD9;
-
-    i = mjpeg_decode_frame(avctx, data, data_size, recoded, j);
-
-    av_free(recoded);
-
-#else
-    /* SOF */
-    s->bits = 8;
-    s->width  = avctx->coded_width;
-    s->height = avctx->coded_height;
-    s->nb_components = 3;
-    s->component_id[0] = 0;
-    s->h_count[0] = 2;
-    s->v_count[0] = 2;
-    s->quant_index[0] = 0;
-    s->component_id[1] = 1;
-    s->h_count[1] = 1;
-    s->v_count[1] = 1;
-    s->quant_index[1] = 1;
-    s->component_id[2] = 2;
-    s->h_count[2] = 1;
-    s->v_count[2] = 1;
-    s->quant_index[2] = 1;
-    s->h_max = 2;
-    s->v_max = 2;
-
-    s->qscale_table = av_mallocz((s->width+15)/16);
-    avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420;
-    s->interlaced = 0;
-
-    s->picture.reference = 0;
-    if (avctx->get_buffer(avctx, &s->picture) < 0)
-    {
-        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-        return -1;
-    }
-
-    s->picture.pict_type = I_TYPE;
-    s->picture.key_frame = 1;
-
-    for (i = 0; i < 3; i++)
-        s->linesize[i] = s->picture.linesize[i] << s->interlaced;
-
-    /* DQT */
-    for (i = 0; i < 64; i++)
-    {
-        j = s->scantable.permutated[i];
-        s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i];
-    }
-    s->qscale[0] = FFMAX(
-        s->quant_matrixes[0][s->scantable.permutated[1]],
-        s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1;
-
-    for (i = 0; i < 64; i++)
-    {
-        j = s->scantable.permutated[i];
-        s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i];
-    }
-    s->qscale[1] = FFMAX(
-        s->quant_matrixes[1][s->scantable.permutated[1]],
-        s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1;
-
-    /* DHT */
-
-    /* SOS */
-    s->comp_index[0] = 0;
-    s->nb_blocks[0] = s->h_count[0] * s->v_count[0];
-    s->h_scount[0] = s->h_count[0];
-    s->v_scount[0] = s->v_count[0];
-    s->dc_index[0] = 0;
-    s->ac_index[0] = 0;
-
-    s->comp_index[1] = 1;
-    s->nb_blocks[1] = s->h_count[1] * s->v_count[1];
-    s->h_scount[1] = s->h_count[1];
-    s->v_scount[1] = s->v_count[1];
-    s->dc_index[1] = 1;
-    s->ac_index[1] = 1;
-
-    s->comp_index[2] = 2;
-    s->nb_blocks[2] = s->h_count[2] * s->v_count[2];
-    s->h_scount[2] = s->h_count[2];
-    s->v_scount[2] = s->v_count[2];
-    s->dc_index[2] = 1;
-    s->ac_index[2] = 1;
-
-    for (i = 0; i < 3; i++)
-        s->last_dc[i] = 1024;
-
-    s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8);
-    s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8);
-
-    init_get_bits(&s->gb, buf+14, (buf_size-14)*8);
-
-    return mjpeg_decode_scan(s);
-#endif
-
-    return i;
-}
-
-static int mjpeg_decode_end(AVCodecContext *avctx)
+av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
 {
     MJpegDecodeContext *s = avctx->priv_data;
     int i, j;
 
+    if (s->picture.data[0])
+        avctx->release_buffer(avctx, &s->picture);
+
     av_free(s->buffer);
     av_free(s->qscale_table);
+    av_freep(&s->ljpeg_buffer);
+    s->ljpeg_buffer_size=0;
 
     for(i=0;i<2;i++) {
         for(j=0;j<4;j++)
             free_vlc(&s->vlcs[i][j]);
     }
+    for(i=0; i<MAX_COMPONENTS; i++) {
+        av_freep(&s->blocks[i]);
+        av_freep(&s->last_nnz[i]);
+    }
     return 0;
 }
 
 AVCodec mjpeg_decoder = {
     "mjpeg",
-    CODEC_TYPE_VIDEO,
+    AVMEDIA_TYPE_VIDEO,
     CODEC_ID_MJPEG,
     sizeof(MJpegDecodeContext),
-    mjpeg_decode_init,
+    ff_mjpeg_decode_init,
     NULL,
-    mjpeg_decode_end,
-    mjpeg_decode_frame,
+    ff_mjpeg_decode_end,
+    ff_mjpeg_decode_frame,
     CODEC_CAP_DR1,
-    NULL
+    NULL,
+    .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"),
 };
 
 AVCodec thp_decoder = {
     "thp",
-    CODEC_TYPE_VIDEO,
+    AVMEDIA_TYPE_VIDEO,
     CODEC_ID_THP,
     sizeof(MJpegDecodeContext),
-    mjpeg_decode_init,
-    NULL,
-    mjpeg_decode_end,
-    mjpeg_decode_frame,
-    CODEC_CAP_DR1,
-    NULL
-};
-
-AVCodec mjpegb_decoder = {
-    "mjpegb",
-    CODEC_TYPE_VIDEO,
-    CODEC_ID_MJPEGB,
-    sizeof(MJpegDecodeContext),
-    mjpeg_decode_init,
+    ff_mjpeg_decode_init,
     NULL,
-    mjpeg_decode_end,
-    mjpegb_decode_frame,
+    ff_mjpeg_decode_end,
+    ff_mjpeg_decode_frame,
     CODEC_CAP_DR1,
-    NULL
-};
-
-AVCodec sp5x_decoder = {
-    "sp5x",
-    CODEC_TYPE_VIDEO,
-    CODEC_ID_SP5X,
-    sizeof(MJpegDecodeContext),
-    mjpeg_decode_init,
     NULL,
-    mjpeg_decode_end,
-    sp5x_decode_frame,
-    CODEC_CAP_DR1,
-    NULL
+    .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"),
 };