]> git.sesse.net Git - ffmpeg/commitdiff
Merge commit 'd58dd4b5b5d31cfd4092e38a5f2c894eee2ab078'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Sep 2012 12:09:09 +0000 (14:09 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Sep 2012 12:09:09 +0000 (14:09 +0200)
* commit 'd58dd4b5b5d31cfd4092e38a5f2c894eee2ab078':
  avopt: Store defaults for AV_OPT_TYPE_FLAGS in the i64 union member

Conflicts:
libavcodec/libvpxenc.c
libavcodec/options_table.h
libavfilter/vf_drawtext.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
15 files changed:
1  2 
libavcodec/libvpxenc.c
libavcodec/mpegvideo.h
libavcodec/options_table.h
libavdevice/libcdio.c
libavfilter/vf_drawtext.c
libavformat/movenc.c
libavformat/mpegtsenc.c
libavformat/options_table.h
libavformat/rtpenc.h
libavformat/rtsp.c
libavformat/spdifenc.c
libavutil/cpu.c
libavutil/opt.c
libswresample/swresample.c
libswscale/options.c

diff --combined libavcodec/libvpxenc.c
index 466546729ff0237efd1af3e5d8d0bc9f6ded9834,dc3b2ce8d1924b021478e3c8fba5f1cd5e50ef59..2db3fff804a80649bf0244768069e5479008208f
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (c) 2010, Google, Inc.
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
@@@ -30,7 -30,6 +30,7 @@@
  
  #include "avcodec.h"
  #include "internal.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/base64.h"
  #include "libavutil/common.h"
  #include "libavutil/mathematics.h"
@@@ -56,27 -55,15 +56,27 @@@ typedef struct VP8EncoderContext 
      struct vpx_codec_ctx encoder;
      struct vpx_image rawimg;
      struct vpx_fixed_buf twopass_stats;
 -    unsigned long deadline; //i.e., RT/GOOD/BEST
 +    int deadline; //i.e., RT/GOOD/BEST
      struct FrameListData *coded_frame_list;
 +
      int cpu_used;
 +    /**
 +     * VP8 specific flags, see VP8F_* below.
 +     */
 +    int flags;
 +#define VP8F_ERROR_RESILIENT 0x00000001 ///< Enable measures appropriate for streaming over lossy links
 +#define VP8F_AUTO_ALT_REF    0x00000002 ///< Enable automatic alternate reference frame generation
 +
      int auto_alt_ref;
 +
      int arnr_max_frames;
      int arnr_strength;
      int arnr_type;
 +
      int lag_in_frames;
      int error_resilient;
 +    int crf;
 +    int max_intra_rate;
  } VP8Context;
  
  /** String mappings for enum vp8e_enc_control_id */
@@@ -97,8 -84,6 +97,8 @@@ static const char *const ctlidstr[] = 
      [VP8E_SET_ARNR_MAXFRAMES]    = "VP8E_SET_ARNR_MAXFRAMES",
      [VP8E_SET_ARNR_STRENGTH]     = "VP8E_SET_ARNR_STRENGTH",
      [VP8E_SET_ARNR_TYPE]         = "VP8E_SET_ARNR_TYPE",
 +    [VP8E_SET_CQ_LEVEL]          = "VP8E_SET_CQ_LEVEL",
 +    [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT",
  };
  
  static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
@@@ -242,13 -227,6 +242,13 @@@ static av_cold int vp8_init(AVCodecCont
                 vpx_codec_err_to_string(res));
          return AVERROR(EINVAL);
      }
 +
 +    if(!avctx->bit_rate)
 +        if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
 +            av_log( avctx, AV_LOG_ERROR, "Rate control parameters set without a bitrate\n");
 +            return AVERROR(EINVAL);
 +        }
 +
      dump_enc_cfg(avctx, &enccfg);
  
      enccfg.g_w            = avctx->width;
      enccfg.g_timebase.num = avctx->time_base.num;
      enccfg.g_timebase.den = avctx->time_base.den;
      enccfg.g_threads      = avctx->thread_count;
 -
 -    if (ctx->lag_in_frames >= 0)
 -        enccfg.g_lag_in_frames = ctx->lag_in_frames;
 +    enccfg.g_lag_in_frames= ctx->lag_in_frames;
  
      if (avctx->flags & CODEC_FLAG_PASS1)
          enccfg.g_pass = VPX_RC_FIRST_PASS;
      else
          enccfg.g_pass = VPX_RC_ONE_PASS;
  
 -    if (!avctx->bit_rate)
 -        avctx->bit_rate = enccfg.rc_target_bitrate * 1000;
 -    else
 -        enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
 -                                              AV_ROUND_NEAR_INF);
 -
      if (avctx->rc_min_rate == avctx->rc_max_rate &&
 -        avctx->rc_min_rate == avctx->bit_rate)
 +        avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate)
          enccfg.rc_end_usage = VPX_CBR;
 +    else if (ctx->crf)
 +        enccfg.rc_end_usage = VPX_CQ;
 +
 +    if (avctx->bit_rate) {
 +        enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
 +                                                AV_ROUND_NEAR_INF);
 +    } else {
 +        if (enccfg.rc_end_usage == VPX_CQ) {
 +            enccfg.rc_target_bitrate = 1000000;
 +        } else {
 +            avctx->bit_rate = enccfg.rc_target_bitrate * 1000;
 +            av_log(avctx, AV_LOG_WARNING,
 +                   "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n",
 +                   enccfg.rc_target_bitrate);
 +        }
 +    }
  
      if (avctx->qmin > 0)
          enccfg.rc_min_quantizer = avctx->qmin;
  
      //0-100 (0 => CBR, 100 => VBR)
      enccfg.rc_2pass_vbr_bias_pct           = round(avctx->qcompress * 100);
 -    enccfg.rc_2pass_vbr_minsection_pct     =
 -        avctx->rc_min_rate * 100LL / avctx->bit_rate;
 +    if (avctx->bit_rate)
 +        enccfg.rc_2pass_vbr_minsection_pct     =
 +            avctx->rc_min_rate * 100LL / avctx->bit_rate;
      if (avctx->rc_max_rate)
          enccfg.rc_2pass_vbr_maxsection_pct =
              avctx->rc_max_rate * 100LL / avctx->bit_rate;
          enccfg.rc_buf_initial_sz =
              avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
      enccfg.rc_buf_optimal_sz     = enccfg.rc_buf_sz * 5 / 6;
 +    enccfg.rc_undershoot_pct     = round(avctx->rc_buffer_aggressivity * 100);
  
      //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO
      if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
     if (avctx->profile != FF_PROFILE_UNKNOWN)
         enccfg.g_profile = avctx->profile;
  
 -    enccfg.g_error_resilient = ctx->error_resilient;
 +    enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT;
  
      dump_enc_cfg(avctx, &enccfg);
      /* Construct Encoder Context */
      av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n");
      if (ctx->cpu_used != INT_MIN)
          codecctl_int(avctx, VP8E_SET_CPUUSED,          ctx->cpu_used);
 +    if (ctx->flags & VP8F_AUTO_ALT_REF)
 +        ctx->auto_alt_ref = 1;
      if (ctx->auto_alt_ref >= 0)
          codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref);
      if (ctx->arnr_max_frames >= 0)
      codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction);
      codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS,  av_log2(avctx->slices));
      codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD,  avctx->mb_threshold);
 +    codecctl_int(avctx, VP8E_SET_CQ_LEVEL,          ctx->crf);
 +    if (ctx->max_intra_rate >= 0)
 +        codecctl_int(avctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, ctx->max_intra_rate);
 +
 +    av_log(avctx, AV_LOG_DEBUG, "Using deadline: %d\n", ctx->deadline);
  
      //provide dummy value to initialize wrapper, values will be updated each _encode()
      vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1,
@@@ -416,7 -377,7 +416,7 @@@ static inline void cx_pktcpy(struct Fra
  static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
                        AVPacket *pkt, AVFrame *coded_frame)
  {
 -    int ret = ff_alloc_packet(pkt, cx_frame->sz);
 +    int ret = ff_alloc_packet2(avctx, pkt, cx_frame->sz);
      if (ret >= 0) {
          memcpy(pkt->data, cx_frame->buf, pkt->size);
          pkt->pts = pkt->dts    = cx_frame->pts;
          } else
              coded_frame->pict_type = AV_PICTURE_TYPE_P;
      } else {
 -        av_log(avctx, AV_LOG_ERROR,
 -               "Error getting output packet of size %zu.\n", cx_frame->sz);
          return ret;
      }
      return pkt->size;
@@@ -470,7 -433,7 +470,7 @@@ static int queue_frames(AVCodecContext 
  
                  /* avoid storing the frame when the list is empty and we haven't yet
                     provided a frame for output */
 -                assert(!ctx->coded_frame_list);
 +                av_assert0(!ctx->coded_frame_list);
                  cx_pktcpy(&cx_frame, pkt);
                  size = storeframe(avctx, &cx_frame, pkt_out, coded_frame);
                  if (size < 0)
              break;
          case VPX_CODEC_STATS_PKT: {
              struct vpx_fixed_buf *stats = &ctx->twopass_stats;
 -            stats->buf = av_realloc(stats->buf,
 -                                    stats->sz + pkt->data.twopass_stats.sz);
 +            stats->buf = av_realloc_f(stats->buf, 1,
 +                                      stats->sz + pkt->data.twopass_stats.sz);
              if (!stats->buf) {
                  av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n");
                  return AVERROR(ENOMEM);
@@@ -526,7 -489,6 +526,7 @@@ static int vp8_encode(AVCodecContext *a
      VP8Context *ctx = avctx->priv_data;
      struct vpx_image *rawimg = NULL;
      int64_t timestamp = 0;
 +    long flags = 0;
      int res, coded_size;
  
      if (frame) {
          rawimg->stride[VPX_PLANE_U] = frame->linesize[1];
          rawimg->stride[VPX_PLANE_V] = frame->linesize[2];
          timestamp                   = frame->pts;
 +        flags                       = frame->pict_type == AV_PICTURE_TYPE_I ? VPX_EFLAG_FORCE_KF : 0;
      }
  
      res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp,
 -                           avctx->ticks_per_frame, 0, ctx->deadline);
 +                           avctx->ticks_per_frame, flags, ctx->deadline);
      if (res != VPX_CODEC_OK) {
          log_encoder_error(avctx, "Error encoding frame");
          return AVERROR_INVALIDDATA;
@@@ -584,8 -545,7 +584,8 @@@ static const AVOption options[] = 
      { "best",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"},
      { "good",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"},
      { "realtime",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME},     0, 0, VE, "quality"},
-     { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, VE, "er"},
+     { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"},
 +    { "max-intra-rate",  "Maximum I-frame bitrate (pct) 0=unlimited",  OFFSET(max_intra_rate),  AV_OPT_TYPE_INT,  {-1}, -1,      INT_MAX, VE},
  #ifdef VPX_ERROR_RESILIENT_DEFAULT
      { "default",         "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
      { "partitions",      "The frame partitions are independently decodable "
                           "though earlier partitions have been lost. Note that intra predicition"
                           " is still done over the partition boundary.",       0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
  #endif
 -    { NULL }
 +{"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.dbl = 3}, -16, 16, VE},
 +{"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.dbl = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
 +{"vp8flags", "", offsetof(VP8Context, flags), FF_OPT_TYPE_FLAGS, {.dbl = 0}, 0, UINT_MAX, VE, "flags"},
 +{"error_resilient", "enable error resilience", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_ERROR_RESILIENT}, INT_MIN, INT_MAX, VE, "flags"},
 +{"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_AUTO_ALT_REF}, INT_MIN, INT_MAX, VE, "flags"},
 +{"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 15, VE},
 +{"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.dbl = 3}, 0, 6, VE},
 +{"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.dbl = 3}, 1, 3, VE},
 +{"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.dbl = 25}, 0, 25, VE},
 +{"crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 63, VE},
 +{NULL}
  };
  
  static const AVClass class = {
diff --combined libavcodec/mpegvideo.h
index 9e2b02587a09c8fe44adb3de5ca5a304a0b22bfe,93adf05add7e5219c0ef244db77156f76bede874..21b2b5c7cae9027f7de9fc54b6640eca6d9280b6
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
   * Copyright (c) 2002-2004 Michael Niedermayer
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
@@@ -36,7 -36,6 +36,7 @@@
  #include "parser.h"
  #include "mpeg12data.h"
  #include "rl.h"
 +#include "libavutil/timecode.h"
  
  #include "libavutil/opt.h"
  
@@@ -58,7 -57,7 +58,7 @@@ enum OutputFormat 
  #define MAX_FCODE 7
  #define MAX_MV 2048
  
 -#define MAX_THREADS 16
 +#define MAX_THREADS 32
  
  #define MAX_PICTURE_COUNT 32
  
@@@ -127,11 -126,10 +127,11 @@@ typedef struct Picture
      int pic_id;                 /**< h264 pic_num (short -> no wrap version of pic_num,
                                       pic_num & max_pic_num; long -> long_pic_num) */
      int long_ref;               ///< 1->long term reference 0->short term reference
 -    int ref_poc[2][2][32];      ///< h264 POCs of the frames used as reference (FIXME need per slice)
 +    int ref_poc[2][2][32];      ///< h264 POCs of the frames/fields used as reference (FIXME need per slice)
      int ref_count[2][2];        ///< number of entries in ref_poc              (FIXME need per slice)
      int mbaff;                  ///< h264 1 -> MBAFF frame 0-> not MBAFF
      int field_picture;          ///< whether or not the picture was encoded in separate fields
 +    int sync;                   ///< has been decoded after a keyframe
  
      int mb_var_sum;             ///< sum of MB variance for current frame
      int mc_mb_var_sum;          ///< motion compensated MB variance for current frame
@@@ -340,7 -338,6 +340,7 @@@ typedef struct MpegEncContext 
      int *lambda_table;
      int adaptive_quant;         ///< use adaptive quantization
      int dquant;                 ///< qscale difference to prev qscale
 +    int closed_gop;             ///< MPEG1/2 GOP is closed
      int pict_type;              ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ...
      int last_pict_type; //FIXME removes
      int last_non_b_pict_type;   ///< used for mpeg4 gmc b-frames & ratecontrol
  
      /** precomputed matrix (combine qscale and DCT renorm) */
      int (*q_intra_matrix)[64];
 +    int (*q_chroma_intra_matrix)[64];
      int (*q_inter_matrix)[64];
      /** identical to the above but for MMX & these are not permutated, second 64 entries are bias*/
      uint16_t (*q_intra_matrix16)[2][64];
 +    uint16_t (*q_chroma_intra_matrix16)[2][64];
      uint16_t (*q_inter_matrix16)[2][64];
  
      /* noise reduction */
      struct MJpegContext *mjpeg_ctx;
      int mjpeg_vsample[3];       ///< vertical sampling factors, default = {2, 1, 1}
      int mjpeg_hsample[3];       ///< horizontal sampling factors, default = {2, 1, 1}
 +    int esc_pos;
  
      /* MSMPEG4 specific */
      int mv_table_index;
      /* RTP specific */
      int rtp_mode;
  
 +    char *tc_opt_str;        ///< timecode option string
 +    AVTimecode tc;           ///< timecode context
 +
      uint8_t *ptr_lastgob;
      int swap_uv;             //vcr2 codec is an MPEG-2 variant with U and V swapped
      DCTELEM (*pblocks[12])[64];
  #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x)
  #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
  #define FF_MPV_COMMON_OPTS \
- { "mpv_flags",      "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+ { "mpv_flags",      "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\
  { "skip_rd",        "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_SKIP_RD },    0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
  { "strict_gop",     "Strictly enforce gop size",             0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
  { "qp_rd",          "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_QP_RD },  0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
@@@ -764,7 -755,7 +764,7 @@@ void ff_MPV_frame_end(MpegEncContext *s
  int ff_MPV_encode_init(AVCodecContext *avctx);
  int ff_MPV_encode_end(AVCodecContext *avctx);
  int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
 -                          const AVFrame *frame, int *got_packet);
 +                          AVFrame *frame, int *got_packet);
  void ff_MPV_encode_init_x86(MpegEncContext *s);
  void ff_MPV_common_init_x86(MpegEncContext *s);
  void ff_MPV_common_init_axp(MpegEncContext *s);
@@@ -816,7 -807,7 +816,7 @@@ extern const enum PixelFormat ff_pixfmt
  extern const enum PixelFormat ff_hwaccel_pixfmt_list_420[];
  
  static inline void ff_update_block_index(MpegEncContext *s){
 -    const int block_size = 8;
 +    const int block_size= 8 >> s->avctx->lowres;
  
      s->block_index[0]+=2;
      s->block_index[1]+=2;
index f2011f988a78541598e875393742f63a9384a0b5,5961f2bcc4faf565702f39f572618905a6492dec..aa7bf80952297cff667133108ef22229901e1377
@@@ -1,21 -1,19 +1,21 @@@
  /*
 + * Copyright (c) 2001 Fabrice Bellard
 + * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
  #define AV_CODEC_DEFAULT_BITRATE 200*1000
  
  static const AVOption options[]={
 -{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.dbl = AV_CODEC_DEFAULT_BITRATE }, INT_MIN, INT_MAX, V|A|E},
 +{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.dbl = AV_CODEC_DEFAULT_BITRATE }, INT_MIN, INT_MAX, A|V|E},
 +{"ab", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.dbl = 128*1000 }, INT_MIN, INT_MAX, A|E},
  {"bt", "Set video bitrate tolerance (in bits/s). In 1-pass mode, bitrate tolerance specifies how far "
         "ratecontrol is willing to deviate from the target average bitrate value. This is not related "
         "to min/max bitrate. Lowering tolerance too much has an adverse effect on quality.",
         OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.dbl = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},
- {"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"},
 -{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|E|D, "flags"},
++{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"},
  {"mv4", "use four motion vector by macroblock (mpeg4)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"},
  {"qpel", "use 1/4 pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"},
  {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},
@@@ -79,8 -76,6 +79,8 @@@
  #endif
  {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
  {"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"},
 +{"chunks", "Frame data might be split into multiple chunks", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_CHUNKS }, INT_MIN, INT_MAX, V|D, "flags2"},
 +{"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"},
  #if FF_API_SUB_ID
  {"sub_id", NULL, OFFSET(sub_id), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  #endif
            OFFSET(qcompress), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -FLT_MAX, FLT_MAX, V|E},
  {"qblur", "video quantizer scale blur (VBR)", OFFSET(qblur), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -1, FLT_MAX, V|E},
  {"qmin", "min video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.dbl = 2 }, -1, 69, V|E},
 -{"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.dbl = 31 }, -1, 69, V|E},
 +{"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.dbl = 31 }, -1, 1024, V|E},
  {"qdiff", "max difference between the quantizer scale (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.dbl = 3 }, INT_MIN, INT_MAX, V|E},
  {"bf", "use 'frames' B frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, -1, FF_MAX_B_FRAMES, V|E},
  {"b_qfactor", "qp factor between p and b frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
  {"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"bug", "workaround not auto detected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.dbl = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
+ {"bug", "workaround not auto detected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
  {"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
  {"old_msmpeg4", "some old lavc generated msmpeg4v3 files (no autodetection)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_OLD_MSMPEG4 }, INT_MIN, INT_MAX, V|D, "bug"},
  {"xvid_ilace", "Xvid interlacing bug (autodetected if fourcc==XVIX)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_XVID_ILACE }, INT_MIN, INT_MAX, V|D, "bug"},
  {"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
  {"experimental", "allow non standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
  {"b_qoffset", "qp offset between P and B frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
- {"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
+ {"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 -{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, V|D, "err_detect"},
 +{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"careful",    "consider things that violate the spec and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
  {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"int", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_INT }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLE }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"simplemmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
 +{"libmpeg2mmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_LIBMPEG2MMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"mmi", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_MMI }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"arm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"xvidmmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVIDMMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
  {"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"},
  {"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.dbl = 3 }, INT_MIN, INT_MAX, V|D, "ec"},
+ {"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"},
  {"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"},
  {"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"},
  {"bits_per_coded_sample", NULL, OFFSET(bits_per_coded_sample), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"plane", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_PLANE }, INT_MIN, INT_MAX, V|E, "pred"},
  {"median", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_MEDIAN }, INT_MIN, INT_MAX, V|E, "pred"},
  {"aspect", "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E},
- {"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"},
+ {"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"},
  {"pict", "picture info", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PICT_INFO }, INT_MIN, INT_MAX, V|D, "debug"},
  {"rc", "rate control", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_RC }, INT_MIN, INT_MAX, V|E, "debug"},
  {"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BITSTREAM }, INT_MIN, INT_MAX, V|D, "debug"},
  #if FF_API_INTER_THRESHOLD
  {"inter_threshold", NULL, OFFSET(inter_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  #endif
- {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"},
+ {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"},
  {"error", NULL, OFFSET(error_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  #if FF_API_MPV_GLOBAL_OPTS
  {"qns", "deprecated, use mpegvideo private options instead", OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"},
  {"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.dbl = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
 +{"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|A|D},
  {"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"all"             , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL     }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.dbl = 1 }, 0, 4, V|E},
  {"brd_scale", "downscales frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, 10, V|E},
 -{"keyint_min", "minimum interval between IDR-frames (x264)", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.dbl = 25 }, INT_MIN, INT_MAX, V|E},
 -{"refs", "reference frames to consider for motion compensation (Snow)", OFFSET(refs), AV_OPT_TYPE_INT, {.dbl = 1 }, INT_MIN, INT_MAX, V|E},
 +{"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.dbl = 25 }, INT_MIN, INT_MAX, V|E},
 +{"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.dbl = 1 }, INT_MIN, INT_MAX, V|E},
  {"chromaoffset", "chroma qp offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
  #if FF_API_MPV_GLOBAL_OPTS
  {"chroma_sample_location", NULL, OFFSET(chroma_sample_location), AV_OPT_TYPE_INT, {.dbl = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, V|E|D},
  {"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.dbl = 0 }, INT_MIN, INT_MAX },
  {"slices", "number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|E},
- {"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.dbl = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|E|D, "thread_type"},
+ {"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|E|D, "thread_type"},
  {"slice", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_SLICE }, INT_MIN, INT_MAX, V|E|D, "thread_type"},
  {"frame", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_FRAME }, INT_MIN, INT_MAX, V|E|D, "thread_type"},
  {"audio_service_type", "audio service type", OFFSET(audio_service_type), AV_OPT_TYPE_INT, {.dbl = AV_AUDIO_SERVICE_TYPE_MAIN }, 0, AV_AUDIO_SERVICE_TYPE_NB-1, A|E, "audio_service_type"},
  {"em", "Emergency",          0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EMERGENCY },         INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"vo", "Voice Over",         0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VOICE_OVER },        INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"ka", "Karaoke",            0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE },           INT_MIN, INT_MAX, A|E, "audio_service_type"},
 -{"request_sample_fmt", NULL, OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.dbl = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
 +{"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.dbl = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
  {"u8" , "8-bit unsigned integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8  }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"s16", "16-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"s32", "32-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"s32p", "32-bit signed integer planar",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32P }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"fltp", "32-bit float planar",           0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLTP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"dblp", "64-bit double planar",          0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBLP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 +{"pkt_timebase", NULL, OFFSET(pkt_timebase), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0},
  {NULL},
  };
  
diff --combined libavdevice/libcdio.c
index 0c3060ac522e11c86d1de2461f81d7e48ea28bd1,bf67a32a7f54b698fd259e527135c46025897067..e3109193ef12f326e05ebd75bf3ba35944b860a8
@@@ -37,7 -37,7 +37,7 @@@
  #undef free
  
  typedef struct CDIOContext {
 -    AVClass             *class;
 +    const AVClass       *class;
      cdrom_drive_t       *drive;
      cdrom_paranoia_t *paranoia;
      int32_t last_sector;
@@@ -161,7 -161,7 +161,7 @@@ static int read_seek(AVFormatContext *c
  #define DEC AV_OPT_FLAG_DECODING_PARAM
  static const AVOption options[] = {
      { "speed",              "Drive reading speed.", OFFSET(speed),         AV_OPT_TYPE_INT,   { 0 }, 0,       INT_MAX, DEC },
-     { "paranoia_mode",      "Error recovery mode.", OFFSET(paranoia_mode), AV_OPT_TYPE_FLAGS, { 0 }, INT_MIN, INT_MAX, DEC, "paranoia_mode" },
+     { "paranoia_mode",      "Error recovery mode.", OFFSET(paranoia_mode), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, DEC, "paranoia_mode" },
          { "verify",         "Verify data integrity in overlap area", 0,    AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_VERIFY },    0, 0, DEC, "paranoia_mode" },
          { "overlap",        "Perform overlapped reads.",             0,    AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_OVERLAP },   0, 0, DEC, "paranoia_mode" },
          { "neverskip",      "Do not skip failed reads.",             0,    AV_OPT_TYPE_CONST, { .i64 = PARANOIA_MODE_NEVERSKIP }, 0, 0, DEC, "paranoia_mode" },
index 291874de70beeb54b4a300b64adc1abe7f2ad93a,06ecd712cfdd2ba99b9983f18293871738de93b8..ac5c999139ccd40f4bbd5f44ea67deb5a76a9fdc
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
   * Copyright (c) 2003 Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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 <sys/time.h>
  #include <time.h>
  
 -#include "libavutil/colorspace.h"
 +#include "config.h"
 +#include "libavutil/avstring.h"
  #include "libavutil/common.h"
  #include "libavutil/file.h"
  #include "libavutil/eval.h"
  #include "libavutil/opt.h"
 -#include "libavutil/mathematics.h"
  #include "libavutil/random_seed.h"
  #include "libavutil/parseutils.h"
 -#include "libavutil/pixdesc.h"
 +#include "libavutil/timecode.h"
  #include "libavutil/tree.h"
  #include "libavutil/lfg.h"
  #include "avfilter.h"
  #include <freetype/config/ftheader.h>
  #include FT_FREETYPE_H
  #include FT_GLYPH_H
 +#if CONFIG_FONTCONFIG
 +#include <fontconfig/fontconfig.h>
 +#endif
  
  static const char *const var_names[] = {
 -    "E",
 -    "PHI",
 -    "PI",
 -    "main_w",    "W", ///< width  of the main    video
 -    "main_h",    "H", ///< height of the main    video
 -    "text_w",    "w", ///< width  of the overlay text
 -    "text_h",    "h", ///< height of the overlay text
 +    "dar",
 +    "hsub", "vsub",
 +    "line_h", "lh",           ///< line height, same as max_glyph_h
 +    "main_h", "h", "H",       ///< height of the input video
 +    "main_w", "w", "W",       ///< width  of the input video
 +    "max_glyph_a", "ascent",  ///< max glyph ascent
 +    "max_glyph_d", "descent", ///< min glyph descent
 +    "max_glyph_h",            ///< max glyph height
 +    "max_glyph_w",            ///< max glyph width
 +    "n",                      ///< number of frame
 +    "sar",
 +    "t",                      ///< timestamp expressed in seconds
 +    "text_h", "th",           ///< height of the rendered text
 +    "text_w", "tw",           ///< width  of the rendered text
      "x",
      "y",
 -    "n",              ///< number of processed frames
 -    "t",              ///< timestamp expressed in seconds
      NULL
  };
  
@@@ -93,28 -85,22 +93,28 @@@ static const eval_func2 fun2[] = 
  };
  
  enum var_name {
 -    VAR_E,
 -    VAR_PHI,
 -    VAR_PI,
 -    VAR_MAIN_W, VAR_MW,
 -    VAR_MAIN_H, VAR_MH,
 -    VAR_TEXT_W, VAR_TW,
 +    VAR_DAR,
 +    VAR_HSUB, VAR_VSUB,
 +    VAR_LINE_H, VAR_LH,
 +    VAR_MAIN_H, VAR_h, VAR_H,
 +    VAR_MAIN_W, VAR_w, VAR_W,
 +    VAR_MAX_GLYPH_A, VAR_ASCENT,
 +    VAR_MAX_GLYPH_D, VAR_DESCENT,
 +    VAR_MAX_GLYPH_H,
 +    VAR_MAX_GLYPH_W,
 +    VAR_N,
 +    VAR_SAR,
 +    VAR_T,
      VAR_TEXT_H, VAR_TH,
 +    VAR_TEXT_W, VAR_TW,
      VAR_X,
      VAR_Y,
 -    VAR_N,
 -    VAR_T,
      VAR_VARS_NB
  };
  
  typedef struct {
      const AVClass *class;
 +    int reinit;                     ///< tells if the filter is being reinited
      uint8_t *fontfile;              ///< font to be used
      uint8_t *text;                  ///< text to be drawn
      uint8_t *expanded_text;         ///< used to contain the strftime()-expanded text
      FT_Vector *positions;           ///< positions for each element in the text
      size_t nb_positions;            ///< number of elements of positions array
      char *textfile;                 ///< file with text to be drawn
 -    int x, y;                       ///< position to start drawing text
 -    int w, h;                       ///< dimension of the text block
 +    int x;                          ///< x position to start drawing text
 +    int y;                          ///< y position to start drawing text
 +    int max_glyph_w;                ///< max glyph width
 +    int max_glyph_h;                ///< max glyph height
      int shadowx, shadowy;
      unsigned int fontsize;          ///< font size to use
      char *fontcolor_string;         ///< font color as string
      char *boxcolor_string;          ///< box color as string
      char *shadowcolor_string;       ///< shadow color as string
 -    uint8_t fontcolor[4];           ///< foreground color
 -    uint8_t boxcolor[4];            ///< background color
 -    uint8_t shadowcolor[4];         ///< shadow color
 -    uint8_t fontcolor_rgba[4];      ///< foreground color in RGBA
 -    uint8_t boxcolor_rgba[4];       ///< background color in RGBA
 -    uint8_t shadowcolor_rgba[4];    ///< shadow color in RGBA
  
      short int draw_box;             ///< draw box around text - true or false
      int use_kerning;                ///< font kerning is used - true/false
      int tabsize;                    ///< tab size
      int fix_bounds;                 ///< do we let it go out of frame bounds - t/f
  
 +    FFDrawContext dc;
 +    FFDrawColor fontcolor;          ///< foreground color
 +    FFDrawColor shadowcolor;        ///< shadow color
 +    FFDrawColor boxcolor;           ///< background color
 +
      FT_Library library;             ///< freetype font library handle
      FT_Face face;                   ///< freetype font face handle
      struct AVTreeNode *glyphs;      ///< rendered glyphs, stored using the UTF-32 char code
 -    int hsub, vsub;                 ///< chroma subsampling values
 -    int is_packed_rgb;
 -    int pixel_step[4];              ///< distance in bytes between the component of each pixel
 -    uint8_t rgba_map[4];            ///< map RGBA offsets to the positions in the packed RGBA format
 -    uint8_t *box_line[4];           ///< line used for filling the box background
 -    char   *x_expr, *y_expr;
 +    char *x_expr;                   ///< expression for x position
 +    char *y_expr;                   ///< expression for y position
      AVExpr *x_pexpr, *y_pexpr;      ///< parsed expressions for x and y
 +    int64_t basetime;               ///< base pts time in the real world for display
      double var_values[VAR_VARS_NB];
 -    char   *d_expr;
 -    AVExpr *d_pexpr;
 +    char   *draw_expr;              ///< expression for draw
 +    AVExpr *draw_pexpr;             ///< parsed expression for draw
      int draw;                       ///< set to zero to prevent drawing
      AVLFG  prng;                    ///< random
 +    char       *tc_opt_string;      ///< specified timecode option string
 +    AVRational  tc_rate;            ///< frame rate for timecode
 +    AVTimecode  tc;                 ///< timecode context
 +    int tc24hmax;                   ///< 1 if timecode is wrapped to 24 hours, 0 otherwise
 +    int frame_id;
  } DrawTextContext;
  
  #define OFFSET(x) offsetof(DrawTextContext, x)
 +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  
  static const AVOption drawtext_options[]= {
 -{"fontfile", "set font file",        OFFSET(fontfile),           AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"text",     "set text",             OFFSET(text),               AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"textfile", "set text file",        OFFSET(textfile),           AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"fontcolor","set foreground color", OFFSET(fontcolor_string),   AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"boxcolor", "set box color",        OFFSET(boxcolor_string),    AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"shadowcolor", "set shadow color",  OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 -{"box",      "set box",              OFFSET(draw_box),           AV_OPT_TYPE_INT,    {.dbl=0},     0,        1        },
 -{"fontsize", "set font size",        OFFSET(fontsize),           AV_OPT_TYPE_INT,    {.dbl=16},    1,        72       },
 -{"x",        "set x",                OFFSET(x_expr),             AV_OPT_TYPE_STRING, {.str="0"},   CHAR_MIN, CHAR_MAX },
 -{"y",        "set y",                OFFSET(y_expr),             AV_OPT_TYPE_STRING, {.str="0"},   CHAR_MIN, CHAR_MAX },
 -{"shadowx",  "set x",                OFFSET(shadowx),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
 -{"shadowy",  "set y",                OFFSET(shadowy),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
 -{"tabsize",  "set tab size",         OFFSET(tabsize),            AV_OPT_TYPE_INT,    {.dbl=4},     0,        INT_MAX  },
 -{"draw",     "if false do not draw", OFFSET(d_expr),             AV_OPT_TYPE_STRING, {.str="1"},   CHAR_MIN, CHAR_MAX },
 -{"fix_bounds", "if true, check and fix text coords to avoid clipping",
 -                                     OFFSET(fix_bounds),         AV_OPT_TYPE_INT,    {.dbl=1},     0,        1        },
 +{"fontfile", "set font file",        OFFSET(fontfile),           AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX, FLAGS},
 +{"text",     "set text",             OFFSET(text),               AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX, FLAGS},
 +{"textfile", "set text file",        OFFSET(textfile),           AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX, FLAGS},
 +{"fontcolor",   "set foreground color", OFFSET(fontcolor_string),   AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
 +{"boxcolor",    "set box color",        OFFSET(boxcolor_string),    AV_OPT_TYPE_STRING, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS},
 +{"shadowcolor", "set shadow color",     OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
 +{"box",      "set box",              OFFSET(draw_box),           AV_OPT_TYPE_INT,    {.dbl=0},     0,        1       , FLAGS},
 +{"fontsize", "set font size",        OFFSET(fontsize),           AV_OPT_TYPE_INT,    {.dbl=0},     0,        INT_MAX , FLAGS},
 +{"x",        "set x expression",     OFFSET(x_expr),             AV_OPT_TYPE_STRING, {.str="0"},   CHAR_MIN, CHAR_MAX, FLAGS},
 +{"y",        "set y expression",     OFFSET(y_expr),             AV_OPT_TYPE_STRING, {.str="0"},   CHAR_MIN, CHAR_MAX, FLAGS},
 +{"shadowx",  "set x",                OFFSET(shadowx),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX , FLAGS},
 +{"shadowy",  "set y",                OFFSET(shadowy),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX , FLAGS},
 +{"tabsize",  "set tab size",         OFFSET(tabsize),            AV_OPT_TYPE_INT,    {.dbl=4},     0,        INT_MAX , FLAGS},
 +{"basetime", "set base time",        OFFSET(basetime),           AV_OPT_TYPE_INT64,  {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS},
 +{"draw",     "if false do not draw", OFFSET(draw_expr),          AV_OPT_TYPE_STRING, {.str="1"},   CHAR_MIN, CHAR_MAX, FLAGS},
 +{"timecode", "set initial timecode", OFFSET(tc_opt_string),      AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX, FLAGS},
 +{"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_INT,  {.dbl=0},            0,        1, FLAGS},
 +{"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate),   AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
 +{"r",        "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
 +{"rate",     "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
 +{"fix_bounds", "if true, check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1, FLAGS},
  
  /* FT_LOAD_* flags */
- {"ft_load_flags", "set font loading flags for libfreetype",   OFFSET(ft_load_flags),  AV_OPT_TYPE_FLAGS,  {.dbl=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, FLAGS, "ft_load_flags"},
 -{"ft_load_flags", "set font loading flags for libfreetype",   OFFSET(ft_load_flags),  AV_OPT_TYPE_FLAGS,  {.i64=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, 0, "ft_load_flags" },
 -{"default",                     "set default",                     0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_DEFAULT},                     INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"no_scale",                    "set no_scale",                    0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_NO_SCALE},                    INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"no_hinting",                  "set no_hinting",                  0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_NO_HINTING},                  INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"render",                      "set render",                      0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_RENDER},                      INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"no_bitmap",                   "set no_bitmap",                   0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_NO_BITMAP},                   INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"vertical_layout",             "set vertical_layout",             0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_VERTICAL_LAYOUT},             INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"force_autohint",              "set force_autohint",              0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_FORCE_AUTOHINT},              INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"crop_bitmap",                 "set crop_bitmap",                 0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_CROP_BITMAP},                 INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"pedantic",                    "set pedantic",                    0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_PEDANTIC},                    INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"ignore_global_advance_width", "set ignore_global_advance_width", 0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH}, INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"no_recurse",                  "set no_recurse",                  0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_NO_RECURSE},                  INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"ignore_transform",            "set ignore_transform",            0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_IGNORE_TRANSFORM},            INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"monochrome",                  "set monochrome",                  0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_MONOCHROME},                  INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"linear_design",               "set linear_design",               0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_LINEAR_DESIGN},               INT_MIN, INT_MAX, 0, "ft_load_flags" },
 -{"no_autohint",                 "set no_autohint",                 0, AV_OPT_TYPE_CONST, {.i64 = FT_LOAD_NO_AUTOHINT},                 INT_MIN, INT_MAX, 0, "ft_load_flags" },
++{"ft_load_flags", "set font loading flags for libfreetype",   OFFSET(ft_load_flags),  AV_OPT_TYPE_FLAGS,  {.i64=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, FLAGS, "ft_load_flags"},
 +{"default",                     "set default",                     0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_DEFAULT},                     INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"no_scale",                    "set no_scale",                    0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_NO_SCALE},                    INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"no_hinting",                  "set no_hinting",                  0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_NO_HINTING},                  INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"render",                      "set render",                      0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_RENDER},                      INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"no_bitmap",                   "set no_bitmap",                   0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_NO_BITMAP},                   INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"vertical_layout",             "set vertical_layout",             0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_VERTICAL_LAYOUT},             INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"force_autohint",              "set force_autohint",              0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_FORCE_AUTOHINT},              INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"crop_bitmap",                 "set crop_bitmap",                 0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_CROP_BITMAP},                 INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"pedantic",                    "set pedantic",                    0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_PEDANTIC},                    INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"ignore_global_advance_width", "set ignore_global_advance_width", 0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH}, INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"no_recurse",                  "set no_recurse",                  0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_NO_RECURSE},                  INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"ignore_transform",            "set ignore_transform",            0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_IGNORE_TRANSFORM},            INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"monochrome",                  "set monochrome",                  0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_MONOCHROME},                  INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"linear_design",               "set linear_design",               0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_LINEAR_DESIGN},               INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
 +{"no_autohint",                 "set no_autohint",                 0, AV_OPT_TYPE_CONST, {.i64=FT_LOAD_NO_AUTOHINT},                 INT_MIN, INT_MAX, FLAGS, "ft_load_flags"},
  {NULL},
  };
  
 -static const char *drawtext_get_name(void *ctx)
 -{
 -    return "drawtext";
 -}
 -
 -static const AVClass drawtext_class = {
 -    "DrawTextContext",
 -    drawtext_get_name,
 -    drawtext_options
 -};
 +AVFILTER_DEFINE_CLASS(drawtext);
  
  #undef __FTERRORS_H__
  #define FT_ERROR_START_LIST {
@@@ -295,91 -281,6 +295,91 @@@ error
      return ret;
  }
  
 +static int load_font_file(AVFilterContext *ctx, const char *path, int index,
 +                          const char **error)
 +{
 +    DrawTextContext *dtext = ctx->priv;
 +    int err;
 +
 +    err = FT_New_Face(dtext->library, path, index, &dtext->face);
 +    if (err) {
 +        *error = FT_ERRMSG(err);
 +        return AVERROR(EINVAL);
 +    }
 +    return 0;
 +}
 +
 +#if CONFIG_FONTCONFIG
 +static int load_font_fontconfig(AVFilterContext *ctx, const char **error)
 +{
 +    DrawTextContext *dtext = ctx->priv;
 +    FcConfig *fontconfig;
 +    FcPattern *pattern, *fpat;
 +    FcResult result = FcResultMatch;
 +    FcChar8 *filename;
 +    int err, index;
 +    double size;
 +
 +    fontconfig = FcInitLoadConfigAndFonts();
 +    if (!fontconfig) {
 +        *error = "impossible to init fontconfig\n";
 +        return AVERROR(EINVAL);
 +    }
 +    pattern = FcNameParse(dtext->fontfile ? dtext->fontfile :
 +                          (uint8_t *)(intptr_t)"default");
 +    if (!pattern) {
 +        *error = "could not parse fontconfig pattern";
 +        return AVERROR(EINVAL);
 +    }
 +    if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
 +        *error = "could not substitue fontconfig options"; /* very unlikely */
 +        return AVERROR(EINVAL);
 +    }
 +    FcDefaultSubstitute(pattern);
 +    fpat = FcFontMatch(fontconfig, pattern, &result);
 +    if (!fpat || result != FcResultMatch) {
 +        *error = "impossible to find a matching font";
 +        return AVERROR(EINVAL);
 +    }
 +    if (FcPatternGetString (fpat, FC_FILE,  0, &filename) != FcResultMatch ||
 +        FcPatternGetInteger(fpat, FC_INDEX, 0, &index   ) != FcResultMatch ||
 +        FcPatternGetDouble (fpat, FC_SIZE,  0, &size    ) != FcResultMatch) {
 +        *error = "impossible to find font information";
 +        return AVERROR(EINVAL);
 +    }
 +    av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
 +    if (!dtext->fontsize)
 +        dtext->fontsize = size + 0.5;
 +    err = load_font_file(ctx, filename, index, error);
 +    if (err)
 +        return err;
 +    FcPatternDestroy(fpat);
 +    FcPatternDestroy(pattern);
 +    FcConfigDestroy(fontconfig);
 +    return 0;
 +}
 +#endif
 +
 +static int load_font(AVFilterContext *ctx)
 +{
 +    DrawTextContext *dtext = ctx->priv;
 +    int err;
 +    const char *error = "unknown error\n";
 +
 +    /* load the face, and set up the encoding, which is by default UTF-8 */
 +    err = load_font_file(ctx, dtext->fontfile, 0, &error);
 +    if (!err)
 +        return 0;
 +#if CONFIG_FONTCONFIG
 +    err = load_font_fontconfig(ctx, &error);
 +    if (!err)
 +        return 0;
 +#endif
 +    av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
 +           dtext->fontfile, error);
 +    return err;
 +}
 +
  static av_cold int init(AVFilterContext *ctx, const char *args)
  {
      int err;
  
      dtext->class = &drawtext_class;
      av_opt_set_defaults(dtext);
 -    dtext->fontcolor_string = av_strdup("black");
 -    dtext->boxcolor_string = av_strdup("white");
 -    dtext->shadowcolor_string = av_strdup("black");
  
 -    if ((err = (av_set_options_string(dtext, args, "=", ":"))) < 0) {
 -        av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
 +    if ((err = av_set_options_string(dtext, args, "=", ":")) < 0)
          return err;
 -    }
  
 -    if (!dtext->fontfile) {
 +    if (!dtext->fontfile && !CONFIG_FONTCONFIG) {
          av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
          return AVERROR(EINVAL);
      }
          av_file_unmap(textbuf, textbuf_size);
      }
  
 +    if (dtext->tc_opt_string) {
 +        int ret = av_timecode_init_from_string(&dtext->tc, dtext->tc_rate,
 +                                               dtext->tc_opt_string, ctx);
 +        if (ret < 0)
 +            return ret;
 +        if (dtext->tc24hmax)
 +            dtext->tc.flags |= AV_TIMECODE_FLAG_24HOURSMAX;
 +        if (!dtext->text)
 +            dtext->text = av_strdup("");
 +    }
 +
      if (!dtext->text) {
          av_log(ctx, AV_LOG_ERROR,
 -               "Either text or a valid file must be provided\n");
 +               "Either text, a valid file or a timecode must be provided\n");
          return AVERROR(EINVAL);
      }
  
 -    if ((err = av_parse_color(dtext->fontcolor_rgba, dtext->fontcolor_string, -1, ctx))) {
 +    if ((err = av_parse_color(dtext->fontcolor.rgba, dtext->fontcolor_string, -1, ctx))) {
          av_log(ctx, AV_LOG_ERROR,
                 "Invalid font color '%s'\n", dtext->fontcolor_string);
          return err;
      }
  
 -    if ((err = av_parse_color(dtext->boxcolor_rgba, dtext->boxcolor_string, -1, ctx))) {
 +    if ((err = av_parse_color(dtext->boxcolor.rgba, dtext->boxcolor_string, -1, ctx))) {
          av_log(ctx, AV_LOG_ERROR,
                 "Invalid box color '%s'\n", dtext->boxcolor_string);
          return err;
      }
  
 -    if ((err = av_parse_color(dtext->shadowcolor_rgba, dtext->shadowcolor_string, -1, ctx))) {
 +    if ((err = av_parse_color(dtext->shadowcolor.rgba, dtext->shadowcolor_string, -1, ctx))) {
          av_log(ctx, AV_LOG_ERROR,
                 "Invalid shadow color '%s'\n", dtext->shadowcolor_string);
          return err;
          return AVERROR(EINVAL);
      }
  
 -    /* load the face, and set up the encoding, which is by default UTF-8 */
 -    if ((err = FT_New_Face(dtext->library, dtext->fontfile, 0, &dtext->face))) {
 -        av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
 -               dtext->fontfile, FT_ERRMSG(err));
 -        return AVERROR(EINVAL);
 -    }
 +    err = load_font(ctx);
 +    if (err)
 +        return err;
 +    if (!dtext->fontsize)
 +        dtext->fontsize = 16;
      if ((err = FT_Set_Pixel_Sizes(dtext->face, 0, dtext->fontsize))) {
          av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
                 dtext->fontsize, FT_ERRMSG(err));
      load_glyph(ctx, NULL, 0);
  
      /* set the tabsize in pixels */
 -    if ((err = load_glyph(ctx, &glyph, ' ') < 0)) {
 +    if ((err = load_glyph(ctx, &glyph, ' ')) < 0) {
          av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n");
          return err;
      }
      dtext->tabsize *= glyph->advance;
  
 -#if !HAVE_LOCALTIME_R
 -    av_log(ctx, AV_LOG_WARNING, "strftime() expansion unavailable!\n");
 -#endif
 -
      return 0;
  }
  
  static int query_formats(AVFilterContext *ctx)
  {
 -    static const enum PixelFormat pix_fmts[] = {
 -        PIX_FMT_ARGB,    PIX_FMT_RGBA,
 -        PIX_FMT_ABGR,    PIX_FMT_BGRA,
 -        PIX_FMT_RGB24,   PIX_FMT_BGR24,
 -        PIX_FMT_YUV420P, PIX_FMT_YUV444P,
 -        PIX_FMT_YUV422P, PIX_FMT_YUV411P,
 -        PIX_FMT_YUV410P, PIX_FMT_YUV440P,
 -        PIX_FMT_NONE
 -    };
 -
 -    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
 +    ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
      return 0;
  }
  
  static int glyph_enu_free(void *opaque, void *elem)
  {
 +    Glyph *glyph = elem;
 +
 +    FT_Done_Glyph(*glyph->glyph);
 +    av_freep(&glyph->glyph);
      av_free(elem);
      return 0;
  }
  static av_cold void uninit(AVFilterContext *ctx)
  {
      DrawTextContext *dtext = ctx->priv;
 -    int i;
  
 -    av_freep(&dtext->fontfile);
 -    av_freep(&dtext->text);
 -    av_freep(&dtext->expanded_text);
 -    av_freep(&dtext->fontcolor_string);
 -    av_freep(&dtext->boxcolor_string);
 +    av_expr_free(dtext->x_pexpr); dtext->x_pexpr = NULL;
 +    av_expr_free(dtext->y_pexpr); dtext->y_pexpr = NULL;
 +    av_expr_free(dtext->draw_pexpr); dtext->draw_pexpr = NULL;
 +    av_opt_free(dtext);
 +
      av_freep(&dtext->positions);
 -    av_freep(&dtext->shadowcolor_string);
 +    dtext->nb_positions = 0;
 +
      av_tree_enumerate(dtext->glyphs, NULL, NULL, glyph_enu_free);
      av_tree_destroy(dtext->glyphs);
 -    dtext->glyphs = 0;
 +    dtext->glyphs = NULL;
 +
      FT_Done_Face(dtext->face);
      FT_Done_FreeType(dtext->library);
 +}
 +
 +static inline int is_newline(uint32_t c)
 +{
 +    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
 +}
 +
 +static int config_input(AVFilterLink *inlink)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    DrawTextContext *dtext = ctx->priv;
 +    int ret;
 +
 +    ff_draw_init(&dtext->dc, inlink->format, 0);
 +    ff_draw_color(&dtext->dc, &dtext->fontcolor,   dtext->fontcolor.rgba);
 +    ff_draw_color(&dtext->dc, &dtext->shadowcolor, dtext->shadowcolor.rgba);
 +    ff_draw_color(&dtext->dc, &dtext->boxcolor,    dtext->boxcolor.rgba);
 +
 +    dtext->var_values[VAR_w]     = dtext->var_values[VAR_W]     = dtext->var_values[VAR_MAIN_W] = inlink->w;
 +    dtext->var_values[VAR_h]     = dtext->var_values[VAR_H]     = dtext->var_values[VAR_MAIN_H] = inlink->h;
 +    dtext->var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
 +    dtext->var_values[VAR_DAR]   = (double)inlink->w / inlink->h * dtext->var_values[VAR_SAR];
 +    dtext->var_values[VAR_HSUB]  = 1 << dtext->dc.hsub_max;
 +    dtext->var_values[VAR_VSUB]  = 1 << dtext->dc.vsub_max;
 +    dtext->var_values[VAR_X]     = NAN;
 +    dtext->var_values[VAR_Y]     = NAN;
 +    if (!dtext->reinit)
 +        dtext->var_values[VAR_N] = 0;
 +    dtext->var_values[VAR_T]     = NAN;
 +
 +    av_lfg_init(&dtext->prng, av_get_random_seed());
  
 -    for (i = 0; i < 4; i++) {
 -        av_freep(&dtext->box_line[i]);
 -        dtext->pixel_step[i] = 0;
 +    if ((ret = av_expr_parse(&dtext->x_pexpr, dtext->x_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 +        (ret = av_expr_parse(&dtext->y_pexpr, dtext->y_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 +        (ret = av_expr_parse(&dtext->draw_pexpr, dtext->draw_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
 +
 +        return AVERROR(EINVAL);
 +
 +    return 0;
 +}
 +
 +static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
 +{
 +    DrawTextContext *dtext = ctx->priv;
 +
 +    if (!strcmp(cmd, "reinit")) {
 +        int ret;
 +        uninit(ctx);
 +        dtext->reinit = 1;
 +        if ((ret = init(ctx, arg)) < 0)
 +            return ret;
 +        return config_input(ctx->inputs[0]);
      }
  
 +    return AVERROR(ENOSYS);
  }
  
 -static inline int is_newline(uint32_t c)
 +static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
 +                       int width, int height, const uint8_t rgbcolor[4], FFDrawColor *color, int x, int y)
  {
 -    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
 +    char *text = dtext->expanded_text;
 +    uint32_t code = 0;
 +    int i, x1, y1;
 +    uint8_t *p;
 +    Glyph *glyph = NULL;
 +
 +    for (i = 0, p = text; *p; i++) {
 +        Glyph dummy = { 0 };
 +        GET_UTF8(code, *p++, continue;);
 +
 +        /* skip new line chars, just go to new line */
 +        if (code == '\n' || code == '\r' || code == '\t')
 +            continue;
 +
 +        dummy.code = code;
 +        glyph = av_tree_find(dtext->glyphs, &dummy, (void *)glyph_cmp, NULL);
 +
 +        if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
 +            glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
 +            return AVERROR(EINVAL);
 +
 +        x1 = dtext->positions[i].x+dtext->x+x;
 +        y1 = dtext->positions[i].y+dtext->y+y;
 +
 +        ff_blend_mask(&dtext->dc, color,
 +                      picref->data, picref->linesize, width, height,
 +                      glyph->bitmap.buffer, glyph->bitmap.pitch,
 +                      glyph->bitmap.width, glyph->bitmap.rows,
 +                      glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 0 : 3,
 +                      0, x1, y1);
 +    }
 +
 +    return 0;
  }
  
 -static int dtext_prepare_text(AVFilterContext *ctx)
 +static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
 +                     int width, int height)
  {
      DrawTextContext *dtext = ctx->priv;
      uint32_t code = 0, prev_code = 0;
      int x = 0, y = 0, i = 0, ret;
 -    int text_height, baseline;
 +    int max_text_line_w = 0, len;
 +    int box_w, box_h;
      char *text = dtext->text;
      uint8_t *p;
 -    int str_w = 0, len;
      int y_min = 32000, y_max = -32000;
 +    int x_min = 32000, x_max = -32000;
      FT_Vector delta;
      Glyph *glyph = NULL, *prev_glyph = NULL;
      Glyph dummy = { 0 };
 -    int width  = ctx->inputs[0]->w;
 -    int height = ctx->inputs[0]->h;
  
 -#if HAVE_LOCALTIME_R
      time_t now = time(0);
      struct tm ltime;
      uint8_t *buf = dtext->expanded_text;
      int buf_size = dtext->expanded_text_size;
  
 -    if (!buf)
 +    if(dtext->basetime != AV_NOPTS_VALUE)
 +        now= picref->pts*av_q2d(ctx->inputs[0]->time_base) + dtext->basetime/1000000;
 +
 +    if (!buf) {
          buf_size = 2*strlen(dtext->text)+1;
 +        buf = av_malloc(buf_size);
 +    }
  
 +#if HAVE_LOCALTIME_R
      localtime_r(&now, &ltime);
 +#else
 +    if(strchr(dtext->text, '%'))
 +        ltime= *localtime(&now);
 +#endif
  
 -    while ((buf = av_realloc(buf, buf_size))) {
 +    do {
          *buf = 1;
          if (strftime(buf, buf_size, dtext->text, &ltime) != 0 || *buf == 0)
              break;
          buf_size *= 2;
 +    } while ((buf = av_realloc(buf, buf_size)));
 +
 +    if (dtext->tc_opt_string) {
 +        char tcbuf[AV_TIMECODE_STR_SIZE];
 +        av_timecode_make_string(&dtext->tc, tcbuf, dtext->frame_id++);
 +        buf = av_asprintf("%s%s", dtext->text, tcbuf);
      }
  
      if (!buf)
          return AVERROR(ENOMEM);
      text = dtext->expanded_text = buf;
      dtext->expanded_text_size = buf_size;
 -#endif
 -
      if ((len = strlen(text)) > dtext->nb_positions) {
 -        FT_Vector *p = av_realloc(dtext->positions,
 -                                  len * sizeof(*dtext->positions));
 -        if (!p) {
 -            av_freep(dtext->positions);
 -            dtext->nb_positions = 0;
 +        if (!(dtext->positions =
 +              av_realloc(dtext->positions, len*sizeof(*dtext->positions))))
              return AVERROR(ENOMEM);
 -        } else {
 -            dtext->positions = p;
 -            dtext->nb_positions = len;
 -        }
 +        dtext->nb_positions = len;
      }
  
 +    x = 0;
 +    y = 0;
 +
      /* load and cache glyphs */
      for (i = 0, p = text; *p; i++) {
          GET_UTF8(code, *p++, continue;);
          dummy.code = code;
          glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
          if (!glyph) {
 -            ret = load_glyph(ctx, &glyph, code);
 -            if (ret)
 -                return ret;
 +            load_glyph(ctx, &glyph, code);
          }
  
          y_min = FFMIN(glyph->bbox.yMin, y_min);
          y_max = FFMAX(glyph->bbox.yMax, y_max);
 +        x_min = FFMIN(glyph->bbox.xMin, x_min);
 +        x_max = FFMAX(glyph->bbox.xMax, x_max);
      }
 -    text_height = y_max - y_min;
 -    baseline    = y_max;
 +    dtext->max_glyph_h = y_max - y_min;
 +    dtext->max_glyph_w = x_max - x_min;
  
      /* compute and save position for each glyph */
      glyph = NULL;
  
          prev_code = code;
          if (is_newline(code)) {
 -            str_w = FFMAX(str_w, x - dtext->x);
 -            y += text_height;
 +            max_text_line_w = FFMAX(max_text_line_w, x);
 +            y += dtext->max_glyph_h;
              x = 0;
              continue;
          }
              x += delta.x >> 6;
          }
  
 -        if (x + glyph->bbox.xMax >= width) {
 -            str_w = FFMAX(str_w, x);
 -            y += text_height;
 -            x = 0;
 -        }
 -
          /* save position */
          dtext->positions[i].x = x + glyph->bitmap_left;
 -        dtext->positions[i].y = y - glyph->bitmap_top + baseline;
 +        dtext->positions[i].y = y - glyph->bitmap_top + y_max;
          if (code == '\t') x  = (x / dtext->tabsize + 1)*dtext->tabsize;
          else              x += glyph->advance;
      }
  
 -    str_w = FFMIN(width - 1, FFMAX(str_w, x));
 -    y     = FFMIN(y + text_height, height - 1);
 -
 -    dtext->w = str_w;
 -    dtext->var_values[VAR_TEXT_W] = dtext->var_values[VAR_TW] = dtext->w;
 -    dtext->h = y;
 -    dtext->var_values[VAR_TEXT_H] = dtext->var_values[VAR_TH] = dtext->h;
 -
 -    return 0;
 -}
 -
 -
 -static int config_input(AVFilterLink *inlink)
 -{
 -    AVFilterContext *ctx  = inlink->dst;
 -    DrawTextContext *dtext = ctx->priv;
 -    const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
 -    int ret;
 -
 -    dtext->hsub = pix_desc->log2_chroma_w;
 -    dtext->vsub = pix_desc->log2_chroma_h;
 -
 -    dtext->var_values[VAR_E  ] = M_E;
 -    dtext->var_values[VAR_PHI] = M_PHI;
 -    dtext->var_values[VAR_PI ] = M_PI;
 -
 -    dtext->var_values[VAR_MAIN_W] =
 -        dtext->var_values[VAR_MW] = ctx->inputs[0]->w;
 -    dtext->var_values[VAR_MAIN_H] =
 -        dtext->var_values[VAR_MH] = ctx->inputs[0]->h;
 -
 -    dtext->var_values[VAR_X] = 0;
 -    dtext->var_values[VAR_Y] = 0;
 -    dtext->var_values[VAR_N] = 0;
 -    dtext->var_values[VAR_T] = NAN;
 -
 -    av_lfg_init(&dtext->prng, av_get_random_seed());
 -
 -    if ((ret = av_expr_parse(&dtext->x_pexpr, dtext->x_expr, var_names,
 -                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 -        (ret = av_expr_parse(&dtext->y_pexpr, dtext->y_expr, var_names,
 -                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 -        (ret = av_expr_parse(&dtext->d_pexpr, dtext->d_expr, var_names,
 -                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
 -        return AVERROR(EINVAL);
 -
 -    if ((ret =
 -         ff_fill_line_with_color(dtext->box_line, dtext->pixel_step,
 -                                 inlink->w, dtext->boxcolor,
 -                                 inlink->format, dtext->boxcolor_rgba,
 -                                 &dtext->is_packed_rgb, dtext->rgba_map)) < 0)
 -        return ret;
 -
 -    if (!dtext->is_packed_rgb) {
 -        uint8_t *rgba = dtext->fontcolor_rgba;
 -        dtext->fontcolor[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
 -        dtext->fontcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
 -        dtext->fontcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
 -        dtext->fontcolor[3] = rgba[3];
 -        rgba = dtext->shadowcolor_rgba;
 -        dtext->shadowcolor[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
 -        dtext->shadowcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
 -        dtext->shadowcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
 -        dtext->shadowcolor[3] = rgba[3];
 -    }
 -
 -    dtext->draw = 1;
 -
 -    return dtext_prepare_text(ctx);
 -}
 -
 -#define GET_BITMAP_VAL(r, c)                                            \
 -    bitmap->pixel_mode == FT_PIXEL_MODE_MONO ?                          \
 -        (bitmap->buffer[(r) * bitmap->pitch + ((c)>>3)] & (0x80 >> ((c)&7))) * 255 : \
 -         bitmap->buffer[(r) * bitmap->pitch +  (c)]
 -
 -#define SET_PIXEL_YUV(picref, yuva_color, val, x, y, hsub, vsub) {           \
 -    luma_pos    = ((x)          ) + ((y)          ) * picref->linesize[0]; \
 -    alpha = yuva_color[3] * (val) * 129;                               \
 -    picref->data[0][luma_pos]    = (alpha * yuva_color[0] + (255*255*129 - alpha) * picref->data[0][luma_pos]   ) >> 23; \
 -    if (((x) & ((1<<(hsub)) - 1)) == 0 && ((y) & ((1<<(vsub)) - 1)) == 0) {\
 -        chroma_pos1 = ((x) >> (hsub)) + ((y) >> (vsub)) * picref->linesize[1]; \
 -        chroma_pos2 = ((x) >> (hsub)) + ((y) >> (vsub)) * picref->linesize[2]; \
 -        picref->data[1][chroma_pos1] = (alpha * yuva_color[1] + (255*255*129 - alpha) * picref->data[1][chroma_pos1]) >> 23; \
 -        picref->data[2][chroma_pos2] = (alpha * yuva_color[2] + (255*255*129 - alpha) * picref->data[2][chroma_pos2]) >> 23; \
 -    }\
 -}
 -
 -static inline int draw_glyph_yuv(AVFilterBufferRef *picref, FT_Bitmap *bitmap, unsigned int x,
 -                                 unsigned int y, unsigned int width, unsigned int height,
 -                                 const uint8_t yuva_color[4], int hsub, int vsub)
 -{
 -    int r, c, alpha;
 -    unsigned int luma_pos, chroma_pos1, chroma_pos2;
 -    uint8_t src_val;
 -
 -    for (r = 0; r < bitmap->rows && r+y < height; r++) {
 -        for (c = 0; c < bitmap->width && c+x < width; c++) {
 -            /* get intensity value in the glyph bitmap (source) */
 -            src_val = GET_BITMAP_VAL(r, c);
 -            if (!src_val)
 -                continue;
 -
 -            SET_PIXEL_YUV(picref, yuva_color, src_val, c+x, y+r, hsub, vsub);
 -        }
 -    }
 -
 -    return 0;
 -}
 -
 -#define SET_PIXEL_RGB(picref, rgba_color, val, x, y, pixel_step, r_off, g_off, b_off, a_off) { \
 -    p   = picref->data[0] + (x) * pixel_step + ((y) * picref->linesize[0]); \
 -    alpha = rgba_color[3] * (val) * 129;                              \
 -    *(p+r_off) = (alpha * rgba_color[0] + (255*255*129 - alpha) * *(p+r_off)) >> 23; \
 -    *(p+g_off) = (alpha * rgba_color[1] + (255*255*129 - alpha) * *(p+g_off)) >> 23; \
 -    *(p+b_off) = (alpha * rgba_color[2] + (255*255*129 - alpha) * *(p+b_off)) >> 23; \
 -}
 -
 -static inline int draw_glyph_rgb(AVFilterBufferRef *picref, FT_Bitmap *bitmap,
 -                                 unsigned int x, unsigned int y,
 -                                 unsigned int width, unsigned int height, int pixel_step,
 -                                 const uint8_t rgba_color[4], const uint8_t rgba_map[4])
 -{
 -    int r, c, alpha;
 -    uint8_t *p;
 -    uint8_t src_val;
 -
 -    for (r = 0; r < bitmap->rows && r+y < height; r++) {
 -        for (c = 0; c < bitmap->width && c+x < width; c++) {
 -            /* get intensity value in the glyph bitmap (source) */
 -            src_val = GET_BITMAP_VAL(r, c);
 -            if (!src_val)
 -                continue;
 -
 -            SET_PIXEL_RGB(picref, rgba_color, src_val, c+x, y+r, pixel_step,
 -                          rgba_map[0], rgba_map[1], rgba_map[2], rgba_map[3]);
 -        }
 -    }
 -
 -    return 0;
 -}
 -
 -static inline void drawbox(AVFilterBufferRef *picref, unsigned int x, unsigned int y,
 -                           unsigned int width, unsigned int height,
 -                           uint8_t *line[4], int pixel_step[4], uint8_t color[4],
 -                           int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4])
 -{
 -    int i, j, alpha;
 -
 -    if (color[3] != 0xFF) {
 -        if (is_rgba_packed) {
 -            uint8_t *p;
 -            for (j = 0; j < height; j++)
 -                for (i = 0; i < width; i++)
 -                    SET_PIXEL_RGB(picref, color, 255, i+x, y+j, pixel_step[0],
 -                                  rgba_map[0], rgba_map[1], rgba_map[2], rgba_map[3]);
 -        } else {
 -            unsigned int luma_pos, chroma_pos1, chroma_pos2;
 -            for (j = 0; j < height; j++)
 -                for (i = 0; i < width; i++)
 -                    SET_PIXEL_YUV(picref, color, 255, i+x, y+j, hsub, vsub);
 -        }
 -    } else {
 -        ff_draw_rectangle(picref->data, picref->linesize,
 -                          line, pixel_step, hsub, vsub,
 -                          x, y, width, height);
 -    }
 -}
 -
 -static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
 -                       int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y)
 -{
 -    char *text = HAVE_LOCALTIME_R ? dtext->expanded_text : dtext->text;
 -    uint32_t code = 0;
 -    int i;
 -    uint8_t *p;
 -    Glyph *glyph = NULL;
 -
 -    for (i = 0, p = text; *p; i++) {
 -        Glyph dummy = { 0 };
 -        GET_UTF8(code, *p++, continue;);
 +    max_text_line_w = FFMAX(x, max_text_line_w);
  
 -        /* skip new line chars, just go to new line */
 -        if (code == '\n' || code == '\r' || code == '\t')
 -            continue;
 +    dtext->var_values[VAR_TW] = dtext->var_values[VAR_TEXT_W] = max_text_line_w;
 +    dtext->var_values[VAR_TH] = dtext->var_values[VAR_TEXT_H] = y + dtext->max_glyph_h;
  
 -        dummy.code = code;
 -        glyph = av_tree_find(dtext->glyphs, &dummy, (void *)glyph_cmp, NULL);
 +    dtext->var_values[VAR_MAX_GLYPH_W] = dtext->max_glyph_w;
 +    dtext->var_values[VAR_MAX_GLYPH_H] = dtext->max_glyph_h;
 +    dtext->var_values[VAR_MAX_GLYPH_A] = dtext->var_values[VAR_ASCENT ] = y_max;
 +    dtext->var_values[VAR_MAX_GLYPH_D] = dtext->var_values[VAR_DESCENT] = y_min;
  
 -        if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
 -            glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
 -            return AVERROR(EINVAL);
 +    dtext->var_values[VAR_LINE_H] = dtext->var_values[VAR_LH] = dtext->max_glyph_h;
  
 -        if (dtext->is_packed_rgb) {
 -            draw_glyph_rgb(picref, &glyph->bitmap,
 -                           dtext->positions[i].x+x, dtext->positions[i].y+y, width, height,
 -                           dtext->pixel_step[0], rgbcolor, dtext->rgba_map);
 -        } else {
 -            draw_glyph_yuv(picref, &glyph->bitmap,
 -                           dtext->positions[i].x+x, dtext->positions[i].y+y, width, height,
 -                           yuvcolor, dtext->hsub, dtext->vsub);
 -        }
 -    }
 +    dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->y = dtext->var_values[VAR_Y] = av_expr_eval(dtext->y_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->draw = av_expr_eval(dtext->draw_pexpr, dtext->var_values, &dtext->prng);
  
 -    return 0;
 -}
 +    if(!dtext->draw)
 +        return 0;
  
 -static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
 -                     int width, int height)
 -{
 -    DrawTextContext *dtext = ctx->priv;
 -    int ret;
 +    box_w = FFMIN(width - 1 , max_text_line_w);
 +    box_h = FFMIN(height - 1, y + dtext->max_glyph_h);
  
      /* draw box */
      if (dtext->draw_box)
 -        drawbox(picref, dtext->x, dtext->y, dtext->w, dtext->h,
 -                dtext->box_line, dtext->pixel_step, dtext->boxcolor,
 -                dtext->hsub, dtext->vsub, dtext->is_packed_rgb,
 -                dtext->rgba_map);
 +        ff_blend_rectangle(&dtext->dc, &dtext->boxcolor,
 +                           picref->data, picref->linesize, width, height,
 +                           dtext->x, dtext->y, box_w, box_h);
  
      if (dtext->shadowx || dtext->shadowy) {
 -        if ((ret = draw_glyphs(dtext, picref, width, height,
 -                               dtext->shadowcolor_rgba,
 -                               dtext->shadowcolor,
 -                               dtext->x + dtext->shadowx,
 -                               dtext->y + dtext->shadowy)) < 0)
 +        if ((ret = draw_glyphs(dtext, picref, width, height, dtext->shadowcolor.rgba,
 +                               &dtext->shadowcolor, dtext->shadowx, dtext->shadowy)) < 0)
              return ret;
      }
  
 -    if ((ret = draw_glyphs(dtext, picref, width, height,
 -                           dtext->fontcolor_rgba,
 -                           dtext->fontcolor,
 -                           dtext->x,
 -                           dtext->y)) < 0)
 +    if ((ret = draw_glyphs(dtext, picref, width, height, dtext->fontcolor.rgba,
 +                           &dtext->fontcolor, 0, 0)) < 0)
          return ret;
  
      return 0;
@@@ -784,23 -797,79 +784,23 @@@ static int null_draw_slice(AVFilterLin
      return 0;
  }
  
 -static inline int normalize_double(int *n, double d)
 -{
 -    int ret = 0;
 -
 -    if (isnan(d)) {
 -        ret = AVERROR(EINVAL);
 -    } else if (d > INT_MAX || d < INT_MIN) {
 -        *n = d > INT_MAX ? INT_MAX : INT_MIN;
 -        ret = AVERROR(EINVAL);
 -    } else
 -        *n = round(d);
 -
 -    return ret;
 -}
 -
 -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 +static int end_frame(AVFilterLink *inlink)
  {
      AVFilterContext *ctx = inlink->dst;
 +    AVFilterLink *outlink = ctx->outputs[0];
      DrawTextContext *dtext = ctx->priv;
 -    AVFilterBufferRef *buf_out;
 -    int ret = 0;
 -
 -    if ((ret = dtext_prepare_text(ctx)) < 0) {
 -        av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
 -        return ret;
 -    }
 -
 -    dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ?
 -        NAN : inpicref->pts * av_q2d(inlink->time_base);
 -    dtext->var_values[VAR_X] =
 -        av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 -    dtext->var_values[VAR_Y] =
 -        av_expr_eval(dtext->y_pexpr, dtext->var_values, &dtext->prng);
 -    dtext->var_values[VAR_X] =
 -        av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 -
 -    dtext->draw = av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng);
 -
 -    normalize_double(&dtext->x, dtext->var_values[VAR_X]);
 -    normalize_double(&dtext->y, dtext->var_values[VAR_Y]);
 -
 -    if (dtext->fix_bounds) {
 -        if (dtext->x < 0) dtext->x = 0;
 -        if (dtext->y < 0) dtext->y = 0;
 -        if ((unsigned)dtext->x + (unsigned)dtext->w > inlink->w)
 -            dtext->x = inlink->w - dtext->w;
 -        if ((unsigned)dtext->y + (unsigned)dtext->h > inlink->h)
 -            dtext->y = inlink->h - dtext->h;
 -    }
 -
 -    dtext->x &= ~((1 << dtext->hsub) - 1);
 -    dtext->y &= ~((1 << dtext->vsub) - 1);
 -
 -    av_dlog(ctx, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n",
 -            (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T],
 -            dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h);
 -
 -    buf_out = avfilter_ref_buffer(inpicref, ~0);
 -    if (!buf_out)
 -        return AVERROR(ENOMEM);
 -
 -    return ff_start_frame(inlink->dst->outputs[0], buf_out);
 -}
 -
 -static int end_frame(AVFilterLink *inlink)
 -{
 -    AVFilterLink *outlink = inlink->dst->outputs[0];
      AVFilterBufferRef *picref = inlink->cur_buf;
 -    DrawTextContext *dtext = inlink->dst->priv;
      int ret;
  
 -    if (dtext->draw)
 -        draw_text(inlink->dst, picref, picref->video->w, picref->video->h);
 +    dtext->var_values[VAR_T] = picref->pts == AV_NOPTS_VALUE ?
 +        NAN : picref->pts * av_q2d(inlink->time_base);
 +
 +    draw_text(ctx, picref, picref->video->w, picref->video->h);
 +
 +    av_log(ctx, AV_LOG_DEBUG, "n:%d t:%f text_w:%d text_h:%d x:%d y:%d\n",
 +           (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T],
 +           (int)dtext->var_values[VAR_TEXT_W], (int)dtext->var_values[VAR_TEXT_H],
 +           dtext->x, dtext->y);
  
      dtext->var_values[VAR_N] += 1.0;
  
@@@ -821,16 -890,15 +821,16 @@@ AVFilter avfilter_vf_drawtext = 
      .inputs    = (const AVFilterPad[]) {{ .name             = "default",
                                            .type             = AVMEDIA_TYPE_VIDEO,
                                            .get_video_buffer = ff_null_get_video_buffer,
 -                                          .start_frame      = start_frame,
 +                                          .start_frame      = ff_null_start_frame,
                                            .draw_slice       = null_draw_slice,
                                            .end_frame        = end_frame,
                                            .config_props     = config_input,
                                            .min_perms        = AV_PERM_WRITE |
 -                                                              AV_PERM_READ,
 -                                          .rej_perms        = AV_PERM_PRESERVE },
 +                                                              AV_PERM_READ },
                                          { .name = NULL}},
      .outputs   = (const AVFilterPad[]) {{ .name             = "default",
                                            .type             = AVMEDIA_TYPE_VIDEO, },
                                          { .name = NULL}},
 +    .process_command = command,
 +    .priv_class = &drawtext_class,
  };
diff --combined libavformat/movenc.c
index a8e5b6181ffa3fdf030e454dcba5b54c7a375804,59854574fe040a113eddbf87c492b846370b3675..72e3bb571fdf92aa634a410f989c52485de0fdb3
@@@ -4,20 -4,20 +4,20 @@@
   * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>
   * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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 <assert.h>
  
  static const AVOption options[] = {
-     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
 +    { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 },
      { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
      FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
 -    { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
 +    { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
      { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
      { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
      { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
@@@ -95,10 -94,8 +95,10 @@@ 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 + track->data_offset);
          else
@@@ -156,11 -153,11 +156,11 @@@ static int mov_write_stsc_tag(AVIOConte
      ffio_wfourcc(pb, "stsc");
      avio_wb32(pb, 0); // version & flags
      entryPos = avio_tell(pb);
 -    avio_wb32(pb, track->entry); // entry count
 +    avio_wb32(pb, track->chunkCount); // entry count
      for (i=0; i<track->entry; i++) {
 -        if (oldval != track->cluster[i].samples_in_chunk)
 +        if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum)
          {
 -            avio_wb32(pb, i+1); // first chunk
 +            avio_wb32(pb, track->cluster[i].chunkNum); // first chunk
              avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk
              avio_wb32(pb, 0x1); // sample description index
              oldval = track->cluster[i].samples_in_chunk;
@@@ -267,14 -264,6 +267,14 @@@ static int mov_write_extradata_tag(AVIO
      return track->enc->extradata_size;
  }
  
 +static int mov_write_enda_tag(AVIOContext *pb)
 +{
 +    avio_wb32(pb, 10);
 +    ffio_wfourcc(pb, "enda");
 +    avio_wb16(pb, 1); /* little endian */
 +    return 10;
 +}
 +
  static void put_descr(AVIOContext *pb, int tag, unsigned int size)
  {
      int i = 3;
      avio_w8(pb, size & 0x7F);
  }
  
 +static unsigned compute_avg_bitrate(MOVTrack *track)
 +{
 +    uint64_t size = 0;
 +    int i;
 +    if (!track->track_duration)
 +        return 0;
 +    for (i = 0; i < track->entry; i++)
 +        size += track->cluster[i].size;
 +    return size * 8 * track->timescale / track->track_duration;
 +}
 +
  static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
  {
      int64_t pos = avio_tell(pb);
      int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0;
 +    unsigned avg_bitrate;
  
      avio_wb32(pb, 0); // size
      ffio_wfourcc(pb, "esds");
      avio_w8(pb,  track->enc->rc_buffer_size>>(3+16));      // Buffersize DB (24 bits)
      avio_wb16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
  
 -    avio_wb32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
 -    if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
 -        avio_wb32(pb, 0); // vbr
 -    else
 -        avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate
 +    avg_bitrate = compute_avg_bitrate(track);
 +    // maxbitrate (FIXME should be max rate in any 1 sec window)
 +    avio_wb32(pb, FFMAX3(track->enc->bit_rate, track->enc->rc_max_rate, avg_bitrate));
 +    avio_wb32(pb, avg_bitrate);
  
      if (track->vos_len) {
          // DecoderSpecific info descriptor
      return update_size(pb, pos);
  }
  
 +static int mov_pcm_le_gt16(enum AVCodecID codec_id)
 +{
 +    return codec_id == AV_CODEC_ID_PCM_S24LE ||
 +           codec_id == AV_CODEC_ID_PCM_S32LE ||
 +           codec_id == AV_CODEC_ID_PCM_F32LE ||
 +           codec_id == AV_CODEC_ID_PCM_F64LE;
 +}
 +
  static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
  {
      int64_t pos = avio_tell(pb);
@@@ -407,11 -377,9 +407,11 @@@ static int mov_write_wave_tag(AVIOConte
      avio_wb32(pb, 0);     /* size */
      ffio_wfourcc(pb, "wave");
  
 +    if (track->enc->codec_id != AV_CODEC_ID_QDM2) {
      avio_wb32(pb, 12);    /* size */
      ffio_wfourcc(pb, "frma");
      avio_wl32(pb, track->tag);
 +    }
  
      if (track->enc->codec_id == AV_CODEC_ID_AAC) {
          /* useless atom needed by mplayer, ipod, not needed by quicktime */
          ffio_wfourcc(pb, "mp4a");
          avio_wb32(pb, 0);
          mov_write_esds_tag(pb, track);
 +    } else if (mov_pcm_le_gt16(track->enc->codec_id)) {
 +        mov_write_enda_tag(pb);
      } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
          mov_write_amr_tag(pb, track);
      } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
          mov_write_ac3_tag(pb, track);
 -    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC) {
 +    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC ||
 +               track->enc->codec_id == AV_CODEC_ID_QDM2) {
          mov_write_extradata_tag(pb, track);
      } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
                 track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
@@@ -587,8 -552,6 +587,8 @@@ static int get_samples_per_packet(MOVTr
  {
      int i, first_duration;
  
 +// return track->enc->frame_size;
 +
      /* use 1 for raw PCM */
      if (!track->audio_vbr)
          return 1;
@@@ -611,16 -574,9 +611,16 @@@ static int mov_write_audio_tag(AVIOCont
      uint32_t tag = track->tag;
  
      if (track->mode == MODE_MOV) {
 -        if (mov_get_lpcm_flags(track->enc->codec_id))
 -            tag = AV_RL32("lpcm");
 -        version = 2;
 +        if (track->timescale > UINT16_MAX) {
 +            if (mov_get_lpcm_flags(track->enc->codec_id))
 +                tag = AV_RL32("lpcm");
 +            version = 2;
 +        } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
 +                   track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
 +                   track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
 +                   track->enc->codec_id == AV_CODEC_ID_QDM2) {
 +            version = 1;
 +        }
      }
  
      avio_wb32(pb, 0); /* size */
          avio_wb32(pb, track->sample_size);
          avio_wb32(pb, get_samples_per_packet(track));
      } else {
 -        /* reserved for mp4/3gp */
 -        avio_wb16(pb, 2);
 -        avio_wb16(pb, 16);
 -        avio_wb16(pb, 0);
 +        if (track->mode == MODE_MOV) {
 +            avio_wb16(pb, track->enc->channels);
 +            if (track->enc->codec_id == AV_CODEC_ID_PCM_U8 ||
 +                track->enc->codec_id == AV_CODEC_ID_PCM_S8)
 +                avio_wb16(pb, 8); /* bits per sample */
 +            else
 +                avio_wb16(pb, 16);
 +            avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
 +        } else { /* reserved for mp4/3gp */
 +            avio_wb16(pb, 2);
 +            avio_wb16(pb, 16);
 +            avio_wb16(pb, 0);
 +        }
  
          avio_wb16(pb, 0); /* packet size (= 0) */
          avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
          avio_wb16(pb, 0); /* Reserved */
      }
  
 +    if(version == 1) { /* SoundDescription V1 extended info */
 +        avio_wb32(pb, track->enc->frame_size); /* Samples per packet */
 +        avio_wb32(pb, track->sample_size / track->enc->channels); /* Bytes per packet */
 +        avio_wb32(pb, track->sample_size); /* Bytes per frame */
 +        avio_wb32(pb, 2); /* Bytes per sample */
 +    }
 +
      if(track->mode == MODE_MOV &&
         (track->enc->codec_id == AV_CODEC_ID_AAC ||
          track->enc->codec_id == AV_CODEC_ID_AC3 ||
          track->enc->codec_id == AV_CODEC_ID_AMR_NB ||
          track->enc->codec_id == AV_CODEC_ID_ALAC ||
          track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
 -        track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV))
 +        track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
 +        track->enc->codec_id == AV_CODEC_ID_QDM2 ||
 +        (mov_pcm_le_gt16(track->enc->codec_id) && version==1)))
          mov_write_wave_tag(pb, track);
      else if(track->tag == MKTAG('m','p','4','a'))
          mov_write_esds_tag(pb, track);
@@@ -717,6 -655,19 +717,6 @@@ static int mov_write_d263_tag(AVIOConte
      return 0xf;
  }
  
 -/* TODO: No idea about these values */
 -static int mov_write_svq3_tag(AVIOContext *pb)
 -{
 -    avio_wb32(pb, 0x15);
 -    ffio_wfourcc(pb, "SMI ");
 -    ffio_wfourcc(pb, "SEQH");
 -    avio_wb32(pb, 0x5);
 -    avio_wb32(pb, 0xe2c0211d);
 -    avio_wb32(pb, 0xc0000000);
 -    avio_w8(pb, 0);
 -    return 0x15;
 -}
 -
  static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
  {
      int64_t pos = avio_tell(pb);
@@@ -851,7 -802,6 +851,7 @@@ static const struct 
      uint32_t tag;
      unsigned bps;
  } mov_pix_fmt_tags[] = {
 +    { PIX_FMT_YUYV422, MKTAG('y','u','v','2'),  0 },
      { PIX_FMT_YUYV422, MKTAG('y','u','v','s'),  0 },
      { PIX_FMT_UYVY422, MKTAG('2','v','u','y'),  0 },
      { PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 },
@@@ -874,7 -824,7 +874,7 @@@ static int mov_get_rawvideo_codec_tag(A
      int i;
  
      for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
 -        if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
 +        if (track->enc->codec_tag == mov_pix_fmt_tags[i].tag && track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
              tag = mov_pix_fmt_tags[i].tag;
              track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
              break;
@@@ -1063,11 -1013,9 +1063,11 @@@ static int mov_write_video_tag(AVIOCont
          mov_write_esds_tag(pb, track);
      else if(track->enc->codec_id == AV_CODEC_ID_H263)
          mov_write_d263_tag(pb);
 -    else if(track->enc->codec_id == AV_CODEC_ID_SVQ3)
 -        mov_write_svq3_tag(pb);
 -    else if(track->enc->codec_id == AV_CODEC_ID_DNXHD)
 +    else if(track->enc->codec_id == AV_CODEC_ID_AVUI ||
 +            track->enc->codec_id == AV_CODEC_ID_SVQ3) {
 +        mov_write_extradata_tag(pb, track);
 +        avio_wb32(pb, 0);
 +    } else if(track->enc->codec_id == AV_CODEC_ID_DNXHD)
          mov_write_avid_tag(pb, track);
      else if(track->enc->codec_id == AV_CODEC_ID_H264) {
          mov_write_avcc_tag(pb, track);
      return update_size(pb, pos);
  }
  
 +static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
 +{
 +    int64_t pos = avio_tell(pb);
 +    int frame_duration = track->enc->time_base.num;
 +    int nb_frames = (track->timescale + frame_duration/2) / frame_duration;
 +
 +    avio_wb32(pb, 0); /* size */
 +    ffio_wfourcc(pb, "tmcd");               /* Data format */
 +    avio_wb32(pb, 0);                       /* Reserved */
 +    avio_wb32(pb, 1);                       /* Data reference index */
 +    avio_wb32(pb, 0);                       /* Flags */
 +    avio_wb32(pb, track->timecode_flags);   /* Flags (timecode) */
 +    avio_wb32(pb, track->timescale);        /* Timescale */
 +    avio_wb32(pb, frame_duration);          /* Frame duration */
 +    avio_w8(pb, nb_frames);                 /* Number of frames */
 +    avio_wb24(pb, 0);                       /* Reserved */
 +    /* TODO: source reference string */
 +    return update_size(pb, pos);
 +}
 +
  static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track)
  {
      int64_t pos = avio_tell(pb);
@@@ -1143,8 -1071,6 +1143,8 @@@ static int mov_write_stsd_tag(AVIOConte
          mov_write_subtitle_tag(pb, track);
      else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
          mov_write_rtp_tag(pb, track);
 +    else if (track->enc->codec_tag == MKTAG('t','m','c','d'))
 +        mov_write_tmcd_tag(pb, track);
      return update_size(pb, pos);
  }
  
@@@ -1231,7 -1157,6 +1231,7 @@@ static int mov_write_dref_tag(AVIOConte
      avio_wb32(pb, 1); /* entry count */
  
      avio_wb32(pb, 0xc); /* size */
 +    //FIXME add the alis and rsrc atom
      ffio_wfourcc(pb, "url ");
      avio_wb32(pb, 1); /* version & flags */
  
@@@ -1277,32 -1202,9 +1277,32 @@@ static int mov_write_nmhd_tag(AVIOConte
      return 12;
  }
  
 -static int mov_write_gmhd_tag(AVIOContext *pb)
 +static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track)
 +{
 +    int64_t pos = avio_tell(pb);
 +    const char *font = "Lucida Grande";
 +    avio_wb32(pb, 0);                   /* size */
 +    ffio_wfourcc(pb, "tcmi");           /* timecode media information atom */
 +    avio_wb32(pb, 0);                   /* version & flags */
 +    avio_wb16(pb, 0);                   /* text font */
 +    avio_wb16(pb, 0);                   /* text face */
 +    avio_wb16(pb, 12);                  /* text size */
 +    avio_wb16(pb, 0);                   /* (unknown, not in the QT specs...) */
 +    avio_wb16(pb, 0x0000);              /* text color (red) */
 +    avio_wb16(pb, 0x0000);              /* text color (green) */
 +    avio_wb16(pb, 0x0000);              /* text color (blue) */
 +    avio_wb16(pb, 0xffff);              /* background color (red) */
 +    avio_wb16(pb, 0xffff);              /* background color (green) */
 +    avio_wb16(pb, 0xffff);              /* background color (blue) */
 +    avio_w8(pb, strlen(font));          /* font len (part of the pascal string) */
 +    avio_write(pb, font, strlen(font)); /* font name */
 +    return update_size(pb, pos);
 +}
 +
 +static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
  {
 -    avio_wb32(pb, 0x20);   /* size */
 +    int64_t pos = avio_tell(pb);
 +    avio_wb32(pb, 0);      /* size */
      ffio_wfourcc(pb, "gmhd");
      avio_wb32(pb, 0x18);   /* gmin size */
      ffio_wfourcc(pb, "gmin");/* generic media info */
      avio_wb16(pb, 0x8000); /* opColor (b?) */
      avio_wb16(pb, 0);      /* balance */
      avio_wb16(pb, 0);      /* reserved */
 -    return 0x20;
 +
 +    /*
 +     * This special text atom is required for
 +     * Apple Quicktime chapters. The contents
 +     * don't appear to be documented, so the
 +     * bytes are copied verbatim.
 +     */
 +    avio_wb32(pb, 0x2C);   /* size */
 +    ffio_wfourcc(pb, "text");
 +    avio_wb16(pb, 0x01);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x01);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x00);
 +    avio_wb32(pb, 0x00004000);
 +    avio_wb16(pb, 0x0000);
 +
 +    if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
 +        int64_t tmcd_pos = avio_tell(pb);
 +        avio_wb32(pb, 0); /* size */
 +        ffio_wfourcc(pb, "tmcd");
 +        mov_write_tcmi_tag(pb, track);
 +        update_size(pb, tmcd_pos);
 +    }
 +    return update_size(pb, pos);
  }
  
  static int mov_write_smhd_tag(AVIOContext *pb)
@@@ -1383,16 -1258,9 +1383,16 @@@ static int mov_write_hdlr_tag(AVIOConte
              if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
              else                                      hdlr_type = "text";
              descr = "SubtitleHandler";
 +        } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
 +            hdlr_type = "tmcd";
 +            descr = "TimeCodeHandler";
          } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
              hdlr_type = "hint";
              descr = "HintHandler";
 +        } else {
 +            hdlr = "dhlr";
 +            hdlr_type = "url ";
 +            descr = "DataHandler";
          }
      }
  
@@@ -1437,10 -1305,8 +1437,10 @@@ static int mov_write_minf_tag(AVIOConte
      else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
          mov_write_smhd_tag(pb);
      else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 -        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
 +        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb, track);
          else                                      mov_write_nmhd_tag(pb);
 +    } else if (track->tag == MKTAG('t','m','c','d')) {
 +        mov_write_gmhd_tag(pb, track);
      } else if (track->tag == MKTAG('r','t','p',' ')) {
          mov_write_hmhd_tag(pb);
      }
@@@ -1498,30 -1364,11 +1498,30 @@@ static int mov_write_mdia_tag(AVIOConte
      return update_size(pb, pos);
  }
  
 +/* transformation matrix
 +     |a  b  u|
 +     |c  d  v|
 +     |tx ty w| */
 +static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c,
 +                         int16_t d, int16_t tx, int16_t ty)
 +{
 +    avio_wb32(pb, a << 16);  /* 16.16 format */
 +    avio_wb32(pb, b << 16);  /* 16.16 format */
 +    avio_wb32(pb, 0);        /* u in 2.30 format */
 +    avio_wb32(pb, c << 16);  /* 16.16 format */
 +    avio_wb32(pb, d << 16);  /* 16.16 format */
 +    avio_wb32(pb, 0);        /* v in 2.30 format */
 +    avio_wb32(pb, tx << 16); /* 16.16 format */
 +    avio_wb32(pb, ty << 16); /* 16.16 format */
 +    avio_wb32(pb, 1 << 30);  /* w in 2.30 format */
 +}
 +
  static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
  {
      int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
                                        track->timescale, AV_ROUND_UP);
      int version = duration < INT32_MAX ? 0 : 1;
 +    int rotation = 0;
  
      if (track->mode == MODE_ISM)
          version = 1;
      avio_wb16(pb, 0); /* reserved */
  
      /* Matrix structure */
 -    avio_wb32(pb, 0x00010000); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x00010000); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x40000000); /* reserved */
 -
 +    if (st && st->metadata) {
 +        AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);
 +        rotation = (rot && rot->value) ? atoi(rot->value) : 0;
 +    }
 +    if (rotation == 90) {
 +        write_matrix(pb,  0,  1, -1,  0, track->enc->height, 0);
 +    } else if (rotation == 180) {
 +        write_matrix(pb, -1,  0,  0, -1, track->enc->width, track->enc->height);
 +    } else if (rotation == 270) {
 +        write_matrix(pb,  0, -1,  1,  0, 0, track->enc->width);
 +    } else {
 +        write_matrix(pb,  1,  0,  0,  1, 0, 0);
 +    }
      /* Track width and height, for visual only */
      if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
                track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
@@@ -1718,8 -1562,11 +1718,8 @@@ static int mov_write_trak_tag(AVIOConte
      avio_wb32(pb, 0); /* size */
      ffio_wfourcc(pb, "trak");
      mov_write_tkhd_tag(pb, track, st);
 -    if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS ||
 -        (track->entry && track->cluster[0].dts)) {
 -        if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
 -            mov_write_edts_tag(pb, track);  // PSP Movies require edts box
 -    }
 +    if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) // EDTS with fragments is tricky as we dont know the duration when its written
 +        mov_write_edts_tag(pb, track);  // PSP Movies and several other cases require edts box
      if (track->tref_tag)
          mov_write_tref_tag(pb, track);
      mov_write_mdia_tag(pb, track);
          mov_write_udta_sdp(pb, track->rtp_ctx, track->track_id);
      if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
          double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
 -        if (0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)
 +        if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio)
              mov_write_tapt_tag(pb, track);
      };
      return update_size(pb, pos);
@@@ -1829,7 -1676,15 +1829,7 @@@ static int mov_write_mvhd_tag(AVIOConte
      avio_wb32(pb, 0); /* reserved */
  
      /* Matrix structure */
 -    avio_wb32(pb, 0x00010000); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x00010000); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x0); /* reserved */
 -    avio_wb32(pb, 0x40000000); /* reserved */
 +    write_matrix(pb, 1, 0, 0, 1, 0, 0);
  
      avio_wb32(pb, 0); /* reserved (preview time) */
      avio_wb32(pb, 0); /* reserved (preview duration) */
@@@ -1913,24 -1768,6 +1913,24 @@@ static int mov_write_string_metadata(AV
      return mov_write_string_tag(pb, name, t->value, lang, long_style);
  }
  
 +/* iTunes bpm number */
 +static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
 +{
 +    AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0);
 +    int size = 0, tmpo = t ? atoi(t->value) : 0;
 +    if (tmpo) {
 +        size = 26;
 +        avio_wb32(pb, size);
 +        ffio_wfourcc(pb, "tmpo");
 +        avio_wb32(pb, size-8); /* size */
 +        ffio_wfourcc(pb, "data");
 +        avio_wb32(pb, 0x15);  //type specifier
 +        avio_wb32(pb, 0);
 +        avio_wb16(pb, tmpo);        // data
 +    }
 +    return size;
 +}
 +
  /* iTunes track number */
  static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
                                AVFormatContext *s)
@@@ -1978,7 -1815,6 +1978,7 @@@ static int mov_write_ilst_tag(AVIOConte
      mov_write_string_metadata(s, pb, "tven",    "episode_id",1);
      mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);
      mov_write_trkn_tag(pb, mov, s);
 +    mov_write_tmpo_tag(pb, s);
      return update_size(pb, pos);
  }
  
@@@ -2088,35 -1924,32 +2088,35 @@@ static int mov_write_udta_tag(AVIOConte
      if(ret < 0)
          return ret;
  
 -        if (mov->mode & MODE_3GP) {
 -            mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
 -            mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
 -            mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
 -            mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
 -            mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
 -            mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
 -            mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
 -            mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
 -        } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
 -            mov_write_string_metadata(s, pb_buf, "\251ART", "artist"     , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251nam", "title"      , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251aut", "author"     , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251alb", "album"      , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251day", "date"       , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251swr", "encoder"    , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251des", "comment"    , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251gen", "genre"      , 0);
 -            mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright"  , 0);
 -        } else {
 -            /* iTunes meta data */
 -            mov_write_meta_tag(pb_buf, mov, s);
 -        }
 +    if (mov->mode & MODE_3GP) {
 +        mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
 +        mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
 +        mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
 +        mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
 +        mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
 +        mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
 +        mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
 +        mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
 +    } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
 +        mov_write_string_metadata(s, pb_buf, "\251ART", "artist"     , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251nam", "title"      , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251aut", "author"     , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251alb", "album"      , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251day", "date"       , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251swr", "encoder"    , 0);
 +        // currently ignored by mov.c
 +        mov_write_string_metadata(s, pb_buf, "\251des", "comment"    , 0);
 +        // add support for libquicktime, this atom is also actually read by mov.c
 +        mov_write_string_metadata(s, pb_buf, "\251cmt", "comment"    , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251gen", "genre"      , 0);
 +        mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright"  , 0);
 +    } else {
 +        /* iTunes meta data */
 +        mov_write_meta_tag(pb_buf, mov, s);
 +    }
  
 -        if (s->nb_chapters)
 -            mov_write_chpl_tag(pb_buf, s);
 +    if (s->nb_chapters)
 +        mov_write_chpl_tag(pb_buf, s);
  
      if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
          avio_wb32(pb, size+8);
@@@ -2179,29 -2012,6 +2179,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)
  {
  
          mov->tracks[i].time = mov->time;
          mov->tracks[i].track_id = i+1;
 +
 +        if (mov->tracks[i].entry)
 +            build_chunks(&mov->tracks[i]);
      }
  
      if (mov->chapter_track)
                  mov->tracks[mov->tracks[i].src_track].track_id;
          }
      }
 +    for (i = 0; i < mov->nb_streams; i++) {
 +        if (mov->tracks[i].tag == MKTAG('t','m','c','d')) {
 +            int src_trk = mov->tracks[i].src_track;
 +            mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
 +            mov->tracks[src_trk].tref_id  = mov->tracks[i].track_id;
 +            mov->tracks[i].track_duration = mov->tracks[src_trk].track_duration;
 +        }
 +    }
  
      mov_write_mvhd_tag(pb, mov);
      if (mov->mode != MODE_MOV && !mov->iods_skip)
@@@ -3031,9 -2830,6 +3031,9 @@@ int ff_mov_write_packet(AVFormatContex
              av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
              return -1;
          }
 +    } else if (enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
 +               enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
 +        samples_in_chunk = enc->frame_size;
      } else if (trk->sample_size)
          samples_in_chunk = size / trk->sample_size;
      else
          } else {
              size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
          }
 +    } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
 +               (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
 +        av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
 +        return -1;
      } else {
          avio_write(pb, pkt->data, size);
      }
      }
  
      if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
 -        trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster));
 +        trk->cluster = av_realloc_f(trk->cluster, sizeof(*trk->cluster), (trk->entry + MOV_INDEX_CLUSTER_SIZE));
          if (!trk->cluster)
              return -1;
      }
  
      trk->cluster[trk->entry].pos = avio_tell(pb) - size;
      trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk;
 +    trk->cluster[trk->entry].chunkNum = 0;
      trk->cluster[trk->entry].size = size;
      trk->cluster[trk->entry].entries = samples_in_chunk;
      trk->cluster[trk->entry].dts = pkt->dts;
      if (trk->start_dts == AV_NOPTS_VALUE)
          trk->start_dts = pkt->dts;
      trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
 +    trk->last_sample_is_subtitle_end = 0;
  
      if (pkt->pts == AV_NOPTS_VALUE) {
          av_log(s, AV_LOG_WARNING, "pts has no value\n");
      return 0;
  }
  
 -static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
 +static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
  {
 -    if (!pkt) {
 -        mov_flush_fragment(s);
 -        return 1;
 -    } else {
          MOVMuxContext *mov = s->priv_data;
          MOVTrack *trk = &mov->tracks[pkt->stream_index];
          AVCodecContext *enc = trk->enc;
  
          if (!pkt->size) return 0; /* Discard 0 sized packets */
  
 -        if (trk->entry)
 +        if (trk->entry && pkt->stream_index < s->nb_streams)
              frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
                                           s->streams[pkt->stream_index]->time_base,
                                           AV_TIME_BASE_Q);
          }
  
          return ff_mov_write_packet(s, pkt);
 +}
 +
 +static int mov_write_subtitle_end_packet(AVFormatContext *s,
 +                                         int stream_index,
 +                                         int64_t dts) {
 +    AVPacket end;
 +    uint8_t data[2] = {0};
 +    int ret;
 +
 +    av_init_packet(&end);
 +    end.size = sizeof(data);
 +    end.data = data;
 +    end.pts = dts;
 +    end.dts = dts;
 +    end.duration = 0;
 +    end.stream_index = stream_index;
 +
 +    ret = mov_write_single_packet(s, &end);
 +    av_free_packet(&end);
 +
 +    return ret;
 +}
 +
 +static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
 +{
 +    if (!pkt) {
 +        mov_flush_fragment(s);
 +        return 1;
 +    } else {
 +        int i;
 +        MOVMuxContext *mov = s->priv_data;
 +
 +        if (!pkt->size) return 0; /* Discard 0 sized packets */
 +
 +        /*
 +         * Subtitles require special handling.
 +         *
 +         * 1) For full complaince, every track must have a sample at
 +         * dts == 0, which is rarely true for subtitles. So, as soon
 +         * as we see any packet with dts > 0, write an empty subtitle
 +         * at dts == 0 for any subtitle track with no samples in it.
 +         *
 +         * 2) For each subtitle track, check if the current packet's
 +         * dts is past the duration of the last subtitle sample. If
 +         * so, we now need to write an end sample for that subtitle.
 +         *
 +         * This must be done conditionally to allow for subtitles that
 +         * immediately replace each other, in which case an end sample
 +         * is not needed, and is, in fact, actively harmful.
 +         *
 +         * 3) See mov_write_trailer for how the final end sample is
 +         * handled.
 +         */
 +        for (i = 0; i < mov->nb_streams; i++) {
 +            MOVTrack *trk = &mov->tracks[i];
 +            int ret;
 +
 +            if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
 +                trk->track_duration < pkt->dts &&
 +                (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
 +                ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
 +                if (ret < 0) return ret;
 +                trk->last_sample_is_subtitle_end = 1;
 +            }
 +        }
 +
 +        return mov_write_single_packet(s, pkt);
      }
  }
  
  // as samples, and a tref pointing from the other tracks to the chapter one.
  static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
  {
 +    AVIOContext *pb;
 +
      MOVMuxContext *mov = s->priv_data;
      MOVTrack *track = &mov->tracks[tracknum];
      AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
      track->enc = avcodec_alloc_context3(NULL);
      track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
  
 +    if (avio_open_dyn_buf(&pb) >= 0) {
 +        int size;
 +        uint8_t *buf;
 +
 +        /* Stub header (usually for Quicktime chapter track) */
 +        // TextSampleEntry
 +        avio_wb32(pb, 0x01); // displayFlags
 +        avio_w8(pb, 0x00);   // horizontal justification
 +        avio_w8(pb, 0x00);   // vertical justification
 +        avio_w8(pb, 0x00);   // bgColourRed
 +        avio_w8(pb, 0x00);   // bgColourGreen
 +        avio_w8(pb, 0x00);   // bgColourBlue
 +        avio_w8(pb, 0x00);   // bgColourAlpha
 +        // BoxRecord
 +        avio_wb16(pb, 0x00); // defTextBoxTop
 +        avio_wb16(pb, 0x00); // defTextBoxLeft
 +        avio_wb16(pb, 0x00); // defTextBoxBottom
 +        avio_wb16(pb, 0x00); // defTextBoxRight
 +        // StyleRecord
 +        avio_wb16(pb, 0x00); // startChar
 +        avio_wb16(pb, 0x00); // endChar
 +        avio_wb16(pb, 0x01); // fontID
 +        avio_w8(pb, 0x00);   // fontStyleFlags
 +        avio_w8(pb, 0x00);   // fontSize
 +        avio_w8(pb, 0x00);   // fgColourRed
 +        avio_w8(pb, 0x00);   // fgColourGreen
 +        avio_w8(pb, 0x00);   // fgColourBlue
 +        avio_w8(pb, 0x00);   // fgColourAlpha
 +        // FontTableBox
 +        avio_wb32(pb, 0x0D); // box size
 +        ffio_wfourcc(pb, "ftab"); // box atom name
 +        avio_wb16(pb, 0x01); // entry count
 +        // FontRecord
 +        avio_wb16(pb, 0x01); // font ID
 +        avio_w8(pb, 0x00);   // font name length
 +
 +        if ((size = avio_close_dyn_buf(pb, &buf)) > 0) {
 +            track->enc->extradata = buf;
 +            track->enc->extradata_size = size;
 +        } else {
 +            av_free(&buf);
 +        }
 +    }
 +
      for (i = 0; i < s->nb_chapters; i++) {
          AVChapter *c = s->chapters[i];
          AVDictionaryEntry *t;
      }
  }
  
 +static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, const char *tcstr)
 +{
 +    int ret;
 +    MOVMuxContext *mov  = s->priv_data;
 +    MOVTrack *track     = &mov->tracks[index];
 +    AVStream *src_st    = s->streams[src_index];
 +    AVTimecode tc;
 +    AVPacket pkt    = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4};
 +    AVRational rate = {src_st->codec->time_base.den, src_st->codec->time_base.num};
 +
 +    /* if the codec time base makes no sense, try to fallback on stream frame rate */
 +    if (av_timecode_check_frame_rate(rate) < 0) {
 +        av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
 +               rate.num, rate.den, src_st->avg_frame_rate.num, src_st->avg_frame_rate.den);
 +        rate = src_st->avg_frame_rate;
 +    }
 +
 +    /* compute the frame number */
 +    ret = av_timecode_init_from_string(&tc, rate, tcstr, s);
 +    if (ret < 0)
 +        return ret;
 +
 +    /* tmcd track based on video stream */
 +    track->mode      = mov->mode;
 +    track->tag       = MKTAG('t','m','c','d');
 +    track->src_track = src_index;
 +    track->timescale = src_st->codec->time_base.den;
 +    if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
 +        track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
 +
 +    /* encode context: tmcd data stream */
 +    track->enc = avcodec_alloc_context3(NULL);
 +    track->enc->codec_type = AVMEDIA_TYPE_DATA;
 +    track->enc->codec_tag  = track->tag;
 +    track->enc->time_base  = src_st->codec->time_base;
 +
 +    /* the tmcd track just contains one packet with the frame number */
 +    pkt.data = av_malloc(pkt.size);
 +    AV_WB32(pkt.data, tc.start);
 +    ret = ff_mov_write_packet(s, &pkt);
 +    av_free(pkt.data);
 +    return ret;
 +}
 +
  static int mov_write_header(AVFormatContext *s)
  {
      AVIOContext *pb = s->pb;
      MOVMuxContext *mov = s->priv_data;
 -    AVDictionaryEntry *t;
 -    int i, hint_track = 0;
 +    AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
 +    int i, hint_track = 0, tmcd_track = 0;
  
      /* Set the FRAGMENT flag if any of the fragmentation methods are
       * enabled. */
          }
      }
  
 +    if (mov->mode == MODE_MOV) {
 +        tmcd_track = mov->nb_streams;
 +
 +        /* +1 tmcd track for each video stream with a timecode */
 +        for (i = 0; i < s->nb_streams; i++) {
 +            AVStream *st = s->streams[i];
 +            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
 +                (global_tcr || av_dict_get(st->metadata, "timecode", NULL, 0)))
 +                mov->nb_meta_tmcd++;
 +        }
 +
 +        /* check if there is already a tmcd track to remux */
 +        if (mov->nb_meta_tmcd) {
 +            for (i = 0; i < s->nb_streams; i++) {
 +                AVStream *st = s->streams[i];
 +                if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
 +                    av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
 +                           "so timecode metadata are now ignored\n");
 +                    mov->nb_meta_tmcd = 0;
 +                }
 +            }
 +        }
 +
 +        mov->nb_streams += mov->nb_meta_tmcd;
 +    }
 +
      mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
      if (!mov->tracks)
          return AVERROR(ENOMEM);
                         "or choose different container.\n");
          }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
              track->timescale = st->codec->sample_rate;
 -            /* set sample_size for PCM and ADPCM */
 -            if (av_get_bits_per_sample(st->codec->codec_id) ||
 -                st->codec->codec_id == AV_CODEC_ID_ILBC) {
 +            if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
 +                av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
 +                track->audio_vbr = 1;
 +            }else if(st->codec->codec_id == AV_CODEC_ID_ADPCM_MS ||
 +                     st->codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
 +                     st->codec->codec_id == AV_CODEC_ID_ILBC){
                  if (!st->codec->block_align) {
 -                    av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set\n", i);
 +                    av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
                      goto error;
                  }
                  track->sample_size = st->codec->block_align;
 -            }
 -            /* set audio_vbr for compressed audio */
 -            if (av_get_bits_per_sample(st->codec->codec_id) < 8) {
 +            }else if(st->codec->frame_size > 1){ /* assume compressed audio */
                  track->audio_vbr = 1;
 +            }else{
 +                track->sample_size = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
              }
              if (track->mode != MODE_MOV &&
                  track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
              }
          }else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
              track->timescale = st->codec->time_base.den;
 +        }else{
 +            track->timescale = MOV_TIMESCALE;
          }
          if (!track->height)
              track->height = st->codec->height;
                        FF_MOV_FLAG_FRAGMENT;
      }
  
 +    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 (mov->nb_meta_tmcd) {
 +        /* Initialize the tmcd tracks */
 +        for (i = 0; i < s->nb_streams; i++) {
 +            AVStream *st = s->streams[i];
 +            t = global_tcr;
 +
 +            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 +                if (!t)
 +                    t = av_dict_get(st->metadata, "timecode", NULL, 0);
 +                if (!t)
 +                    continue;
 +                if (mov_create_timecode_track(s, tmcd_track, i, t->value) < 0)
 +                    goto error;
 +                tmcd_track++;
 +            }
 +        }
 +    }
 +
      avio_flush(pb);
  
      if (mov->flags & FF_MOV_FLAG_ISML)
@@@ -3603,24 -3186,10 +3603,24 @@@ static int mov_write_trailer(AVFormatCo
  {
      MOVMuxContext *mov = s->priv_data;
      AVIOContext *pb = s->pb;
 +    int64_t moov_pos;
      int res = 0;
      int i;
  
 -    int64_t moov_pos = avio_tell(pb);
 +    /*
 +     * Before actually writing the trailer, make sure that there are no
 +     * dangling subtitles, that need a terminating sample.
 +     */
 +    for (i = 0; i < mov->nb_streams; i++) {
 +        MOVTrack *trk = &mov->tracks[i];
 +        if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
 +            !trk->last_sample_is_subtitle_end) {
 +            mov_write_subtitle_end_packet(s, i, trk->track_duration);
 +            trk->last_sample_is_subtitle_end = 1;
 +        }
 +    }
 +
 +    moov_pos = avio_tell(pb);
  
      if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
          /* Write size of mdat tag */
              ffio_wfourcc(pb, "mdat");
              avio_wb64(pb, mov->mdat_size + 16);
          }
 -        avio_seek(pb, moov_pos, SEEK_SET);
 +        avio_seek(pb, mov->reserved_moov_size ? mov->reserved_moov_pos : moov_pos, SEEK_SET);
  
          mov_write_moov_tag(pb, mov, s);
 +        if(mov->reserved_moov_size){
 +            int64_t size=  mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_moov_pos);
 +            if(size < 8){
 +                av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size);
 +                return -1;
 +            }
 +            avio_wb32(pb, size);
 +            ffio_wfourcc(pb, "free");
 +            for(i=0; i<size; i++)
 +                avio_w8(pb, 0);
 +            avio_seek(pb, moov_pos, SEEK_SET);
 +        }
      } else {
          mov_flush_fragment(s);
          mov_write_mfra_tag(pb, mov);
      for (i=0; i<mov->nb_streams; i++) {
          if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
              ff_mov_close_hinting(&mov->tracks[i]);
 +        else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
 +            av_freep(&mov->tracks[i].enc);
          if (mov->flags & FF_MOV_FLAG_FRAGMENT &&
              mov->tracks[i].vc1_info.struct_offset && s->pb->seekable) {
              int64_t off = avio_tell(pb);
diff --combined libavformat/mpegtsenc.c
index 1c0c4c67a472b2afe5d76422b3a3d74873954474,ac659ce8ae4505a6d4f7f00237636f6fe3d9b003..0ebf1729053c1febb146d6e1abe7c87ee9c817ca
@@@ -2,20 -2,20 +2,20 @@@
   * MPEG2 transport stream (aka DVB) muxer
   * Copyright (c) 2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
@@@ -24,7 -24,6 +24,7 @@@
  #include "libavutil/dict.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/opt.h"
 +#include "libavutil/avassert.h"
  #include "libavcodec/mpegvideo.h"
  #include "avformat.h"
  #include "internal.h"
@@@ -76,14 -75,12 +76,14 @@@ typedef struct MpegTSWrite 
  
      int pmt_start_pid;
      int start_pid;
 +    int m2ts_mode;
  
      int reemit_pat_pmt; // backward compatibility
  
  #define MPEGTS_FLAG_REEMIT_PAT_PMT  0x01
  #define MPEGTS_FLAG_AAC_LATM        0x02
      int flags;
 +    int copyts;
  } MpegTSWrite;
  
  /* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
@@@ -98,16 -95,13 +98,16 @@@ static const AVOption options[] = 
      { "mpegts_service_id", "Set service_id field.",
        offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, {.dbl = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM},
      { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
 -      offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT, {.dbl = 0x1000 }, 0x1000, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM},
 +      offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT, {.dbl = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM},
      { "mpegts_start_pid", "Set the first pid.",
        offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT, {.dbl = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM},
 +    {"mpegts_m2ts_mode", "Enable m2ts mode.",
 +        offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT, {.dbl = -1 },
 +        -1,1, AV_OPT_FLAG_ENCODING_PARAM},
      { "muxrate", NULL, offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, {1}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
      { "pes_payload_size", "Minimum PES packet payload in bytes",
        offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, {DEFAULT_PES_PAYLOAD_SIZE}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
-     { "mpegts_flags", "MPEG-TS muxing flags", offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, 0, INT_MAX,
+     { "mpegts_flags", "MPEG-TS muxing flags", offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX,
        AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" },
      { "resend_headers", "Reemit PAT/PMT before writing the next packet",
        0, AV_OPT_TYPE_CONST, {.i64 = MPEGTS_FLAG_REEMIT_PAT_PMT}, 0, INT_MAX,
      // backward compatibility
      { "resend_headers", "Reemit PAT/PMT before writing the next packet",
        offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
 +    { "mpegts_copyts", "dont offset dts/pts",
 +      offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT, {.dbl=-1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
      { NULL },
  };
  
@@@ -198,7 -190,7 +198,7 @@@ static int mpegts_write_section1(MpegTS
      tot_len = 3 + 5 + len + 4;
      /* check if not too big */
      if (tot_len > 1024)
 -        return -1;
 +        return AVERROR_INVALIDDATA;
  
      q = section;
      *q++ = tid;
  /*********************************************/
  /* mpegts writer */
  
 -#define DEFAULT_PROVIDER_NAME   "Libav"
 +#define DEFAULT_PROVIDER_NAME   "FFmpeg"
  #define DEFAULT_SERVICE_NAME    "Service01"
  
  /* we retransmit the SI info at this rate */
@@@ -230,7 -222,6 +230,7 @@@ typedef struct MpegTSWriteStream 
      int cc;
      int payload_size;
      int first_pts_check; ///< first pts check needed
 +    int prev_payload_key;
      int64_t payload_pts;
      int64_t payload_dts;
      int payload_flags;
@@@ -316,20 -307,6 +316,20 @@@ static void mpegts_write_pmt(AVFormatCo
          /* write optional descriptors here */
          switch(st->codec->codec_type) {
          case AVMEDIA_TYPE_AUDIO:
 +            if(st->codec->codec_id==AV_CODEC_ID_EAC3){
 +                *q++=0x7a; // EAC3 descriptor see A038 DVB SI
 +                *q++=1; // 1 byte, all flags sets to 0
 +                *q++=0; // omit all fields...
 +            }
 +            if(st->codec->codec_id==AV_CODEC_ID_S302M){
 +                *q++ = 0x05; /* MPEG-2 registration descriptor*/
 +                *q++ = 4;
 +                *q++ = 'B';
 +                *q++ = 'S';
 +                *q++ = 'S';
 +                *q++ = 'D';
 +            }
 +
              if (lang) {
                  char *p;
                  char *next = lang->value;
@@@ -477,28 -454,9 +477,28 @@@ static MpegTSService *mpegts_add_servic
      return service;
  }
  
 +static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
 +{
 +    return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
 +           ts->first_pcr;
 +}
 +
 +static void mpegts_prefix_m2ts_header(AVFormatContext *s)
 +{
 +    MpegTSWrite *ts = s->priv_data;
 +    if (ts->m2ts_mode) {
 +        int64_t pcr = get_pcr(s->priv_data, s->pb);
 +        uint32_t tp_extra_header = pcr % 0x3fffffff;
 +        tp_extra_header = AV_RB32(&tp_extra_header);
 +        avio_write(s->pb, (unsigned char *) &tp_extra_header,
 +                sizeof(tp_extra_header));
 +    }
 +}
 +
  static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
  {
      AVFormatContext *ctx = s->opaque;
 +    mpegts_prefix_m2ts_header(ctx);
      avio_write(ctx->pb, packet, TS_PACKET_SIZE);
  }
  
@@@ -639,10 -597,9 +639,10 @@@ static int mpegts_write_header(AVFormat
          ts->pat_packet_period      = (ts->mux_rate * PAT_RETRANS_TIME) /
              (TS_PACKET_SIZE * 8 * 1000);
  
 -        ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
 +        if(ts->copyts < 1)
 +            ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
      } else {
 -        /* Arbitrary values, PAT/PMT could be written on key frames */
 +        /* Arbitrary values, PAT/PMT will also be written on video key frames */
          ts->sdt_packet_period = 200;
          ts->pat_packet_period = 40;
          if (pcr_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
              service->pcr_packet_period =
                  pcr_st->codec->time_base.den/(10*pcr_st->codec->time_base.num);
          }
 +        if(!service->pcr_packet_period)
 +            service->pcr_packet_period = 1;
      }
  
      // output a PCR as soon as possible
             service->pcr_packet_period,
             ts->sdt_packet_period, ts->pat_packet_period);
  
 +    if (ts->m2ts_mode == -1) {
 +        if (av_match_ext(s->filename, "m2ts")) {
 +            ts->m2ts_mode = 1;
 +        } else {
 +            ts->m2ts_mode = 0;
 +        }
 +    }
 +
      avio_flush(s->pb);
  
      return 0;
  }
  
  /* send SDT, PAT and PMT tables regulary */
 -static void retransmit_si_info(AVFormatContext *s)
 +static void retransmit_si_info(AVFormatContext *s, int force_pat)
  {
      MpegTSWrite *ts = s->priv_data;
      int i;
          ts->sdt_packet_count = 0;
          mpegts_write_sdt(s);
      }
 -    if (++ts->pat_packet_count == ts->pat_packet_period) {
 +    if (++ts->pat_packet_count == ts->pat_packet_period || force_pat) {
          ts->pat_packet_count = 0;
          mpegts_write_pat(s);
          for(i = 0; i < ts->nb_services; i++) {
      }
  }
  
 -static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
 -{
 -    return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
 -           ts->first_pcr;
 -}
 -
  static int write_pcr_bits(uint8_t *buf, int64_t pcr)
  {
      int64_t pcr_low = pcr % 300, pcr_high = pcr / 300;
@@@ -752,7 -705,6 +752,7 @@@ static void mpegts_insert_null_packet(A
      *q++ = 0xff;
      *q++ = 0x10;
      memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf));
 +    mpegts_prefix_m2ts_header(s);
      avio_write(s->pb, buf, TS_PACKET_SIZE);
  }
  
@@@ -778,7 -730,6 +778,7 @@@ static void mpegts_insert_pcr_only(AVFo
  
      /* stuffing bytes */
      memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
 +    mpegts_prefix_m2ts_header(s);
      avio_write(s->pb, buf, TS_PACKET_SIZE);
  }
  
@@@ -800,7 -751,7 +800,7 @@@ static void write_pts(uint8_t *q, int f
  static void set_af_flag(uint8_t *pkt, int flag)
  {
      // expect at least one flag to set
 -    assert(flag);
 +    av_assert0(flag);
  
      if ((pkt[3] & 0x20) == 0) {
          // no AF yet, set adaptation field flag
  static void extend_af(uint8_t *pkt, int size)
  {
      // expect already existing adaptation field
 -    assert(pkt[3] & 0x20);
 +    av_assert0(pkt[3] & 0x20);
      pkt[4] += size;
  }
  
@@@ -846,12 -797,10 +846,12 @@@ static void mpegts_write_pes(AVFormatCo
      int afc_len, stuffing_len;
      int64_t pcr = -1; /* avoid warning */
      int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
 +    int force_pat = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
  
      is_start = 1;
      while (payload_size > 0) {
 -        retransmit_si_info(s);
 +        retransmit_si_info(s, force_pat);
 +        force_pat = 0;
  
          write_pcr = 0;
          if (ts_st->pid == ts_st->service->pcr_pid) {
                          st->codec->codec_id == AV_CODEC_ID_MP3 ||
                          st->codec->codec_id == AV_CODEC_ID_AAC)) {
                  *q++ = 0xc0;
 +            } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
 +                        st->codec->codec_id == AV_CODEC_ID_AC3 &&
 +                        ts->m2ts_mode) {
 +                *q++ = 0xfd;
              } else {
                  *q++ = 0xbd;
                  if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
                  */
                  header_len += 3;
              }
 +            /* for Blu-ray AC3 Audio the PES Extension flag should be as follow
 +             * otherwise it will not play sound on blu-ray
 +             */
 +            if (ts->m2ts_mode &&
 +                st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
 +                st->codec->codec_id == AV_CODEC_ID_AC3) {
 +                        /* set PES_extension_flag */
 +                        pes_extension = 1;
 +                        flags |= 0x01;
 +                        header_len += 3;
 +            }
              len = payload_size + header_len + 3;
              if (private_code != 0)
                  len++;
                  */
                  *q++ = 0x00 | 0x60;
              }
 +            /* For Blu-ray AC3 Audio Setting extended flags */
 +          if (ts->m2ts_mode &&
 +              pes_extension &&
 +              st->codec->codec_id == AV_CODEC_ID_AC3) {
 +                      flags = 0x01; /* set PES_extension_flag_2 */
 +                      *q++ = flags;
 +                      *q++ = 0x80 | 0x01; /* marker bit + extension length */
 +                      *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */
 +              }
 +
 +
              if (private_code != 0)
                  *q++ = private_code;
              is_start = 0;
          memcpy(buf + TS_PACKET_SIZE - len, payload, len);
          payload += len;
          payload_size -= len;
 +        mpegts_prefix_m2ts_header(s);
          avio_write(s->pb, buf, TS_PACKET_SIZE);
      }
      avio_flush(s->pb);
 +    ts_st->prev_payload_key = key;
  }
  
  static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
      uint8_t *data= NULL;
      MpegTSWrite *ts = s->priv_data;
      MpegTSWriteStream *ts_st = st->priv_data;
 -    const uint64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE)*2;
 -    int64_t dts = AV_NOPTS_VALUE, pts = AV_NOPTS_VALUE;
 +    const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE)*2;
 +    int64_t dts = pkt->dts, pts = pkt->pts;
  
      if (ts->reemit_pat_pmt) {
          av_log(s, AV_LOG_WARNING, "resend_headers option is deprecated, use -mpegts_flags resend_headers\n");
          ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT;
      }
  
 -    if (pkt->pts != AV_NOPTS_VALUE)
 -        pts = pkt->pts + delay;
 -    if (pkt->dts != AV_NOPTS_VALUE)
 -        dts = pkt->dts + delay;
 +    if(ts->copyts < 1){
 +        if (pts != AV_NOPTS_VALUE)
 +            pts += delay;
 +        if (dts != AV_NOPTS_VALUE)
 +            dts += delay;
 +    }
  
      if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) {
          av_log(s, AV_LOG_ERROR, "first pts value must set\n");
 -        return AVERROR(EINVAL);
 +        return AVERROR_INVALIDDATA;
      }
      ts_st->first_pts_check = 0;
  
  
          if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) {
              av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, "
 -                   "no startcode found, use -bsf h264_mp4toannexb\n");
 +                   "no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)\n");
              return AVERROR(EINVAL);
          }
  
      } else if (st->codec->codec_id == AV_CODEC_ID_AAC) {
          if (pkt->size < 2) {
              av_log(s, AV_LOG_ERROR, "AAC packet too short\n");
 -            return AVERROR(EINVAL);
 +            return AVERROR_INVALIDDATA;
          }
          if ((AV_RB16(pkt->data) & 0xfff0) != 0xfff0) {
              int ret;
              if (!ts_st->amux) {
                  av_log(s, AV_LOG_ERROR, "AAC bitstream not in ADTS format "
                         "and extradata missing\n");
 -                return AVERROR(EINVAL);
 +                return AVERROR_INVALIDDATA;
              }
  
              av_init_packet(&pkt2);
          }
      }
  
 -    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
 +    if (pkt->dts != AV_NOPTS_VALUE) {
 +        int i;
 +        for(i=0; i<s->nb_streams; i++){
 +            AVStream *st2 = s->streams[i];
 +            MpegTSWriteStream *ts_st2 = st2->priv_data;
 +            if(   ts_st2->payload_size
 +               && ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > delay/2){
 +                mpegts_write_pes(s, st2, ts_st2->payload, ts_st2->payload_size,
 +                                ts_st2->payload_pts, ts_st2->payload_dts,
 +                                ts_st2->payload_flags & AV_PKT_FLAG_KEY);
 +                ts_st2->payload_size = 0;
 +            }
 +        }
 +    }
 +
 +    if (ts_st->payload_size && ts_st->payload_size + size > ts->pes_payload_size) {
 +        mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
 +                         ts_st->payload_pts, ts_st->payload_dts,
 +                         ts_st->payload_flags & AV_PKT_FLAG_KEY);
 +        ts_st->payload_size = 0;
 +    }
 +
 +    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO || size > ts->pes_payload_size) {
 +        av_assert0(!ts_st->payload_size);
          // for video and subtitle, write a single pes packet
          mpegts_write_pes(s, st, buf, size, pts, dts, pkt->flags & AV_PKT_FLAG_KEY);
          av_free(data);
          return 0;
      }
  
 -    if (ts_st->payload_size + size > ts->pes_payload_size) {
 -        if (ts_st->payload_size) {
 -            mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
 -                             ts_st->payload_pts, ts_st->payload_dts,
 -                             ts_st->payload_flags & AV_PKT_FLAG_KEY);
 -            ts_st->payload_size = 0;
 -        }
 -        if (size > ts->pes_payload_size) {
 -            mpegts_write_pes(s, st, buf, size, pts, dts,
 -                             pkt->flags & AV_PKT_FLAG_KEY);
 -            av_free(data);
 -            return 0;
 -        }
 -    }
 -
      if (!ts_st->payload_size) {
          ts_st->payload_pts = pts;
          ts_st->payload_dts = dts;
@@@ -1253,7 -1164,7 +1253,7 @@@ AVOutputFormat ff_mpegts_muxer = 
      .name              = "mpegts",
      .long_name         = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),
      .mime_type         = "video/x-mpegts",
 -    .extensions        = "ts,m2t",
 +    .extensions        = "ts,m2t,m2ts,mts",
      .priv_data_size    = sizeof(MpegTSWrite),
      .audio_codec       = AV_CODEC_ID_MP2,
      .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
index 4194017afe2b428bd60704d9d872782bf355f095,20d2842cd81f7d790012e5dba44fd338e0984fcd..e62275a8eeba988a9a984e8ecec7e160dacf229f
@@@ -1,20 -1,18 +1,20 @@@
  /*
 - * This file is part of Libav.
 + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
   *
 - * Libav is free software; you can redistribute it and/or
 + * This file is part of FFmpeg.
 + *
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
  #define D AV_OPT_FLAG_DECODING_PARAM
  
  static const AVOption options[]={
- {"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"},
++{"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"},
 +{"direct", "reduce buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVIO_FLAG_DIRECT }, INT_MIN, INT_MAX, D|E, "avioflags"},
  {"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT, {.dbl = 5000000 }, 32, INT_MAX, D},
  {"packetsize", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, INT_MAX, E},
- {"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, INT_MIN, INT_MAX, D|E, "fflags"},
+ {"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "fflags"},
  {"ignidx", "ignore index", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNIDX }, INT_MIN, INT_MAX, D, "fflags"},
  {"genpts", "generate pts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_GENPTS }, INT_MIN, INT_MAX, D, "fflags"},
  {"nofillin", "do not fill in missing values that can be exactly calculated", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOFILLIN }, INT_MIN, INT_MAX, D, "fflags"},
  {"noparse", "disable AVParsers, this needs nofillin too", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOPARSE }, INT_MIN, INT_MAX, D, "fflags"},
  {"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"},
  {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"},
 +{"sortdts", "try to interleave outputted packets by dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_SORT_DTS }, INT_MIN, INT_MAX, D, "fflags"},
 +{"keepside", "dont merge side data", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"},
 +{"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"},
  {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"},
  {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.dbl = 5*AV_TIME_BASE }, 0, INT_MAX, D},
  {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
  {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.dbl = 1<<20 }, 0, INT_MAX, D},
  {"rtbufsize", "max memory used for buffering real-time frames", OFFSET(max_picture_buffer), AV_OPT_TYPE_INT, {.dbl = 3041280 }, 0, INT_MAX, D}, /* defaults to 1s of 15fps 352x288 YUYV422 video */
- {"fdebug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, 0, INT_MAX, E|D, "fdebug"},
+ {"fdebug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, E|D, "fdebug"},
  {"ts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_FDEBUG_TS }, INT_MIN, INT_MAX, E|D, "fdebug"},
  {"max_delay", "maximum muxing or demuxing delay in microseconds", OFFSET(max_delay), AV_OPT_TYPE_INT, {.dbl = -1 }, -1, INT_MAX, E|D},
  {"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX-1, D},
 +{"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
 +{"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
 +{"chunk_size", "size in bytes for each chunk", OFFSET(max_chunk_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, E},
  /* this is a crutch for avconv, since it cannot deal with identically named options in different contexts.
   * to be removed when avconv is fixed */
- {"f_err_detect", "set error detection flags (deprecated; use err_detect, save via avconv)", OFFSET(error_recognition), AV_OPT_TYPE_FLAGS, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
- {"err_detect", "set error detection flags", OFFSET(error_recognition), AV_OPT_TYPE_FLAGS, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
+ {"f_err_detect", "set error detection flags (deprecated; use err_detect, save via avconv)", OFFSET(error_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
+ {"err_detect", "set error detection flags", OFFSET(error_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
  {"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
  {"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, D, "err_detect"},
  {"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, D, "err_detect"},
  {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"},
 +{"careful",    "consider things that violate the spec and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"},
 +{"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"},
 +{"aggressive", "consider things that a sane encoder shouldnt do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"},
 +{"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX-1, D},
  {NULL},
  };
  
diff --combined libavformat/rtpenc.h
index 77206927dfa902b582828a731c53b91f9196d6fa,6a506c4d4f64fdcbca6fa802bb31c79f899e4c68..4b3f5dbc6d4e11cd20985a23e7f44e4679389d80
@@@ -2,20 -2,20 +2,20 @@@
   * RTP muxer definitions
   * Copyright (c) 2002 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  #ifndef AVFORMAT_RTPENC_H
@@@ -69,7 -69,7 +69,7 @@@ typedef struct RTPMuxContext RTPMuxCont
  #define FF_RTP_FLAG_H264_MODE0 8
  
  #define FF_RTP_FLAG_OPTS(ctx, fieldname) \
-     { "rtpflags", "RTP muxer flags", offsetof(ctx, fieldname), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
+     { "rtpflags", "RTP muxer flags", offsetof(ctx, fieldname), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
      { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
      { "rfc2190", "Use RFC 2190 packetization instead of RFC 4629 for H.263", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_RFC2190}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
      { "skip_rtcp", "Don't send RTCP sender reports", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_SKIP_RTCP}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
@@@ -88,7 -88,7 +88,7 @@@ void ff_rtp_send_mpegvideo(AVFormatCont
  void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size);
  void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size);
  
 -const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *restrict start,
 -                                                  const uint8_t *restrict end);
 +const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start,
 +                                                  const uint8_t *av_restrict end);
  
  #endif /* AVFORMAT_RTPENC_H */
diff --combined libavformat/rtsp.c
index d4c3cbc81c6b5ecf34b006afc542f365c68cc303,4027a626c3fc7ca32a36de0d41acb6e1ece65228..79a610e288e44df13a6d8e59759c1c1b3a24c984
@@@ -2,20 -2,20 +2,20 @@@
   * RTSP/SDP client
   * Copyright (c) 2002 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
  #define ENC AV_OPT_FLAG_ENCODING_PARAM
  
  #define RTSP_FLAG_OPTS(name, longname) \
-     { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
+     { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
      { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \
      { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }
  
  #define RTSP_MEDIATYPE_OPTS(name, longname) \
-     { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
+     { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { .i64 = (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
      { "video", "Video", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_VIDEO}, 0, 0, DEC, "allowed_media_types" }, \
      { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \
      { "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
@@@ -77,7 -77,7 +77,7 @@@
  const AVOption ff_rtsp_options[] = {
      { "initial_pause",  "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC },
      FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
-     { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
+     { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
      { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
      { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
      { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
@@@ -1213,6 -1213,10 +1213,6 @@@ int ff_rtsp_make_setup_request(AVFormat
      /* default timeout: 1 minute */
      rt->timeout = 60;
  
 -    /* for each stream, make the setup request */
 -    /* XXX: we assume the same server is used for the control of each
 -     * RTSP stream */
 -
      /* Choose a random starting offset within the first half of the
       * port range, to allow for a number of ports to try even if the offset
       * happens to be at the end of the random range. */
                                 &s->interrupt_callback, NULL))
                      goto rtp_opened;
              }
 -
              av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
              err = AVERROR(EIO);
              goto fail;
diff --combined libavformat/spdifenc.c
index 0406d6b7951cfa62f6b4af32fb553b689fae3626,3e902b525d8b87bfdc4199cd49a2cf6f586cbcdd..873e839eeb3bafa2cdba975c5b6521fda0e18acd
@@@ -4,20 -4,20 +4,20 @@@
   * Copyright (c) 2010 Anssi Hannula
   * Copyright (c) 2010 Carl Eugen Hoyos
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
@@@ -85,7 -85,7 +85,7 @@@ typedef struct IEC61937Context 
  } IEC61937Context;
  
  static const AVOption options[] = {
- { "spdif_flags", "IEC 61937 encapsulation flags", offsetof(IEC61937Context, spdif_flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "spdif_flags" },
+ { "spdif_flags", "IEC 61937 encapsulation flags", offsetof(IEC61937Context, spdif_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "spdif_flags" },
  { "be", "output in big-endian format (for use as s16be)", 0, AV_OPT_TYPE_CONST, {.i64 = SPDIF_FLAG_BIGENDIAN},  0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "spdif_flags" },
  { "dtshd_rate", "mux complete DTS frames in HD mode at the specified IEC958 rate (in Hz, default 0=disabled)", offsetof(IEC61937Context, dtshd_rate), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 768000, AV_OPT_FLAG_ENCODING_PARAM },
  { "dtshd_fallback_time", "min secs to strip HD for after an overflow (-1: till the end, default 60)", offsetof(IEC61937Context, dtshd_fallback), AV_OPT_TYPE_INT, {.dbl = 60}, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
@@@ -520,13 -520,13 +520,13 @@@ static int spdif_write_packet(struct AV
      }
  
      if (ctx->extra_bswap ^ (ctx->spdif_flags & SPDIF_FLAG_BIGENDIAN)) {
 -    avio_write(s->pb, ctx->out_buf, ctx->out_bytes & ~1);
 +        avio_write(s->pb, ctx->out_buf, ctx->out_bytes & ~1);
      } else {
 -    av_fast_malloc(&ctx->buffer, &ctx->buffer_size, ctx->out_bytes + FF_INPUT_BUFFER_PADDING_SIZE);
 -    if (!ctx->buffer)
 -        return AVERROR(ENOMEM);
 -    ff_spdif_bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)ctx->out_buf, ctx->out_bytes >> 1);
 -    avio_write(s->pb, ctx->buffer, ctx->out_bytes & ~1);
 +        av_fast_malloc(&ctx->buffer, &ctx->buffer_size, ctx->out_bytes + FF_INPUT_BUFFER_PADDING_SIZE);
 +        if (!ctx->buffer)
 +            return AVERROR(ENOMEM);
 +        ff_spdif_bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)ctx->out_buf, ctx->out_bytes >> 1);
 +        avio_write(s->pb, ctx->buffer, ctx->out_bytes & ~1);
      }
  
      /* a final lone byte has to be MSB aligned */
diff --combined libavutil/cpu.c
index 7e291c4c76658d37b572d78dbd91a7c79321df02,8db69be24e2d90698ea6d4da6fc4eda59baec55f..f651cab64b0b6cf71b191979e4284c9fccda4ac9
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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 "config.h"
  #include "opt.h"
  
 -static int cpuflags_mask = -1, checked;
 +static int flags, checked;
 +
 +void av_force_cpu_flags(int arg){
 +    flags   = arg;
 +    checked = arg != -1;
 +}
  
  int av_get_cpu_flags(void)
  {
 -    static int flags;
 -
      if (checked)
          return flags;
  
      if (ARCH_PPC) flags = ff_get_cpu_flags_ppc();
      if (ARCH_X86) flags = ff_get_cpu_flags_x86();
  
 -    flags  &= cpuflags_mask;
      checked = 1;
 -
      return flags;
  }
  
  void av_set_cpu_flags_mask(int mask)
  {
 -    cpuflags_mask = mask;
      checked       = 0;
 +    flags         = av_get_cpu_flags() & mask;
 +    checked       = 1;
  }
  
  int av_parse_cpu_flags(const char *s)
@@@ -64,7 -62,7 +64,7 @@@
  #define CPUFLAG_XOP      (AV_CPU_FLAG_XOP      | CPUFLAG_AVX)
  #define CPUFLAG_FMA4     (AV_CPU_FLAG_FMA4     | CPUFLAG_AVX)
      static const AVOption cpuflags_opts[] = {
-         { "flags"   , NULL, 0, AV_OPT_TYPE_FLAGS, { 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
+         { "flags"   , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
  #if   ARCH_PPC
          { "altivec" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ALTIVEC  },    .unit = "flags" },
  #elif ARCH_X86
      return flags & INT_MAX;
  }
  
-         { "flags"   , NULL, 0, AV_OPT_TYPE_FLAGS, { 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
 +int av_parse_cpu_caps(unsigned *flags, const char *s)
 +{
 +        static const AVOption cpuflags_opts[] = {
++        { "flags"   , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
 +#if   ARCH_PPC
 +        { "altivec" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ALTIVEC  },    .unit = "flags" },
 +#elif ARCH_X86
 +        { "mmx"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX      },    .unit = "flags" },
 +        { "mmx2"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX2     },    .unit = "flags" },
 +        { "mmxext"  , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX2     },    .unit = "flags" },
 +        { "sse"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE      },    .unit = "flags" },
 +        { "sse2"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE2     },    .unit = "flags" },
 +        { "sse2slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE2SLOW },    .unit = "flags" },
 +        { "sse3"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE3     },    .unit = "flags" },
 +        { "sse3slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE3SLOW },    .unit = "flags" },
 +        { "ssse3"   , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSSE3    },    .unit = "flags" },
 +        { "atom"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ATOM     },    .unit = "flags" },
 +        { "sse4.1"  , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE4     },    .unit = "flags" },
 +        { "sse4.2"  , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE42    },    .unit = "flags" },
 +        { "avx"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX      },    .unit = "flags" },
 +        { "xop"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_XOP      },    .unit = "flags" },
 +        { "fma4"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_FMA4     },    .unit = "flags" },
 +        { "3dnow"   , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_3DNOW    },    .unit = "flags" },
 +        { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_3DNOWEXT },    .unit = "flags" },
 +#elif ARCH_ARM
 +        { "armv5te",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV5TE  },    .unit = "flags" },
 +        { "armv6",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6    },    .unit = "flags" },
 +        { "armv6t2",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6T2  },    .unit = "flags" },
 +        { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
 +        { "vfpv3",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFPV3    },    .unit = "flags" },
 +        { "neon",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON     },    .unit = "flags" },
 +#endif
 +        { NULL },
 +    };
 +    static const AVClass class = {
 +        .class_name = "cpuflags",
 +        .item_name  = av_default_item_name,
 +        .option     = cpuflags_opts,
 +        .version    = LIBAVUTIL_VERSION_INT,
 +    };
 +    const AVClass *pclass = &class;
 +
 +    return av_opt_eval_flags(&pclass, &cpuflags_opts[0], s, flags);
 +}
  #ifdef TEST
  
  #undef printf
diff --combined libavutil/opt.c
index fe282f6beae0d6fc3fc5a0450189e48aee5c8010,5deb5c59d659d4a6ece457ae4ba4eae8250e1acd..36eff8d656b68bde7624ff2892818034fd1d71a6
@@@ -2,20 -2,20 +2,20 @@@
   * AVOptions
   * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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 "eval.h"
  #include "dict.h"
  #include "log.h"
 +#include "parseutils.h"
 +#include "pixdesc.h"
  #include "mathematics.h"
  
  #if FF_API_FIND_OPT
  //FIXME order them and do a bin search
  const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
  {
 -    AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
 -    const AVOption *o= c->option;
 +    const AVOption *o = NULL;
  
 -    for (; o && o->name; o++) {
 +    while ((o = av_next_option(v, o))) {
          if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
              return o;
      }
@@@ -60,8 -59,7 +60,8 @@@ const AVOption *av_next_option(void *ob
  const AVOption *av_opt_next(void *obj, const AVOption *last)
  {
      AVClass *class = *(AVClass**)obj;
 -    if (!last && class->option[0].name) return class->option;
 +    if (!last && class->option && class->option[0].name)
 +        return class->option;
      if (last && last[1].name)           return ++last;
      return NULL;
  }
@@@ -77,7 -75,6 +77,7 @@@ static int read_number(const AVOption *
      case AV_OPT_TYPE_RATIONAL:  *intnum = ((AVRational*)dst)->num;
                                  *den    = ((AVRational*)dst)->den;
                                                          return 0;
 +    case AV_OPT_TYPE_CONST:     *num    = o->default_val.dbl; return 0;
      }
      return AVERROR(EINVAL);
  }
@@@ -85,7 -82,7 +85,7 @@@
  static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
  {
      if (o->max*den < num*intnum || o->min*den > num*intnum) {
 -        av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n",
 +        av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n",
                 num*intnum/den, o->name);
          return AVERROR(ERANGE);
      }
@@@ -164,7 -161,8 +164,8 @@@ static int set_string(void *obj, const 
  }
  
  #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
-                               opt->type == AV_OPT_TYPE_CONST) ? \
+                               opt->type == AV_OPT_TYPE_CONST || \
+                               opt->type == AV_OPT_TYPE_FLAGS) ? \
                               opt->default_val.i64 : opt->default_val.dbl)
  
  static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
@@@ -234,12 -232,11 +235,12 @@@ int av_set_string3(void *obj, const cha
  
  int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
  {
 +    int ret;
      void *dst, *target_obj;
      const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
      if (!o || !target_obj)
          return AVERROR_OPTION_NOT_FOUND;
 -    if (!val)
 +    if (!val && o->type != AV_OPT_TYPE_STRING)
          return AVERROR(EINVAL);
  
      dst = ((uint8_t*)target_obj) + o->offset;
      case AV_OPT_TYPE_FLOAT:
      case AV_OPT_TYPE_DOUBLE:
      case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
 +    case AV_OPT_TYPE_IMAGE_SIZE:
 +        ret = av_parse_video_size(dst, ((int *)dst) + 1, val);
 +        if (ret < 0)
 +            av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
 +        return ret;
 +    case AV_OPT_TYPE_PIXEL_FMT:
 +        ret = av_get_pix_fmt(val);
 +        if (ret == PIX_FMT_NONE) {
 +            char *tail;
 +            ret = strtol(val, &tail, 0);
 +            if (*tail || (unsigned)ret >= PIX_FMT_NB) {
 +                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as pixel format\n", val);
 +                return AVERROR(EINVAL);
 +            }
 +        }
 +        *(enum PixelFormat *)dst = ret;
 +        return 0;
      }
  
      av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@@ -381,7 -361,7 +382,7 @@@ int av_opt_set_bin(void *obj, const cha
   */
  const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
  {
 -    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
 +    const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN);
      void *dst;
      uint8_t *bin;
      int len, i;
      case AV_OPT_TYPE_FLOAT:     snprintf(buf, buf_len, "%f" , *(float  *)dst);break;
      case AV_OPT_TYPE_DOUBLE:    snprintf(buf, buf_len, "%f" , *(double *)dst);break;
      case AV_OPT_TYPE_RATIONAL:  snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
 +    case AV_OPT_TYPE_CONST:     snprintf(buf, buf_len, "%f" , o->default_val.dbl);break;
      case AV_OPT_TYPE_STRING:    return *(void**)dst;
      case AV_OPT_TYPE_BINARY:
          len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
@@@ -421,7 -400,7 +422,7 @@@ int av_opt_get(void *obj, const char *n
      uint8_t *bin, buf[128];
      int len, i, ret;
  
 -    if (!o || !target_obj)
 +    if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
          return AVERROR_OPTION_NOT_FOUND;
  
      dst = (uint8_t*)target_obj + o->offset;
      case AV_OPT_TYPE_FLOAT:     ret = snprintf(buf, sizeof(buf), "%f" ,     *(float  *)dst);break;
      case AV_OPT_TYPE_DOUBLE:    ret = snprintf(buf, sizeof(buf), "%f" ,     *(double *)dst);break;
      case AV_OPT_TYPE_RATIONAL:  ret = snprintf(buf, sizeof(buf), "%d/%d",   ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
 +    case AV_OPT_TYPE_CONST:     ret = snprintf(buf, sizeof(buf), "%f" ,     o->default_val.dbl);break;
      case AV_OPT_TYPE_STRING:
          if (*(uint8_t**)dst)
              *out_val = av_strdup(*(uint8_t**)dst);
          for (i = 0; i < len; i++)
              snprintf(*out_val + i*2, 3, "%02X", bin[i]);
          return 0;
 +    case AV_OPT_TYPE_IMAGE_SIZE:
 +        ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
 +        break;
 +    case AV_OPT_TYPE_PIXEL_FMT:
 +        ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum PixelFormat *)dst), "?"));
 +        break;
      default:
          return AVERROR(EINVAL);
      }
@@@ -626,12 -598,6 +627,12 @@@ static void opt_list(void *obj, void *a
              case AV_OPT_TYPE_BINARY:
                  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
                  break;
 +            case AV_OPT_TYPE_IMAGE_SIZE:
 +                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<image_size>");
 +                break;
 +            case AV_OPT_TYPE_PIXEL_FMT:
 +                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<pix_fmt>");
 +                break;
              case AV_OPT_TYPE_CONST:
              default:
                  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
          }
          av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
          av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
 +        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.');
          av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
          av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
          av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
@@@ -684,13 -649,13 +685,13 @@@ void av_opt_set_defaults2(void *s, int 
              case AV_OPT_TYPE_CONST:
                  /* Nothing to be done here */
              break;
-             case AV_OPT_TYPE_FLAGS:
              case AV_OPT_TYPE_INT: {
                  int val;
                  val = opt->default_val.dbl;
                  av_opt_set_int(s, opt->name, val, 0);
              }
              break;
+             case AV_OPT_TYPE_FLAGS:
              case AV_OPT_TYPE_INT64:
                  av_opt_set_int(s, opt->name, opt->default_val.i64, 0);
              break;
              }
              break;
              case AV_OPT_TYPE_STRING:
 +            case AV_OPT_TYPE_IMAGE_SIZE:
 +            case AV_OPT_TYPE_PIXEL_FMT:
                  av_opt_set(s, opt->name, opt->default_val.str, 0);
                  break;
              case AV_OPT_TYPE_BINARY:
@@@ -754,7 -717,7 +755,7 @@@ static int parse_key_value_pair(void *c
          return AVERROR(EINVAL);
      }
  
 -    av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
 +    av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
  
      ret = av_opt_set(ctx, key, val, 0);
      if (ret == AVERROR_OPTION_NOT_FOUND)
@@@ -823,14 -786,9 +824,14 @@@ const AVOption *av_opt_find(void *obj, 
  const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
                               int opt_flags, int search_flags, void **target_obj)
  {
 -    const AVClass  *c = *(AVClass**)obj;
 +    const AVClass  *c;
      const AVOption *o = NULL;
  
 +    if(!obj)
 +        return NULL;
 +
 +    c= *(AVClass**)obj;
 +
      if (search_flags & AV_OPT_SEARCH_CHILDREN) {
          if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
              const AVClass *child = NULL;
      while (o = av_opt_next(obj, o)) {
          if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
              ((!unit && o->type != AV_OPT_TYPE_CONST) ||
 -             (unit  && o->unit && !strcmp(o->unit, unit)))) {
 +             (unit  && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
              if (target_obj) {
                  if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
                      *target_obj = obj;
@@@ -876,14 -834,6 +877,14 @@@ const AVClass *av_opt_child_class_next(
      return NULL;
  }
  
 +void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
 +{
 +    const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
 +    if(!opt)
 +        return NULL;
 +    return (uint8_t*)obj + opt->offset;
 +}
 +
  #ifdef TEST
  
  #undef printf
@@@ -896,8 -846,6 +897,8 @@@ typedef struct TestContex
      char *string;
      int flags;
      AVRational rational;
 +    int w, h;
 +    enum PixelFormat pix_fmt;
  } TestContext;
  
  #define OFFSET(x) offsetof(TestContext, x)
@@@ -911,12 -859,10 +912,12 @@@ static const AVOption test_options[]= 
  {"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {0},              0,        1                   },
  {"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {0},              0,        10                  },
  {"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {0},              CHAR_MIN, CHAR_MAX            },
- {"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {0},              0,        INT_MAX, 0, "flags" },
+ {"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 0},       0,        INT_MAX, 0, "flags" },
  {"cool",     "set cool flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 0, "flags" },
  {"lame",     "set lame flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 0, "flags" },
  {"mu",       "set mu flag ",   0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_MU},   INT_MIN,  INT_MAX, 0, "flags" },
 +{"size",     "set size",       OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE,{0},             0,        0                   },
 +{"pix_fmt",  "set pixfmt",     OFFSET(pix_fmt),  AV_OPT_TYPE_PIXEL_FMT,{0},              0,        0                   },
  {NULL},
  };
  
@@@ -937,7 -883,7 +938,7 @@@ int main(void
  
      printf("\nTesting av_set_options_string()\n");
      {
 -        TestContext test_ctx;
 +        TestContext test_ctx = { 0 };
          const char *options[] = {
              "",
              ":",
              "num=42 : string=blahblah",
              "rational=0 : rational=1/2 : rational=1/-1",
              "rational=-1/0",
 +            "size=1024x768",
 +            "size=pal",
 +            "size=bogus",
 +            "pix_fmt=yuv420p",
 +            "pix_fmt=2",
 +            "pix_fmt=bogus",
          };
  
          test_ctx.class = &test_class;
                  av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
              printf("\n");
          }
 +        av_freep(&test_ctx.string);
      }
  
      return 0;
index dbf94d4749deb7aa2032df895678f9b397d6054f,0000000000000000000000000000000000000000..703b9733312d14452825b0a8f357e014216d14a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,789 -1,0 +1,789 @@@
- {"flags"                , NULL                          , OFFSET(flags          ), AV_OPT_TYPE_FLAGS, {.dbl=0                     }, 0      , UINT_MAX  , PARAM, "flags"},
- {"swr_flags"            , NULL                          , OFFSET(flags          ), AV_OPT_TYPE_FLAGS, {.dbl=0                     }, 0      , UINT_MAX  , PARAM, "flags"},
 +/*
 + * Copyright (C) 2011-2012 Michael Niedermayer (michaelni@gmx.at)
 + *
 + * This file is part of libswresample
 + *
 + * libswresample 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.
 + *
 + * libswresample 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 libswresample; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/opt.h"
 +#include "swresample_internal.h"
 +#include "audioconvert.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/audioconvert.h"
 +
 +#include <float.h>
 +
 +#define  C30DB  M_SQRT2
 +#define  C15DB  1.189207115
 +#define C__0DB  1.0
 +#define C_15DB  0.840896415
 +#define C_30DB  M_SQRT1_2
 +#define C_45DB  0.594603558
 +#define C_60DB  0.5
 +
 +#define ALIGN 32
 +
 +//TODO split options array out?
 +#define OFFSET(x) offsetof(SwrContext,x)
 +#define PARAM AV_OPT_FLAG_AUDIO_PARAM
 +
 +static const AVOption options[]={
 +{"ich"                  ,  "Input Channel Count"        , OFFSET( in.ch_count   ), AV_OPT_TYPE_INT  , {.dbl=2                     }, 0      , SWR_CH_MAX, PARAM},
 +{"in_channel_count"     ,  "Input Channel Count"        , OFFSET( in.ch_count   ), AV_OPT_TYPE_INT  , {.dbl=2                     }, 0      , SWR_CH_MAX, PARAM},
 +{"och"                  , "Output Channel Count"        , OFFSET(out.ch_count   ), AV_OPT_TYPE_INT  , {.dbl=2                     }, 0      , SWR_CH_MAX, PARAM},
 +{"out_channel_count"    , "Output Channel Count"        , OFFSET(out.ch_count   ), AV_OPT_TYPE_INT  , {.dbl=2                     }, 0      , SWR_CH_MAX, PARAM},
 +{"uch"                  ,   "Used Channel Count"        , OFFSET(used_ch_count  ), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , SWR_CH_MAX, PARAM},
 +{"used_channel_count"   ,   "Used Channel Count"        , OFFSET(used_ch_count  ), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , SWR_CH_MAX, PARAM},
 +{"isr"                  ,  "Input Sample Rate"          , OFFSET( in_sample_rate), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , INT_MAX   , PARAM},
 +{"in_sample_rate"       ,  "Input Sample Rate"          , OFFSET( in_sample_rate), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , INT_MAX   , PARAM},
 +{"osr"                  , "Output Sample Rate"          , OFFSET(out_sample_rate), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , INT_MAX   , PARAM},
 +{"out_sample_rate"      , "Output Sample Rate"          , OFFSET(out_sample_rate), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , INT_MAX   , PARAM},
 +{"isf"                  ,    "Input Sample Format"      , OFFSET( in_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_NB-1+256, PARAM},
 +{"in_sample_fmt"        ,    "Input Sample Format"      , OFFSET( in_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_NB-1+256, PARAM},
 +{"osf"                  ,   "Output Sample Format"      , OFFSET(out_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_NB-1+256, PARAM},
 +{"out_sample_fmt"       ,   "Output Sample Format"      , OFFSET(out_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_NB-1+256, PARAM},
 +{"tsf"                  , "Internal Sample Format"      , OFFSET(int_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_FLTP, PARAM},
 +{"internal_sample_fmt"  , "Internal Sample Format"      , OFFSET(int_sample_fmt ), AV_OPT_TYPE_INT  , {.dbl=AV_SAMPLE_FMT_NONE    }, -1     , AV_SAMPLE_FMT_FLTP, PARAM},
 +{"icl"                  ,   "Input Channel Layout"      , OFFSET( in_ch_layout  ), AV_OPT_TYPE_INT64, {.i64=0                     }, 0      , INT64_MAX , PARAM, "channel_layout"},
 +{"in_channel_layout"    ,   "Input Channel Layout"      , OFFSET( in_ch_layout  ), AV_OPT_TYPE_INT64, {.i64=0                     }, 0      , INT64_MAX , PARAM, "channel_layout"},
 +{"ocl"                  ,  "Output Channel Layout"      , OFFSET(out_ch_layout  ), AV_OPT_TYPE_INT64, {.i64=0                     }, 0      , INT64_MAX , PARAM, "channel_layout"},
 +{"out_channel_layout"   ,  "Output Channel Layout"      , OFFSET(out_ch_layout  ), AV_OPT_TYPE_INT64, {.i64=0                     }, 0      , INT64_MAX , PARAM, "channel_layout"},
 +{"clev"                 ,    "Center Mix Level"         , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 +{"center_mix_level"     ,    "Center Mix Level"         , OFFSET(clev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 +{"slev"                 , "Sourround Mix Level"         , OFFSET(slev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 +{"surround_mix_level"   , "Sourround Mix Level"         , OFFSET(slev           ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB                }, -32    , 32        , PARAM},
 +{"lfe_mix_level"        , "LFE Mix Level"               , OFFSET(lfe_mix_level  ), AV_OPT_TYPE_FLOAT, {.dbl=0                     }, -32    , 32        , PARAM},
 +{"rmvol"                , "Rematrix Volume"             , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0                   }, -1000  , 1000      , PARAM},
 +{"rematrix_volume"      , "Rematrix Volume"             , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0                   }, -1000  , 1000      , PARAM},
++{"flags"                , NULL                          , OFFSET(flags          ), AV_OPT_TYPE_FLAGS, {.i64=0                     }, 0      , UINT_MAX  , PARAM, "flags"},
++{"swr_flags"            , NULL                          , OFFSET(flags          ), AV_OPT_TYPE_FLAGS, {.i64=0                     }, 0      , UINT_MAX  , PARAM, "flags"},
 +{"res"                  , "Force Resampling"            , 0                      , AV_OPT_TYPE_CONST, {.i64=SWR_FLAG_RESAMPLE     }, INT_MIN, INT_MAX   , PARAM, "flags"},
 +{"dither_scale"         , "Dither Scale"                , OFFSET(dither_scale   ), AV_OPT_TYPE_FLOAT, {.dbl=1                     }, 0      , INT_MAX   , PARAM},
 +{"dither_method"        , "Dither Method"               , OFFSET(dither_method  ), AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , SWR_DITHER_NB-1, PARAM, "dither_method"},
 +{"rectangular"          , "Rectangular Dither"          , 0                      , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX   , PARAM, "dither_method"},
 +{"triangular"           ,  "Triangular Dither"          , 0                      , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX   , PARAM, "dither_method"},
 +{"triangular_hp"        , "Triangular Dither With High Pass" , 0                 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"},
 +{"filter_size"          , "Resampling Filter Size"      , OFFSET(filter_size)    , AV_OPT_TYPE_INT  , {.dbl=16                    }, 0      , INT_MAX   , PARAM },
 +{"phase_shift"          , "Resampling Phase Shift"      , OFFSET(phase_shift)    , AV_OPT_TYPE_INT  , {.dbl=10                    }, 0      , 30        , PARAM },
 +{"linear_interp"        , "Use Linear Interpolation"    , OFFSET(linear_interp)  , AV_OPT_TYPE_INT  , {.dbl=0                     }, 0      , 1         , PARAM },
 +{"cutoff"               , "Cutoff Frequency Ratio"      , OFFSET(cutoff)         , AV_OPT_TYPE_DOUBLE,{.dbl=0.8                   }, 0      , 1         , PARAM },
 +{"min_comp"             , "Minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied"
 +                                                        , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX               }, 0      , FLT_MAX   , PARAM },
 +{"min_hard_comp"        , "Minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data."
 +                                                   , OFFSET(min_hard_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0.1                   }, 0      , INT_MAX   , PARAM },
 +{"comp_duration"        , "Duration (in seconds) over which data is stretched/squeezed to make it match the timestamps."
 +                                              , OFFSET(soft_compensation_duration),AV_OPT_TYPE_FLOAT ,{.dbl=1                     }, 0      , INT_MAX   , PARAM },
 +{"max_soft_comp"        , "Maximum factor by which data is stretched/squeezed to make it match the timestamps."
 +                                                   , OFFSET(max_soft_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0                     }, INT_MIN, INT_MAX   , PARAM },
 +{ "filter_type"         , "Filter Type"                 , OFFSET(filter_type)    , AV_OPT_TYPE_INT  , { SWR_FILTER_TYPE_KAISER }, SWR_FILTER_TYPE_CUBIC, SWR_FILTER_TYPE_KAISER, PARAM, "filter_type" },
 +    { "cubic"           , "Cubic"                       , 0                      , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_CUBIC            }, INT_MIN, INT_MAX, PARAM, "filter_type" },
 +    { "blackman_nuttall", "Blackman Nuttall Windowed Sinc", 0                    , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" },
 +    { "kaiser"          , "Kaiser Windowed Sinc"        , 0                      , AV_OPT_TYPE_CONST, { .i64 = SWR_FILTER_TYPE_KAISER           }, INT_MIN, INT_MAX, PARAM, "filter_type" },
 +{ "kaiser_beta"         , "Kaiser Window Beta"          ,OFFSET(kaiser_beta)     , AV_OPT_TYPE_INT  , {.dbl=9                     }, 2      , 16        , PARAM },
 +
 +{0}
 +};
 +
 +static const char* context_to_name(void* ptr) {
 +    return "SWR";
 +}
 +
 +static const AVClass av_class = {
 +    .class_name                = "SWResampler",
 +    .item_name                 = context_to_name,
 +    .option                    = options,
 +    .version                   = LIBAVUTIL_VERSION_INT,
 +    .log_level_offset_offset   = OFFSET(log_level_offset),
 +    .parent_log_context_offset = OFFSET(log_ctx),
 +    .category                  = AV_CLASS_CATEGORY_SWRESAMPLER,
 +};
 +
 +unsigned swresample_version(void)
 +{
 +    av_assert0(LIBSWRESAMPLE_VERSION_MICRO >= 100);
 +    return LIBSWRESAMPLE_VERSION_INT;
 +}
 +
 +const char *swresample_configuration(void)
 +{
 +    return FFMPEG_CONFIGURATION;
 +}
 +
 +const char *swresample_license(void)
 +{
 +#define LICENSE_PREFIX "libswresample license: "
 +    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
 +}
 +
 +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){
 +    if(!s || s->in_convert) // s needs to be allocated but not initialized
 +        return AVERROR(EINVAL);
 +    s->channel_map = channel_map;
 +    return 0;
 +}
 +
 +const AVClass *swr_get_class(void)
 +{
 +    return &av_class;
 +}
 +
 +struct SwrContext *swr_alloc(void){
 +    SwrContext *s= av_mallocz(sizeof(SwrContext));
 +    if(s){
 +        s->av_class= &av_class;
 +        av_opt_set_defaults(s);
 +    }
 +    return s;
 +}
 +
 +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
 +                                      int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
 +                                      int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
 +                                      int log_offset, void *log_ctx){
 +    if(!s) s= swr_alloc();
 +    if(!s) return NULL;
 +
 +    s->log_level_offset= log_offset;
 +    s->log_ctx= log_ctx;
 +
 +    av_opt_set_int(s, "ocl", out_ch_layout,   0);
 +    av_opt_set_int(s, "osf", out_sample_fmt,  0);
 +    av_opt_set_int(s, "osr", out_sample_rate, 0);
 +    av_opt_set_int(s, "icl", in_ch_layout,    0);
 +    av_opt_set_int(s, "isf", in_sample_fmt,   0);
 +    av_opt_set_int(s, "isr", in_sample_rate,  0);
 +    av_opt_set_int(s, "tsf", AV_SAMPLE_FMT_NONE,   0);
 +    av_opt_set_int(s, "ich", av_get_channel_layout_nb_channels(s-> in_ch_layout), 0);
 +    av_opt_set_int(s, "och", av_get_channel_layout_nb_channels(s->out_ch_layout), 0);
 +    av_opt_set_int(s, "uch", 0, 0);
 +    return s;
 +}
 +
 +static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){
 +    a->fmt   = fmt;
 +    a->bps   = av_get_bytes_per_sample(fmt);
 +    a->planar= av_sample_fmt_is_planar(fmt);
 +}
 +
 +static void free_temp(AudioData *a){
 +    av_free(a->data);
 +    memset(a, 0, sizeof(*a));
 +}
 +
 +void swr_free(SwrContext **ss){
 +    SwrContext *s= *ss;
 +    if(s){
 +        free_temp(&s->postin);
 +        free_temp(&s->midbuf);
 +        free_temp(&s->preout);
 +        free_temp(&s->in_buffer);
 +        free_temp(&s->dither);
 +        swri_audio_convert_free(&s-> in_convert);
 +        swri_audio_convert_free(&s->out_convert);
 +        swri_audio_convert_free(&s->full_convert);
 +        swri_resample_free(&s->resample);
 +        swri_rematrix_free(s);
 +    }
 +
 +    av_freep(ss);
 +}
 +
 +int swr_init(struct SwrContext *s){
 +    s->in_buffer_index= 0;
 +    s->in_buffer_count= 0;
 +    s->resample_in_constraint= 0;
 +    free_temp(&s->postin);
 +    free_temp(&s->midbuf);
 +    free_temp(&s->preout);
 +    free_temp(&s->in_buffer);
 +    free_temp(&s->dither);
 +    swri_audio_convert_free(&s-> in_convert);
 +    swri_audio_convert_free(&s->out_convert);
 +    swri_audio_convert_free(&s->full_convert);
 +    swri_rematrix_free(s);
 +
 +    s->flushed = 0;
 +
 +    if(s-> in_sample_fmt >= AV_SAMPLE_FMT_NB){
 +        av_log(s, AV_LOG_ERROR, "Requested input sample format %d is invalid\n", s->in_sample_fmt);
 +        return AVERROR(EINVAL);
 +    }
 +    if(s->out_sample_fmt >= AV_SAMPLE_FMT_NB){
 +        av_log(s, AV_LOG_ERROR, "Requested output sample format %d is invalid\n", s->out_sample_fmt);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
 +        if(av_get_planar_sample_fmt(s->in_sample_fmt) <= AV_SAMPLE_FMT_S16P){
 +            s->int_sample_fmt= AV_SAMPLE_FMT_S16P;
 +        }else if(av_get_planar_sample_fmt(s->in_sample_fmt) <= AV_SAMPLE_FMT_FLTP){
 +            s->int_sample_fmt= AV_SAMPLE_FMT_FLTP;
 +        }else{
 +            av_log(s, AV_LOG_DEBUG, "Using double precision mode\n");
 +            s->int_sample_fmt= AV_SAMPLE_FMT_DBLP;
 +        }
 +    }
 +
 +    if(   s->int_sample_fmt != AV_SAMPLE_FMT_S16P
 +        &&s->int_sample_fmt != AV_SAMPLE_FMT_S32P
 +        &&s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
 +        &&s->int_sample_fmt != AV_SAMPLE_FMT_DBLP){
 +        av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, S16/S32/FLT/DBL is supported\n", av_get_sample_fmt_name(s->int_sample_fmt));
 +        return AVERROR(EINVAL);
 +    }
 +
 +    set_audiodata_fmt(&s-> in, s-> in_sample_fmt);
 +    set_audiodata_fmt(&s->out, s->out_sample_fmt);
 +
 +    if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
 +        s->resample = swri_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta);
 +    }else
 +        swri_resample_free(&s->resample);
 +    if(    s->int_sample_fmt != AV_SAMPLE_FMT_S16P
 +        && s->int_sample_fmt != AV_SAMPLE_FMT_S32P
 +        && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
 +        && s->int_sample_fmt != AV_SAMPLE_FMT_DBLP
 +        && s->resample){
 +        av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16/s32/flt/dbl\n");
 +        return -1;
 +    }
 +
 +    if(!s->used_ch_count)
 +        s->used_ch_count= s->in.ch_count;
 +
 +    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
 +        av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
 +        s-> in_ch_layout= 0;
 +    }
 +
 +    if(!s-> in_ch_layout)
 +        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
 +    if(!s->out_ch_layout)
 +        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
 +
 +    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0 ||
 +                 s->rematrix_custom;
 +
 +#define RSC 1 //FIXME finetune
 +    if(!s-> in.ch_count)
 +        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
 +    if(!s->used_ch_count)
 +        s->used_ch_count= s->in.ch_count;
 +    if(!s->out.ch_count)
 +        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
 +
 +    if(!s-> in.ch_count){
 +        av_assert0(!s->in_ch_layout);
 +        av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
 +        return -1;
 +    }
 +
 +    if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
 +        av_log(s, AV_LOG_ERROR, "Rematrix is needed but there is not enough information to do it\n");
 +        return -1;
 +    }
 +
 +av_assert0(s->used_ch_count);
 +av_assert0(s->out.ch_count);
 +    s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;
 +
 +    s->in_buffer= s->in;
 +
 +    if(!s->resample && !s->rematrix && !s->channel_map && !s->dither_method){
 +        s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt,
 +                                                   s-> in_sample_fmt, s-> in.ch_count, NULL, 0);
 +        return 0;
 +    }
 +
 +    s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt,
 +                                             s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0);
 +    s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt,
 +                                             s->int_sample_fmt, s->out.ch_count, NULL, 0);
 +
 +
 +    s->postin= s->in;
 +    s->preout= s->out;
 +    s->midbuf= s->in;
 +
 +    if(s->channel_map){
 +        s->postin.ch_count=
 +        s->midbuf.ch_count= s->used_ch_count;
 +        if(s->resample)
 +            s->in_buffer.ch_count= s->used_ch_count;
 +    }
 +    if(!s->resample_first){
 +        s->midbuf.ch_count= s->out.ch_count;
 +        if(s->resample)
 +            s->in_buffer.ch_count = s->out.ch_count;
 +    }
 +
 +    set_audiodata_fmt(&s->postin, s->int_sample_fmt);
 +    set_audiodata_fmt(&s->midbuf, s->int_sample_fmt);
 +    set_audiodata_fmt(&s->preout, s->int_sample_fmt);
 +
 +    if(s->resample){
 +        set_audiodata_fmt(&s->in_buffer, s->int_sample_fmt);
 +    }
 +
 +    s->dither = s->preout;
 +
 +    if(s->rematrix || s->dither_method)
 +        return swri_rematrix_init(s);
 +
 +    return 0;
 +}
 +
 +static int realloc_audio(AudioData *a, int count){
 +    int i, countb;
 +    AudioData old;
 +
 +    if(count < 0 || count > INT_MAX/2/a->bps/a->ch_count)
 +        return AVERROR(EINVAL);
 +
 +    if(a->count >= count)
 +        return 0;
 +
 +    count*=2;
 +
 +    countb= FFALIGN(count*a->bps, ALIGN);
 +    old= *a;
 +
 +    av_assert0(a->bps);
 +    av_assert0(a->ch_count);
 +
 +    a->data= av_mallocz(countb*a->ch_count);
 +    if(!a->data)
 +        return AVERROR(ENOMEM);
 +    for(i=0; i<a->ch_count; i++){
 +        a->ch[i]= a->data + i*(a->planar ? countb : a->bps);
 +        if(a->planar) memcpy(a->ch[i], old.ch[i], a->count*a->bps);
 +    }
 +    if(!a->planar) memcpy(a->ch[0], old.ch[0], a->count*a->ch_count*a->bps);
 +    av_free(old.data);
 +    a->count= count;
 +
 +    return 1;
 +}
 +
 +static void copy(AudioData *out, AudioData *in,
 +                 int count){
 +    av_assert0(out->planar == in->planar);
 +    av_assert0(out->bps == in->bps);
 +    av_assert0(out->ch_count == in->ch_count);
 +    if(out->planar){
 +        int ch;
 +        for(ch=0; ch<out->ch_count; ch++)
 +            memcpy(out->ch[ch], in->ch[ch], count*out->bps);
 +    }else
 +        memcpy(out->ch[0], in->ch[0], count*out->ch_count*out->bps);
 +}
 +
 +static void fill_audiodata(AudioData *out, uint8_t *in_arg [SWR_CH_MAX]){
 +    int i;
 +    if(!in_arg){
 +        memset(out->ch, 0, sizeof(out->ch));
 +    }else if(out->planar){
 +        for(i=0; i<out->ch_count; i++)
 +            out->ch[i]= in_arg[i];
 +    }else{
 +        for(i=0; i<out->ch_count; i++)
 +            out->ch[i]= in_arg[0] + i*out->bps;
 +    }
 +}
 +
 +static void reversefill_audiodata(AudioData *out, uint8_t *in_arg [SWR_CH_MAX]){
 +    int i;
 +    if(out->planar){
 +        for(i=0; i<out->ch_count; i++)
 +            in_arg[i]= out->ch[i];
 +    }else{
 +        in_arg[0]= out->ch[0];
 +    }
 +}
 +
 +/**
 + *
 + * out may be equal in.
 + */
 +static void buf_set(AudioData *out, AudioData *in, int count){
 +    int ch;
 +    if(in->planar){
 +        for(ch=0; ch<out->ch_count; ch++)
 +            out->ch[ch]= in->ch[ch] + count*out->bps;
 +    }else{
 +        for(ch=out->ch_count-1; ch>=0; ch--)
 +            out->ch[ch]= in->ch[0] + (ch + count*out->ch_count) * out->bps;
 +    }
 +}
 +
 +/**
 + *
 + * @return number of samples output per channel
 + */
 +static int resample(SwrContext *s, AudioData *out_param, int out_count,
 +                             const AudioData * in_param, int in_count){
 +    AudioData in, out, tmp;
 +    int ret_sum=0;
 +    int border=0;
 +
 +    av_assert1(s->in_buffer.ch_count == in_param->ch_count);
 +    av_assert1(s->in_buffer.planar   == in_param->planar);
 +    av_assert1(s->in_buffer.fmt      == in_param->fmt);
 +
 +    tmp=out=*out_param;
 +    in =  *in_param;
 +
 +    do{
 +        int ret, size, consumed;
 +        if(!s->resample_in_constraint && s->in_buffer_count){
 +            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
 +            ret= swri_multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed);
 +            out_count -= ret;
 +            ret_sum += ret;
 +            buf_set(&out, &out, ret);
 +            s->in_buffer_count -= consumed;
 +            s->in_buffer_index += consumed;
 +
 +            if(!in_count)
 +                break;
 +            if(s->in_buffer_count <= border){
 +                buf_set(&in, &in, -s->in_buffer_count);
 +                in_count += s->in_buffer_count;
 +                s->in_buffer_count=0;
 +                s->in_buffer_index=0;
 +                border = 0;
 +            }
 +        }
 +
 +        if(in_count && !s->in_buffer_count){
 +            s->in_buffer_index=0;
 +            ret= swri_multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed);
 +            out_count -= ret;
 +            ret_sum += ret;
 +            buf_set(&out, &out, ret);
 +            in_count -= consumed;
 +            buf_set(&in, &in, consumed);
 +        }
 +
 +        //TODO is this check sane considering the advanced copy avoidance below
 +        size= s->in_buffer_index + s->in_buffer_count + in_count;
 +        if(   size > s->in_buffer.count
 +           && s->in_buffer_count + in_count <= s->in_buffer_index){
 +            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
 +            copy(&s->in_buffer, &tmp, s->in_buffer_count);
 +            s->in_buffer_index=0;
 +        }else
 +            if((ret=realloc_audio(&s->in_buffer, size)) < 0)
 +                return ret;
 +
 +        if(in_count){
 +            int count= in_count;
 +            if(s->in_buffer_count && s->in_buffer_count+2 < count && out_count) count= s->in_buffer_count+2;
 +
 +            buf_set(&tmp, &s->in_buffer, s->in_buffer_index + s->in_buffer_count);
 +            copy(&tmp, &in, /*in_*/count);
 +            s->in_buffer_count += count;
 +            in_count -= count;
 +            border += count;
 +            buf_set(&in, &in, count);
 +            s->resample_in_constraint= 0;
 +            if(s->in_buffer_count != count || in_count)
 +                continue;
 +        }
 +        break;
 +    }while(1);
 +
 +    s->resample_in_constraint= !!out_count;
 +
 +    return ret_sum;
 +}
 +
 +static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_count,
 +                                                      AudioData *in , int  in_count){
 +    AudioData *postin, *midbuf, *preout;
 +    int ret/*, in_max*/;
 +    AudioData preout_tmp, midbuf_tmp;
 +
 +    if(s->full_convert){
 +        av_assert0(!s->resample);
 +        swri_audio_convert(s->full_convert, out, in, in_count);
 +        return out_count;
 +    }
 +
 +//     in_max= out_count*(int64_t)s->in_sample_rate / s->out_sample_rate + resample_filter_taps;
 +//     in_count= FFMIN(in_count, in_in + 2 - s->hist_buffer_count);
 +
 +    if((ret=realloc_audio(&s->postin, in_count))<0)
 +        return ret;
 +    if(s->resample_first){
 +        av_assert0(s->midbuf.ch_count == s->used_ch_count);
 +        if((ret=realloc_audio(&s->midbuf, out_count))<0)
 +            return ret;
 +    }else{
 +        av_assert0(s->midbuf.ch_count ==  s->out.ch_count);
 +        if((ret=realloc_audio(&s->midbuf,  in_count))<0)
 +            return ret;
 +    }
 +    if((ret=realloc_audio(&s->preout, out_count))<0)
 +        return ret;
 +
 +    postin= &s->postin;
 +
 +    midbuf_tmp= s->midbuf;
 +    midbuf= &midbuf_tmp;
 +    preout_tmp= s->preout;
 +    preout= &preout_tmp;
 +
 +    if(s->int_sample_fmt == s-> in_sample_fmt && s->in.planar && !s->channel_map)
 +        postin= in;
 +
 +    if(s->resample_first ? !s->resample : !s->rematrix)
 +        midbuf= postin;
 +
 +    if(s->resample_first ? !s->rematrix : !s->resample)
 +        preout= midbuf;
 +
 +    if(s->int_sample_fmt == s->out_sample_fmt && s->out.planar){
 +        if(preout==in){
 +            out_count= FFMIN(out_count, in_count); //TODO check at the end if this is needed or redundant
 +            av_assert0(s->in.planar); //we only support planar internally so it has to be, we support copying non planar though
 +            copy(out, in, out_count);
 +            return out_count;
 +        }
 +        else if(preout==postin) preout= midbuf= postin= out;
 +        else if(preout==midbuf) preout= midbuf= out;
 +        else                    preout= out;
 +    }
 +
 +    if(in != postin){
 +        swri_audio_convert(s->in_convert, postin, in, in_count);
 +    }
 +
 +    if(s->resample_first){
 +        if(postin != midbuf)
 +            out_count= resample(s, midbuf, out_count, postin, in_count);
 +        if(midbuf != preout)
 +            swri_rematrix(s, preout, midbuf, out_count, preout==out);
 +    }else{
 +        if(postin != midbuf)
 +            swri_rematrix(s, midbuf, postin, in_count, midbuf==out);
 +        if(midbuf != preout)
 +            out_count= resample(s, preout, out_count, midbuf, in_count);
 +    }
 +
 +    if(preout != out && out_count){
 +        if(s->dither_method){
 +            int ch;
 +            int dither_count= FFMAX(out_count, 1<<16);
 +            av_assert0(preout != in);
 +
 +            if((ret=realloc_audio(&s->dither, dither_count))<0)
 +                return ret;
 +            if(ret)
 +                for(ch=0; ch<s->dither.ch_count; ch++)
 +                    swri_get_dither(s, s->dither.ch[ch], s->dither.count, 12345678913579<<ch, s->out_sample_fmt, s->int_sample_fmt);
 +            av_assert0(s->dither.ch_count == preout->ch_count);
 +
 +            if(s->dither_pos + out_count > s->dither.count)
 +                s->dither_pos = 0;
 +
 +            for(ch=0; ch<preout->ch_count; ch++)
 +                s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, out_count);
 +
 +            s->dither_pos += out_count;
 +        }
 +//FIXME packed doesnt need more than 1 chan here!
 +        swri_audio_convert(s->out_convert, out, preout, out_count);
 +    }
 +    return out_count;
 +}
 +
 +int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count,
 +                                const uint8_t *in_arg [SWR_CH_MAX], int  in_count){
 +    AudioData * in= &s->in;
 +    AudioData *out= &s->out;
 +
 +    if(s->drop_output > 0){
 +        int ret;
 +        AudioData tmp = s->out;
 +        uint8_t *tmp_arg[SWR_CH_MAX];
 +        tmp.count = 0;
 +        tmp.data  = NULL;
 +        if((ret=realloc_audio(&tmp, s->drop_output))<0)
 +            return ret;
 +
 +        reversefill_audiodata(&tmp, tmp_arg);
 +        s->drop_output *= -1; //FIXME find a less hackish solution
 +        ret = swr_convert(s, tmp_arg, -s->drop_output, in_arg, in_count); //FIXME optimize but this is as good as never called so maybe it doesnt matter
 +        s->drop_output *= -1;
 +        if(ret>0)
 +            s->drop_output -= ret;
 +
 +        av_freep(&tmp.data);
 +        if(s->drop_output || !out_arg)
 +            return 0;
 +        in_count = 0;
 +    }
 +
 +    if(!in_arg){
 +        if(s->in_buffer_count){
 +            if (s->resample && !s->flushed) {
 +                AudioData *a= &s->in_buffer;
 +                int i, j, ret;
 +                if((ret=realloc_audio(a, s->in_buffer_index + 2*s->in_buffer_count)) < 0)
 +                    return ret;
 +                av_assert0(a->planar);
 +                for(i=0; i<a->ch_count; i++){
 +                    for(j=0; j<s->in_buffer_count; j++){
 +                        memcpy(a->ch[i] + (s->in_buffer_index+s->in_buffer_count+j  )*a->bps,
 +                            a->ch[i] + (s->in_buffer_index+s->in_buffer_count-j-1)*a->bps, a->bps);
 +                    }
 +                }
 +                s->in_buffer_count += (s->in_buffer_count+1)/2;
 +                s->resample_in_constraint = 0;
 +                s->flushed = 1;
 +            }
 +        }else{
 +            return 0;
 +        }
 +    }else
 +        fill_audiodata(in ,  (void*)in_arg);
 +
 +    fill_audiodata(out, out_arg);
 +
 +    if(s->resample){
 +        int ret = swr_convert_internal(s, out, out_count, in, in_count);
 +        if(ret>0 && !s->drop_output)
 +            s->outpts += ret * (int64_t)s->in_sample_rate;
 +        return ret;
 +    }else{
 +        AudioData tmp= *in;
 +        int ret2=0;
 +        int ret, size;
 +        size = FFMIN(out_count, s->in_buffer_count);
 +        if(size){
 +            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
 +            ret= swr_convert_internal(s, out, size, &tmp, size);
 +            if(ret<0)
 +                return ret;
 +            ret2= ret;
 +            s->in_buffer_count -= ret;
 +            s->in_buffer_index += ret;
 +            buf_set(out, out, ret);
 +            out_count -= ret;
 +            if(!s->in_buffer_count)
 +                s->in_buffer_index = 0;
 +        }
 +
 +        if(in_count){
 +            size= s->in_buffer_index + s->in_buffer_count + in_count - out_count;
 +
 +            if(in_count > out_count) { //FIXME move after swr_convert_internal
 +                if(   size > s->in_buffer.count
 +                && s->in_buffer_count + in_count - out_count <= s->in_buffer_index){
 +                    buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
 +                    copy(&s->in_buffer, &tmp, s->in_buffer_count);
 +                    s->in_buffer_index=0;
 +                }else
 +                    if((ret=realloc_audio(&s->in_buffer, size)) < 0)
 +                        return ret;
 +            }
 +
 +            if(out_count){
 +                size = FFMIN(in_count, out_count);
 +                ret= swr_convert_internal(s, out, size, in, size);
 +                if(ret<0)
 +                    return ret;
 +                buf_set(in, in, ret);
 +                in_count -= ret;
 +                ret2 += ret;
 +            }
 +            if(in_count){
 +                buf_set(&tmp, &s->in_buffer, s->in_buffer_index + s->in_buffer_count);
 +                copy(&tmp, in, in_count);
 +                s->in_buffer_count += in_count;
 +            }
 +        }
 +        if(ret2>0 && !s->drop_output)
 +            s->outpts += ret2 * (int64_t)s->in_sample_rate;
 +        return ret2;
 +    }
 +}
 +
 +int swr_drop_output(struct SwrContext *s, int count){
 +    s->drop_output += count;
 +
 +    if(s->drop_output <= 0)
 +        return 0;
 +
 +    av_log(s, AV_LOG_VERBOSE, "discarding %d audio samples\n", count);
 +    return swr_convert(s, NULL, s->drop_output, NULL, 0);
 +}
 +
 +int swr_inject_silence(struct SwrContext *s, int count){
 +    int ret, i;
 +    AudioData silence = s->in;
 +    uint8_t *tmp_arg[SWR_CH_MAX];
 +
 +    if(count <= 0)
 +        return 0;
 +
 +    silence.count = 0;
 +    silence.data  = NULL;
 +    if((ret=realloc_audio(&silence, count))<0)
 +        return ret;
 +
 +    if(silence.planar) for(i=0; i<silence.ch_count; i++) {
 +        memset(silence.ch[i], silence.bps==1 ? 0x80 : 0, count*silence.bps);
 +    } else
 +        memset(silence.ch[0], silence.bps==1 ? 0x80 : 0, count*silence.bps*silence.ch_count);
 +
 +    reversefill_audiodata(&silence, tmp_arg);
 +    av_log(s, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", count);
 +    ret = swr_convert(s, NULL, 0, (const uint8_t**)tmp_arg, count);
 +    av_freep(&silence.data);
 +    return ret;
 +}
 +
 +int64_t swr_next_pts(struct SwrContext *s, int64_t pts){
 +    if(pts == INT64_MIN)
 +        return s->outpts;
 +    if(s->min_compensation >= FLT_MAX) {
 +        return (s->outpts = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate));
 +    } else {
 +        int64_t delta = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate) - s->outpts;
 +        double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate);
 +
 +        if(fabs(fdelta) > s->min_compensation) {
 +            if(!s->outpts || fabs(fdelta) > s->min_hard_compensation){
 +                int ret;
 +                if(delta > 0) ret = swr_inject_silence(s,  delta / s->out_sample_rate);
 +                else          ret = swr_drop_output   (s, -delta / s-> in_sample_rate);
 +                if(ret<0){
 +                    av_log(s, AV_LOG_ERROR, "Failed to compensate for timestamp delta of %f\n", fdelta);
 +                }
 +            } else if(s->soft_compensation_duration && s->max_soft_compensation) {
 +                int duration = s->out_sample_rate * s->soft_compensation_duration;
 +                double max_soft_compensation = s->max_soft_compensation / (s->max_soft_compensation < 0 ? -s->in_sample_rate : 1);
 +                int comp = av_clipf(fdelta, -max_soft_compensation, max_soft_compensation) * duration ;
 +                av_log(s, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", fdelta, comp, duration);
 +                swr_set_compensation(s, comp, duration);
 +            }
 +        }
 +
 +        return s->outpts;
 +    }
 +}
diff --combined libswscale/options.c
index f15b73fb57969a2a55aa2e22fe6305d637587253,09eec15bb6620fcc89d9298324f0efb4b057756f..3b490573a7c7da6f63c926d5248a0b16d15cdbc2
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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
 - * 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
   */
  
@@@ -34,7 -34,7 +34,7 @@@ static const char *sws_context_to_name(
  #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  
  static const AVOption options[] = {
-     { "sws_flags",       "scaler flags",                  OFFSET(flags),     AV_OPT_TYPE_FLAGS,  { .dbl = DEFAULT            }, 0,       UINT_MAX,       VE, "sws_flags" },
+     { "sws_flags",       "scaler flags",                  OFFSET(flags),     AV_OPT_TYPE_FLAGS,  { .i64 = DEFAULT            }, 0,       UINT_MAX,       VE, "sws_flags" },
      { "fast_bilinear",   "fast bilinear",                 0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_FAST_BILINEAR  }, INT_MIN, INT_MAX,        VE, "sws_flags" },
      { "bilinear",        "bilinear",                      0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_BILINEAR       }, INT_MIN, INT_MAX,        VE, "sws_flags" },
      { "bicubic",         "bicubic",                       0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_BICUBIC        }, INT_MIN, INT_MAX,        VE, "sws_flags" },
      { NULL }
  };
  
 -const AVClass sws_context_class = { "SWScaler", sws_context_to_name, options };
 +const AVClass sws_context_class = {
 +    .class_name = "SWScaler",
 +    .item_name  = sws_context_to_name,
 +    .option     = options,
 +    .category   = AV_CLASS_CATEGORY_SWSCALER,
 +};
  
  const AVClass *sws_get_class(void)
  {