]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mjpeg.c
cosmetics: Move one code block to save an #ifdef in the next commit.
[ffmpeg] / libavcodec / mjpeg.c
index f0be96426e5245419d720d1b63176530c8d157b7..e3583e54e05732d235e50648be3a8de414c314eb 100644 (file)
@@ -4,18 +4,20 @@
  * Copyright (c) 2003 Alex Beregszaszi
  * Copyright (c) 2003-2004 Michael Niedermayer
  *
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * 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 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This library 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 this library; 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
  *
  * Support for external huffman table, various fixes (AVID workaround),
@@ -34,6 +36,7 @@
 #include "avcodec.h"
 #include "dsputil.h"
 #include "mpegvideo.h"
+#include "bytestream.h"
 
 /* use two quantizer tables (one for luminance and one for chrominance) */
 /* not yet working */
@@ -438,7 +441,7 @@ void mjpeg_picture_header(MpegEncContext *s)
     }
 
     put_bits(&s->pb, 16, 17);
-    if(lossless && s->avctx->pix_fmt == PIX_FMT_RGBA32)
+    if(lossless && s->avctx->pix_fmt == PIX_FMT_RGB32)
         put_bits(&s->pb, 8, 9); /* 9 bits/component RCT */
     else
         put_bits(&s->pb, 8, 8); /* 8 bits/component */
@@ -613,7 +616,7 @@ static void encode_block(MpegEncContext *s, DCTELEM *block, int n)
     uint16_t *huff_code_ac;
 
     /* DC coef */
-    component = (n <= 3 ? 0 : n - 4 + 1);
+    component = (n <= 3 ? 0 : (n&1) + 1);
     dc = block[0]; /* overflow is impossible */
     val = dc - s->last_dc[component];
     if (n < 4) {
@@ -666,9 +669,16 @@ void mjpeg_encode_mb(MpegEncContext *s,
                      DCTELEM block[6][64])
 {
     int i;
-    for(i=0;i<6;i++) {
+    for(i=0;i<5;i++) {
         encode_block(s, block[i], i);
     }
+    if (s->chroma_format == CHROMA_420) {
+        encode_block(s, block[5], 5);
+    } else {
+        encode_block(s, block[6], 6);
+        encode_block(s, block[5], 5);
+        encode_block(s, block[7], 7);
+    }
 }
 
 static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
@@ -690,7 +700,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
 
     s->header_bits= put_bits_count(&s->pb);
 
-    if(avctx->pix_fmt == PIX_FMT_RGBA32){
+    if(avctx->pix_fmt == PIX_FMT_RGB32){
         int x, y, i;
         const int linesize= p->linesize[0];
         uint16_t (*buffer)[4]= (void *) s->rd_scratchpad;
@@ -845,6 +855,7 @@ typedef struct MJpegDecodeContext {
     int bottom_field;   /* true if bottom field */
     int lossless;
     int ls;
+    int progressive;
     int rgb;
     int rct;            /* standard rct */
     int pegasus_rct;    /* pegasus reversible colorspace transform */
@@ -876,6 +887,7 @@ typedef struct MJpegDecodeContext {
     DECLARE_ALIGNED_8(DCTELEM, block[64]);
     ScanTable scantable;
     void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+    void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
 
     int restart_interval;
     int restart_count;
@@ -889,7 +901,7 @@ typedef struct MJpegDecodeContext {
     int cur_scan; /* current scan, used by JPEG-LS */
 } MJpegDecodeContext;
 
-#include "jpeg_ls.c" //FIXME make jpeg-ls more independant
+#include "jpeg_ls.c" //FIXME make jpeg-ls more independent
 
 static int mjpeg_decode_dht(MJpegDecodeContext *s);
 
@@ -932,6 +944,7 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
 
     s->scantable= s2.intra_scantable;
     s->idct_put= s2.dsp.idct_put;
+    s->idct_add= s2.dsp.idct_add;
 
     s->mpeg_enc_ctx_allocated = 0;
     s->buffer_size = 0;
@@ -952,6 +965,13 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
         mjpeg_decode_dht(s);
         /* should check for error - but dunno */
     }
+    if (avctx->extradata_size > 9 &&
+        AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) {
+        if (avctx->extradata[9] == 6) { /* quicktime icefloe 019 */
+            s->interlace_polarity = 1; /* bottom field first */
+            av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
+        }
+    }
 
     return 0;
 }
@@ -1030,13 +1050,13 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s)
         /* only 8 bit precision handled */
         if (get_bits(&s->gb, 4) != 0)
         {
-            dprintf("dqt: 16bit precision\n");
+            av_log(s->avctx, AV_LOG_ERROR, "dqt: 16bit precision\n");
             return -1;
         }
         index = get_bits(&s->gb, 4);
         if (index >= 4)
             return -1;
-        dprintf("index=%d\n", index);
+        av_log(s->avctx, AV_LOG_DEBUG, "index=%d\n", index);
         /* read quant table */
         for(i=0;i<64;i++) {
             j = s->scantable.permutated[i];
@@ -1047,7 +1067,7 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s)
         s->qscale[index]= FFMAX(
             s->quant_matrixes[index][s->scantable.permutated[1]],
             s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1;
-        dprintf("qscale[%d]: %d\n", index, s->qscale[index]);
+        av_log(s->avctx, AV_LOG_DEBUG, "qscale[%d]: %d\n", index, s->qscale[index]);
         len -= 65;
     }
 
@@ -1092,7 +1112,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s)
 
         /* build VLC and flush previous vlc if present */
         free_vlc(&s->vlcs[class][index]);
-        dprintf("class=%d index=%d nb_codes=%d\n",
+        av_log(s->avctx, AV_LOG_DEBUG, "class=%d index=%d nb_codes=%d\n",
                class, index, code_max + 1);
         if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0, class > 0) < 0){
             return -1;
@@ -1103,7 +1123,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s)
 
 static int mjpeg_decode_sof(MJpegDecodeContext *s)
 {
-    int len, nb_components, i, width, height;
+    int len, nb_components, i, width, height, pix_fmt_id;
 
     /* XXX: verify len field validity */
     len = get_bits(&s->gb, 16);
@@ -1116,15 +1136,11 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n");
         return -1;
     }
-    if (s->bits > 8 && s->ls){
-        av_log(s->avctx, AV_LOG_ERROR, "only <= 8 bits/component accepted for JPEG-LS\n");
-        return -1;
-    }
 
     height = get_bits(&s->gb, 16);
     width = get_bits(&s->gb, 16);
 
-    dprintf("sof0: picture: %dx%d\n", width, height);
+    av_log(s->avctx, AV_LOG_DEBUG, "sof0: picture: %dx%d\n", width, height);
     if(avcodec_check_dimensions(s->avctx, width, height))
         return -1;
 
@@ -1132,6 +1148,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
     if (nb_components <= 0 ||
         nb_components > MAX_COMPONENTS)
         return -1;
+    if (s->ls && !(s->bits <= 8 || nb_components == 1)){
+        av_log(s->avctx, AV_LOG_ERROR, "only <= 8 bits/component or 16-bit gray accepted for JPEG-LS\n");
+        return -1;
+    }
     s->nb_components = nb_components;
     s->h_max = 1;
     s->v_max = 1;
@@ -1148,8 +1168,8 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         s->quant_index[i] = get_bits(&s->gb, 8);
         if (s->quant_index[i] >= 4)
             return -1;
-        dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
-            s->v_count[i], s->component_id[i], s->quant_index[i]);
+        av_log(s->avctx, AV_LOG_DEBUG, "component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
+               s->v_count[i], s->component_id[i], s->quant_index[i]);
     }
 
     if(s->ls && (s->h_max > 1 || s->v_max > 1)) {
@@ -1172,8 +1192,9 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
             s->org_height != 0 &&
             s->height < ((s->org_height * 3) / 4)) {
             s->interlaced = 1;
-//            s->bottom_field = (s->interlace_polarity) ? 1 : 0;
-            s->bottom_field = 0;
+            s->bottom_field = s->interlace_polarity;
+            s->picture.interlaced_frame = 1;
+            s->picture.top_field_first = !s->interlace_polarity;
             height *= 2;
         }
 
@@ -1184,32 +1205,40 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         s->first_picture = 0;
     }
 
-    if(s->interlaced && s->bottom_field)
+    if(s->interlaced && (s->bottom_field == !s->interlace_polarity))
         return 0;
 
     /* XXX: not complete test ! */
-    switch((s->h_count[0] << 4) | s->v_count[0]) {
-    case 0x11:
+    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];
+    av_log(s->avctx, AV_LOG_DEBUG, "pix fmt id %x\n", pix_fmt_id);
+    switch(pix_fmt_id){
+    case 0x222222:
+    case 0x111111:
         if(s->rgb){
-            s->avctx->pix_fmt = PIX_FMT_RGBA32;
+            s->avctx->pix_fmt = PIX_FMT_RGB32;
         }else if(s->nb_components==3)
             s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P;
         else
             s->avctx->pix_fmt = PIX_FMT_GRAY8;
         break;
-    case 0x21:
+    case 0x211111:
+    case 0x221212:
         s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P;
         break;
     default:
-    case 0x22:
+    case 0x221111:
         s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P;
         break;
     }
     if(s->ls){
         if(s->nb_components > 1)
             s->avctx->pix_fmt = PIX_FMT_RGB24;
-        else
+        else if(s->bits <= 8)
             s->avctx->pix_fmt = PIX_FMT_GRAY8;
+        else
+            s->avctx->pix_fmt = PIX_FMT_GRAY16;
     }
 
     if(s->picture.data[0])
@@ -1231,9 +1260,15 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
 
     if (len != (8+(3*nb_components)))
     {
-        dprintf("decode_sof0: error, len(%d) mismatch\n", len);
+        av_log(s->avctx, AV_LOG_DEBUG, "decode_sof0: error, len(%d) mismatch\n", len);
     }
 
+    /* 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]));
+    }
     return 0;
 }
 
@@ -1243,8 +1278,8 @@ static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index)
     code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2);
     if (code < 0)
     {
-        dprintf("mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", 0, dc_index,
-                &s->vlcs[0][dc_index]);
+        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;
     }
 
@@ -1263,7 +1298,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
     /* DC coef */
     val = mjpeg_decode_dc(s, dc_index);
     if (val == 0xffff) {
-        dprintf("error dc\n");
+        av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
         return -1;
     }
     val = val * quant_matrix[0] + s->last_dc[component];
@@ -1299,7 +1334,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
                     block[j] = level * quant_matrix[j];
                     break;
                 }
-                dprintf("error count: %d\n", i);
+                av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);
                 return -1;
             }
             j = s->scantable.permutated[i];
@@ -1311,6 +1346,83 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
     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)
+{
+    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;
+    }
+    {OPEN_READER(re, &s->gb)
+    for(i=ss;;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) {
+            i += ((unsigned) code) >> 4;
+            code &= 0xf;
+            if(code > MIN_CACHE_BITS - 16){
+                UPDATE_CACHE(re, &s->gb)
+            }
+            {
+                int cache=GET_CACHE(re,&s->gb);
+                int sign=(~cache)>>31;
+                level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign;
+            }
+
+            LAST_SKIP_BITS(re, &s->gb, code)
+
+            if (i >= se) {
+                if(i == se){
+                    j = s->scantable.permutated[se];
+                    block[j] = level * quant_matrix[j] << Al;
+                    break;
+                }
+                av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);
+                return -1;
+            }
+            j = s->scantable.permutated[i];
+            block[j] = level * quant_matrix[j] << Al;
+        }else{
+            run = ((unsigned) code) >> 4;
+            if(run == 0xF){// ZRL - skip 15 coefficients
+                i += 15;
+            }else{
+                val = run;
+                run = (1 << run);
+                UPDATE_CACHE(re, &s->gb);
+                run += (GET_CACHE(re, &s->gb) >> (32 - val)) & (run - 1);
+                if(val)
+                    LAST_SKIP_BITS(re, &s->gb, val);
+                *EOBRUN = run - 1;
+                break;
+            }
+        }
+    }
+    CLOSE_READER(re, &s->gb)}
+
+    return 0;
+}
+
 static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
     int i, mb_x, mb_y;
     uint16_t buffer[32768][4];
@@ -1462,10 +1574,11 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point
     return 0;
 }
 
-static int mjpeg_decode_scan(MJpegDecodeContext *s){
+static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, int se, int Ah, int Al){
     int i, mb_x, mb_y;
-    const int nb_components=3;
+    int EOBRUN = 0;
 
+    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)
@@ -1482,20 +1595,29 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){
                 y = 0;
                 for(j=0;j<n;j++) {
                     memset(s->block, 0, sizeof(s->block));
-                    if (decode_block(s, s->block, i,
+                    if (!s->progressive && decode_block(s, s->block, i,
                                      s->dc_index[i], s->ac_index[i],
                                      s->quant_matrixes[ s->quant_index[c] ]) < 0) {
-                        dprintf("error y=%d x=%d\n", mb_y, mb_x);
+                        av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x);
                         return -1;
                     }
-//                    dprintf("mb: %d %d processed\n", mb_y, mb_x);
+                    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_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);
-                    s->idct_put(ptr, s->linesize[c], s->block);
+                    if(!s->progressive)
+                        s->idct_put(ptr, s->linesize[c], s->block);
+                    else
+                        s->idct_add(ptr, s->linesize[c], s->block);
                     if (++x == h) {
                         x = 0;
                         y++;
@@ -1520,34 +1642,28 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
     int len, nb_components, i, h, v, predictor, point_transform;
     int vmax, hmax, index, id;
     const int block_size= s->lossless ? 1 : 8;
-    int ilv;
+    int ilv, prev_shift;
 
     /* XXX: verify len field validity */
     len = get_bits(&s->gb, 16);
     nb_components = get_bits(&s->gb, 8);
     if (len != 6+2*nb_components)
     {
-        dprintf("decode_sos: invalid len (%d)\n", len);
-        return -1;
-    }
-    /* XXX: only interleaved scan accepted */
-    if ((nb_components != s->nb_components) && !s->ls)
-    {
-        dprintf("decode_sos: components(%d) mismatch\n", 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;
-        dprintf("component: %d\n", id);
+        av_log(s->avctx, AV_LOG_DEBUG, "component: %d\n", id);
         /* find component index */
         for(index=0;index<s->nb_components;index++)
             if (id == s->component_id[index])
                 break;
         if (index == s->nb_components)
         {
-            dprintf("decode_sos: index(%d) out of components\n", index);
+            av_log(s->avctx, AV_LOG_ERROR, "decode_sos: index(%d) out of components\n", index);
             return -1;
         }
 
@@ -1585,7 +1701,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
 
     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 */
-    skip_bits(&s->gb, 4); /* Ah */
+    prev_shift = get_bits(&s->gb, 4); /* Ah */
     point_transform= get_bits(&s->gb, 4); /* Al */
 
     for(i=0;i<nb_components;i++)
@@ -1596,8 +1712,8 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
         s->mb_width  = (s->width  + s->h_max * block_size - 1) / (s->h_max * block_size);
         s->mb_height = (s->height + s->v_max * block_size - 1) / (s->v_max * block_size);
     } else if(!s->ls) { /* skip this for JPEG-LS */
-        h = s->h_max / s->h_scount[s->comp_index[0]];
-        v = s->v_max / s->v_scount[s->comp_index[0]];
+        h = s->h_max / s->h_scount[0];
+        v = s->v_max / s->v_scount[0];
         s->mb_width  = (s->width  + h * block_size - 1) / (h * block_size);
         s->mb_height = (s->height + v * block_size - 1) / (v * block_size);
         s->nb_blocks[0] = 1;
@@ -1631,13 +1747,13 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
             }
         }
     }else{
-        if(mjpeg_decode_scan(s) < 0)
+        if(mjpeg_decode_scan(s, nb_components, predictor, ilv, prev_shift, point_transform) < 0)
             return -1;
     }
     emms_c();
     return 0;
  out_of_range:
-    dprintf("decode_sos: ac/dc index out of range\n");
+    av_log(s->avctx, AV_LOG_ERROR, "decode_sos: ac/dc index out of range\n");
     return -1;
 }
 
@@ -1647,7 +1763,7 @@ static int mjpeg_decode_dri(MJpegDecodeContext *s)
         return -1;
     s->restart_interval = get_bits(&s->gb, 16);
     s->restart_count = 0;
-    dprintf("restart interval: %d\n", s->restart_interval);
+    av_log(s->avctx, AV_LOG_DEBUG, "restart interval: %d\n", s->restart_interval);
 
     return 0;
 }
@@ -1881,7 +1997,7 @@ static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
     val = -1;
 found:
 #ifdef DEBUG
-    dprintf("find_marker skipped %d bytes\n", skipped);
+    av_log(NULL, AV_LOG_VERBOSE, "find_marker skipped %d bytes\n", skipped);
 #endif
     *pbuf_ptr = buf_ptr;
     return val;
@@ -1906,14 +2022,14 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
             if (start_code < 0) {
                 goto the_end;
             } else {
-                dprintf("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=%d\n", start_code, buf_end - buf_ptr);
 
                 if ((buf_end - buf_ptr) > s->buffer_size)
                 {
                     av_free(s->buffer);
                     s->buffer_size = buf_end-buf_ptr;
                     s->buffer = av_malloc(s->buffer_size + FF_INPUT_BUFFER_PADDING_SIZE);
-                    dprintf("buffer too small, expanding to %d bytes\n",
+                    av_log(avctx, AV_LOG_DEBUG, "buffer too small, expanding to %d bytes\n",
                         s->buffer_size);
                 }
 
@@ -1928,21 +2044,23 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                         uint8_t x = *(src++);
 
                         *(dst++) = x;
-                        if (x == 0xff)
+                        if (avctx->codec_id != CODEC_ID_THP)
                         {
-                            while(src<buf_end && x == 0xff)
-                                x = *(src++);
-
-                            if (x >= 0xd0 && x <= 0xd7)
-                                *(dst++) = x;
-                            else if (x)
-                                break;
+                            if (x == 0xff) {
+                                while (src < buf_end && x == 0xff)
+                                    x = *(src++);
+
+                                if (x >= 0xd0 && x <= 0xd7)
+                                    *(dst++) = x;
+                                else if (x)
+                                    break;
+                            }
                         }
                     }
                     init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8);
 
-                    dprintf("escaping removed %d bytes\n",
-                        (buf_end - buf_ptr) - (dst - s->buffer));
+                    av_log(avctx, AV_LOG_DEBUG, "escaping removed %d bytes\n",
+                           (buf_end - buf_ptr) - (dst - s->buffer));
                 }
                 else if(start_code == SOS && s->ls){
                     uint8_t *src = buf_ptr;
@@ -1988,12 +2106,12 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
 
                 s->start_code = start_code;
                 if(s->avctx->debug & FF_DEBUG_STARTCODE){
-                    av_log(s->avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code);
+                    av_log(avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code);
                 }
 
                 /* process markers */
                 if (start_code >= 0xd0 && start_code <= 0xd7) {
-                    dprintf("restart marker: %d\n", start_code&0x0f);
+                    av_log(avctx, AV_LOG_DEBUG, "restart marker: %d\n", start_code&0x0f);
                     /* APP fields */
                 } else if (start_code >= APP0 && start_code <= APP15) {
                     mjpeg_decode_app(s);
@@ -2014,23 +2132,35 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                     break;
                 case DHT:
                     if(mjpeg_decode_dht(s) < 0){
-                        av_log(s->avctx, AV_LOG_ERROR, "huffman table decode error\n");
+                        av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n");
                         return -1;
                     }
                     break;
                 case SOF0:
                     s->lossless=0;
+                    s->ls=0;
+                    s->progressive=0;
+                    if (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)
                         return -1;
                     break;
                 case SOF3:
                     s->lossless=1;
+                    s->ls=0;
+                    s->progressive=0;
                     if (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)
                         return -1;
                     break;
@@ -2047,7 +2177,7 @@ eoi_parser:
                         if (s->interlaced) {
                             s->bottom_field ^= 1;
                             /* if not bottom field, do not output image yet */
-                            if (s->bottom_field)
+                            if (s->bottom_field == !s->interlace_polarity)
                                 goto not_the_end;
                         }
                         *picture = s->picture;
@@ -2059,7 +2189,7 @@ eoi_parser:
                             picture->qscale_table= s->qscale_table;
                             memset(picture->qscale_table, picture->quality, (s->width+15)/16);
                             if(avctx->debug & FF_DEBUG_QP)
-                                av_log(s->avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
+                                av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
                             picture->quality*= FF_QP2LAMBDA;
                         }
 
@@ -2077,7 +2207,6 @@ eoi_parser:
                     mjpeg_decode_dri(s);
                     break;
                 case SOF1:
-                case SOF2:
                 case SOF5:
                 case SOF6:
                 case SOF7:
@@ -2088,7 +2217,7 @@ eoi_parser:
                 case SOF14:
                 case SOF15:
                 case JPG:
-                    av_log(s->avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
+                    av_log(avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
                     break;
 //                default:
 //                    printf("mjpeg: unsupported marker (%x)\n", start_code);
@@ -2098,13 +2227,13 @@ eoi_parser:
 not_the_end:
                 /* eof process start code */
                 buf_ptr += (get_bits_count(&s->gb)+7)/8;
-                dprintf("marker parser used %d bytes (%d bits)\n",
-                    (get_bits_count(&s->gb)+7)/8, get_bits_count(&s->gb));
+                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));
             }
         }
     }
 the_end:
-    dprintf("mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr);
+    av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr);
 //    return buf_end - buf_ptr;
     return buf_ptr - buf;
 }
@@ -2133,22 +2262,22 @@ read_header:
 
     skip_bits(&hgb, 32); /* reserved zeros */
 
-    if (get_bits_long(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg")))
+    if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g'))
     {
-        dprintf("not mjpeg-b (bad fourcc)\n");
+        av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n");
         return 0;
     }
 
     field_size = get_bits_long(&hgb, 32); /* field size */
-    dprintf("field size: 0x%x\n", 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);
-    dprintf("second field offs: 0x%x\n", second_field_offs);
+    av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs);
     if (second_field_offs)
         s->interlaced = 1;
 
     dqt_offs = get_bits_long(&hgb, 32);
-    dprintf("dqt offs: 0x%x\n", dqt_offs);
+    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);
@@ -2157,7 +2286,7 @@ read_header:
     }
 
     dht_offs = get_bits_long(&hgb, 32);
-    dprintf("dht offs: 0x%x\n", dht_offs);
+    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);
@@ -2166,7 +2295,7 @@ read_header:
     }
 
     sof_offs = get_bits_long(&hgb, 32);
-    dprintf("sof offs: 0x%x\n", sof_offs);
+    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);
@@ -2176,9 +2305,9 @@ read_header:
     }
 
     sos_offs = get_bits_long(&hgb, 32);
-    dprintf("sos offs: 0x%x\n", sos_offs);
+    av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs);
     sod_offs = get_bits_long(&hgb, 32);
-    dprintf("sod offs: 0x%x\n", sod_offs);
+    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);
@@ -2388,6 +2517,61 @@ static int mjpeg_decode_end(AVCodecContext *avctx)
     return 0;
 }
 
+static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
+                              uint8_t **poutbuf, int *poutbuf_size,
+                              const uint8_t *buf, int buf_size, int keyframe)
+{
+    uint8_t *poutbufp;
+    int i;
+
+    if (avctx->codec_id != CODEC_ID_MJPEG) {
+        av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n");
+        return 0;
+    }
+
+    *poutbuf_size = 0;
+    *poutbuf = av_malloc(buf_size + 44 + FF_INPUT_BUFFER_PADDING_SIZE);
+    poutbufp = *poutbuf;
+    bytestream_put_byte(&poutbufp, 0xff);
+    bytestream_put_byte(&poutbufp, SOI);
+    bytestream_put_byte(&poutbufp, 0xff);
+    bytestream_put_byte(&poutbufp, APP1);
+    bytestream_put_be16(&poutbufp, 42); /* size */
+    bytestream_put_be32(&poutbufp, 0);
+    bytestream_put_buffer(&poutbufp, "mjpg", 4);
+    bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */
+    bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */
+    bytestream_put_be32(&poutbufp, 0);             /* next ptr */
+
+    for (i = 0; i < buf_size - 1; i++) {
+        if (buf[i] == 0xff) {
+            switch (buf[i + 1]) {
+            case DQT:  /* quant off */
+            case DHT:  /* huff  off */
+            case SOF0: /* image off */
+                bytestream_put_be32(&poutbufp, i + 46);
+                break;
+            case SOS:
+                bytestream_put_be32(&poutbufp, i + 46); /* scan off */
+                bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */
+                bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */
+                *poutbuf_size = poutbufp - *poutbuf;
+                return 1;
+            case APP1:
+                if (i + 8 < buf_size && AV_RL32(buf + i + 8) == ff_get_fourcc("mjpg")) {
+                    av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n");
+                    memcpy(*poutbuf, buf, buf_size);
+                    *poutbuf_size = buf_size;
+                    return 1;
+                }
+            }
+        }
+    }
+    av_freep(poutbuf);
+    av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
+    return 0;
+}
+
 AVCodec mjpeg_decoder = {
     "mjpeg",
     CODEC_TYPE_VIDEO,
@@ -2401,6 +2585,19 @@ AVCodec mjpeg_decoder = {
     NULL
 };
 
+AVCodec thp_decoder = {
+    "thp",
+    CODEC_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,
@@ -2447,3 +2644,8 @@ AVCodecParser mjpeg_parser = {
     ff_parse_close,
 };
 
+AVBitStreamFilter mjpega_dump_header_bsf = {
+    "mjpegadump",
+    0,
+    mjpega_dump_header,
+};