---
 libavcodec/avcodec.h       |   89 ++++++++++-
 libavcodec/internal.h      |   29 +---
 libavcodec/mpegvideo.c     |    3 -
 libavcodec/options.c       |    4 +-
 libavcodec/options_table.h |    1 +
 libavcodec/pthread.c       |    2 -
 libavcodec/utils.c         |  348 ++++++++++++++++++++++++--------------------
 libavcodec/version.h       |    3 +
 libavutil/frame.h          |    6 +
 9 files changed, 292 insertions(+), 193 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 40626a0..292c866 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -786,6 +786,7 @@ typedef struct RcOverride{
 #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.
@@ -795,6 +796,7 @@ typedef struct RcOverride{
 #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
 
 /**
  * @defgroup lavc_packet AVPacket
@@ -1821,6 +1823,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.
      *
@@ -1881,6 +1884,7 @@ typedef struct AVCodecContext {
      * - encoding: unused
      * - decoding: Set by libavcodec, user can override.
      */
+    attribute_deprecated
     int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic);
 
     /**
@@ -1892,6 +1896,7 @@ typedef struct AVCodecContext {
      * - encoding: unused
      * - decoding: Set by libavcodec, user can override.
      */
+    attribute_deprecated
     void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic);
 
     /**
@@ -1906,7 +1911,89 @@ 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.
+     *
+     * 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.
+     *   * 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 set if there are more buffers
+     *   than buf[] can hold.
+     *
+     * If CODEC_CAP_DR1 is not set then get_buffer2() must call
+     * avcodec_default_get_buffer() 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_buffer()
+     *
+     * Video:
+     *
+     * If pic.reference is set then the frame will be read later by libavcodec.
+     * 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,
+     * it may be called from a different thread, but not from more than one at
+     * once. Does not need to be reentrant.
+     *
+     * @see avcodec_align_dimensions2()
+     *
+     * Audio:
+     *
+     * Decoders request a buffer of a particular size by setting
+     * AVFrame.nb_samples prior to calling get_buffer(). The decoder may,
+     * however, utilize only part of the buffer by setting AVFrame.nb_samples
+     * to a smaller value in the output frame.
+     *
+     * Decoders cannot use the buffer after returning from
+     * avcodec_decode_audio4(), so they will not call release_buffer(), as it
+     * is assumed to be released immediately upon return.
+     *
+     * As a convenience, av_samples_get_buffer_size() and
+     * av_samples_fill_arrays() in libavutil may be used by custom get_buffer()
+     * 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);
+
+    /**
+     * If non-zero, the decoded audio and video frames are reference-counted 
and
+     * are valid indefinitely. The caller must free them with av_frame_unref()
+     * when they are not needed. The decoder may keep its own reference if
+     * needed.
+     * 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().
+     *
+     * @warning The default is 0 currently to preserve compatibility with
+     * previous behavior. However that will change after the next major bump.
+     */
+    int refcounted_frames;
 
 
     /* - encoding parameters */
@@ -4101,8 +4188,6 @@ int avcodec_fill_audio_frame(AVFrame *frame, int 
nb_channels,
  */
 void avcodec_flush_buffers(AVCodecContext *avctx);
 
-void avcodec_default_free_buffers(AVCodecContext *s);
-
 /**
  * Return codec bits per sample.
  *
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 069a855..960a18c 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -32,29 +32,8 @@
 
 #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 {
     /**
-     * internal buffer count
-     * used by default get/release/reget_buffer().
-     */
-    int buffer_count;
-
-    /**
-     * internal buffers
-     * used by default get/release/reget_buffer().
-     */
-    InternalBuffer *buffer;
-
-    /**
      * Whether the parent AVCodecContext is a copy of the context which had
      * init() called on it.
      * This is used by multithreading - shared tables and picture pointers
@@ -76,11 +55,7 @@ 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;
 } AVCodecInternal;
 
 struct AVCodecDefault {
@@ -151,4 +126,6 @@ static av_always_inline int64_t 
ff_samples_to_time_base(AVCodecContext *avctx,
  */
 int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame);
 
+int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame);
+
 #endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 71afec8..0c9783e 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -1008,9 +1008,6 @@ static int free_context_frame(MpegEncContext *s)
     for (i = 0; i < 3; i++)
         av_freep(&s->visualization_buffer[i]);
 
-    if (!(s->avctx->active_thread_type & FF_THREAD_FRAME))
-        avcodec_default_free_buffers(s->avctx);
-
     return 0;
 }
 
diff --git a/libavcodec/options.c b/libavcodec/options.c
index fc2a184..7506f4a 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_buffer;
     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 624239e..682bcd1 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -402,6 +402,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 cd330fc..a55957d 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 21a2ced..8ef1cf1 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])
 {
@@ -309,14 +308,14 @@ static int audio_get_buffer(AVCodecContext *avctx, 
AVFrame *frame)
     if (buf_size < 0)
         return AVERROR(EINVAL);
 
-    frame->data[0] = av_mallocz(buf_size);
-    if (!frame->data[0])
+    frame->buf[0] = av_buffer_alloc(buf_size);
+    if (!frame->buf[0])
         return AVERROR(ENOMEM);
 
     ret = avcodec_fill_audio_frame(frame, avctx->channels, avctx->sample_fmt,
-                                   frame->data[0], buf_size, 0);
+                                   frame->buf[0]->data, buf_size, 0);
     if (ret < 0) {
-        av_freep(&frame->data[0]);
+        av_buffer_unref(&frame->buf[0]);
         return ret;
     }
 
@@ -333,36 +332,16 @@ 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];
-
-    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;
@@ -402,48 +381,41 @@ 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));
+        memset(pic->base, 0, sizeof(pic->base));
+        memset(pic->data, 0, sizeof(pic->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;
 
-            buf->linesize[i] = picture.linesize[i];
+            pic->linesize[i] = picture.linesize[i];
 
-            buf->base[i] = av_malloc(size[i] + 16); //FIXME 16
-            if (buf->base[i] == NULL)
-                return -1;
-            memset(buf->base[i], 128, size[i]);
+            pic->buf[i] = av_buffer_alloc(size[i] + 16); //FIXME 16
+            if (!pic->buf[i]) {
+                av_frame_unref(pic);
+                return AVERROR(ENOMEM);
+            }
+            pic->base[i] = pic->buf[i]->data;
+            memset(pic->base[i], 128, size[i]);
 
             // no edge if EDGE EMU or not planar YUV
             if ((s->flags & CODEC_FLAG_EMU_EDGE) || !size[2])
-                buf->data[i] = buf->base[i];
+                pic->data[i] = pic->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]);
+                pic->data[i] = pic->base[i] + FFALIGN((pic->linesize[i] * 
EDGE_WIDTH >> v_shift) + (pixel_size * EDGE_WIDTH >> h_shift), stride_align[i]);
         }
         for (; i < AV_NUM_DATA_POINTERS; i++) {
-            buf->base[i]     = buf->data[i] = NULL;
-            buf->linesize[i] = 0;
+            pic->base[i]     = pic->data[i] = NULL;
+            pic->linesize[i] = 0;
         }
         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;
+            avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt);
     }
 
-    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];
-    }
     pic->extended_data = pic->data;
-    avci->buffer_count++;
 
     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;
 }
@@ -461,6 +433,26 @@ int avcodec_default_get_buffer(AVCodecContext *avctx, 
AVFrame *frame)
     }
 }
 
+#if FF_API_GET_BUFFER
+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)
 {
     switch (avctx->codec_type) {
@@ -481,87 +473,144 @@ 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;
+        ret = avctx->get_buffer(avctx, frame);
+        if (ret < 0)
+            return ret;
 
-    assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
+        priv = av_mallocz(sizeof(*priv));
+        if (!priv) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        priv->avctx = *avctx;
+        priv->frame = *frame;
+
+        dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv);
+        if (!dummy_buf) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+#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);                              \
+    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 < planes; i++) {
+                int h_shift    = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
+                int plane_size = (frame->width >> h_shift) * 
frame->linesize[i];
 
-    assert(pic->type == FF_BUFFER_TYPE_INTERNAL);
-    assert(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;
+                }
+            }
 
-    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;
+            for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)
+                WRAP_PLANE(frame->buf[i], frame->extended_data[i], 
frame->linesize[0]);
+
+            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]);
         }
-        assert(i < avci->buffer_count);
-        avci->buffer_count--;
-        last = &avci->buffer[avci->buffer_count];
 
-        if (buf != last)
-            FFSWAP(InternalBuffer, *buf, *last);
-    }
+        av_buffer_unref(&dummy_buf);
 
-    for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
-        pic->data[i] = NULL;
-//        pic->base[i]=NULL;
+        return 0;
 
-    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);
+fail:
+        avctx->release_buffer(avctx, frame);
+        av_freep(&priv);
+        av_buffer_unref(&dummy_buf);
+        return ret;
+    }
+#endif
+
+    return avctx->get_buffer2(avctx, frame);
 }
 
-int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
+int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
 {
-    AVFrame temp_pic;
-    int i;
-
-    assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
+    AVFrame tmp;
+    int ret;
 
-    /* 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);
-    }
+    av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO);
 
-    assert(s->pix_fmt == pic->format);
+    if (!frame->data[0])
+        return ff_get_buffer(avctx, frame);
 
-    /* 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;
+    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);
+    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);
+}
+
 int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, 
void *arg2), void *arg, int *ret, int count, int size)
 {
     int i;
@@ -1274,6 +1323,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;
@@ -1285,6 +1335,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,
@@ -1301,8 +1354,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;
 
@@ -1366,6 +1428,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;
 
@@ -1382,6 +1445,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) {
@@ -1389,7 +1455,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;
@@ -1456,8 +1530,11 @@ av_cold int avcodec_close(AVCodecContext *avctx)
             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) {
+            AVCodecInternal *avci = avctx->internal;
+            av_frame_unref(&avci->to_free);
+        }
         av_freep(&avctx->internal);
     }
 
@@ -1726,49 +1803,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) {
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 8f5662d..ad33817 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -97,5 +97,8 @@
 #ifndef FF_API_AVFRAME_LAVC
 #define FF_API_AVFRAME_LAVC      (LIBAVCODEC_VERSION_MAJOR < 56)
 #endif
+#ifndef FF_API_GET_BUFFER
+#define FF_API_GET_BUFFER        (LIBAVCODEC_VERSION_MAJOR < 56)
+#endif
 
 #endif /* AVCODEC_VERSION_H */
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 08d63a2..57e8273 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -201,6 +201,7 @@ typedef struct AVFrame {
      */
     int quality;
 
+#if FF_API_GET_BUFFER
     /**
      * is this picture used as reference
      * The values for this are the same as the MpegEncContext.picture_structure
@@ -209,7 +210,9 @@ typedef struct AVFrame {
      * - encoding: unused
      * - decoding: Set by libavcodec. (before get_buffer() call)).
      */
+    attribute_deprecated
     int reference;
+#endif
 
     /**
      * QP table
@@ -325,12 +328,15 @@ typedef struct AVFrame {
      */
     int palette_has_changed;
 
+#if FF_API_GET_BUFFER
     /**
      * codec suggestion on buffer type if != 0
      * - encoding: unused
      * - decoding: Set by libavcodec. (before get_buffer() call)).
      */
+    attribute_deprecated
     int buffer_hints;
+#endif
 
     /**
      * Pan scan.
-- 
1.7.10.4

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

Reply via email to