Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 26 Dec 2011 02:35:54 +0000 (03:35 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 26 Dec 2011 03:10:47 +0000 (04:10 +0100)
* qatar/master:
  avs: call release_buffer() at the end.
  Add minor bumps and APIchanges entries for lavc/lavfi changes.
  mpegvideo.c: K&R formatting and cosmetics.
  avconv: avoid memcpy in vsrc_buffer when possible.
  avconv: implement get_buffer()/release_buffer().
  lavfi: add a new function av_buffersrc_buffer().
  lavfi: add avfilter_copy_frame_props()
  lavc: add format field to AVFrame
  lavc: add width and height fields to AVFrame
  lavc: add a sample_aspect_ratio field to AVFrame
  doxy: add website-alike style to the html output
  FAQ: add an entry for common error when using -profile

Conflicts:
avconv.c
cmdutils.c
doc/APIchanges
libavcodec/avcodec.h
libavcodec/mpegvideo.c
libavcodec/utils.c
libavcodec/version.h
libavfilter/Makefile
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/src_movie.c
libavfilter/vsrc_buffer.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
15 files changed:
1  2 
Doxyfile
avconv.c
doc/faq.texi
ffmpeg.c
libavcodec/avcodec.h
libavcodec/avs.c
libavcodec/mpegvideo.c
libavcodec/pthread.c
libavcodec/utils.c
libavcodec/version.h
libavfilter/avcodec.c
libavfilter/avcodec.h
libavfilter/avfilter.h
libavfilter/src_movie.c
libavfilter/vsrc_buffer.c

diff --cc Doxyfile
Simple merge
diff --cc avconv.c
+++ b/avconv.c
  #include "libavutil/pixdesc.h"
  #include "libavutil/avstring.h"
  #include "libavutil/libm.h"
+ #include "libavutil/imgutils.h"
  #include "libavformat/os_support.h"
  
 +#include "libavformat/ffm.h" // not public API
 +
  #if CONFIG_AVFILTER
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
 +# include "libavfilter/buffersink.h"
+ # include "libavfilter/buffersrc.h"
  # include "libavfilter/vsrc_buffer.h"
  #endif
  
@@@ -1855,32 -1923,43 +1999,47 @@@ static int transcode_video(InputStream 
              continue;
  
  #if CONFIG_AVFILTER
-         if (ost->input_video_filter) {
-             if (!decoded_frame->sample_aspect_ratio.num)
-                 decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
-             decoded_frame->pts = ist->pts;
 -        if (ist->st->sample_aspect_ratio.num)
++        if (!decoded_frame->sample_aspect_ratio.num)
+             decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
++        decoded_frame->pts = ist->pts;
+         if (ist->st->codec->codec->capabilities & CODEC_CAP_DR1) {
+             FrameBuffer      *buf = decoded_frame->opaque;
+             AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
+                                         decoded_frame->data, decoded_frame->linesize,
+                                         AV_PERM_READ | AV_PERM_PRESERVE,
+                                         ist->st->codec->width, ist->st->codec->height,
+                                         ist->st->codec->pix_fmt);
+             avfilter_copy_frame_props(fb, decoded_frame);
+             fb->pts                 = ist->pts;
+             fb->buf->priv           = buf;
+             fb->buf->free           = filter_release_buffer;
+             buf->refcount++;
+             av_buffersrc_buffer(ost->input_video_filter, fb);
+         } else
 -            av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame,
 -                                     ist->pts, decoded_frame->sample_aspect_ratio);
 +            av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
-             if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
-                 av_free(buffer_to_free);
-                 return AVERROR(ENOMEM);
-             } else
-                 avcodec_get_frame_defaults(ist->filtered_frame);
-             filtered_frame = ist->filtered_frame;
-             frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
-         }
+         if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
+             av_free(buffer_to_free);
+             return AVERROR(ENOMEM);
+         } else
+             avcodec_get_frame_defaults(ist->filtered_frame);
+         filtered_frame = ist->filtered_frame;
+         frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
          while (frame_available) {
 -            AVRational ist_pts_tb;
 -            if (ost->output_video_filter)
 -                get_filtered_video_frame(ost->output_video_filter, filtered_frame, &ost->picref, &ist_pts_tb);
 -            if (ost->picref)
 -                ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
 +            if (ost->output_video_filter) {
 +                AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
 +                if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
 +                    goto cont;
 +                if (ost->picref) {
 +                    avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref);
 +                    ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
 +                }
 +            }
              if (ost->picref->video && !ost->frame_aspect_ratio)
 -                ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect;
 +                ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
  #else
              filtered_frame = decoded_frame;
  #endif
@@@ -2055,6 -2133,22 +2214,12 @@@ static int init_input_stream(int ist_in
              return AVERROR(EINVAL);
          }
  
 -        /* update requested sample format for the decoder based on the
 -           corresponding encoder sample format */
 -        for (i = 0; i < nb_output_streams; i++) {
 -            OutputStream *ost = &output_streams[i];
 -            if (ost->source_index == ist_index) {
 -                update_sample_fmt(ist->st->codec, codec, ost->st->codec);
 -                break;
 -            }
 -        }
 -
+         if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) {
+             ist->st->codec->get_buffer     = codec_get_buffer;
+             ist->st->codec->release_buffer = codec_release_buffer;
+             ist->st->codec->opaque         = ist;
+         }
          if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
              snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
                      ist->file_index, ist->st->index);
diff --cc doc/faq.texi
@@@ -272,13 -266,33 +272,33 @@@ ffmpeg -f u16le -acodec pcm_s16le -ac 
  rm temp[12].[av] all.[av]
  @end example
  
 -@command{avconv} prints an error like
+ @section -profile option fails when encoding H.264 video with AAC audio
 -by using @url{http://libav.org/avconv.html#Stream-specifiers-1, Stream specifiers}.
++@command{ffmpeg} prints an error like
+ @example
+ Undefined constant or missing '(' in 'baseline'
+ Unable to parse option value "baseline"
+ Error setting option profile to value baseline.
+ @end example
+ Short answer: write @option{-profile:v} instead of @option{-profile}.
+ Long answer: this happens because the @option{-profile} option can apply to both
+ video and audio.  Specifically the AAC encoder also defines some profiles, none
+ of which are named @var{baseline}.
+ The solution is to apply the @option{-profile} option to the video stream only
++by using @url{http://ffmpeg.org/ffmpeg.html#Stream-specifiers-1, Stream specifiers}.
+ Appending @code{:v} to it will do exactly that.
  @chapter Development
  
 -@section Are there examples illustrating how to use the Libav libraries, particularly libavcodec and libavformat?
 +@section Are there examples illustrating how to use the FFmpeg libraries, particularly libavcodec and libavformat?
  
 -Yes. Read the Developers Guide of the Libav documentation. Alternatively,
 +Yes. Read the Developers Guide of the FFmpeg documentation. Alternatively,
  examine the source code for one of the many open source projects that
 -already incorporate Libav at (@url{projects.html}).
 +already incorporate FFmpeg at (@url{projects.html}).
  
  @section Can you support my C compiler XXX?
  
diff --cc ffmpeg.c
+++ b/ffmpeg.c
  #include "libavutil/pixdesc.h"
  #include "libavutil/avstring.h"
  #include "libavutil/libm.h"
++#include "libavutil/imgutils.h"
  #include "libavformat/os_support.h"
 +#include "libswresample/swresample.h"
 +
 +#include "libavformat/ffm.h" // not public API
  
  #if CONFIG_AVFILTER
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
 +# include "libavfilter/buffersink.h"
++# include "libavfilter/buffersrc.h"
  # include "libavfilter/vsrc_buffer.h"
  #endif
  
@@@ -172,35 -238,7 +174,51 @@@ static uint8_t *input_tmp= NULL
  
  #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
  
 -struct InputStream;
++typedef struct FrameBuffer {
++    uint8_t *base[4];
++    uint8_t *data[4];
++    int  linesize[4];
++
++    int h, w;
++    enum PixelFormat pix_fmt;
++
++    int refcount;
++    struct InputStream *ist;
++    struct FrameBuffer *next;
++} FrameBuffer;
++
 +typedef struct InputStream {
 +    int file_index;
 +    AVStream *st;
 +    int discard;             /* true if stream data should be discarded */
 +    int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
 +    AVCodec *dec;
 +    AVFrame *decoded_frame;
 +    AVFrame *filtered_frame;
 +
 +    int64_t       start;     /* time when read started */
 +    int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
 +                                is not defined */
 +    int64_t       pts;       /* current pts */
 +    double ts_scale;
 +    int is_start;            /* is 1 at the start and after a discontinuity */
 +    int showed_multi_packet_warning;
 +    AVDictionary *opts;
++
++    /* a pool of free buffers for decoded data */
++    FrameBuffer *buffer_pool;
 +} InputStream;
 +
 +typedef struct InputFile {
 +    AVFormatContext *ctx;
 +    int eof_reached;      /* true if eof reached */
 +    int ist_index;        /* index of first stream in input_streams */
 +    int buffer_size;      /* current total buffer size */
 +    int64_t ts_offset;
 +    int nb_streams;       /* number of stream that ffmpeg is aware of; may be different
 +                             from ctx.nb_streams if new streams appear during av_read_frame() */
 +    int rate_emu;
 +} InputFile;
  
  typedef struct OutputStream {
      int file_index;          /* file index */
@@@ -286,161 -330,6 +304,286 @@@ static int         nb_input_streams = 0
  static InputFile   *input_files   = NULL;
  static int         nb_input_files   = 0;
  
 +static OutputStream *output_streams = NULL;
 +static int        nb_output_streams = 0;
 +static OutputFile   *output_files   = NULL;
 +static int        nb_output_files   = 0;
 +
 +typedef struct OptionsContext {
 +    /* input/output options */
 +    int64_t start_time;
 +    const char *format;
 +
 +    SpecifierOpt *codec_names;
 +    int        nb_codec_names;
 +    SpecifierOpt *audio_channels;
 +    int        nb_audio_channels;
 +    SpecifierOpt *audio_sample_rate;
 +    int        nb_audio_sample_rate;
 +    SpecifierOpt *rematrix_volume;
 +    int        nb_rematrix_volume;
 +    SpecifierOpt *frame_rates;
 +    int        nb_frame_rates;
 +    SpecifierOpt *frame_sizes;
 +    int        nb_frame_sizes;
 +    SpecifierOpt *frame_pix_fmts;
 +    int        nb_frame_pix_fmts;
 +
 +    /* input options */
 +    int64_t input_ts_offset;
 +    int rate_emu;
 +
 +    SpecifierOpt *ts_scale;
 +    int        nb_ts_scale;
 +    SpecifierOpt *dump_attachment;
 +    int        nb_dump_attachment;
 +
 +    /* output options */
 +    StreamMap *stream_maps;
 +    int     nb_stream_maps;
 +    AudioChannelMap *audio_channel_maps; ///< one info entry per -map_channel
 +    int           nb_audio_channel_maps; ///< number of (valid) -map_channel settings
 +    /* first item specifies output metadata, second is input */
 +    MetadataMap (*meta_data_maps)[2];
 +    int nb_meta_data_maps;
 +    int metadata_global_manual;
 +    int metadata_streams_manual;
 +    int metadata_chapters_manual;
 +    const char **attachments;
 +    int       nb_attachments;
 +
 +    int chapters_input_file;
 +
 +    int64_t recording_time;
 +    uint64_t limit_filesize;
 +    float mux_preload;
 +    float mux_max_delay;
 +
 +    int video_disable;
 +    int audio_disable;
 +    int subtitle_disable;
 +    int data_disable;
 +
 +    /* indexed by output file stream index */
 +    int   *streamid_map;
 +    int nb_streamid_map;
 +
 +    SpecifierOpt *metadata;
 +    int        nb_metadata;
 +    SpecifierOpt *max_frames;
 +    int        nb_max_frames;
 +    SpecifierOpt *bitstream_filters;
 +    int        nb_bitstream_filters;
 +    SpecifierOpt *codec_tags;
 +    int        nb_codec_tags;
 +    SpecifierOpt *sample_fmts;
 +    int        nb_sample_fmts;
 +    SpecifierOpt *qscale;
 +    int        nb_qscale;
 +    SpecifierOpt *forced_key_frames;
 +    int        nb_forced_key_frames;
 +    SpecifierOpt *force_fps;
 +    int        nb_force_fps;
 +    SpecifierOpt *frame_aspect_ratios;
 +    int        nb_frame_aspect_ratios;
 +    SpecifierOpt *rc_overrides;
 +    int        nb_rc_overrides;
 +    SpecifierOpt *intra_matrices;
 +    int        nb_intra_matrices;
 +    SpecifierOpt *inter_matrices;
 +    int        nb_inter_matrices;
 +    SpecifierOpt *top_field_first;
 +    int        nb_top_field_first;
 +    SpecifierOpt *metadata_map;
 +    int        nb_metadata_map;
 +    SpecifierOpt *presets;
 +    int        nb_presets;
 +    SpecifierOpt *copy_initial_nonkeyframes;
 +    int        nb_copy_initial_nonkeyframes;
 +#if CONFIG_AVFILTER
 +    SpecifierOpt *filters;
 +    int        nb_filters;
 +#endif
 +} OptionsContext;
 +
 +#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
 +{\
 +    int i, ret;\
 +    for (i = 0; i < o->nb_ ## name; i++) {\
 +        char *spec = o->name[i].specifier;\
 +        if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\
 +            outvar = o->name[i].u.type;\
 +        else if (ret < 0)\
 +            exit_program(1);\
 +    }\
 +}
 +
 +static void reset_options(OptionsContext *o, int is_input)
 +{
 +    const OptionDef *po = options;
 +    OptionsContext bak= *o;
 +
 +    /* all OPT_SPEC and OPT_STRING can be freed in generic way */
 +    while (po->name) {
 +        void *dst = (uint8_t*)o + po->u.off;
 +
 +        if (po->flags & OPT_SPEC) {
 +            SpecifierOpt **so = dst;
 +            int i, *count = (int*)(so + 1);
 +            for (i = 0; i < *count; i++) {
 +                av_freep(&(*so)[i].specifier);
 +                if (po->flags & OPT_STRING)
 +                    av_freep(&(*so)[i].u.str);
 +            }
 +            av_freep(so);
 +            *count = 0;
 +        } else if (po->flags & OPT_OFFSET && po->flags & OPT_STRING)
 +            av_freep(dst);
 +        po++;
 +    }
 +
 +    av_freep(&o->stream_maps);
 +    av_freep(&o->audio_channel_maps);
 +    av_freep(&o->meta_data_maps);
 +    av_freep(&o->streamid_map);
 +
 +    memset(o, 0, sizeof(*o));
 +
 +    if(is_input) o->recording_time = bak.recording_time;
 +    else         o->recording_time = INT64_MAX;
 +    o->mux_max_delay  = 0.7;
 +    o->limit_filesize = UINT64_MAX;
 +    o->chapters_input_file = INT_MAX;
 +
 +    uninit_opts();
 +    init_opts();
 +}
 +
++static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf)
++{
++    AVCodecContext *s = ist->st->codec;
++    FrameBuffer  *buf = av_mallocz(sizeof(*buf));
++    int ret;
++    const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
++    int h_chroma_shift, v_chroma_shift;
++    int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
++    int w = s->width, h = s->height;
++
++    if (!buf)
++        return AVERROR(ENOMEM);
++
++    if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
++        w += 2*edge;
++        h += 2*edge;
++    }
++
++    avcodec_align_dimensions(s, &w, &h);
++    if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
++                              s->pix_fmt, 32)) < 0) {
++        av_freep(&buf);
++        return ret;
++    }
++    /* XXX this shouldn't be needed, but some tests break without this line
++     * those decoders are buggy and need to be fixed.
++     * the following tests fail:
++     * bethsoft-vid, cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
++     */
++    memset(buf->base[0], 128, ret);
++
++    avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
++    for (int i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
++        const int h_shift = i==0 ? 0 : h_chroma_shift;
++        const int v_shift = i==0 ? 0 : v_chroma_shift;
++        if (s->flags & CODEC_FLAG_EMU_EDGE)
++            buf->data[i] = buf->base[i];
++        else
++            buf->data[i] = buf->base[i] +
++                           FFALIGN((buf->linesize[i]*edge >> v_shift) +
++                                   (pixel_size*edge >> h_shift), 32);
++    }
++    buf->w       = s->width;
++    buf->h       = s->height;
++    buf->pix_fmt = s->pix_fmt;
++    buf->ist     = ist;
++
++    *pbuf = buf;
++    return 0;
++}
++
++static void free_buffer_pool(InputStream *ist)
++{
++    FrameBuffer *buf = ist->buffer_pool;
++    while (buf) {
++        ist->buffer_pool = buf->next;
++        av_freep(&buf->base[0]);
++        av_free(buf);
++        buf = ist->buffer_pool;
++    }
++}
++
++static void unref_buffer(InputStream *ist, FrameBuffer *buf)
++{
++    av_assert0(buf->refcount);
++    buf->refcount--;
++    if (!buf->refcount) {
++        buf->next = ist->buffer_pool;
++        ist->buffer_pool = buf;
++    }
++}
++
++static int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
++{
++    InputStream *ist = s->opaque;
++    FrameBuffer *buf;
++    int ret, i;
++
++    if (!ist->buffer_pool && (ret = alloc_buffer(ist, &ist->buffer_pool)) < 0)
++        return ret;
++
++    buf              = ist->buffer_pool;
++    ist->buffer_pool = buf->next;
++    buf->next        = NULL;
++    if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
++        av_freep(&buf->base[0]);
++        av_free(buf);
++        if ((ret = alloc_buffer(ist, &buf)) < 0)
++            return ret;
++    }
++    buf->refcount++;
++
++    frame->opaque        = buf;
++    frame->type          = FF_BUFFER_TYPE_USER;
++    frame->extended_data = frame->data;
++    frame->pkt_pts       = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE;
++
++    for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
++        frame->base[i]     = buf->base[i];  // XXX h264.c uses base though it shouldn't
++        frame->data[i]     = buf->data[i];
++        frame->linesize[i] = buf->linesize[i];
++    }
++
++    return 0;
++}
++
++static void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
++{
++    InputStream *ist = s->opaque;
++    FrameBuffer *buf = frame->opaque;
++    int i;
++
++    for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
++        frame->data[i] = NULL;
++
++    unref_buffer(ist, buf);
++}
++
++static void filter_release_buffer(AVFilterBuffer *fb)
++{
++    FrameBuffer *buf = fb->priv;
++    av_free(fb);
++    unref_buffer(buf->ist, buf);
++}
++
  #if CONFIG_AVFILTER
  
  static int configure_video_filters(InputStream *ist, OutputStream *ost)
@@@ -658,16 -456,17 +801,17 @@@ void av_noreturn exit_program(int ret
          if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
              avio_close(s->pb);
          avformat_free_context(s);
 -        av_free(output_streams_for_file[i]);
 -        av_dict_free(&output_opts[i]);
 +        av_dict_free(&output_files[i].opts);
      }
      for(i=0;i<nb_input_files;i++) {
 -        av_close_input_file(input_files[i].ctx);
 +        avformat_close_input(&input_files[i].ctx);
      }
 -    for (i = 0; i < nb_input_streams; i++)
 +    for (i = 0; i < nb_input_streams; i++) {
 +        av_freep(&input_streams[i].decoded_frame);
 +        av_freep(&input_streams[i].filtered_frame);
          av_dict_free(&input_streams[i].opts);
 -
 -    av_free(intra_matrix);
 -    av_free(inter_matrix);
++        free_buffer_pool(&input_streams[i]);
 +    }
  
      if (vstats_file)
          fclose(vstats_file);
@@@ -1309,28 -1280,7 +1305,26 @@@ typedef struct AVFrame 
       * - encoding: unused
       * - decoding: Read by user.
       */
-     AVRational sample_aspect_ratio;
+     int format;
 +
 +    /**
-      * width and height of the video frame
++     * frame timestamp estimated using various heuristics, in stream time base
 +     * Code outside libavcodec should access this field using:
-      *  av_opt_ptr(avcodec_get_frame_class(), frame, "width");
++     *  av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp");
 +     * - encoding: unused
-      * - decoding: Read by user.
++     * - decoding: set by libavcodec, read by user.
 +     */
-     int width, height;
++    int64_t best_effort_timestamp;
 +
 +    /**
-      * format of the frame, -1 if unknown or unset
-      * It should be cast to the corresponding enum (enum PixelFormat
-      * for video, enum AVSampleFormat for audio)
++     * reordered pos from the last AVPacket that has been input into the decoder
 +     * Code outside libavcodec should access this field using:
-      *  av_opt_ptr(avcodec_get_frame_class(), frame, "format");
++     *  av_opt_ptr(avcodec_get_frame_class(), frame, "pkt_pos");
 +     * - encoding: unused
 +     * - decoding: Read by user.
 +     */
-     int format;
++    int64_t pkt_pos;
 +
  } AVFrame;
  
  struct AVCodecInternal;
Simple merge
@@@ -1081,30 -1129,17 +1081,31 @@@ int ff_find_unused_picture(MpegEncConte
          }
      }
  
 -    return AVERROR_INVALIDDATA;
 +    av_log(s->avctx, AV_LOG_FATAL,
 +           "Internal error, picture buffer overflow\n");
 +    /* We could return -1, but the codec would crash trying to draw into a
 +     * non-existing frame anyway. This is safer than waiting for a random crash.
 +     * Also the return of this is never useful, an encoder must only allocate
 +     * as much as allowed in the specification. This has no relationship to how
 +     * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large
 +     * enough for such valid streams).
 +     * Plus, a decoder has to check stream validity and remove frames if too
 +     * many reference frames are around. Waiting for "OOM" is not correct at
 +     * all. Similarly, missing reference frames have to be replaced by
 +     * interpolated/MC frames, anything else is a bug in the codec ...
 +     */
 +    abort();
 +    return -1;
  }
  
- static void update_noise_reduction(MpegEncContext *s){
+ static void update_noise_reduction(MpegEncContext *s)
+ {
      int intra, i;
  
-     for(intra=0; intra<2; intra++){
-         if(s->dct_count[intra] > (1<<16)){
-             for(i=0; i<64; i++){
-                 s->dct_error_sum[intra][i] >>=1;
+     for (intra = 0; intra < 2; intra++) {
+         if (s->dct_count[intra] > (1 << 16)) {
+             for (i = 0; i < 64; i++) {
+                 s->dct_error_sum[intra][i] >>= 1;
              }
              s->dct_count[intra] >>= 1;
          }
@@@ -1143,19 -1189,19 +1155,21 @@@ int MPV_frame_start(MpegEncContext *s, 
                  }
              }
          }
-       }
      }
  
-     if(!s->encoding){
+     if (!s->encoding) {
          ff_release_unused_pictures(s, 1);
  
-         if (s->current_picture_ptr && s->current_picture_ptr->f.data[0] == NULL)
-             pic= s->current_picture_ptr; //we already have a unused image (maybe it was set before reading the header)
-         else{
-             i= ff_find_unused_picture(s, 0);
+         if (s->current_picture_ptr &&
+             s->current_picture_ptr->f.data[0] == NULL) {
+             // we already have a unused image
+             // (maybe it was set before reading the header)
+             pic = s->current_picture_ptr;
+         } else {
+             i   = ff_find_unused_picture(s, 0);
 +            if (i < 0)
 +                return i;
-             pic= &s->picture[i];
+             pic = &s->picture[i];
          }
  
          pic->f.reference = 0;
      ff_copy_picture(&s->current_picture, s->current_picture_ptr);
  
      if (s->pict_type != AV_PICTURE_TYPE_B) {
-         s->last_picture_ptr= s->next_picture_ptr;
-         if(!s->dropable)
-             s->next_picture_ptr= s->current_picture_ptr;
+         s->last_picture_ptr = s->next_picture_ptr;
+         if (!s->dropable)
+             s->next_picture_ptr = s->current_picture_ptr;
      }
- /*    av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
-         s->last_picture_ptr    ? s->last_picture_ptr->f.data[0]    : NULL,
-         s->next_picture_ptr    ? s->next_picture_ptr->f.data[0]    : NULL,
-         s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL,
-         s->pict_type, s->dropable);*/
-     if(s->codec_id != CODEC_ID_H264){
-         if ((s->last_picture_ptr == NULL || s->last_picture_ptr->f.data[0] == NULL) &&
-            (s->pict_type!=AV_PICTURE_TYPE_I || s->picture_structure != PICT_FRAME)){
+     /* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n",
+            s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
+            s->last_picture_ptr    ? s->last_picture_ptr->f.data[0]    : NULL,
+            s->next_picture_ptr    ? s->next_picture_ptr->f.data[0]    : NULL,
+            s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL,
+            s->pict_type, s->dropable); */
+     if (s->codec_id != CODEC_ID_H264) {
+         if ((s->last_picture_ptr == NULL ||
+              s->last_picture_ptr->f.data[0] == NULL) &&
+             (s->pict_type != AV_PICTURE_TYPE_I ||
+              s->picture_structure != PICT_FRAME)) {
              if (s->pict_type != AV_PICTURE_TYPE_I)
-                 av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n");
+                 av_log(avctx, AV_LOG_ERROR,
+                        "warning: first frame is no keyframe\n");
              else if (s->picture_structure != PICT_FRAME)
-                 av_log(avctx, AV_LOG_INFO, "allocate dummy last picture for field based first keyframe\n");
+                 av_log(avctx, AV_LOG_INFO,
+                        "allocate dummy last picture for field based first keyframe\n");
  
              /* Allocate a dummy frame */
-             i= ff_find_unused_picture(s, 0);
+             i = ff_find_unused_picture(s, 0);
 -            s->last_picture_ptr = &s->picture[i];
 +            if (i < 0)
 +                return i;
 +            s->last_picture_ptr= &s->picture[i];
 +            s->last_picture_ptr->f.key_frame = 0;
-             if(ff_alloc_picture(s, s->last_picture_ptr, 0) < 0)
+             if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0)
                  return -1;
-             ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 0);
-             ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 1);
 +
 +            if(s->codec_id == CODEC_ID_FLV1 || s->codec_id == CODEC_ID_H263){
 +                for(i=0; i<avctx->height; i++)
 +                    memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width);
 +            }
 +
+             ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
+                                       INT_MAX, 0);
+             ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
+                                       INT_MAX, 1);
          }
-         if ((s->next_picture_ptr == NULL || s->next_picture_ptr->f.data[0] == NULL) && s->pict_type == AV_PICTURE_TYPE_B) {
+         if ((s->next_picture_ptr == NULL ||
+              s->next_picture_ptr->f.data[0] == NULL) &&
+             s->pict_type == AV_PICTURE_TYPE_B) {
              /* Allocate a dummy frame */
-             i= ff_find_unused_picture(s, 0);
+             i = ff_find_unused_picture(s, 0);
 -            s->next_picture_ptr = &s->picture[i];
 +            if (i < 0)
 +                return i;
 +            s->next_picture_ptr= &s->picture[i];
 +            s->next_picture_ptr->f.key_frame = 0;
-             if(ff_alloc_picture(s, s->next_picture_ptr, 0) < 0)
+             if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0)
                  return -1;
-             ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 0);
-             ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 1);
+             ff_thread_report_progress((AVFrame *) s->next_picture_ptr,
+                                       INT_MAX, 0);
+             ff_thread_report_progress((AVFrame *) s->next_picture_ptr,
+                                       INT_MAX, 1);
          }
      }
  
@@@ -1288,27 -1341,30 +1321,30 @@@ void MPV_frame_end(MpegEncContext *s
  {
      int i;
      /* redraw edges for the frame if decoding didn't complete */
-     //just to make sure that all data is rendered.
-     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){
+     // just to make sure that all data is rendered.
+     if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) {
          ff_xvmc_field_end(s);
-    }else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND))
-        && !s->avctx->hwaccel
-        && !(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
-        && s->unrestricted_mv
-        && s->current_picture.f.reference
-        && !s->intra_only
-        && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
-             int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w;
-             int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h;
-             s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize,
-                               s->h_edge_pos             , s->v_edge_pos,
-                               EDGE_WIDTH        , EDGE_WIDTH        , EDGE_TOP | EDGE_BOTTOM);
-             s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize,
-                               s->h_edge_pos>>hshift, s->v_edge_pos>>vshift,
-                               EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
-             s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize,
-                               s->h_edge_pos>>hshift, s->v_edge_pos>>vshift,
-                               EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
 -   } else if ((s->error_count || s->encoding) &&
++   } else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) &&
+               !s->avctx->hwaccel &&
+               !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) &&
+               s->unrestricted_mv &&
+               s->current_picture.f.reference &&
+               !s->intra_only &&
+               !(s->flags & CODEC_FLAG_EMU_EDGE)) {
+         int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w;
+         int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h;
+         s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize,
+                           s->h_edge_pos, s->v_edge_pos,
+                           EDGE_WIDTH, EDGE_WIDTH,
+                           EDGE_TOP | EDGE_BOTTOM);
+         s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize,
+                           s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
+                           EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
+                           EDGE_TOP | EDGE_BOTTOM);
+         s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize,
+                           s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
+                           EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
+                           EDGE_TOP | EDGE_BOTTOM);
      }
  
      emms_c();
@@@ -1372,29 -1432,31 +1412,31 @@@ static void draw_line(uint8_t *buf, in
              FFSWAP(int, sx, ex);
              FFSWAP(int, sy, ey);
          }
-         buf+= sx + sy*stride;
-         ex-= sx;
-         f= ((ey-sy)<<16)/ex;
+         buf += sx + sy * stride;
+         ex  -= sx;
+         f    = ((ey - sy) << 16) / ex;
 -        for (x = 0; x = ex; x++) {
 +        for(x= 0; x <= ex; x++){
-             y = (x*f)>>16;
-             fr= (x*f)&0xFFFF;
-             buf[ y   *stride + x]+= (color*(0x10000-fr))>>16;
-             buf[(y+1)*stride + x]+= (color*         fr )>>16;
+             y  = (x * f) >> 16;
+             fr = (x * f) & 0xFFFF;
+             buf[y * stride + x]       += (color * (0x10000 - fr)) >> 16;
+             buf[(y + 1) * stride + x] += (color *            fr ) >> 16;
          }
-     }else{
-         if(sy > ey){
+     } else {
+         if (sy > ey) {
              FFSWAP(int, sx, ex);
              FFSWAP(int, sy, ey);
          }
-         buf+= sx + sy*stride;
-         ey-= sy;
-         if(ey) f= ((ex-sx)<<16)/ey;
-         else   f= 0;
+         buf += sx + sy * stride;
+         ey  -= sy;
+         if (ey)
 -            f  = ((ex - sx) << 16) / ey;
++            f = ((ex - sx) << 16) / ey;
+         else
+             f = 0;
 -        for (y = 0; y = ey; y++) {
 -            x  = (y * f) >> 16;
 -            fr = (y * f) & 0xFFFF;
 +        for(y= 0; y <= ey; y++){
-             x = (y*f)>>16;
-             fr= (y*f)&0xFFFF;
-             buf[y*stride + x  ]+= (color*(0x10000-fr))>>16;
-             buf[y*stride + x+1]+= (color*         fr )>>16;
++            x  = (y*f) >> 16;
++            fr = (y*f) & 0xFFFF;
+             buf[y * stride + x]     += (color * (0x10000 - fr)) >> 16;
+             buf[y * stride + x + 1] += (color *            fr ) >> 16;
          }
      }
  }
@@@ -1433,53 -1497,75 +1477,56 @@@ static void draw_arrow(uint8_t *buf, in
  }
  
  /**
-  * Print debuging info for the given picture.
+  * Print debugging info for the given picture.
   */
- void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
-     if(s->avctx->hwaccel || !pict || !pict->mb_type) return;
+ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
+ {
+     if (s->avctx->hwaccel || !pict || !pict->mb_type)
+         return;
  
-     if(s->avctx->debug&(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)){
+     if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
          int x,y;
  
 -        av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
 -        switch (pict->pict_type) {
 -        case AV_PICTURE_TYPE_I:
 -            av_log(s->avctx,AV_LOG_DEBUG,"I\n");
 -            break;
 -        case AV_PICTURE_TYPE_P:
 -            av_log(s->avctx,AV_LOG_DEBUG,"P\n");
 -            break;
 -        case AV_PICTURE_TYPE_B:
 -            av_log(s->avctx,AV_LOG_DEBUG,"B\n");
 -            break;
 -        case AV_PICTURE_TYPE_S:
 -            av_log(s->avctx,AV_LOG_DEBUG,"S\n");
 -            break;
 -        case AV_PICTURE_TYPE_SI:
 -            av_log(s->avctx,AV_LOG_DEBUG,"SI\n");
 -            break;
 -        case AV_PICTURE_TYPE_SP:
 -            av_log(s->avctx,AV_LOG_DEBUG,"SP\n");
 -            break;
 -        }
 +        av_log(s->avctx, AV_LOG_DEBUG, "New frame, type: %c\n",
 +               av_get_picture_type_char(pict->pict_type));
-         for(y=0; y<s->mb_height; y++){
-             for(x=0; x<s->mb_width; x++){
-                 if(s->avctx->debug&FF_DEBUG_SKIP){
-                     int count= s->mbskip_table[x + y*s->mb_stride];
-                     if(count>9) count=9;
+         for (y = 0; y < s->mb_height; y++) {
+             for (x = 0; x < s->mb_width; x++) {
+                 if (s->avctx->debug & FF_DEBUG_SKIP) {
+                     int count = s->mbskip_table[x + y * s->mb_stride];
+                     if (count > 9)
+                         count = 9;
                      av_log(s->avctx, AV_LOG_DEBUG, "%1d", count);
                  }
-                 if(s->avctx->debug&FF_DEBUG_QP){
-                     av_log(s->avctx, AV_LOG_DEBUG, "%2d", pict->qscale_table[x + y*s->mb_stride]);
+                 if (s->avctx->debug & FF_DEBUG_QP) {
+                     av_log(s->avctx, AV_LOG_DEBUG, "%2d",
+                            pict->qscale_table[x + y * s->mb_stride]);
                  }
-                 if(s->avctx->debug&FF_DEBUG_MB_TYPE){
-                     int mb_type= pict->mb_type[x + y*s->mb_stride];
-                     //Type & MV direction
-                     if(IS_PCM(mb_type))
+                 if (s->avctx->debug & FF_DEBUG_MB_TYPE) {
+                     int mb_type = pict->mb_type[x + y * s->mb_stride];
+                     // Type & MV direction
+                     if (IS_PCM(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "P");
-                     else if(IS_INTRA(mb_type) && IS_ACPRED(mb_type))
+                     else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "A");
-                     else if(IS_INTRA4x4(mb_type))
+                     else if (IS_INTRA4x4(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "i");
-                     else if(IS_INTRA16x16(mb_type))
+                     else if (IS_INTRA16x16(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "I");
-                     else if(IS_DIRECT(mb_type) && IS_SKIP(mb_type))
+                     else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "d");
-                     else if(IS_DIRECT(mb_type))
+                     else if (IS_DIRECT(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "D");
-                     else if(IS_GMC(mb_type) && IS_SKIP(mb_type))
+                     else if (IS_GMC(mb_type) && IS_SKIP(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "g");
-                     else if(IS_GMC(mb_type))
+                     else if (IS_GMC(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "G");
-                     else if(IS_SKIP(mb_type))
+                     else if (IS_SKIP(mb_type))
                          av_log(s->avctx, AV_LOG_DEBUG, "S");
-                     else if(!USES_LIST(mb_type, 1))
+                     else if (!USES_LIST(mb_type, 1))
                          av_log(s->avctx, AV_LOG_DEBUG, ">");
-                     else if(!USES_LIST(mb_type, 0))
+                     else if (!USES_LIST(mb_type, 0))
                          av_log(s->avctx, AV_LOG_DEBUG, "<");
-                     else{
+                     else {
                          assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
                          av_log(s->avctx, AV_LOG_DEBUG, "X");
                      }
          uint8_t *ptr;
          int i;
          int h_chroma_shift, v_chroma_shift, block_height;
-         const int width = s->avctx->width;
-         const int height= s->avctx->height;
-         const int mv_sample_log2= 4 - pict->motion_subsample_log2;
-         const int mv_stride= (s->mb_width << mv_sample_log2) + (s->codec_id == CODEC_ID_H264 ? 0 : 1);
-         s->low_delay=0; //needed to see the vectors without trashing the buffers
-         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
-         for(i=0; i<3; i++){
-             memcpy(s->visualization_buffer[i], pict->data[i], (i==0) ? pict->linesize[i]*height:pict->linesize[i]*height >> v_chroma_shift);
-             pict->data[i]= s->visualization_buffer[i];
+         const int width          = s->avctx->width;
+         const int height         = s->avctx->height;
+         const int mv_sample_log2 = 4 - pict->motion_subsample_log2;
+         const int mv_stride      = (s->mb_width << mv_sample_log2) +
+                                    (s->codec_id == CODEC_ID_H264 ? 0 : 1);
+         s->low_delay = 0; // needed to see the vectors without trashing the buffers
+         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,
+                                       &h_chroma_shift, &v_chroma_shift);
+         for (i = 0; i < 3; i++) {
+             memcpy(s->visualization_buffer[i], pict->data[i],
+                    (i == 0) ? pict->linesize[i] * height:
+                               pict->linesize[i] * height >> v_chroma_shift);
+             pict->data[i] = s->visualization_buffer[i];
          }
-         pict->type= FF_BUFFER_TYPE_COPY;
+         pict->type   = FF_BUFFER_TYPE_COPY;
 +        pict->opaque= NULL;
-         ptr= pict->data[0];
-         block_height = 16>>v_chroma_shift;
+         ptr          = pict->data[0];
+         block_height = 16 >> v_chroma_shift;
  
-         for(mb_y=0; mb_y<s->mb_height; mb_y++){
+         for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
              int mb_x;
-             for(mb_x=0; mb_x<s->mb_width; mb_x++){
-                 const int mb_index= mb_x + mb_y*s->mb_stride;
-                 if (s->avctx->debug_mv && pict->motion_val) {
-                   int type;
-                   for(type=0; type<3; type++){
-                     int direction = 0;
-                     switch (type) {
-                       case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_P))
+             for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
+                 const int mb_index = mb_x + mb_y * s->mb_stride;
+                 if ((s->avctx->debug_mv) && pict->motion_val) {
+                     int type;
+                     for (type = 0; type < 3; type++) {
+                         int direction = 0;
+                         switch (type) {
+                         case 0:
+                             if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_P_FOR)) ||
+                                 (pict->pict_type!= AV_PICTURE_TYPE_P))
                                  continue;
-                               direction = 0;
-                               break;
-                       case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
+                             direction = 0;
+                             break;
+                         case 1:
+                             if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_FOR)) ||
+                                 (pict->pict_type!= AV_PICTURE_TYPE_B))
                                  continue;
-                               direction = 0;
-                               break;
-                       case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
+                             direction = 0;
+                             break;
+                         case 2:
+                             if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_BACK)) ||
+                                 (pict->pict_type!= AV_PICTURE_TYPE_B))
                                  continue;
-                               direction = 1;
-                               break;
-                     }
-                     if(!USES_LIST(pict->mb_type[mb_index], direction))
-                         continue;
-                     if(IS_8X8(pict->mb_type[mb_index])){
-                       int i;
-                       for(i=0; i<4; i++){
-                         int sx= mb_x*16 + 4 + 8*(i&1);
-                         int sy= mb_y*16 + 4 + 8*(i>>1);
-                         int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1);
-                         int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
-                         int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
-                         draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
-                       }
-                     }else if(IS_16X8(pict->mb_type[mb_index])){
-                       int i;
-                       for(i=0; i<2; i++){
-                         int sx=mb_x*16 + 8;
-                         int sy=mb_y*16 + 4 + 8*i;
-                         int xy= (mb_x*2 + (mb_y*2 + i)*mv_stride) << (mv_sample_log2-1);
-                         int mx=(pict->motion_val[direction][xy][0]>>shift);
-                         int my=(pict->motion_val[direction][xy][1]>>shift);
-                         if(IS_INTERLACED(pict->mb_type[mb_index]))
-                             my*=2;
-                         draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100);
-                       }
-                     }else if(IS_8X16(pict->mb_type[mb_index])){
-                       int i;
-                       for(i=0; i<2; i++){
-                         int sx=mb_x*16 + 4 + 8*i;
-                         int sy=mb_y*16 + 8;
-                         int xy= (mb_x*2 + i + mb_y*2*mv_stride) << (mv_sample_log2-1);
-                         int mx=(pict->motion_val[direction][xy][0]>>shift);
-                         int my=(pict->motion_val[direction][xy][1]>>shift);
-                         if(IS_INTERLACED(pict->mb_type[mb_index]))
-                             my*=2;
-                         draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100);
-                       }
-                     }else{
-                       int sx= mb_x*16 + 8;
-                       int sy= mb_y*16 + 8;
-                       int xy= (mb_x + mb_y*mv_stride) << mv_sample_log2;
-                       int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
-                       int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
-                       draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
+                             direction = 1;
+                             break;
+                         }
+                         if (!USES_LIST(pict->mb_type[mb_index], direction))
+                             continue;
+                         if (IS_8X8(pict->mb_type[mb_index])) {
+                             int i;
+                             for (i = 0; i < 4; i++) {
+                                 int sx = mb_x * 16 + 4 + 8 * (i & 1);
+                                 int sy = mb_y * 16 + 4 + 8 * (i >> 1);
+                                 int xy = (mb_x * 2 + (i & 1) +
+                                           (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1);
+                                 int mx = (pict->motion_val[direction][xy][0] >> shift) + sx;
+                                 int my = (pict->motion_val[direction][xy][1] >> shift) + sy;
+                                 draw_arrow(ptr, sx, sy, mx, my, width,
+                                            height, s->linesize, 100);
+                             }
+                         } else if (IS_16X8(pict->mb_type[mb_index])) {
+                             int i;
+                             for (i = 0; i < 2; i++) {
+                                 int sx = mb_x * 16 + 8;
+                                 int sy = mb_y * 16 + 4 + 8 * i;
+                                 int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1);
+                                 int mx = (pict->motion_val[direction][xy][0] >> shift);
+                                 int my = (pict->motion_val[direction][xy][1] >> shift);
+                                 if (IS_INTERLACED(pict->mb_type[mb_index]))
+                                     my *= 2;
+                             draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
+                                        height, s->linesize, 100);
+                             }
+                         } else if (IS_8X16(pict->mb_type[mb_index])) {
+                             int i;
+                             for (i = 0; i < 2; i++) {
+                                 int sx = mb_x * 16 + 4 + 8 * i;
+                                 int sy = mb_y * 16 + 8;
+                                 int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1);
+                                 int mx = pict->motion_val[direction][xy][0] >> shift;
+                                 int my = pict->motion_val[direction][xy][1] >> shift;
+                                 if (IS_INTERLACED(pict->mb_type[mb_index]))
+                                     my *= 2;
+                                 draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
+                                            height, s->linesize, 100);
+                             }
+                         } else {
 -                              int sx = mb_x * 16 + 8;
 -                              int sy = mb_y * 16 + 8;
 -                              int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2;
 -                              int mx = pict->motion_val[direction][xy][0] >> shift + sx;
 -                              int my = pict->motion_val[direction][xy][1] >> shift + sy;
++                              int sx= mb_x * 16 + 8;
++                              int sy= mb_y * 16 + 8;
++                              int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2;
++                              int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
++                              int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
+                               draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
+                         }
                      }
-                   }
                  }
-                 if((s->avctx->debug&FF_DEBUG_VIS_QP) && pict->motion_val){
-                     uint64_t c= (pict->qscale_table[mb_index]*128/31) * 0x0101010101010101ULL;
+                 if ((s->avctx->debug & FF_DEBUG_VIS_QP) && pict->motion_val) {
+                     uint64_t c = (pict->qscale_table[mb_index] * 128 / 31) *
+                                  0x0101010101010101ULL;
                      int y;
-                     for(y=0; y<block_height; y++){
-                         *(uint64_t*)(pict->data[1] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[1])= c;
-                         *(uint64_t*)(pict->data[2] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[2])= c;
+                     for (y = 0; y < block_height; y++) {
+                         *(uint64_t *)(pict->data[1] + 8 * mb_x +
+                                       (block_height * mb_y + y) *
+                                       pict->linesize[1]) = c;
+                         *(uint64_t *)(pict->data[2] + 8 * mb_x +
+                                       (block_height * mb_y + y) *
+                                       pict->linesize[2]) = c;
                      }
                  }
-                 if((s->avctx->debug&FF_DEBUG_VIS_MB_TYPE) && pict->motion_val){
-                     int mb_type= pict->mb_type[mb_index];
+                 if ((s->avctx->debug & FF_DEBUG_VIS_MB_TYPE) &&
+                     pict->motion_val) {
+                     int mb_type = pict->mb_type[mb_index];
                      uint64_t u,v;
                      int y;
- #define COLOR(theta, r)\
- u= (int)(128 + r*cos(theta*3.141592/180));\
- v= (int)(128 + r*sin(theta*3.141592/180));
-                     u=v=128;
-                     if(IS_PCM(mb_type)){
-                         COLOR(120,48)
-                     }else if((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || IS_INTRA16x16(mb_type)){
-                         COLOR(30,48)
-                     }else if(IS_INTRA4x4(mb_type)){
-                         COLOR(90,48)
-                     }else if(IS_DIRECT(mb_type) && IS_SKIP(mb_type)){
- //                        COLOR(120,48)
-                     }else if(IS_DIRECT(mb_type)){
-                         COLOR(150,48)
-                     }else if(IS_GMC(mb_type) && IS_SKIP(mb_type)){
-                         COLOR(170,48)
-                     }else if(IS_GMC(mb_type)){
-                         COLOR(190,48)
-                     }else if(IS_SKIP(mb_type)){
- //                        COLOR(180,48)
-                     }else if(!USES_LIST(mb_type, 1)){
-                         COLOR(240,48)
-                     }else if(!USES_LIST(mb_type, 0)){
-                         COLOR(0,48)
-                     }else{
+ #define COLOR(theta, r) \
+     u = (int)(128 + r * cos(theta * 3.141592 / 180)); \
+     v = (int)(128 + r * sin(theta * 3.141592 / 180));
+                     u = v = 128;
+                     if (IS_PCM(mb_type)) {
+                         COLOR(120, 48)
+                     } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) ||
+                                IS_INTRA16x16(mb_type)) {
+                         COLOR(30, 48)
+                     } else if (IS_INTRA4x4(mb_type)) {
+                         COLOR(90, 48)
+                     } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) {
+                         // COLOR(120, 48)
+                     } else if (IS_DIRECT(mb_type)) {
+                         COLOR(150, 48)
+                     } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) {
+                         COLOR(170, 48)
+                     } else if (IS_GMC(mb_type)) {
+                         COLOR(190, 48)
+                     } else if (IS_SKIP(mb_type)) {
+                         // COLOR(180, 48)
+                     } else if (!USES_LIST(mb_type, 1)) {
+                         COLOR(240, 48)
+                     } else if (!USES_LIST(mb_type, 0)) {
+                         COLOR(0, 48)
+                     } else {
                          assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
                          COLOR(300,48)
                      }
@@@ -1734,119 -1852,118 +1814,135 @@@ static inline int hpel_motion_lowres(Mp
  
  /* apply one mpeg motion vector to the three components */
  static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
-                                uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
-                                int field_based, int bottom_field, int field_select,
-                                uint8_t **ref_picture, h264_chroma_mc_func *pix_op,
-                                int motion_x, int motion_y, int h, int mb_y)
+                                                 uint8_t *dest_y,
+                                                 uint8_t *dest_cb,
+                                                 uint8_t *dest_cr,
+                                                 int field_based,
+                                                 int bottom_field,
+                                                 int field_select,
+                                                 uint8_t **ref_picture,
+                                                 h264_chroma_mc_func *pix_op,
+                                                 int motion_x, int motion_y,
+                                                 int h, int mb_y)
  {
      uint8_t *ptr_y, *ptr_cb, *ptr_cr;
-     int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy, uvsx, uvsy;
-     const int lowres= s->avctx->lowres;
-     const int op_index= FFMIN(lowres-1+s->chroma_x_shift, 2);
-     const int block_s= 8>>lowres;
-     const int s_mask= (2<<lowres)-1;
+     int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
+         uvsx, uvsy;
+     const int lowres     = s->avctx->lowres;
 -    const int op_index   = FFMIN(lowres, 2);
++    const int op_index   = FFMIN(lowres-1+s->chroma_x_shift, 2);
+     const int block_s    = 8>>lowres;
+     const int s_mask     = (2 << lowres) - 1;
      const int h_edge_pos = s->h_edge_pos >> lowres;
      const int v_edge_pos = s->v_edge_pos >> lowres;
      linesize   = s->current_picture.f.linesize[0] << field_based;
      uvlinesize = s->current_picture.f.linesize[1] << field_based;
  
-     if(s->quarter_sample){ //FIXME obviously not perfect but qpel will not work in lowres anyway
-         motion_x/=2;
-         motion_y/=2;
+     // FIXME obviously not perfect but qpel will not work in lowres anyway
+     if (s->quarter_sample) {
+         motion_x /= 2;
+         motion_y /= 2;
      }
  
 -    if (field_based) {
 -        motion_y += (bottom_field - field_select) * (1 << lowres - 1);
 +    if(field_based){
-         motion_y += (bottom_field - field_select)*((1<<lowres)-1);
++        motion_y += (bottom_field - field_select)*((1 << lowres)-1);
      }
  
-     sx= motion_x & s_mask;
-     sy= motion_y & s_mask;
-     src_x = s->mb_x*2*block_s               + (motion_x >> (lowres+1));
-     src_y =(   mb_y*2*block_s>>field_based) + (motion_y >> (lowres+1));
+     sx = motion_x & s_mask;
+     sy = motion_y & s_mask;
+     src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1);
+     src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1);
  
      if (s->out_format == FMT_H263) {
-         uvsx = ((motion_x>>1) & s_mask) | (sx&1);
-         uvsy = ((motion_y>>1) & s_mask) | (sy&1);
-         uvsrc_x = src_x>>1;
-         uvsrc_y = src_y>>1;
-     }else if(s->out_format == FMT_H261){//even chroma mv's are full pel in H261
-         mx = motion_x / 4;
-         my = motion_y / 4;
-         uvsx = (2*mx) & s_mask;
-         uvsy = (2*my) & s_mask;
-         uvsrc_x = s->mb_x*block_s               + (mx >> lowres);
-         uvsrc_y =    mb_y*block_s               + (my >> lowres);
+         uvsx    = ((motion_x >> 1) & s_mask) | (sx & 1);
+         uvsy    = ((motion_y >> 1) & s_mask) | (sy & 1);
+         uvsrc_x = src_x >> 1;
+         uvsrc_y = src_y >> 1;
+     } else if (s->out_format == FMT_H261) {
+         // even chroma mv's are full pel in H261
+         mx      = motion_x / 4;
+         my      = motion_y / 4;
+         uvsx    = (2 * mx) & s_mask;
+         uvsy    = (2 * my) & s_mask;
+         uvsrc_x = s->mb_x * block_s + (mx >> lowres);
+         uvsrc_y =    mb_y * block_s + (my >> lowres);
      } else {
 -        mx      = motion_x / 2;
 -        my      = motion_y / 2;
 -        uvsx    = mx & s_mask;
 -        uvsy    = my & s_mask;
 -        uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
 -        uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
 +        if(s->chroma_y_shift){
-             mx = motion_x / 2;
-             my = motion_y / 2;
-             uvsx = mx & s_mask;
-             uvsy = my & s_mask;
-             uvsrc_x = s->mb_x*block_s               + (mx >> (lowres+1));
-             uvsrc_y =(   mb_y*block_s>>field_based) + (my >> (lowres+1));
++            mx      = motion_x / 2;
++            my      = motion_y / 2;
++            uvsx    = mx & s_mask;
++            uvsy    = my & s_mask;
++            uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
++            uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
 +        } else {
 +            if(s->chroma_x_shift){
 +            //Chroma422
 +                mx = motion_x / 2;
 +                uvsx = mx & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_y = src_y;
 +                uvsrc_x = s->mb_x*block_s               + (mx >> (lowres+1));
 +            } else {
 +            //Chroma444
 +                uvsx = motion_x & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_x = src_x;
 +                uvsrc_y = src_y;
 +            }
 +        }
      }
  
-     ptr_y  = ref_picture[0] + src_y * linesize + src_x;
+     ptr_y  = ref_picture[0] + src_y   * linesize   + src_x;
      ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
      ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
  
-     if(   (unsigned)src_x > h_edge_pos                 - (!!sx) - 2*block_s
-        || (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){
-             s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
-                              src_x, src_y<<field_based, h_edge_pos, v_edge_pos);
-             ptr_y = s->edge_emu_buffer;
-             if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
-                 uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
-                 s->dsp.emulated_edge_mc(uvbuf  , ptr_cb, s->uvlinesize, 9, 9+field_based,
-                                  uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1);
-                 s->dsp.emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based,
-                                  uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1);
-                 ptr_cb= uvbuf;
-                 ptr_cr= uvbuf+16;
-             }
+     if ((unsigned) src_x >  h_edge_pos - (!!sx) - 2 * block_s ||
+         (unsigned) src_y > (v_edge_pos >> field_based) - (!!sy) - h) {
+         s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
+                                 s->linesize, 17, 17 + field_based,
+                                 src_x, src_y << field_based, h_edge_pos,
+                                 v_edge_pos);
+         ptr_y = s->edge_emu_buffer;
+         if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
+             uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize;
+             s->dsp.emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9,
+                                     9 + field_based,
+                                     uvsrc_x, uvsrc_y << field_based,
+                                     h_edge_pos >> 1, v_edge_pos >> 1);
+             s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9,
+                                     9 + field_based,
+                                     uvsrc_x, uvsrc_y << field_based,
+                                     h_edge_pos >> 1, v_edge_pos >> 1);
+             ptr_cb = uvbuf;
+             ptr_cr = uvbuf + 16;
+         }
      }
  
-     if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
-         dest_y += s->linesize;
-         dest_cb+= s->uvlinesize;
-         dest_cr+= s->uvlinesize;
+     // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
+     if (bottom_field) {
+         dest_y  += s->linesize;
+         dest_cb += s->uvlinesize;
+         dest_cr += s->uvlinesize;
      }
  
-     if(field_select){
-         ptr_y += s->linesize;
-         ptr_cb+= s->uvlinesize;
-         ptr_cr+= s->uvlinesize;
+     if (field_select) {
+         ptr_y   += s->linesize;
+         ptr_cb  += s->uvlinesize;
+         ptr_cr  += s->uvlinesize;
      }
  
-     sx= (sx << 2) >> lowres;
-     sy= (sy << 2) >> lowres;
-     pix_op[lowres-1](dest_y, ptr_y, linesize, h, sx, sy);
+     sx = (sx << 2) >> lowres;
+     sy = (sy << 2) >> lowres;
+     pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy);
  
-     if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
-         uvsx= (uvsx << 2) >> lowres;
-         uvsy= (uvsy << 2) >> lowres;
-         if(h >> s->chroma_y_shift){
+     if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
+         uvsx = (uvsx << 2) >> lowres;
+         uvsy = (uvsy << 2) >> lowres;
 -        pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift,
 -                         uvsx, uvsy);
 -        pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift,
 -                         uvsx, uvsy);
++        if (h >> s->chroma_y_shift) {
 +            pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +            pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +        }
      }
-     //FIXME h261 lowres loop filter
+     // FIXME h261 lowres loop filter
  }
  
  static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
Simple merge
Simple merge
@@@ -21,8 -21,8 +21,8 @@@
  #define AVCODEC_VERSION_H
  
  #define LIBAVCODEC_VERSION_MAJOR 53
- #define LIBAVCODEC_VERSION_MINOR 47
 -#define LIBAVCODEC_VERSION_MINOR 31
 -#define LIBAVCODEC_VERSION_MICRO  0
++#define LIBAVCODEC_VERSION_MINOR 48
 +#define LIBAVCODEC_VERSION_MICRO 100
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                 LIBAVCODEC_VERSION_MINOR, \
index 2010040,0000000..2850c4d
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,75 @@@
- void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
 +/*
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * libavcodec/libavfilter gluing utilities
 + */
 +
 +#include "avcodec.h"
 +
++int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
 +{
 +    dst->pts    = src->pts;
 +    dst->pos    = src->pkt_pos;
 +    dst->format = src->format;
 +
 +    switch (dst->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        dst->video->w                   = src->width;
 +        dst->video->h                   = src->height;
 +        dst->video->sample_aspect_ratio = src->sample_aspect_ratio;
 +        dst->video->interlaced          = src->interlaced_frame;
 +        dst->video->top_field_first     = src->top_field_first;
 +        dst->video->key_frame           = src->key_frame;
 +        dst->video->pict_type           = src->pict_type;
 +    }
++
++    return 0;
 +}
 +
 +AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame,
 +                                                            int perms)
 +{
 +    AVFilterBufferRef *picref =
 +        avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, perms,
 +                                                  frame->width, frame->height,
 +                                                  frame->format);
 +    if (!picref)
 +        return NULL;
 +    avfilter_copy_frame_props(picref, frame);
 +    return picref;
 +}
 +
 +int avfilter_fill_frame_from_video_buffer_ref(AVFrame *frame,
 +                                              const AVFilterBufferRef *picref)
 +{
 +    if (!picref || !picref->video || !frame)
 +        return AVERROR(EINVAL);
 +
 +    memcpy(frame->data,     picref->data,     sizeof(frame->data));
 +    memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize));
 +    frame->pkt_pos          = picref->pos;
 +    frame->interlaced_frame = picref->video->interlaced;
 +    frame->top_field_first  = picref->video->top_field_first;
 +    frame->key_frame        = picref->video->key_frame;
 +    frame->pict_type        = picref->video->pict_type;
 +    frame->sample_aspect_ratio = picref->video->sample_aspect_ratio;
 +
 +    return 0;
 +}
index dec5ae4,0000000..22dd1a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,71 -1,0 +1,71 @@@
- void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
 +/*
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#ifndef AVFILTER_AVCODEC_H
 +#define AVFILTER_AVCODEC_H
 +
 +/**
 + * @file
 + * libavcodec/libavfilter gluing utilities
 + *
 + * This should be included in an application ONLY if the installed
 + * libavfilter has been compiled with libavcodec support, otherwise
 + * symbols defined below will not be available.
 + */
 +
 +#include "libavcodec/avcodec.h" // AVFrame
 +#include "avfilter.h"
 +#include "vsrc_buffer.h"
 +
 +/**
 + * Copy the frame properties of src to dst, without copying the actual
 + * image data.
 + */
++int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
 +
 +/**
 + * Create and return a picref reference from the data and properties
 + * contained in frame.
 + *
 + * @param perms permissions to assign to the new buffer reference
 + */
 +AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame, int perms);
 +
 +/**
 + * Fill an AVFrame with the information stored in picref.
 + *
 + * @param frame an already allocated AVFrame
 + * @param picref a video buffer reference
 + * @return 0 in case of success, a negative AVERROR code in case of
 + * failure
 + */
 +int avfilter_fill_frame_from_video_buffer_ref(AVFrame *frame,
 +                                              const AVFilterBufferRef *picref);
 +
 +/**
 + * Add frame data to buffer_src.
 + *
 + * @param buffer_src pointer to a buffer source context
 + * @param flags a combination of AV_VSRC_BUF_FLAG_* flags
 + * @return >= 0 in case of success, a negative AVERROR code in case of
 + * failure
 + */
 +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src,
 +                             const AVFrame *frame, int flags);
 +
 +#endif /* AVFILTER_AVCODEC_H */
  #include "libavutil/samplefmt.h"
  #include "libavutil/pixfmt.h"
  #include "libavutil/rational.h"
+ #include "libavcodec/avcodec.h"
  
  #define LIBAVFILTER_VERSION_MAJOR  2
- #define LIBAVFILTER_VERSION_MINOR 53
 -#define LIBAVFILTER_VERSION_MINOR  14
 -#define LIBAVFILTER_VERSION_MICRO  0
++#define LIBAVFILTER_VERSION_MINOR 54
 +#define LIBAVFILTER_VERSION_MICRO 100
  
  #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                 LIBAVFILTER_VERSION_MINOR, \
index 840000f,0000000..a0b427d
mode 100644,000000..100644
--- /dev/null
@@@ -1,470 -1,0 +1,471 @@@
 +/*
 + * Copyright (c) 2010 Stefano Sabatini
 + * Copyright (c) 2008 Victor Paesa
 + *
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * movie video source
 + *
 + * @todo use direct rendering (no allocation of a new frame)
 + * @todo support a PTS correction mechanism
 + * @todo support more than one output stream
 + */
 +
 +/* #define DEBUG */
 +
 +#include <float.h>
 +#include "libavutil/avstring.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/imgutils.h"
 +#include "libavformat/avformat.h"
 +#include "avcodec.h"
 +#include "avfilter.h"
 +
 +typedef struct {
 +    /* common A/V fields */
 +    const AVClass *class;
 +    int64_t seek_point;   ///< seekpoint in microseconds
 +    double seek_point_d;
 +    char *format_name;
 +    char *file_name;
 +    int stream_index;
 +
 +    AVFormatContext *format_ctx;
 +    AVCodecContext *codec_ctx;
 +    int is_done;
 +    AVFrame *frame;   ///< video frame to store the decoded images in
 +
 +    /* video-only fields */
 +    int w, h;
 +    AVFilterBufferRef *picref;
 +
 +    /* audio-only fields */
 +    int bps;            ///< bytes per sample
 +    AVPacket pkt, pkt0;
 +    AVFilterBufferRef *samplesref;
 +} MovieContext;
 +
 +#define OFFSET(x) offsetof(MovieContext, x)
 +
 +static const AVOption movie_options[]= {
 +{"format_name",  "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MIN, CHAR_MAX },
 +{"f",            "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MIN, CHAR_MAX },
 +{"stream_index", "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    {.dbl = -1},  -1,       INT_MAX  },
 +{"si",           "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    {.dbl = -1},  -1,       INT_MAX  },
 +{"seek_point",   "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl =  0},  0,        (INT64_MAX-1) / 1000000 },
 +{"sp",           "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl =  0},  0,        (INT64_MAX-1) / 1000000 },
 +{NULL},
 +};
 +
 +static const char *movie_get_name(void *ctx)
 +{
 +    return "movie";
 +}
 +
 +static const AVClass movie_class = {
 +    "MovieContext",
 +    movie_get_name,
 +    movie_options
 +};
 +
 +static av_cold int movie_common_init(AVFilterContext *ctx, const char *args, void *opaque,
 +                                     enum AVMediaType type)
 +{
 +    MovieContext *movie = ctx->priv;
 +    AVInputFormat *iformat = NULL;
 +    AVCodec *codec;
 +    int64_t timestamp;
 +    int ret;
 +
 +    movie->class = &movie_class;
 +    av_opt_set_defaults(movie);
 +
 +    if (args)
 +        movie->file_name = av_get_token(&args, ":");
 +    if (!movie->file_name || !*movie->file_name) {
 +        av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if (*args++ == ':' && (ret = av_set_options_string(movie, args, "=", ":")) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
 +        return ret;
 +    }
 +
 +    movie->seek_point = movie->seek_point_d * 1000000 + 0.5;
 +
 +    av_register_all();
 +
 +    // Try to find the movie format (container)
 +    iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;
 +
 +    movie->format_ctx = NULL;
 +    if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "Failed to avformat_open_input '%s'\n", movie->file_name);
 +        return ret;
 +    }
 +    if ((ret = avformat_find_stream_info(movie->format_ctx, NULL)) < 0)
 +        av_log(ctx, AV_LOG_WARNING, "Failed to find stream info\n");
 +
 +    // if seeking requested, we execute it
 +    if (movie->seek_point > 0) {
 +        timestamp = movie->seek_point;
 +        // add the stream start time, should it exist
 +        if (movie->format_ctx->start_time != AV_NOPTS_VALUE) {
 +            if (timestamp > INT64_MAX - movie->format_ctx->start_time) {
 +                av_log(ctx, AV_LOG_ERROR,
 +                       "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
 +                       movie->file_name, movie->format_ctx->start_time, movie->seek_point);
 +                return AVERROR(EINVAL);
 +            }
 +            timestamp += movie->format_ctx->start_time;
 +        }
 +        if ((ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD)) < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",
 +                   movie->file_name, timestamp);
 +            return ret;
 +        }
 +    }
 +
 +    /* select the media stream */
 +    if ((ret = av_find_best_stream(movie->format_ctx, type,
 +                                   movie->stream_index, -1, NULL, 0)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "No %s stream with index '%d' found\n",
 +               av_get_media_type_string(type), movie->stream_index);
 +        return ret;
 +    }
 +    movie->stream_index = ret;
 +    movie->codec_ctx = movie->format_ctx->streams[movie->stream_index]->codec;
 +
 +    /*
 +     * So now we've got a pointer to the so-called codec context for our video
 +     * stream, but we still have to find the actual codec and open it.
 +     */
 +    codec = avcodec_find_decoder(movie->codec_ctx->codec_id);
 +    if (!codec) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to find any codec\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if ((ret = avcodec_open2(movie->codec_ctx, codec, NULL)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n");
 +        return ret;
 +    }
 +
 +    av_log(ctx, AV_LOG_INFO, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",
 +           movie->seek_point, movie->format_name, movie->file_name,
 +           movie->stream_index);
 +
 +    if (!(movie->frame = avcodec_alloc_frame()) ) {
 +        av_log(ctx, AV_LOG_ERROR, "Failed to alloc frame\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void movie_common_uninit(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +
 +    av_free(movie->file_name);
 +    av_free(movie->format_name);
 +    if (movie->codec_ctx)
 +        avcodec_close(movie->codec_ctx);
 +    if (movie->format_ctx)
 +        avformat_close_input(&movie->format_ctx);
 +
 +    avfilter_unref_buffer(movie->picref);
 +    av_freep(&movie->frame);
 +
 +    avfilter_unref_buffer(movie->samplesref);
 +}
 +
 +#if CONFIG_MOVIE_FILTER
 +
 +static av_cold int movie_init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    MovieContext *movie = ctx->priv;
 +    int ret;
 +
 +    if ((ret = movie_common_init(ctx, args, opaque, AVMEDIA_TYPE_VIDEO)) < 0)
 +        return ret;
 +
 +    movie->w = movie->codec_ctx->width;
 +    movie->h = movie->codec_ctx->height;
 +
 +    return 0;
 +}
 +
 +static int movie_query_formats(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +    enum PixelFormat pix_fmts[] = { movie->codec_ctx->pix_fmt, PIX_FMT_NONE };
 +
 +    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
 +    return 0;
 +}
 +
 +static int movie_config_output_props(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +
 +    outlink->w = movie->w;
 +    outlink->h = movie->h;
 +    outlink->time_base = movie->format_ctx->streams[movie->stream_index]->time_base;
 +
 +    return 0;
 +}
 +
 +static int movie_get_frame(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVPacket pkt;
 +    int ret, frame_decoded;
 +    AVStream *st = movie->format_ctx->streams[movie->stream_index];
 +
 +    if (movie->is_done == 1)
 +        return 0;
 +
 +    while ((ret = av_read_frame(movie->format_ctx, &pkt)) >= 0) {
 +        // Is this a packet from the video stream?
 +        if (pkt.stream_index == movie->stream_index) {
 +            avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt);
 +
 +            if (frame_decoded) {
 +                /* FIXME: avoid the memcpy */
 +                movie->picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE | AV_PERM_PRESERVE |
 +                                                          AV_PERM_REUSE2, outlink->w, outlink->h);
 +                av_image_copy(movie->picref->data, movie->picref->linesize,
 +                              (void*)movie->frame->data,  movie->frame->linesize,
 +                              movie->picref->format, outlink->w, outlink->h);
 +                avfilter_copy_frame_props(movie->picref, movie->frame);
 +
 +                /* FIXME: use a PTS correction mechanism as that in
 +                 * ffplay.c when some API will be available for that */
 +                /* use pkt_dts if pkt_pts is not available */
 +                movie->picref->pts = movie->frame->pkt_pts == AV_NOPTS_VALUE ?
 +                    movie->frame->pkt_dts : movie->frame->pkt_pts;
++
 +                if (!movie->frame->sample_aspect_ratio.num)
 +                    movie->picref->video->sample_aspect_ratio = st->sample_aspect_ratio;
 +                av_dlog(outlink->src,
 +                        "movie_get_frame(): file:'%s' pts:%"PRId64" time:%lf pos:%"PRId64" aspect:%d/%d\n",
 +                        movie->file_name, movie->picref->pts,
 +                        (double)movie->picref->pts * av_q2d(st->time_base),
 +                        movie->picref->pos,
 +                        movie->picref->video->sample_aspect_ratio.num,
 +                        movie->picref->video->sample_aspect_ratio.den);
 +                // We got it. Free the packet since we are returning
 +                av_free_packet(&pkt);
 +
 +                return 0;
 +            }
 +        }
 +        // Free the packet that was allocated by av_read_frame
 +        av_free_packet(&pkt);
 +    }
 +
 +    // On multi-frame source we should stop the mixing process when
 +    // the movie source does not have more frames
 +    if (ret == AVERROR_EOF)
 +        movie->is_done = 1;
 +    return ret;
 +}
 +
 +static int movie_request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterBufferRef *outpicref;
 +    MovieContext *movie = outlink->src->priv;
 +    int ret;
 +
 +    if (movie->is_done)
 +        return AVERROR_EOF;
 +    if ((ret = movie_get_frame(outlink)) < 0)
 +        return ret;
 +
 +    outpicref = avfilter_ref_buffer(movie->picref, ~0);
 +    avfilter_start_frame(outlink, outpicref);
 +    avfilter_draw_slice(outlink, 0, outlink->h, 1);
 +    avfilter_end_frame(outlink);
 +    avfilter_unref_buffer(movie->picref);
 +    movie->picref = NULL;
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_vsrc_movie = {
 +    .name          = "movie",
 +    .description   = NULL_IF_CONFIG_SMALL("Read from a movie source."),
 +    .priv_size     = sizeof(MovieContext),
 +    .init          = movie_init,
 +    .uninit        = movie_common_uninit,
 +    .query_formats = movie_query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_VIDEO,
 +                                    .request_frame   = movie_request_frame,
 +                                    .config_props    = movie_config_output_props, },
 +                                  { .name = NULL}},
 +};
 +
 +#endif  /* CONFIG_MOVIE_FILTER */
 +
 +#if CONFIG_AMOVIE_FILTER
 +
 +static av_cold int amovie_init(AVFilterContext *ctx, const char *args, void *opaque)
 +{
 +    MovieContext *movie = ctx->priv;
 +    int ret;
 +
 +    if ((ret = movie_common_init(ctx, args, opaque, AVMEDIA_TYPE_AUDIO)) < 0)
 +        return ret;
 +
 +    movie->bps = av_get_bytes_per_sample(movie->codec_ctx->sample_fmt);
 +    return 0;
 +}
 +
 +static int amovie_query_formats(AVFilterContext *ctx)
 +{
 +    MovieContext *movie = ctx->priv;
 +    AVCodecContext *c = movie->codec_ctx;
 +
 +    enum AVSampleFormat sample_fmts[] = { c->sample_fmt, -1 };
 +    int packing_fmts[] = { AVFILTER_PACKED, -1 };
 +    int64_t chlayouts[] = { c->channel_layout ? c->channel_layout :
 +                            av_get_default_channel_layout(c->channels), -1 };
 +
 +    avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
 +    avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
 +    avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
 +
 +    return 0;
 +}
 +
 +static int amovie_config_output_props(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVCodecContext *c = movie->codec_ctx;
 +
 +    outlink->sample_rate = c->sample_rate;
 +    outlink->time_base = movie->format_ctx->streams[movie->stream_index]->time_base;
 +
 +    return 0;
 +}
 +
 +static int amovie_get_samples(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    AVPacket pkt;
 +    int ret, got_frame = 0;
 +
 +    if (!movie->pkt.size && movie->is_done == 1)
 +        return AVERROR_EOF;
 +
 +    /* check for another frame, in case the previous one was completely consumed */
 +    if (!movie->pkt.size) {
 +        while ((ret = av_read_frame(movie->format_ctx, &pkt)) >= 0) {
 +            // Is this a packet from the selected stream?
 +            if (pkt.stream_index != movie->stream_index) {
 +                av_free_packet(&pkt);
 +                continue;
 +            } else {
 +                movie->pkt0 = movie->pkt = pkt;
 +                break;
 +            }
 +        }
 +
 +        if (ret == AVERROR_EOF) {
 +            movie->is_done = 1;
 +            return ret;
 +        }
 +    }
 +
 +    /* decode and update the movie pkt */
 +    avcodec_get_frame_defaults(movie->frame);
 +    ret = avcodec_decode_audio4(movie->codec_ctx, movie->frame, &got_frame, &movie->pkt);
 +    if (ret < 0) {
 +        movie->pkt.size = 0;
 +        return ret;
 +    }
 +    movie->pkt.data += ret;
 +    movie->pkt.size -= ret;
 +
 +    /* wrap the decoded data in a samplesref */
 +    if (got_frame) {
 +        int nb_samples = movie->frame->nb_samples;
 +        int data_size =
 +            av_samples_get_buffer_size(NULL, movie->codec_ctx->channels,
 +                                       nb_samples, movie->codec_ctx->sample_fmt, 1);
 +        if (data_size < 0)
 +            return data_size;
 +        movie->samplesref =
 +            avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
 +        memcpy(movie->samplesref->data[0], movie->frame->data[0], data_size);
 +        movie->samplesref->pts = movie->pkt.pts;
 +        movie->samplesref->pos = movie->pkt.pos;
 +        movie->samplesref->audio->sample_rate = movie->codec_ctx->sample_rate;
 +    }
 +
 +    // We got it. Free the packet since we are returning
 +    if (movie->pkt.size <= 0)
 +        av_free_packet(&movie->pkt0);
 +
 +    return 0;
 +}
 +
 +static int amovie_request_frame(AVFilterLink *outlink)
 +{
 +    MovieContext *movie = outlink->src->priv;
 +    int ret;
 +
 +    if (movie->is_done)
 +        return AVERROR_EOF;
 +    do {
 +        if ((ret = amovie_get_samples(outlink)) < 0)
 +            return ret;
 +    } while (!movie->samplesref);
 +
 +    avfilter_filter_samples(outlink, avfilter_ref_buffer(movie->samplesref, ~0));
 +    avfilter_unref_buffer(movie->samplesref);
 +    movie->samplesref = NULL;
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_asrc_amovie = {
 +    .name          = "amovie",
 +    .description   = NULL_IF_CONFIG_SMALL("Read audio from a movie source."),
 +    .priv_size     = sizeof(MovieContext),
 +    .init          = amovie_init,
 +    .uninit        = movie_common_uninit,
 +    .query_formats = amovie_query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) {{ .name = NULL }},
 +    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
 +                                    .type            = AVMEDIA_TYPE_AUDIO,
 +                                    .request_frame   = amovie_request_frame,
 +                                    .config_props    = amovie_config_output_props, },
 +                                  { .name = NULL}},
 +};
 +
 +#endif /* CONFIG_AMOVIE_FILTER */
@@@ -24,8 -24,7 +24,9 @@@
   */
  
  #include "avfilter.h"
 +#include "internal.h"
 +#include "avcodec.h"
+ #include "buffersrc.h"
  #include "vsrc_buffer.h"
  #include "libavutil/imgutils.h"
  
@@@ -112,25 -61,23 +113,42 @@@ int av_vsrc_buffer_add_video_buffer_ref
      return 0;
  }
  
 -    if (c->buf) {
+ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
+ {
+     BufferSourceContext *c = s->priv;
 -    c->buf = buf;
++    if (c->picref) {
+         av_log(s, AV_LOG_ERROR,
+                "Buffering several frames is not supported. "
+                "Please consume all available frames before adding a new one.\n"
+             );
+         return AVERROR(EINVAL);
+     }
++    c->picref = buf;
+     return 0;
+ }
 +#if CONFIG_AVCODEC
 +#include "avcodec.h"
 +
 +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src,
 +                             const AVFrame *frame, int flags)
 +{
 +    int ret;
 +    AVFilterBufferRef *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;