Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 14 Apr 2012 19:49:01 +0000 (21:49 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 14 Apr 2012 20:37:43 +0000 (22:37 +0200)
* qatar/master:
  vsrc_buffer: fix check from 7ae7c41.
  libxvid: Reorder functions to avoid forward declarations; make functions static.
  libxvid: drop some pointless dead code
  wmal: vertical alignment cosmetics
  wmal: Warn about missing bitstream splicing feature and ask for sample.
  wmal: Skip seekable_frame_in_packet.
  wmal: Drop unused variable num_possible_block_size.
  avfiltergraph: make the AVFilterInOut alloc/free API public
  graphparser: allow specifying sws flags in the graph description.
  graphparser: fix the order of connecting unlabeled links.
  graphparser: add avfilter_graph_parse2().
  vsrc_buffer: allow using a NULL buffer to signal EOF.
  swscale: handle last pixel if lines have an odd width.
  qdm2: fix a dubious pointer cast
  WMAL: Do not try to read rawpcm coefficients if bits is invalid
  mov: Fix detecting there is no sync sample.
  tiffdec: K&R cosmetics
  avf: has_duration does not check the global one
  dsputil: fix optimized emu_edge function on Win64.

Conflicts:
doc/APIchanges
libavcodec/libxvid_rc.c
libavcodec/libxvidff.c
libavcodec/tiff.c
libavcodec/wmalosslessdec.c
libavfilter/avfiltergraph.h
libavfilter/graphparser.c
libavfilter/version.h
libavfilter/vsrc_buffer.c
libswscale/output.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
17 files changed:
1  2 
doc/APIchanges
doc/filters.texi
libavcodec/libxvid_rc.c
libavcodec/libxvidff.c
libavcodec/qdm2.c
libavcodec/tiff.c
libavcodec/wmalosslessdec.c
libavcodec/x86/dsputil_yasm.asm
libavfilter/avfiltergraph.h
libavfilter/graphparser.c
libavfilter/version.h
libavfilter/vsrc_buffer.c
libavformat/isom.h
libavformat/mov.c
libavformat/utils.c
libswscale/output.c
tests/lavfi-regression.sh

diff --cc doc/APIchanges
@@@ -13,12 -12,10 +13,15 @@@ libavutil:   2011-04-1
  
  API changes, most recent first:
  
 -  Add avfilter_graph_parse2(), avfilter_inout_alloc() and
 -  avfilter_inout_free() functions.
 +2012-04-12 - xxxxxxx - lavfi 2.68.100
 +  Install libavfilter/asrc_abuffer.h public header.
 +
 +2012-03-26 - a67d9cf - lavfi 2.66.100
 +  Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
 +
+ 2012-xx-xx - xxxxxxx - lavfi 2.16.0 - avfiltergraph.h
++  Add avfilter_graph_parse2()
  2012-xx-xx - xxxxxxx - lavu 51.27.0 - samplefmt.h
    Add av_get_packed_sample_fmt() and av_get_planar_sample_fmt()
  
Simple merge
@@@ -39,9 -36,7 +37,7 @@@ int ff_xvid_rate_control_init(MpegEncCo
      xvid_plg_create_t xvid_plg_create = { 0 };
      xvid_plugin_2pass2_t xvid_2pass2  = { 0 };
  
- //xvid_debug=-1;
 -    fd=ff_tempfile("xvidrc.", &tmp_name);
 +    fd=av_tempfile("xvidrc.", &tmp_name, 0, s->avctx);
      if (fd == -1) {
          av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n");
          return -1;
              frame_types[rce->pict_type], (int)lrintf(rce->qscale / FF_QP2LAMBDA), rce->i_count, s->mb_num - rce->i_count - rce->skip_count,
              rce->skip_count, (rce->i_tex_bits + rce->p_tex_bits + rce->misc_bits+7)/8, (rce->header_bits+rce->mv_bits+7)/8);
  
- //av_log(NULL, AV_LOG_ERROR, "%s\n", tmp);
 -        write(fd, tmp, strlen(tmp));
 +        if (write(fd, tmp, strlen(tmp)) < 0) {
 +            av_log(NULL, AV_LOG_ERROR, "Error %s writing 2pass logfile\n", strerror(errno));
 +            return AVERROR(errno);
 +        }
      }
  
      close(fd);
@@@ -72,155 -73,455 +72,420 @@@ struct xvid_ff_pass1 
      struct xvid_context *context;   /**< Pointer to private context */
  };
  
- /* Prototypes - See function implementation for details */
- int xvid_strip_vol_header(AVCodecContext *avctx, AVPacket *pkt, unsigned int header_len, unsigned int frame_len);
- int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2);
- void xvid_correct_framerate(AVCodecContext *avctx);
+ /*
+  * Xvid 2-Pass Kludge Section
+  *
+  * Xvid's default 2-pass doesn't allow us to create data as we need to, so
+  * this section spends time replacing the first pass plugin so we can write
+  * statistic information as libavcodec requests in. We have another kludge
+  * that allows us to pass data to the second pass in Xvid without a custom
+  * rate-control plugin.
+  */
  
 -/* Wrapper to work around the lack of mkstemp() on mingw.
 - * Also, tries to create file in /tmp first, if possible.
 - * *prefix can be a character constant; *filename will be allocated internally.
 - * @return file descriptor of opened file (or -1 on error)
 - * and opened file name in **filename. */
 -int ff_tempfile(const char *prefix, char **filename) {
 -    int fd=-1;
 -#if !HAVE_MKSTEMP
 -    *filename = tempnam(".", prefix);
 -#else
 -    size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
 -    *filename = av_malloc(len);
 -#endif
 -    /* -----common section-----*/
 -    if (*filename == NULL) {
 -        av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
 -        return -1;
 -    }
 -#if !HAVE_MKSTEMP
 -    fd = open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444);
 -#else
 -    snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
 -    fd = mkstemp(*filename);
 -    if (fd < 0) {
 -        snprintf(*filename, len, "./%sXXXXXX", prefix);
 -        fd = mkstemp(*filename);
 -    }
 -#endif
 -    /* -----common section-----*/
 -    if (fd < 0) {
 -        av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
 -        return -1;
 -    }
 -    return fd; /* success */
 -}
  
  /**
-  * Create the private context for the encoder.
-  * All buffers are allocated, settings are loaded from the user,
-  * and the encoder context created.
+  * Initialize the two-pass plugin and context.
   *
-  * @param avctx AVCodecContext pointer to context
-  * @return Returns 0 on success, -1 on failure
+  * @param param Input construction parameter structure
+  * @param handle Private context handle
+  * @return Returns XVID_ERR_xxxx on failure, or 0 on success.
   */
- static av_cold int xvid_encode_init(AVCodecContext *avctx)  {
-     int xerr, i;
-     int xvid_flags = avctx->flags;
-     struct xvid_context *x = avctx->priv_data;
-     uint16_t *intra, *inter;
-     int fd;
+ static int xvid_ff_2pass_create(xvid_plg_create_t * param,
+                                 void ** handle) {
+     struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param;
+     char *log = x->context->twopassbuffer;
  
-     xvid_plugin_single_t single       = { 0 };
-     struct xvid_ff_pass1 rc2pass1     = { 0 };
-     xvid_plugin_2pass2_t rc2pass2     = { 0 };
-     xvid_gbl_init_t xvid_gbl_init     = { 0 };
-     xvid_enc_create_t xvid_enc_create = { 0 };
-     xvid_enc_plugin_t plugins[7];
+     /* Do a quick bounds check */
+     if( log == NULL )
+         return XVID_ERR_FAIL;
  
-     /* Bring in VOP flags from ffmpeg command-line */
-     x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */
-     if( xvid_flags & CODEC_FLAG_4MV )
-         x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */
-     if( avctx->trellis
-         )
-         x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */
-     if( xvid_flags & CODEC_FLAG_AC_PRED )
-         x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */
-     if( xvid_flags & CODEC_FLAG_GRAY )
-         x->vop_flags |= XVID_VOP_GREYSCALE;
+     /* We use snprintf() */
+     /* This is because we can safely prevent a buffer overflow */
+     log[0] = 0;
+     snprintf(log, BUFFER_REMAINING(log),
 -        "# avconv 2-pass log file, using xvid codec\n");
++        "# ffmpeg 2-pass log file, using xvid codec\n");
+     snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),
+         "# Do not modify. libxvidcore version: %d.%d.%d\n\n",
+         XVID_VERSION_MAJOR(XVID_VERSION),
+         XVID_VERSION_MINOR(XVID_VERSION),
+         XVID_VERSION_PATCH(XVID_VERSION));
  
-     /* Decide which ME quality setting to use */
-     x->me_flags = 0;
-     switch( avctx->me_method ) {
-        case ME_FULL:   /* Quality 6 */
-            x->me_flags |=  XVID_ME_EXTSEARCH16
-                        |   XVID_ME_EXTSEARCH8;
+     *handle = x->context;
+     return 0;
+ }
  
-        case ME_EPZS:   /* Quality 4 */
-            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND8
-                        |   XVID_ME_HALFPELREFINE8
-                        |   XVID_ME_CHROMA_PVOP
-                        |   XVID_ME_CHROMA_BVOP;
+ /**
+  * Destroy the two-pass plugin context.
+  *
+  * @param ref Context pointer for the plugin
+  * @param param Destrooy context
+  * @return Returns 0, success guaranteed
+  */
+ static int xvid_ff_2pass_destroy(struct xvid_context *ref,
+                                 xvid_plg_destroy_t *param) {
+     /* Currently cannot think of anything to do on destruction */
+     /* Still, the framework should be here for reference/use */
+     if( ref->twopassbuffer != NULL )
+         ref->twopassbuffer[0] = 0;
+     return 0;
+ }
  
-        case ME_LOG:    /* Quality 2 */
-        case ME_PHODS:
-        case ME_X1:
-            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND16
-                        |   XVID_ME_HALFPELREFINE16;
+ /**
+  * Enable fast encode mode during the first pass.
+  *
+  * @param ref Context pointer for the plugin
+  * @param param Frame data
+  * @return Returns 0, success guaranteed
+  */
+ static int xvid_ff_2pass_before(struct xvid_context *ref,
+                                 xvid_plg_data_t *param) {
+     int motion_remove;
+     int motion_replacements;
+     int vop_remove;
  
-        case ME_ZERO:   /* Quality 0 */
-        default:
-            break;
-     }
+     /* Nothing to do here, result is changed too much */
+     if( param->zone && param->zone->mode == XVID_ZONE_QUANT )
+         return 0;
  
-     /* Decide how we should decide blocks */
-     switch( avctx->mb_decision ) {
-        case 2:
-            x->vop_flags |= XVID_VOP_MODEDECISION_RD;
-            x->me_flags |=  XVID_ME_HALFPELREFINE8_RD
-                        |   XVID_ME_QUARTERPELREFINE8_RD
-                        |   XVID_ME_EXTSEARCH_RD
-                        |   XVID_ME_CHECKPREDICTION_RD;
-        case 1:
-            if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) )
-                x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD;
-            x->me_flags |=  XVID_ME_HALFPELREFINE16_RD
-                        |   XVID_ME_QUARTERPELREFINE16_RD;
+     /* We can implement a 'turbo' first pass mode here */
+     param->quant = 2;
  
-        default:
-            break;
-     }
+     /* Init values */
+     motion_remove = ~XVID_ME_CHROMA_PVOP &
+                     ~XVID_ME_CHROMA_BVOP &
+                     ~XVID_ME_EXTSEARCH16 &
+                     ~XVID_ME_ADVANCEDDIAMOND16;
+     motion_replacements = XVID_ME_FAST_MODEINTERPOLATE |
+                           XVID_ME_SKIP_DELTASEARCH |
+                           XVID_ME_FASTREFINE16 |
+                           XVID_ME_BFRAME_EARLYSTOP;
+     vop_remove = ~XVID_VOP_MODEDECISION_RD &
+                  ~XVID_VOP_FAST_MODEDECISION_RD &
+                  ~XVID_VOP_TRELLISQUANT &
+                  ~XVID_VOP_INTER4V &
+                  ~XVID_VOP_HQACPRED;
  
-     /* Bring in VOL flags from ffmpeg command-line */
-     x->vol_flags = 0;
-     if( xvid_flags & CODEC_FLAG_GMC ) {
-         x->vol_flags |= XVID_VOL_GMC;
-         x->me_flags |= XVID_ME_GME_REFINE;
-     }
-     if( xvid_flags & CODEC_FLAG_QPEL ) {
-         x->vol_flags |= XVID_VOL_QUARTERPEL;
-         x->me_flags |= XVID_ME_QUARTERPELREFINE16;
-         if( x->vop_flags & XVID_VOP_INTER4V )
-             x->me_flags |= XVID_ME_QUARTERPELREFINE8;
-     }
+     param->vol_flags &= ~XVID_VOL_GMC;
+     param->vop_flags &= vop_remove;
+     param->motion_flags &= motion_remove;
+     param->motion_flags |= motion_replacements;
  
-     xvid_gbl_init.version = XVID_VERSION;
-     xvid_gbl_init.debug = 0;
+     return 0;
+ }
  
- #if ARCH_PPC
-     /* Xvid's PPC support is borked, use libavcodec to detect */
- #if HAVE_ALTIVEC
-     if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) {
-         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC;
-     } else
- #endif
-         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
- #else
-     /* Xvid can detect on x86 */
-     xvid_gbl_init.cpu_flags = 0;
- #endif
+ /**
+  * Capture statistic data and write it during first pass.
+  *
+  * @param ref Context pointer for the plugin
+  * @param param Statistic data
+  * @return Returns XVID_ERR_xxxx on failure, or 0 on success
+  */
+ static int xvid_ff_2pass_after(struct xvid_context *ref,
+                                 xvid_plg_data_t *param) {
+     char *log = ref->twopassbuffer;
+     const char *frame_types = " ipbs";
+     char frame_type;
  
-     /* Initialize */
-     xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
+     /* Quick bounds check */
+     if( log == NULL )
+         return XVID_ERR_FAIL;
  
-     /* Create the encoder reference */
-     xvid_enc_create.version = XVID_VERSION;
+     /* Convert the type given to us into a character */
+     if( param->type < 5 && param->type > 0 ) {
+         frame_type = frame_types[param->type];
+     } else {
+         return XVID_ERR_FAIL;
+     }
  
-     /* Store the desired frame size */
-     xvid_enc_create.width = x->xsize = avctx->width;
-     xvid_enc_create.height = x->ysize = avctx->height;
+     snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),
+         "%c %d %d %d %d %d %d\n",
+         frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks,
+         param->stats.ublks, param->stats.length, param->stats.hlength);
  
-     /* Xvid can determine the proper profile to use */
-     /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */
+     return 0;
+ }
  
-     /* We don't use zones */
-     xvid_enc_create.zones = NULL;
-     xvid_enc_create.num_zones = 0;
+ /**
+  * Dispatch function for our custom plugin.
+  * This handles the dispatch for the Xvid plugin. It passes data
+  * on to other functions for actual processing.
+  *
+  * @param ref Context pointer for the plugin
+  * @param cmd The task given for us to complete
+  * @param p1 First parameter (varies)
+  * @param p2 Second parameter (varies)
+  * @return Returns XVID_ERR_xxxx on failure, or 0 on success
+  */
+ static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2)
+ {
+     switch( cmd ) {
+         case XVID_PLG_INFO:
+         case XVID_PLG_FRAME:
+             return 0;
  
-     xvid_enc_create.num_threads = avctx->thread_count;
+         case XVID_PLG_BEFORE:
+             return xvid_ff_2pass_before(ref, p1);
  
-     xvid_enc_create.plugins = plugins;
-     xvid_enc_create.num_plugins = 0;
+         case XVID_PLG_CREATE:
+             return xvid_ff_2pass_create(p1, p2);
  
-     /* Initialize Buffers */
-     x->twopassbuffer = NULL;
-     x->old_twopassbuffer = NULL;
-     x->twopassfile = NULL;
+         case XVID_PLG_AFTER:
+             return xvid_ff_2pass_after(ref, p1);
  
-     if( xvid_flags & CODEC_FLAG_PASS1 ) {
-         rc2pass1.version = XVID_VERSION;
-         rc2pass1.context = x;
-         x->twopassbuffer = av_malloc(BUFFER_SIZE);
-         x->old_twopassbuffer = av_malloc(BUFFER_SIZE);
-         if( x->twopassbuffer == NULL || x->old_twopassbuffer == NULL ) {
-             av_log(avctx, AV_LOG_ERROR,
-                 "Xvid: Cannot allocate 2-pass log buffers\n");
-             return -1;
-         }
-         x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0;
+         case XVID_PLG_DESTROY:
+             return xvid_ff_2pass_destroy(ref, p1);
+         default:
+             return XVID_ERR_FAIL;
+     }
+ }
+ /**
+  * Routine to create a global VO/VOL header for MP4 container.
+  * What we do here is extract the header from the Xvid bitstream
+  * as it is encoded. We also strip the repeated headers from the
+  * bitstream when a global header is requested for MPEG-4 ISO
+  * compliance.
+  *
+  * @param avctx AVCodecContext pointer to context
+  * @param frame Pointer to encoded frame data
+  * @param header_len Length of header to search
+  * @param frame_len Length of encoded frame data
+  * @return Returns new length of frame data
+  */
+ static int xvid_strip_vol_header(AVCodecContext *avctx,
+                   AVPacket *pkt,
+                   unsigned int header_len,
+                   unsigned int frame_len) {
+     int vo_len = 0, i;
+     for( i = 0; i < header_len - 3; i++ ) {
+         if( pkt->data[i] == 0x00 &&
+             pkt->data[i+1] == 0x00 &&
+             pkt->data[i+2] == 0x01 &&
+             pkt->data[i+3] == 0xB6 ) {
+             vo_len = i;
+             break;
+         }
+     }
+     if( vo_len > 0 ) {
+         /* We need to store the header, so extract it */
+         if( avctx->extradata == NULL ) {
+             avctx->extradata = av_malloc(vo_len);
+             memcpy(avctx->extradata, pkt->data, vo_len);
+             avctx->extradata_size = vo_len;
+         }
+         /* Less dangerous now, memmove properly copies the two
+            chunks of overlapping data */
+         memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len);
+         pkt->size = frame_len - vo_len;
+     }
+     return 0;
+ }
+ /**
+  * Routine to correct a possibly erroneous framerate being fed to us.
+  * Xvid currently chokes on framerates where the ticks per frame is
+  * extremely large. This function works to correct problems in this area
+  * by estimating a new framerate and taking the simpler fraction of
+  * the two presented.
+  *
+  * @param avctx Context that contains the framerate to correct.
+  */
+ static void xvid_correct_framerate(AVCodecContext *avctx)
+ {
+     int frate, fbase;
+     int est_frate, est_fbase;
+     int gcd;
+     float est_fps, fps;
+     frate = avctx->time_base.den;
+     fbase = avctx->time_base.num;
+     gcd = av_gcd(frate, fbase);
+     if( gcd > 1 ) {
+         frate /= gcd;
+         fbase /= gcd;
+     }
+     if( frate <= 65000 && fbase <= 65000 ) {
+         avctx->time_base.den = frate;
+         avctx->time_base.num = fbase;
+         return;
+     }
+     fps = (float)frate / (float)fbase;
+     est_fps = roundf(fps * 1000.0) / 1000.0;
+     est_frate = (int)est_fps;
+     if( est_fps > (int)est_fps ) {
+         est_frate = (est_frate + 1) * 1000;
+         est_fbase = (int)roundf((float)est_frate / est_fps);
+     } else
+         est_fbase = 1;
+     gcd = av_gcd(est_frate, est_fbase);
+     if( gcd > 1 ) {
+         est_frate /= gcd;
+         est_fbase /= gcd;
+     }
+     if( fbase > est_fbase ) {
+         avctx->time_base.den = est_frate;
+         avctx->time_base.num = est_fbase;
+         av_log(avctx, AV_LOG_DEBUG,
+             "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n",
+             est_fps, (((est_fps - fps)/fps) * 100.0));
+     } else {
+         avctx->time_base.den = frate;
+         avctx->time_base.num = fbase;
+     }
+ }
+ /**
+  * Create the private context for the encoder.
+  * All buffers are allocated, settings are loaded from the user,
+  * and the encoder context created.
+  *
+  * @param avctx AVCodecContext pointer to context
+  * @return Returns 0 on success, -1 on failure
+  */
+ static av_cold int xvid_encode_init(AVCodecContext *avctx)  {
+     int xerr, i;
+     int xvid_flags = avctx->flags;
+     struct xvid_context *x = avctx->priv_data;
+     uint16_t *intra, *inter;
+     int fd;
+     xvid_plugin_single_t single       = { 0 };
+     struct xvid_ff_pass1 rc2pass1     = { 0 };
+     xvid_plugin_2pass2_t rc2pass2     = { 0 };
+     xvid_gbl_init_t xvid_gbl_init     = { 0 };
+     xvid_enc_create_t xvid_enc_create = { 0 };
+     xvid_enc_plugin_t plugins[7];
 -    /* Bring in VOP flags from avconv command-line */
++    /* Bring in VOP flags from ffmpeg command-line */
+     x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */
+     if( xvid_flags & CODEC_FLAG_4MV )
+         x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */
+     if( avctx->trellis
+         )
+         x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */
+     if( xvid_flags & CODEC_FLAG_AC_PRED )
+         x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */
+     if( xvid_flags & CODEC_FLAG_GRAY )
+         x->vop_flags |= XVID_VOP_GREYSCALE;
+     /* Decide which ME quality setting to use */
+     x->me_flags = 0;
+     switch( avctx->me_method ) {
+        case ME_FULL:   /* Quality 6 */
+            x->me_flags |=  XVID_ME_EXTSEARCH16
+                        |   XVID_ME_EXTSEARCH8;
+        case ME_EPZS:   /* Quality 4 */
+            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND8
+                        |   XVID_ME_HALFPELREFINE8
+                        |   XVID_ME_CHROMA_PVOP
+                        |   XVID_ME_CHROMA_BVOP;
+        case ME_LOG:    /* Quality 2 */
+        case ME_PHODS:
+        case ME_X1:
+            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND16
+                        |   XVID_ME_HALFPELREFINE16;
+        case ME_ZERO:   /* Quality 0 */
+        default:
+            break;
+     }
+     /* Decide how we should decide blocks */
+     switch( avctx->mb_decision ) {
+        case 2:
+            x->vop_flags |= XVID_VOP_MODEDECISION_RD;
+            x->me_flags |=  XVID_ME_HALFPELREFINE8_RD
+                        |   XVID_ME_QUARTERPELREFINE8_RD
+                        |   XVID_ME_EXTSEARCH_RD
+                        |   XVID_ME_CHECKPREDICTION_RD;
+        case 1:
+            if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) )
+                x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD;
+            x->me_flags |=  XVID_ME_HALFPELREFINE16_RD
+                        |   XVID_ME_QUARTERPELREFINE16_RD;
+        default:
+            break;
+     }
 -    /* Bring in VOL flags from avconv command-line */
++    /* Bring in VOL flags from ffmpeg command-line */
+     x->vol_flags = 0;
+     if( xvid_flags & CODEC_FLAG_GMC ) {
+         x->vol_flags |= XVID_VOL_GMC;
+         x->me_flags |= XVID_ME_GME_REFINE;
+     }
+     if( xvid_flags & CODEC_FLAG_QPEL ) {
+         x->vol_flags |= XVID_VOL_QUARTERPEL;
+         x->me_flags |= XVID_ME_QUARTERPELREFINE16;
+         if( x->vop_flags & XVID_VOP_INTER4V )
+             x->me_flags |= XVID_ME_QUARTERPELREFINE8;
+     }
+     xvid_gbl_init.version = XVID_VERSION;
+     xvid_gbl_init.debug = 0;
+ #if ARCH_PPC
+     /* Xvid's PPC support is borked, use libavcodec to detect */
+ #if HAVE_ALTIVEC
+     if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) {
+         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC;
+     } else
+ #endif
+         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
+ #else
+     /* Xvid can detect on x86 */
+     xvid_gbl_init.cpu_flags = 0;
+ #endif
+     /* Initialize */
+     xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
+     /* Create the encoder reference */
+     xvid_enc_create.version = XVID_VERSION;
+     /* Store the desired frame size */
+     xvid_enc_create.width = x->xsize = avctx->width;
+     xvid_enc_create.height = x->ysize = avctx->height;
+     /* Xvid can determine the proper profile to use */
+     /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */
+     /* We don't use zones */
+     xvid_enc_create.zones = NULL;
+     xvid_enc_create.num_zones = 0;
+     xvid_enc_create.num_threads = avctx->thread_count;
+     xvid_enc_create.plugins = plugins;
+     xvid_enc_create.num_plugins = 0;
+     /* Initialize Buffers */
+     x->twopassbuffer = NULL;
+     x->old_twopassbuffer = NULL;
+     x->twopassfile = NULL;
+     if( xvid_flags & CODEC_FLAG_PASS1 ) {
+         rc2pass1.version = XVID_VERSION;
+         rc2pass1.context = x;
+         x->twopassbuffer = av_malloc(BUFFER_SIZE);
+         x->old_twopassbuffer = av_malloc(BUFFER_SIZE);
+         if( x->twopassbuffer == NULL || x->old_twopassbuffer == NULL ) {
+             av_log(avctx, AV_LOG_ERROR,
+                 "Xvid: Cannot allocate 2-pass log buffers\n");
+             return -1;
+         }
+         x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0;
  
          plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass;
          plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
  }
  
  /**
-  * Enable fast encode mode during the first pass.
+  * Encode a single frame.
   *
-  * @param ref Context pointer for the plugin
-  * @param param Frame data
-  * @return Returns 0, success guaranteed
+  * @param avctx AVCodecContext pointer to context
+  * @param frame Pointer to encoded frame buffer
+  * @param buf_size Size of encoded frame buffer
+  * @param data Pointer to AVFrame of unencoded frame
+  * @return Returns 0 on success, -1 on failure
   */
- static int xvid_ff_2pass_before(struct xvid_context *ref,
-                                 xvid_plg_data_t *param) {
-     int motion_remove;
-     int motion_replacements;
-     int vop_remove;
+ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                              const AVFrame *picture, int *got_packet)
+ {
+     int xerr, i, ret, user_packet = !!pkt->data;
+     char *tmp;
+     struct xvid_context *x = avctx->priv_data;
+     AVFrame *p = &x->encoded_picture;
+     int mb_width   = (avctx->width  + 15) / 16;
+     int mb_height  = (avctx->height + 15) / 16;
  
-     /* Nothing to do here, result is changed too much */
-     if( param->zone && param->zone->mode == XVID_ZONE_QUANT )
-         return 0;
+     xvid_enc_frame_t xvid_enc_frame = { 0 };
+     xvid_enc_stats_t xvid_enc_stats = { 0 };
  
-     /* We can implement a 'turbo' first pass mode here */
-     param->quant = 2;
 -    if (!user_packet &&
 -        (ret = av_new_packet(pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
++    if ((ret = ff_alloc_packet2(avctx, pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0)
+         return ret;
 -    }
  
-     /* Init values */
-     motion_remove = ~XVID_ME_CHROMA_PVOP &
-                     ~XVID_ME_CHROMA_BVOP &
-                     ~XVID_ME_EXTSEARCH16 &
-                     ~XVID_ME_ADVANCEDDIAMOND16;
-     motion_replacements = XVID_ME_FAST_MODEINTERPOLATE |
-                           XVID_ME_SKIP_DELTASEARCH |
-                           XVID_ME_FASTREFINE16 |
-                           XVID_ME_BFRAME_EARLYSTOP;
-     vop_remove = ~XVID_VOP_MODEDECISION_RD &
-                  ~XVID_VOP_FAST_MODEDECISION_RD &
-                  ~XVID_VOP_TRELLISQUANT &
-                  ~XVID_VOP_INTER4V &
-                  ~XVID_VOP_HQACPRED;
+     /* Start setting up the frame */
+     xvid_enc_frame.version = XVID_VERSION;
+     xvid_enc_stats.version = XVID_VERSION;
+     *p = *picture;
  
-     param->vol_flags &= ~XVID_VOL_GMC;
-     param->vop_flags &= vop_remove;
-     param->motion_flags &= motion_remove;
-     param->motion_flags |= motion_replacements;
+     /* Let Xvid know where to put the frame. */
+     xvid_enc_frame.bitstream = pkt->data;
+     xvid_enc_frame.length    = pkt->size;
  
-     return 0;
- }
+     /* Initialize input image fields */
+     if( avctx->pix_fmt != PIX_FMT_YUV420P ) {
+         av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420p not supported\n");
+         return -1;
+     }
  
- /**
-  * Capture statistic data and write it during first pass.
-  *
-  * @param ref Context pointer for the plugin
-  * @param param Statistic data
-  * @return Returns XVID_ERR_xxxx on failure, or 0 on success
-  */
- static int xvid_ff_2pass_after(struct xvid_context *ref,
-                                 xvid_plg_data_t *param) {
-     char *log = ref->twopassbuffer;
-     const char *frame_types = " ipbs";
-     char frame_type;
+     xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */
  
-     /* Quick bounds check */
-     if( log == NULL )
-         return XVID_ERR_FAIL;
+     for( i = 0; i < 4; i++ ) {
+         xvid_enc_frame.input.plane[i] = picture->data[i];
+         xvid_enc_frame.input.stride[i] = picture->linesize[i];
+     }
  
-     /* Convert the type given to us into a character */
-     if( param->type < 5 && param->type > 0 ) {
-         frame_type = frame_types[param->type];
-     } else {
-         return XVID_ERR_FAIL;
+     /* Encoder Flags */
+     xvid_enc_frame.vop_flags = x->vop_flags;
+     xvid_enc_frame.vol_flags = x->vol_flags;
+     xvid_enc_frame.motion = x->me_flags;
+     xvid_enc_frame.type =
+         picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP :
+         picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP :
+         picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP :
+                                           XVID_TYPE_AUTO;
+     /* Pixel aspect ratio setting */
 -    if (avctx->sample_aspect_ratio.num < 1 || avctx->sample_aspect_ratio.num > 255 ||
 -        avctx->sample_aspect_ratio.den < 1 || avctx->sample_aspect_ratio.den > 255) {
++    if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.num > 255 ||
++        avctx->sample_aspect_ratio.den < 0 || avctx->sample_aspect_ratio.den > 255) {
+         av_log(avctx, AV_LOG_ERROR, "Invalid pixel aspect ratio %i/%i\n",
+                avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
+         return -1;
      }
+     xvid_enc_frame.par = XVID_PAR_EXT;
+     xvid_enc_frame.par_width  = avctx->sample_aspect_ratio.num;
+     xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den;
  
-     snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),
-         "%c %d %d %d %d %d %d\n",
-         frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks,
-         param->stats.ublks, param->stats.length, param->stats.hlength);
+     /* Quant Setting */
+     if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA;
+     else xvid_enc_frame.quant = 0;
  
-     return 0;
+     /* Matrices */
+     xvid_enc_frame.quant_intra_matrix = x->intra_matrix;
+     xvid_enc_frame.quant_inter_matrix = x->inter_matrix;
+     /* Encode */
+     xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE,
+         &xvid_enc_frame, &xvid_enc_stats);
+     /* Two-pass log buffer swapping */
+     avctx->stats_out = NULL;
+     if( x->twopassbuffer ) {
+         tmp = x->old_twopassbuffer;
+         x->old_twopassbuffer = x->twopassbuffer;
+         x->twopassbuffer = tmp;
+         x->twopassbuffer[0] = 0;
+         if( x->old_twopassbuffer[0] != 0 ) {
+             avctx->stats_out = x->old_twopassbuffer;
+         }
+     }
+     if (xerr > 0) {
+         *got_packet = 1;
+         p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
+         if( xvid_enc_stats.type == XVID_TYPE_PVOP )
+             p->pict_type = AV_PICTURE_TYPE_P;
+         else if( xvid_enc_stats.type == XVID_TYPE_BVOP )
+             p->pict_type = AV_PICTURE_TYPE_B;
+         else if( xvid_enc_stats.type == XVID_TYPE_SVOP )
+             p->pict_type = AV_PICTURE_TYPE_S;
+         else
+             p->pict_type = AV_PICTURE_TYPE_I;
+         if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) {
+             p->key_frame = 1;
+             pkt->flags |= AV_PKT_FLAG_KEY;
+             if( x->quicktime_format )
+                 return xvid_strip_vol_header(avctx, pkt,
+                     xvid_enc_stats.hlength, xerr);
+          } else
+             p->key_frame = 0;
+         pkt->size = xerr;
+         return 0;
+     } else {
+         if (!user_packet)
+             av_free_packet(pkt);
+         if (!xerr)
+             return 0;
+         av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr);
+         return -1;
+     }
  }
  
  /**
-  * Dispatch function for our custom plugin.
-  * This handles the dispatch for the Xvid plugin. It passes data
-  * on to other functions for actual processing.
+  * Destroy the private context for the encoder.
+  * All buffers are freed, and the Xvid encoder context is destroyed.
   *
-  * @param ref Context pointer for the plugin
-  * @param cmd The task given for us to complete
-  * @param p1 First parameter (varies)
-  * @param p2 Second parameter (varies)
-  * @return Returns XVID_ERR_xxxx on failure, or 0 on success
+  * @param avctx AVCodecContext pointer to context
+  * @return Returns 0, success guaranteed
   */
- int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) {
-     switch( cmd ) {
-         case XVID_PLG_INFO:
-         case XVID_PLG_FRAME:
-             return 0;
-         case XVID_PLG_BEFORE:
-             return xvid_ff_2pass_before(ref, p1);
-         case XVID_PLG_CREATE:
-             return xvid_ff_2pass_create(p1, p2);
-         case XVID_PLG_AFTER:
-             return xvid_ff_2pass_after(ref, p1);
+ static av_cold int xvid_encode_close(AVCodecContext *avctx) {
+     struct xvid_context *x = avctx->priv_data;
  
-         case XVID_PLG_DESTROY:
-             return xvid_ff_2pass_destroy(ref, p1);
+     xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
  
-         default:
-             return XVID_ERR_FAIL;
+     av_freep(&avctx->extradata);
+     if( x->twopassbuffer != NULL ) {
+         av_free(x->twopassbuffer);
+         av_free(x->old_twopassbuffer);
++        avctx->stats_out = NULL;
      }
+     av_free(x->twopassfile);
+     av_free(x->intra_matrix);
+     av_free(x->inter_matrix);
+     return 0;
  }
  
  /**
Simple merge
@@@ -101,47 -106,9 +105,49 @@@ static int tiff_uncompress(uint8_t *dst
  }
  #endif
  
- static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uint8_t *src, int size, int lines){
 +static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst,
 +                                             int usePtr, const uint8_t *src,
 +                                             uint8_t c, int width, int offset)
 +{
 +    switch (bpp) {
 +    case 1:
 +        while (--width >= 0) {
 +            dst[(width+offset)*8+7] = (usePtr ? src[width] : c)      & 0x1;
 +            dst[(width+offset)*8+6] = (usePtr ? src[width] : c) >> 1 & 0x1;
 +            dst[(width+offset)*8+5] = (usePtr ? src[width] : c) >> 2 & 0x1;
 +            dst[(width+offset)*8+4] = (usePtr ? src[width] : c) >> 3 & 0x1;
 +            dst[(width+offset)*8+3] = (usePtr ? src[width] : c) >> 4 & 0x1;
 +            dst[(width+offset)*8+2] = (usePtr ? src[width] : c) >> 5 & 0x1;
 +            dst[(width+offset)*8+1] = (usePtr ? src[width] : c) >> 6 & 0x1;
 +            dst[(width+offset)*8+0] = (usePtr ? src[width] : c) >> 7;
 +        }
 +        break;
 +    case 2:
 +        while (--width >= 0) {
 +            dst[(width+offset)*4+3] = (usePtr ? src[width] : c) & 0x3;
 +            dst[(width+offset)*4+2] = (usePtr ? src[width] : c) >> 2 & 0x3;
 +            dst[(width+offset)*4+1] = (usePtr ? src[width] : c) >> 4 & 0x3;
 +            dst[(width+offset)*4+0] = (usePtr ? src[width] : c) >> 6;
 +        }
 +        break;
 +    case 4:
 +        while (--width >= 0) {
 +            dst[(width+offset)*2+1] = (usePtr ? src[width] : c) & 0xF;
 +            dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4;
 +        }
 +        break;
 +    default:
 +        if (usePtr) {
 +            memcpy(dst + offset, src, width);
 +        } else {
 +            memset(dst + offset, c, width);
 +        }
 +    }
 +}
 +
+ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
+                              const uint8_t *src, int size, int lines)
+ {
      int c, line, pixels, code;
      const uint8_t *ssrc = src;
      int width = ((s->width * s->bpp) + 7) >> 3;
              return -1;
          }
          src = zbuf;
-         for(line = 0; line < lines; line++){
+         for (line = 0; line < lines; line++) {
 -            memcpy(dst, src, width);
 +            if(s->bpp < 8 && s->avctx->pix_fmt == PIX_FMT_PAL8){
 +                horizontal_fill(s->bpp, dst, 1, src, 0, width, 0);
 +            }else{
 +                memcpy(dst, src, width);
 +            }
              dst += stride;
              src += width;
          }
          case TIFF_CCITT_RLE:
          case TIFF_G3:
          case TIFF_G4:
-             ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, s->compr, s->fax_opts);
+             ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride,
+                                   s->compr, s->fax_opts);
              break;
          }
 +        if (s->bpp < 8 && s->avctx->pix_fmt == PIX_FMT_PAL8)
 +            for (line = 0; line < lines; line++) {
 +                horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
 +                dst += stride;
 +            }
          av_free(src2);
          return ret;
      }
              src += width;
              break;
          case TIFF_PACKBITS:
-             for(pixels = 0; pixels < width;){
-                 code = (int8_t)*src++;
-                 if(code >= 0){
+             for (pixels = 0; pixels < width;) {
+                 code = (int8_t) * src++;
+                 if (code >= 0) {
                      code++;
-                     if(pixels + code > width){
-                         av_log(s->avctx, AV_LOG_ERROR, "Copy went out of bounds\n");
+                     if (pixels + code > width) {
+                         av_log(s->avctx, AV_LOG_ERROR,
+                                "Copy went out of bounds\n");
                          return -1;
                      }
 -                    memcpy(dst + pixels, src, code);
 +                    horizontal_fill(s->bpp * (s->avctx->pix_fmt == PIX_FMT_PAL8),
 +                                    dst, 1, src, 0, code, pixels);
                      src += code;
                      pixels += code;
-                 }else if(code != -128){ // -127..-1
+                 } else if (code != -128) { // -127..-1
                      code = (-code) + 1;
-                     if(pixels + code > width){
-                         av_log(s->avctx, AV_LOG_ERROR, "Run went out of bounds\n");
+                     if (pixels + code > width) {
+                         av_log(s->avctx, AV_LOG_ERROR,
+                                "Run went out of bounds\n");
                          return -1;
                      }
                      c = *src++;
              break;
          case TIFF_LZW:
              pixels = ff_lzw_decode(s->lzw, dst, width);
-             if(pixels < width){
-                 av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", pixels, width);
+             if (pixels < width) {
+                 av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n",
+                        pixels, width);
                  return -1;
              }
 +            if (s->bpp < 8 && s->avctx->pix_fmt == PIX_FMT_PAL8)
 +                horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
              break;
          }
          dst += stride;
@@@ -544,11 -507,10 +577,11 @@@ static int tiff_decode_tag(TiffContext 
          gp = buf + count / 3 * off;
          bp = buf + count / 3 * off * 2;
          off = (type_sizes[type] - 1) << 3;
-         for(i = 0; i < count / 3; i++){
+         for (i = 0; i < count / 3; i++) {
 -            j  = (tget(&rp, type, s->le) >> off) << 16;
 +            j = 0xff << 24;
 +            j |= (tget(&rp, type, s->le) >> off) << 16;
              j |= (tget(&gp, type, s->le) >> off) << 8;
-             j |= tget(&bp, type, s->le) >> off;
+             j |=  tget(&bp, type, s->le) >> off;
              pal[i] = j;
          }
          s->palette_is_set = 1;
@@@ -666,35 -633,22 +704,35 @@@ static int decode_frame(AVCodecContext 
          dst = p->data[0];
          soff = s->bpp >> 3;
          ssize = s->width * soff;
 -        for (i = 0; i < s->height; i++) {
 -            for (j = soff; j < ssize; j++)
 -                dst[j] += dst[j - soff];
 -            dst += stride;
 +        if (s->avctx->pix_fmt == PIX_FMT_RGB48LE ||
 +            s->avctx->pix_fmt == PIX_FMT_RGBA64LE) {
 +            for (i = 0; i < s->height; i++) {
 +                for (j = soff; j < ssize; j += 2)
 +                    AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff));
 +                dst += stride;
 +            }
 +        } else if (s->avctx->pix_fmt == PIX_FMT_RGB48BE ||
 +                   s->avctx->pix_fmt == PIX_FMT_RGBA64BE) {
 +            for (i = 0; i < s->height; i++) {
 +                for (j = soff; j < ssize; j += 2)
 +                    AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff));
 +                dst += stride;
 +            }
 +        } else {
-             for(i = 0; i < s->height; i++) {
-                 for(j = soff; j < ssize; j++)
++            for (i = 0; i < s->height; i++) {
++                for (j = soff; j < ssize; j++)
 +                    dst[j] += dst[j - soff];
 +                dst += stride;
 +            }
          }
      }
  
-     if(s->invert){
+     if (s->invert) {
 -        uint8_t *src;
 -        int j;
 -
 -        src = s->picture.data[0];
 -        for (j = 0; j < s->height; j++) {
 -            for (i = 0; i < s->picture.linesize[0]; i++)
 -                src[i] = 255 - src[i];
 -            src += s->picture.linesize[0];
 +        dst = s->picture.data[0];
-         for(i = 0; i < s->height; i++){
-             for(j = 0; j < s->picture.linesize[0]; j++)
++        for (i = 0; i < s->height; i++) {
++            for (j = 0; j < s->picture.linesize[0]; j++)
 +                dst[j] = (s->avctx->pix_fmt == PIX_FMT_PAL8 ? (1<<s->bpp) - 1 : 255) - dst[j];
 +            dst += s->picture.linesize[0];
          }
      }
      *picture   = s->picture;
Simple merge
Simple merge
@@@ -141,48 -138,37 +142,83 @@@ int avfilter_graph_parse(AVFilterGraph 
                           void *log_ctx);
  
  /**
+  * Add a graph described by a string to a graph.
+  *
+  * @param[in]  graph   the filter graph where to link the parsed graph context
+  * @param[in]  filters string to be parsed
+  * @param[out] inputs  a linked list of all free (unlinked) inputs of the
+  *                     parsed graph will be returned here. It is to be freed
+  *                     by the caller using avfilter_inout_free().
+  * @param[out] outputs a linked list of all free (unlinked) outputs of the
+  *                     parsed graph will be returned here. It is to be freed by the
+  *                     caller using avfilter_inout_free().
+  * @return zero on success, a negative AVERROR code on error
+  *
+  * @note the difference between avfilter_graph_parse2() and
+  * avfilter_graph_parse() is that in avfilter_graph_parse(), the caller provides
+  * the lists of inputs and outputs, which therefore must be known before calling
+  * the function. On the other hand, avfilter_graph_parse2() \em returns the
+  * inputs and outputs that are left unlinked after parsing the graph and the
+  * caller then deals with them. Another difference is that in
+  * avfilter_graph_parse(), the inputs parameter describes inputs of the
+  * <em>already existing</em> part of the graph; i.e. from the point of view of
+  * the newly created part, they are outputs. Similarly the outputs parameter
+  * describes outputs of the already existing filters, which are provided as
+  * inputs to the parsed filters.
+  * avfilter_graph_parse2() takes the opposite approach -- it makes no reference
+  * whatsoever to already existing parts of the graph and the inputs parameter
+  * will on return contain inputs of the newly parsed part of the graph.
+  * Analogously the outputs parameter will contain outputs of the newly created
+  * filters.
+  */
+ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
+                           AVFilterInOut **inputs,
+                           AVFilterInOut **outputs);
++
++/**
 + * Send a command to one or more filter instances.
 + *
 + * @param graph  the filter graph
 + * @param target the filter(s) to which the command should be sent
 + *               "all" sends to all filters
 + *               otherwise it can be a filter or filter instance name
 + *               which will send the command to all matching filters.
 + * @param cmd    the command to sent, for handling simplicity all commands must be alphanumeric only
 + * @param arg    the argument for the command
 + * @param res    a buffer with size res_size where the filter(s) can return a response.
 + *
 + * @returns >=0 on success otherwise an error code.
 + *              AVERROR(ENOSYS) on unsupported commands
 + */
 +int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags);
 +
 +/**
 + * Queue a command for one or more filter instances.
 + *
 + * @param graph  the filter graph
 + * @param target the filter(s) to which the command should be sent
 + *               "all" sends to all filters
 + *               otherwise it can be a filter or filter instance name
 + *               which will send the command to all matching filters.
 + * @param cmd    the command to sent, for handling simplicity all commands must be alphanummeric only
 + * @param arg    the argument for the command
 + * @param ts     time at which the command should be sent to the filter
 + *
 + * @note As this executes commands after this function returns, no return code
 + *       from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.
 + */
 +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts);
 +
 +
 +/**
 + * Dump a graph into a human-readable string representation.
 + *
 + * @param graph    the graph to dump
 + * @param options  formatting options; currently ignored
 + * @return  a string, or NULL in case of memory allocation failure;
 + *          the string must be freed using av_free
 + */
 +char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
 +
  #endif /* AVFILTER_AVFILTERGRAPH_H */
@@@ -334,83 -349,163 +349,248 @@@ static int parse_outputs(const char **b
      return pad;
  }
  
 -    int index = 0, ret;
+ #if FF_API_GRAPH_AVCLASS
+ #define log_ctx graph
+ #else
+ #define log_ctx NULL
+ #endif
+ static int parse_sws_flags(const char **buf, AVFilterGraph *graph)
+ {
+     char *p = strchr(*buf, ';');
+     if (strncmp(*buf, "sws_flags=", 10))
+         return 0;
+     if (!p) {
+         av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n");
+         return AVERROR(EINVAL);
+     }
+     *buf += 4;  // keep the 'flags=' part
+     av_freep(&graph->scale_sws_opts);
+     if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1)))
+         return AVERROR(ENOMEM);
+     av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1);
+     *buf = p + 1;
+     return 0;
+ }
+ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,
+                           AVFilterInOut **inputs,
+                           AVFilterInOut **outputs)
+ {
 -            goto fail;
++    int index = 0, ret = 0;
+     char chr = 0;
+     AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL;
+     filters += strspn(filters, WHITESPACES);
+     if ((ret = parse_sws_flags(&filters, graph)) < 0)
+         goto fail;
+     do {
+         AVFilterContext *filter;
+         filters += strspn(filters, WHITESPACES);
+         if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
 -            goto fail;
 -
++            goto end;
+         if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
 -            goto fail;
++            goto end;
+         if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
 -            goto fail;
++            goto end;
+         if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
+                                  log_ctx)) < 0)
 -        goto fail;
++            goto end;
+         filters += strspn(filters, WHITESPACES);
+         chr = *filters++;
+         if (chr == ';' && curr_inputs)
+             append_inout(&open_outputs, &curr_inputs);
+         index++;
+     } while (chr == ',' || chr == ';');
+     if (chr) {
+         av_log(log_ctx, AV_LOG_ERROR,
+                "Unable to parse graph description substring: \"%s\"\n",
+                filters - 1);
+         ret = AVERROR(EINVAL);
 - fail:
++        goto end;
+     }
+     append_inout(&open_outputs, &curr_inputs);
++
+     *inputs  = open_inputs;
+     *outputs = open_outputs;
+     return 0;
++ fail:end:
+     for (; graph->filter_count > 0; graph->filter_count--)
+         avfilter_free(graph->filters[graph->filter_count - 1]);
+     av_freep(&graph->filters);
+     avfilter_inout_free(&open_inputs);
+     avfilter_inout_free(&open_outputs);
+     avfilter_inout_free(&curr_inputs);
+     *inputs  = NULL;
+     *outputs = NULL;
+     return ret;
+ }
+ #undef log_ctx
  int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
 -                         AVFilterInOut *open_inputs,
 -                         AVFilterInOut *open_outputs, void *log_ctx)
 +                         AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr,
 +                         void *log_ctx)
  {
 -    avfilter_inout_free(&open_inputs);
 -    avfilter_inout_free(&open_outputs);
++#if 0
+     int ret;
++    AVFilterInOut *open_inputs  = open_inputs_ptr  ? *open_inputs_ptr  : NULL;
++    AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
+     AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL;
+     if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0)
+         goto fail;
+     /* First input can be omitted if it is "[in]" */
+     if (inputs && !inputs->name)
+         inputs->name = av_strdup("in");
+     for (cur = inputs; cur; cur = cur->next) {
+         if (!cur->name) {
+               av_log(log_ctx, AV_LOG_ERROR,
+                      "Not enough inputs specified for the \"%s\" filter.\n",
+                      cur->filter_ctx->filter->name);
+               ret = AVERROR(EINVAL);
+               goto fail;
+         }
+         if (!(match = extract_inout(cur->name, &open_outputs)))
+             continue;
+         ret = avfilter_link(match->filter_ctx, match->pad_idx,
+                             cur->filter_ctx,   cur->pad_idx);
+         avfilter_inout_free(&match);
+         if (ret < 0)
+             goto fail;
+     }
+     /* Last output can be omitted if it is "[out]" */
+     if (outputs && !outputs->name)
+         outputs->name = av_strdup("out");
+     for (cur = outputs; cur; cur = cur->next) {
+         if (!cur->name) {
+             av_log(log_ctx, AV_LOG_ERROR,
+                    "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
+                    filters);
+             ret = AVERROR(EINVAL);
+             goto fail;
+         }
+         if (!(match = extract_inout(cur->name, &open_inputs)))
+             continue;
+         ret = avfilter_link(cur->filter_ctx,   cur->pad_idx,
+                             match->filter_ctx, match->pad_idx);
+         avfilter_inout_free(&match);
+         if (ret < 0)
+             goto fail;
+     }
+  fail:
+     if (ret < 0) {
+         for (; graph->filter_count > 0; graph->filter_count--)
+             avfilter_free(graph->filters[graph->filter_count - 1]);
+         av_freep(&graph->filters);
+     }
+     avfilter_inout_free(&inputs);
+     avfilter_inout_free(&outputs);
++    /* clear open_in/outputs only if not passed as parameters */
++    if (open_inputs_ptr) *open_inputs_ptr = open_inputs;
++    else avfilter_inout_free(&open_inputs);
++    if (open_outputs_ptr) *open_outputs_ptr = open_outputs;
++    else avfilter_inout_free(&open_outputs);
++    return ret;
++}
++#else
 +    int index = 0, ret = 0;
 +    char chr = 0;
 +
 +    AVFilterInOut *curr_inputs = NULL;
 +    AVFilterInOut *open_inputs  = open_inputs_ptr  ? *open_inputs_ptr  : NULL;
 +    AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL;
 +
 +    do {
 +        AVFilterContext *filter;
 +        const char *filterchain = filters;
 +        filters += strspn(filters, WHITESPACES);
 +
 +        if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0)
 +            goto end;
 +
 +        if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0)
 +            goto end;
 +
 +        if (filter->input_count == 1 && !curr_inputs && !index) {
 +            /* First input pad, assume it is "[in]" if not specified */
 +            const char *tmp = "[in]";
 +            if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0)
 +                goto end;
 +        }
 +
 +        if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0)
 +            goto end;
 +
 +        if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs,
 +                                 log_ctx)) < 0)
 +            goto end;
 +
 +        filters += strspn(filters, WHITESPACES);
 +        chr = *filters++;
 +
 +        if (chr == ';' && curr_inputs) {
 +            av_log(log_ctx, AV_LOG_ERROR,
 +                   "Invalid filterchain containing an unlabelled output pad: \"%s\"\n",
 +                   filterchain);
 +            ret = AVERROR(EINVAL);
 +            goto end;
 +        }
 +        index++;
 +    } while (chr == ',' || chr == ';');
 +
 +    if (chr) {
 +        av_log(log_ctx, AV_LOG_ERROR,
 +               "Unable to parse graph description substring: \"%s\"\n",
 +               filters - 1);
 +        ret = AVERROR(EINVAL);
 +        goto end;
 +    }
 +
 +    if (curr_inputs) {
 +        /* Last output pad, assume it is "[out]" if not specified */
 +        const char *tmp = "[out]";
 +        if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs,
 +                                 log_ctx)) < 0)
 +            goto end;
 +    }
 +
 +end:
 +    /* clear open_in/outputs only if not passed as parameters */
 +    if (open_inputs_ptr) *open_inputs_ptr = open_inputs;
 +    else avfilter_inout_free(&open_inputs);
 +    if (open_outputs_ptr) *open_outputs_ptr = open_outputs;
 +    else avfilter_inout_free(&open_outputs);
 +    avfilter_inout_free(&curr_inputs);
 +
 +    if (ret < 0) {
 +        for (; graph->filter_count > 0; graph->filter_count--)
 +            avfilter_free(graph->filters[graph->filter_count - 1]);
 +        av_freep(&graph->filters);
 +    }
      return ret;
  }
++
++#endif
@@@ -29,8 -29,8 +29,8 @@@
  #include "libavutil/avutil.h"
  
  #define LIBAVFILTER_VERSION_MAJOR  2
- #define LIBAVFILTER_VERSION_MINOR 69
- #define LIBAVFILTER_VERSION_MICRO 101
 -#define LIBAVFILTER_VERSION_MINOR  16
 -#define LIBAVFILTER_VERSION_MICRO  0
++#define LIBAVFILTER_VERSION_MINOR 70
++#define LIBAVFILTER_VERSION_MICRO 100
  
  #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                 LIBAVFILTER_VERSION_MINOR, \
@@@ -37,8 -34,8 +37,9 @@@ typedef struct 
      int               h, w;
      enum PixelFormat  pix_fmt;
      AVRational        time_base;     ///< time_base to set in the output link
 -    AVRational        pixel_aspect;
 +    AVRational        sample_aspect_ratio;
 +    char              sws_param[256];
+     int eof;
  } BufferSourceContext;
  
  #define CHECK_PARAM_CHANGE(s, c, width, height, format)\
@@@ -55,6 -51,12 +56,12 @@@ int av_vsrc_buffer_add_video_buffer_ref
      AVFilterBufferRef *buf;
      int ret;
  
 -    if (!frame) {
++    if (!picref) {
+         c->eof = 1;
+         return 0;
+     } else if (c->eof)
+         return AVERROR(EINVAL);
      if (!av_fifo_space(c->fifo) &&
          (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
                                           sizeof(buf))) < 0)
@@@ -138,25 -105,6 +151,33 @@@ int av_buffersrc_buffer(AVFilterContex
      return 0;
  }
  
-     AVFilterBufferRef *picref =
-         avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE);
 +#if CONFIG_AVCODEC
 +#include "avcodec.h"
 +
 +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src,
 +                             const AVFrame *frame, int flags)
 +{
++    BufferSourceContext *c = buffer_src->priv;
++    AVFilterBufferRef *picref;
 +    int ret;
++
++    if (!frame) {
++        c->eof = 1;
++        return 0;
++    } else if (c->eof)
++        return AVERROR(EINVAL);
++
++    picref = avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE);
 +    if (!picref)
 +        return AVERROR(ENOMEM);
 +    ret = av_vsrc_buffer_add_video_buffer_ref(buffer_src, picref, flags);
 +    picref->buf->data[0] = NULL;
 +    avfilter_unref_buffer(picref);
 +
 +    return ret;
 +}
 +#endif
 +
  static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
  {
      BufferSourceContext *c = ctx->priv;
@@@ -226,7 -173,9 +247,9 @@@ static int request_frame(AVFilterLink *
      AVFilterBufferRef *buf;
  
      if (!av_fifo_size(c->fifo)) {
 -        av_log(link->src, AV_LOG_ERROR,
+         if (c->eof)
+             return AVERROR_EOF;
 +        av_log(link->src, AV_LOG_WARNING,
                 "request_frame() called with no available frame!\n");
          return AVERROR(EINVAL);
      }
@@@ -103,10 -103,10 +103,11 @@@ typedef struct MOVStreamContext 
      unsigned *stps_data;  ///< partial sync sample for mpeg-2 open gop
      int ctts_index;
      int ctts_sample;
 -    unsigned int sample_size;
 +    unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom
 +    unsigned int alt_sample_size; ///< always contains sample size from stsz atom
      unsigned int sample_count;
      int *sample_sizes;
+     int keyframe_absent;
      unsigned int keyframe_count;
      int *keyframes;
      int time_scale;
Simple merge
Simple merge
@@@ -539,18 -534,11 +539,18 @@@ yuv2422_1_c_template(SwsContext *c, con
      int i;
  
      if (uvalpha < 2048) {
-         for (i = 0; i < (dstW >> 1); i++) {
+         for (i = 0; i < ((dstW + 1) >> 1); i++) {
 -            int Y1 = buf0[i * 2]     >> 7;
 -            int Y2 = buf0[i * 2 + 1] >> 7;
 -            int U  = ubuf0[i]        >> 7;
 -            int V  = vbuf0[i]        >> 7;
 +            int Y1 = (buf0[i * 2    ]+64) >> 7;
 +            int Y2 = (buf0[i * 2 + 1]+64) >> 7;
 +            int U  = (ubuf0[i]       +64) >> 7;
 +            int V  = (vbuf0[i]       +64) >> 7;
 +
 +            if ((Y1 | Y2 | U | V) & 0x100) {
 +                Y1 = av_clip_uint8(Y1);
 +                Y2 = av_clip_uint8(Y2);
 +                U  = av_clip_uint8(U);
 +                V  = av_clip_uint8(V);
 +            }
  
              Y1 = av_clip_uint8(Y1);
              Y2 = av_clip_uint8(Y2);
          }
      } else {
          const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1];
-         for (i = 0; i < (dstW >> 1); i++) {
+         for (i = 0; i < ((dstW + 1) >> 1); i++) {
 -            int Y1 =  buf0[i * 2]          >> 7;
 -            int Y2 =  buf0[i * 2 + 1]      >> 7;
 -            int U  = (ubuf0[i] + ubuf1[i]) >> 8;
 -            int V  = (vbuf0[i] + vbuf1[i]) >> 8;
 +            int Y1 = (buf0[i * 2    ]    + 64) >> 7;
 +            int Y2 = (buf0[i * 2 + 1]    + 64) >> 7;
 +            int U  = (ubuf0[i] + ubuf1[i]+128) >> 8;
 +            int V  = (vbuf0[i] + vbuf1[i]+128) >> 8;
 +
 +            if ((Y1 | Y2 | U | V) & 0x100) {
 +                Y1 = av_clip_uint8(Y1);
 +                Y2 = av_clip_uint8(Y2);
 +                U  = av_clip_uint8(U);
 +                V  = av_clip_uint8(V);
 +            }
  
              Y1 = av_clip_uint8(Y1);
              Y2 = av_clip_uint8(Y2);
@@@ -1050,15 -1037,15 +1050,15 @@@ yuv2rgb_1_c_template(SwsContext *c, con
      int i;
  
      if (uvalpha < 2048) {
-         for (i = 0; i < (dstW >> 1); i++) {
+         for (i = 0; i < ((dstW + 1) >> 1); i++) {
 -            int Y1 = buf0[i * 2]     >> 7;
 -            int Y2 = buf0[i * 2 + 1] >> 7;
 -            int U  = ubuf0[i]        >> 7;
 -            int V  = vbuf0[i]        >> 7;
 +            int Y1 = (buf0[i * 2    ] + 64) >> 7;
 +            int Y2 = (buf0[i * 2 + 1] + 64) >> 7;
 +            int U  = (ubuf0[i]        + 64) >> 7;
 +            int V  = (vbuf0[i]        + 64) >> 7;
              int A1, A2;
 -            const void *r =  c->table_rV[V],
 -                       *g = (c->table_gU[U] + c->table_gV[V]),
 -                       *b =  c->table_bU[U];
 +            const void *r =  c->table_rV[V + YUVRGB_TABLE_HEADROOM],
 +                       *g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]),
 +                       *b =  c->table_bU[U + YUVRGB_TABLE_HEADROOM];
  
              Y1 = av_clip_uint8(Y1);
              Y2 = av_clip_uint8(Y2);
          }
      } else {
          const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1];
-         for (i = 0; i < (dstW >> 1); i++) {
+         for (i = 0; i < ((dstW + 1) >> 1); i++) {
 -            int Y1 =  buf0[i * 2]          >> 7;
 -            int Y2 =  buf0[i * 2 + 1]      >> 7;
 -            int U  = (ubuf0[i] + ubuf1[i]) >> 8;
 -            int V  = (vbuf0[i] + vbuf1[i]) >> 8;
 +            int Y1 = (buf0[i * 2    ]     +  64) >> 7;
 +            int Y2 = (buf0[i * 2 + 1]     +  64) >> 7;
 +            int U  = (ubuf0[i] + ubuf1[i] + 128) >> 8;
 +            int V  = (vbuf0[i] + vbuf1[i] + 128) >> 8;
              int A1, A2;
 -            const void *r =  c->table_rV[V],
 -                       *g = (c->table_gU[U] + c->table_gV[V]),
 -                       *b =  c->table_bU[U];
 +            const void *r =  c->table_rV[V + YUVRGB_TABLE_HEADROOM],
 +                       *g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]),
 +                       *b =  c->table_bU[U + YUVRGB_TABLE_HEADROOM];
  
              Y1 = av_clip_uint8(Y1);
              Y2 = av_clip_uint8(Y2);
@@@ -37,25 -32,9 +37,25 @@@ do_lavfi "crop"               "crop=iw-
  do_lavfi "crop_scale"         "crop=iw-100:ih-100:100:100,scale=400:-1"
  do_lavfi "crop_scale_vflip"   "null,null,crop=iw-200:ih-200:200:200,crop=iw-20:ih-20:20:20,scale=200:200,scale=250:250,vflip,vflip,null,scale=200:200,crop=iw-100:ih-100:100:100,vflip,scale=200:200,null,vflip,crop=iw-100:ih-100:100:100,null"
  do_lavfi "crop_vflip"         "crop=iw-100:ih-100:100:100,vflip"
 +do_lavfi "drawbox"            "drawbox=224:24:88:72:#FF8010@0.5"
 +do_lavfi "fade"               "fade=in:5:15,fade=out:30:15"
  do_lavfi "null"               "null"
- do_lavfi "overlay"            "split[m],scale=88:72,pad=96:80:4:4[o2];[m]fifo,[o2]overlay=240:16"
++do_lavfi "overlay"            "split[m],scale=88:72,pad=96:80:4:4[o2];[m]fifo[o1],[o1][o2]overlay=240:16"
 +do_lavfi "pad"                "pad=iw*1.5:ih*1.5:iw*0.3:ih*0.2"
 +do_lavfi "pp"                 "mp=pp=be/de/tn/l5/al"
 +do_lavfi "pp2"                "mp=pp=be/fq:16/fa/lb"
 +do_lavfi "pp3"                "mp=pp=be/fq:8/ac/li"
 +do_lavfi "pp4"                "mp=pp=be/ci"
 +do_lavfi "pp5"                "mp=pp=md"
 +do_lavfi "pp6"                "mp=pp=be/fd"
  do_lavfi "scale200"           "scale=200:200"
  do_lavfi "scale500"           "scale=500:500"
 +do_lavfi "select"             "select=not(eq(mod(n\,2)\,0)+eq(mod(n\,3)\,0))"
 +do_lavfi "setdar"             "setdar=16/9"
 +do_lavfi "setsar"             "setsar=16/11"
 +do_lavfi "thumbnail"          "thumbnail=10"
 +do_lavfi "transpose"          "transpose"
 +do_lavfi "unsharp"            "unsharp=10:10:-1.5:10:10:-1.5"
  do_lavfi "vflip"              "vflip"
  do_lavfi "vflip_crop"         "vflip,crop=iw-100:ih-100:100:100"
  do_lavfi "vflip_vflip"        "vflip,vflip"