On 2013-02-13 19:48:32 +0100, Anton Khirnov wrote:
> ---
>  libavcodec/avcodec.h       |  123 +++++++++-
>  libavcodec/internal.h      |   49 ++--
>  libavcodec/options.c       |    4 +-
>  libavcodec/options_table.h |    1 +
>  libavcodec/pthread.c       |    2 -
>  libavcodec/utils.c         |  578 
> +++++++++++++++++++++++++++-----------------
>  libavcodec/version.h       |    3 +
>  7 files changed, 505 insertions(+), 255 deletions(-)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 4dde26c..589b750 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -823,6 +823,7 @@ typedef struct AVPanScan{
>  #define FF_QSCALE_TYPE_H264  2
>  #define FF_QSCALE_TYPE_VP56  3
>  
> +#if FF_API_GET_BUFFER
>  #define FF_BUFFER_TYPE_INTERNAL 1
>  #define FF_BUFFER_TYPE_USER     2 ///< direct rendering buffers (image is 
> (de)allocated by user)
>  #define FF_BUFFER_TYPE_SHARED   4 ///< Buffer from somewhere else; don't 
> deallocate image (data/base), all other tables are not shared.
> @@ -832,6 +833,12 @@ typedef struct AVPanScan{
>  #define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer.
>  #define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content.
>  #define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer 
> (update).
> +#endif
> +
> +/**
> + * The decoder will keep a reference to the frame and may reuse it later.
> + */
> +#define AV_GET_BUFFER_FLAG_REF (1 << 0)
>  
>  /**
>   * @defgroup lavc_packet AVPacket
> @@ -1859,6 +1866,7 @@ typedef struct AVCodecContext {
>       */
>      enum AVSampleFormat request_sample_fmt;
>  
> +#if FF_API_GET_BUFFER
>      /**
>       * Called at the beginning of each frame to get a buffer for it.
>       *
> @@ -1918,7 +1926,10 @@ typedef struct AVCodecContext {
>       *
>       * - encoding: unused
>       * - decoding: Set by libavcodec, user can override.
> +     *
> +     * @deprecated use get_buffer2()
>       */
> +    attribute_deprecated
>      int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic);
>  
>      /**
> @@ -1929,7 +1940,10 @@ typedef struct AVCodecContext {
>       * but not by more than one thread at once, so does not need to be 
> reentrant.
>       * - encoding: unused
>       * - decoding: Set by libavcodec, user can override.
> +     *
> +     * @deprecated custom freeing callbacks should be set from get_buffer2()
>       */
> +    attribute_deprecated
>      void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic);
>  
>      /**
> @@ -1944,8 +1958,100 @@ typedef struct AVCodecContext {
>       * - encoding: unused
>       * - decoding: Set by libavcodec, user can override.
>       */
> +    attribute_deprecated
>      int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic);
> +#endif
>  
> +    /**
> +     * This callback is called at the beginning of each frame to get data
> +     * buffer(s) for it. There may be one contiguous buffer for all the data 
> or
> +     * there may be a buffer per each data plane or anything in between. Each
> +     * buffer must be reference-counted using the AVBuffer API.
> +     *
> +     * The following fields will be set in the frame before this callback is
> +     * called:
> +     * - format
> +     * - width, height (video only)
> +     * - sample_rate, channel_layout, nb_samples (audio only)
> +     * Their values may differ from the corresponding values in
> +     * AVCodecContext. This callback must use the frame values, not the codec
> +     * context values, to calculate the required buffer size.
> +     *
> +     * This callback must fill the following fields in the frame:
> +     * - data[]
> +     * - linesize[]
> +     * - extended_data:
> +     *   * if the data is planar audio with more than 8 channels, then this
> +     *     callback must allocate and fill extended_data to contain all 
> pointers
> +     *     to all data planes. data[] must hold as many pointers as it can.
> +     *     extended_data must be allocated with av_malloc() and will be 
> freed in
> +     *     av_frame_unref().
> +     *   * otherwise exended_data must point to data
> +     * - buf[] must contain references to the buffers that contain the frame
> +     *   data.
> +     * - extended_buf and nb_extended_buf must be allocated with av_malloc() 
> by
> +     *   this callback and filled with the extra buffers if there are more
> +     *   buffers than buf[] can hold. extended_buf will be freed in
> +     *   av_frame_unref().
> +     *
> +     * If CODEC_CAP_DR1 is not set then get_buffer2() must call
> +     * avcodec_default_get_buffer2() instead of providing buffers allocated 
> by
> +     * some other means.
> +     *
> +     * Each data plane must be aligned to the maximum required by the target
> +     * CPU.
> +     *
> +     * @see avcodec_default_get_buffer2()
> +     *
> +     * Video:
> +     *
> +     * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused
> +     * (read and/or written to if it is writable) later by libavcodec.
> +     *
> +     * If CODEC_FLAG_EMU_EDGE is not set in s->flags, the buffer must 
> contain an
> +     * edge of the size returned by avcodec_get_edge_width() on all sides
> +     *
> +     * avcodec_align_dimensions2() should be used to find the required width 
> and
> +     * height, as they normally need to be rounded up to the next multiple 
> of 16.
> +     *
> +     * If frame multithreading is used and thread_safe_callbacks is set,
> +     * this callback may be called from a different thread, but not from more
> +     * than one at once. Does not need to be reentrant.

Are you sure the last part is true? It's probably true since we have to
guarantee that get_buffer is always called before finish_setup for
non-thread safe callbacks but it seems to be an odd and unecessary
limitation. Who writes thread-safe but not reentrant safe functions?

> +     *
> +     * @see avcodec_align_dimensions2()
> +     *
> +     * Audio:
> +     *
> +     * Decoders request a buffer of a particular size by setting
> +     * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may,
> +     * however, utilize only part of the buffer by setting AVFrame.nb_samples
> +     * to a smaller value in the output frame.
> +     *
> +     * As a convenience, av_samples_get_buffer_size() and
> +     * av_samples_fill_arrays() in libavutil may be used by custom 
> get_buffer2()
> +     * functions to find the required data size and to fill data pointers and
> +     * linesize. In AVFrame.linesize, only linesize[0] may be set for audio
> +     * since all planes must be the same size.
> +     *
> +     * @see av_samples_get_buffer_size(), av_samples_fill_arrays()
> +     *
> +     * - encoding: unused
> +     * - decoding: Set by libavcodec, user can override.
> +     */
> +    int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags);

ahem, you have to extend AVCodecContext at the end for ABI compatibility

> +
> +    /**
> +     * If non-zero, the decoded audio and video frames returned from
> +     * avcodec_decode_video2() and avcodec_decode_audio4() are 
> reference-counted
> +     * and are valid indefinitely. The caller must free them with
> +     * av_frame_unref() when they are not needed anymore.
> +     * Otherwise, the decoded frames must not be freed by the caller and are
> +     * only valid until the next decode call.
> +     *
> +     * - encoding: unused
> +     * - decoding: set by the caller before avcodec_open2().
> +     */
> +    int refcounted_frames;
>  
>      /* - encoding parameters */
>      float qcompress;  ///< amount of qscale change between easy & hard 
> scenes (0.0-1.0)
> @@ -3208,9 +3314,18 @@ AVCodec *avcodec_find_decoder(enum AVCodecID id);
>   */
>  AVCodec *avcodec_find_decoder_by_name(const char *name);
>  
> -int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic);
> -void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic);
> -int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic);
> +#if FF_API_GET_BUFFER
> +attribute_deprecated int avcodec_default_get_buffer(AVCodecContext *s, 
> AVFrame *pic);
> +attribute_deprecated void avcodec_default_release_buffer(AVCodecContext *s, 
> AVFrame *pic);
> +attribute_deprecated int avcodec_default_reget_buffer(AVCodecContext *s, 
> AVFrame *pic);
> +#endif
> +
> +/**
> + * The default callback for AVCodecContext.get_buffer2(). It is made public 
> so
> + * it can be called by custom get_buffer2() implementations for decoders 
> without
> + * CODEC_CAP_DR1 set.
> + */
> +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int 
> flags);
>  
>  /**
>   * Return the amount of padding in pixels which the get_buffer callback must
> @@ -4141,8 +4256,6 @@ int avcodec_fill_audio_frame(AVFrame *frame, int 
> nb_channels,
>   */
>  void avcodec_flush_buffers(AVCodecContext *avctx);
>  
> -void avcodec_default_free_buffers(AVCodecContext *s);
> -

removing a public exported function without major bump

>  /**
>   * Return codec bits per sample.
>   *
> diff --git a/libavcodec/internal.h b/libavcodec/internal.h
> index 069a855..8e64640 100644
> --- a/libavcodec/internal.h
> +++ b/libavcodec/internal.h
> @@ -26,34 +26,33 @@
>  
>  #include <stdint.h>
>  
> +#include "libavutil/buffer.h"
>  #include "libavutil/mathematics.h"
>  #include "libavutil/pixfmt.h"
>  #include "avcodec.h"
>  
>  #define FF_SANE_NB_CHANNELS 128U
>  
> -typedef struct InternalBuffer {
> -    uint8_t *base[AV_NUM_DATA_POINTERS];
> -    uint8_t *data[AV_NUM_DATA_POINTERS];
> -    int linesize[AV_NUM_DATA_POINTERS];
> -    int width;
> -    int height;
> -    enum AVPixelFormat pix_fmt;
> -} InternalBuffer;
> -
> -typedef struct AVCodecInternal {
> +typedef struct FramePool {
>      /**
> -     * internal buffer count
> -     * used by default get/release/reget_buffer().
> +     * Pools for each data plane. For audio all the planes have the same 
> size,
> +     * so only pools[0] is used.
>       */
> -    int buffer_count;
> +    AVBufferPool *pools[4];
>  
> -    /**
> -     * internal buffers
> -     * used by default get/release/reget_buffer().
> +    /*
> +     * Pool parameters
>       */
> -    InternalBuffer *buffer;
> +    int format;
> +    int width, height;
> +    int stride_align[AV_NUM_DATA_POINTERS];
> +    int linesize[4];
> +    int planes;
> +    int channels;
> +    int samples;
> +} FramePool;
>  
> +typedef struct AVCodecInternal {
>      /**
>       * Whether the parent AVCodecContext is a copy of the context which had
>       * init() called on it.
> @@ -76,11 +75,9 @@ typedef struct AVCodecInternal {
>       */
>      int last_audio_frame;
>  
> -    /**
> -     * The data for the last allocated audio frame.
> -     * Stored here so we can free it.
> -     */
> -    uint8_t *audio_data;
> +    AVFrame to_free;
> +
> +    FramePool *pool;
>  } AVCodecInternal;
>  
>  struct AVCodecDefault {
> @@ -149,6 +146,12 @@ static av_always_inline int64_t 
> ff_samples_to_time_base(AVCodecContext *avctx,
>   * AVCodecContext.get_buffer() and should be used instead calling 
> get_buffer()
>   * directly.
>   */
> -int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame);
> +int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags);
> +
> +/**
> + * Identical in function to av_frame_make_writable(), except it uses
> + * ff_get_buffer() to allocate the buffer when needed.
> + */
> +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame);
>  
>  #endif /* AVCODEC_INTERNAL_H */
> diff --git a/libavcodec/options.c b/libavcodec/options.c
> index fc2a184..d140552 100644
> --- a/libavcodec/options.c
> +++ b/libavcodec/options.c
> @@ -88,8 +88,7 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const 
> AVCodec *codec)
>      av_opt_set_defaults(s);
>  
>      s->time_base           = (AVRational){0,1};
> -    s->get_buffer          = avcodec_default_get_buffer;
> -    s->release_buffer      = avcodec_default_release_buffer;
> +    s->get_buffer2         = avcodec_default_get_buffer2;
>      s->get_format          = avcodec_default_get_format;
>      s->execute             = avcodec_default_execute;
>      s->execute2            = avcodec_default_execute2;
> @@ -97,7 +96,6 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const 
> AVCodec *codec)
>      s->pix_fmt             = AV_PIX_FMT_NONE;
>      s->sample_fmt          = AV_SAMPLE_FMT_NONE;
>  
> -    s->reget_buffer        = avcodec_default_reget_buffer;
>      s->reordered_opaque    = AV_NOPTS_VALUE;
>      if(codec && codec->priv_data_size){
>          if(!s->priv_data){
> diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
> index 7d0795a..28ce352 100644
> --- a/libavcodec/options_table.h
> +++ b/libavcodec/options_table.h
> @@ -403,6 +403,7 @@ static const AVOption options[]={
>  {"s32p", "32-bit signed integer planar",  0, AV_OPT_TYPE_CONST, {.i64 = 
> AV_SAMPLE_FMT_S32P }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
>  {"fltp", "32-bit float planar",           0, AV_OPT_TYPE_CONST, {.i64 = 
> AV_SAMPLE_FMT_FLTP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
>  {"dblp", "64-bit double planar",          0, AV_OPT_TYPE_CONST, {.i64 = 
> AV_SAMPLE_FMT_DBLP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
> +{"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_INT, 
> {.i64 = 0}, 0, 1, A|V|D },
>  {NULL},
>  };
>  
> diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
> index 751fca8..82df03c 100644
> --- a/libavcodec/pthread.c
> +++ b/libavcodec/pthread.c
> @@ -760,8 +760,6 @@ static void frame_thread_free(AVCodecContext *avctx, int 
> thread_count)
>      for (i = 0; i < thread_count; i++) {
>          PerThreadContext *p = &fctx->threads[i];
>  
> -        avcodec_default_free_buffers(p->avctx);
> -
>          pthread_mutex_destroy(&p->mutex);
>          pthread_mutex_destroy(&p->progress_mutex);
>          pthread_cond_destroy(&p->input_cond);
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index 27e9cfe..253290c 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -29,6 +29,7 @@
>  #include "libavutil/avstring.h"
>  #include "libavutil/channel_layout.h"
>  #include "libavutil/crc.h"
> +#include "libavutil/frame.h"
>  #include "libavutil/mathematics.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/imgutils.h"
> @@ -154,8 +155,6 @@ void avcodec_set_dimensions(AVCodecContext *s, int width, 
> int height)
>      s->height       = height;
>  }
>  
> -#define INTERNAL_BUFFER_SIZE (32 + 1)
> -
>  void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
>                                 int linesize_align[AV_NUM_DATA_POINTERS])
>  {
> @@ -297,87 +296,26 @@ int avcodec_fill_audio_frame(AVFrame *frame, int 
> nb_channels,
>      return ret;
>  }
>  
> -static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> +static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
>  {
> -    AVCodecInternal *avci = avctx->internal;
> -    int buf_size, ret;
> -
> -    av_freep(&avci->audio_data);
> -    buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
> -                                          frame->nb_samples, 
> avctx->sample_fmt,
> -                                          0);
> -    if (buf_size < 0)
> -        return AVERROR(EINVAL);
> -
> -    frame->data[0] = av_mallocz(buf_size);
> -    if (!frame->data[0])
> -        return AVERROR(ENOMEM);
> -
> -    ret = avcodec_fill_audio_frame(frame, avctx->channels, avctx->sample_fmt,
> -                                   frame->data[0], buf_size, 0);
> -    if (ret < 0) {
> -        av_freep(&frame->data[0]);
> -        return ret;
> -    }
> -
> -    avci->audio_data = frame->data[0];
> -    if (avctx->debug & FF_DEBUG_BUFFERS)
> -        av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p, "
> -                                    "internal audio buffer used\n", frame);
> -
> -    return 0;
> -}
> -
> -static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
> -{
> -    int i;
> -    int w = s->width;
> -    int h = s->height;
> -    InternalBuffer *buf;
> -    AVCodecInternal *avci = s->internal;
> -
> -    if (pic->data[0] != NULL) {
> -        av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in 
> avcodec_default_get_buffer\n");
> -        return -1;
> -    }
> -    if (avci->buffer_count >= INTERNAL_BUFFER_SIZE) {
> -        av_log(s, AV_LOG_ERROR, "buffer_count overflow (missing 
> release_buffer?)\n");
> -        return -1;
> -    }
> -
> -    if (av_image_check_size(w, h, 0, s))
> -        return -1;
> -
> -    if (!avci->buffer) {
> -        avci->buffer = av_mallocz((INTERNAL_BUFFER_SIZE + 1) *
> -                                  sizeof(InternalBuffer));
> -    }
> -
> -    buf = &avci->buffer[avci->buffer_count];
> +    FramePool *pool = avctx->internal->pool;
> +    int i, ret;
>  
> -    if (buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt 
> != s->pix_fmt)) {
> -        for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
> -            av_freep(&buf->base[i]);
> -            buf->data[i] = NULL;
> -        }
> -    }
> -
> -    if (!buf->base[0]) {
> -        int h_chroma_shift, v_chroma_shift;
> -        int size[4] = { 0 };
> -        int tmpsize;
> -        int unaligned;
> +    switch (avctx->codec_type) {
> +    case AVMEDIA_TYPE_VIDEO: {
>          AVPicture picture;
> -        int stride_align[AV_NUM_DATA_POINTERS];
> -        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt);
> -        const int pixel_size = desc->comp[0].step_minus1 + 1;
> +        int size[4] = { 0 };
> +        int w = frame->width;
> +        int h = frame->height;
> +        int tmpsize, unaligned;
>  
> -        av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift,
> -                                         &v_chroma_shift);
> +        if (pool->format == frame->format &&
> +            pool->width == frame->width && pool->height == frame->height)
> +            return 0;
>  
> -        avcodec_align_dimensions2(s, &w, &h, stride_align);
> +        avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
>  
> -        if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
> +        if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
>              w += EDGE_WIDTH * 2;
>              h += EDGE_WIDTH * 2;
>          }
> @@ -385,16 +323,17 @@ static int video_get_buffer(AVCodecContext *s, AVFrame 
> *pic)
>          do {
>              // NOTE: do not align linesizes individually, this breaks e.g. 
> assumptions
>              // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 
> 4:2:2
> -            av_image_fill_linesizes(picture.linesize, s->pix_fmt, w);
> +            av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w);
>              // increase alignment of w for next try (rhs gives the lowest 
> bit set in w)
>              w += w & ~(w - 1);
>  
>              unaligned = 0;
>              for (i = 0; i < 4; i++)
> -                unaligned |= picture.linesize[i] % stride_align[i];
> +                unaligned |= picture.linesize[i] % pool->stride_align[i];
>          } while (unaligned);
>  
> -        tmpsize = av_image_fill_pointers(picture.data, s->pix_fmt, h, NULL, 
> picture.linesize);
> +        tmpsize = av_image_fill_pointers(picture.data, avctx->pix_fmt, h,
> +                                         NULL, picture.linesize);
>          if (tmpsize < 0)
>              return -1;
>  
> @@ -402,54 +341,156 @@ static int video_get_buffer(AVCodecContext *s, AVFrame 
> *pic)
>              size[i] = picture.data[i + 1] - picture.data[i];
>          size[i] = tmpsize - (picture.data[i] - picture.data[0]);
>  
> -        memset(buf->base, 0, sizeof(buf->base));
> -        memset(buf->data, 0, sizeof(buf->data));
> -
> -        for (i = 0; i < 4 && size[i]; i++) {
> -            const int h_shift = i == 0 ? 0 : h_chroma_shift;
> -            const int v_shift = i == 0 ? 0 : v_chroma_shift;
> +        for (i = 0; i < 4; i++) {
> +            av_buffer_pool_uninit(&pool->pools[i]);
> +            pool->linesize[i] = picture.linesize[i];
> +            if (size[i]) {
> +                pool->pools[i] = av_buffer_pool_init(size[i], NULL);
> +                if (!pool->pools[i])
> +                    return AVERROR(ENOMEM);
> +            }
> +        }
> +        pool->format = frame->format;
> +        pool->width  = frame->width;
> +        pool->height = frame->height;
>  
> -            buf->linesize[i] = picture.linesize[i];
> +        break;
> +        }
> +    case AVMEDIA_TYPE_AUDIO: {
> +        int ch     = 
> av_get_channel_layout_nb_channels(frame->channel_layout);
> +        int planar = av_sample_fmt_is_planar(frame->format);
> +        int planes = planar ? ch : 1;
> +
> +        if (pool->format == frame->format && pool->planes == planes &&
> +            pool->channels == ch && frame->nb_samples == pool->samples)
> +            return 0;
> +
> +        av_buffer_pool_uninit(&pool->pools[0]);
> +        ret = av_samples_get_buffer_size(&pool->linesize[0], ch,
> +                                         frame->nb_samples, frame->format, 
> 0);
> +        if (ret < 0)
> +            return AVERROR(EINVAL);
>  
> -            buf->base[i] = av_malloc(size[i] + 16); //FIXME 16
> -            if (buf->base[i] == NULL)
> -                return -1;
> +        pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL);
> +        if (!pool->pools[0])
> +            return AVERROR(ENOMEM);
>  
> -            // no edge if EDGE EMU or not planar YUV
> -            if ((s->flags & CODEC_FLAG_EMU_EDGE) || !size[2])
> -                buf->data[i] = buf->base[i];
> -            else
> -                buf->data[i] = buf->base[i] + FFALIGN((buf->linesize[i] * 
> EDGE_WIDTH >> v_shift) + (pixel_size * EDGE_WIDTH >> h_shift), 
> stride_align[i]);
> +        pool->format     = frame->format;
> +        pool->planes     = planes;
> +        pool->channels   = ch;
> +        pool->samples = frame->nb_samples;
> +        break;
>          }
> -        for (; i < AV_NUM_DATA_POINTERS; i++) {
> -            buf->base[i]     = buf->data[i] = NULL;
> -            buf->linesize[i] = 0;
> +    default: av_assert0(0);

if you want to leave the assert in av_assert0(avctx->codec_type == 
AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) would be nicer

> +    }
> +    return 0;
> +}
> +
> +static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> +{
> +    FramePool *pool = avctx->internal->pool;
> +    int planes = pool->planes;
> +    int i;
> +
> +    if (planes > AV_NUM_DATA_POINTERS) {
> +        frame->extended_data = av_mallocz(planes * 
> sizeof(*frame->extended_data));
> +        frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
> +        frame->extended_buf  = av_mallocz(frame->nb_extended_buf *
> +                                          sizeof(*frame->extended_buf));
> +        if (!frame->extended_data || !frame->extended_buf) {
> +            av_freep(&frame->extended_data);
> +            av_freep(&frame->extended_buf);
> +            return AVERROR(ENOMEM);
>          }
> -        if (size[1] && !size[2])
> -            avpriv_set_systematic_pal2((uint32_t *)buf->data[1], s->pix_fmt);
> -        buf->width   = s->width;
> -        buf->height  = s->height;
> -        buf->pix_fmt = s->pix_fmt;
> +    } else
> +        frame->extended_data = frame->data;
> +
> +    for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
> +        frame->buf[i] = av_buffer_alloc_pool(pool->pools[0]);
> +        if (!frame->buf[i])
> +            goto fail;
> +        frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
> +    }
> +    for (i = 0; i < frame->nb_extended_buf; i++) {
> +        frame->extended_buf[i] = av_buffer_alloc_pool(pool->pools[0]);
> +        if (!frame->extended_buf[i])
> +            goto fail;
> +        frame->extended_data[i + AV_NUM_DATA_POINTERS] = 
> frame->extended_buf[i]->data;
>      }
>  
> -    for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
> -        pic->base[i]     = buf->base[i];
> -        pic->data[i]     = buf->data[i];
> -        pic->linesize[i] = buf->linesize[i];
> +    if (avctx->debug & FF_DEBUG_BUFFERS)
> +        av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", 
> frame);
> +
> +    return 0;
> +fail:
> +    av_frame_unref(frame);
> +    return AVERROR(ENOMEM);
> +}
> +
> +static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
> +{
> +    FramePool *pool = s->internal->pool;
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
> +    int pixel_size = desc->comp[0].step_minus1 + 1;
> +    int h_chroma_shift, v_chroma_shift;
> +    int i;
> +
> +    if (pic->data[0] != NULL) {
> +        av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in 
> avcodec_default_get_buffer\n");
> +        return -1;
>      }
> +
> +    memset(pic->data, 0, sizeof(pic->data));
>      pic->extended_data = pic->data;
> -    avci->buffer_count++;
> +
> +    av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, 
> &v_chroma_shift);
> +
> +    for (i = 0; i < 4 && pool->pools[i]; i++) {
> +        const int h_shift = i == 0 ? 0 : h_chroma_shift;
> +        const int v_shift = i == 0 ? 0 : v_chroma_shift;
> +
> +        pic->linesize[i] = pool->linesize[i];
> +
> +        pic->buf[i] = av_buffer_alloc_pool(pool->pools[i]);
> +        if (!pic->buf[i])
> +            goto fail;
> +
> +        // no edge if EDGE EMU or not planar YUV

that's probably not a good idea and it would needed to be documented
somewhere else.

> +        if ((s->flags & CODEC_FLAG_EMU_EDGE) || !pool->pools[2])
> +            pic->data[i] = pic->buf[i]->data;
> +        else {
> +            pic->data[i] = pic->buf[i]->data +
> +                FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) +
> +                        (pixel_size * EDGE_WIDTH >> h_shift), 
> pool->stride_align[i]);
> +        }
> +    }
> +    for (; i < AV_NUM_DATA_POINTERS; i++) {
> +        pic->data[i] = NULL;
> +        pic->linesize[i] = 0;
> +    }
> +    if (pic->data[1] && !pic->data[2])
> +        avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt);
>  
>      if (s->debug & FF_DEBUG_BUFFERS)
> -        av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d "
> -                                "buffers used\n", pic, avci->buffer_count);
> +        av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", 
> pic);
>  
>      return 0;
> +fail:
> +    av_frame_unref(pic);
> +    return AVERROR(ENOMEM);
>  }
>  
> -int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> +int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int 
> flags)
>  {
> +    int ret;
> +
> +    if ((ret = update_frame_pool(avctx, frame)) < 0)
> +        return ret;
> +
> +#if FF_API_GET_BUFFER
>      frame->type = FF_BUFFER_TYPE_INTERNAL;
> +#endif
> +
>      switch (avctx->codec_type) {
>      case AVMEDIA_TYPE_VIDEO:
>          return video_get_buffer(avctx, frame);
> @@ -460,14 +501,44 @@ int avcodec_default_get_buffer(AVCodecContext *avctx, 
> AVFrame *frame)
>      }
>  }
>  
> -int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> +#if FF_API_GET_BUFFER
> +int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> +{
> +    return avcodec_default_get_buffer2(avctx, frame, 0);
> +}
> +
> +typedef struct CompatReleaseBufPriv {
> +    AVCodecContext avctx;
> +    AVFrame frame;
> +} CompatReleaseBufPriv;
> +
> +static void compat_free_buffer(void *opaque, uint8_t *data)
> +{
> +    CompatReleaseBufPriv *priv = opaque;
> +    priv->avctx.release_buffer(&priv->avctx, &priv->frame);
> +    av_freep(&priv);
> +}
> +
> +static void compat_release_buffer(void *opaque, uint8_t *data)
> +{
> +    AVBufferRef *buf = opaque;
> +    av_buffer_unref(&buf);
> +}
> +#endif
> +
> +int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
>  {
> +    int ret;
> +
>      switch (avctx->codec_type) {
>      case AVMEDIA_TYPE_VIDEO:
>          frame->width               = avctx->width;
>          frame->height              = avctx->height;
>          frame->format              = avctx->pix_fmt;
>          frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
> +
> +        if ((ret = av_image_check_size(avctx->width, avctx->height, 0, 
> avctx)) < 0)
> +            return ret;
>          break;
>      case AVMEDIA_TYPE_AUDIO:
>          frame->sample_rate    = avctx->sample_rate;
> @@ -480,87 +551,154 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame 
> *frame)
>      frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE;
>      frame->reordered_opaque = avctx->reordered_opaque;
>  
> -    return avctx->get_buffer(avctx, frame);
> -}
> +#if FF_API_GET_BUFFER
> +    /*
> +     * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers.
> +     * We wrap each plane in its own AVBuffer. Each of those has a reference 
> to
> +     * a dummy AVBuffer as its private data, unreffing it on free.
> +     * When all the planes are freed, the dummy buffer's free callback calls
> +     * release_buffer().
> +     */
> +    if (avctx->get_buffer) {
> +        CompatReleaseBufPriv *priv = NULL;
> +        AVBufferRef *dummy_buf = NULL;
> +        int planes, i, ret;
>  
> -void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
> -{
> -    int i;
> -    InternalBuffer *buf, *last;
> -    AVCodecInternal *avci = s->internal;
> +        if (flags & AV_GET_BUFFER_FLAG_REF)
> +            frame->reference    = 1;
>  
> -    assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
> +        ret = avctx->get_buffer(avctx, frame);
> +        if (ret < 0)
> +            return ret;
>  
> -    assert(pic->type == FF_BUFFER_TYPE_INTERNAL);
> -    assert(avci->buffer_count);
> +        /* return if the buffers are already set up
> +         * this would happen e.g. when a custom get_buffer() calls
> +         * avcodec_default_get_buffer
> +         */
> +        if (frame->buf[0])
> +            return 0;
> +
> +        priv = av_mallocz(sizeof(*priv));
> +        if (!priv) {
> +            ret = AVERROR(ENOMEM);
> +            goto fail;
> +        }
> +        priv->avctx = *avctx;
> +        priv->frame = *frame;
>  
> -    if (avci->buffer) {
> -        buf = NULL; /* avoids warning */
> -        for (i = 0; i < avci->buffer_count; i++) { //just 3-5 checks so is 
> not worth to optimize
> -            buf = &avci->buffer[i];
> -            if (buf->data[0] == pic->data[0])
> -                break;
> +        dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0);
> +        if (!dummy_buf) {
> +            ret = AVERROR(ENOMEM);
> +            goto fail;
>          }
> -        assert(i < avci->buffer_count);
> -        avci->buffer_count--;
> -        last = &avci->buffer[avci->buffer_count];
>  
> -        if (buf != last)
> -            FFSWAP(InternalBuffer, *buf, *last);
> -    }
> +#define WRAP_PLANE(ref_out, data, data_size)                            \
> +do {                                                                    \
> +    AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf);                  \
> +    if (!dummy_ref) {                                                   \
> +        ret = AVERROR(ENOMEM);                                          \
> +        goto fail;                                                      \
> +    }                                                                   \
> +    ref_out = av_buffer_create(data, data_size, compat_release_buffer,  \
> +                               dummy_ref, 0);                           \
> +    if (!ref_out) {                                                     \
> +        av_frame_unref(frame);                                          \
> +        ret = AVERROR(ENOMEM);                                          \
> +        goto fail;                                                      \
> +    }                                                                   \
> +} while (0)
> +
> +        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
> +            const AVPixFmtDescriptor *desc = 
> av_pix_fmt_desc_get(frame->format);
> +
> +            if (!desc) {
> +                ret = AVERROR(EINVAL);
> +                goto fail;
> +            }
> +            planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 
> 1;
>  
> -    for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
> -        pic->data[i] = NULL;
> -//        pic->base[i]=NULL;
> +            for (i = 0; i < planes; i++) {
> +                int h_shift    = (i == 1 || i == 2) ? desc->log2_chroma_h : 
> 0;
> +                int plane_size = (frame->width >> h_shift) * 
> frame->linesize[i];
>  
> -    if (s->debug & FF_DEBUG_BUFFERS)
> -        av_log(s, AV_LOG_DEBUG, "default_release_buffer called on pic %p, %d 
> "
> -                                "buffers used\n", pic, avci->buffer_count);
> -}
> +                WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);
> +            }
> +        } else {
> +            int planar = av_sample_fmt_is_planar(frame->format);
> +            planes = planar ? avctx->channels : 1;
> +
> +            if (planes > FF_ARRAY_ELEMS(frame->buf)) {
> +                frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf);
> +                frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) 
> *
> +                                                frame->nb_extended_buf);
> +                if (!frame->extended_buf) {
> +                    ret = AVERROR(ENOMEM);
> +                    goto fail;
> +                }
> +            }
>  
> -int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
> -{
> -    AVFrame temp_pic;
> -    int i;
> +            for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)
> +                WRAP_PLANE(frame->buf[i], frame->extended_data[i], 
> frame->linesize[0]);
>  
> -    assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
> +            for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++)
> +                WRAP_PLANE(frame->extended_buf[i],
> +                           frame->extended_data[i + 
> FF_ARRAY_ELEMS(frame->buf)],
> +                           frame->linesize[0]);
> +        }
> +
> +        av_buffer_unref(&dummy_buf);
> +
> +        return 0;
>  
> -    /* If no picture return a new buffer */
> -    if (pic->data[0] == NULL) {
> -        /* We will copy from buffer, so must be readable */
> -        pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
> -        return ff_get_buffer(s, pic);
> +fail:
> +        avctx->release_buffer(avctx, frame);
> +        av_freep(&priv);
> +        av_buffer_unref(&dummy_buf);
> +        return ret;
>      }
> +#endif
>  
> -    assert(s->pix_fmt == pic->format);
> +    return avctx->get_buffer2(avctx, frame, flags);
> +}
>  
> -    /* If internal buffer type return the same buffer */
> -    if (pic->type == FF_BUFFER_TYPE_INTERNAL) {
> -        if (s->pkt)
> -            pic->pkt_pts = s->pkt->pts;
> -        else
> -            pic->pkt_pts = AV_NOPTS_VALUE;
> -        pic->reordered_opaque = s->reordered_opaque;
> +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
> +{
> +    AVFrame tmp;
> +    int ret;
> +
> +    av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO);
> +
> +    if (!frame->data[0])
> +        return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
> +
> +    if (av_frame_is_writable(frame))
>          return 0;
> -    }
>  
> -    /*
> -     * Not internal type and reget_buffer not overridden, emulate cr buffer
> -     */
> -    temp_pic = *pic;
> -    for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
> -        pic->data[i] = pic->base[i] = NULL;
> -    pic->opaque = NULL;
> -    /* Allocate new frame */
> -    if (ff_get_buffer(s, pic))
> -        return -1;
> -    /* Copy image data from old buffer to new buffer */
> -    av_picture_copy((AVPicture *)pic, (AVPicture *)&temp_pic, s->pix_fmt, 
> s->width,
> -                    s->height);
> -    s->release_buffer(s, &temp_pic); // Release old frame
> +    tmp = *frame;
> +    tmp.extended_data = tmp.data;
> +
> +    ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
> +    if (ret < 0)
> +        return ret;
> +
> +    av_image_copy(frame->data, frame->linesize, tmp.data, tmp.linesize,
> +                  frame->format, frame->width, frame->height);
> +
> +    av_frame_unref(&tmp);
> +
>      return 0;
>  }
>  
> +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
> +{
> +    av_assert0(0);
> +}
> +
> +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
> +{
> +    av_assert0(0);
> +}

a nasty way of deprecating external functions.
avcodec_default_release_buffer() is used third party code. I only
checked mythtv.

> +
>  int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext 
> *c2, void *arg2), void *arg, int *ret, int count, int size)
>  {
>      int i;
> @@ -684,6 +822,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext 
> *avctx, const AVCodec *code
>          goto end;
>      }
>  
> +    avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));
> +    if (!avctx->internal->pool) {
> +        ret = AVERROR(ENOMEM);
> +        goto free_and_end;
> +    }
> +
>      if (codec->priv_data_size > 0) {
>          if (!avctx->priv_data) {
>              avctx->priv_data = av_mallocz(codec->priv_data_size);
> @@ -869,6 +1013,8 @@ end:
>  free_and_end:
>      av_dict_free(&tmp);
>      av_freep(&avctx->priv_data);
> +    if (avctx->internal)
> +        av_freep(&avctx->internal->pool);
>      av_freep(&avctx->internal);
>      avctx->codec = NULL;
>      goto end;
> @@ -1272,6 +1418,7 @@ int attribute_align_arg 
> avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
>                                                int *got_picture_ptr,
>                                                AVPacket *avpkt)
>  {
> +    AVCodecInternal *avci = avctx->internal;
>      int ret;
>  
>      *got_picture_ptr = 0;
> @@ -1283,6 +1430,9 @@ int attribute_align_arg 
> avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
>  
>      avcodec_get_frame_defaults(picture);
>  
> +    if (!avctx->refcounted_frames)
> +        av_frame_unref(&avci->to_free);
> +
>      if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || 
> (avctx->active_thread_type & FF_THREAD_FRAME)) {
>          if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
>              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
> @@ -1302,8 +1452,17 @@ int attribute_align_arg 
> avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
>  
>          emms_c(); //needed to avoid an emms_c() call before every return;
>  
> -        if (*got_picture_ptr)
> +        if (ret < 0 && picture->data[0])
> +            av_frame_unref(picture);
> +
> +        if (*got_picture_ptr) {
> +            if (!avctx->refcounted_frames) {
> +                avci->to_free = *picture;
> +                avci->to_free.extended_data = avci->to_free.data;
> +            }
> +
>              avctx->frame_number++;
> +        }
>      } else
>          ret = 0;
>  
> @@ -1367,6 +1526,7 @@ int attribute_align_arg 
> avcodec_decode_audio4(AVCodecContext *avctx,
>                                                int *got_frame_ptr,
>                                                AVPacket *avpkt)
>  {
> +    AVCodecInternal *avci = avctx->internal;
>      int planar, channels;
>      int ret = 0;
>  
> @@ -1383,6 +1543,9 @@ int attribute_align_arg 
> avcodec_decode_audio4(AVCodecContext *avctx,
>  
>      avcodec_get_frame_defaults(frame);
>  
> +    if (!avctx->refcounted_frames)
> +        av_frame_unref(&avci->to_free);
> +
>      if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
>          ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
>          if (ret >= 0 && *got_frame_ptr) {
> @@ -1390,7 +1553,15 @@ int attribute_align_arg 
> avcodec_decode_audio4(AVCodecContext *avctx,
>              frame->pkt_dts = avpkt->dts;
>              if (frame->format == AV_SAMPLE_FMT_NONE)
>                  frame->format = avctx->sample_fmt;
> +
> +            if (!avctx->refcounted_frames) {
> +                avci->to_free = *frame;
> +                avci->to_free.extended_data = avci->to_free.data;
> +            }
>          }
> +
> +        if (ret < 0 && frame->data[0])
> +            av_frame_unref(frame);
>      }
>  
>      /* many decoders assign whole AVFrames, thus overwriting extended_data;
> @@ -1453,12 +1624,18 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>      }
>  
>      if (avcodec_is_open(avctx)) {
> +        FramePool *pool = avctx->internal->pool;
> +        int i;
>          if (HAVE_THREADS && avctx->thread_opaque)
>              ff_thread_free(avctx);
>          if (avctx->codec && avctx->codec->close)
>              avctx->codec->close(avctx);
> -        avcodec_default_free_buffers(avctx);
>          avctx->coded_frame = NULL;
> +        if (!avctx->refcounted_frames)
> +            av_frame_unref(&avctx->internal->to_free);
> +        for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
> +            av_buffer_pool_uninit(&pool->pools[i]);
> +        av_freep(&avctx->internal->pool);
>          av_freep(&avctx->internal);
>      }
>  
> @@ -1727,49 +1904,6 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
>          avctx->codec->flush(avctx);
>  }
>  
> -static void video_free_buffers(AVCodecContext *s)
> -{
> -    AVCodecInternal *avci = s->internal;
> -    int i, j;
> -
> -    if (!avci->buffer)
> -        return;
> -
> -    if (avci->buffer_count)
> -        av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n",
> -               avci->buffer_count);
> -    for (i = 0; i < INTERNAL_BUFFER_SIZE; i++) {
> -        InternalBuffer *buf = &avci->buffer[i];
> -        for (j = 0; j < 4; j++) {
> -            av_freep(&buf->base[j]);
> -            buf->data[j] = NULL;
> -        }
> -    }
> -    av_freep(&avci->buffer);
> -
> -    avci->buffer_count = 0;
> -}
> -
> -static void audio_free_buffers(AVCodecContext *avctx)
> -{
> -    AVCodecInternal *avci = avctx->internal;
> -    av_freep(&avci->audio_data);
> -}
> -
> -void avcodec_default_free_buffers(AVCodecContext *avctx)
> -{
> -    switch (avctx->codec_type) {
> -    case AVMEDIA_TYPE_VIDEO:
> -        video_free_buffers(avctx);
> -        break;
> -    case AVMEDIA_TYPE_AUDIO:
> -        audio_free_buffers(avctx);
> -        break;
> -    default:
> -        break;
> -    }
> -}
> -
>  int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
>  {
>      switch (codec_id) {
> @@ -2107,15 +2241,15 @@ unsigned int avpriv_toupper4(unsigned int x)
>  
>  #if !HAVE_THREADS
>  
> -int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
> +int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
>  {
>      f->owner = avctx;
> -    return ff_get_buffer(avctx, f);
> +    return ff_get_buffer(avctx, f, flags);
>  }
>  
>  void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f)
>  {
> -    f->owner->release_buffer(f->owner, f);
> +    av_frame_unref(f);
>  }
>  
>  void ff_thread_finish_setup(AVCodecContext *avctx)
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index d80dc0a..20da9cb 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -100,5 +100,8 @@
>  #ifndef FF_API_DESTRUCT_PACKET
>  #define FF_API_DESTRUCT_PACKET   (LIBAVCODEC_VERSION_MAJOR < 56)
>  #endif
> +#ifndef FF_API_GET_BUFFER
> +#define FF_API_GET_BUFFER        (LIBAVCODEC_VERSION_MAJOR < 56)
> +#endif
>  
>  #endif /* AVCODEC_VERSION_H */

otherwise good

Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to