1
mirror of https://github.com/mpv-player/mpv synced 2024-11-03 03:19:24 +01:00
mpv/video/vdpau.h
wm4 b40d8fdfa3 vdpau: get surface data as nv12 if possible
For now, this affects taking screenshots only.

If the video mixer is actually needed, we want to go through the video
mixer for screenshots too - which is why this function simply always
used the video mixer, and then copied the surface to RAM as RGBA.

Add reading the surface as nv12 if possible. If the format is correct,
and no special video processing (like deinterlacing) is used, then it's
read directly without going through the video mixer.

There's no particular reason for doing this, other than avoiding the
video mixer (like vo_opengl can do it now). Also, the next commit will
make use of this in vf_vdpaurb.c.
2016-06-21 21:31:58 +02:00

105 lines
3.2 KiB
C

#ifndef MPV_VDPAU_H
#define MPV_VDPAU_H
#include <stdbool.h>
#include <inttypes.h>
#include <pthread.h>
#include <vdpau/vdpau.h>
#include <vdpau/vdpau_x11.h>
#include "common/msg.h"
#include "hwdec.h"
#define CHECK_VDP_ERROR_ST(ctx, message, statement) \
do { \
if (vdp_st != VDP_STATUS_OK) { \
MP_ERR(ctx, "%s: %s\n", message, vdp->get_error_string(vdp_st)); \
statement \
} \
} while (0)
#define CHECK_VDP_ERROR(ctx, message) \
CHECK_VDP_ERROR_ST(ctx, message, return -1;)
#define CHECK_VDP_ERROR_NORETURN(ctx, message) \
CHECK_VDP_ERROR_ST(ctx, message, ;)
#define CHECK_VDP_WARNING(ctx, message) \
do { \
if (vdp_st != VDP_STATUS_OK) \
MP_WARN(ctx, "%s: %s\n", message, vdp->get_error_string(vdp_st)); \
} while (0)
struct vdp_functions {
#define VDP_FUNCTION(vdp_type, _, mp_name) vdp_type *mp_name;
#include "video/vdpau_functions.inc"
#undef VDP_FUNCTION
};
#define MAX_VIDEO_SURFACES 50
// Shared state. Objects created from different VdpDevices are often (always?)
// incompatible to each other, so all code must use a shared VdpDevice.
struct mp_vdpau_ctx {
struct mp_log *log;
Display *x11;
struct mp_hwdec_ctx hwctx;
// These are mostly immutable, except on preemption. We don't really care
// to synchronize the preemption case fully correctly, because it's an
// extremely obscure corner case, and basically a vdpau API design bug.
// What we do will sort-of work anyway (no memory errors are possible).
struct vdp_functions vdp;
VdpGetProcAddress *get_proc_address;
VdpDevice vdp_device;
pthread_mutex_t preempt_lock;
bool is_preempted; // set to true during unavailability
uint64_t preemption_counter; // incremented after _restoring_
bool preemption_user_notified;
double last_preemption_retry_fail;
VdpOutputSurface preemption_obj; // dummy for reliable preempt. check
// Surface pool
pthread_mutex_t pool_lock;
int64_t age_counter;
struct surface_entry {
VdpVideoSurface surface;
VdpOutputSurface osurface;
bool allocated;
int w, h;
VdpRGBAFormat rgb_format;
VdpChromaType chroma;
bool rgb;
bool in_use;
int64_t age;
} video_surfaces[MAX_VIDEO_SURFACES];
struct mp_vdpau_mixer *getimg_mixer;
VdpOutputSurface getimg_surface;
int getimg_w, getimg_h;
};
struct mp_vdpau_ctx *mp_vdpau_create_device_x11(struct mp_log *log, Display *x11,
bool probing);
void mp_vdpau_destroy(struct mp_vdpau_ctx *ctx);
int mp_vdpau_handle_preemption(struct mp_vdpau_ctx *ctx, uint64_t *counter);
struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
VdpChromaType chroma, int w, int h);
bool mp_vdpau_get_format(int imgfmt, VdpChromaType *out_chroma_type,
VdpYCbCrFormat *out_pixel_format);
bool mp_vdpau_get_rgb_format(int imgfmt, VdpRGBAFormat *out_rgba_format);
struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
struct mp_image *mpi);
bool mp_vdpau_guess_if_emulated(struct mp_vdpau_ctx *ctx);
#endif