added forgotten emms() - fix various segmentation faults when using mjpeg
[ffmpeg.git] / libavcodec / mjpeg.c
index 1dcc9ac..97a9501 100644 (file)
@@ -220,7 +220,7 @@ static int put_huffman_table(MpegEncContext *s, int table_class, int table_id,
 static void jpeg_table_header(MpegEncContext *s)
 {
     PutBitContext *p = &s->pb;
-    int i, size;
+    int i, j, size;
     UINT8 *ptr;
 
     /* quant matrixes */
@@ -229,13 +229,15 @@ static void jpeg_table_header(MpegEncContext *s)
     put_bits(p, 4, 0); /* 8 bit precision */
     put_bits(p, 4, 0); /* table 0 */
     for(i=0;i<64;i++) {
-        put_bits(p, 8, s->intra_matrix[i]);
+        j = zigzag_direct[i];
+        put_bits(p, 8, s->intra_matrix[j]);
     }
 #if 0
     put_bits(p, 4, 0); /* 8 bit precision */
     put_bits(p, 4, 1); /* table 1 */
     for(i=0;i<64;i++) {
-        put_bits(p, 8, s->chroma_intra_matrix[i]);
+        j = zigzag_direct[i];
+        put_bits(p, 8, s->chroma_intra_matrix[j]);
     }
 #endif
 
@@ -455,6 +457,18 @@ typedef struct MJpegDecodeContext {
     UINT8 buffer[PICTURE_BUFFER_SIZE]; 
 } MJpegDecodeContext;
 
+static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table, 
+                      int nb_codes)
+{
+    UINT8 huff_size[256];
+    UINT16 huff_code[256];
+
+    memset(huff_size, 0, sizeof(huff_size));
+    build_huffman_codes(huff_size, huff_code, bits_table, val_table);
+    
+    init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2);
+}
+
 static int mjpeg_decode_init(AVCodecContext *avctx)
 {
     MJpegDecodeContext *s = avctx->priv_data;
@@ -465,6 +479,11 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
                                                  account FF 00 case */
     s->start_code = -1;
     s->buf_ptr = s->buffer;
+
+    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);
     return 0;
 }
 
@@ -472,7 +491,7 @@ static int mjpeg_decode_init(AVCodecContext *avctx)
 static int mjpeg_decode_dqt(MJpegDecodeContext *s,
                             UINT8 *buf, int buf_size)
 {
-    int len, index, i;
+    int len, index, i, j;
     init_get_bits(&s->gb, buf, buf_size);
 
     len = get_bits(&s->gb, 16);
@@ -487,8 +506,10 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s,
             return -1;
         dprintf("index=%d\n", index);
         /* read quant table */
-        for(i=0;i<64;i++)
-            s->quant_matrixes[index][i] = get_bits(&s->gb, 8);
+        for(i=0;i<64;i++) {
+            j = zigzag_direct[i];
+            s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
+        }
         len -= 65;
     }
     return 0;
@@ -501,8 +522,6 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s,
     int len, index, i, class, n, v, code_max;
     UINT8 bits_table[17];
     UINT8 val_table[256];
-    UINT8 huff_size[256];
-    UINT16 huff_code[256];
     
     init_get_bits(&s->gb, buf, buf_size);
 
@@ -536,17 +555,11 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s,
         }
         len -= n;
 
-        /* now build size/code table */
-        memset(huff_size, 0, sizeof(huff_size));
-        build_huffman_codes(huff_size, huff_code, bits_table, val_table);
-        
         /* build VLC and flush previous vlc if present */
         free_vlc(&s->vlcs[class][index]);
         dprintf("class=%d index=%d nb_codes=%d\n",
                class, index, code_max + 1);
-        init_vlc(&s->vlcs[class][index], 9, code_max + 1,
-                 huff_size, 1, 1,
-                 huff_code, 2, 2);
+        build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1);
     }
     return 0;
 }
@@ -583,12 +596,6 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s,
             s->h_max = s->h_count[i];
         if (s->v_count[i] > s->v_max)
             s->v_max = s->v_count[i];
-#if 1
-        /* XXX: only 420 is accepted */
-        if ((i == 0 && (s->h_count[i] != 2 || s->v_count[i] != 2)) ||
-            (i != 0 && (s->h_count[i] != 1 || s->v_count[i] != 1)))
-            return -1;
-#endif
         s->quant_index[i] = get_bits(&s->gb, 8);
         if (s->quant_index[i] >= 4)
             return -1;
@@ -659,7 +666,6 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
     val = val * quant_matrix[0] + s->last_dc[component];
     s->last_dc[component] = val;
     block[0] = val;
-
     /* AC coefs */
     ac_vlc = &s->vlcs[1][ac_index];
     i = 1;
@@ -688,6 +694,8 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
             j = zigzag_direct[i];
             block[j] = level * quant_matrix[j];
             i++;
+            if (i >= 64)
+                break;
         }
     }
     return 0;
@@ -727,7 +735,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
         nb_blocks[i] = s->h_count[index] * s->v_count[index];
         h_count[i] = s->h_count[index];
         v_count[i] = s->v_count[index];
-        
+
         dc_index[i] = get_bits(&s->gb, 4);
         if (dc_index[i] >= 4)
             return -1;
@@ -788,6 +796,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s,
             }
         }
     }
+    emms_c();
     return 0;
 }
 
@@ -866,6 +875,7 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                 start_code = s->start_code;
                 s->buf_ptr = s->buffer;
                 s->start_code = code;
+                dprintf("marker=%x\n", start_code);
                 switch(start_code) {
                 case SOI:
                     /* nothing to do on SOI */
@@ -882,7 +892,6 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                 case SOS:
                     mjpeg_decode_sos(s, s->buffer, input_size);
                     if (s->start_code == EOI) {
-                        /* XXX: YUV420 hardcoded */
                         for(i=0;i<3;i++) {
                             picture->data[i] = s->current_picture[i];
                             picture->linesize[i] = s->linesize[i];
@@ -890,7 +899,19 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
                         *data_size = sizeof(AVPicture);
                         avctx->height = s->height;
                         avctx->width = s->width;
-                        avctx->pix_fmt = PIX_FMT_YUV420P;
+                        /* XXX: not complete test ! */
+                        switch((s->h_count[0] << 4) | s->v_count[0]) {
+                        case 0x11:
+                            avctx->pix_fmt = PIX_FMT_YUV444P;
+                            break;
+                        case 0x21:
+                            avctx->pix_fmt = PIX_FMT_YUV422P;
+                            break;
+                        default:
+                        case 0x22:
+                            avctx->pix_fmt = PIX_FMT_YUV420P;
+                            break;
+                        }
                         goto the_end;
                     }
                     break;