summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/decode/lavc.h7
-rw-r--r--video/decode/lavc_dr1.c5
-rw-r--r--video/decode/vd_lavc.c62
3 files changed, 58 insertions, 16 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index bf8a3fc12c..c4d24aad94 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -1,6 +1,8 @@
#ifndef MPV_LAVC_H
#define MPV_LAVC_H
+#include <stdbool.h>
+
#include <libavcodec/avcodec.h>
#include "demux/stheader.h"
@@ -11,11 +13,11 @@
typedef struct ffmpeg_ctx {
AVCodecContext *avctx;
AVFrame *pic;
- struct mp_image export_mpi;
+ struct mp_image *last_mpi;
struct mp_image hwdec_mpi[MAX_NUM_MPI];
struct hwdec *hwdec;
enum PixelFormat pix_fmt;
- int do_dr1;
+ int do_hw_dr1, do_dr1;
int vo_initialized;
int best_csp;
int qp_stat[32];
@@ -35,6 +37,7 @@ 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);
diff --git a/video/decode/lavc_dr1.c b/video/decode/lavc_dr1.c
index 1049b6105a..34aad2e030 100644
--- a/video/decode/lavc_dr1.c
+++ b/video/decode/lavc_dr1.c
@@ -190,6 +190,11 @@ void mp_buffer_unref(struct FrameBuffer *buf)
mp_buffer_pool_free(&pool);
}
+bool mp_buffer_is_unique(struct FrameBuffer *buf)
+{
+ return buf->refcount == 1;
+}
+
void mp_codec_release_buffer(AVCodecContext *s, AVFrame *frame)
{
FrameBuffer *buf = frame->opaque;
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index ba015b0ad6..120555b283 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -306,7 +306,7 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
if (!sh->codecname)
sh->codecname = lavc_codec->name;
- ctx->do_dr1 = 0;
+ ctx->do_dr1 = ctx->do_hw_dr1 = 0;
ctx->pix_fmt = PIX_FMT_NONE;
ctx->vo_initialized = 0;
ctx->hwdec = hwdec;
@@ -320,7 +320,8 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
avctx->thread_count = lavc_param->threads;
if (ctx->hwdec && ctx->hwdec->api == HWDEC_VDPAU) {
- ctx->do_dr1 = true;
+ assert(lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU);
+ ctx->do_hw_dr1 = true;
avctx->thread_count = 1;
avctx->get_format = get_format_hwdec;
avctx->get_buffer = get_buffer_hwdec;
@@ -330,7 +331,8 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
avctx->slice_flags =
SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
}
- } else {
+ } 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;
}
@@ -475,6 +477,8 @@ static void uninit_avctx(sh_video_t *sh)
av_freep(&avctx);
avcodec_free_frame(&ctx->pic);
+
+ mp_image_unrefp(&ctx->last_mpi);
mp_buffer_pool_free(&ctx->dr1_buffer_pool);
}
@@ -514,6 +518,7 @@ static int init_vo(sh_video_t *sh)
width != sh->disp_w || height != sh->disp_h ||
avctx->pix_fmt != ctx->pix_fmt || !ctx->vo_initialized)
{
+ mp_image_unrefp(&ctx->last_mpi);
ctx->vo_initialized = 0;
mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] aspect_ratio: %f\n", aspect);
@@ -658,6 +663,21 @@ static av_unused void swap_palette(void *pal)
p[i] = le2me_32(p[i]);
}
+static void fb_ref(void *b)
+{
+ mp_buffer_ref(b);
+}
+
+static void fb_unref(void *b)
+{
+ mp_buffer_unref(b);
+}
+
+static bool fb_is_unique(void *b)
+{
+ return mp_buffer_is_unique(b);
+}
+
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)
@@ -706,21 +726,35 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
return -1;
struct mp_image *mpi = NULL;
- if (ctx->do_dr1 && pic->opaque)
- mpi = (mp_image_t *)pic->opaque;
+ if (ctx->do_hw_dr1 && pic->opaque)
+ mpi = pic->opaque; // reordered frame
if (!mpi) {
- mpi = &ctx->export_mpi;
- *mpi = (struct mp_image) {0};
- mpi->type = MP_IMGTYPE_EXPORT;
- mpi->flags = MP_IMGFLAG_PRESERVE;
- mpi->w = mpi->width = avctx->width;
- mpi->h = mpi->height = avctx->height;
- mp_image_setfmt(mpi, ctx->best_csp);
+ struct mp_image new = {0};
+ new.type = MP_IMGTYPE_EXPORT;
+ new.flags = MP_IMGFLAG_PRESERVE;
+ new.w = new.width = avctx->width;
+ new.h = new.height = avctx->height;
+ mp_image_setfmt(&new, ctx->best_csp);
for (int i = 0; i < 4; i++) {
- mpi->planes[i] = pic->data[i];
- mpi->stride[i] = pic->linesize[i];
+ new.planes[i] = pic->data[i];
+ new.stride[i] = pic->linesize[i];
+ }
+ if (ctx->do_dr1 && pic->opaque) {
+ struct FrameBuffer *fb = pic->opaque;
+ mp_image_unrefp(&ctx->last_mpi);
+ mp_buffer_ref(fb); // reference for last_mpi
+ ctx->last_mpi = mp_image_new_external_ref(&new, fb, fb_ref,
+ fb_unref, fb_is_unique);
+ } else {
+ if (!ctx->last_mpi)
+ ctx->last_mpi = mp_image_alloc(ctx->best_csp, new.w, new.h);
+ mp_image_make_writeable(&ctx->last_mpi);
+ assert(ctx->last_mpi->w == new.w && ctx->last_mpi->h == new.h);
+ assert(ctx->last_mpi->imgfmt == new.imgfmt);
+ mp_image_copy(ctx->last_mpi, &new);
}
+ mpi = ctx->last_mpi;
}
if (!mpi->planes[0])