mirror of
https://github.com/mpv-player/mpv
synced 2025-04-28 22:34:59 +00:00
vd_lavc: remove compatibility crap
All this code was needed for compatibility with very old libavcodec versions only (such as Libav 9). Includes some now-possible simplifications too.
This commit is contained in:
parent
75b185dfc5
commit
3ec7f528c4
@ -1833,9 +1833,11 @@ if test "$_vdpau" = auto && test "$_x11" = yes ; then
|
||||
fi
|
||||
if test "$_vdpau" = yes ; then
|
||||
def_vdpau='#define HAVE_VDPAU 1'
|
||||
def_vdpau_hwaccel='#define HAVE_VDPAU_HWACCEL 1'
|
||||
vomodules="vdpau $vomodules"
|
||||
else
|
||||
def_vdpau='#define HAVE_VDPAU 0'
|
||||
def_vdpau_hwaccel='#define HAVE_VDPAU_HWACCEL 0'
|
||||
novomodules="vdpau $novomodules"
|
||||
fi
|
||||
echores "$_vdpau"
|
||||
@ -2711,34 +2713,6 @@ else
|
||||
fi
|
||||
|
||||
|
||||
echocheck "libavcodec new vdpau API"
|
||||
_avcodec_new_vdpau_api=no
|
||||
statement_check libavutil/pixfmt.h 'int x = AV_PIX_FMT_VDPAU' && _avcodec_new_vdpau_api=yes
|
||||
if test "$_avcodec_new_vdpau_api" = yes ; then
|
||||
def_avcodec_new_vdpau_api='#define HAVE_AVCODEC_NEW_VDPAU_API 1'
|
||||
else
|
||||
def_avcodec_new_vdpau_api='#define HAVE_AVCODEC_NEW_VDPAU_API 0'
|
||||
fi
|
||||
echores "$_avcodec_new_vdpau_api"
|
||||
|
||||
_vdpau_dec=no
|
||||
_vdpau_dec_old=no
|
||||
if test "$_vdpau" = yes ; then
|
||||
if test "$_avcodec_new_vdpau_api" = yes ; then
|
||||
_vdpau_dec=yes
|
||||
def_vdpau_dec='#define HAVE_VDPAU_HWACCEL 1'
|
||||
def_vdpau_dec_old='#define HAVE_VDPAU_DECODER 0'
|
||||
else
|
||||
_vdpau_dec_old=yes
|
||||
def_vdpau_dec='#define HAVE_VDPAU_HWACCEL 0'
|
||||
def_vdpau_dec_old='#define HAVE_VDPAU_DECODER 1'
|
||||
fi
|
||||
else
|
||||
def_vdpau_dec='#define HAVE_VDPAU_HWACCEL 0'
|
||||
def_vdpau_dec_old='#define HAVE_VDPAU_DECODER 0'
|
||||
fi
|
||||
|
||||
|
||||
echocheck "libavcodec avcodec_enum_to_chroma_pos API"
|
||||
_avcodec_has_chroma_pos_api=no
|
||||
statement_check libavcodec/avcodec.h 'int x, y; avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)' && _avcodec_has_chroma_pos_api=yes
|
||||
@ -2772,17 +2746,6 @@ fi
|
||||
echores "$_avutil_has_qp_api"
|
||||
|
||||
|
||||
echocheck "libavutil ref-counting API"
|
||||
_avutil_has_refcounting=no
|
||||
statement_check libavutil/frame.h 'av_frame_unref(NULL)' && _avutil_has_refcounting=yes
|
||||
if test "$_avutil_has_refcounting" = yes ; then
|
||||
def_avutil_has_refcounting='#define HAVE_AVUTIL_REFCOUNTING 1'
|
||||
else
|
||||
def_avutil_has_refcounting='#define HAVE_AVUTIL_REFCOUNTING 0'
|
||||
fi
|
||||
echores "$_avutil_has_refcounting"
|
||||
|
||||
|
||||
# libavfilter as it can be used by vf_lavfi is 3.45.101 in FFmpeg, and
|
||||
# 3.5.0 in Libav. Completely useless version numbers.
|
||||
echocheck "libavfilter"
|
||||
@ -2816,11 +2779,7 @@ echocheck "using libavfilter through vf_lavfi"
|
||||
if test "$vf_lavfi" = auto ; then
|
||||
vf_lavfi=no
|
||||
if test "$libavfilter" = yes ; then
|
||||
if test "$_avutil_has_refcounting" = no ; then
|
||||
res_comment="libavutil too old"
|
||||
else
|
||||
vf_lavfi=yes
|
||||
fi
|
||||
vf_lavfi=yes
|
||||
fi
|
||||
fi
|
||||
if test "$vf_lavfi" = yes ; then
|
||||
@ -2881,13 +2840,9 @@ if darwin ; then
|
||||
echocheck "VDA"
|
||||
if test "$_vda" = auto ; then
|
||||
_vda=no
|
||||
if test "$_avutil_has_refcounting" = "yes" ; then
|
||||
header_check VideoDecodeAcceleration/VDADecoder.h &&
|
||||
statement_check libavcodec/vda.h 'ff_vda_create_decoder(NULL, NULL, NULL)' &&
|
||||
_vda=yes
|
||||
else
|
||||
res_comment="libavutil too old"
|
||||
fi
|
||||
header_check VideoDecodeAcceleration/VDADecoder.h &&
|
||||
statement_check libavcodec/vda.h 'ff_vda_create_decoder(NULL, NULL, NULL)' &&
|
||||
_vda=yes
|
||||
fi
|
||||
if test "$_vda" = yes ; then
|
||||
def_vda='#define HAVE_VDA_HWACCEL 1'
|
||||
@ -3303,7 +3258,6 @@ GL_X11 = $_gl_x11
|
||||
GL_WAYLAND = $_gl_wayland
|
||||
HAVE_POSIX_SELECT = $_posix_select
|
||||
HAVE_SYS_MMAN_H = $_mman
|
||||
HAVE_AVUTIL_REFCOUNTING = $_avutil_has_refcounting
|
||||
JACK = $_jack
|
||||
JOYSTICK = $_joystick
|
||||
JPEG = $_jpeg
|
||||
@ -3343,8 +3297,6 @@ TV_V4L2 = $_tv_v4l2
|
||||
LIBV4L2 = $_libv4l2
|
||||
VCD = $_vcd
|
||||
VDPAU = $_vdpau
|
||||
VDPAU_DEC = $_vdpau_dec
|
||||
VDPAU_DEC_OLD = $_vdpau_dec_old
|
||||
VDPAU_GL_X11 = $_vdpau_gl_x11
|
||||
VDA = $_vda
|
||||
VDA_REFCOUNTING = $_vda_refcounting
|
||||
@ -3454,9 +3406,7 @@ $def_vcd
|
||||
$def_mpg123
|
||||
$def_zlib
|
||||
|
||||
$def_avutil_has_refcounting
|
||||
$def_avutil_has_qp_api
|
||||
$def_avcodec_new_vdpau_api
|
||||
$def_avcodec_has_chroma_pos_api
|
||||
$def_avcodec_has_metadata_update_side_data
|
||||
$def_libpostproc
|
||||
@ -3530,9 +3480,8 @@ $def_gl_wayland
|
||||
$def_jpeg
|
||||
$def_v4l2
|
||||
$def_vdpau
|
||||
$def_vdpau_dec
|
||||
$def_vdpau_dec_old
|
||||
$def_vdpau_gl_x11
|
||||
$def_vdpau_hwaccel
|
||||
$def_vda
|
||||
$def_vda_gl
|
||||
$def_vda_refcounting
|
||||
|
@ -115,12 +115,11 @@ SOURCES-$(PULSE) += audio/out/ao_pulse.c
|
||||
SOURCES-$(PORTAUDIO) += audio/out/ao_portaudio.c
|
||||
SOURCES-$(RSOUND) += audio/out/ao_rsound.c
|
||||
SOURCES-$(SNDIO) += audio/out/ao_sndio.c
|
||||
SOURCES-$(VDPAU) += video/vdpau.c video/out/vo_vdpau.c
|
||||
SOURCES-$(VDPAU) += video/vdpau.c video/out/vo_vdpau.c \
|
||||
video/decode/vdpau.c
|
||||
SOURCES-$(VDPAU_GL_X11) += video/out/gl_hwdec_vdpau.c
|
||||
SOURCES-$(VDA) += video/decode/vda.c
|
||||
SOURCES-$(VDA_GL) += video/out/gl_hwdec_vda.c
|
||||
SOURCES-$(VDPAU_DEC) += video/decode/vdpau.c
|
||||
SOURCES-$(VDPAU_DEC_OLD) += video/decode/vdpau_old.c
|
||||
SOURCES-$(VAAPI) += video/out/vo_vaapi.c \
|
||||
video/decode/vaapi.c \
|
||||
video/vaapi.c
|
||||
@ -136,10 +135,6 @@ SOURCES-$(AF_LAVFI) += audio/filter/af_lavfi.c
|
||||
|
||||
SOURCES-$(LUA) += player/lua.c
|
||||
|
||||
ifeq ($(HAVE_AVUTIL_REFCOUNTING),no)
|
||||
SOURCES-yes += video/decode/lavc_dr1.c
|
||||
endif
|
||||
|
||||
SOURCES-$(DLOPEN) += video/filter/vf_dlopen.c
|
||||
|
||||
SOURCES = audio/audio.c \
|
||||
|
@ -41,25 +41,13 @@ typedef struct lavc_ctx {
|
||||
int hwdec_fmt;
|
||||
int hwdec_w;
|
||||
int hwdec_h;
|
||||
|
||||
// Legacy
|
||||
bool do_dr1;
|
||||
struct FramePool *dr1_buffer_pool;
|
||||
struct mp_image_pool *non_dr1_pool;
|
||||
} vd_ffmpeg_ctx;
|
||||
|
||||
struct vd_lavc_hwdec {
|
||||
enum hwdec_type type;
|
||||
// If non-NULL: lists pairs software and hardware decoders. If the current
|
||||
// codec is not one of the listed software decoders, probing fails.
|
||||
// Otherwise, the AVCodecContext is initialized with the associated
|
||||
// hardware decoder.
|
||||
// Useful only if hw decoding requires a special codec, instead of using
|
||||
// the libavcodec hwaccel infrastructure.
|
||||
const char **codec_pairs;
|
||||
// If not-NULL: a 0 terminated list of IMGFMT_ formats, and only one of
|
||||
// these formats is accepted in the libavcodec get_format callback.
|
||||
const int *image_formats;
|
||||
// If not-0: the IMGFMT_ format that should be accepted in the libavcodec
|
||||
// get_format callback.
|
||||
int image_format;
|
||||
int (*probe)(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
|
||||
const char *decoder);
|
||||
int (*init)(struct lavc_ctx *ctx);
|
||||
@ -90,14 +78,4 @@ bool hwdec_check_codec_support(const char *decoder,
|
||||
const struct hwdec_profile_entry *table);
|
||||
int hwdec_get_max_refs(struct lavc_ctx *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);
|
||||
bool mp_buffer_check(struct FrameBuffer *buffer);
|
||||
|
||||
#endif
|
||||
|
@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Various utilities for command line tools
|
||||
* Copyright (c) 2000-2003 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: this file is for compatibility with older versions of
|
||||
* libavcodec, before AVFrame reference counting was introduced.
|
||||
* It is not compiled if libavcodec is new enough.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/avassert.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/common.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "lavc.h"
|
||||
#include "video/decode/dec_video.h"
|
||||
|
||||
static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define pool_lock() pthread_mutex_lock(&pool_mutex)
|
||||
#define pool_unlock() pthread_mutex_unlock(&pool_mutex)
|
||||
|
||||
typedef struct FramePool {
|
||||
struct FrameBuffer *list;
|
||||
// used to deal with frames that live past the time the pool should live
|
||||
int dead;
|
||||
int refcount; // number of allocated buffers (not in list)
|
||||
} FramePool;
|
||||
|
||||
typedef struct FrameBuffer {
|
||||
uint8_t *base[4];
|
||||
uint8_t *data[4];
|
||||
int linesize[4];
|
||||
|
||||
int h, w;
|
||||
int pix_fmt;
|
||||
|
||||
int used_by_decoder, needed_by_decoder;
|
||||
int refcount;
|
||||
struct FramePool *pool;
|
||||
struct FrameBuffer *next;
|
||||
} FrameBuffer;
|
||||
|
||||
|
||||
static int alloc_buffer(FramePool *pool, AVCodecContext *s)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[s->pix_fmt];
|
||||
FrameBuffer *buf;
|
||||
int i, ret;
|
||||
int pixel_size;
|
||||
int h_chroma_shift, v_chroma_shift;
|
||||
int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
|
||||
int w = s->width, h = s->height;
|
||||
|
||||
if (!desc)
|
||||
return AVERROR(EINVAL);
|
||||
pixel_size = desc->comp[0].step_minus1 + 1;
|
||||
|
||||
buf = av_mallocz(sizeof(*buf));
|
||||
if (!buf)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
avcodec_align_dimensions(s, &w, &h);
|
||||
|
||||
if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
|
||||
w += 2*edge;
|
||||
h += 2*edge;
|
||||
}
|
||||
|
||||
if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
|
||||
s->pix_fmt, 32)) < 0) {
|
||||
av_freep(&buf);
|
||||
av_log(s, AV_LOG_ERROR, "alloc_buffer: av_image_alloc() failed\n");
|
||||
return ret;
|
||||
}
|
||||
/* XXX this shouldn't be needed, but some tests break without this line
|
||||
* those decoders are buggy and need to be fixed.
|
||||
* the following tests fail:
|
||||
* cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
|
||||
*/
|
||||
memset(buf->base[0], 128, ret);
|
||||
|
||||
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
||||
const int h_shift = i==0 ? 0 : h_chroma_shift;
|
||||
const int v_shift = i==0 ? 0 : v_chroma_shift;
|
||||
if ((s->flags & CODEC_FLAG_EMU_EDGE) || !buf->linesize[i] || !buf->base[i])
|
||||
buf->data[i] = buf->base[i];
|
||||
else
|
||||
buf->data[i] = buf->base[i] +
|
||||
FFALIGN((buf->linesize[i]*edge >> v_shift) +
|
||||
(pixel_size*edge >> h_shift), 32);
|
||||
}
|
||||
buf->w = s->width;
|
||||
buf->h = s->height;
|
||||
buf->pix_fmt = s->pix_fmt;
|
||||
buf->pool = pool;
|
||||
|
||||
buf->next = pool->list;
|
||||
pool->list = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame)
|
||||
{
|
||||
struct dec_video *vd = s->opaque;
|
||||
struct lavc_ctx *ctx = vd->priv;
|
||||
|
||||
if (!ctx->dr1_buffer_pool) {
|
||||
ctx->dr1_buffer_pool = av_mallocz(sizeof(*ctx->dr1_buffer_pool));
|
||||
if (!ctx->dr1_buffer_pool)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
FramePool *pool = ctx->dr1_buffer_pool;
|
||||
FrameBuffer *buf;
|
||||
int ret, i;
|
||||
|
||||
if(av_image_check_size(s->width, s->height, 0, s) || s->pix_fmt<0) {
|
||||
av_log(s, AV_LOG_ERROR, "codec_get_buffer: image parameters invalid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pool_lock();
|
||||
|
||||
if (!pool->list && (ret = alloc_buffer(pool, s)) < 0) {
|
||||
pool_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf = pool->list;
|
||||
if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
|
||||
pool->list = buf->next;
|
||||
av_freep(&buf->base[0]);
|
||||
av_free(buf);
|
||||
if ((ret = alloc_buffer(pool, s)) < 0) {
|
||||
pool_unlock();
|
||||
return ret;
|
||||
}
|
||||
buf = pool->list;
|
||||
}
|
||||
av_assert0(!buf->refcount);
|
||||
buf->refcount++;
|
||||
|
||||
pool->list = buf->next;
|
||||
pool->refcount++;
|
||||
|
||||
pool_unlock();
|
||||
|
||||
frame->opaque = buf;
|
||||
frame->type = FF_BUFFER_TYPE_USER;
|
||||
frame->extended_data = frame->data;
|
||||
|
||||
buf->used_by_decoder = buf->needed_by_decoder = 1;
|
||||
if (frame->buffer_hints & FF_BUFFER_HINTS_VALID) {
|
||||
buf->needed_by_decoder =
|
||||
(frame->buffer_hints & FF_BUFFER_HINTS_PRESERVE) ||
|
||||
(frame->buffer_hints & FF_BUFFER_HINTS_REUSABLE);
|
||||
} else {
|
||||
buf->needed_by_decoder = !!frame->reference;
|
||||
}
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
||||
frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't
|
||||
frame->data[i] = buf->data[i];
|
||||
frame->linesize[i] = buf->linesize[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mp_buffer_ref(struct FrameBuffer *buf)
|
||||
{
|
||||
pool_lock();
|
||||
buf->refcount++;
|
||||
pool_unlock();
|
||||
}
|
||||
|
||||
bool mp_buffer_check(struct FrameBuffer *buf)
|
||||
{
|
||||
pool_lock();
|
||||
bool ok = buf->refcount > 0;
|
||||
if (ok)
|
||||
buf->refcount++;
|
||||
pool_unlock();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void mp_buffer_unref(struct FrameBuffer *buf)
|
||||
{
|
||||
FramePool *pool = buf->pool;
|
||||
bool pool_dead;
|
||||
|
||||
pool_lock();
|
||||
|
||||
av_assert0(pool->refcount > 0);
|
||||
av_assert0(buf->refcount > 0);
|
||||
buf->refcount--;
|
||||
if (!buf->refcount) {
|
||||
FrameBuffer *tmp;
|
||||
for(tmp= pool->list; tmp; tmp= tmp->next)
|
||||
av_assert1(tmp != buf);
|
||||
|
||||
buf->next = pool->list;
|
||||
pool->list = buf;
|
||||
pool->refcount--;
|
||||
}
|
||||
|
||||
pool_dead = pool->dead && pool->refcount == 0;
|
||||
pool_unlock();
|
||||
|
||||
if (pool_dead)
|
||||
mp_buffer_pool_free(&pool);
|
||||
}
|
||||
|
||||
bool mp_buffer_is_unique(struct FrameBuffer *buf)
|
||||
{
|
||||
int refcount;
|
||||
pool_lock();
|
||||
refcount = buf->refcount;
|
||||
// Decoder has a reference, but doesn't want to use it. (ffmpeg has no good
|
||||
// way of transferring frame ownership to the user.)
|
||||
if (buf->used_by_decoder && !buf->needed_by_decoder)
|
||||
refcount--;
|
||||
pool_unlock();
|
||||
return refcount == 1;
|
||||
}
|
||||
|
||||
void mp_codec_release_buffer(AVCodecContext *s, AVFrame *frame)
|
||||
{
|
||||
FrameBuffer *buf = frame->opaque;
|
||||
int i;
|
||||
|
||||
if(frame->type!=FF_BUFFER_TYPE_USER) {
|
||||
avcodec_default_release_buffer(s, frame);
|
||||
return;
|
||||
}
|
||||
|
||||
buf->used_by_decoder = buf->needed_by_decoder = 0;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
|
||||
frame->data[i] = NULL;
|
||||
|
||||
mp_buffer_unref(buf);
|
||||
}
|
||||
|
||||
void mp_buffer_pool_free(struct FramePool **p_pool)
|
||||
{
|
||||
struct FramePool *pool = *p_pool;
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
pool_lock();
|
||||
|
||||
while (pool->list) {
|
||||
FrameBuffer *buf = pool->list;
|
||||
pool->list = buf->next;
|
||||
av_assert0(buf->refcount == 0);
|
||||
av_freep(&buf->base[0]);
|
||||
av_free(buf);
|
||||
}
|
||||
pool->dead = 1;
|
||||
if (pool->refcount == 0)
|
||||
av_free(pool);
|
||||
|
||||
pool_unlock();
|
||||
|
||||
*p_pool = NULL;
|
||||
}
|
@ -451,7 +451,7 @@ static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img)
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
|
||||
.type = HWDEC_VAAPI,
|
||||
.image_formats = (const int[]) {IMGFMT_VAAPI, 0},
|
||||
.image_format = IMGFMT_VAAPI,
|
||||
.probe = probe,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
@ -461,7 +461,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
|
||||
.type = HWDEC_VAAPI_COPY,
|
||||
.image_formats = (const int[]) {IMGFMT_VAAPI, 0},
|
||||
.image_format = IMGFMT_VAAPI,
|
||||
.probe = probe_copy,
|
||||
.init = init_copy,
|
||||
.uninit = uninit,
|
||||
|
@ -44,7 +44,6 @@
|
||||
|
||||
#include "vd.h"
|
||||
#include "video/img_format.h"
|
||||
#include "video/mp_image_pool.h"
|
||||
#include "video/filter/vf.h"
|
||||
#include "video/decode/dec_video.h"
|
||||
#include "demux/stheader.h"
|
||||
@ -62,8 +61,8 @@
|
||||
static void init_avctx(struct dec_video *vd, const char *decoder,
|
||||
struct vd_lavc_hwdec *hwdec);
|
||||
static void uninit_avctx(struct dec_video *vd);
|
||||
static void setup_refcounting_hw(struct AVCodecContext *s);
|
||||
|
||||
static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags);
|
||||
static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
|
||||
const enum AVPixelFormat *pix_fmt);
|
||||
|
||||
@ -85,7 +84,6 @@ const m_option_t lavc_decode_opts_conf[] = {
|
||||
};
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vdpau;
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vdpau_old;
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vda;
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vaapi;
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy;
|
||||
@ -94,9 +92,6 @@ static const struct vd_lavc_hwdec *hwdec_list[] = {
|
||||
#if HAVE_VDPAU_HWACCEL
|
||||
&mp_vd_lavc_vdpau,
|
||||
#endif
|
||||
#if HAVE_VDPAU_DECODER
|
||||
&mp_vd_lavc_vdpau_old,
|
||||
#endif
|
||||
#if HAVE_VDA_HWACCEL
|
||||
&mp_vd_lavc_vda,
|
||||
#endif
|
||||
@ -191,52 +186,35 @@ void hwdec_request_api(struct mp_hwdec_info *info, const char *api_name)
|
||||
}
|
||||
|
||||
static int hwdec_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
|
||||
const char *decoder, const char **hw_decoder)
|
||||
const char *decoder)
|
||||
{
|
||||
if (hwdec->codec_pairs) {
|
||||
for (int n = 0; hwdec->codec_pairs[n + 0]; n += 2) {
|
||||
const char *sw = hwdec->codec_pairs[n + 0];
|
||||
const char *hw = hwdec->codec_pairs[n + 1];
|
||||
if (decoder && strcmp(decoder, sw) == 0) {
|
||||
AVCodec *codec = avcodec_find_decoder_by_name(hw);
|
||||
*hw_decoder = hw;
|
||||
if (codec)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return HWDEC_ERR_NO_CODEC;
|
||||
found: ;
|
||||
}
|
||||
int r = 0;
|
||||
if (hwdec->probe)
|
||||
r = hwdec->probe(hwdec, info, decoder);
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool probe_hwdec(struct dec_video *vd, bool autoprobe, enum hwdec_type api,
|
||||
const char *decoder, struct vd_lavc_hwdec **use_hwdec,
|
||||
const char **use_decoder)
|
||||
static struct vd_lavc_hwdec *probe_hwdec(struct dec_video *vd, bool autoprobe,
|
||||
enum hwdec_type api,
|
||||
const char *decoder)
|
||||
{
|
||||
struct vd_lavc_hwdec *hwdec = find_hwcodec(api);
|
||||
if (!hwdec) {
|
||||
MP_VERBOSE(vd, "Requested hardware decoder not "
|
||||
"compiled.\n");
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
const char *hw_decoder = NULL;
|
||||
int r = hwdec_probe(hwdec, &vd->hwdec_info, decoder, &hw_decoder);
|
||||
int r = hwdec_probe(hwdec, &vd->hwdec_info, decoder);
|
||||
if (r >= 0) {
|
||||
*use_hwdec = hwdec;
|
||||
*use_decoder = hw_decoder;
|
||||
return true;
|
||||
return hwdec;
|
||||
} else if (r == HWDEC_ERR_NO_CODEC) {
|
||||
MP_VERBOSE(vd, "Hardware decoder '%s' not found in "
|
||||
"libavcodec.\n", hw_decoder ? hw_decoder : decoder);
|
||||
"libavcodec.\n", decoder);
|
||||
} else if (r == HWDEC_ERR_NO_CTX && !autoprobe) {
|
||||
MP_WARN(vd, "VO does not support requested "
|
||||
"hardware decoder.\n");
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -246,7 +224,6 @@ static int init(struct dec_video *vd, const char *decoder)
|
||||
ctx = vd->priv = talloc_zero(NULL, vd_ffmpeg_ctx);
|
||||
ctx->log = vd->log;
|
||||
ctx->opts = vd->opts;
|
||||
ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16));
|
||||
|
||||
if (bstr_endswith0(bstr0(decoder), "_vdpau")) {
|
||||
MP_WARN(vd, "VDPAU decoder '%s' was requested. "
|
||||
@ -260,18 +237,16 @@ static int init(struct dec_video *vd, const char *decoder)
|
||||
}
|
||||
|
||||
struct vd_lavc_hwdec *hwdec = NULL;
|
||||
const char *hw_decoder = NULL;
|
||||
|
||||
if (hwdec_codec_allowed(vd, decoder)) {
|
||||
if (vd->opts->hwdec_api == HWDEC_AUTO) {
|
||||
for (int n = 0; hwdec_list[n]; n++) {
|
||||
if (probe_hwdec(vd, true, hwdec_list[n]->type, decoder,
|
||||
&hwdec, &hw_decoder))
|
||||
hwdec = probe_hwdec(vd, true, hwdec_list[n]->type, decoder);
|
||||
if (hwdec)
|
||||
break;
|
||||
}
|
||||
} else if (vd->opts->hwdec_api != HWDEC_NONE) {
|
||||
probe_hwdec(vd, false, vd->opts->hwdec_api, decoder,
|
||||
&hwdec, &hw_decoder);
|
||||
hwdec = probe_hwdec(vd, false, vd->opts->hwdec_api, decoder);
|
||||
}
|
||||
} else {
|
||||
MP_VERBOSE(vd, "Not trying to use hardware decoding: "
|
||||
@ -280,8 +255,6 @@ static int init(struct dec_video *vd, const char *decoder)
|
||||
|
||||
if (hwdec) {
|
||||
ctx->software_fallback_decoder = talloc_strdup(ctx, decoder);
|
||||
if (hw_decoder)
|
||||
decoder = hw_decoder;
|
||||
MP_INFO(vd, "Trying to use hardware decoding.\n");
|
||||
} else if (vd->opts->hwdec_api != HWDEC_NONE) {
|
||||
MP_INFO(vd, "Using software decoding.\n");
|
||||
@ -336,7 +309,7 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
|
||||
|
||||
ctx->hwdec_info = &vd->hwdec_info;
|
||||
|
||||
ctx->do_dr1 = ctx->do_hw_dr1 = 0;
|
||||
ctx->do_hw_dr1 = 0;
|
||||
ctx->pix_fmt = AV_PIX_FMT_NONE;
|
||||
ctx->hwdec = hwdec;
|
||||
ctx->hwdec_fmt = 0;
|
||||
@ -346,30 +319,19 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
|
||||
avctx->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
avctx->codec_id = lavc_codec->id;
|
||||
|
||||
#if HAVE_AVUTIL_REFCOUNTING
|
||||
avctx->refcounted_frames = 1;
|
||||
ctx->pic = av_frame_alloc();
|
||||
#else
|
||||
ctx->pic = avcodec_alloc_frame();
|
||||
#endif
|
||||
|
||||
if (ctx->hwdec) {
|
||||
ctx->do_hw_dr1 = true;
|
||||
avctx->thread_count = 1;
|
||||
avctx->get_format = get_format_hwdec;
|
||||
setup_refcounting_hw(avctx);
|
||||
avctx->get_buffer2 = get_buffer2_hwdec;
|
||||
if (ctx->hwdec->init(ctx) < 0) {
|
||||
uninit_avctx(vd);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
#if !HAVE_AVUTIL_REFCOUNTING
|
||||
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
|
||||
mp_set_avcodec_threads(avctx, lavc_param->threads);
|
||||
}
|
||||
|
||||
@ -446,12 +408,7 @@ static void uninit_avctx(struct dec_video *vd)
|
||||
if (ctx->hwdec && ctx->hwdec->uninit)
|
||||
ctx->hwdec->uninit(ctx);
|
||||
|
||||
#if HAVE_AVUTIL_REFCOUNTING
|
||||
av_frame_free(&ctx->pic);
|
||||
#else
|
||||
avcodec_free_frame(&ctx->pic);
|
||||
mp_buffer_pool_free(&ctx->dr1_buffer_pool);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uninit(struct dec_video *vd)
|
||||
@ -468,10 +425,6 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
|
||||
float aspect = av_q2d(frame->sample_aspect_ratio) * width / height;
|
||||
int pix_fmt = frame->format;
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0)
|
||||
pix_fmt = ctx->avctx->pix_fmt;
|
||||
#endif
|
||||
|
||||
if (pix_fmt != ctx->pix_fmt) {
|
||||
ctx->pix_fmt = pix_fmt;
|
||||
ctx->best_csp = pixfmt2imgfmt(pix_fmt);
|
||||
@ -509,13 +462,12 @@ static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
|
||||
|
||||
assert(ctx->hwdec);
|
||||
|
||||
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
|
||||
const int *okfmt = ctx->hwdec->image_formats;
|
||||
for (int n = 0; okfmt && okfmt[n]; n++) {
|
||||
if (imgfmt2pixfmt(okfmt[n]) == fmt[i]) {
|
||||
if (ctx->hwdec->image_format) {
|
||||
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
|
||||
if (ctx->hwdec->image_format == pixfmt2imgfmt(fmt[i])) {
|
||||
ctx->hwdec_w = avctx->width;
|
||||
ctx->hwdec_h = avctx->height;
|
||||
ctx->hwdec_fmt = okfmt[n];
|
||||
ctx->hwdec_fmt = ctx->hwdec->image_format;
|
||||
if (ctx->hwdec->init_decoder) {
|
||||
if (ctx->hwdec->init_decoder(ctx, ctx->hwdec_fmt,
|
||||
ctx->hwdec_w, ctx->hwdec_h) < 0)
|
||||
@ -573,8 +525,6 @@ static struct mp_image *get_surface_hwdec(struct dec_video *vd, AVFrame *pic)
|
||||
return mpi;
|
||||
}
|
||||
|
||||
#if HAVE_AVUTIL_REFCOUNTING
|
||||
|
||||
static void free_mpi(void *opaque, uint8_t *data)
|
||||
{
|
||||
struct mp_image *mpi = opaque;
|
||||
@ -594,120 +544,6 @@ static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_refcounting_hw(AVCodecContext *avctx)
|
||||
{
|
||||
avctx->get_buffer2 = get_buffer2_hwdec;
|
||||
}
|
||||
|
||||
#else /* HAVE_AVUTIL_REFCOUNTING */
|
||||
|
||||
static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
|
||||
{
|
||||
struct dec_video *vd = avctx->opaque;
|
||||
|
||||
struct mp_image *mpi = get_surface_hwdec(vd, pic);
|
||||
if (!mpi)
|
||||
return -1;
|
||||
|
||||
pic->opaque = mpi;
|
||||
pic->type = FF_BUFFER_TYPE_USER;
|
||||
|
||||
/* The libavcodec reordered_opaque functionality is implemented by
|
||||
* a similar copy in avcodec_default_get_buffer() and without a
|
||||
* workaround like this it'd stop working when a custom buffer
|
||||
* callback is used.
|
||||
*/
|
||||
pic->reordered_opaque = avctx->reordered_opaque;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
|
||||
{
|
||||
mp_image_t *mpi = pic->opaque;
|
||||
|
||||
assert(pic->type == FF_BUFFER_TYPE_USER);
|
||||
assert(mpi);
|
||||
|
||||
talloc_free(mpi);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
pic->data[i] = NULL;
|
||||
}
|
||||
|
||||
static void setup_refcounting_hw(AVCodecContext *avctx)
|
||||
{
|
||||
avctx->get_buffer = get_buffer_hwdec;
|
||||
avctx->release_buffer = release_buffer_hwdec;
|
||||
}
|
||||
|
||||
#endif /* HAVE_AVUTIL_REFCOUNTING */
|
||||
|
||||
#if HAVE_AVUTIL_REFCOUNTING
|
||||
|
||||
static struct mp_image *image_from_decoder(struct dec_video *vd)
|
||||
{
|
||||
vd_ffmpeg_ctx *ctx = vd->priv;
|
||||
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);
|
||||
}
|
||||
|
||||
static void fb_unref(void *b)
|
||||
{
|
||||
mp_buffer_unref(b);
|
||||
}
|
||||
|
||||
static bool fb_is_unique(void *b)
|
||||
{
|
||||
return mp_buffer_is_unique(b);
|
||||
}
|
||||
|
||||
static struct mp_image *image_from_decoder(struct dec_video *vd)
|
||||
{
|
||||
vd_ffmpeg_ctx *ctx = vd->priv;
|
||||
AVFrame *pic = ctx->pic;
|
||||
|
||||
struct mp_image new = {0};
|
||||
mp_image_copy_fields_from_av_frame(&new, pic);
|
||||
|
||||
struct mp_image *mpi;
|
||||
if (ctx->do_hw_dr1 && pic->opaque) {
|
||||
mpi = pic->opaque; // reordered frame
|
||||
assert(mpi);
|
||||
mpi = mp_image_new_ref(mpi);
|
||||
mp_image_copy_attributes(mpi, &new);
|
||||
} else if (ctx->do_dr1 && pic->opaque) {
|
||||
struct FrameBuffer *fb = pic->opaque;
|
||||
// initial reference for mpi
|
||||
if (!new.planes[0] || !mp_buffer_check(fb)) {
|
||||
// Decoder returned an unreferenced buffer! Taking this would just
|
||||
// lead to an eventual double-free. Nothing we can do about this.
|
||||
// So just say "fuck you" in a nice way.
|
||||
MP_FATAL(vd,
|
||||
"Impossible condition detected! This version of Libav/FFmpeg is not\n"
|
||||
"supported anymore. Please update.\n");
|
||||
return NULL;
|
||||
}
|
||||
mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
|
||||
fb_is_unique, NULL);
|
||||
} else {
|
||||
mpi = mp_image_pool_new_copy(ctx->non_dr1_pool, &new);
|
||||
}
|
||||
return mpi;
|
||||
}
|
||||
|
||||
#endif /* HAVE_AVUTIL_REFCOUNTING */
|
||||
|
||||
static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
int flags, struct mp_image **out_image)
|
||||
{
|
||||
@ -741,8 +577,8 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
vd->codec_pts = mp_pts_from_av(ctx->pic->pkt_pts, NULL);
|
||||
vd->codec_dts = mp_pts_from_av(ctx->pic->pkt_dts, NULL);
|
||||
|
||||
// Note: potentially resets ctx->pic as it is transferred to mpi
|
||||
struct mp_image *mpi = image_from_decoder(vd);
|
||||
struct mp_image *mpi = mp_image_from_av_frame(ctx->pic);
|
||||
av_frame_unref(ctx->pic);
|
||||
if (!mpi)
|
||||
return 0;
|
||||
assert(mpi->planes[0]);
|
||||
|
@ -214,7 +214,7 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int fmt,
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vda = {
|
||||
.type = HWDEC_VDA,
|
||||
.image_formats = (const int[]) { IMGFMT_VDA, 0 },
|
||||
.image_format = IMGFMT_VDA,
|
||||
.probe = probe,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
|
@ -206,7 +206,7 @@ static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vdpau = {
|
||||
.type = HWDEC_VDPAU,
|
||||
.image_formats = (const int[]) {IMGFMT_VDPAU, 0},
|
||||
.image_format = IMGFMT_VDPAU,
|
||||
.probe = probe,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* VDPAU video output driver
|
||||
*
|
||||
* Copyright (C) 2008 NVIDIA
|
||||
* Copyright (C) 2009 Uoti Urpala
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libavcodec/vdpau.h>
|
||||
#include <libavutil/common.h>
|
||||
|
||||
#include "lavc.h"
|
||||
#include "video/fmt-conversion.h"
|
||||
#include "video/vdpau.h"
|
||||
#include "video/hwdec.h"
|
||||
#include "video/decode/dec_video.h"
|
||||
|
||||
struct priv {
|
||||
struct mp_log *log;
|
||||
struct mp_vdpau_ctx *mpvdp;
|
||||
struct vdp_functions *vdp;
|
||||
VdpDevice vdp_device;
|
||||
uint64_t preemption_counter;
|
||||
|
||||
int image_format;
|
||||
int vid_width;
|
||||
int vid_height;
|
||||
|
||||
VdpDecoder decoder;
|
||||
int decoder_max_refs;
|
||||
};
|
||||
|
||||
static void mark_uninitialized(struct lavc_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
|
||||
p->vdp_device = VDP_INVALID_HANDLE;
|
||||
p->decoder = VDP_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int handle_preemption(struct lavc_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
|
||||
if (!mp_vdpau_status_ok(p->mpvdp))
|
||||
return -1;
|
||||
|
||||
// Mark objects as destroyed if preemption+reinit occured
|
||||
if (p->preemption_counter < p->mpvdp->preemption_counter) {
|
||||
p->preemption_counter = p->mpvdp->preemption_counter;
|
||||
mark_uninitialized(ctx);
|
||||
}
|
||||
|
||||
p->vdp_device = p->mpvdp->vdp_device;
|
||||
p->vdp = p->mpvdp->vdp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool create_vdp_decoder(struct lavc_ctx *ctx, int max_refs)
|
||||
{
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
struct vdp_functions *vdp = p->mpvdp->vdp;
|
||||
VdpStatus vdp_st;
|
||||
VdpDecoderProfile vdp_decoder_profile;
|
||||
|
||||
if (handle_preemption(ctx) < 0)
|
||||
return false;
|
||||
|
||||
if (p->decoder != VDP_INVALID_HANDLE)
|
||||
vdp->decoder_destroy(p->decoder);
|
||||
|
||||
switch (p->image_format) {
|
||||
case IMGFMT_VDPAU_MPEG1:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1;
|
||||
break;
|
||||
case IMGFMT_VDPAU_MPEG2:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
|
||||
break;
|
||||
case IMGFMT_VDPAU_H264:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH;
|
||||
MP_VERBOSE(p, "Creating H264 hardware decoder "
|
||||
"for %d reference frames.\n", max_refs);
|
||||
break;
|
||||
case IMGFMT_VDPAU_WMV3:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN;
|
||||
break;
|
||||
case IMGFMT_VDPAU_VC1:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
|
||||
break;
|
||||
case IMGFMT_VDPAU_MPEG4:
|
||||
vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
|
||||
break;
|
||||
default:
|
||||
MP_ERR(p, "Unknown image format!\n");
|
||||
goto fail;
|
||||
}
|
||||
vdp_st = vdp->decoder_create(p->vdp_device, vdp_decoder_profile,
|
||||
p->vid_width, p->vid_height, max_refs,
|
||||
&p->decoder);
|
||||
CHECK_VDP_WARNING(p, "Failed creating VDPAU decoder");
|
||||
if (vdp_st != VDP_STATUS_OK)
|
||||
goto fail;
|
||||
p->decoder_max_refs = max_refs;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
p->decoder = VDP_INVALID_HANDLE;
|
||||
p->decoder_max_refs = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_slice_hwdec(struct AVCodecContext *s,
|
||||
const AVFrame *src, int offset[4],
|
||||
int y, int type, int height)
|
||||
{
|
||||
struct dec_video *vd = s->opaque;
|
||||
struct lavc_ctx *ctx = vd->priv;
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
struct vdp_functions *vdp = p->vdp;
|
||||
VdpStatus vdp_st;
|
||||
|
||||
if (handle_preemption(ctx) < 0)
|
||||
return;
|
||||
|
||||
struct vdpau_render_state *rndr = (void *)src->data[0];
|
||||
|
||||
int max_refs = p->image_format == IMGFMT_VDPAU_H264 ?
|
||||
rndr->info.h264.num_ref_frames : 2;
|
||||
if ((p->decoder == VDP_INVALID_HANDLE || p->decoder_max_refs < max_refs)
|
||||
&& !create_vdp_decoder(ctx, max_refs))
|
||||
return;
|
||||
|
||||
vdp_st = vdp->decoder_render(p->decoder, rndr->surface,
|
||||
(void *)&rndr->info,
|
||||
rndr->bitstream_buffers_used,
|
||||
rndr->bitstream_buffers);
|
||||
CHECK_VDP_WARNING(p, "Failed VDPAU decoder rendering");
|
||||
}
|
||||
|
||||
static void release_surface(void *ptr)
|
||||
{
|
||||
struct vdpau_render_state *state = ptr;
|
||||
// Free bitstream buffers allocated by libavcodec
|
||||
av_freep(&state->bitstream_buffers);
|
||||
talloc_free(state);
|
||||
}
|
||||
|
||||
static struct mp_image *allocate_image(struct lavc_ctx *ctx, int imgfmt,
|
||||
int w, int h)
|
||||
{
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
|
||||
if (!IMGFMT_IS_VDPAU(imgfmt))
|
||||
return NULL;
|
||||
|
||||
if (w != p->vid_width || h != p->vid_height || imgfmt != p->image_format) {
|
||||
p->vid_width = w;
|
||||
p->vid_height = h;
|
||||
p->image_format = imgfmt;
|
||||
if (!create_vdp_decoder(ctx, 2))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VdpChromaType chroma;
|
||||
mp_vdpau_get_format(p->image_format, &chroma, NULL);
|
||||
|
||||
struct mp_image *img =
|
||||
mp_vdpau_get_video_surface(p->mpvdp, imgfmt, chroma, w, h);
|
||||
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
// Create chained reference for vdpau_render_state. This will track the
|
||||
// lifetime of the actual reference too.
|
||||
// This is quite roundabout, but at least it allows us to share the
|
||||
// surface allocator in vo_vdpau.c with the new vdpau code.
|
||||
|
||||
struct vdpau_render_state *state = talloc_ptrtype(NULL, state);
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->surface = (VdpVideoSurface)(intptr_t)img->planes[3];
|
||||
|
||||
talloc_steal(state, img);
|
||||
|
||||
struct mp_image *new = mp_image_new_custom_ref(img, state, release_surface);
|
||||
new->planes[0] = (void *)state;
|
||||
return new;
|
||||
}
|
||||
|
||||
static void uninit(struct lavc_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (p->decoder != VDP_INVALID_HANDLE)
|
||||
p->vdp->decoder_destroy(p->decoder);
|
||||
|
||||
talloc_free(p);
|
||||
ctx->hwdec_priv = NULL;
|
||||
}
|
||||
|
||||
static int init(struct lavc_ctx *ctx)
|
||||
{
|
||||
struct priv *p = talloc_ptrtype(NULL, p);
|
||||
*p = (struct priv) {
|
||||
.log = mp_log_new(p, ctx->log, "vdpau"),
|
||||
.mpvdp = ctx->hwdec_info->vdpau_ctx,
|
||||
};
|
||||
ctx->hwdec_priv = p;
|
||||
|
||||
p->preemption_counter = p->mpvdp->preemption_counter;
|
||||
mark_uninitialized(ctx);
|
||||
|
||||
if (handle_preemption(ctx) < 0)
|
||||
return -1;
|
||||
|
||||
AVCodecContext *avctx = ctx->avctx;
|
||||
|
||||
avctx->draw_horiz_band = draw_slice_hwdec;
|
||||
avctx->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
|
||||
const char *decoder)
|
||||
{
|
||||
hwdec_request_api(info, "vdpau");
|
||||
if (!info || !info->vdpau_ctx)
|
||||
return HWDEC_ERR_NO_CTX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mp_image *process_image(struct lavc_ctx *ctx, struct mp_image *img)
|
||||
{
|
||||
// Make it follow the convention of the "new" vdpau decoder
|
||||
struct vdpau_render_state *rndr = (void *)img->planes[0];
|
||||
img->planes[0] = (void *)"dummy"; // must be non-NULL, otherwise arbitrary
|
||||
img->planes[3] = (void *)(intptr_t)rndr->surface;
|
||||
mp_image_setfmt(img, IMGFMT_VDPAU);
|
||||
return img;
|
||||
}
|
||||
|
||||
const struct vd_lavc_hwdec mp_vd_lavc_vdpau_old = {
|
||||
.type = HWDEC_VDPAU,
|
||||
.image_formats = (const int[]) {
|
||||
IMGFMT_VDPAU_MPEG1, IMGFMT_VDPAU_MPEG2, IMGFMT_VDPAU_H264,
|
||||
IMGFMT_VDPAU_WMV3, IMGFMT_VDPAU_VC1, IMGFMT_VDPAU_MPEG4,
|
||||
0
|
||||
},
|
||||
.codec_pairs = (const char *[]) {
|
||||
"h264", "h264_vdpau",
|
||||
"wmv3", "wmv3_vdpau",
|
||||
"vc1", "vc1_vdpau",
|
||||
"mpegvideo", "mpegvideo_vdpau",
|
||||
"mpeg1video", "mpeg1video_vdpau",
|
||||
"mpeg2video", "mpegvideo_vdpau",
|
||||
"mpeg2", "mpeg2_vdpau",
|
||||
"mpeg4", "mpeg4_vdpau",
|
||||
NULL
|
||||
},
|
||||
.probe = probe,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
.allocate_image = allocate_image,
|
||||
.process_image = process_image,
|
||||
};
|
@ -19,7 +19,6 @@
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/avutil.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "video/img_format.h"
|
||||
#include "fmt-conversion.h"
|
||||
|
||||
@ -68,9 +67,7 @@ static const struct {
|
||||
{IMGFMT_NV12, AV_PIX_FMT_NV12},
|
||||
{IMGFMT_NV21, AV_PIX_FMT_NV21},
|
||||
{IMGFMT_Y8, AV_PIX_FMT_GRAY8},
|
||||
// Support really ancient ffmpeg versions (before e91946ed23dfbb)
|
||||
// Newer versions use AV_PIX_FMT_GRAY8A
|
||||
{IMGFMT_YA8, AV_PIX_FMT_Y400A},
|
||||
{IMGFMT_YA8, AV_PIX_FMT_GRAY8A},
|
||||
{IMGFMT_Y16_LE, AV_PIX_FMT_GRAY16LE},
|
||||
{IMGFMT_Y16_BE, AV_PIX_FMT_GRAY16BE},
|
||||
{IMGFMT_410P, AV_PIX_FMT_YUV410P},
|
||||
@ -108,7 +105,6 @@ static const struct {
|
||||
|
||||
{IMGFMT_420AP, AV_PIX_FMT_YUVA420P},
|
||||
|
||||
#if LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 10, 0)
|
||||
{IMGFMT_422AP, AV_PIX_FMT_YUVA422P},
|
||||
{IMGFMT_444AP, AV_PIX_FMT_YUVA444P},
|
||||
|
||||
@ -132,13 +128,9 @@ static const struct {
|
||||
{IMGFMT_444AP10_LE, AV_PIX_FMT_YUVA444P10LE},
|
||||
{IMGFMT_444AP16_BE, AV_PIX_FMT_YUVA444P16BE},
|
||||
{IMGFMT_444AP16_LE, AV_PIX_FMT_YUVA444P16LE},
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 25, 0)
|
||||
// Libav added this already at 52.10.0
|
||||
{IMGFMT_XYZ12_LE, AV_PIX_FMT_XYZ12LE},
|
||||
{IMGFMT_XYZ12_BE, AV_PIX_FMT_XYZ12BE},
|
||||
#endif
|
||||
|
||||
// ffmpeg only
|
||||
#if LIBAVUTIL_VERSION_MICRO >= 100
|
||||
@ -178,19 +170,7 @@ static const struct {
|
||||
{IMGFMT_BGR0, AV_PIX_FMT_BGRA},
|
||||
#endif
|
||||
|
||||
#if HAVE_AVCODEC_NEW_VDPAU_API
|
||||
{IMGFMT_VDPAU, AV_PIX_FMT_VDPAU},
|
||||
#else
|
||||
{IMGFMT_VDPAU_MPEG1, AV_PIX_FMT_VDPAU_MPEG1},
|
||||
{IMGFMT_VDPAU_MPEG2, AV_PIX_FMT_VDPAU_MPEG2},
|
||||
{IMGFMT_VDPAU_H264, AV_PIX_FMT_VDPAU_H264},
|
||||
{IMGFMT_VDPAU_WMV3, AV_PIX_FMT_VDPAU_WMV3},
|
||||
{IMGFMT_VDPAU_VC1, AV_PIX_FMT_VDPAU_VC1},
|
||||
{IMGFMT_VDPAU_MPEG4, AV_PIX_FMT_VDPAU_MPEG4},
|
||||
// map to an arbitrary but existing vdpau format
|
||||
{IMGFMT_VDPAU, AV_PIX_FMT_VDPAU_H264},
|
||||
#endif
|
||||
|
||||
{IMGFMT_VDA, AV_PIX_FMT_VDA_VLD},
|
||||
{IMGFMT_VAAPI, AV_PIX_FMT_VAAPI_VLD},
|
||||
|
||||
|
@ -600,8 +600,6 @@ void mp_image_copy_fields_to_av_frame(struct AVFrame *dst,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_AVUTIL_REFCOUNTING
|
||||
|
||||
static void frame_free(void *p)
|
||||
{
|
||||
AVFrame *frame = p;
|
||||
@ -659,5 +657,3 @@ struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img)
|
||||
talloc_free(new_ref);
|
||||
return frame;
|
||||
}
|
||||
|
||||
#endif /* HAVE_AVUTIL_REFCOUNTING */
|
||||
|
27
wscript
27
wscript
@ -362,12 +362,6 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
|
||||
'func': check_true,
|
||||
'req': True,
|
||||
'fmsg': 'No resampler found. Install libavresample or libswresample (FFmpeg).'
|
||||
}, {
|
||||
'name': 'avcodec-new-vdpau-api',
|
||||
'desc': 'libavcodec new vdpau API',
|
||||
'func': check_statement('libavutil/pixfmt.h',
|
||||
'int x = AV_PIX_FMT_VDPAU',
|
||||
use='libav'),
|
||||
}, {
|
||||
'name': 'avcodec-chroma-pos-api',
|
||||
'desc': 'libavcodec avcodec_enum_to_chroma_pos API',
|
||||
@ -380,11 +374,6 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
|
||||
'func': check_statement('libavutil/frame.h',
|
||||
'av_frame_get_qp_table(NULL, NULL, NULL)',
|
||||
use='libav')
|
||||
}, {
|
||||
'name': 'avutil-refcounting',
|
||||
'desc': 'libavutil ref-counting API',
|
||||
'func': check_statement('libavutil/frame.h', 'av_frame_unref(NULL)',
|
||||
use='libav'),
|
||||
}, {
|
||||
'name': '--libavfilter',
|
||||
'desc': 'libavfilter',
|
||||
@ -395,12 +384,12 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
|
||||
}, {
|
||||
'name': '--vf-lavfi',
|
||||
'desc': 'using libavfilter through vf_lavfi',
|
||||
'deps': [ 'libavfilter', 'avutil-refcounting' ],
|
||||
'deps': [ 'libavfilter' ],
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--af-lavfi',
|
||||
'desc': 'using libavfilter through af_lavfi',
|
||||
'deps': [ 'libavfilter', 'avutil-refcounting' ],
|
||||
'deps': [ 'libavfilter' ],
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--libavdevice',
|
||||
@ -678,7 +667,7 @@ hwaccel_features = [
|
||||
} , {
|
||||
'name': '--vda-hwaccel',
|
||||
'desc': 'libavcodec VDA hwaccel',
|
||||
'deps': [ 'corevideo', 'avutil-refcounting'],
|
||||
'deps': [ 'corevideo'],
|
||||
'func': compose_checks(
|
||||
check_headers('VideoDecodeAcceleration/VDADecoder.h'),
|
||||
check_statement('libavcodec/vda.h',
|
||||
@ -697,16 +686,10 @@ hwaccel_features = [
|
||||
'desc': 'VDA with OpenGL',
|
||||
'deps': [ 'gl-cocoa', 'vda-hwaccel' ],
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--vdpau-decoder',
|
||||
'desc': 'VDPAU decoder (old)',
|
||||
'deps': [ 'vdpau' ],
|
||||
'deps_neg': ['avcodec-new-vdpau-api'],
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--vdpau-hwaccel',
|
||||
'desc': 'libavcodec VDPAU hwaccel (new)',
|
||||
'deps': [ 'vdpau', 'avcodec-new-vdpau-api' ],
|
||||
'desc': 'libavcodec VDPAU hwaccel',
|
||||
'deps': [ 'vdpau' ],
|
||||
'func': check_true,
|
||||
}
|
||||
]
|
||||
|
@ -291,12 +291,10 @@ def build(ctx):
|
||||
( "video/vaapi.c", "vaapi" ),
|
||||
( "video/vdpau.c", "vdpau" ),
|
||||
( "video/decode/dec_video.c"),
|
||||
( "video/decode/lavc_dr1.c", "!avutil-refcounting" ),
|
||||
( "video/decode/vaapi.c", "vaapi-hwaccel" ),
|
||||
( "video/decode/vd_lavc.c" ),
|
||||
( "video/decode/vda.c", "vda-hwaccel" ),
|
||||
( "video/decode/vdpau.c", "vdpau-hwaccel" ),
|
||||
( "video/decode/vdpau_old.c", "vdpau-decoder" ),
|
||||
( "video/filter/pullup.c" ),
|
||||
( "video/filter/vf.c" ),
|
||||
( "video/filter/vf_crop.c" ),
|
||||
|
Loading…
Reference in New Issue
Block a user