Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 23 Feb 2012 01:33:21 +0000 (02:33 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 23 Feb 2012 03:31:55 +0000 (04:31 +0100)
* qatar/master:
  dxva2: don't check for DXVA_PictureParameters->wDecodedPictureIndex
  img2: split muxer and demuxer into separate files
  rm: prevent infinite loops for index parsing.
  aac: fix infinite loop on end-of-frame with sequence of 1-bits.
  mov: Add more HDV and XDCAM FourCCs.
  lavf: don't set AVCodecContext.has_b_frames in compute_pkt_fields().
  rmdec: when using INT4 deinterleaving, error out if sub_packet_h <= 1.
  cdxl: correctly synchronize video timestamps to audio
  mlpdec_parser: fix a few channel layouts.
  Add channel names to channel_names[] array for channels added in b2890f5
  movenc: Buffer the mdat for the initial moov fragment, too
  flvdec: Ignore the index if the ignidx flag is set
  flvdec: Fix indentation
  movdec: Don't parse all fragments if ignidx is set
  movdec: Restart parsing root-level atoms at the right spot
  prores: use natural integer type for the codebook index
  mov: Add support for MPEG2 HDV 720p24 (hdv4)
  swscale: K&R formatting cosmetics (part I)
  swscale: variable declaration and placement cosmetics

Conflicts:
configure
libavcodec/aacdec.c
libavcodec/mlp_parser.c
libavformat/flvdec.c
libavformat/img2.c
libavformat/isom.h
libavformat/mov.c
libavformat/movenc.c
libswscale/rgb2rgb.c
libswscale/rgb2rgb_template.c
libswscale/yuv2rgb.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
20 files changed:
1  2 
libavcodec/aacdec.c
libavcodec/mlp_parser.c
libavcodec/proresdec_lgpl.c
libavcodec/proresenc_kostya.c
libavformat/Makefile
libavformat/flvdec.c
libavformat/img2.c
libavformat/img2dec.c
libavformat/img2enc.c
libavformat/isom.c
libavformat/isom.h
libavformat/mov.c
libavformat/movenc.c
libavformat/movenc.h
libavformat/rmdec.c
libavutil/audioconvert.c
libswscale/options.c
libswscale/rgb2rgb.c
libswscale/rgb2rgb_template.c
libswscale/yuv2rgb.c

Simple merge
@@@ -82,9 -82,9 +82,9 @@@ static const uint64_t thd_layout[13] = 
      AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRc
      AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT,                       // LRrs
      AV_CH_BACK_CENTER,                                      // Cs
 -    AV_CH_TOP_BACK_CENTER,                                  // Ts
 -    AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT,                       // LRsd
 +    AV_CH_TOP_CENTER,                                       // Ts
 +    AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT,                       // LRsd - TODO: Surround Direct
-     AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRw  - TODO: Wide
+     AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT,                       // LRw
      AV_CH_TOP_FRONT_CENTER,                                 // Cvh
      AV_CH_LOW_FREQUENCY                                     // LFE2
  };
@@@ -107,9 -107,10 +107,10 @@@ static int truehd_channels(int chanmap
      return channels;
  }
  
 -static uint64_t truehd_layout(int chanmap)
 +uint64_t ff_truehd_layout(int chanmap)
  {
-     int layout = 0, i;
+     int i;
+     uint64_t layout = 0;
  
      for (i = 0; i < 13; i++)
          layout |= thd_layout[i] * ((chanmap >> i) & 1);
index 1070193,0000000..882503a
mode 100644,000000..100644
--- /dev/null
@@@ -1,654 -1,0 +1,654 @@@
- static inline int decode_vlc_codeword(GetBitContext *gb, uint8_t codebook)
 +/*
 + * Apple ProRes compatible decoder
 + *
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + *
 + * 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
 + * Lesser General Public License for more details.
 + *
 + * 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
 + */
 +
 +/**
 + * @file
 + * This is a decoder for Apple ProRes 422 SD/HQ/LT/Proxy and ProRes 4444.
 + * It is used for storing and editing high definition video data in Apple's Final Cut Pro.
 + *
 + * @see http://wiki.multimedia.cx/index.php?title=Apple_ProRes
 + */
 +
 +#define LONG_BITSTREAM_READER // some ProRes vlc codes require up to 28 bits to be read at once
 +
 +#include <stdint.h>
 +
 +#include "libavutil/intmath.h"
 +#include "avcodec.h"
 +#include "proresdata.h"
 +#include "proresdsp.h"
 +#include "get_bits.h"
 +
 +typedef struct {
 +    const uint8_t *index;            ///< pointers to the data of this slice
 +    int slice_num;
 +    int x_pos, y_pos;
 +    int slice_width;
 +    int prev_slice_sf;               ///< scalefactor of the previous decoded slice
 +    DECLARE_ALIGNED(16, DCTELEM, blocks)[8 * 4 * 64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64];
 +} ProresThreadData;
 +
 +typedef struct {
 +    ProresDSPContext dsp;
 +    AVFrame    picture;
 +    ScanTable  scantable;
 +    int        scantable_type;           ///< -1 = uninitialized, 0 = progressive, 1/2 = interlaced
 +
 +    int        frame_type;               ///< 0 = progressive, 1 = top-field first, 2 = bottom-field first
 +    int        pic_format;               ///< 2 = 422, 3 = 444
 +    uint8_t    qmat_luma[64];            ///< dequantization matrix for luma
 +    uint8_t    qmat_chroma[64];          ///< dequantization matrix for chroma
 +    int        qmat_changed;             ///< 1 - global quantization matrices changed
 +    int        total_slices;            ///< total number of slices in a picture
 +    ProresThreadData *slice_data;
 +    int        pic_num;
 +    int        chroma_factor;
 +    int        mb_chroma_factor;
 +    int        num_chroma_blocks;       ///< number of chrominance blocks in a macroblock
 +    int        num_x_slices;
 +    int        num_y_slices;
 +    int        slice_width_factor;
 +    int        slice_height_factor;
 +    int        num_x_mbs;
 +    int        num_y_mbs;
 +    int        alpha_info;
 +} ProresContext;
 +
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    ctx->total_slices     = 0;
 +    ctx->slice_data       = NULL;
 +
 +    avctx->bits_per_raw_sample = PRORES_BITS_PER_SAMPLE;
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +
 +    avctx->coded_frame = &ctx->picture;
 +    avcodec_get_frame_defaults(&ctx->picture);
 +    ctx->picture.type      = AV_PICTURE_TYPE_I;
 +    ctx->picture.key_frame = 1;
 +
 +    ctx->scantable_type = -1;   // set scantable type to uninitialized
 +    memset(ctx->qmat_luma, 4, 64);
 +    memset(ctx->qmat_chroma, 4, 64);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, version, width, height, flags;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "frame data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    if (version >= 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported header version: %d\n", version);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "picture dimension changed: old: %d x %d, new: %d x %d\n",
 +               avctx->width, avctx->height, width, height);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +    if (ctx->frame_type > 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported frame type: %d\n", ctx->frame_type);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->chroma_factor     = (buf[12] >> 6) & 3;
 +    ctx->mb_chroma_factor  = ctx->chroma_factor + 2;
 +    ctx->num_chroma_blocks = (1 << ctx->chroma_factor) >> 1;
 +    switch (ctx->chroma_factor) {
 +    case 2:
 +        avctx->pix_fmt = PIX_FMT_YUV422P10;
 +        break;
 +    case 3:
 +        avctx->pix_fmt = PIX_FMT_YUV444P10;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported picture format: %d\n", ctx->pic_format);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->scantable_type != ctx->frame_type) {
 +        if (!ctx->frame_type)
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_progressive_scan);
 +        else
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_interlaced_scan);
 +        ctx->scantable_type = ctx->frame_type;
 +    }
 +
 +    if (ctx->frame_type) {      /* if interlaced */
 +        ctx->picture.interlaced_frame = 1;
 +        ctx->picture.top_field_first  = ctx->frame_type & 1;
 +    }
 +
 +    ctx->alpha_info = buf[17] & 0xf;
 +    if (ctx->alpha_info)
 +        av_log_missing_feature(avctx, "alpha channel", 0);
 +
 +    ctx->qmat_changed = 0;
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    if (flags & 2) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        if (memcmp(ctx->qmat_luma, ptr, 64)) {
 +            memcpy(ctx->qmat_luma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    if (flags & 1) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return -1;
 +        }
 +        if (memcmp(ctx->qmat_chroma, ptr, 64)) {
 +            memcpy(ctx->qmat_chroma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    return hdr_size;
 +}
 +
 +
 +static int decode_picture_header(ProresContext *ctx, const uint8_t *buf,
 +                                 const int data_size, AVCodecContext *avctx)
 +{
 +    int   i, hdr_size, pic_data_size, num_slices;
 +    int   slice_width_factor, slice_height_factor;
 +    int   remainder, num_x_slices;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = data_size > 0 ? buf[0] >> 3 : 0;
 +    if (hdr_size < 8 || hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture header too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    slice_width_factor  = buf[7] >> 4;
 +    slice_height_factor = buf[7] & 0xF;
 +    if (slice_width_factor > 3 || slice_height_factor) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported slice dimension: %d x %d\n",
 +               1 << slice_width_factor, 1 << slice_height_factor);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->slice_width_factor  = slice_width_factor;
 +    ctx->slice_height_factor = slice_height_factor;
 +
 +    ctx->num_x_mbs = (avctx->width + 15) >> 4;
 +    ctx->num_y_mbs = (avctx->height +
 +                      (1 << (4 + ctx->picture.interlaced_frame)) - 1) >>
 +                     (4 + ctx->picture.interlaced_frame);
 +
 +    remainder    = ctx->num_x_mbs & ((1 << slice_width_factor) - 1);
 +    num_x_slices = (ctx->num_x_mbs >> slice_width_factor) + (remainder & 1) +
 +                   ((remainder >> 1) & 1) + ((remainder >> 2) & 1);
 +
 +    num_slices = num_x_slices * ctx->num_y_mbs;
 +    if (num_slices != AV_RB16(buf + 5)) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid number of slices\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->total_slices != num_slices) {
 +        av_freep(&ctx->slice_data);
 +        ctx->slice_data = av_malloc((num_slices + 1) * sizeof(ctx->slice_data[0]));
 +        if (!ctx->slice_data)
 +            return AVERROR(ENOMEM);
 +        ctx->total_slices = num_slices;
 +    }
 +
 +    if (hdr_size + num_slices * 2 > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "slice table too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice table allowing quick access to the slice data */
 +    index_ptr = buf + hdr_size;
 +    data_ptr = index_ptr + num_slices * 2;
 +
 +    for (i = 0; i < num_slices; i++) {
 +        ctx->slice_data[i].index = data_ptr;
 +        ctx->slice_data[i].prev_slice_sf = 0;
 +        data_ptr += AV_RB16(index_ptr + i * 2);
 +    }
 +    ctx->slice_data[i].index = data_ptr;
 +    ctx->slice_data[i].prev_slice_sf = 0;
 +
 +    if (data_ptr > buf + data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "out of slice data\n");
 +        return -1;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +
 +/**
 + * Read an unsigned rice/exp golomb codeword.
 + */
++static inline int decode_vlc_codeword(GetBitContext *gb, unsigned codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits;
 +    unsigned int buf, code;
 +    int log, prefix_len, len;
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);
 +    buf = GET_CACHE(re, gb);
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  = codebook >> 5;        /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    log = 31 - av_log2(buf); /* count prefix bits (zeroes) */
 +
 +    if (log < switch_bits) { /* ok, we got a rice code */
 +        if (!rice_order) {
 +            /* shortcut for faster decoding of rice codes without remainder */
 +            code = log;
 +            LAST_SKIP_BITS(re, gb, log + 1);
 +        } else {
 +            prefix_len = log + 1;
 +            code = (log << rice_order) + NEG_USR32(buf << prefix_len, rice_order);
 +            LAST_SKIP_BITS(re, gb, prefix_len + rice_order);
 +        }
 +    } else { /* otherwise we got a exp golomb code */
 +        len  = (log << 1) - switch_bits + exp_order + 1;
 +        code = NEG_USR32(buf, len) - (1 << exp_order) + (switch_bits << rice_order);
 +        LAST_SKIP_BITS(re, gb, len);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +
 +    return code;
 +}
 +
 +#define LSB2SIGN(x) (-((x) & 1))
 +#define TOSIGNED(x) (((x) >> 1) ^ LSB2SIGN(x))
 +
 +/**
 + * Decode DC coefficients for all blocks in a slice.
 + */
 +static inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,
 +                                    int nblocks)
 +{
 +    DCTELEM prev_dc;
 +    int     i, sign;
 +    int16_t delta;
 +    unsigned int code;
 +
 +    code   = decode_vlc_codeword(gb, FIRST_DC_CB);
 +    out[0] = prev_dc = TOSIGNED(code);
 +
 +    out   += 64; /* move to the DC coeff of the next block */
 +    delta  = 3;
 +
 +    for (i = 1; i < nblocks; i++, out += 64) {
 +        code = decode_vlc_codeword(gb, ff_prores_dc_codebook[FFMIN(FFABS(delta), 3)]);
 +
 +        sign     = -(((delta >> 15) & 1) ^ (code & 1));
 +        delta    = (((code + 1) >> 1) ^ sign) - sign;
 +        prev_dc += delta;
 +        out[0]   = prev_dc;
 +    }
 +}
 +
 +
 +/**
 + * Decode AC coefficients for all blocks in a slice.
 + */
 +static inline void decode_ac_coeffs(GetBitContext *gb, DCTELEM *out,
 +                                    int blocks_per_slice,
 +                                    int plane_size_factor,
 +                                    const uint8_t *scan)
 +{
 +    int pos, block_mask, run, level, sign, run_cb_index, lev_cb_index;
 +    int max_coeffs, bits_left;
 +
 +    /* set initial prediction values */
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = blocks_per_slice - 1; pos < max_coeffs;) {
 +        run_cb_index = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +        lev_cb_index = ff_prores_lev_to_cb_index[FFMIN(level, 9)];
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        run = decode_vlc_codeword(gb, ff_prores_ac_codebook[run_cb_index]);
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        level = decode_vlc_codeword(gb, ff_prores_ac_codebook[lev_cb_index]) + 1;
 +
 +        pos += run + 1;
 +        if (pos >= max_coeffs)
 +            break;
 +
 +        sign = get_sbits(gb, 1);
 +        out[((pos & block_mask) << 6) + scan[pos >> plane_size_factor]] =
 +            (level ^ sign) - sign;
 +    }
 +}
 +
 +
 +/**
 + * Decode a slice plane (luma or chroma).
 + */
 +static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
 +                               const uint8_t *buf,
 +                               int data_size, uint16_t *out_ptr,
 +                               int linesize, int mbs_per_slice,
 +                               int blocks_per_mb, int plane_size_factor,
 +                               const int16_t *qmat)
 +{
 +    GetBitContext gb;
 +    DCTELEM *block_ptr;
 +    int mb_num, blocks_per_slice;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    memset(td->blocks, 0, 8 * 4 * 64 * sizeof(*td->blocks));
 +
 +    init_get_bits(&gb, buf, data_size << 3);
 +
 +    decode_dc_coeffs(&gb, td->blocks, blocks_per_slice);
 +
 +    decode_ac_coeffs(&gb, td->blocks, blocks_per_slice,
 +                     plane_size_factor, ctx->scantable.permutated);
 +
 +    /* inverse quantization, inverse transform and output */
 +    block_ptr = td->blocks;
 +
 +    for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
 +        ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
 +        block_ptr += 64;
 +        if (blocks_per_mb > 2) {
 +            ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +        }
 +        ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
 +        block_ptr += 64;
 +        if (blocks_per_mb > 2) {
 +            ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
 +            block_ptr += 64;
 +        }
 +    }
 +}
 +
 +
 +static int decode_slice(AVCodecContext *avctx, void *tdata)
 +{
 +    ProresThreadData *td = tdata;
 +    ProresContext *ctx = avctx->priv_data;
 +    int mb_x_pos  = td->x_pos;
 +    int mb_y_pos  = td->y_pos;
 +    int pic_num   = ctx->pic_num;
 +    int slice_num = td->slice_num;
 +    int mbs_per_slice = td->slice_width;
 +    const uint8_t *buf;
 +    uint8_t *y_data, *u_data, *v_data;
 +    AVFrame *pic = avctx->coded_frame;
 +    int i, sf, slice_width_factor;
 +    int slice_data_size, hdr_size, y_data_size, u_data_size, v_data_size;
 +    int y_linesize, u_linesize, v_linesize;
 +
 +    buf             = ctx->slice_data[slice_num].index;
 +    slice_data_size = ctx->slice_data[slice_num + 1].index - buf;
 +
 +    slice_width_factor = av_log2(mbs_per_slice);
 +
 +    y_data     = pic->data[0];
 +    u_data     = pic->data[1];
 +    v_data     = pic->data[2];
 +    y_linesize = pic->linesize[0];
 +    u_linesize = pic->linesize[1];
 +    v_linesize = pic->linesize[2];
 +
 +    if (pic->interlaced_frame) {
 +        if (!(pic_num ^ pic->top_field_first)) {
 +            y_data += y_linesize;
 +            u_data += u_linesize;
 +            v_data += v_linesize;
 +        }
 +        y_linesize <<= 1;
 +        u_linesize <<= 1;
 +        v_linesize <<= 1;
 +    }
 +
 +    if (slice_data_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "slice data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice header */
 +    hdr_size    = buf[0] >> 3;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = hdr_size > 7 ? AV_RB16(buf + 6) :
 +        slice_data_size - y_data_size - u_data_size - hdr_size;
 +
 +    if (hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size ||
 +        v_data_size < 0 || hdr_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid data size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    sf = av_clip(buf[1], 1, 224);
 +    sf = sf > 128 ? (sf - 96) << 2 : sf;
 +
 +    /* scale quantization matrixes according with slice's scale factor */
 +    /* TODO: this can be SIMD-optimized a lot */
 +    if (ctx->qmat_changed || sf != td->prev_slice_sf) {
 +        td->prev_slice_sf = sf;
 +        for (i = 0; i < 64; i++) {
 +            td->qmat_luma_scaled[ctx->dsp.idct_permutation[i]]   = ctx->qmat_luma[i]   * sf;
 +            td->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf;
 +        }
 +    }
 +
 +    /* decode luma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size, y_data_size,
 +                       (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize +
 +                                    (mb_x_pos << 5)), y_linesize,
 +                       mbs_per_slice, 4, slice_width_factor + 2,
 +                       td->qmat_luma_scaled);
 +
 +    /* decode U chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size,
 +                       (uint16_t*) (u_data + (mb_y_pos << 4) * u_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       u_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
 +                       td->qmat_chroma_scaled);
 +
 +    /* decode V chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size,
 +                       v_data_size,
 +                       (uint16_t*) (v_data + (mb_y_pos << 4) * v_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       v_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
 +                       td->qmat_chroma_scaled);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_picture(ProresContext *ctx, int pic_num,
 +                          AVCodecContext *avctx)
 +{
 +    int slice_num, slice_width, x_pos, y_pos;
 +
 +    slice_num = 0;
 +
 +    ctx->pic_num = pic_num;
 +    for (y_pos = 0; y_pos < ctx->num_y_mbs; y_pos++) {
 +        slice_width = 1 << ctx->slice_width_factor;
 +
 +        for (x_pos = 0; x_pos < ctx->num_x_mbs && slice_width;
 +             x_pos += slice_width) {
 +            while (ctx->num_x_mbs - x_pos < slice_width)
 +                slice_width >>= 1;
 +
 +            ctx->slice_data[slice_num].slice_num   = slice_num;
 +            ctx->slice_data[slice_num].x_pos       = x_pos;
 +            ctx->slice_data[slice_num].y_pos       = y_pos;
 +            ctx->slice_data[slice_num].slice_width = slice_width;
 +
 +            slice_num++;
 +        }
 +    }
 +
 +    return avctx->execute(avctx, decode_slice,
 +                          ctx->slice_data, NULL, slice_num,
 +                          sizeof(ctx->slice_data[0]));
 +}
 +
 +
 +#define MOVE_DATA_PTR(nbytes) buf += (nbytes); buf_size -= (nbytes)
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    AVFrame *picture   = avctx->coded_frame;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size       = avpkt->size;
 +    int frame_hdr_size, pic_num, pic_data_size;
 +
 +    /* check frame atom container */
 +    if (buf_size < 28 || buf_size < AV_RB32(buf) ||
 +        AV_RB32(buf + 4) != FRAME_ID) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    MOVE_DATA_PTR(8);
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return AVERROR_INVALIDDATA;
 +
 +    MOVE_DATA_PTR(frame_hdr_size);
 +
 +    if (picture->data[0])
 +        avctx->release_buffer(avctx, picture);
 +
 +    picture->reference = 0;
 +    if (avctx->get_buffer(avctx, picture) < 0)
 +        return -1;
 +
 +    for (pic_num = 0; ctx->picture.interlaced_frame - pic_num + 1; pic_num++) {
 +        pic_data_size = decode_picture_header(ctx, buf, buf_size, avctx);
 +        if (pic_data_size < 0)
 +            return AVERROR_INVALIDDATA;
 +
 +        if (decode_picture(ctx, pic_num, avctx))
 +            return -1;
 +
 +        MOVE_DATA_PTR(pic_data_size);
 +    }
 +
 +    *data_size       = sizeof(AVPicture);
 +    *(AVFrame*) data = *avctx->coded_frame;
 +
 +    return avpkt->size;
 +}
 +
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    if (ctx->picture.data[0])
 +        avctx->release_buffer(avctx, &ctx->picture);
 +
 +    av_freep(&ctx->slice_data);
 +
 +    return 0;
 +}
 +
 +
 +AVCodec ff_prores_lgpl_decoder = {
 +    .name           = "prores_lgpl",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)")
 +};
index 8259b2a,0000000..375dc52
mode 100644,000000..100644
--- /dev/null
@@@ -1,890 -1,0 +1,890 @@@
- static inline void encode_vlc_codeword(PutBitContext *pb, uint8_t codebook, int val)
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2012 Konstantin Shishkov
 + *
 + * 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
 + * Lesser General Public License for more details.
 + *
 + * 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 "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "proresdsp.h"
 +#include "proresdata.h"
 +
 +#define CFACTOR_Y422 2
 +#define CFACTOR_Y444 3
 +
 +#define MAX_MBS_PER_SLICE 8
 +
 +#define MAX_PLANES 3 // should be increased to 4 when there's PIX_FMT_YUV444AP10
 +
 +enum {
 +    PRORES_PROFILE_PROXY = 0,
 +    PRORES_PROFILE_LT,
 +    PRORES_PROFILE_STANDARD,
 +    PRORES_PROFILE_HQ,
 +};
 +
 +#define NUM_MB_LIMITS 4
 +static const int prores_mb_limits[NUM_MB_LIMITS] = {
 +    1620, // up to 720x576
 +    2700, // up to 960x720
 +    6075, // up to 1440x1080
 +    9216, // up to 2048x1152
 +};
 +
 +static const struct prores_profile {
 +    const char *full_name;
 +    uint32_t    tag;
 +    int         min_quant;
 +    int         max_quant;
 +    int         br_tab[NUM_MB_LIMITS];
 +    uint8_t     quant[64];
 +} prores_profile_info[4] = {
 +    {
 +        .full_name = "proxy",
 +        .tag       = MKTAG('a', 'p', 'c', 'o'),
 +        .min_quant = 4,
 +        .max_quant = 8,
 +        .br_tab    = { 300, 242, 220, 194 },
 +        .quant     = {
 +             4,  7,  9, 11, 13, 14, 15, 63,
 +             7,  7, 11, 12, 14, 15, 63, 63,
 +             9, 11, 13, 14, 15, 63, 63, 63,
 +            11, 11, 13, 14, 63, 63, 63, 63,
 +            11, 13, 14, 63, 63, 63, 63, 63,
 +            13, 14, 63, 63, 63, 63, 63, 63,
 +            13, 63, 63, 63, 63, 63, 63, 63,
 +            63, 63, 63, 63, 63, 63, 63, 63,
 +        },
 +    },
 +    {
 +        .full_name = "LT",
 +        .tag       = MKTAG('a', 'p', 'c', 's'),
 +        .min_quant = 1,
 +        .max_quant = 9,
 +        .br_tab    = { 720, 560, 490, 440 },
 +        .quant     = {
 +             4,  5,  6,  7,  9, 11, 13, 15,
 +             5,  5,  7,  8, 11, 13, 15, 17,
 +             6,  7,  9, 11, 13, 15, 15, 17,
 +             7,  7,  9, 11, 13, 15, 17, 19,
 +             7,  9, 11, 13, 14, 16, 19, 23,
 +             9, 11, 13, 14, 16, 19, 23, 29,
 +             9, 11, 13, 15, 17, 21, 28, 35,
 +            11, 13, 16, 17, 21, 28, 35, 41,
 +        },
 +    },
 +    {
 +        .full_name = "standard",
 +        .tag       = MKTAG('a', 'p', 'c', 'n'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1050, 808, 710, 632 },
 +        .quant     = {
 +             4,  4,  5,  5,  6,  7,  7,  9,
 +             4,  4,  5,  6,  7,  7,  9,  9,
 +             5,  5,  6,  7,  7,  9,  9, 10,
 +             5,  5,  6,  7,  7,  9,  9, 10,
 +             5,  6,  7,  7,  8,  9, 10, 12,
 +             6,  7,  7,  8,  9, 10, 12, 15,
 +             6,  7,  7,  9, 10, 11, 14, 17,
 +             7,  7,  9, 10, 11, 14, 17, 21,
 +        },
 +    },
 +    {
 +        .full_name = "high quality",
 +        .tag       = MKTAG('a', 'p', 'c', 'h'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1566, 1216, 1070, 950 },
 +        .quant     = {
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  5,
 +             4,  4,  4,  4,  4,  4,  5,  5,
 +             4,  4,  4,  4,  4,  5,  5,  6,
 +             4,  4,  4,  4,  5,  5,  6,  7,
 +             4,  4,  4,  4,  5,  6,  7,  7,
 +        },
 +    }
 +// for 4444 profile bitrate numbers are { 2350, 1828, 1600, 1425 }
 +};
 +
 +#define TRELLIS_WIDTH 16
 +#define SCORE_LIMIT   INT_MAX / 2
 +
 +struct TrellisNode {
 +    int prev_node;
 +    int quant;
 +    int bits;
 +    int score;
 +};
 +
 +#define MAX_STORED_Q 16
 +
 +typedef struct ProresContext {
 +    AVClass *class;
 +    DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
 +    DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16];
 +    int16_t quants[MAX_STORED_Q][64];
 +    int16_t custom_q[64];
 +
 +    ProresDSPContext dsp;
 +    ScanTable  scantable;
 +
 +    int mb_width, mb_height;
 +    int mbs_per_slice;
 +    int num_chroma_blocks, chroma_factor;
 +    int slices_width;
 +    int num_slices;
 +    int num_planes;
 +    int bits_per_mb;
 +
 +    int frame_size;
 +
 +    int profile;
 +    const struct prores_profile *profile_info;
 +
 +    struct TrellisNode *nodes;
 +    int *slice_q;
 +} ProresContext;
 +
 +static void get_slice_data(ProresContext *ctx, const uint16_t *src,
 +                           int linesize, int x, int y, int w, int h,
 +                           DCTELEM *blocks,
 +                           int mbs_per_slice, int blocks_per_mb)
 +{
 +    const uint16_t *esrc;
 +    const int mb_width = 4 * blocks_per_mb;
 +    int elinesize;
 +    int i, j, k;
 +
 +    for (i = 0; i < mbs_per_slice; i++, src += mb_width) {
 +        if (x >= w) {
 +            memset(blocks, 0, 64 * (mbs_per_slice - i) * blocks_per_mb
 +                              * sizeof(*blocks));
 +            return;
 +        }
 +        if (x + mb_width <= w && y + 16 <= h) {
 +            esrc      = src;
 +            elinesize = linesize;
 +        } else {
 +            int bw, bh, pix;
 +            const int estride = 16 / sizeof(*ctx->emu_buf);
 +
 +            esrc      = ctx->emu_buf;
 +            elinesize = 16;
 +
 +            bw = FFMIN(w - x, mb_width);
 +            bh = FFMIN(h - y, 16);
 +
 +            for (j = 0; j < bh; j++) {
 +                memcpy(ctx->emu_buf + j * estride, src + j * linesize,
 +                       bw * sizeof(*src));
 +                pix = ctx->emu_buf[j * estride + bw - 1];
 +                for (k = bw; k < mb_width; k++)
 +                    ctx->emu_buf[j * estride + k] = pix;
 +            }
 +            for (; j < 16; j++)
 +                memcpy(ctx->emu_buf + j * estride,
 +                       ctx->emu_buf + (bh - 1) * estride,
 +                       mb_width * sizeof(*ctx->emu_buf));
 +        }
 +        ctx->dsp.fdct(esrc, elinesize, blocks);
 +        blocks += 64;
 +        if (blocks_per_mb > 2) {
 +            ctx->dsp.fdct(src + 8, linesize, blocks);
 +            blocks += 64;
 +        }
 +        ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
 +        blocks += 64;
 +        if (blocks_per_mb > 2) {
 +            ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
 +            blocks += 64;
 +        }
 +
 +        x += mb_width;
 +    }
 +}
 +
 +/**
 + * Write an unsigned rice/exp golomb codeword.
 + */
- static inline int estimate_vlc(uint8_t codebook, int val)
++static inline void encode_vlc_codeword(PutBitContext *pb, unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        put_bits(pb, exponent - exp_order + switch_bits, 0);
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, exponent, val);
 +    } else {
 +        exponent = val >> rice_order;
 +
 +        if (exponent)
 +            put_bits(pb, exponent, 0);
 +        put_bits(pb, 1, 1);
 +        if (rice_order)
 +            put_sbits(pb, rice_order, val);
 +    }
 +}
 +
 +#define GET_SIGN(x)  ((x) >> 31)
 +#define MAKE_CODE(x) (((x) << 1) ^ GET_SIGN(x))
 +
 +static void encode_dcs(PutBitContext *pb, DCTELEM *blocks,
 +                       int blocks_per_slice, int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +
 +    prev_dc = (blocks[0] - 0x4000) / scale;
 +    encode_vlc_codeword(pb, FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        encode_vlc_codeword(pb, ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +}
 +
 +static void encode_acs(PutBitContext *pb, DCTELEM *blocks,
 +                       int blocks_per_slice,
 +                       int plane_size_factor,
 +                       const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level = blocks[idx] / qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[run_cb], run);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[lev_cb],
 +                                    abs_level - 1);
 +                put_sbits(pb, 1, GET_SIGN(level));
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +}
 +
 +static int encode_slice_plane(ProresContext *ctx, PutBitContext *pb,
 +                              const uint16_t *src, int linesize,
 +                              int mbs_per_slice, DCTELEM *blocks,
 +                              int blocks_per_mb, int plane_size_factor,
 +                              const int16_t *qmat)
 +{
 +    int blocks_per_slice, saved_pos;
 +
 +    saved_pos = put_bits_count(pb);
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    encode_dcs(pb, blocks, blocks_per_slice, qmat[0]);
 +    encode_acs(pb, blocks, blocks_per_slice, plane_size_factor,
 +               ctx->scantable.permutated, qmat);
 +    flush_put_bits(pb);
 +
 +    return (put_bits_count(pb) - saved_pos) >> 3;
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
 +                        PutBitContext *pb,
 +                        int sizes[4], int x, int y, int quant,
 +                        int mbs_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, xp, yp;
 +    int total_size = 0;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks, pwidth;
 +    int plane_factor, is_chroma;
 +    uint16_t *qmat;
 +
 +    if (quant < MAX_STORED_Q) {
 +        qmat = ctx->quants[quant];
 +    } else {
 +        qmat = ctx->custom_q;
 +        for (i = 0; i < 64; i++)
 +            qmat[i] = ctx->profile_info->quant[i] * quant;
 +    }
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma    = (i == 1 || i == 2);
 +        plane_factor = slice_width_factor + 2;
 +        if (is_chroma)
 +            plane_factor += ctx->chroma_factor - 3;
 +        if (!is_chroma || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp          = x << 4;
 +            yp          = y << 4;
 +            num_cblocks = 4;
 +            pwidth      = avctx->width;
 +        } else {
 +            xp          = x << 3;
 +            yp          = y << 4;
 +            num_cblocks = 2;
 +            pwidth      = avctx->width >> 1;
 +        }
 +        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, pic->linesize[i], xp, yp,
 +                       pwidth, avctx->height, ctx->blocks[0],
 +                       mbs_per_slice, num_cblocks);
 +        sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i],
 +                                      mbs_per_slice, ctx->blocks[0],
 +                                      num_cblocks, plane_factor,
 +                                      qmat);
 +        total_size += sizes[i];
 +    }
 +    return total_size;
 +}
 +
++static inline int estimate_vlc(unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        return exponent * 2 - exp_order + switch_bits + 1;
 +    } else {
 +        return (val >> rice_order) + rice_order + 1;
 +    }
 +}
 +
 +static int estimate_dcs(int *error, DCTELEM *blocks, int blocks_per_slice,
 +                        int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +    int bits;
 +
 +    prev_dc  = (blocks[0] - 0x4000) / scale;
 +    bits     = estimate_vlc(FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +    *error  += FFABS(blocks[0] - 0x4000) % scale;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        *error  += FFABS(blocks[0] - 0x4000) % scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        bits    += estimate_vlc(ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +
 +    return bits;
 +}
 +
 +static int estimate_acs(int *error, DCTELEM *blocks, int blocks_per_slice,
 +                        int plane_size_factor,
 +                        const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +    int bits = 0;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level   = blocks[idx] / qmat[scan[i]];
 +            *error += FFABS(blocks[idx]) % qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                bits += estimate_vlc(ff_prores_ac_codebook[run_cb], run);
 +                bits += estimate_vlc(ff_prores_ac_codebook[lev_cb],
 +                                     abs_level - 1) + 1;
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +
 +    return bits;
 +}
 +
 +static int estimate_slice_plane(ProresContext *ctx, int *error, int plane,
 +                                const uint16_t *src, int linesize,
 +                                int mbs_per_slice,
 +                                int blocks_per_mb, int plane_size_factor,
 +                                const int16_t *qmat)
 +{
 +    int blocks_per_slice;
 +    int bits;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    bits  = estimate_dcs(error, ctx->blocks[plane], blocks_per_slice, qmat[0]);
 +    bits += estimate_acs(error, ctx->blocks[plane], blocks_per_slice,
 +                         plane_size_factor, ctx->scantable.permutated, qmat);
 +
 +    return FFALIGN(bits, 8);
 +}
 +
 +static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,
 +                            int trellis_node, int x, int y, int mbs_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, q, pq, xp, yp;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks[MAX_PLANES], pwidth;
 +    int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES];
 +    const int min_quant = ctx->profile_info->min_quant;
 +    const int max_quant = ctx->profile_info->max_quant;
 +    int error, bits, bits_limit;
 +    int mbs, prev, cur, new_score;
 +    int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];
 +    int overquant;
 +    uint16_t *qmat;
 +
 +    mbs = x + mbs_per_slice;
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma[i]    = (i == 1 || i == 2);
 +        plane_factor[i] = slice_width_factor + 2;
 +        if (is_chroma[i])
 +            plane_factor[i] += ctx->chroma_factor - 3;
 +        if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp             = x << 4;
 +            yp             = y << 4;
 +            num_cblocks[i] = 4;
 +            pwidth         = avctx->width;
 +        } else {
 +            xp             = x << 3;
 +            yp             = y << 4;
 +            num_cblocks[i] = 2;
 +            pwidth         = avctx->width >> 1;
 +        }
 +        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, pic->linesize[i], xp, yp,
 +                       pwidth, avctx->height, ctx->blocks[i],
 +                       mbs_per_slice, num_cblocks[i]);
 +    }
 +
 +    for (q = min_quant; q < max_quant + 2; q++) {
 +        ctx->nodes[trellis_node + q].prev_node = -1;
 +        ctx->nodes[trellis_node + q].quant     = q;
 +    }
 +
 +    // todo: maybe perform coarser quantising to fit into frame size when needed
 +    for (q = min_quant; q <= max_quant; q++) {
 +        bits  = 0;
 +        error = 0;
 +        for (i = 0; i < ctx->num_planes; i++) {
 +            bits += estimate_slice_plane(ctx, &error, i,
 +                                         src, pic->linesize[i],
 +                                         mbs_per_slice,
 +                                         num_cblocks[i], plane_factor[i],
 +                                         ctx->quants[q]);
 +        }
 +        if (bits > 65000 * 8) {
 +            error = SCORE_LIMIT;
 +            break;
 +        }
 +        slice_bits[q]  = bits;
 +        slice_score[q] = error;
 +    }
 +    if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) {
 +        slice_bits[max_quant + 1]  = slice_bits[max_quant];
 +        slice_score[max_quant + 1] = slice_score[max_quant] + 1;
 +        overquant = max_quant;
 +    } else {
 +        for (q = max_quant + 1; q < 128; q++) {
 +            bits  = 0;
 +            error = 0;
 +            if (q < MAX_STORED_Q) {
 +                qmat = ctx->quants[q];
 +            } else {
 +                qmat = ctx->custom_q;
 +                for (i = 0; i < 64; i++)
 +                    qmat[i] = ctx->profile_info->quant[i] * q;
 +            }
 +            for (i = 0; i < ctx->num_planes; i++) {
 +                bits += estimate_slice_plane(ctx, &error, i,
 +                                             src, pic->linesize[i],
 +                                             mbs_per_slice,
 +                                             num_cblocks[i], plane_factor[i],
 +                                             qmat);
 +            }
 +            if (bits <= ctx->bits_per_mb * mbs_per_slice)
 +                break;
 +        }
 +
 +        slice_bits[max_quant + 1]  = bits;
 +        slice_score[max_quant + 1] = error;
 +        overquant = q;
 +    }
 +    ctx->nodes[trellis_node + max_quant + 1].quant = overquant;
 +
 +    bits_limit = mbs * ctx->bits_per_mb;
 +    for (pq = min_quant; pq < max_quant + 2; pq++) {
 +        prev = trellis_node - TRELLIS_WIDTH + pq;
 +
 +        for (q = min_quant; q < max_quant + 2; q++) {
 +            cur = trellis_node + q;
 +
 +            bits  = ctx->nodes[prev].bits + slice_bits[q];
 +            error = slice_score[q];
 +            if (bits > bits_limit)
 +                error = SCORE_LIMIT;
 +
 +            if (ctx->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT)
 +                new_score = ctx->nodes[prev].score + error;
 +            else
 +                new_score = SCORE_LIMIT;
 +            if (ctx->nodes[cur].prev_node == -1 ||
 +                ctx->nodes[cur].score >= new_score) {
 +
 +                ctx->nodes[cur].bits      = bits;
 +                ctx->nodes[cur].score     = new_score;
 +                ctx->nodes[cur].prev_node = prev;
 +            }
 +        }
 +    }
 +
 +    error = ctx->nodes[trellis_node + min_quant].score;
 +    pq    = trellis_node + min_quant;
 +    for (q = min_quant + 1; q < max_quant + 2; q++) {
 +        if (ctx->nodes[trellis_node + q].score <= error) {
 +            error = ctx->nodes[trellis_node + q].score;
 +            pq    = trellis_node + q;
 +        }
 +    }
 +
 +    return pq;
 +}
 +
 +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                        const AVFrame *pic, int *got_packet)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t *orig_buf, *buf, *slice_hdr, *slice_sizes, *tmp;
 +    uint8_t *picture_size_pos;
 +    PutBitContext pb;
 +    int x, y, i, mb, q = 0;
 +    int sizes[4] = { 0 };
 +    int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
 +    int frame_size, picture_size, slice_size;
 +    int mbs_per_slice = ctx->mbs_per_slice;
 +    int pkt_size, ret;
 +
 +    *avctx->coded_frame           = *pic;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +    avctx->coded_frame->key_frame = 1;
 +
 +    pkt_size = ctx->frame_size + FF_MIN_BUFFER_SIZE;
 +
 +    if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
 +        return ret;
 +    }
 +
 +    orig_buf = pkt->data;
 +
 +    // frame atom
 +    orig_buf += 4;                              // frame size
 +    bytestream_put_be32  (&orig_buf, FRAME_ID); // frame container ID
 +    buf = orig_buf;
 +
 +    // frame header
 +    tmp = buf;
 +    buf += 2;                                   // frame header size will be stored here
 +    bytestream_put_be16  (&buf, 0);             // version 1
 +    bytestream_put_buffer(&buf, "Lavc", 4);     // creator
 +    bytestream_put_be16  (&buf, avctx->width);
 +    bytestream_put_be16  (&buf, avctx->height);
 +    bytestream_put_byte  (&buf, ctx->chroma_factor << 6); // frame flags
 +    bytestream_put_byte  (&buf, 0);             // reserved
 +    bytestream_put_byte  (&buf, 0);             // primaries
 +    bytestream_put_byte  (&buf, 0);             // transfer function
 +    bytestream_put_byte  (&buf, 6);             // colour matrix - ITU-R BT.601-4
 +    bytestream_put_byte  (&buf, 0x40);          // source format and alpha information
 +    bytestream_put_byte  (&buf, 0);             // reserved
 +    bytestream_put_byte  (&buf, 0x03);          // matrix flags - both matrices are present
 +    // luma quantisation matrix
 +    for (i = 0; i < 64; i++)
 +        bytestream_put_byte(&buf, ctx->profile_info->quant[i]);
 +    // chroma quantisation matrix
 +    for (i = 0; i < 64; i++)
 +        bytestream_put_byte(&buf, ctx->profile_info->quant[i]);
 +    bytestream_put_be16  (&tmp, buf - orig_buf); // write back frame header size
 +
 +    // picture header
 +    picture_size_pos = buf + 1;
 +    bytestream_put_byte  (&buf, 0x40);          // picture header size (in bits)
 +    buf += 4;                                   // picture data size will be stored here
 +    bytestream_put_be16  (&buf, ctx->num_slices); // total number of slices
 +    bytestream_put_byte  (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
 +
 +    // seek table - will be filled during slice encoding
 +    slice_sizes = buf;
 +    buf += ctx->num_slices * 2;
 +
 +    // slices
 +    for (y = 0; y < ctx->mb_height; y++) {
 +        mbs_per_slice = ctx->mbs_per_slice;
 +        for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +            while (ctx->mb_width - x < mbs_per_slice)
 +                mbs_per_slice >>= 1;
 +            q = find_slice_quant(avctx, pic, (mb + 1) * TRELLIS_WIDTH, x, y,
 +                                 mbs_per_slice);
 +        }
 +
 +        for (x = ctx->slices_width - 1; x >= 0; x--) {
 +            ctx->slice_q[x] = ctx->nodes[q].quant;
 +            q = ctx->nodes[q].prev_node;
 +        }
 +
 +        mbs_per_slice = ctx->mbs_per_slice;
 +        for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +            q = ctx->slice_q[mb];
 +
 +            while (ctx->mb_width - x < mbs_per_slice)
 +                mbs_per_slice >>= 1;
 +
 +            bytestream_put_byte(&buf, slice_hdr_size << 3);
 +            slice_hdr = buf;
 +            buf += slice_hdr_size - 1;
 +            init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8);
 +            encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice);
 +
 +            bytestream_put_byte(&slice_hdr, q);
 +            slice_size = slice_hdr_size + sizes[ctx->num_planes - 1];
 +            for (i = 0; i < ctx->num_planes - 1; i++) {
 +                bytestream_put_be16(&slice_hdr, sizes[i]);
 +                slice_size += sizes[i];
 +            }
 +            bytestream_put_be16(&slice_sizes, slice_size);
 +            buf += slice_size - slice_hdr_size;
 +        }
 +    }
 +
 +    orig_buf -= 8;
 +    frame_size = buf - orig_buf;
 +    picture_size = buf - picture_size_pos - 6;
 +    bytestream_put_be32(&orig_buf, frame_size);
 +    bytestream_put_be32(&picture_size_pos, picture_size);
 +
 +    pkt->size   = frame_size;
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    if (avctx->coded_frame->data[0])
 +        avctx->release_buffer(avctx, avctx->coded_frame);
 +
 +    av_freep(&avctx->coded_frame);
 +
 +    av_freep(&ctx->nodes);
 +    av_freep(&ctx->slice_q);
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int mps;
 +    int i, j;
 +    int min_quant, max_quant;
 +
 +    avctx->bits_per_raw_sample = 10;
 +    avctx->coded_frame = avcodec_alloc_frame();
 +    if (!avctx->coded_frame)
 +        return AVERROR(ENOMEM);
 +
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +    ff_init_scantable(ctx->dsp.dct_permutation, &ctx->scantable,
 +                      ff_prores_progressive_scan);
 +
 +    mps = ctx->mbs_per_slice;
 +    if (mps & (mps - 1)) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "there should be an integer power of two MBs per slice\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    ctx->chroma_factor = avctx->pix_fmt == PIX_FMT_YUV422P10
 +                         ? CFACTOR_Y422
 +                         : CFACTOR_Y444;
 +    ctx->profile_info  = prores_profile_info + ctx->profile;
 +    ctx->num_planes    = 3;
 +
 +    ctx->mb_width      = FFALIGN(avctx->width,  16) >> 4;
 +    ctx->mb_height     = FFALIGN(avctx->height, 16) >> 4;
 +    ctx->slices_width  = ctx->mb_width / mps;
 +    ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps);
 +    ctx->num_slices    = ctx->mb_height * ctx->slices_width;
 +
 +    for (i = 0; i < NUM_MB_LIMITS - 1; i++)
 +        if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height)
 +            break;
 +    ctx->bits_per_mb   = ctx->profile_info->br_tab[i];
 +
 +    ctx->frame_size = ctx->num_slices * (2 + 2 * ctx->num_planes
 +                                         + (2 * mps * ctx->bits_per_mb) / 8)
 +                      + 200;
 +
 +    min_quant = ctx->profile_info->min_quant;
 +    max_quant = ctx->profile_info->max_quant;
 +    for (i = min_quant; i < MAX_STORED_Q; i++) {
 +        for (j = 0; j < 64; j++)
 +            ctx->quants[i][j] = ctx->profile_info->quant[j] * i;
 +    }
 +
 +    avctx->codec_tag   = ctx->profile_info->tag;
 +
 +    av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n",
 +           ctx->profile, ctx->num_slices, ctx->bits_per_mb);
 +    av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n",
 +           ctx->frame_size);
 +
 +    ctx->nodes = av_malloc((ctx->slices_width + 1) * TRELLIS_WIDTH
 +                           * sizeof(*ctx->nodes));
 +    if (!ctx->nodes) {
 +        encode_close(avctx);
 +        return AVERROR(ENOMEM);
 +    }
 +    for (i = min_quant; i < max_quant + 2; i++) {
 +        ctx->nodes[i].prev_node = -1;
 +        ctx->nodes[i].bits      = 0;
 +        ctx->nodes[i].score     = 0;
 +    }
 +
 +    ctx->slice_q = av_malloc(ctx->slices_width * sizeof(*ctx->slice_q));
 +    if (!ctx->slice_q) {
 +        encode_close(avctx);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(ProresContext, x)
 +#define VE     AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +
 +static const AVOption options[] = {
 +    { "mbs_per_slice", "macroblocks per slice", OFFSET(mbs_per_slice),
 +        AV_OPT_TYPE_INT, { 8 }, 1, MAX_MBS_PER_SLICE, VE },
 +    { "profile",       NULL, OFFSET(profile), AV_OPT_TYPE_INT,
 +        { PRORES_PROFILE_STANDARD },
 +        PRORES_PROFILE_PROXY, PRORES_PROFILE_HQ, VE, "profile" },
 +    { "proxy",         NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_PROXY },
 +        0, 0, VE, "profile" },
 +    { "lt",            NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_LT },
 +        0, 0, VE, "profile" },
 +    { "standard",      NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_STANDARD },
 +        0, 0, VE, "profile" },
 +    { "hq",            NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_HQ },
 +        0, 0, VE, "profile" },
 +    { NULL }
 +};
 +
 +static const AVClass proresenc_class = {
 +    .class_name = "ProRes encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_prores_kostya_encoder = {
 +    .name           = "prores_kostya",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = encode_init,
 +    .close          = encode_close,
 +    .encode2        = encode_frame,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
 +    .pix_fmts       = (const enum PixelFormat[]) {
 +                          PIX_FMT_YUV422P10, PIX_FMT_YUV444P10, PIX_FMT_NONE
 +                      },
 +    .priv_class     = &proresenc_class,
 +};
@@@ -115,14 -104,12 +115,14 @@@ OBJS-$(CONFIG_H263_MUXER
  OBJS-$(CONFIG_H264_DEMUXER)              += h264dec.o rawdec.o
  OBJS-$(CONFIG_H264_MUXER)                += rawenc.o
  OBJS-$(CONFIG_HLS_DEMUXER)               += hls.o
 +OBJS-$(CONFIG_ICO_DEMUXER)               += icodec.o
  OBJS-$(CONFIG_IDCIN_DEMUXER)             += idcin.o
 +OBJS-$(CONFIG_IDF_DEMUXER)               += bintext.o
  OBJS-$(CONFIG_IFF_DEMUXER)               += iff.o
- OBJS-$(CONFIG_IMAGE2_DEMUXER)            += img2.o
- OBJS-$(CONFIG_IMAGE2_MUXER)              += img2.o
- OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER)        += img2.o
- OBJS-$(CONFIG_IMAGE2PIPE_MUXER)          += img2.o
+ OBJS-$(CONFIG_IMAGE2_DEMUXER)            += img2dec.o img2.o
+ OBJS-$(CONFIG_IMAGE2_MUXER)              += img2enc.o img2.o
+ OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER)        += img2dec.o img2.o
+ OBJS-$(CONFIG_IMAGE2PIPE_MUXER)          += img2enc.o img2.o
  OBJS-$(CONFIG_INGENIENT_DEMUXER)         += ingenientdec.o rawdec.o
  OBJS-$(CONFIG_IPMOVIE_DEMUXER)           += ipmovie.o
  OBJS-$(CONFIG_ISS_DEMUXER)               += iss.o
@@@ -149,9 -157,11 +149,12 @@@ static int parse_keyframes_index(AVForm
          return 0;
      }
  
+     if (s->flags & AVFMT_FLAG_IGNIDX)
+         return 0;
      while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
 -        int64_t* current_array;
 +        int64_t** current_array;
 +        unsigned int arraylen;
  
          // Expect array object in context
          if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY)
          }
      }
  
 -    if (!ret && timeslen == fileposlen)
 -        for (i = 0; i < fileposlen; i++)
 +    if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) {
 +        int64_t dts, size0, size1;
 +        avio_seek(ioc, filepositions[1]-4, SEEK_SET);
 +        size0 = avio_rb32(ioc);
 +                avio_r8(ioc);
 +        size1 = avio_rb24(ioc);
 +        dts   = avio_rb24(ioc);
 +        dts  |= avio_r8(ioc) << 24;
 +        if (size0 > filepositions[1] || FFABS(dts - times[1]*1000)>5000/*arbitraray threshold to detect invalid index*/)
 +            goto invalid;
-          for(i = 0; i < timeslen; i++)
-              av_add_index_entry(vstream, filepositions[i], times[i]*1000, 0, 0, AVINDEX_KEYFRAME);
++        for(i = 0; i < timeslen; i++)
+             av_add_index_entry(vstream, filepositions[i], times[i]*1000,
+                                0, 0, AVINDEX_KEYFRAME);
 -    else
 +    } else {
 +invalid:
          av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
 +    }
  
  finish:
      av_freep(&times);
Simple merge
index 0000000,b4b9723..e8b695f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,322 +1,327 @@@
 - * This file is part of Libav.
+ /*
+  * Image format
+  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+  * Copyright (c) 2004 Michael Niedermayer
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg 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
 -            if(codec->codec_id != CODEC_ID_RAWVIDEO)
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "libavutil/avstring.h"
+ #include "libavutil/log.h"
+ #include "libavutil/opt.h"
+ #include "libavutil/pixdesc.h"
+ #include "libavutil/parseutils.h"
+ #include "avformat.h"
+ #include "internal.h"
+ typedef struct {
+     const AVClass *class;  /**< Class for private options. */
+     int img_first;
+     int img_last;
+     int img_number;
+     int img_count;
+     int is_pipe;
++    int split_planes;       /**< use independent file for each Y, U, V plane */
+     char path[1024];
+     char *pixel_format;     /**< Set by a private option. */
+     char *video_size;       /**< Set by a private option. */
+     char *framerate;        /**< Set by a private option. */
+     int loop;
+ } VideoDemuxData;
+ static const int sizes[][2] = {
+     { 640, 480 },
+     { 720, 480 },
+     { 720, 576 },
+     { 352, 288 },
+     { 352, 240 },
+     { 160, 128 },
+     { 512, 384 },
+     { 640, 352 },
+     { 640, 240 },
+ };
+ static int infer_size(int *width_ptr, int *height_ptr, int size)
+ {
+     int i;
+     for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
+         if ((sizes[i][0] * sizes[i][1]) == size) {
+             *width_ptr = sizes[i][0];
+             *height_ptr = sizes[i][1];
+             return 0;
+         }
+     }
+     return -1;
+ }
+ /* return -1 if no image found */
+ static int find_image_range(int *pfirst_index, int *plast_index,
+                             const char *path)
+ {
+     char buf[1024];
+     int range, last_index, range1, first_index;
+     /* find the first image */
+     for(first_index = 0; first_index < 5; first_index++) {
+         if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
+             *pfirst_index =
+             *plast_index = 1;
+             if (avio_check(buf, AVIO_FLAG_READ) > 0)
+                 return 0;
+             return -1;
+         }
+         if (avio_check(buf, AVIO_FLAG_READ) > 0)
+             break;
+     }
+     if (first_index == 5)
+         goto fail;
+     /* find the last image */
+     last_index = first_index;
+     for(;;) {
+         range = 0;
+         for(;;) {
+             if (!range)
+                 range1 = 1;
+             else
+                 range1 = 2 * range;
+             if (av_get_frame_filename(buf, sizeof(buf), path,
+                                       last_index + range1) < 0)
+                 goto fail;
+             if (avio_check(buf, AVIO_FLAG_READ) <= 0)
+                 break;
+             range = range1;
+             /* just in case... */
+             if (range >= (1 << 30))
+                 goto fail;
+         }
+         /* we are sure than image last_index + range exists */
+         if (!range)
+             break;
+         last_index += range;
+     }
+     *pfirst_index = first_index;
+     *plast_index = last_index;
+     return 0;
+  fail:
+     return -1;
+ }
+ static int read_probe(AVProbeData *p)
+ {
+     if (p->filename && ff_guess_image2_codec(p->filename)) {
+         if (av_filename_number_test(p->filename))
+             return AVPROBE_SCORE_MAX;
+         else
+             return AVPROBE_SCORE_MAX/2;
+     }
+     return 0;
+ }
+ static int read_header(AVFormatContext *s1)
+ {
+     VideoDemuxData *s = s1->priv_data;
+     int first_index, last_index, ret = 0;
+     int width = 0, height = 0;
+     AVStream *st;
+     enum PixelFormat pix_fmt = PIX_FMT_NONE;
+     AVRational framerate;
+     s1->ctx_flags |= AVFMTCTX_NOHEADER;
+     st = avformat_new_stream(s1, NULL);
+     if (!st) {
+         return AVERROR(ENOMEM);
+     }
+     if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
+         av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
+         return AVERROR(EINVAL);
+     }
+     if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
+         av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
+         return ret;
+     }
+     if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
+         av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
+         return ret;
+     }
+     av_strlcpy(s->path, s1->filename, sizeof(s->path));
+     s->img_number = 0;
+     s->img_count = 0;
+     /* find format */
+     if (s1->iformat->flags & AVFMT_NOFILE)
+         s->is_pipe = 0;
+     else{
+         s->is_pipe = 1;
+         st->need_parsing = AVSTREAM_PARSE_FULL;
+     }
+     avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
+     if (width && height) {
+         st->codec->width  = width;
+         st->codec->height = height;
+     }
+     if (!s->is_pipe) {
+         if (find_image_range(&first_index, &last_index, s->path) < 0)
+             return AVERROR(ENOENT);
+         s->img_first = first_index;
+         s->img_last = last_index;
+         s->img_number = first_index;
+         /* compute duration */
+         st->start_time = 0;
+         st->duration = last_index - first_index + 1;
+     }
+     if(s1->video_codec_id){
+         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+         st->codec->codec_id = s1->video_codec_id;
+     }else if(s1->audio_codec_id){
+         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+         st->codec->codec_id = s1->audio_codec_id;
+     }else{
++        const char *str= strrchr(s->path, '.');
++        s->split_planes = str && !av_strcasecmp(str + 1, "y");
+         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+         st->codec->codec_id = ff_guess_image2_codec(s->path);
++        if (st->codec->codec_id == CODEC_ID_LJPEG)
++            st->codec->codec_id = CODEC_ID_MJPEG;
+     }
+     if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE)
+         st->codec->pix_fmt = pix_fmt;
+     return 0;
+ }
+ static int read_packet(AVFormatContext *s1, AVPacket *pkt)
+ {
+     VideoDemuxData *s = s1->priv_data;
+     char filename[1024];
+     int i;
+     int size[3]={0}, ret[3]={0};
+     AVIOContext *f[3];
+     AVCodecContext *codec= s1->streams[0]->codec;
+     if (!s->is_pipe) {
+         /* loop over input */
+         if (s->loop && s->img_number > s->img_last) {
+             s->img_number = s->img_first;
+         }
+         if (s->img_number > s->img_last)
+             return AVERROR_EOF;
+         if (av_get_frame_filename(filename, sizeof(filename),
+                                   s->path, s->img_number)<0 && s->img_number > 1)
+             return AVERROR(EIO);
+         for(i=0; i<3; i++){
+             if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
+                            &s1->interrupt_callback, NULL) < 0) {
+                 if(i==1)
+                     break;
+                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
+                 return AVERROR(EIO);
+             }
+             size[i]= avio_size(f[i]);
 -        if (f[0]->eof_reached)
++            if(!s->split_planes)
+                 break;
+             filename[ strlen(filename) - 1 ]= 'U' + i;
+         }
+         if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
+             infer_size(&codec->width, &codec->height, size[0]);
+     } else {
+         f[0] = s1->pb;
++        if (url_feof(f[0]))
+             return AVERROR(EIO);
+         size[0]= 4096;
+     }
+     av_new_packet(pkt, size[0] + size[1] + size[2]);
+     pkt->stream_index = 0;
+     pkt->flags |= AV_PKT_FLAG_KEY;
+     pkt->size= 0;
+     for(i=0; i<3; i++){
+         if(size[i]){
+             ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
+             if (!s->is_pipe)
+                 avio_close(f[i]);
+             if(ret[i]>0)
+                 pkt->size += ret[i];
+         }
+     }
+     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
+         av_free_packet(pkt);
+         return AVERROR(EIO); /* signal EOF */
+     } else {
+         s->img_count++;
+         s->img_number++;
+         return 0;
+     }
+ }
+ #define OFFSET(x) offsetof(VideoDemuxData, x)
+ #define DEC AV_OPT_FLAG_DECODING_PARAM
+ static const AVOption options[] = {
+     { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+     { "video_size",   "", OFFSET(video_size),   AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+     { "framerate",    "", OFFSET(framerate),    AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
+     { "loop",         "", OFFSET(loop),         AV_OPT_TYPE_INT,    {.dbl = 0},    0, 1, DEC },
+     { NULL },
+ };
+ #if CONFIG_IMAGE2_DEMUXER
+ static const AVClass img2_class = {
+     .class_name = "image2 demuxer",
+     .item_name  = av_default_item_name,
+     .option     = options,
+     .version    = LIBAVUTIL_VERSION_INT,
+ };
+ AVInputFormat ff_image2_demuxer = {
+     .name           = "image2",
+     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
+     .priv_data_size = sizeof(VideoDemuxData),
+     .read_probe     = read_probe,
+     .read_header    = read_header,
+     .read_packet    = read_packet,
+     .flags          = AVFMT_NOFILE,
+     .priv_class     = &img2_class,
+ };
+ #endif
+ #if CONFIG_IMAGE2PIPE_DEMUXER
+ static const AVClass img2pipe_class = {
+     .class_name = "image2pipe demuxer",
+     .item_name  = av_default_item_name,
+     .option     = options,
+     .version    = LIBAVUTIL_VERSION_INT,
+ };
+ AVInputFormat ff_image2pipe_demuxer = {
+     .name           = "image2pipe",
+     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
+     .priv_data_size = sizeof(VideoDemuxData),
+     .read_header    = read_header,
+     .read_packet    = read_packet,
+     .priv_class     = &img2pipe_class,
+ };
+ #endif
index 0000000,8fbe37e..9b4b30e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,151 +1,175 @@@
 - * This file is part of Libav.
+ /*
+  * Image format
+  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+  * Copyright (c) 2004 Michael Niedermayer
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg 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
 -                                  img->path, img->img_number) < 0 && img->img_number>1) {
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "libavutil/intreadwrite.h"
+ #include "libavutil/avstring.h"
+ #include "libavutil/log.h"
++#include "libavutil/opt.h"
+ #include "avformat.h"
+ #include "avio_internal.h"
+ #include "internal.h"
+ typedef struct {
++    const AVClass *class;  /**< Class for private options. */
+     int img_number;
+     int is_pipe;
++    int split_planes;       /**< use independent file for each Y, U, V plane */
+     char path[1024];
++    int updatefirst;
+ } VideoMuxData;
+ static int write_header(AVFormatContext *s)
+ {
+     VideoMuxData *img = s->priv_data;
++    const char *str;
+     img->img_number = 1;
+     av_strlcpy(img->path, s->filename, sizeof(img->path));
+     /* find format */
+     if (s->oformat->flags & AVFMT_NOFILE)
+         img->is_pipe = 0;
+     else
+         img->is_pipe = 1;
++    str = strrchr(img->path, '.');
++    img->split_planes = str && !av_strcasecmp(str + 1, "y");
+     return 0;
+ }
+ static int write_packet(AVFormatContext *s, AVPacket *pkt)
+ {
+     VideoMuxData *img = s->priv_data;
+     AVIOContext *pb[3];
+     char filename[1024];
+     AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
+     int i;
+     if (!img->is_pipe) {
+         if (av_get_frame_filename(filename, sizeof(filename),
 -            return AVERROR(EIO);
++                                  img->path, img->img_number) < 0 && img->img_number>1 && !img->updatefirst) {
+             av_log(s, AV_LOG_ERROR,
+                    "Could not get frame filename number %d from pattern '%s'\n",
+                    img->img_number, img->path);
 -            if(codec->codec_id != CODEC_ID_RAWVIDEO)
++            return AVERROR(EINVAL);
+         }
+         for(i=0; i<3; i++){
+             if (avio_open2(&pb[i], filename, AVIO_FLAG_WRITE,
+                            &s->interrupt_callback, NULL) < 0) {
+                 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename);
+                 return AVERROR(EIO);
+             }
 -    if(codec->codec_id == CODEC_ID_RAWVIDEO){
++            if(!img->split_planes)
+                 break;
+             filename[ strlen(filename) - 1 ]= 'U' + i;
+         }
+     } else {
+         pb[0] = s->pb;
+     }
 -                av_log(s, AV_LOG_ERROR, "malformed JPEG 2000 codestream\n");
++    if(img->split_planes){
+         int ysize = codec->width * codec->height;
+         avio_write(pb[0], pkt->data        , ysize);
+         avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
+         avio_write(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
+         avio_flush(pb[1]);
+         avio_flush(pb[2]);
+         avio_close(pb[1]);
+         avio_close(pb[2]);
+     }else{
+         if(ff_guess_image2_codec(s->filename) == CODEC_ID_JPEG2000){
+             AVStream *st = s->streams[0];
+             if(st->codec->extradata_size > 8 &&
+                AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){
+                 if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c'))
+                     goto error;
+                 avio_wb32(pb[0], 12);
+                 ffio_wfourcc(pb[0], "jP  ");
+                 avio_wb32(pb[0], 0x0D0A870A); // signature
+                 avio_wb32(pb[0], 20);
+                 ffio_wfourcc(pb[0], "ftyp");
+                 ffio_wfourcc(pb[0], "jp2 ");
+                 avio_wb32(pb[0], 0);
+                 ffio_wfourcc(pb[0], "jp2 ");
+                 avio_write(pb[0], st->codec->extradata, st->codec->extradata_size);
++            }else if(pkt->size >= 8 && AV_RB32(pkt->data) == 0xFF4FFF51){
++                //jpeg2000 codestream
+             }else if(pkt->size < 8 ||
+                      (!st->codec->extradata_size &&
+                       AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature
+             error:
 -    .extensions     = "bmp,dpx,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
 -                      "ppm,sgi,tga,tif,tiff,jp2,xwd,sun,ras,rs,im1,im8,im24,"
++                av_log(s, AV_LOG_ERROR, "malformed JPEG 2000 codestream %X\n", AV_RB32(pkt->data));
+                 return -1;
+             }
+         }
+         avio_write(pb[0], pkt->data, pkt->size);
+     }
+     avio_flush(pb[0]);
+     if (!img->is_pipe) {
+         avio_close(pb[0]);
+     }
+     img->img_number++;
+     return 0;
+ }
++#define OFFSET(x) offsetof(VideoMuxData, x)
++#define ENC AV_OPT_FLAG_ENCODING_PARAM
++static const AVOption muxoptions[] = {
++    { "updatefirst",  "", OFFSET(updatefirst),  AV_OPT_TYPE_INT,    {.dbl = 0},    0, 1, ENC },
++    { NULL },
++};
++
++
+ #if CONFIG_IMAGE2_MUXER
++static const AVClass img2mux_class = {
++    .class_name = "image2 muxer",
++    .item_name  = av_default_item_name,
++    .option     = muxoptions,
++    .version    = LIBAVUTIL_VERSION_INT,
++};
+ AVOutputFormat ff_image2_muxer = {
+     .name           = "image2",
+     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
 -    .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE
++    .extensions     = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
++                      "ppm,sgi,tga,tif,tiff,jp2,j2c,xwd,sun,ras,rs,im1,im8,im24,"
+                       "sunras",
+     .priv_data_size = sizeof(VideoMuxData),
+     .video_codec    = CODEC_ID_MJPEG,
+     .write_header   = write_header,
+     .write_packet   = write_packet,
++    .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE,
++    .priv_class     = &img2mux_class,
+ };
+ #endif
+ #if CONFIG_IMAGE2PIPE_MUXER
+ AVOutputFormat ff_image2pipe_muxer = {
+     .name           = "image2pipe",
+     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
+     .priv_data_size = sizeof(VideoMuxData),
+     .video_codec    = CODEC_ID_MJPEG,
+     .write_header   = write_header,
+     .write_packet   = write_packet,
+     .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
+ };
+ #endif
Simple merge
@@@ -147,7 -143,7 +147,8 @@@ typedef struct MOVContext 
      unsigned trex_count;
      int itunes_metadata;  ///< metadata are itunes style
      int chapter_track;
 +    int use_absolute_path;
+     int64_t next_root_atom; ///< offset of the next root atom
  } MOVContext;
  
  int ff_mp4_read_descr_len(AVIOContext *pb);
@@@ -2821,9 -2671,12 +2825,12 @@@ static int mov_read_packet(AVFormatCont
      sample = mov_find_next_sample(s, &st);
      if (!sample) {
          mov->found_mdat = 0;
-         if (s->pb->seekable||
-             mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 ||
+         if (!mov->next_root_atom)
+             return AVERROR_EOF;
+         avio_seek(s->pb, mov->next_root_atom, SEEK_SET);
+         mov->next_root_atom = 0;
+         if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 ||
 -            s->pb->eof_reached)
 +            url_feof(s->pb))
              return AVERROR_EOF;
          av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
          goto retry;
@@@ -94,14 -93,12 +94,14 @@@ static int mov_write_stco_tag(AVIOConte
      } else
          ffio_wfourcc(pb, "stco");
      avio_wb32(pb, 0); /* version & flags */
 -    avio_wb32(pb, track->entry); /* entry count */
 +    avio_wb32(pb, track->chunkCount); /* entry count */
      for (i=0; i<track->entry; i++) {
 +        if(!track->cluster[i].chunkNum)
 +            continue;
          if(mode64 == 1)
-             avio_wb64(pb, track->cluster[i].pos);
+             avio_wb64(pb, track->cluster[i].pos + track->data_offset);
          else
-             avio_wb32(pb, track->cluster[i].pos);
+             avio_wb32(pb, track->cluster[i].pos + track->data_offset);
      }
      return update_size(pb, pos);
  }
@@@ -2030,27 -1996,6 +2030,29 @@@ static int mov_write_uuidusmt_tag(AVIOC
      return 0;
  }
  
 +static void build_chunks(MOVTrack *trk)
 +{
 +    int i;
 +    MOVIentry *chunk= &trk->cluster[0];
 +    uint64_t chunkSize = chunk->size;
 +    chunk->chunkNum= 1;
++    if (trk->chunkCount)
++        return;
 +    trk->chunkCount= 1;
 +    for(i=1; i<trk->entry; i++){
 +        if(chunk->pos + chunkSize == trk->cluster[i].pos &&
 +            chunkSize + trk->cluster[i].size < (1<<20)){
 +            chunkSize             += trk->cluster[i].size;
 +            chunk->samples_in_chunk += trk->cluster[i].entries;
 +        }else{
 +            trk->cluster[i].chunkNum = chunk->chunkNum+1;
 +            chunk=&trk->cluster[i];
 +            chunkSize = chunk->size;
 +            trk->chunkCount++;
 +        }
 +    }
 +}
 +
  static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
                                AVFormatContext *s)
  {
@@@ -3181,23 -3149,11 +3216,16 @@@ static int mov_write_header(AVFormatCon
                              FF_MOV_FLAG_FRAG_CUSTOM)) &&
              !mov->max_fragment_duration && !mov->max_fragment_size)
              mov->max_fragment_duration = 5000000;
-         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF;
+         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
+                       FF_MOV_FLAG_FRAGMENT;
      }
  
-     /* Set the FRAGMENT flag if any of the fragmentation methods are
-      * enabled. */
-     if (mov->max_fragment_duration || mov->max_fragment_size ||
-         mov->flags & (FF_MOV_FLAG_EMPTY_MOOV |
-                       FF_MOV_FLAG_FRAG_KEYFRAME |
-                       FF_MOV_FLAG_FRAG_CUSTOM))
-         mov->flags |= FF_MOV_FLAG_FRAGMENT;
-     if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV))
 +    if(mov->reserved_moov_size){
 +        mov->reserved_moov_pos= avio_tell(pb);
 +        avio_skip(pb, mov->reserved_moov_size);
 +    }
 +
+     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
          mov_write_mdat_tag(pb, mov);
  
      if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
Simple merge
Simple merge
Simple merge
Simple merge
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  #include <inttypes.h>
- #include "config.h"
  #include "libavutil/bswap.h"
+ #include "config.h"
  #include "rgb2rgb.h"
  #include "swscale.h"
  #include "swscale_internal.h"
@@@ -162,22 -172,21 +172,21 @@@ void rgb24to32(const uint8_t *src, uint
  
  void rgb16tobgr32(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
  #if HAVE_BIGENDIAN
          *d++ = 255;
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0xF800) >> 8;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
  #else
 -        *d++ = (bgr & 0xF800) >> 8;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
          *d++ = 255;
  #endif
      }
@@@ -204,16 -213,15 +213,15 @@@ void rgb12to15(const uint8_t *src, uint
  
  void rgb16to24(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
 -        *d++ = (bgr & 0xF800) >> 8;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
      }
  }
  
@@@ -241,22 -247,21 +247,21 @@@ void rgb16tobgr15(const uint8_t *src, u
  
  void rgb15tobgr32(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
  #if HAVE_BIGENDIAN
          *d++ = 255;
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x7C00) >> 7;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
  #else
 -        *d++ = (bgr & 0x7C00) >> 7;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
          *d++ = 255;
  #endif
      }
  
  void rgb15to24(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
 -        *d++ = (bgr & 0x7C00) >> 7;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
      }
  }
  
@@@ -314,12 -314,26 +314,14 @@@ void rgb12tobgr12(const uint8_t *src, u
      }
  }
  
 -void bgr8torgb8(const uint8_t *src, uint8_t *dst, int src_size)
 -{
 -    int i, num_pixels = src_size;
 -
 -    for (i = 0; i < num_pixels; i++) {
 -        register uint8_t rgb = src[i];
 -        unsigned r           = (rgb & 0x07);
 -        unsigned g           = (rgb & 0x38) >> 3;
 -        unsigned b           = (rgb & 0xC0) >> 6;
 -        dst[i]               = ((b << 1) & 0x07) | ((g & 0x07) << 3) | ((r & 0x03) << 6);
 -    }
 -}
  #define DEFINE_SHUFFLE_BYTES(a, b, c, d)                                \
- void shuffle_bytes_##a##b##c##d(const uint8_t *src, uint8_t *dst, int src_size) \
+ void shuffle_bytes_ ## a ## b ## c ## d(const uint8_t *src,             \
+                                         uint8_t *dst, int src_size)     \
  {                                                                       \
-     int i;                                                             \
+     int i;                                                              \
                                                                          \
-     for (i = 0; i < src_size; i+=4) {                                   \
+     for (i = 0; i < src_size; i += 4) {                                 \
          dst[i + 0] = src[i + a];                                        \
          dst[i + 1] = src[i + b];                                        \
          dst[i + 2] = src[i + c];                                        \
@@@ -227,54 -238,74 +238,53 @@@ static inline void rgb24to15_c(const ui
      }
  }
  
- static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size)
 -/*
 - * I use less accurate approximation here by simply left-shifting the input
 - * value and filling the low order bits with zeroes. This method improves PNG
 - * compression but this scheme cannot reproduce white exactly, since it does
 - * not generate an all-ones maximum value; the net effect is to darken the
 - * image slightly.
 - *
 - * The better method should be "left bit replication":
 - *
 - *  4 3 2 1 0
 - *  ---------
 - *  1 1 0 1 1
 - *
 - *  7 6 5 4 3  2 1 0
 - *  ----------------
 - *  1 1 0 1 1  1 1 0
 - *  |=======|  |===|
 - *      |      leftmost bits repeated to fill open bits
 - *      |
 - *  original bits
 - */
+ static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst,
+                                   int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t*)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
+         register uint16_t bgr = *s++;
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x7C00) >> 7;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
      }
  }
  
- static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size)
+ static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst,
+                                   int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = (uint8_t *)dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = (uint8_t *)dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
+         register uint16_t bgr = *s++;
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0xF800) >> 8;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
      }
  }
  
  static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t *)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
  #if HAVE_BIGENDIAN
          *d++ = 255;
 -        *d++ = (bgr & 0x7C00) >> 7;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  #else
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x3E0)>>2) | ((bgr&0x3E0)>>7);
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x3E0)  >> 2;
 -        *d++ = (bgr & 0x7C00) >> 7;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
 +        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
          *d++ = 255;
  #endif
      }
  
  static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, int src_size)
  {
-     const uint16_t *end;
-     uint8_t *d = dst;
-     const uint16_t *s = (const uint16_t*)src;
-     end = s + src_size/2;
+     uint8_t *d          = dst;
+     const uint16_t *s   = (const uint16_t *)src;
+     const uint16_t *end = s + src_size / 2;
      while (s < end) {
-         register uint16_t bgr;
-         bgr = *s++;
+         register uint16_t bgr = *s++;
  #if HAVE_BIGENDIAN
          *d++ = 255;
 -        *d++ = (bgr & 0xF800) >> 8;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0x1F)   << 3;
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
  #else
-         *d++ = ((bgr&0x1F)<<3) | ((bgr&0x1F)>>2);
-         *d++ = ((bgr&0x7E0)>>3) | ((bgr&0x7E0)>>9);
 -        *d++ = (bgr & 0x1F)   << 3;
 -        *d++ = (bgr & 0x7E0)  >> 3;
 -        *d++ = (bgr & 0xF800) >> 8;
++        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
++        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
 +        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
          *d++ = 255;
  #endif
      }
@@@ -637,24 -665,21 +644,24 @@@ void rgb24toyv12_c(const uint8_t *src, 
          ydst += lumStride;
          src  += srcStride;
  
-         if(y+1 == height)
++        if (y+1 == height)
 +            break;
 +
-         for (i=0; i<chromWidth; i++) {
-             unsigned int b = src[6*i+0];
-             unsigned int g = src[6*i+1];
-             unsigned int r = src[6*i+2];
+         for (i = 0; i < chromWidth; i++) {
+             unsigned int b = src[6 * i + 0];
+             unsigned int g = src[6 * i + 1];
+             unsigned int r = src[6 * i + 2];
  
-             unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
+             unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
  
-             ydst[2*i]     = Y;
+             ydst[2 * i] = Y;
  
-             b = src[6*i+3];
-             g = src[6*i+4];
-             r = src[6*i+5];
+             b = src[6 * i + 3];
+             g = src[6 * i + 4];
+             r = src[6 * i + 5];
  
-             Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
-             ydst[2*i+1]     = Y;
+             Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
+             ydst[2 * i + 1] = Y;
          }
          udst += chromStride;
          vdst += chromStride;
@@@ -32,9 -34,6 +34,7 @@@
  #include "rgb2rgb.h"
  #include "swscale.h"
  #include "swscale_internal.h"
- #include "libavutil/cpu.h"
- #include "libavutil/bswap.h"
 +#include "libavutil/pixdesc.h"
  
  extern const uint8_t dither_4x4_16[4][8];
  extern const uint8_t dither_8x8_32[8][8];
@@@ -62,102 -61,111 +62,111 @@@ const int *sws_getCoefficients(int colo
  #define LOADCHROMA(i)                               \
      U = pu[i];                                      \
      V = pv[i];                                      \
 -    r = (void *)c->table_rV[V];                     \
 -    g = (void *)(c->table_gU[U] + c->table_gV[V]);  \
 -    b = (void *)c->table_bU[U];
 +    r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM];                     \
 +    g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] + c->table_gV[V+YUVRGB_TABLE_HEADROOM]);  \
 +    b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM];
  
- #define PUTRGB(dst,src,i)            \
-     Y = src[2*i];                    \
-     dst[2*i  ] = r[Y] + g[Y] + b[Y]; \
-     Y = src[2*i+1];                  \
-     dst[2*i+1] = r[Y] + g[Y] + b[Y];
- #define PUTRGB24(dst,src,i)                                  \
-     Y = src[2*i];                                            \
-     dst[6*i+0] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \
-     Y = src[2*i+1];                                          \
-     dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y];
- #define PUTBGR24(dst,src,i)                                  \
-     Y = src[2*i];                                            \
-     dst[6*i+0] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \
-     Y = src[2*i+1];                                          \
-     dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y];
- #define PUTRGBA(dst,ysrc,asrc,i,s)                      \
-     Y = ysrc[2*i];                                      \
-     dst[2*i  ] = r[Y] + g[Y] + b[Y] + (asrc[2*i  ]<<s); \
-     Y = ysrc[2*i+1];                                    \
-     dst[2*i+1] = r[Y] + g[Y] + b[Y] + (asrc[2*i+1]<<s);
- #define PUTRGB48(dst,src,i)             \
-     Y = src[2*i];                       \
-     dst[12*i+ 0] = dst[12*i+ 1] = r[Y]; \
-     dst[12*i+ 2] = dst[12*i+ 3] = g[Y]; \
-     dst[12*i+ 4] = dst[12*i+ 5] = b[Y]; \
-     Y = src[2*i+1];                     \
-     dst[12*i+ 6] = dst[12*i+ 7] = r[Y]; \
-     dst[12*i+ 8] = dst[12*i+ 9] = g[Y]; \
-     dst[12*i+10] = dst[12*i+11] = b[Y];
- #define PUTBGR48(dst,src,i)             \
-     Y = src[2*i];                       \
-     dst[12*i+ 0] = dst[12*i+ 1] = b[Y]; \
-     dst[12*i+ 2] = dst[12*i+ 3] = g[Y]; \
-     dst[12*i+ 4] = dst[12*i+ 5] = r[Y]; \
-     Y = src[2*i+1];                     \
-     dst[12*i+ 6] = dst[12*i+ 7] = b[Y]; \
-     dst[12*i+ 8] = dst[12*i+ 9] = g[Y]; \
-     dst[12*i+10] = dst[12*i+11] = r[Y];
- #define YUV2RGBFUNC(func_name, dst_type, alpha) \
- static int func_name(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, \
-                      int srcSliceH, uint8_t* dst[], int dstStride[]) \
- {\
-     int y;\
- \
-     if (!alpha && c->srcFormat == PIX_FMT_YUV422P) {\
-         srcStride[1] *= 2;\
-         srcStride[2] *= 2;\
-     }\
-     for (y=0; y<srcSliceH; y+=2) {\
-         dst_type *dst_1 = (dst_type*)(dst[0] + (y+srcSliceY  )*dstStride[0]);\
-         dst_type *dst_2 = (dst_type*)(dst[0] + (y+srcSliceY+1)*dstStride[0]);\
-         dst_type av_unused *r, *b;\
-         dst_type *g;\
-         const uint8_t *py_1 = src[0] + y*srcStride[0];\
-         const uint8_t *py_2 = py_1 + srcStride[0];\
-         const uint8_t *pu = src[1] + (y>>1)*srcStride[1];\
-         const uint8_t *pv = src[2] + (y>>1)*srcStride[2];\
-         const uint8_t av_unused *pa_1, *pa_2;\
-         unsigned int h_size = c->dstW>>3;\
-         if (alpha) {\
-             pa_1 = src[3] + y*srcStride[3];\
-             pa_2 = pa_1 + srcStride[3];\
-         }\
-         while (h_size--) {\
-             int av_unused U, V;\
-             int Y;\
- #define ENDYUV2RGBLINE(dst_delta)\
-             pu += 4;\
-             pv += 4;\
-             py_1 += 8;\
-             py_2 += 8;\
-             dst_1 += dst_delta;\
-             dst_2 += dst_delta;\
-         }\
-         if (c->dstW & 4) {\
-             int av_unused Y, U, V;\
- #define ENDYUV2RGBFUNC()\
-         }\
-     }\
-     return srcSliceH;\
- }
+ #define PUTRGB(dst, src, i)                         \
+     Y              = src[2 * i];                    \
+     dst[2 * i]     = r[Y] + g[Y] + b[Y];            \
+     Y              = src[2 * i + 1];                \
+     dst[2 * i + 1] = r[Y] + g[Y] + b[Y];
+ #define PUTRGB24(dst, src, i)                       \
+     Y              = src[2 * i];                    \
+     dst[6 * i + 0] = r[Y];                          \
+     dst[6 * i + 1] = g[Y];                          \
+     dst[6 * i + 2] = b[Y];                          \
+     Y              = src[2 * i + 1];                \
+     dst[6 * i + 3] = r[Y];                          \
+     dst[6 * i + 4] = g[Y];                          \
+     dst[6 * i + 5] = b[Y];
+ #define PUTBGR24(dst, src, i)                       \
+     Y              = src[2 * i];                    \
+     dst[6 * i + 0] = b[Y];                          \
+     dst[6 * i + 1] = g[Y];                          \
+     dst[6 * i + 2] = r[Y];                          \
+     Y              = src[2 * i + 1];                \
+     dst[6 * i + 3] = b[Y];                          \
+     dst[6 * i + 4] = g[Y];                          \
+     dst[6 * i + 5] = r[Y];
+ #define PUTRGBA(dst, ysrc, asrc, i, s)                                  \
+     Y              = ysrc[2 * i];                                       \
+     dst[2 * i]     = r[Y] + g[Y] + b[Y] + (asrc[2 * i]     << s);       \
+     Y              = ysrc[2 * i + 1];                                   \
+     dst[2 * i + 1] = r[Y] + g[Y] + b[Y] + (asrc[2 * i + 1] << s);
+ #define PUTRGB48(dst, src, i)                       \
+     Y                = src[ 2 * i];                 \
+     dst[12 * i +  0] = dst[12 * i +  1] = r[Y];     \
+     dst[12 * i +  2] = dst[12 * i +  3] = g[Y];     \
+     dst[12 * i +  4] = dst[12 * i +  5] = b[Y];     \
+     Y                = src[ 2 * i + 1];             \
+     dst[12 * i +  6] = dst[12 * i +  7] = r[Y];     \
+     dst[12 * i +  8] = dst[12 * i +  9] = g[Y];     \
+     dst[12 * i + 10] = dst[12 * i + 11] = b[Y];
+ #define PUTBGR48(dst, src, i)                       \
+     Y                = src[2 * i];                  \
+     dst[12 * i +  0] = dst[12 * i +  1] = b[Y];     \
+     dst[12 * i +  2] = dst[12 * i +  3] = g[Y];     \
+     dst[12 * i +  4] = dst[12 * i +  5] = r[Y];     \
+     Y                = src[2  * i +  1];            \
+     dst[12 * i +  6] = dst[12 * i +  7] = b[Y];     \
+     dst[12 * i +  8] = dst[12 * i +  9] = g[Y];     \
+     dst[12 * i + 10] = dst[12 * i + 11] = r[Y];
+ #define YUV2RGBFUNC(func_name, dst_type, alpha)                             \
+     static int func_name(SwsContext *c, const uint8_t *src[],               \
+                          int srcStride[], int srcSliceY, int srcSliceH,     \
+                          uint8_t *dst[], int dstStride[])                   \
+     {                                                                       \
+         int y;                                                              \
+                                                                             \
+         if (!alpha && c->srcFormat == PIX_FMT_YUV422P) {                    \
+             srcStride[1] *= 2;                                              \
+             srcStride[2] *= 2;                                              \
+         }                                                                   \
+         for (y = 0; y < srcSliceH; y += 2) {                                \
+             dst_type *dst_1 =                                               \
+                 (dst_type *)(dst[0] + (y + srcSliceY)     * dstStride[0]);  \
+             dst_type *dst_2 =                                               \
+                 (dst_type *)(dst[0] + (y + srcSliceY + 1) * dstStride[0]);  \
+             dst_type av_unused *r, *g, *b;                                  \
+             const uint8_t *py_1 = src[0] +  y       * srcStride[0];         \
+             const uint8_t *py_2 = py_1   +            srcStride[0];         \
+             const uint8_t *pu   = src[1] + (y >> 1) * srcStride[1];         \
+             const uint8_t *pv   = src[2] + (y >> 1) * srcStride[2];         \
+             const uint8_t av_unused *pa_1, *pa_2;                           \
+             unsigned int h_size = c->dstW >> 3;                             \
+             if (alpha) {                                                    \
+                 pa_1 = src[3] + y * srcStride[3];                           \
+                 pa_2 = pa_1   +     srcStride[3];                           \
+             }                                                               \
+             while (h_size--) {                                              \
+                 int av_unused U, V, Y;                                      \
+ #define ENDYUV2RGBLINE(dst_delta)                   \
+     pu    += 4;                                     \
+     pv    += 4;                                     \
+     py_1  += 8;                                     \
+     py_2  += 8;                                     \
+     dst_1 += dst_delta;                             \
+     dst_2 += dst_delta;                             \
+     }                                               \
+     if (c->dstW & 4) {                              \
+         int av_unused Y, U, V;                      \
+ #define ENDYUV2RGBFUNC()                            \
+             }                                       \
+         }                                           \
+         return srcSliceH;                           \
+     }
  
- #define CLOSEYUV2RGBFUNC(dst_delta)\
-     ENDYUV2RGBLINE(dst_delta)\
+ #define CLOSEYUV2RGBFUNC(dst_delta)                 \
+     ENDYUV2RGBLINE(dst_delta)                       \
      ENDYUV2RGBFUNC()
  
  YUV2RGBFUNC(yuv2rgb_c_48, uint8_t, 0)
@@@ -477,30 -503,30 +504,30 @@@ YUV2RGBFUNC(yuv2rgb_c_4b_ordered_dither
  CLOSEYUV2RGBFUNC(8)
  
  YUV2RGBFUNC(yuv2rgb_c_1_ordered_dither, uint8_t, 0)
-         const uint8_t *d128 = dither_8x8_220[y&7];
-         char out_1 = 0, out_2 = 0;
-         g= c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM];
+     const uint8_t *d128 = dither_8x8_220[y & 7];
+     char out_1 = 0, out_2 = 0;
 -    g = c->table_gU[128] + c->table_gV[128];
++    g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM];
  
- #define PUTRGB1(out,src,i,o)    \
-     Y = src[2*i];               \
-     out+= out + g[Y+d128[0+o]]; \
-     Y = src[2*i+1];             \
-     out+= out + g[Y+d128[1+o]];
+ #define PUTRGB1(out, src, i, o)                     \
+     Y    = src[2 * i];                              \
+     out += out + g[Y + d128[0 + o]];                \
+     Y    = src[2 * i + 1];                          \
+     out += out + g[Y + d128[1 + o]];
  
-     PUTRGB1(out_1,py_1,0,0);
-     PUTRGB1(out_2,py_2,0,0+8);
+     PUTRGB1(out_1, py_1, 0, 0);
+     PUTRGB1(out_2, py_2, 0, 0 + 8);
  
-     PUTRGB1(out_2,py_2,1,2+8);
-     PUTRGB1(out_1,py_1,1,2);
+     PUTRGB1(out_2, py_2, 1, 2 + 8);
+     PUTRGB1(out_1, py_1, 1, 2);
  
-     PUTRGB1(out_1,py_1,2,4);
-     PUTRGB1(out_2,py_2,2,4+8);
+     PUTRGB1(out_1, py_1, 2, 4);
+     PUTRGB1(out_2, py_2, 2, 4 + 8);
  
-     PUTRGB1(out_2,py_2,3,6+8);
-     PUTRGB1(out_1,py_1,3,6);
+     PUTRGB1(out_2, py_2, 3, 6 + 8);
+     PUTRGB1(out_1, py_1, 3, 6);
  
-     dst_1[0]= out_1;
-     dst_2[0]= out_2;
+     dst_1[0] = out_1;
+     dst_2[0] = out_2;
  CLOSEYUV2RGBFUNC(1)
  
  SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c)
      if (t)
          return t;
  
-     av_log(c, AV_LOG_WARNING, "No accelerated colorspace conversion found from %s to %s.\n",
+     av_log(c, AV_LOG_WARNING,
+            "No accelerated colorspace conversion found from %s to %s.\n",
 -           sws_format_name(c->srcFormat), sws_format_name(c->dstFormat));
 +           av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
  
      switch (c->dstFormat) {
      case PIX_FMT_BGR48BE:
-     case PIX_FMT_BGR48LE:    return yuv2rgb_c_bgr48;
+     case PIX_FMT_BGR48LE:
+         return yuv2rgb_c_bgr48;
      case PIX_FMT_RGB48BE:
-     case PIX_FMT_RGB48LE:    return yuv2rgb_c_48;
+     case PIX_FMT_RGB48LE:
+         return yuv2rgb_c_48;
      case PIX_FMT_ARGB:
-     case PIX_FMT_ABGR:       if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) return yuva2argb_c;
+     case PIX_FMT_ABGR:
 -        if (CONFIG_SWSCALE_ALPHA && c->srcFormat == PIX_FMT_YUVA420P)
++        if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat))
+             return yuva2argb_c;
      case PIX_FMT_RGBA:
-     case PIX_FMT_BGRA:       return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva2rgba_c : yuv2rgb_c_32;
-     case PIX_FMT_RGB24:      return yuv2rgb_c_24_rgb;
-     case PIX_FMT_BGR24:      return yuv2rgb_c_24_bgr;
+     case PIX_FMT_BGRA:
 -        if (CONFIG_SWSCALE_ALPHA && c->srcFormat == PIX_FMT_YUVA420P)
 -            return yuva2rgba_c;
 -        else
 -            return yuv2rgb_c_32;
++        return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva2rgba_c : yuv2rgb_c_32;
+     case PIX_FMT_RGB24:
+         return yuv2rgb_c_24_rgb;
+     case PIX_FMT_BGR24:
+         return yuv2rgb_c_24_bgr;
      case PIX_FMT_RGB565:
      case PIX_FMT_BGR565:
      case PIX_FMT_RGB555:
      return NULL;
  }
  
- static void fill_table(uint8_t* table[256 + 2*YUVRGB_TABLE_HEADROOM], const int elemsize, const int inc, void *y_tab)
 -static void fill_table(uint8_t *table[256], const int elemsize,
++static void fill_table(uint8_t* table[256 + 2*YUVRGB_TABLE_HEADROOM], const int elemsize,
+                        const int inc, void *y_tab)
  {
      int i;
 -    int64_t cb       = 0;
      uint8_t *y_table = y_tab;
  
      y_table -= elemsize * (inc >> 9);
      }
  }
  
 -static void fill_gv_table(int table[256], const int elemsize, const int inc)
 +static void fill_gv_table(int table[256 + 2*YUVRGB_TABLE_HEADROOM], const int elemsize, const int inc)
  {
      int i;
-     int off = -(inc >> 9);
 -    int64_t cb = 0;
+     int off    = -(inc >> 9);
  
 -    for (i = 0; i < 256; i++) {
 +    for (i = 0; i < 256 + 2*YUVRGB_TABLE_HEADROOM; i++) {
 +        int64_t cb = av_clip(i-YUVRGB_TABLE_HEADROOM, 0, 255)*inc;
          table[i] = elemsize * (off + (cb >> 16));
 -        cb      += inc;
      }
  }