summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/decode/lavc.h10
-rw-r--r--video/decode/vd_lavc.c77
-rw-r--r--video/mp_image.c28
-rw-r--r--video/mp_image.h1
4 files changed, 106 insertions, 10 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index d23c3e85f6..41701be1d6 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -5,6 +5,8 @@
#include <libavcodec/avcodec.h>
+#include "config.h"
+
#include "demux/stheader.h"
#include "video/mp_image.h"
@@ -13,25 +15,25 @@ typedef struct ffmpeg_ctx {
AVFrame *pic;
struct hwdec *hwdec;
enum PixelFormat pix_fmt;
- int do_hw_dr1, do_dr1;
+ int do_hw_dr1;
int vo_initialized;
int best_csp;
AVRational last_sample_aspect_ratio;
enum AVDiscard skip_frame;
const char *software_fallback_decoder;
+
+ bool do_dr1;
struct FramePool *dr1_buffer_pool;
struct mp_image_pool *non_dr1_pool;
} vd_ffmpeg_ctx;
+// lavc_dr1.c
int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame);
void mp_codec_release_buffer(AVCodecContext *s, AVFrame *frame);
-
struct FrameBuffer;
-
void mp_buffer_ref(struct FrameBuffer *buffer);
void mp_buffer_unref(struct FrameBuffer *buffer);
bool mp_buffer_is_unique(struct FrameBuffer *buffer);
-
void mp_buffer_pool_free(struct FramePool **pool);
#endif
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 874dd12694..9e334334cc 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -280,11 +280,15 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
}
} else {
+#if HAVE_AVUTIL_REFCOUNTING
+ avctx->refcounted_frames = 1;
+#else
if (lavc_codec->capabilities & CODEC_CAP_DR1) {
ctx->do_dr1 = true;
avctx->get_buffer = mp_codec_get_buffer;
avctx->release_buffer = mp_codec_release_buffer;
}
+#endif
}
if (avctx->thread_count == 0) {
@@ -373,7 +377,9 @@ static void uninit_avctx(sh_video_t *sh)
av_freep(&avctx);
avcodec_free_frame(&ctx->pic);
+#if !HAVE_AVUTIL_REFCOUNTING
mp_buffer_pool_free(&ctx->dr1_buffer_pool);
+#endif
}
static void uninit(sh_video_t *sh)
@@ -466,9 +472,8 @@ static void draw_slice_hwdec(struct AVCodecContext *s,
vf->control(vf, VFCTRL_HWDEC_DECODER_RENDER, state_ptr);
}
-static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
+static struct mp_image *get_surface_hwdec(struct sh_video *sh, AVFrame *pic)
{
- sh_video_t *sh = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context;
/* Decoders using ffmpeg's hwaccel architecture (everything except vdpau)
@@ -484,10 +489,10 @@ static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
*/
int imgfmt = pixfmt2imgfmt(pic->format);
if (!IMGFMT_IS_HWACCEL(imgfmt))
- return -1;
+ return NULL;
if (init_vo(sh, pic) < 0)
- return -1;
+ return NULL;
assert(IMGFMT_IS_HWACCEL(ctx->best_csp));
@@ -495,11 +500,52 @@ static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
struct vf_instance *vf = sh->vfilter;
vf->control(vf, VFCTRL_HWDEC_ALLOC_SURFACE, &mpi);
+
+ if (mpi) {
+ for (int i = 0; i < 4; i++)
+ pic->data[i] = mpi->planes[i];
+ }
+
+ return mpi;
+}
+
+#if HAVE_AVUTIL_REFCOUNTING
+
+static void free_mpi(void *opaque, uint8_t *data)
+{
+ struct mp_image *mpi = opaque;
+ talloc_free(mpi);
+}
+
+static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags)
+{
+ sh_video_t *sh = avctx->opaque;
+
+ struct mp_image *mpi = get_surface_hwdec(sh, pic);
+ if (!mpi)
+ return -1;
+
+ pic->buf[0] = av_buffer_create(NULL, 0, free_mpi, mpi, 0);
+
+ return 0;
+}
+
+static void setup_refcounting_hw(AVCodecContext *avctx)
+{
+ avctx->get_buffer2 = get_buffer2_hwdec;
+ avctx->refcounted_frames = 1;
+}
+
+#else /* HAVE_AVUTIL_REFCOUNTING */
+
+static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
+{
+ sh_video_t *sh = avctx->opaque;
+
+ struct mp_image *mpi = get_surface_hwdec(sh, pic);
if (!mpi)
return -1;
- for (int i = 0; i < 4; i++)
- pic->data[i] = mpi->planes[i];
pic->opaque = mpi;
pic->type = FF_BUFFER_TYPE_USER;
@@ -531,6 +577,23 @@ static void setup_refcounting_hw(AVCodecContext *avctx)
avctx->release_buffer = release_buffer_hwdec;
}
+#endif /* HAVE_AVUTIL_REFCOUNTING */
+
+#if HAVE_AVUTIL_REFCOUNTING
+
+static struct mp_image *image_from_decoder(struct sh_video *sh)
+{
+ vd_ffmpeg_ctx *ctx = sh->context;
+ AVFrame *pic = ctx->pic;
+
+ struct mp_image *img = mp_image_from_av_frame(pic);
+ av_frame_unref(pic);
+
+ return img;
+}
+
+#else /* HAVE_AVUTIL_REFCOUNTING */
+
static void fb_ref(void *b)
{
mp_buffer_ref(b);
@@ -571,6 +634,8 @@ static struct mp_image *image_from_decoder(struct sh_video *sh)
return mpi;
}
+#endif /* HAVE_AVUTIL_REFCOUNTING */
+
static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
int len, int flags, double *reordered_pts,
struct mp_image **out_image)
diff --git a/video/mp_image.c b/video/mp_image.c
index 57124eab11..72da838822 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -459,3 +459,31 @@ void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
if (src->repeat_pict == 1)
dst->fields |= MP_IMGFIELD_REPEAT_FIRST;
}
+
+#if HAVE_AVUTIL_REFCOUNTING
+
+static void frame_free(void *p)
+{
+ AVFrame *frame = p;
+ av_frame_free(&frame);
+}
+
+static bool frame_is_unique(void *p)
+{
+ AVFrame *frame = p;
+ return av_frame_is_writable(frame);
+}
+
+// Create a new mp_image reference to av_frame.
+struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame)
+{
+ AVFrame *new_ref = av_frame_clone(av_frame);
+ if (!new_ref)
+ abort(); // OOM
+ struct mp_image t = {0};
+ mp_image_copy_fields_from_av_frame(&t, new_ref);
+ return mp_image_new_external_ref(&t, new_ref, NULL, NULL, frame_is_unique,
+ frame_free);
+}
+
+#endif /* HAVE_AVUTIL_REFCOUNTING */
diff --git a/video/mp_image.h b/video/mp_image.h
index 3fe2429445..85adac65f0 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -130,6 +130,7 @@ void mp_image_set_colorspace_details(struct mp_image *image,
struct AVFrame;
void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
struct AVFrame *src);
+struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame);
// align must be a power of two (align >= 1), v >= 0
#define MP_ALIGN_UP(v, align) FFALIGN(v, align)