summaryrefslogtreecommitdiffstats
path: root/video/decode/vd_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-09 20:50:06 +0100
committerwm4 <wm4@nowhere>2013-03-13 23:51:30 +0100
commit514d8a7c9dfde2acc89ee4d19dd9db6b9db5b882 (patch)
tree5a4eeebc797a16866a7dc4f8b846854c9a33f0b8 /video/decode/vd_lavc.c
parent71b09be04056d9a505f32c71375ebc327d842ae4 (diff)
downloadmpv-514d8a7c9dfde2acc89ee4d19dd9db6b9db5b882.tar.bz2
mpv-514d8a7c9dfde2acc89ee4d19dd9db6b9db5b882.tar.xz
video: make use of libavcodec refcounting
Now lavc_dr1.c is not used anymore if libavcodec is recent enough.
Diffstat (limited to 'video/decode/vd_lavc.c')
-rw-r--r--video/decode/vd_lavc.c77
1 files changed, 71 insertions, 6 deletions
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)