mjpeg: Rename some symbols to avpriv_* instead of ff_*
[ffmpeg.git] / libavcodec / mjpegenc.c
index ead7260..d369d36 100644 (file)
 /*
  * MJPEG encoder
- * Copyright (c) 2000 Gerard Lantau.
+ * Copyright (c) 2000, 2001 Fabrice Bellard
+ * Copyright (c) 2003 Alex Beregszaszi
+ * Copyright (c) 2003-2004 Michael Niedermayer
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Support for external huffman table, various fixes (AVID workaround),
+ * aspecting, new decode_frame mechanism and apple mjpeg-b support
+ *                                  by Alex Beregszaszi
  *
- * This program is distributed in the hope that it will be useful,
+ * This file is part of Libav.
+ *
+ * Libav 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.1 of the License, or (at your option) any later version.
+ *
+ * Libav 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 General Public License for more details.
+ * 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 General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
-#include <stdlib.h>
-#include <stdio.h>
-#include "avcodec.h"
-#include "dsputil.h"
-#include "mpegvideo.h"
 
-typedef struct MJpegContext {
-    UINT8 huff_size_dc_luminance[12];
-    UINT16 huff_code_dc_luminance[12];
-    UINT8 huff_size_dc_chrominance[12];
-    UINT16 huff_code_dc_chrominance[12];
-
-    UINT8 huff_size_ac_luminance[256];
-    UINT16 huff_code_ac_luminance[256];
-    UINT8 huff_size_ac_chrominance[256];
-    UINT16 huff_code_ac_chrominance[256];
-} MJpegContext;
-
-#define SOF0 0xc0
-#define SOI 0xd8
-#define EOI 0xd9
-#define DQT 0xdb
-#define DHT 0xc4
-#define SOS 0xda
-
-#if 0
-/* These are the sample quantization tables given in JPEG spec section K.1.
- * The spec says that the values given produce "good" quality, and
- * when divided by 2, "very good" quality.
+/**
+ * @file
+ * MJPEG encoder.
  */
-static const unsigned char std_luminance_quant_tbl[64] = {
-    16,  11,  10,  16,  24,  40,  51,  61,
-    12,  12,  14,  19,  26,  58,  60,  55,
-    14,  13,  16,  24,  40,  57,  69,  56,
-    14,  17,  22,  29,  51,  87,  80,  62,
-    18,  22,  37,  56,  68, 109, 103,  77,
-    24,  35,  55,  64,  81, 104, 113,  92,
-    49,  64,  78,  87, 103, 121, 120, 101,
-    72,  92,  95,  98, 112, 100, 103,  99
-};
-static const unsigned char std_chrominance_quant_tbl[64] = {
-    17,  18,  24,  47,  99,  99,  99,  99,
-    18,  21,  26,  66,  99,  99,  99,  99,
-    24,  26,  56,  99,  99,  99,  99,  99,
-    47,  66,  99,  99,  99,  99,  99,  99,
-    99,  99,  99,  99,  99,  99,  99,  99,
-    99,  99,  99,  99,  99,  99,  99,  99,
-    99,  99,  99,  99,  99,  99,  99,  99,
-    99,  99,  99,  99,  99,  99,  99,  99
-};
-#endif
 
-/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
-/* IMPORTANT: these are only valid for 8-bit data precision! */
-static const UINT8 bits_dc_luminance[17] =
-{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
-static const UINT8 val_dc_luminance[] =
-{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
-
-static const UINT8 bits_dc_chrominance[17] =
-{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
-static const UINT8 val_dc_chrominance[] =
-{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
-
-static const UINT8 bits_ac_luminance[17] =
-{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
-static const UINT8 val_ac_luminance[] =
-{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-  0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-  0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-  0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-  0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-  0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-  0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-  0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-  0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-  0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-  0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-  0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-  0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-  0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-  0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-  0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-  0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-  0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-  0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-  0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-  0xf9, 0xfa 
-};
-
-static const UINT8 bits_ac_chrominance[17] =
-{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
-
-static const UINT8 val_ac_chrominance[] =
-{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
-  0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-  0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-  0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-  0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
-  0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
-  0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-  0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
-  0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-  0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-  0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-  0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-  0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
-  0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-  0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
-  0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
-  0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-  0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
-  0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-  0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-  0xf9, 0xfa 
-};
+//#define DEBUG
+#include <assert.h>
 
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "mjpeg.h"
+#include "mjpegenc.h"
 
-/* isn't this function nicer than the one in the libjpeg ? */
-static void build_huffman_codes(UINT8 *huff_size, UINT16 *huff_code,
-                                const UINT8 *bits_table, const UINT8 *val_table)
-{
-    int i, j, k,nb, code, sym;
+/* use two quantizer tables (one for luminance and one for chrominance) */
+/* not yet working */
+#undef TWOMATRIXES
 
-    code = 0;
-    k = 0;
-    for(i=1;i<=16;i++) {
-        nb = bits_table[i];
-        for(j=0;j<nb;j++) {
-            sym = val_table[k++];
-            huff_size[sym] = i;
-            huff_code[sym] = code;
-            code++;
-        }
-        code <<= 1;
-    }
-}
 
-int mjpeg_init(MpegEncContext *s)
+av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
 {
     MJpegContext *m;
-    
-    m = malloc(sizeof(MJpegContext));
+
+    m = av_malloc(sizeof(MJpegContext));
     if (!m)
         return -1;
 
+    s->min_qcoeff=-1023;
+    s->max_qcoeff= 1023;
+
     /* build all the huffman tables */
-    build_huffman_codes(m->huff_size_dc_luminance,
-                        m->huff_code_dc_luminance,
-                        bits_dc_luminance,
-                        val_dc_luminance);
-    build_huffman_codes(m->huff_size_dc_chrominance,
-                        m->huff_code_dc_chrominance,
-                        bits_dc_chrominance,
-                        val_dc_chrominance);
-    build_huffman_codes(m->huff_size_ac_luminance,
-                        m->huff_code_ac_luminance,
-                        bits_ac_luminance,
-                        val_ac_luminance);
-    build_huffman_codes(m->huff_size_ac_chrominance,
-                        m->huff_code_ac_chrominance,
-                        bits_ac_chrominance,
-                        val_ac_chrominance);
-    
+    ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance,
+                                 m->huff_code_dc_luminance,
+                                 avpriv_mjpeg_bits_dc_luminance,
+                                 avpriv_mjpeg_val_dc);
+    ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance,
+                                 m->huff_code_dc_chrominance,
+                                 avpriv_mjpeg_bits_dc_chrominance,
+                                 avpriv_mjpeg_val_dc);
+    ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance,
+                                 m->huff_code_ac_luminance,
+                                 avpriv_mjpeg_bits_ac_luminance,
+                                 avpriv_mjpeg_val_ac_luminance);
+    ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance,
+                                 m->huff_code_ac_chrominance,
+                                 avpriv_mjpeg_bits_ac_chrominance,
+                                 avpriv_mjpeg_val_ac_chrominance);
+
     s->mjpeg_ctx = m;
     return 0;
 }
 
-void mjpeg_close(MpegEncContext *s)
-{
-    free(s->mjpeg_ctx);
-}
-
-static inline void put_marker(PutBitContext *p, int code)
+void ff_mjpeg_encode_close(MpegEncContext *s)
 {
-    put_bits(p, 8, 0xff);
-    put_bits(p, 8, code);
+    av_free(s->mjpeg_ctx);
 }
 
 /* table_class: 0 = DC coef, 1 = AC coefs */
 static int put_huffman_table(MpegEncContext *s, int table_class, int table_id,
-                             const UINT8 *bits_table, const UINT8 *value_table)
+                             const uint8_t *bits_table, const uint8_t *value_table)
 {
     PutBitContext *p = &s->pb;
     int n, i;
@@ -220,127 +107,266 @@ 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;
-    UINT8 *ptr;
+    int i, j, size;
+    uint8_t *ptr;
 
     /* quant matrixes */
     put_marker(p, DQT);
+#ifdef TWOMATRIXES
+    put_bits(p, 16, 2 + 2 * (1 + 64));
+#else
     put_bits(p, 16, 2 + 1 * (1 + 64));
+#endif
     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 = s->intra_scantable.permutated[i];
+        put_bits(p, 8, s->intra_matrix[j]);
     }
-#if 0
+#ifdef TWOMATRIXES
     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 = s->intra_scantable.permutated[i];
+        put_bits(p, 8, s->chroma_intra_matrix[j]);
     }
 #endif
 
     /* huffman table */
     put_marker(p, DHT);
     flush_put_bits(p);
-    ptr = p->buf_ptr;
+    ptr = put_bits_ptr(p);
     put_bits(p, 16, 0); /* patched later */
     size = 2;
-    size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance);
-    size += put_huffman_table(s, 0, 1, bits_dc_chrominance, val_dc_chrominance);
-    
-    size += put_huffman_table(s, 1, 0, bits_ac_luminance, val_ac_luminance);
-    size += put_huffman_table(s, 1, 1, bits_ac_chrominance, val_ac_chrominance);
-    ptr[0] = size >> 8;
-    ptr[1] = size;
+    size += put_huffman_table(s, 0, 0, avpriv_mjpeg_bits_dc_luminance,
+                              avpriv_mjpeg_val_dc);
+    size += put_huffman_table(s, 0, 1, avpriv_mjpeg_bits_dc_chrominance,
+                              avpriv_mjpeg_val_dc);
+
+    size += put_huffman_table(s, 1, 0, avpriv_mjpeg_bits_ac_luminance,
+                              avpriv_mjpeg_val_ac_luminance);
+    size += put_huffman_table(s, 1, 1, avpriv_mjpeg_bits_ac_chrominance,
+                              avpriv_mjpeg_val_ac_chrominance);
+    AV_WB16(ptr, size);
 }
 
-void mjpeg_picture_header(MpegEncContext *s)
+static void jpeg_put_comments(MpegEncContext *s)
 {
+    PutBitContext *p = &s->pb;
+    int size;
+    uint8_t *ptr;
+
+    if (s->aspect_ratio_info /* && !lossless */)
+    {
+    /* JFIF header */
+    put_marker(p, APP0);
+    put_bits(p, 16, 16);
+    ff_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 */
+    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 */
+    }
+
+    /* comment */
+    if(!(s->flags & CODEC_FLAG_BITEXACT)){
+        put_marker(p, COM);
+        flush_put_bits(p);
+        ptr = put_bits_ptr(p);
+        put_bits(p, 16, 0); /* patched later */
+        ff_put_string(p, LIBAVCODEC_IDENT, 1);
+        size = strlen(LIBAVCODEC_IDENT)+3;
+        AV_WB16(ptr, 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 = put_bits_ptr(p);
+        put_bits(p, 16, 0); /* patched later */
+        ff_put_string(p, "CS=ITU601", 1);
+        size = strlen("CS=ITU601")+3;
+        AV_WB16(ptr, size);
+    }
+}
+
+void ff_mjpeg_encode_picture_header(MpegEncContext *s)
+{
+    const int lossless= s->avctx->codec_id != AV_CODEC_ID_MJPEG;
+
     put_marker(&s->pb, SOI);
 
+    jpeg_put_comments(s);
+
     jpeg_table_header(s);
 
-    put_marker(&s->pb, SOF0);
+    switch(s->avctx->codec_id){
+    case AV_CODEC_ID_MJPEG:  put_marker(&s->pb, SOF0 ); break;
+    case AV_CODEC_ID_LJPEG:  put_marker(&s->pb, SOF3 ); break;
+    default: assert(0);
+    }
 
     put_bits(&s->pb, 16, 17);
-    put_bits(&s->pb, 8, 8); /* 8 bits/component */
+    if(lossless && s->avctx->pix_fmt == PIX_FMT_BGRA)
+        put_bits(&s->pb, 8, 9); /* 9 bits/component RCT */
+    else
+        put_bits(&s->pb, 8, 8); /* 8 bits/component */
     put_bits(&s->pb, 16, s->height);
     put_bits(&s->pb, 16, s->width);
     put_bits(&s->pb, 8, 3); /* 3 components */
-    
+
     /* Y component */
     put_bits(&s->pb, 8, 1); /* component number */
-    put_bits(&s->pb, 4, 2); /* H factor */
-    put_bits(&s->pb, 4, 2); /* V factor */
+    put_bits(&s->pb, 4, s->mjpeg_hsample[0]); /* H factor */
+    put_bits(&s->pb, 4, s->mjpeg_vsample[0]); /* V factor */
     put_bits(&s->pb, 8, 0); /* select matrix */
-    
+
     /* Cb component */
     put_bits(&s->pb, 8, 2); /* component number */
-    put_bits(&s->pb, 4, 1); /* H factor */
-    put_bits(&s->pb, 4, 1); /* V factor */
+    put_bits(&s->pb, 4, s->mjpeg_hsample[1]); /* H factor */
+    put_bits(&s->pb, 4, s->mjpeg_vsample[1]); /* V factor */
+#ifdef TWOMATRIXES
+    put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
+#else
     put_bits(&s->pb, 8, 0); /* select matrix */
+#endif
 
     /* Cr component */
     put_bits(&s->pb, 8, 3); /* component number */
-    put_bits(&s->pb, 4, 1); /* H factor */
-    put_bits(&s->pb, 4, 1); /* V factor */
+    put_bits(&s->pb, 4, s->mjpeg_hsample[2]); /* H factor */
+    put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */
+#ifdef TWOMATRIXES
+    put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
+#else
     put_bits(&s->pb, 8, 0); /* select matrix */
+#endif
 
     /* scan header */
     put_marker(&s->pb, SOS);
     put_bits(&s->pb, 16, 12); /* length */
     put_bits(&s->pb, 8, 3); /* 3 components */
-    
+
     /* Y component */
     put_bits(&s->pb, 8, 1); /* index */
     put_bits(&s->pb, 4, 0); /* DC huffman table index */
     put_bits(&s->pb, 4, 0); /* AC huffman table index */
-    
+
     /* Cb component */
     put_bits(&s->pb, 8, 2); /* index */
     put_bits(&s->pb, 4, 1); /* DC huffman table index */
-    put_bits(&s->pb, 4, 1); /* AC huffman table index */
-    
+    put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */
+
     /* Cr component */
     put_bits(&s->pb, 8, 3); /* index */
     put_bits(&s->pb, 4, 1); /* DC huffman table index */
-    put_bits(&s->pb, 4, 1); /* AC huffman table index */
+    put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */
+
+    put_bits(&s->pb, 8, lossless ? s->avctx->prediction_method+1 : 0); /* Ss (not used) */
+
+    switch(s->avctx->codec_id){
+    case AV_CODEC_ID_MJPEG:  put_bits(&s->pb, 8, 63); break; /* Se (not used) */
+    case AV_CODEC_ID_LJPEG:  put_bits(&s->pb, 8,  0); break; /* not used */
+    default: assert(0);
+    }
+
+    put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */
+}
+
+static void escape_FF(MpegEncContext *s, int start)
+{
+    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;
+
+    assert((size&7) == 0);
+    size >>= 3;
+
+    ff_count=0;
+    for(i=0; i<size && i<align; i++){
+        if(buf[i]==0xFF) ff_count++;
+    }
+    for(; i<size-15; i+=16){
+        int acc, v;
+
+        v= *(uint32_t*)(&buf[i]);
+        acc= (((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
+        v= *(uint32_t*)(&buf[i+4]);
+        acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
+        v= *(uint32_t*)(&buf[i+8]);
+        acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
+        v= *(uint32_t*)(&buf[i+12]);
+        acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010;
+
+        acc>>=4;
+        acc+= (acc>>16);
+        acc+= (acc>>8);
+        ff_count+= acc&0xFF;
+    }
+    for(; i<size; i++){
+        if(buf[i]==0xFF) ff_count++;
+    }
+
+    if(ff_count==0) return;
+
+    flush_put_bits(&s->pb);
+    skip_put_bytes(&s->pb, ff_count);
+
+    for(i=size-1; ff_count; i--){
+        int v= buf[i];
+
+        if(v==0xFF){
+//printf("%d %d\n", i, ff_count);
+            buf[i+ff_count]= 0;
+            ff_count--;
+        }
+
+        buf[i+ff_count]= v;
+    }
+}
 
-    put_bits(&s->pb, 8, 0); /* Ss (not used) */
-    put_bits(&s->pb, 8, 63); /* Se (not used) */
-    put_bits(&s->pb, 8, 0); /* (not used) */
+void ff_mjpeg_encode_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)
+void ff_mjpeg_encode_picture_trailer(MpegEncContext *s)
 {
-    jflush_put_bits(&s->pb);
+    ff_mjpeg_encode_stuffing(&s->pb);
+    flush_put_bits(&s->pb);
+
+    assert((s->header_bits&7)==0);
+
+    escape_FF(s, s->header_bits>>3);
+
     put_marker(&s->pb, EOI);
 }
 
-static inline void encode_dc(MpegEncContext *s, int val, 
-                             UINT8 *huff_size, UINT16 *huff_code)
+void ff_mjpeg_encode_dc(MpegEncContext *s, int val,
+                        uint8_t *huff_size, uint16_t *huff_code)
 {
     int mant, nbits;
 
     if (val == 0) {
-        jput_bits(&s->pb, huff_size[0], huff_code[0]);
+        put_bits(&s->pb, huff_size[0], huff_code[0]);
     } else {
         mant = val;
         if (val < 0) {
             val = -val;
             mant--;
         }
-        
-        /* compute the log (XXX: optimize) */
-        nbits = 0;
-        while (val != 0) {
-            val = val >> 1;
-            nbits++;
-        }
-            
-        jput_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
-        
-        jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+
+        nbits= av_log2_16bit(val) + 1;
+
+        put_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
+
+        put_sbits(&s->pb, nbits, mant);
     }
 }
 
@@ -349,36 +375,36 @@ static void encode_block(MpegEncContext *s, DCTELEM *block, int n)
     int mant, nbits, code, i, j;
     int component, dc, run, last_index, val;
     MJpegContext *m = s->mjpeg_ctx;
-    UINT8 *huff_size_ac;
-    UINT16 *huff_code_ac;
-    
+    uint8_t *huff_size_ac;
+    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) {
-        encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
+        ff_mjpeg_encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
         huff_size_ac = m->huff_size_ac_luminance;
         huff_code_ac = m->huff_code_ac_luminance;
     } else {
-        encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
+        ff_mjpeg_encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
         huff_size_ac = m->huff_size_ac_chrominance;
         huff_code_ac = m->huff_code_ac_chrominance;
     }
     s->last_dc[component] = dc;
-    
+
     /* AC coefs */
-    
+
     run = 0;
     last_index = s->block_last_index[n];
     for(i=1;i<=last_index;i++) {
-        j = zigzag_direct[i];
+        j = s->intra_scantable.permutated[i];
         val = block[j];
         if (val == 0) {
             run++;
         } else {
             while (run >= 16) {
-                jput_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
+                put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
                 run -= 16;
             }
             mant = val;
@@ -386,32 +412,49 @@ static void encode_block(MpegEncContext *s, DCTELEM *block, int n)
                 val = -val;
                 mant--;
             }
-            
-            /* compute the log (XXX: optimize) */
-            nbits = 0;
-            while (val != 0) {
-                val = val >> 1;
-                nbits++;
-            }
+
+            nbits= av_log2(val) + 1;
             code = (run << 4) | nbits;
 
-            jput_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
-        
-            jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+            put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
+
+            put_sbits(&s->pb, nbits, mant);
             run = 0;
         }
     }
 
     /* output EOB only if not already 64 values */
     if (last_index < 63 || run != 0)
-        jput_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
+        put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
 }
 
-void mjpeg_encode_mb(MpegEncContext *s, 
-                     DCTELEM block[6][64])
+void ff_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);
+    }
+
+    s->i_tex_bits += get_bits_diff(s);
 }
+
+AVCodec ff_mjpeg_encoder = {
+    .name           = "mjpeg",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_MJPEG,
+    .priv_data_size = sizeof(MpegEncContext),
+    .init           = ff_MPV_encode_init,
+    .encode2        = ff_MPV_encode_picture,
+    .close          = ff_MPV_encode_end,
+    .pix_fmts       = (const enum PixelFormat[]){
+        PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_NONE
+    },
+    .long_name      = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"),
+};