diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/decode/lavc.h | 10 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 77 | ||||
-rw-r--r-- | video/mp_image.c | 28 | ||||
-rw-r--r-- | video/mp_image.h | 1 |
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) |