static int vdpau_alloc(AVCodecContext *s) { int loglevel = AV_LOG_ERROR; VDPAUContext *ctx; const char *display, *vendor; VdpStatus err; int ret; VdpDevice device; VdpGetProcAddress *get_proc_address; VdpGetInformationString *get_information_string; VDPAUHWDevicePriv *device_priv = NULL; AVHWDeviceContext *device_ctx; AVVDPAUDeviceContext *device_hwctx; AVHWFramesContext *frames_ctx; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM); device_priv = av_mallocz(sizeof(*device_priv)); if (!device_priv) { av_freep(&ctx); goto fail; } device_priv->dpy = XOpenDisplay(":0"); if (!device_priv->dpy) { av_log(NULL, loglevel, "Cannot open the X11 display %s.\n", XDisplayName(":0")); goto fail; } display = XDisplayString(device_priv->dpy); err = vdp_device_create_x11(device_priv->dpy, XDefaultScreen(device_priv->dpy), &device, &get_proc_address); if (err != VDP_STATUS_OK) { av_log(NULL, loglevel, "VDPAU device creation on X11 display %s failed.\n", display); goto fail; } #define GET_CALLBACK(id, result) \ do { \ void *tmp; \ err = get_proc_address(device, id, &tmp); \ if (err != VDP_STATUS_OK) { \ av_log(NULL, loglevel, "Error getting the " #id " callback.\n"); \ goto fail; \ } \ result = tmp; \ } while (0) GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string); GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, device_priv->device_destroy); device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VDPAU); if (!device_ref) goto fail; device_ctx = (AVHWDeviceContext*)device_ref->data; device_hwctx = device_ctx->hwctx; device_ctx->user_opaque = device_priv; device_ctx->free = device_free; device_hwctx->device = device; device_hwctx->get_proc_address = get_proc_address; device_priv = NULL; ret = av_hwdevice_ctx_init(device_ref); if (ret < 0) goto fail; ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); if (!ctx->hw_frames_ctx) goto fail; //av_buffer_unref(&device_ref); frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; frames_ctx->format = AV_PIX_FMT_VDPAU; frames_ctx->sw_format = s->sw_pix_fmt; frames_ctx->width = 1920; frames_ctx->height = 1080; ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); if (ret < 0) goto fail; if (av_vdpau_bind_context(s, device, get_proc_address, 0)) goto fail; s->opaque = ctx; return 0; fail: if (device_priv) { if (device_priv->device_destroy) device_priv->device_destroy(device); if (device_priv->dpy) XCloseDisplay(device_priv->dpy); } av_freep(&device_priv); av_buffer_unref(&device_ref); vdpau_uninit(s); return AVERROR(EINVAL); }
static int Open(vlc_va_t *va, AVCodecContext *avctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys) { if (pix_fmt != AV_PIX_FMT_VDPAU) return VLC_EGENERIC; (void) fmt; (void) p_sys; void *func; VdpStatus err; VdpChromaType type; uint32_t width, height; if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) return VLC_EGENERIC; switch (type) { case VDP_CHROMA_TYPE_420: case VDP_CHROMA_TYPE_422: case VDP_CHROMA_TYPE_444: break; default: msg_Err(va, "unsupported chroma type %"PRIu32, type); return VLC_EGENERIC; } if (!vlc_xlib_init(VLC_OBJECT(va))) { msg_Err(va, "Xlib is required for VDPAU"); return VLC_EGENERIC; } unsigned refs = avctx->refs + 2 * avctx->thread_count + 5; vlc_va_sys_t *sys = malloc(sizeof (*sys) + (refs + 1) * sizeof (sys->pool[0])); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->type = type; sys->width = width; sys->height = height; err = vdp_get_x11(NULL, -1, &sys->vdp, &sys->device); if (err != VDP_STATUS_OK) { free(sys); return VLC_EGENERIC; } unsigned flags = AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH; err = vdp_get_proc_address(sys->vdp, sys->device, VDP_FUNC_ID_GET_PROC_ADDRESS, &func); if (err != VDP_STATUS_OK) goto error; if (av_vdpau_bind_context(avctx, sys->device, func, flags)) goto error; va->sys = sys; unsigned i = 0; while (i < refs) { sys->pool[i] = CreateSurface(va); if (sys->pool[i] == NULL) break; i++; } sys->pool[i] = NULL; if (i < avctx->refs + 3u) { msg_Err(va, "not enough video RAM"); while (i > 0) DestroySurface(sys->pool[--i]); goto error; } if (i < refs) msg_Warn(va, "video RAM low (allocated %u of %u buffers)", i, refs); const char *infos; if (vdp_get_information_string(sys->vdp, &infos) != VDP_STATUS_OK) infos = "VDPAU"; va->description = infos; va->get = Lock; va->release = NULL; va->extract = Copy; return VLC_SUCCESS; error: vdp_release_x11(sys->vdp); free(sys); return VLC_EGENERIC; }