]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mjpeg.c
reinitialize on aspect change,
[ffmpeg] / libavcodec / mjpeg.c
index e6bbd97559a41558de9286ffc467cad4126f4750..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
@@ -243,6 +245,7 @@ static void build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
     }
 }
 
+#ifdef CONFIG_ENCODERS
 int mjpeg_init(MpegEncContext *s)
 {
     MJpegContext *m;
@@ -280,6 +283,7 @@ void mjpeg_close(MpegEncContext *s)
 {
     av_free(s->mjpeg_ctx);
 }
+#endif //CONFIG_ENCODERS
 
 #define PREDICT(ret, topleft, top, left, predictor)\
     switch(predictor){\
@@ -376,31 +380,11 @@ static void jpeg_put_comments(MpegEncContext *s)
     /* JFIF header */
     put_marker(p, APP0);
     put_bits(p, 16, 16);
-    put_string(p, "JFIF"); /* this puts the trailing zero-byte too */
+    put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */
     put_bits(p, 16, 0x0201); /* v 1.02 */
     put_bits(p, 8, 0); /* units type: 0 - aspect ratio */
-    switch(s->aspect_ratio_info)
-    {
-       case FF_ASPECT_4_3_625:
-       case FF_ASPECT_4_3_525:
-           put_bits(p, 16, 4); 
-           put_bits(p, 16, 3);
-           break;
-       case FF_ASPECT_16_9_625:
-       case FF_ASPECT_16_9_525:
-           put_bits(p, 16, 16); 
-           put_bits(p, 16, 9);
-           break;
-       case FF_ASPECT_EXTENDED:
-           put_bits(p, 16, s->aspected_width);
-           put_bits(p, 16, s->aspected_height);
-           break;
-       case FF_ASPECT_SQUARE:
-       default:
-           put_bits(p, 16, 1); /* aspect: 1:1 */
-           put_bits(p, 16, 1);
-           break;
-    }
+    put_bits(p, 16, s->avctx->sample_aspect_ratio.num);
+    put_bits(p, 16, s->avctx->sample_aspect_ratio.den);
     put_bits(p, 8, 0); /* thumbnail width */
     put_bits(p, 8, 0); /* thumbnail height */
     }
@@ -411,11 +395,24 @@ static void jpeg_put_comments(MpegEncContext *s)
         flush_put_bits(p);
         ptr = pbBufPtr(p);
         put_bits(p, 16, 0); /* patched later */
-        put_string(p, LIBAVCODEC_IDENT);
+        put_string(p, LIBAVCODEC_IDENT, 1);
         size = strlen(LIBAVCODEC_IDENT)+3;
         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)
@@ -495,7 +492,7 @@ void mjpeg_picture_header(MpegEncContext *s)
 
 static void escape_FF(MpegEncContext *s, int start)
 {
-    int size= get_bit_count(&s->pb) - start*8;
+    int size= put_bits_count(&s->pb) - start*8;
     int i, ff_count;
     uint8_t *buf= s->pb.buf + start;
     int align= (-(size_t)(buf))&3;
@@ -549,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= (-get_bit_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);
@@ -661,7 +663,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
     AVFrame * const p= (AVFrame*)&s->current_picture;
     const int predictor= avctx->prediction_method+1;
 
-    init_put_bits(&s->pb, buf, buf_size, NULL, NULL);
+    init_put_bits(&s->pb, buf, buf_size);
 
     *p = *pict;
     p->pict_type= FF_I_TYPE;
@@ -669,12 +671,12 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
     
     mjpeg_picture_header(s);
 
-    s->header_bits= get_bit_count(&s->pb);
-
+    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++){
@@ -685,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];
             }
@@ -718,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++) {
@@ -788,7 +799,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
 
     flush_put_bits(&s->pb);
     return pbBufPtr(&s->pb) - s->pb.buf;
-//    return (get_bit_count(&f->pb)+7)/8;
+//    return (put_bits_count(&f->pb)+7)/8;
 }
 
 #endif //CONFIG_ENCODERS
@@ -811,7 +822,7 @@ typedef struct MJpegDecodeContext {
     VLC vlcs[2][4];
     int qscale[4];      ///< quantizer scale calculated from quant_matrixes
 
-    int org_width, org_height;  /* size given at codec init */
+    int org_height;  /* size given at codec init */
     int first_picture;    /* true if decoding first picture */
     int interlaced;     /* true if interlaced */
     int bottom_field;   /* true if bottom field */
@@ -838,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*/);
@@ -847,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];
@@ -861,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)
@@ -873,16 +887,13 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
 
     /* ugly way to get the idct & scantable FIXME */
     memset(&s2, 0, sizeof(MpegEncContext));
-    s2.flags= avctx->flags;
     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,
@@ -892,17 +903,16 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
        return -1;
     s->start_code = -1;
     s->first_picture = 1;
-    s->org_width = avctx->width;
-    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)
     {
-       printf("mjpeg: using external huffman table\n");
+       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 */
@@ -911,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)
 {
@@ -939,6 +1012,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]);
         len -= 65;
     }
     
@@ -985,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;
         }
     }
@@ -1004,12 +1078,15 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
     if(s->bits==9 && !s->pegasus_rct) s->rct=1;    //FIXME ugly
 
     if (s->bits != 8 && !s->lossless){
-        printf("only 8 bits/component accepted\n");
+        av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n");
         return -1;
     }
     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 ||
@@ -1044,13 +1121,16 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
             
         s->width = width;
         s->height = height;
+        avcodec_set_dimensions(s->avctx, width, height);
+
         /* test interlaced mode */
         if (s->first_picture &&
             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 = 0;
+            s->avctx->height *= 2;
         }
 
         s->qscale_table= av_mallocz((s->width+15)/16);
@@ -1066,15 +1146,17 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
     case 0x11:
         if(s->rgb){
             s->avctx->pix_fmt = PIX_FMT_RGBA32;
-        }else
-            s->avctx->pix_fmt = PIX_FMT_YUV444P;
+        }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:
-        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;
     }
 
@@ -1083,7 +1165,7 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
 
     s->picture.reference= 0;
     if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){
-        fprintf(stderr, "get_buffer() failed\n");
+        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return -1;
     }
     s->picture.pict_type= I_TYPE;
@@ -1172,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);
     }
@@ -1346,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;
@@ -1386,7 +1471,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
        return -1;
     }
     /* XXX: only interleaved scan accepted */
-    if (nb_components != 3)
+    if (nb_components != s->nb_components)
     {
        dprintf("decode_sos: components(%d) mismatch\n", nb_components);
         return -1;
@@ -1461,8 +1546,12 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
     }
 
     if(s->avctx->debug & FF_DEBUG_PICT_INFO)
-        printf("%s %s p:%d >>:%d\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "", predictor, point_transform);
+        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)
@@ -1506,7 +1595,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     len -= 6;
 
     if(s->avctx->debug & FF_DEBUG_STARTCODE){
-        printf("APPx %8X\n", id); 
+        av_log(s->avctx, AV_LOG_DEBUG, "APPx %8X\n", id); 
     }
     
     /* buggy AVID, it puts EOI only at every 10th frame */
@@ -1540,33 +1629,21 @@ 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 */
-       printf("mjpeg: JFIF header found (version: %x.%x)\n",
-           get_bits(&s->gb, 8), get_bits(&s->gb, 8));
-       if (get_bits(&s->gb, 8) == 0)
-       {
-           int x_density, y_density; 
-           x_density = get_bits(&s->gb, 16);
-           y_density = get_bits(&s->gb, 16);
+       v1= get_bits(&s->gb, 8);
+        v2= get_bits(&s->gb, 8);
+        skip_bits(&s->gb, 8);
 
-           dprintf("x/y density: %d (%f), %d (%f)\n", x_density,
-               (float)x_density, y_density, (float)y_density);
-#if 0
-            //MN: needs to be checked
-            if(x_density)
-//                s->avctx->aspect_ratio= s->width*y_density/((float)s->height*x_density);
-               s->avctx->aspect_ratio = (float)x_density/y_density;
-               /* it's better, but every JFIF I have seen stores 1:1 */
-            else
-                s->avctx->aspect_ratio= 0.0;
-#endif
-       }
-       else
-       {
-           skip_bits(&s->gb, 16);
-           skip_bits(&s->gb, 16);
-       }
+        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);
@@ -1582,7 +1659,8 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     
     if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e'))
     {
-       printf("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 */
@@ -1592,7 +1670,8 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
     }
 
     if (id == ff_get_fourcc("LJIF")){
-        printf("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? */
@@ -1607,7 +1686,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
             s->pegasus_rct=1;
             break;
         default:
-            printf("unknown colorspace\n");
+            av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n");
         }
         len -= 9;
         goto out;
@@ -1631,15 +1710,15 @@ 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)
-               printf("mjpeg: Apple MJPEG-A header found\n");
+            if (s->avctx->debug & FF_DEBUG_PICT_INFO)
+               av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n");
        }
     }
 
 out:
     /* slow but needed for extreme adobe jpegs */
     if (len < 0)
-       printf("mjpeg: error, decode_app parser read over the end\n");
+       av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error, decode_app parser read over the end\n");
     while(--len > 0)
        skip_bits(&s->gb, 8);
 
@@ -1662,7 +1741,8 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
            else
                cbuf[i] = 0;
 
-           printf("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"))
@@ -1671,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);
        }
@@ -1717,7 +1800,7 @@ static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
     while (buf_ptr < buf_end) {
         v = *buf_ptr++;
        v2 = *buf_ptr;
-        if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe)) {
+        if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
            val = *buf_ptr++;
            goto found;
         }
@@ -1740,15 +1823,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
 {
     MJpegDecodeContext *s = avctx->priv_data;
     uint8_t *buf_end, *buf_ptr;
-    int i, start_code;
+    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) {
@@ -1783,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)
@@ -1802,19 +1879,18 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                
                s->start_code = start_code;
                 if(s->avctx->debug & FF_DEBUG_STARTCODE){
-                    printf("startcode: %X\n", start_code);
+                    av_log(s->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);
-               } 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) {
@@ -1827,7 +1903,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                     break;
                 case DHT:
                     if(mjpeg_decode_dht(s) < 0){
-                        fprintf(stderr, "huffman table decode error\n");
+                        av_log(s->avctx, AV_LOG_ERROR, "huffman table decode error\n");
                         return -1;
                     }
                     break;
@@ -1854,10 +1930,6 @@ eoi_parser:
                         }
                         *picture = s->picture;
                         *data_size = sizeof(AVFrame);
-                        avctx->height = s->height;
-                        if (s->interlaced)
-                            avctx->height *= 2;
-                        avctx->width = s->width;
 
                         if(!s->lossless){
                             picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]); 
@@ -1865,7 +1937,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)
-                                printf("QP: %d\n", picture->quality);
+                                av_log(s->avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
                             picture->quality*= FF_QP2LAMBDA;
                         }
                         
@@ -1894,7 +1966,7 @@ eoi_parser:
                case SOF14:
                case SOF15:
                case JPG:
-                   printf("mjpeg: unsupported coding type (%x)\n", start_code);
+                   av_log(s->avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
                    break;
 //             default:
 //                 printf("mjpeg: unsupported marker (%x)\n", start_code);
@@ -1921,17 +1993,10 @@ static int mjpegb_decode_frame(AVCodecContext *avctx,
 {
     MJpegDecodeContext *s = avctx->priv_data;
     uint8_t *buf_end, *buf_ptr;
-    int i;
     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;
@@ -1939,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)
     {
@@ -1967,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)
     {
@@ -1976,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)
     {
@@ -1986,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 */
@@ -2013,10 +2080,6 @@ read_header:
 
     *picture= s->picture;
     *data_size = sizeof(AVFrame);
-    avctx->height = s->height;
-    if (s->interlaced)
-        avctx->height *= 2;
-    avctx->width = s->width;
     
     if(!s->lossless){
         picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]); 
@@ -2024,13 +2087,168 @@ read_header:
         picture->qscale_table= s->qscale_table;
         memset(picture->qscale_table, picture->quality, (s->width+15)/16);
         if(avctx->debug & FF_DEBUG_QP)
-            printf("QP: %d\n", picture->quality);
+            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)
+    {
+       fprintf(stderr, "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)
 {
@@ -2039,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++)
@@ -2074,6 +2291,19 @@ AVCodec mjpegb_decoder = {
     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
+};
+
 #ifdef CONFIG_ENCODERS
 AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
     "ljpeg",
@@ -2085,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,
+};
+