Skip to content
Snippets Groups Projects
mjpeg.c 75.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * MJPEG encoder and decoder
    
     * Copyright (c) 2000, 2001 Fabrice Bellard.
    
    Alex Beregszaszi's avatar
    Alex Beregszaszi committed
     * 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
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
    
     * This library 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
    
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    
     * Support for external huffman table, various fixes (AVID workaround),
    
     * aspecting, new decode_frame mechanism and apple mjpeg-b support
    
     *                                  by Alex Beregszaszi <alex@naxine.org>
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
    /**
     * @file mjpeg.c
     * MJPEG encoder and decoder.
     */
    
    Alex Beregszaszi's avatar
    Alex Beregszaszi committed
    //#define DEBUG
    
    #include <assert.h>
    
    
    #include "avcodec.h"
    #include "dsputil.h"
    #include "mpegvideo.h"
    
    
    /* use two quantizer tables (one for luminance and one for chrominance) */
    
    /* not yet working */
    #undef TWOMATRIXES
    
    
    typedef struct MJpegContext {
    
        uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chrom, for easier addressing
    
        uint16_t huff_code_dc_luminance[12];
        uint8_t huff_size_dc_chrominance[12];
        uint16_t huff_code_dc_chrominance[12];
    
        uint8_t huff_size_ac_luminance[256];
        uint16_t huff_code_ac_luminance[256];
        uint8_t huff_size_ac_chrominance[256];
        uint16_t huff_code_ac_chrominance[256];
    
    /* JPEG marker codes */
    typedef enum {
        /* start of frame */
    
        SOF0  = 0xc0,       /* baseline */
        SOF1  = 0xc1,       /* extended sequential, huffman */
        SOF2  = 0xc2,       /* progressive, huffman */
        SOF3  = 0xc3,       /* lossless, huffman */
    
        SOF5  = 0xc5,       /* differential sequential, huffman */
        SOF6  = 0xc6,       /* differential progressive, huffman */
        SOF7  = 0xc7,       /* differential lossless, huffman */
        JPG   = 0xc8,       /* reserved for JPEG extension */
        SOF9  = 0xc9,       /* extended sequential, arithmetic */
        SOF10 = 0xca,       /* progressive, arithmetic */
        SOF11 = 0xcb,       /* lossless, arithmetic */
    
        SOF13 = 0xcd,       /* differential sequential, arithmetic */
        SOF14 = 0xce,       /* differential progressive, arithmetic */
        SOF15 = 0xcf,       /* differential lossless, arithmetic */
    
        DHT   = 0xc4,       /* define huffman tables */
    
        DAC   = 0xcc,       /* define arithmetic-coding conditioning */
    
    
        /* restart with modulo 8 count "m" */
        RST0  = 0xd0,
        RST1  = 0xd1,
        RST2  = 0xd2,
        RST3  = 0xd3,
        RST4  = 0xd4,
        RST5  = 0xd5,
        RST6  = 0xd6,
        RST7  = 0xd7,
    
    
        SOI   = 0xd8,       /* start of image */
        EOI   = 0xd9,       /* end of image */
        SOS   = 0xda,       /* start of scan */
        DQT   = 0xdb,       /* define quantization tables */
        DNL   = 0xdc,       /* define number of lines */
        DRI   = 0xdd,       /* define restart interval */
        DHP   = 0xde,       /* define hierarchical progression */
        EXP   = 0xdf,       /* expand reference components */
    
    
        APP0  = 0xe0,
        APP1  = 0xe1,
        APP2  = 0xe2,
        APP3  = 0xe3,
        APP4  = 0xe4,
        APP5  = 0xe5,
        APP6  = 0xe6,
        APP7  = 0xe7,
        APP8  = 0xe8,
        APP9  = 0xe9,
        APP10 = 0xea,
        APP11 = 0xeb,
        APP12 = 0xec,
        APP13 = 0xed,
        APP14 = 0xee,
        APP15 = 0xef,
    
        JPG0  = 0xf0,
        JPG1  = 0xf1,
        JPG2  = 0xf2,
        JPG3  = 0xf3,
        JPG4  = 0xf4,
        JPG5  = 0xf5,
        JPG6  = 0xf6,
    
        SOF48 = 0xf7,       ///< JPEG-LS
        LSE   = 0xf8,       ///< JPEG-LS extension parameters
    
        JPG9  = 0xf9,
        JPG10 = 0xfa,
        JPG11 = 0xfb,
        JPG12 = 0xfc,
        JPG13 = 0xfd,
    
    
        COM   = 0xfe,       /* comment */
    
        TEM   = 0x01,       /* temporary private use for arithmetic coding */
    
    
    #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.
     */
    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_t 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_t val_dc_luminance[] =
    
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
    
    
    static const uint8_t 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_t val_dc_chrominance[] =
    
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
    
    
    static const uint8_t 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_t 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,
    
    static const uint8_t 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_t 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,
    
    };
    
    /* isn't this function nicer than the one in the libjpeg ? */
    
    static void build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
                                    const uint8_t *bits_table, const uint8_t *val_table)
    
    {
        int i, j, k,nb, code, sym;
    
        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)
    {
        MJpegContext *m;
    
        m = av_malloc(sizeof(MJpegContext));
    
        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);
    
        s->mjpeg_ctx = m;
        return 0;
    }
    
    void mjpeg_close(MpegEncContext *s)
    {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #define PREDICT(ret, topleft, top, left, predictor)\
        switch(predictor){\
            case 1: ret= left; break;\
            case 2: ret= top; break;\
            case 3: ret= topleft; break;\
            case 4: ret= left   +   top - topleft; break;\
            case 5: ret= left   + ((top - topleft)>>1); break;\
            case 6: ret= top + ((left   - topleft)>>1); break;\
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            default:\
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            case 7: ret= (left + top)>>1; break;\
    
    #ifdef CONFIG_ENCODERS
    
    static inline void put_marker(PutBitContext *p, int code)
    {
        put_bits(p, 8, 0xff);
        put_bits(p, 8, code);
    }
    
    /* table_class: 0 = DC coef, 1 = AC coefs */
    static int put_huffman_table(MpegEncContext *s, int table_class, int table_id,
    
                                 const uint8_t *bits_table, const uint8_t *value_table)
    
    {
        PutBitContext *p = &s->pb;
        int n, i;
    
        put_bits(p, 4, table_class);
        put_bits(p, 4, table_id);
    
        n = 0;
        for(i=1;i<=16;i++) {
            n += bits_table[i];
            put_bits(p, 8, bits_table[i]);
        }
    
        for(i=0;i<n;i++)
            put_bits(p, 8, value_table[i]);
    
        return n + 17;
    }
    
    static void jpeg_table_header(MpegEncContext *s)
    {
        PutBitContext *p = &s->pb;
    
        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));
    
        put_bits(p, 4, 0); /* 8 bit precision */
        put_bits(p, 4, 0); /* table 0 */
        for(i=0;i<64;i++) {
    
            j = s->intra_scantable.permutated[i];
    
            put_bits(p, 8, s->intra_matrix[j]);
    
        put_bits(p, 4, 0); /* 8 bit precision */
        put_bits(p, 4, 1); /* table 1 */
        for(i=0;i<64;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);
    
        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;
    }
    
    
    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 */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        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 */
    
        if(!(s->flags & CODEC_FLAG_BITEXACT)){
    
            put_marker(p, COM);
            flush_put_bits(p);
            ptr = pbBufPtr(p);
            put_bits(p, 16, 0); /* patched later */
    
            ff_put_string(p, LIBAVCODEC_IDENT, 1);
    
    Alex Beregszaszi's avatar
    Alex Beregszaszi committed
            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 */
    
            size = strlen("CS=ITU601")+3;
            ptr[0] = size >> 8;
            ptr[1] = size;
        }
    
    void mjpeg_picture_header(MpegEncContext *s)
    {
    
        const int lossless= s->avctx->codec_id != CODEC_ID_MJPEG;
        const int ls      = s->avctx->codec_id == CODEC_ID_JPEGLS;
    
        assert(!(ls && s->mjpeg_write_tables));
    
        jpeg_put_comments(s);
    
        if (s->mjpeg_write_tables) jpeg_table_header(s);
    
        switch(s->avctx->codec_id){
        case CODEC_ID_MJPEG:  put_marker(&s->pb, SOF0 ); break;
        case CODEC_ID_LJPEG:  put_marker(&s->pb, SOF3 ); break;
        case CODEC_ID_JPEGLS: put_marker(&s->pb, SOF48); break;
        default: assert(0);
        }
    
    
        put_bits(&s->pb, 16, 17);
    
        if(lossless && s->avctx->pix_fmt == PIX_FMT_RGBA32)
            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, 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, s->mjpeg_hsample[1]); /* H factor */
        put_bits(&s->pb, 4, s->mjpeg_vsample[1]); /* V factor */
    
        put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
    
        put_bits(&s->pb, 8, 0); /* select matrix */
    
    
        /* Cr component */
        put_bits(&s->pb, 8, 3); /* component number */
    
        put_bits(&s->pb, 4, s->mjpeg_hsample[2]); /* H factor */
        put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */
    
        put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */
    
        put_bits(&s->pb, 8, 0); /* select matrix */
    
    
        /* 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, 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, lossless ? 0 : 1); /* AC huffman table index */
    
        put_bits(&s->pb, 8, (lossless && !ls) ? s->avctx->prediction_method+1 : 0); /* Ss (not used) */
    
        switch(s->avctx->codec_id){
        case CODEC_ID_MJPEG:  put_bits(&s->pb, 8, 63); break; /* Se (not used) */
        case CODEC_ID_LJPEG:  put_bits(&s->pb, 8,  0); break; /* not used */
        case CODEC_ID_JPEGLS: put_bits(&s->pb, 8,  1); break; /* ILV = line interleaved */
        default: assert(0);
        }
    
    
        put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */
    
    
        //FIXME DC/AC entropy table selectors stuff in jpegls
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    static void escape_FF(MpegEncContext *s, int start)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    {
    
        int size= put_bits_count(&s->pb) - start*8;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int i, ff_count;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        uint8_t *buf= s->pb.buf + start;
    
    Falk Hüffner's avatar
    Falk Hüffner committed
        int align= (-(size_t)(buf))&3;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        assert((size&7) == 0);
        size >>= 3;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        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;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        /* skip put bits */
        for(i=0; i<ff_count-3; i+=4)
            put_bits(&s->pb, 32, 0);
        put_bits(&s->pb, (ff_count-i)*8, 0);
    
        flush_put_bits(&s->pb);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
        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;
        }
    }
    
    
    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)
    {
    
        ff_mjpeg_stuffing(&s->pb);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        flush_put_bits(&s->pb);
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        assert((s->header_bits&7)==0);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        escape_FF(s, s->header_bits>>3);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
    
    static inline void mjpeg_encode_dc(MpegEncContext *s, int val,
    
                                       uint8_t *huff_size, uint16_t *huff_code)
    
    {
        int mant, nbits;
    
        if (val == 0) {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            put_bits(&s->pb, huff_size[0], huff_code[0]);
    
        } else {
            mant = val;
            if (val < 0) {
                val = -val;
                mant--;
            }
    
            nbits= av_log2_16bit(val) + 1;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            put_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
    
        }
    }
    
    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_t *huff_size_ac;
        uint16_t *huff_code_ac;
    
        /* DC coef */
        component = (n <= 3 ? 0 : n - 4 + 1);
        dc = block[0]; /* overflow is impossible */
        val = dc - s->last_dc[component];
        if (n < 4) {
    
            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 {
    
            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;
    
        run = 0;
        last_index = s->block_last_index[n];
        for(i=1;i<=last_index;i++) {
    
            j = s->intra_scantable.permutated[i];
    
            val = block[j];
            if (val == 0) {
                run++;
            } else {
                while (run >= 16) {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                    put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
    
                    run -= 16;
                }
                mant = val;
                if (val < 0) {
                    val = -val;
                    mant--;
                }
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                nbits= av_log2(val) + 1;
    
                code = (run << 4) | nbits;
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
    
                run = 0;
            }
        }
    
        /* output EOB only if not already 64 values */
        if (last_index < 63 || run != 0)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
    
    void mjpeg_encode_mb(MpegEncContext *s,
    
                         DCTELEM block[6][64])
    {
        int i;
        for(i=0;i<6;i++) {
            encode_block(s, block[i], i);
        }
    }
    
    
    static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
        MpegEncContext * const s = avctx->priv_data;
        MJpegContext * const m = s->mjpeg_ctx;
        AVFrame *pict = data;
        const int width= s->width;
        const int height= s->height;
        AVFrame * const p= (AVFrame*)&s->current_picture;
        const int predictor= avctx->prediction_method+1;
    
    
        init_put_bits(&s->pb, buf, buf_size);
    
    
        *p = *pict;
        p->pict_type= FF_I_TYPE;
        p->key_frame= 1;
    
        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)[4]= (void *) s->rd_scratchpad;
    
            int left[3], top[3], topleft[3];
    
            for(i=0; i<3; i++){
                buffer[0][i]= 1 << (9 - 1);
            }
    
            for(y = 0; y < height; y++) {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                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];
                }
                for(x = 0; x < width; x++) {
                    buffer[x][1] = ptr[4*x+0] - ptr[4*x+1] + 0x100;
                    buffer[x][2] = ptr[4*x+2] - ptr[4*x+1] + 0x100;
                    buffer[x][0] = (ptr[4*x+0] + 2*ptr[4*x+1] + ptr[4*x+2])>>2;
    
                    for(i=0;i<3;i++) {
                        int pred, diff;
    
                        PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
    
                        topleft[i]= top[i];
                        top[i]= buffer[x+1][i];
    
                        left[i]= buffer[x][i];
    
                        diff= ((left[i] - pred + 0x100)&0x1FF) - 0x100;
    
                        if(i==0)
                            mjpeg_encode_dc(s, diff, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
                        else
                            mjpeg_encode_dc(s, diff, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
                    }
                }
            }
        }else{
            int mb_x, mb_y, i;
            const int mb_width  = (width  + s->mjpeg_hsample[0] - 1) / s->mjpeg_hsample[0];
            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++) {
                            uint8_t *ptr;
                            int x, y, h, v, linesize;
                            h = s->mjpeg_hsample[i];
                            v = s->mjpeg_vsample[i];
                            linesize= p->linesize[i];
    
                            for(y=0; y<v; y++){
                                for(x=0; x<h; x++){
                                    int pred;
    
                                    ptr = p->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
                                    if(y==0 && mb_y==0){
                                        if(x==0 && mb_x==0){
                                            pred= 128;
                                        }else{
                                            pred= ptr[-1];
                                        }
                                    }else{
                                        if(x==0 && mb_x==0){
                                            pred= ptr[-linesize];
                                        }else{
                                            PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
                                        }
                                    }
    
                                    if(i==0)
                                        mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
                                    else
                                        mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
                                }
                            }
                        }
                    }else{
                        for(i=0;i<3;i++) {
                            uint8_t *ptr;
                            int x, y, h, v, linesize;
                            h = s->mjpeg_hsample[i];
                            v = s->mjpeg_vsample[i];
                            linesize= p->linesize[i];
    
                            for(y=0; y<v; y++){
                                for(x=0; x<h; x++){
                                    int pred;
    
                                    ptr = p->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
    
    //printf("%d %d %d %d %8X\n", mb_x, mb_y, x, y, ptr);
    
                                    PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
    
                                    if(i==0)
                                        mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
                                    else
                                        mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
                                }
                            }
                        }
                    }
                }
            }
        }
    
        emms_c();
    
        mjpeg_picture_trailer(s);
        s->picture_number++;
    
        flush_put_bits(&s->pb);
        return pbBufPtr(&s->pb) - s->pb.buf;
    
    //    return (put_bits_count(&f->pb)+7)/8;
    
    #endif //CONFIG_ENCODERS
    
    /******************************************/
    /* decoding */
    
    #define MAX_COMPONENTS 4
    
    typedef struct MJpegDecodeContext {
    
        int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
    
    
        int start_code; /* current start code */
        int buffer_size;
    
        uint8_t *buffer;
    
        int16_t quant_matrixes[4][64];
    
        int qscale[4];      ///< quantizer scale calculated from quant_matrixes
    
        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 */
    
        int lossless;
    
        int rct;            /* standard rct */
        int pegasus_rct;    /* pegasus reversible colorspace transform */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int bits;           /* bits per component */
    
        int maxval;
        int near;         ///< near lossless bound (si 0 for lossless)
        int t1,t2,t3;
        int reset;        ///< context halfing intervall ?rename
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int mb_width, mb_height;
    
        int nb_components;
        int component_id[MAX_COMPONENTS];
    
        int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */
        int v_count[MAX_COMPONENTS];
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        int comp_index[MAX_COMPONENTS];
        int dc_index[MAX_COMPONENTS];
        int ac_index[MAX_COMPONENTS];
        int nb_blocks[MAX_COMPONENTS];
        int h_scount[MAX_COMPONENTS];
        int v_scount[MAX_COMPONENTS];
    
        int h_max, v_max; /* maximum h and v counts */
        int quant_index[4];   /* quant table index for each component */
        int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        AVFrame picture; /* picture structure */
        int linesize[MAX_COMPONENTS];                   ///< linesize << interlaced
    
        DECLARE_ALIGNED_8(DCTELEM, block[64]);
    
        void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
    
        int restart_interval;
        int restart_count;
    
        int cs_itu601;
    
    
        int cur_scan; /* current scan, used by JPEG-LS */
    
    #include "jpeg_ls.c" //FIXME make jpeg-ls more independant
    
    
    static int mjpeg_decode_dht(MJpegDecodeContext *s);
    
    Juanjo's avatar
    Juanjo committed
    
    
    static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table,
    
                          int nb_codes, int use_static, int is_ac)
    
        uint8_t huff_size[256+16];
        uint16_t huff_code[256+16];
    
        assert(nb_codes <= 256);
    
    
        memset(huff_size, 0, sizeof(huff_size));
        build_huffman_codes(huff_size, huff_code, bits_table, val_table);
    
        if(is_ac){
            memmove(huff_size+16, huff_size, sizeof(uint8_t)*nb_codes);
            memmove(huff_code+16, huff_code, sizeof(uint16_t)*nb_codes);
            memset(huff_size, 0, sizeof(uint8_t)*16);
            memset(huff_code, 0, sizeof(uint16_t)*16);
            nb_codes += 16;
        }
    
    
        return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);
    
    static int mjpeg_decode_init(AVCodecContext *avctx)
    {
        MJpegDecodeContext *s = avctx->priv_data;
    
        memset(s, 0, sizeof(MJpegDecodeContext));
    
        /* ugly way to get the idct & scantable FIXME */
    
        memset(&s2, 0, sizeof(MpegEncContext));
        s2.avctx= avctx;
    //    s2->out_format = FMT_MJPEG;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        dsputil_init(&s2.dsp, avctx);
        DCT_common_init(&s2);
    
    
        s->scantable= s2.intra_scantable;
    
        s->idct_put= s2.dsp.idct_put;
    
        s->mpeg_enc_ctx_allocated = 0;
    
        s->first_picture = 1;
    
        s->org_height = avctx->coded_height;
    
        build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12, 0, 0);
        build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12, 0, 0);
        build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251, 0, 1);
        build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251, 0, 1);
    
            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 */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
    /**
     * 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;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        vop_found= pc->frame_start_found;
        state= pc->state;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        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;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                    return i-1;
                }
            }
        }
        pc->frame_start_found= vop_found;
        pc->state= state;
        return END_NOT_FOUND;
    }