diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2017-02-12 01:01:56 +0100 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2017-02-12 01:01:56 +0100 |
commit | 35aa705c3ece8293652ffcf449c71fe80b96e722 (patch) | |
tree | 7c0fb34ec96204cbcd867a973b2476689919a5b4 /video/decode | |
parent | 10a005df0c981050afc35184a42173bea7ea2527 (diff) | |
parent | 3739d1318fdb658bb6037bfe06bb6cefb3b50a09 (diff) | |
download | mpv-35aa705c3ece8293652ffcf449c71fe80b96e722.tar.bz2 mpv-35aa705c3ece8293652ffcf449c71fe80b96e722.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/dec_video.c | 100 | ||||
-rw-r--r-- | video/decode/dec_video.h | 3 | ||||
-rw-r--r-- | video/decode/hw_cuda.c (renamed from video/decode/cuda.c) | 41 | ||||
-rw-r--r-- | video/decode/hw_d3d11va.c (renamed from video/decode/d3d11va.c) | 2 | ||||
-rw-r--r-- | video/decode/hw_dxva2.c (renamed from video/decode/dxva2.c) | 47 | ||||
-rw-r--r-- | video/decode/hw_vaapi.c | 171 | ||||
-rw-r--r-- | video/decode/hw_vaapi_old.c (renamed from video/decode/vaapi.c) | 166 | ||||
-rw-r--r-- | video/decode/hw_vdpau.c (renamed from video/decode/vdpau.c) | 56 | ||||
-rw-r--r-- | video/decode/hw_videotoolbox.c (renamed from video/decode/videotoolbox.c) | 0 | ||||
-rw-r--r-- | video/decode/lavc.h | 25 | ||||
-rw-r--r-- | video/decode/vd.h | 9 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 362 |
12 files changed, 551 insertions, 431 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index d9dbf0f326..23aba81709 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -33,6 +33,7 @@ #include "demux/packet.h" #include "common/codecs.h" +#include "common/recorder.h" #include "video/out/vo.h" #include "video/csputils.h" @@ -89,7 +90,6 @@ void video_uninit(struct dec_video *d_video) if (!d_video) return; mp_image_unrefp(&d_video->current_mpi); - mp_image_unrefp(&d_video->cover_art_mpi); if (d_video->vd_driver) { MP_VERBOSE(d_video, "Uninit video.\n"); d_video->vd_driver->uninit(d_video); @@ -252,36 +252,53 @@ static void fix_image_params(struct dec_video *d_video, d_video->fixed_format = p; } -static struct mp_image *decode_packet(struct dec_video *d_video, - struct demux_packet *packet, - int drop_frame) +static bool send_packet(struct dec_video *d_video, struct demux_packet *packet) { - struct MPOpts *opts = d_video->opts; - - if (!d_video->vd_driver) - return NULL; - double pkt_pts = packet ? packet->pts : MP_NOPTS_VALUE; double pkt_dts = packet ? packet->dts : MP_NOPTS_VALUE; if (pkt_pts == MP_NOPTS_VALUE) d_video->has_broken_packet_pts = 1; + bool dts_replaced = false; + if (packet && packet->dts == MP_NOPTS_VALUE && !d_video->codec->avi_dts) { + packet->dts = packet->pts; + dts_replaced = true; + } + double pkt_pdts = pkt_pts == MP_NOPTS_VALUE ? pkt_dts : pkt_pts; if (pkt_pdts != MP_NOPTS_VALUE && d_video->first_packet_pdts == MP_NOPTS_VALUE) d_video->first_packet_pdts = pkt_pdts; MP_STATS(d_video, "start decode video"); - struct mp_image *mpi = d_video->vd_driver->decode(d_video, packet, drop_frame); + bool res = d_video->vd_driver->send_packet(d_video, packet); MP_STATS(d_video, "end decode video"); - // Error, discarded frame, dropped frame, or initial codec delay. - if (!mpi || drop_frame) { - talloc_free(mpi); - return NULL; - } + // Stream recording can't deal with almost surely wrong fake DTS. + if (dts_replaced) + packet->dts = MP_NOPTS_VALUE; + + return res; +} + +static bool receive_frame(struct dec_video *d_video, struct mp_image **out_image) +{ + struct MPOpts *opts = d_video->opts; + struct mp_image *mpi = NULL; + + assert(!*out_image); + + MP_STATS(d_video, "start decode video"); + + bool progress = d_video->vd_driver->receive_frame(d_video, &mpi); + + MP_STATS(d_video, "end decode video"); + + // Error, EOF, discarded frame, dropped frame, or initial codec delay. + if (!mpi) + return progress; if (opts->field_dominance == 0) { mpi->fields |= MP_IMGFIELD_TOP_FIRST | MP_IMGFIELD_INTERLACED; @@ -353,7 +370,8 @@ static struct mp_image *decode_packet(struct dec_video *d_video, mpi->pts -= MPMAX(delay, 0) / d_video->fps; } - return mpi; + *out_image = mpi; + return true; } void video_reset_params(struct dec_video *d_video) @@ -379,24 +397,8 @@ void video_set_start(struct dec_video *d_video, double start_pts) void video_work(struct dec_video *d_video) { - if (d_video->current_mpi) - return; - - if (d_video->header->attached_picture) { - if (d_video->current_state == DATA_AGAIN && !d_video->cover_art_mpi) { - struct demux_packet *packet = - demux_copy_packet(d_video->header->attached_picture); - d_video->cover_art_mpi = decode_packet(d_video, packet, 0); - // Might need flush. - if (!d_video->cover_art_mpi) - d_video->cover_art_mpi = decode_packet(d_video, NULL, 0); - talloc_free(packet); - } - if (d_video->current_state != DATA_EOF) - d_video->current_mpi = mp_image_new_ref(d_video->cover_art_mpi); - d_video->current_state = DATA_EOF; + if (d_video->current_mpi || !d_video->vd_driver) return; - } if (!d_video->packet && !d_video->new_segment && demux_read_packet_async(d_video->header, &d_video->packet) == 0) @@ -405,20 +407,12 @@ void video_work(struct dec_video *d_video) return; } - if (d_video->packet) { - if (d_video->packet->dts == MP_NOPTS_VALUE && !d_video->codec->avi_dts) - d_video->packet->dts = d_video->packet->pts; - } - if (d_video->packet && d_video->packet->new_segment) { assert(!d_video->new_segment); d_video->new_segment = d_video->packet; d_video->packet = NULL; } - bool had_input_packet = !!d_video->packet; - bool had_packet = had_input_packet || d_video->new_segment; - double start_pts = d_video->start_pts; if (d_video->start != MP_NOPTS_VALUE && (start_pts == MP_NOPTS_VALUE || d_video->start > start_pts)) @@ -431,23 +425,29 @@ void video_work(struct dec_video *d_video) { framedrop_type = 2; } - d_video->current_mpi = decode_packet(d_video, d_video->packet, framedrop_type); - if (d_video->packet && d_video->packet->len == 0) { + + d_video->vd_driver->control(d_video, VDCTRL_SET_FRAMEDROP, &framedrop_type); + + if (send_packet(d_video, d_video->packet)) { + if (d_video->recorder_sink) + mp_recorder_feed_packet(d_video->recorder_sink, d_video->packet); + talloc_free(d_video->packet); d_video->packet = NULL; } + bool progress = receive_frame(d_video, &d_video->current_mpi); + d_video->current_state = DATA_OK; - if (!d_video->current_mpi) { + if (!progress) { d_video->current_state = DATA_EOF; - if (had_packet) { - if (framedrop_type == 1) - d_video->dropped_frames += 1; - d_video->current_state = DATA_AGAIN; - } + } else if (!d_video->current_mpi) { + if (framedrop_type == 1) + d_video->dropped_frames += 1; + d_video->current_state = DATA_AGAIN; } - bool segment_ended = !d_video->current_mpi && !had_input_packet; + bool segment_ended = d_video->current_state == DATA_EOF; if (d_video->current_mpi && d_video->current_mpi->pts != MP_NOPTS_VALUE) { double vpts = d_video->current_mpi->pts; diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 1d2b3f087e..5ef1f9252a 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -42,6 +42,8 @@ struct dec_video { int dropped_frames; + struct mp_recorder_sink *recorder_sink; + // Internal (shared with vd_lavc.c). void *priv; // for free use by vd_driver @@ -75,7 +77,6 @@ struct dec_video { struct demux_packet *new_segment; struct demux_packet *packet; bool framedrop_enabled; - struct mp_image *cover_art_mpi; struct mp_image *current_mpi; int current_state; }; diff --git a/video/decode/cuda.c b/video/decode/hw_cuda.c index cad02b2353..92ba0772c4 100644 --- a/video/decode/cuda.c +++ b/video/decode/hw_cuda.c @@ -38,54 +38,45 @@ static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, static int init(struct lavc_ctx *ctx) { - ctx->hwdec_priv = hwdec_devices_get(ctx->hwdec_devs, HWDEC_CUDA)->ctx; + ctx->hwdec_priv = hwdec_devices_get(ctx->hwdec_devs, HWDEC_CUDA); return 0; } static int init_decoder(struct lavc_ctx *ctx, int w, int h) { AVCodecContext *avctx = ctx->avctx; - AVCUDADeviceContext *device_hwctx; - AVHWDeviceContext *device_ctx; - AVHWFramesContext *hwframe_ctx; - int ret = 0; + struct mp_hwdec_ctx *hwctx = ctx->hwdec_priv; if (avctx->hw_frames_ctx) { MP_ERR(ctx, "hw_frames_ctx already initialised!\n"); return -1; } - AVBufferRef *hw_device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA); - if (!hw_device_ctx) { - MP_WARN(ctx, "av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA) failed\n"); - goto error; - } - - device_ctx = (AVHWDeviceContext*)hw_device_ctx->data; - - device_hwctx = device_ctx->hwctx; - device_hwctx->cuda_ctx = ctx->hwdec_priv; - - ret = av_hwdevice_ctx_init(hw_device_ctx); - if (ret < 0) { - MP_ERR(ctx, "av_hwdevice_ctx_init failed\n"); - goto error; - } - - avctx->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(hwctx->av_device_ref); if (!avctx->hw_frames_ctx) { MP_ERR(ctx, "av_hwframe_ctx_alloc failed\n"); goto error; } - hwframe_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + AVHWFramesContext *hwframe_ctx = (void* )avctx->hw_frames_ctx->data; hwframe_ctx->format = AV_PIX_FMT_CUDA; + // This is proper use of the hw_frames_ctx API, but it does not work + // (appaears to work but fails e.g. with 10 bit). The cuvid wrapper + // does non-standard things, and it's a meesy situation. + /* + hwframe_ctx->width = w; + hwframe_ctx->height = h; + hwframe_ctx->sw_format = avctx->sw_pix_fmt; + + if (av_hwframe_ctx_init(avctx->hw_frames_ctx) < 0) + goto error; + */ + return 0; error: av_buffer_unref(&avctx->hw_frames_ctx); - av_buffer_unref(&hw_device_ctx); return -1; } diff --git a/video/decode/d3d11va.c b/video/decode/hw_d3d11va.c index e31582d37c..a69a3890bd 100644 --- a/video/decode/d3d11va.c +++ b/video/decode/hw_d3d11va.c @@ -27,7 +27,7 @@ #include "d3d.h" -#define ADDITIONAL_SURFACES (4 + HWDEC_DELAY_QUEUE_COUNT) +#define ADDITIONAL_SURFACES (HWDEC_EXTRA_SURFACES + HWDEC_DELAY_QUEUE_COUNT) struct d3d11va_decoder { ID3D11VideoDecoder *decoder; diff --git a/video/decode/dxva2.c b/video/decode/hw_dxva2.c index ab91c186df..7b1a6b4bc7 100644 --- a/video/decode/dxva2.c +++ b/video/decode/hw_dxva2.c @@ -32,7 +32,7 @@ #include "d3d.h" -#define ADDITIONAL_SURFACES (4 + HWDEC_DELAY_QUEUE_COUNT) +#define ADDITIONAL_SURFACES (HWDEC_EXTRA_SURFACES + HWDEC_DELAY_QUEUE_COUNT) struct priv { struct mp_log *log; @@ -357,44 +357,53 @@ static bool create_device(struct lavc_ctx *s) return false; } - IDirect3D9* (WINAPI *Direct3DCreate9)(UINT) = - (void *)GetProcAddress(d3d9_dll, "Direct3DCreate9"); - if (!Direct3DCreate9) { - MP_ERR(p, "Failed to locate Direct3DCreate9\n"); + HRESULT (WINAPI *Direct3DCreate9Ex)(UINT, IDirect3D9Ex **) = + (void *)GetProcAddress(d3d9_dll, "Direct3DCreate9Ex"); + if (!Direct3DCreate9Ex) { + MP_ERR(p, "Failed to locate Direct3DCreate9Ex\n"); return false; } - p->d3d9 = Direct3DCreate9(D3D_SDK_VERSION); - if (!p->d3d9) { - MP_ERR(p, "Failed to create IDirect3D object\n"); + IDirect3D9Ex *d3d9ex = NULL; + HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex); + if (FAILED(hr)) { + MP_ERR(p, "Failed to create IDirect3D9Ex object\n"); return false; } UINT adapter = D3DADAPTER_DEFAULT; - D3DDISPLAYMODE display_mode; - IDirect3D9_GetAdapterDisplayMode(p->d3d9, adapter, &display_mode); + D3DDISPLAYMODEEX modeex = {0}; + IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL); + D3DPRESENT_PARAMETERS present_params = { .Windowed = TRUE, .BackBufferWidth = 640, .BackBufferHeight = 480, .BackBufferCount = 0, - .BackBufferFormat = display_mode.Format, + .BackBufferFormat = modeex.Format, .SwapEffect = D3DSWAPEFFECT_DISCARD, .Flags = D3DPRESENTFLAG_VIDEO, }; - HRESULT hr = IDirect3D9_CreateDevice(p->d3d9, adapter, - D3DDEVTYPE_HAL, - GetShellWindow(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING | - D3DCREATE_MULTITHREADED | - D3DCREATE_FPU_PRESERVE, - &present_params, - &p->device); + + IDirect3DDevice9Ex *exdev = NULL; + hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, adapter, + D3DDEVTYPE_HAL, + GetShellWindow(), + D3DCREATE_SOFTWARE_VERTEXPROCESSING | + D3DCREATE_MULTITHREADED | + D3DCREATE_FPU_PRESERVE, + &present_params, + NULL, + &exdev); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D device: %s\n", mp_HRESULT_to_str(hr)); + IDirect3D9_Release(d3d9ex); return false; } + + p->d3d9 = (IDirect3D9 *)d3d9ex; + p->device = (IDirect3DDevice9 *)exdev; return true; } diff --git a/video/decode/hw_vaapi.c b/video/decode/hw_vaapi.c new file mode 100644 index 0000000000..99c23f48c4 --- /dev/null +++ b/video/decode/hw_vaapi.c @@ -0,0 +1,171 @@ +/* + * This file is part of mpv. + * + * mpv 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. + * + * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stddef.h> +#include <assert.h> + +#include <libavcodec/avcodec.h> +#include <libavutil/common.h> +#include <libavutil/hwcontext.h> +#include <libavutil/hwcontext_vaapi.h> + +#include "config.h" + +#include "lavc.h" +#include "common/common.h" +#include "common/av_common.h" +#include "video/fmt-conversion.h" +#include "video/vaapi.h" +#include "video/mp_image_pool.h" +#include "video/hwdec.h" +#include "video/filter/vf.h" + +#define ADDITIONAL_SURFACES (HWDEC_EXTRA_SURFACES + HWDEC_DELAY_QUEUE_COUNT) + +struct priv { + struct mp_log *log; + struct mp_vaapi_ctx *ctx; + struct mp_hwdec_ctx *hwdev; +}; + +static int init_decoder(struct lavc_ctx *ctx, int w, int h) +{ + struct priv *p = ctx->hwdec_priv; + // libavcodec has no way yet to communicate the exact surface format needed + // for the frame pool, or the required minimum size of the frame pool. + // Hopefully, this weakness in the libavcodec API will be fixed in the + // future. + // For the pixel format, we try to second-guess from what the libavcodec + // software decoder would require (sw_pix_fmt). It could break and require + // adjustment if new VAAPI surface formats are added. + int sw_format = ctx->avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + + // The video output might not support all formats. + // Note that supported_formats==NULL means any are accepted. + if (p->hwdev && p->hwdev->supported_formats) { + int mp_format = pixfmt2imgfmt(sw_format); + bool found = false; + for (int n = 0; p->hwdev->supported_formats[n]; n++) { + if (p->hwdev->supported_formats[n] == mp_format) { + found = true; + break; + } + } + if (!found) { + MP_WARN(ctx, "Surface format %s not supported for direct rendering.\n", + mp_imgfmt_to_name(mp_format)); + return -1; + } + } + + return hwdec_setup_hw_frames_ctx(ctx, p->ctx->av_device_ref, sw_format, + hwdec_get_max_refs(ctx) + ADDITIONAL_SURFACES); +} + +static void uninit(struct lavc_ctx *ctx) +{ + struct priv *p = ctx->hwdec_priv; + + if (!p) + return; + + if (!p->hwdev) + va_destroy(p->ctx); + + talloc_free(p); + ctx->hwdec_priv = NULL; +} + +static int init(struct lavc_ctx *ctx, bool direct) +{ + struct priv *p = talloc_ptrtype(NULL, p); + *p = (struct priv) { + .log = mp_log_new(p, ctx->log, "vaapi"), + }; + + if (direct) { + p->hwdev = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VAAPI); + p->ctx = p->hwdev->ctx; + } else { + p->ctx = va_create_standalone(ctx->log, false); + if (!p->ctx) { + talloc_free(p); + return -1; + } + } + + ctx->hwdec_priv = p; + + if (!p->ctx->av_device_ref) + return -1; + + return 0; +} + +static int init_direct(struct lavc_ctx *ctx) +{ + return init(ctx, true); +} + +static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, + const char *codec) +{ + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VAAPI)) + return HWDEC_ERR_NO_CTX; + return 0; +} + +static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, + const char *codec) +{ + struct mp_vaapi_ctx *dummy = va_create_standalone(ctx->log, true); + if (!dummy) + return HWDEC_ERR_NO_CTX; + bool emulated = va_guess_if_emulated(dummy); + va_destroy(dummy); + if (emulated) + return HWDEC_ERR_EMULATED; + return 0; +} + +static int init_copy(struct lavc_ctx *ctx) +{ + return init(ctx, false); +} + +const struct vd_lavc_hwdec mp_vd_lavc_vaapi = { + .type = HWDEC_VAAPI, + .image_format = IMGFMT_VAAPI, + .volatile_context = true, + .probe = probe, + .init = init_direct, + .uninit = uninit, + .init_decoder = init_decoder, +}; + +const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = { + .type = HWDEC_VAAPI_COPY, + .copying = true, + .image_format = IMGFMT_VAAPI, + .volatile_context = true, + .probe = probe_copy, + .init = init_copy, + .uninit = uninit, + .init_decoder = init_decoder, + .delay_queue = HWDEC_DELAY_QUEUE_COUNT, +}; diff --git a/video/decode/vaapi.c b/video/decode/hw_vaapi_old.c index c095868816..88379dfed8 100644 --- a/video/decode/vaapi.c +++ b/video/decode/hw_vaapi_old.c @@ -52,11 +52,9 @@ struct priv { struct mp_log *log; struct mp_vaapi_ctx *ctx; + bool own_ctx; VADisplay display; - const struct va_native_display *native_display_fns; - void *native_display; - // libavcodec shared struct struct vaapi_context *va_context; struct vaapi_context va_context_storage; @@ -67,98 +65,6 @@ struct priv { struct mp_image_pool *sw_pool; }; -struct va_native_display { - void (*create)(struct priv *p); - void (*destroy)(struct priv *p); -}; - -#if HAVE_VAAPI_X11 -#include <X11/Xlib.h> -#include <va/va_x11.h> - -static void x11_destroy(struct priv *p) -{ - if (p->native_display) - XCloseDisplay(p->native_display); - p->native_display = NULL; -} - -static void x11_create(struct priv *p) -{ - p->native_display = XOpenDisplay(NULL); - if (!p->native_display) - return; - p->display = vaGetDisplay(p->native_display); - if (!p->display) - x11_destroy(p); -} - -static const struct va_native_display disp_x11 = { - .create = x11_create, - .destroy = x11_destroy, -}; -#endif - -#if HAVE_VAAPI_DRM -#include <unistd.h> -#include <fcntl.h> -#include <va/va_drm.h> - -struct va_native_display_drm { - int drm_fd; -}; - -static void drm_destroy(struct priv *p) -{ - struct va_native_display_drm *native_display = p->native_display; - if (native_display) { - if (native_display->drm_fd >= 0) - close(native_display->drm_fd); - talloc_free(native_display); - p->native_display = NULL; - } -} - -static void drm_create(struct priv *p) -{ - static const char *drm_device_paths[] = { - "/dev/dri/renderD128", - "/dev/dri/card0", - NULL - }; - - for (int i = 0; drm_device_paths[i]; i++) { - int drm_fd = open(drm_device_paths[i], O_RDWR); - if (drm_fd < 0) - continue; - - struct va_native_display_drm *native_display = talloc_ptrtype(NULL, native_display); - native_display->drm_fd = drm_fd; - p->native_display = native_display; - p->display = vaGetDisplayDRM(drm_fd); - if (p->display) - return; - - drm_destroy(p); - } -} - -static const struct va_native_display disp_drm = { - .create = drm_create, - .destroy = drm_destroy, -}; -#endif - -static const struct va_native_display *const native_displays[] = { -#if HAVE_VAAPI_DRM - &disp_drm, -#endif -#if HAVE_VAAPI_X11 - &disp_x11, -#endif - NULL -}; - #define HAS_HEVC VA_CHECK_VERSION(0, 38, 0) #define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0)) @@ -264,8 +170,6 @@ static void destroy_decoder(struct lavc_ctx *ctx) { struct priv *p = ctx->hwdec_priv; - va_lock(p->ctx); - if (p->va_context->context_id != VA_INVALID_ID) { vaDestroyContext(p->display, p->va_context->context_id); p->va_context->context_id = VA_INVALID_ID; @@ -276,8 +180,6 @@ static void destroy_decoder(struct lavc_ctx *ctx) p->va_context->config_id = VA_INVALID_ID; } - va_unlock(p->ctx); - mp_image_pool_clear(p->pool); } @@ -300,8 +202,6 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h) destroy_decoder(ctx); - va_lock(p->ctx); - const struct hwdec_profile_entry *pe = hwdec_find_profile(ctx, profiles); if (!pe) { MP_ERR(p, "Unsupported codec or profile.\n"); @@ -376,7 +276,6 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h) res = 0; error: - va_unlock(p->ctx); talloc_free(tmp); return res; } @@ -397,40 +296,6 @@ static struct mp_image *update_format(struct lavc_ctx *ctx, struct mp_image *img return img; } -static void destroy_va_dummy_ctx(struct priv *p) -{ - va_destroy(p->ctx); - p->ctx = NULL; - p->display = NULL; - if (p->native_display_fns) - p->native_display_fns->destroy(p); -} - -// Creates a "private" VADisplay, disconnected from the VO. We just create a -// new X connection, because that's simpler. (We could also pass the X -// connection along with struct mp_hwdec_devices, if we wanted.) -static bool create_va_dummy_ctx(struct priv *p) -{ - for (int n = 0; native_displays[n]; n++) { - native_displays[n]->create(p); - if (p->display) { - p->native_display_fns = native_displays[n]; - break; - } - } - if (!p->display) - goto destroy_ctx; - p->ctx = va_initialize(p->display, p->log, true); - if (!p->ctx) { - vaTerminate(p->display); - goto destroy_ctx; - } - return true; -destroy_ctx: - destroy_va_dummy_ctx(p); - return false; -} - static void uninit(struct lavc_ctx *ctx) { struct priv *p = ctx->hwdec_priv; @@ -443,8 +308,8 @@ static void uninit(struct lavc_ctx *ctx) talloc_free(p->pool); p->pool = NULL; - if (p->native_display_fns) - destroy_va_dummy_ctx(p); + if (p->own_ctx) + va_destroy(p->ctx); talloc_free(p); ctx->hwdec_priv = NULL; @@ -462,11 +327,12 @@ static int init(struct lavc_ctx *ctx, bool direct) if (direct) { p->ctx = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VAAPI)->ctx; } else { - create_va_dummy_ctx(p); + p->ctx = va_create_standalone(ctx->log, false); if (!p->ctx) { talloc_free(p); return -1; } + p->own_ctx = true; } p->display = p->ctx->display; @@ -502,11 +368,11 @@ static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - struct priv dummy = {mp_null_log}; - if (!create_va_dummy_ctx(&dummy)) + struct mp_vaapi_ctx *dummy = va_create_standalone(ctx->log, true); + if (!dummy) return HWDEC_ERR_NO_CTX; - bool emulated = va_guess_if_emulated(dummy.ctx); - destroy_va_dummy_ctx(&dummy); + bool emulated = va_guess_if_emulated(dummy); + va_destroy(dummy); if (!hwdec_check_codec_support(codec, profiles)) return HWDEC_ERR_NO_CODEC; if (emulated) @@ -531,18 +397,6 @@ static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img) return img; } -static void intel_shit_lock(struct lavc_ctx *ctx) -{ - struct priv *p = ctx->hwdec_priv; - va_lock(p->ctx); -} - -static void intel_crap_unlock(struct lavc_ctx *ctx) -{ - struct priv *p = ctx->hwdec_priv; - va_unlock(p->ctx); -} - const struct vd_lavc_hwdec mp_vd_lavc_vaapi = { .type = HWDEC_VAAPI, .image_format = IMGFMT_VAAPI, @@ -551,8 +405,6 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = { .uninit = uninit, .init_decoder = init_decoder, .allocate_image = allocate_image, - .lock = intel_shit_lock, - .unlock = intel_crap_unlock, .process_image = update_format, }; diff --git a/video/decode/vdpau.c b/video/decode/hw_vdpau.c index a6b6210804..6047ef1360 100644 --- a/video/decode/vdpau.c +++ b/video/decode/hw_vdpau.c @@ -18,6 +18,7 @@ #include <libavcodec/avcodec.h> #include <libavcodec/vdpau.h> #include <libavutil/common.h> +#include <libavutil/hwcontext.h> #include "lavc.h" #include "common/common.h" @@ -31,12 +32,20 @@ struct priv { uint64_t preemption_counter; // vdpau-copy Display *display; - struct mp_image_pool *sw_pool; }; static int init_decoder(struct lavc_ctx *ctx, int w, int h) { struct priv *p = ctx->hwdec_priv; + int sw_format = ctx->avctx->sw_pix_fmt; + + if (sw_format != AV_PIX_FMT_YUV420P && sw_format != AV_PIX_FMT_NV12) { + MP_VERBOSE(ctx, "Rejecting non 4:2:0 8 bit decoding.\n"); + return -1; + } + + if (hwdec_setup_hw_frames_ctx(ctx, p->mpvdp->av_device_ref, sw_format, 0) < 0) + return -1; // During preemption, pretend everything is ok. if (mp_vdpau_handle_preemption(p->mpvdp, &p->preemption_counter) < 0) @@ -48,34 +57,6 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h) AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH); } -static struct mp_image *allocate_image(struct lavc_ctx *ctx, int w, int h) -{ - struct priv *p = ctx->hwdec_priv; - - // In case of preemption, reinit the decoder. Setting hwdec_request_reinit - // will cause init_decoder() to be called again. - if (mp_vdpau_handle_preemption(p->mpvdp, &p->preemption_counter) == 0) - ctx->hwdec_request_reinit = true; - - VdpChromaType chroma = 0; - uint32_t s_w = w, s_h = h; - if (av_vdpau_get_surface_parameters(ctx->avctx, &chroma, &s_w, &s_h) < 0) - return NULL; - - return mp_vdpau_get_video_surface(p->mpvdp, chroma, s_w, s_h); -} - -static struct mp_image *update_format(struct lavc_ctx *ctx, struct mp_image *img) -{ - VdpChromaType chroma = 0; - uint32_t s_w, s_h; - if (av_vdpau_get_surface_parameters(ctx->avctx, &chroma, &s_w, &s_h) >= 0) { - if (chroma == VDP_CHROMA_TYPE_420) - img->params.hw_subfmt = IMGFMT_NV12; - } - return img; -} - static void uninit(struct lavc_ctx *ctx) { struct priv *p = ctx->hwdec_priv; @@ -128,8 +109,6 @@ static int init_copy(struct lavc_ctx *ctx) if (!p->mpvdp) goto error; - p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); - ctx->hwdec_priv = p; mp_vdpau_handle_preemption(p->mpvdp, &p->preemption_counter); @@ -156,15 +135,6 @@ static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, return r; } -static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img) -{ - struct priv *p = ctx->hwdec_priv; - struct mp_hwdec_ctx *hwctx = &p->mpvdp->hwctx; - struct mp_image *out = hwctx->download_image(hwctx, img, p->sw_pool); - talloc_free(img); - return out; -} - const struct vd_lavc_hwdec mp_vd_lavc_vdpau = { .type = HWDEC_VDPAU, .image_format = IMGFMT_VDPAU, @@ -172,8 +142,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vdpau = { .init = init, .uninit = uninit, .init_decoder = init_decoder, - .allocate_image = allocate_image, - .process_image = update_format, + .volatile_context = true, }; const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy = { @@ -184,6 +153,5 @@ const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy = { .init = init_copy, .uninit = uninit, .init_decoder = init_decoder, - .allocate_image = allocate_image, - .process_image = copy_image, + .volatile_context = true, }; diff --git a/video/decode/videotoolbox.c b/video/decode/hw_videotoolbox.c index c6f1a472bf..c6f1a472bf 100644 --- a/video/decode/videotoolbox.c +++ b/video/decode/hw_videotoolbox.c diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 993c3ec437..fd1c7feb42 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h |