]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mjpeg.c
reinitialize on aspect change,
[ffmpeg] / libavcodec / mjpeg.c
index 7aed3e28acf890724863aec87f63ef5d5b157a1a..4c2b4793bf36670fbeab18f92c50bb477c84f3cf 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * MJPEG encoder and decoder
  * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2003 Alex Beregszaszi
+ * Copyright (c) 2003-2004 Michael Niedermayer
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -398,6 +400,19 @@ static void jpeg_put_comments(MpegEncContext *s)
         ptr[0] = size >> 8;
         ptr[1] = size;
     }
+
+    if(  s->avctx->pix_fmt == PIX_FMT_YUV420P 
+       ||s->avctx->pix_fmt == PIX_FMT_YUV422P
+       ||s->avctx->pix_fmt == PIX_FMT_YUV444P){
+        put_marker(p, COM);
+        flush_put_bits(p);
+        ptr = pbBufPtr(p);
+        put_bits(p, 16, 0); /* patched later */
+        put_string(p, "CS=ITU601", 1);
+        size = strlen("CS=ITU601")+3;
+        ptr[0] = size >> 8;
+        ptr[1] = size;
+    }
 }
 
 void mjpeg_picture_header(MpegEncContext *s)
@@ -531,11 +546,16 @@ static void escape_FF(MpegEncContext *s, int start)
     }
 }
 
+void ff_mjpeg_stuffing(PutBitContext * pbc)
+{
+    int length;
+    length= (-put_bits_count(pbc))&7;
+    if(length) put_bits(pbc, length, (1<<length)-1);
+}
+
 void mjpeg_picture_trailer(MpegEncContext *s)
 {
-    int pad= (-put_bits_count(&s->pb))&7;
-    
-    put_bits(&s->pb, pad,0xFF>>(8-pad));
+    ff_mjpeg_stuffing(&s->pb);
     flush_put_bits(&s->pb);
 
     assert((s->header_bits&7)==0);
@@ -652,11 +672,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
     mjpeg_picture_header(s);
 
     s->header_bits= put_bits_count(&s->pb);
-
+    
     if(avctx->pix_fmt == PIX_FMT_RGBA32){
         int x, y, i;
         const int linesize= p->linesize[0];
-        uint16_t buffer[2048][4];
+        uint16_t (*buffer)[4]= (void *) s->rd_scratchpad;
         int left[3], top[3], topleft[3];
 
         for(i=0; i<3; i++){
@@ -667,6 +687,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
             const int modified_predictor= y ? predictor : 1;
             uint8_t *ptr = p->data[0] + (linesize * y);
 
+            if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < width*3*4){
+                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+                return -1;
+            }
+            
             for(i=0; i<3; i++){
                 top[i]= left[i]= topleft[i]= buffer[0][i];
             }
@@ -700,6 +725,10 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
         const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0];
         
         for(mb_y = 0; mb_y < mb_height; mb_y++) {
+            if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){
+                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+                return -1;
+            }
             for(mb_x = 0; mb_x < mb_width; mb_x++) {
                 if(mb_x==0 || mb_y==0){
                     for(i=0;i<3;i++) {
@@ -820,7 +849,7 @@ typedef struct MJpegDecodeContext {
     int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */
     AVFrame picture; /* picture structure */
     int linesize[MAX_COMPONENTS];                   ///< linesize << interlaced
-    uint8_t *qscale_table;
+    int8_t *qscale_table;
     DCTELEM block[64] __align8;
     ScanTable scantable;
     void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
@@ -829,13 +858,16 @@ typedef struct MJpegDecodeContext {
     int restart_count;
 
     int buggy_avid;
+    int cs_itu601;
     int interlace_polarity;
+
+    int mjpb_skiptosod;
 } MJpegDecodeContext;
 
 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 nb_codes, int use_static)
 {
     uint8_t huff_size[256];
     uint16_t huff_code[256];
@@ -843,7 +875,7 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_tab
     memset(huff_size, 0, sizeof(huff_size));
     build_huffman_codes(huff_size, huff_code, bits_table, val_table);
     
-    return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2);
+    return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);
 }
 
 static int mjpeg_decode_init(AVCodecContext *avctx)
@@ -857,13 +889,11 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
     memset(&s2, 0, sizeof(MpegEncContext));
     s2.avctx= avctx;
 //    s2->out_format = FMT_MJPEG;
-    s2.width = 8;
-    s2.height = 8;
-    if (MPV_common_init(&s2) < 0)
-       return -1;
+    dsputil_init(&s2.dsp, avctx);
+    DCT_common_init(&s2);
+
     s->scantable= s2.intra_scantable;
     s->idct_put= s2.dsp.idct_put;
-    MPV_common_end(&s2);
 
     s->mpeg_enc_ctx_allocated = 0;
     s->buffer_size = 102400; /* smaller buffer should be enough,
@@ -873,12 +903,12 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
        return -1;
     s->start_code = -1;
     s->first_picture = 1;
-    s->org_height = avctx->height;
+    s->org_height = avctx->coded_height;
     
-    build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12);
-    build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12);
-    build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251);
-    build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251);
+    build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12, 0);
+    build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12, 0);
+    build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251, 0);
+    build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251, 0);
 
     if (avctx->flags & CODEC_FLAG_EXTERN_HUFF)
     {
@@ -891,6 +921,69 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
     return 0;
 }
 
+
+/**
+ * finds the end of the current frame in the bitstream.
+ * @return the position of the first byte of the next frame, or -1
+ */
+static int find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){
+    int vop_found, i;
+    uint16_t state;
+    
+    vop_found= pc->frame_start_found;
+    state= pc->state;
+    
+    i=0;
+    if(!vop_found){
+        for(i=0; i<buf_size; i++){
+            state= (state<<8) | buf[i];
+            if(state == 0xFFD8){
+                i++;
+                vop_found=1;
+                break;
+            }
+        }
+    }
+
+    if(vop_found){
+        /* EOF considered as end of frame */
+        if (buf_size == 0)
+            return 0;
+        for(; i<buf_size; i++){
+            state= (state<<8) | buf[i];
+            if(state == 0xFFD8){
+                pc->frame_start_found=0;
+                pc->state=0; 
+                return i-1;
+            }
+        }
+    }
+    pc->frame_start_found= vop_found;
+    pc->state= state;
+    return END_NOT_FOUND;
+}
+
+static int jpeg_parse(AVCodecParserContext *s,
+                           AVCodecContext *avctx,
+                           uint8_t **poutbuf, int *poutbuf_size, 
+                           const uint8_t *buf, int buf_size)
+{
+    ParseContext *pc = s->priv_data;
+    int next;
+    
+    next= find_frame_end(pc, buf, buf_size);
+
+    if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return buf_size;
+    }
+
+    *poutbuf = (uint8_t *)buf;
+    *poutbuf_size = buf_size;
+    return next;
+}
+
 /* quantize tables */
 static int mjpeg_decode_dqt(MJpegDecodeContext *s)
 {
@@ -966,7 +1059,7 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s)
         free_vlc(&s->vlcs[class][index]);
         dprintf("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){
+        if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0) < 0){
             return -1;
         }
     }
@@ -990,7 +1083,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
     }
     height = get_bits(&s->gb, 16);
     width = get_bits(&s->gb, 16);
+    
     dprintf("sof0: picture: %dx%d\n", width, height);
+    if(avcodec_check_dimensions(s->avctx, width, height))
+        return -1;
 
     nb_components = get_bits(&s->gb, 8);
     if (nb_components <= 0 ||
@@ -1025,8 +1121,7 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
             
         s->width = width;
         s->height = height;
-        s->avctx->width = s->width;
-        s->avctx->height = s->height;
+        avcodec_set_dimensions(s->avctx, width, height);
 
         /* test interlaced mode */
         if (s->first_picture &&
@@ -1052,16 +1147,16 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
         if(s->rgb){
             s->avctx->pix_fmt = PIX_FMT_RGBA32;
         }else if(s->nb_components==3)
-            s->avctx->pix_fmt = PIX_FMT_YUV444P;
+            s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P;
         else
             s->avctx->pix_fmt = PIX_FMT_GRAY8;
         break;
     case 0x21:
-        s->avctx->pix_fmt = PIX_FMT_YUV422P;
+        s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P;
         break;
     default:
     case 0x22:
-        s->avctx->pix_fmt = PIX_FMT_YUV420P;
+        s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P;
         break;
     }
 
@@ -1159,11 +1254,14 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
 
 static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
     int i, mb_x, mb_y;
-    uint16_t buffer[2048][4];
+    uint16_t buffer[32768][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;
+    
     for(i=0; i<3; i++){
         buffer[0][i]= 1 << (s->bits + point_transform - 1);
     }
@@ -1333,11 +1431,11 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){
                     }
 //                 dprintf("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->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;
-//printf("%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);
+//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 (++x == h) {
                         x = 0;
@@ -1450,6 +1548,10 @@ 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\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "", predictor, point_transform);
     
+    /* mjpeg-b can have padding bytes between sos and image data, skip them */
+    for (i = s->mjpb_skiptosod; i > 0; i--)
+        skip_bits(&s->gb, 8);
+
     if(s->lossless){
             if(s->rgb){
                 if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0)
@@ -1527,15 +1629,22 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     
     if (id == ff_get_fourcc("JFIF"))
     {
-       int t_w, t_h;
+       int t_w, t_h, v1, v2;
        skip_bits(&s->gb, 8); /* the trailing zero-byte */
-       av_log(s->avctx, AV_LOG_INFO, "mjpeg: JFIF header found (version: %x.%x)\n",
-           get_bits(&s->gb, 8), get_bits(&s->gb, 8));
+       v1= get_bits(&s->gb, 8);
+        v2= get_bits(&s->gb, 8);
         skip_bits(&s->gb, 8);
 
         s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 16);
         s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 16);
 
+        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
+            av_log(s->avctx, AV_LOG_INFO, "mjpeg: JFIF header found (version: %x.%x) SAR=%d/%d\n",
+                v1, v2,
+                s->avctx->sample_aspect_ratio.num,
+                s->avctx->sample_aspect_ratio.den
+            );
+
        t_w = get_bits(&s->gb, 8);
        t_h = get_bits(&s->gb, 8);
        if (t_w && t_h)
@@ -1550,7 +1659,8 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     
     if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e'))
     {
-       av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n");
+        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
+            av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n");
        skip_bits(&s->gb, 16); /* version */
        skip_bits(&s->gb, 16); /* flags0 */
        skip_bits(&s->gb, 16); /* flags1 */
@@ -1560,7 +1670,8 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     }
 
     if (id == ff_get_fourcc("LJIF")){
-        av_log(s->avctx, AV_LOG_INFO, "Pegasus lossless jpeg header found\n");
+        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? */
@@ -1599,7 +1710,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
            skip_bits(&s->gb, 32); /* scan off */
            skip_bits(&s->gb, 32); /* data off */
 #endif
-           if (s->first_picture)
+            if (s->avctx->debug & FF_DEBUG_PICT_INFO)
                av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n");
        }
     }
@@ -1630,7 +1741,8 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
            else
                cbuf[i] = 0;
 
-           av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf);
+            if(s->avctx->debug & FF_DEBUG_PICT_INFO)
+                av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf);
 
            /* buggy avid, it puts EOI only at every 10th frame */
            if (!strcmp(cbuf, "AVID"))
@@ -1639,6 +1751,9 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
                //      if (s->first_picture)
                //          printf("mjpeg: workarounding buggy AVID\n");
            }
+            else if(!strcmp(cbuf, "CS=ITU601")){
+                s->cs_itu601= 1;
+            }
 
            av_free(cbuf);
        }
@@ -1711,12 +1826,6 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
     int start_code;
     AVFrame *picture = data;
 
-    *data_size = 0;
-
-    /* no supplementary picture */
-    if (buf_size == 0)
-        return 0;
-
     buf_ptr = buf;
     buf_end = buf + buf_size;
     while (buf_ptr < buf_end) {
@@ -1751,9 +1860,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                        *(dst++) = x;
                        if (x == 0xff)
                        {
-                           while(*src == 0xff) src++;
+                            while(src<buf_end && x == 0xff)
+                                x = *(src++);
 
-                           x = *(src++);
                            if (x >= 0xd0 && x <= 0xd7)
                                *(dst++) = x;
                            else if (x)
@@ -1776,13 +1885,12 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                /* process markers */
                if (start_code >= 0xd0 && start_code <= 0xd7) {
                    dprintf("restart marker: %d\n", start_code&0x0f);
-               } else if (s->first_picture) {
                    /* APP fields */
-                   if (start_code >= 0xe0 && start_code <= 0xef)
-                       mjpeg_decode_app(s);
+               } else if (start_code >= APP0 && start_code <= APP15) {
+                   mjpeg_decode_app(s);
                    /* Comment */
-                   else if (start_code == COM)
-                       mjpeg_decode_com(s);
+               } else if (start_code == COM){
+                   mjpeg_decode_com(s);
                }
 
                 switch(start_code) {
@@ -1888,13 +1996,7 @@ static int mjpegb_decode_frame(AVCodecContext *avctx,
     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;
-
-    *data_size = 0;
-
-    /* no supplementary picture */
-    if (buf_size == 0)
-        return 0;
+    uint32_t field_size, sod_offs;
 
     buf_ptr = buf;
     buf_end = buf + buf_size;
@@ -1902,26 +2004,27 @@ static int mjpegb_decode_frame(AVCodecContext *avctx,
 read_header:
     /* reset on every SOI */
     s->restart_interval = 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(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg")))
+    if (get_bits_long(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg")))
     {
        dprintf("not mjpeg-b (bad fourcc)\n");
        return 0;
     }
 
-    field_size = get_bits(&hgb, 32); /* field size */
+    field_size = get_bits_long(&hgb, 32); /* field size */
     dprintf("field size: 0x%x\n", field_size);
     skip_bits(&hgb, 32); /* padded field size */
-    second_field_offs = get_bits(&hgb, 32);
+    second_field_offs = get_bits_long(&hgb, 32);
     dprintf("second field offs: 0x%x\n", second_field_offs);
     if (second_field_offs)
        s->interlaced = 1;
 
-    dqt_offs = get_bits(&hgb, 32);
+    dqt_offs = get_bits_long(&hgb, 32);
     dprintf("dqt offs: 0x%x\n", dqt_offs);
     if (dqt_offs)
     {
@@ -1930,7 +2033,7 @@ read_header:
        mjpeg_decode_dqt(s);
     }
     
-    dht_offs = get_bits(&hgb, 32);
+    dht_offs = get_bits_long(&hgb, 32);
     dprintf("dht offs: 0x%x\n", dht_offs);
     if (dht_offs)
     {
@@ -1939,7 +2042,7 @@ read_header:
        mjpeg_decode_dht(s);
     }
 
-    sof_offs = get_bits(&hgb, 32);
+    sof_offs = get_bits_long(&hgb, 32);
     dprintf("sof offs: 0x%x\n", sof_offs);
     if (sof_offs)
     {
@@ -1949,18 +2052,19 @@ read_header:
            return -1;
     }
 
-    sos_offs = get_bits(&hgb, 32);
+    sos_offs = get_bits_long(&hgb, 32);
     dprintf("sos offs: 0x%x\n", sos_offs);
+    sod_offs = get_bits_long(&hgb, 32);
+    dprintf("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);
     }
 
-    skip_bits(&hgb, 32); /* start of data offset */
-
     if (s->interlaced) {
         s->bottom_field ^= 1;
         /* if not bottom field, do not output image yet */
@@ -2003,12 +2107,6 @@ static int sp5x_decode_frame(AVCodecContext *avctx,
     uint8_t *buf_ptr, *buf_end, *recoded;
     int i = 0, j = 0;
 
-    *data_size = 0;
-
-    /* no supplementary picture */
-    if (buf_size == 0)
-        return 0;
-
     if (!avctx->width || !avctx->height)
        return -1;
 
@@ -2033,10 +2131,10 @@ static int sp5x_decode_frame(AVCodecContext *avctx,
     j += sizeof(sp5x_data_dht);
 
     memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof));
-    recoded[j+5] = (avctx->height >> 8) & 0xFF;
-    recoded[j+6] = avctx->height & 0xFF;
-    recoded[j+7] = (avctx->width >> 8) & 0xFF;
-    recoded[j+8] = avctx->width & 0xFF;
+    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));
@@ -2060,8 +2158,8 @@ static int sp5x_decode_frame(AVCodecContext *avctx,
 #else
     /* SOF */
     s->bits = 8;
-    s->width = avctx->width;
-    s->height = avctx->height;
+    s->width  = avctx->coded_width;
+    s->height = avctx->coded_height;
     s->nb_components = 3;
     s->component_id[0] = 0;
     s->h_count[0] = 2;
@@ -2079,7 +2177,7 @@ static int sp5x_decode_frame(AVCodecContext *avctx,
     s->v_max = 2;
     
     s->qscale_table = av_mallocz((s->width+15)/16);
-    avctx->pix_fmt = PIX_FMT_YUV420P;
+    avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420;
     s->interlaced = 0;
     
     s->picture.reference = 0;
@@ -2159,7 +2257,6 @@ static int mjpeg_decode_end(AVCodecContext *avctx)
 
     av_free(s->buffer);
     av_free(s->qscale_table);
-    avcodec_default_free_buffers(avctx);
     
     for(i=0;i<2;i++) {
         for(j=0;j<4;j++)
@@ -2218,3 +2315,12 @@ AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
     MPV_encode_end,
 };
 #endif
+
+AVCodecParser mjpeg_parser = {
+    { CODEC_ID_MJPEG },
+    sizeof(ParseContext),
+    NULL,
+    jpeg_parse,
+    ff_parse_close,
+};
+