static int vdp_device_Create (vlc_object_t *obj, void **sysp, VdpDevice *devp, VdpGetProcAddress **gpap) { VdpStatus err; if (!vlc_xlib_init (obj)) { msg_Err (obj, "Xlib is required for VDPAU"); return VLC_EGENERIC; } Display *x11 = XOpenDisplay (NULL); if (x11 == NULL) { msg_Err (obj, "windowing system failure failure"); return VLC_EGENERIC; } err = vdp_device_create_x11 (x11, XDefaultScreen (x11), devp, gpap); if (err) { msg_Err (obj, "device creation failure: error %d", (int)err); XCloseDisplay (x11); return VLC_EGENERIC; } *sysp = x11; return VLC_SUCCESS; }
static int win_x11_init_vdpau_procs(struct mp_vdpau_ctx *ctx) { struct vo_x11_state *x11 = ctx->x11; VdpStatus vdp_st; // Don't operate on ctx->vdp directly, so that even if init fails, ctx->vdp // will have the function pointers from the previous successful init, and // won't randomly make other code crash on calling NULL pointers. struct vdp_functions vdp = {0}; if (!x11) return -1; struct vdp_function { const int id; int offset; }; static const struct vdp_function vdp_func[] = { #define VDP_FUNCTION(_, macro_name, mp_name) {macro_name, offsetof(struct vdp_functions, mp_name)}, #include "video/vdpau_functions.inc" #undef VDP_FUNCTION {0, -1} }; VdpGetProcAddress *get_proc_address; vdp_st = vdp_device_create_x11(x11->display, x11->screen, &ctx->vdp_device, &get_proc_address); if (vdp_st != VDP_STATUS_OK) { if (ctx->is_preempted) MP_DBG(ctx, "Error calling vdp_device_create_x11 while preempted: %d\n", vdp_st); else MP_ERR(ctx, "Error when calling vdp_device_create_x11: %d\n", vdp_st); return -1; } for (const struct vdp_function *dsc = vdp_func; dsc->offset >= 0; dsc++) { vdp_st = get_proc_address(ctx->vdp_device, dsc->id, (void **)((char *)&vdp + dsc->offset)); if (vdp_st != VDP_STATUS_OK) { MP_ERR(ctx, "Error when calling vdp_get_proc_address(function " "id %d): %s\n", dsc->id, vdp.get_error_string ? vdp.get_error_string(vdp_st) : "?"); return -1; } } *ctx->vdp = vdp; ctx->get_proc_address = get_proc_address; vdp_st = vdp.preemption_callback_register(ctx->vdp_device, preemption_callback, ctx); return 0; }
static VdpStatus vdpau_setup_x11(vdpau_dev_t *vd) { VdpStatus r; VdpGetProcAddress *getproc; r = vdp_device_create_x11(vd->vd_dpy, vd->vd_screen, &vd->vd_dev, &getproc); if(r != VDP_STATUS_OK) { TRACE(TRACE_DEBUG, "VDPAU", "Unable to create VDPAU device"); return r; } if((r = resolve_funcs(vd, getproc)) != VDP_STATUS_OK) return r; vd->vdp_preemption_callback_register(vd->vd_dev, preempt, vd); return VDP_STATUS_OK; }
int main(int argc, char **argv) { /* Parse options */ struct Options o = parse_options(argc, argv); /* Create an X Display */ Display *display = XOpenDisplay(o.display_name); if(!display) { fprintf(stderr,"%s: cannot connect to X server %s\n", argv[0], o.display_name); exit(-1); } int screen = (o.screen == -1) ? DefaultScreen(display) : o.screen; if(screen >= ScreenCount(display)) invalid_argument(argv[0], "screen %d requested but X server only has %d screen%s\n", screen, ScreenCount(display), ScreenCount(display) == 1 ? "" : "s"); printf("display: %s screen: %i\n", o.display_name, screen); /* Create device */ VdpDevice device; VdpGetProcAddress *get_proc_address; VdpStatus rv; rv = vdp_device_create_x11(display, screen, &device, &get_proc_address); if(rv != VDP_STATUS_OK) { fprintf(stderr, "Error creating VDPAU device: %i\n", rv); /* cannot use GetErrorString here */ exit(-1); } VDPDeviceImpl *impl = new VDPDeviceImpl(device, get_proc_address); queryBaseInfo(impl); queryVideoSurface(impl); queryDecoderCaps(impl); queryOutputSurface(impl); queryBitmapSurface(impl); queryVideoMixer(impl); printf("\n"); }
static int vdpau_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { AVVDPAUDeviceContext *hwctx = ctx->hwctx; VDPAUDevicePriv *priv; VdpStatus err; VdpGetInformationString *get_information_string; const char *display, *vendor; priv = av_mallocz(sizeof(*priv)); if (!priv) return AVERROR(ENOMEM); ctx->user_opaque = priv; ctx->free = vdpau_device_free; priv->dpy = XOpenDisplay(device); if (!priv->dpy) { av_log(ctx, AV_LOG_ERROR, "Cannot open the X11 display %s.\n", XDisplayName(device)); return AVERROR_UNKNOWN; } display = XDisplayString(priv->dpy); err = vdp_device_create_x11(priv->dpy, XDefaultScreen(priv->dpy), &hwctx->device, &hwctx->get_proc_address); if (err != VDP_STATUS_OK) { av_log(ctx, AV_LOG_ERROR, "VDPAU device creation on X11 display %s failed.\n", display); return AVERROR_UNKNOWN; } GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string); GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, priv->device_destroy); get_information_string(&vendor); av_log(ctx, AV_LOG_VERBOSE, "Successfully created a VDPAU device (%s) on " "X11 display %s\n", vendor, display); return 0; }
static gboolean gst_vdp_device_open (GstVdpDevice * device, GError ** error) { gint screen; VdpStatus status; gint i; typedef struct { gint id; void *func; } VdpFunction; VdpFunction vdp_function[] = { {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, &device->vdp_video_surface_create}, {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, &device->vdp_video_surface_destroy}, {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, &device->vdp_video_surface_query_capabilities}, {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, &device->vdp_video_surface_query_ycbcr_capabilities}, {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, &device->vdp_video_surface_get_bits_ycbcr}, {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, &device->vdp_video_surface_put_bits_ycbcr}, {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, &device->vdp_video_surface_get_parameters}, {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, &device->vdp_decoder_query_capabilities}, {VDP_FUNC_ID_DECODER_GET_PARAMETERS, &device->vdp_decoder_get_parameters}, {VDP_FUNC_ID_VIDEO_MIXER_CREATE, &device->vdp_video_mixer_create}, {VDP_FUNC_ID_VIDEO_MIXER_DESTROY, &device->vdp_video_mixer_destroy}, {VDP_FUNC_ID_VIDEO_MIXER_RENDER, &device->vdp_video_mixer_render}, {VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES, &device->vdp_video_mixer_set_feature_enables}, {VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES, &device->vdp_video_mixer_set_attribute_values}, {VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, &device->vdp_output_surface_create}, {VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, &device->vdp_output_surface_destroy}, {VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES, &device->vdp_output_surface_query_capabilities}, {VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, &device->vdp_output_surface_get_bits_native}, {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, &device->vdp_presentation_queue_target_create_x11}, {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY, &device->vdp_presentation_queue_target_destroy}, {VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, &device->vdp_presentation_queue_create}, {VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, &device->vdp_presentation_queue_destroy}, {VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, &device->vdp_presentation_queue_display}, {VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, &device->vdp_presentation_queue_block_until_surface_idle}, {VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR, &device->vdp_presentation_queue_set_background_color}, {VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS, &device->vdp_presentation_queue_query_surface_status} }; device->display = XOpenDisplay (device->display_name); if (!device->display) goto create_display_error; screen = DefaultScreen (device->display); status = vdp_device_create_x11 (device->display, screen, &device->device, &device->vdp_get_proc_address); if (status != VDP_STATUS_OK) goto create_device_error; status = device->vdp_get_proc_address (device->device, VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); if (status != VDP_STATUS_OK) goto get_error_string_error; for (i = 0; i < G_N_ELEMENTS (vdp_function); i++) { status = device->vdp_get_proc_address (device->device, vdp_function[i].id, vdp_function[i].func); if (status != VDP_STATUS_OK) goto function_error; } return TRUE; create_display_error: g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_READ, "Could not open X display with name: %s", device->display_name); return FALSE; create_device_error: g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_READ, "Could not create VDPAU device for display: %s", device->display_name); return FALSE; get_error_string_error: g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_READ, "Could not get vdp_get_error_string function pointer from VDPAU"); return FALSE; function_error: g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_READ, "Could not get function pointer from VDPAU, error returned was: %s", device->vdp_get_error_string (status)); return FALSE; }
QString VDPAUContext::init() { QString err; vdp_get_proc_address = NULL; vdpDevice = VDP_INVALID_HANDLE; VdpStatus st = vdp_device_create_x11( vdpDisplay, vdpScreen, &vdpDevice, &vdp_get_proc_address ); if ( st != VDP_STATUS_OK ) { err = "Can't create vdp device : "; if ( st == VDP_STATUS_NO_IMPLEMENTATION ) err += "No vdpau implementation."; else err += "Unsupported GPU?"; return err; } if ( vdpDevice==VDP_INVALID_HANDLE ) return "Invalid VdpDevice handle !!"; if ( !vdp_get_proc_address ) return "vdp_get_proc_address is NULL !!"; if ( !getFunc( VDP_FUNC_ID_GET_ERROR_STRING , (void**)&vdp_get_error_string ) ) return "Can't get VDP_FUNC_ID_GET_ERROR_STRING address !!"; if ( !getFunc( VDP_FUNC_ID_GET_API_VERSION , (void**)&vdp_get_api_version ) ) return "Can't get VDP_FUNC_ID_GET_API_VERSION address !!"; if ( !getFunc( VDP_FUNC_ID_GET_INFORMATION_STRING , (void**)&vdp_get_information_string ) ) return "Can't get VDP_FUNC_ID_GET_INFORMATION_STRING address !!"; if ( !getFunc( VDP_FUNC_ID_DEVICE_DESTROY , (void**)&vdp_device_destroy ) ) return "Can't get VDP_FUNC_ID_DEVICE_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_GENERATE_CSC_MATRIX , (void**)&vdp_generate_csc_matrix ) ) return "Can't get VDP_FUNC_ID_GENERATE_CSC_MATRIX address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES , (void**)&vdp_video_surface_query_capabilities ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES , (void**)&vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void**)&vdp_video_surface_create ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void**)&vdp_video_surface_destroy ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS , (void**)&vdp_video_surface_get_parameters ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , (void**)&vdp_video_surface_get_bits_y_cb_cr ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void**)&vdp_video_surface_put_bits_y_cb_cr ) ) return "Can't get VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES , (void**)&vdp_output_surface_query_capabilities ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES , (void**)&vdp_output_surface_query_get_put_bits_native_capabilities ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES , (void**)&vdp_output_surface_query_put_bits_indexed_capabilities ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES , (void**)&vdp_output_surface_query_put_bits_y_cb_cr_capabilities ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void**)&vdp_output_surface_create ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void**)&vdp_output_surface_destroy ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS , (void**)&vdp_output_surface_get_parameters ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , (void**)&vdp_output_surface_get_bits_native ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , (void**)&vdp_output_surface_put_bits_native ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED , (void**)&vdp_output_surface_put_bits_indexed ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , (void**)&vdp_output_surface_put_bits_y_cb_cr ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR address !!"; if ( !getFunc( VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES , (void**)&vdp_bitmap_surface_query_capabilities ) ) return "Can't get VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_BITMAP_SURFACE_CREATE , (void**)&vdp_bitmap_surface_create ) ) return "Can't get VDP_FUNC_ID_BITMAP_SURFACE_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_BITMAP_SURFACE_DESTROY , (void**)&vdp_bitmap_surface_destroy ) ) return "Can't get VDP_FUNC_ID_BITMAP_SURFACE_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS , (void**)&vdp_bitmap_surface_get_parameters ) ) return "Can't get VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS address !!"; if ( !getFunc( VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void**)&vdp_bitmap_surface_put_bits_native ) ) return "Can't get VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE , (void**)&vdp_output_surface_render_output_surface ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE address !!"; if ( !getFunc( VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void**)&vdp_output_surface_render_bitmap_surface ) ) return "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE address !!"; if ( !getFunc( VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void**)&vdp_decoder_query_capabilities ) ) return "Can't get VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES address !!"; if ( !getFunc( VDP_FUNC_ID_DECODER_CREATE , (void**)&vdp_decoder_create ) ) return "Can't get VDP_FUNC_ID_DECODER_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_DECODER_DESTROY , (void**)&vdp_decoder_destroy ) ) return "Can't get VDP_FUNC_ID_DECODER_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_DECODER_GET_PARAMETERS , (void**)&vdp_decoder_get_parameters ) ) return "Can't get VDP_FUNC_ID_DECODER_GET_PARAMETERS address !!"; if ( !getFunc( VDP_FUNC_ID_DECODER_RENDER , (void**)&vdp_decoder_render ) ) return "Can't get VDP_FUNC_ID_DECODER_RENDER address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , (void**)&vdp_video_mixer_query_feature_support ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , (void**)&vdp_video_mixer_query_parameter_support ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT , (void**)&vdp_video_mixer_query_attribute_support ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE , (void**)&vdp_video_mixer_query_parameter_value_range ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE , (void**)&vdp_video_mixer_query_attribute_value_range ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_CREATE , (void**)&vdp_video_mixer_create ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , (void**)&vdp_video_mixer_set_feature_enables ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , (void**)&vdp_video_mixer_set_attribute_values ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT , (void**)&vdp_video_mixer_get_feature_support ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES , (void**)&vdp_video_mixer_get_feature_enables ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES , (void**)&vdp_video_mixer_get_parameter_values ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES , (void**)&vdp_video_mixer_get_attribute_values ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_DESTROY , (void**)&vdp_video_mixer_destroy ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_VIDEO_MIXER_RENDER , (void**)&vdp_video_mixer_render ) ) return "Can't get VDP_FUNC_ID_VIDEO_MIXER_RENDER address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , (void**)&vdp_presentation_queue_target_create_x11 ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , (void**)&vdp_presentation_queue_target_destroy ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , (void**)&vdp_presentation_queue_create ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , (void**)&vdp_presentation_queue_destroy ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void**)&vdp_presentation_queue_set_background_color ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR , (void**)&vdp_presentation_queue_get_background_color ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , (void**)&vdp_presentation_queue_get_time ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , (void**)&vdp_presentation_queue_display ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE , (void**)&vdp_presentation_queue_block_until_surface_idle ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE address !!"; if ( !getFunc( VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , (void**)&vdp_presentation_queue_query_surface_status ) ) return "Can't get VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS address !!"; if ( !getFunc( VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER , (void**)&vdp_preemption_callback_register ) ) return "Can't get VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER address !!"; unsigned int tmp; vdp_get_api_version( &tmp ); context.append( QString("VDPAU API version : %1\n").arg(tmp) ); const char *s; st = vdp_get_information_string( &s ); context.append( QString("VDPAU implementation : %1\n\n").arg(s) ); getDecoderCaps(); #ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 vdp_video_mixer_query_feature_support( vdpDevice, VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1, &hqScaling ); #endif return ""; }
int main(int argc, char **argv) { int width = 1280, height = 544; Display *display = XOpenDisplay(NULL); Window root = XDefaultRootWindow(display); Window window = XCreateSimpleWindow( display, root, 0, 0, 1280, 544, 0, 0, 0); XSelectInput(display, window, ExposureMask | KeyPressMask); XMapWindow(display, window); XSync(display, 0); VdpDevice dev; mark("vdp_device_create_x11\n"); int ret = vdp_device_create_x11(display, 0, &dev, &vdp_get_proc_address); assert(ret == VDP_STATUS_OK); #define get(id, func) \ ret = vdp_get_proc_address(dev, id, (void **)&func); \ assert(ret == VDP_STATUS_OK); get(VDP_FUNC_ID_DECODER_CREATE, vdp_decoder_create); get(VDP_FUNC_ID_DECODER_DESTROY, vdp_decoder_destroy); get(VDP_FUNC_ID_DECODER_RENDER, vdp_decoder_render); get(VDP_FUNC_ID_VIDEO_MIXER_CREATE, vdp_video_mixer_create); get(VDP_FUNC_ID_VIDEO_MIXER_DESTROY, vdp_video_mixer_destroy); get(VDP_FUNC_ID_VIDEO_MIXER_RENDER, vdp_video_mixer_render); get(VDP_FUNC_ID_VIDEO_SURFACE_CREATE, vdp_video_surface_create); get(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, vdp_video_surface_destroy); get(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, vdp_video_surface_get_bits_ycbcr); get(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, vdp_output_surface_create); get(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, vdp_output_surface_destroy); get(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, vdp_output_surface_get_bits_native); get(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, vdp_presentation_queue_create); get(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, vdp_presentation_queue_destroy); get(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, vdp_presentation_queue_display); get(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, vdp_presentation_queue_target_create_x11); get(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, vdp_presentation_queue_block_until_surface_idle); get(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME, vdp_presentation_queue_get_time); #undef get VdpDecoder dec; VdpVideoSurface video[16]; VdpOutputSurface output; VdpPresentationQueue queue; VdpPresentationQueueTarget target; VdpVideoMixer mixer; VdpVideoMixerFeature mixer_features[] = { }; VdpVideoMixerParameter mixer_params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; int zero = 0; const void *mixer_param_vals[] = { &width, &height, &zero }; mark("vdp_decoder_create\n"); ret = vdp_decoder_create(dev, VDP_DECODER_PROFILE_H264_MAIN, 1280, 544, 6, &dec); assert(ret == VDP_STATUS_OK); int i; for (i = 0; i < 16; i++) { mark("vdp_video_surface_create: %d\n", i); ret = vdp_video_surface_create(dev, VDP_CHROMA_TYPE_420, 1280, 544, &video[i]); assert(ret == VDP_STATUS_OK); mark(" <-- %d\n", video[i]); } mark("vdp_output_surface_create\n"); ret = vdp_output_surface_create(dev, VDP_RGBA_FORMAT_B8G8R8A8, 1280, 544, &output); assert(ret == VDP_STATUS_OK); mark("vdp_presentation_queue_target_create_x11\n"); ret = vdp_presentation_queue_target_create_x11(dev, window, &target); assert(ret == VDP_STATUS_OK); mark("vdp_presentation_queue_create\n"); ret = vdp_presentation_queue_create(dev, target, &queue); assert(ret == VDP_STATUS_OK); mark("vdp_video_mixer_create\n"); ret = vdp_video_mixer_create(dev, sizeof(mixer_features)/sizeof(mixer_features[0]), mixer_features, sizeof(mixer_params)/sizeof(mixer_params[0]), mixer_params, mixer_param_vals, &mixer); assert(ret == VDP_STATUS_OK); assert(argc > 1); int fd = open(argv[1], O_RDONLY); struct stat statbuf; assert(fstat(fd, &statbuf) == 0); void *addr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); void *orig_addr = addr; mark("mmap file addr: 0x%p size: 0x%lx\n", addr, statbuf.st_size); //printf("mmap'd file of size: %ld\n", statbuf.st_size); VdpPictureInfoH264 info = { .slice_count = 1, .field_order_cnt = { 65536, 65536 }, .is_reference = 1, .frame_num = -1, .field_pic_flag = 0, .bottom_field_flag = 0, .num_ref_frames = 6, .mb_adaptive_frame_field_flag = 0, .constrained_intra_pred_flag = 0, .weighted_pred_flag = 0, .weighted_bipred_idc = 0, .frame_mbs_only_flag = 1, .transform_8x8_mode_flag = 0, .chroma_qp_index_offset = 0, .second_chroma_qp_index_offset = 0, .pic_init_qp_minus26 = 0, .num_ref_idx_l0_active_minus1 = 0, .num_ref_idx_l1_active_minus1 = 0, .log2_max_frame_num_minus4 = 5, .pic_order_cnt_type = 0, .log2_max_pic_order_cnt_lsb_minus4 = 6, .delta_pic_order_always_zero_flag = 0, .direct_8x8_inference_flag = 1, .entropy_coding_mode_flag = 1, .pic_order_present_flag = 0, .deblocking_filter_control_present_flag = 1, .redundant_pic_cnt_present_flag = 0, }; int j; for (j = 0; j < 6; ++j) { int k; for (k = 0; k < 16; ++k) info.scaling_lists_4x4[j][k] = 16; } for (j = 0; j < 2; ++j) { int k; for (k = 0; k < 64; ++k) info.scaling_lists_8x8[j][k] = 16; } for (j = 0; j < 16; ++j) info.referenceFrames[j].surface = VDP_INVALID_HANDLE; mark("vdp_presentation_queue_get_time\n"); VdpTime t; ret = vdp_presentation_queue_get_time(queue, &t); assert(ret == VDP_STATUS_OK); fprintf(stderr, "Start time: %ld\n", t); int vframe = 0; while ((addr - orig_addr) < statbuf.st_size) { int size = ntohl(*(int *)addr); addr += 4; int nal_type = (*(char *)addr) & 0x1F; int nal_ref_idc = (*(char *)addr) >> 5; if (nal_type != 1 && nal_type != 5) { //fprintf(stderr, "Skipping NAL type %d, size: %d\n", nal_type, size); addr += size; continue; } //fprintf(stderr, "Processing NAL type %d, ref_idc: %d, size: %d\n", nal_type, nal_ref_idc, size); int bit_offset = 8; ue(addr, &bit_offset); int slice_type = ue(addr, &bit_offset); mark("nal_type: %d, ref_idc: %d, size: %d, slice_type: %d\n", nal_type, nal_ref_idc, size, slice_type); //fprintf(stderr, "Slice type: %d\n", slice_type); ue(addr, &bit_offset); info.frame_num = read_bits(addr, &bit_offset, info.log2_max_frame_num_minus4 + 4); if (nal_type == 5) { ue(addr, &bit_offset); info.frame_num = 0; for (j = 0; j < 16; ++j) info.referenceFrames[j].surface = VDP_INVALID_HANDLE; } uint32_t poc_lsb = read_bits(addr, &bit_offset, info.log2_max_pic_order_cnt_lsb_minus4 + 4); info.field_order_cnt[0] = (1 << 16) + poc_lsb; info.field_order_cnt[1] = (1 << 16) + poc_lsb; info.is_reference = nal_ref_idc != 0; VdpBitstreamBuffer buffer[2]; static const char header[3] = {0, 0, 1}; buffer[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; buffer[0].bitstream = header; buffer[0].bitstream_bytes = sizeof(header); buffer[1].struct_version = VDP_BITSTREAM_BUFFER_VERSION; buffer[1].bitstream = addr; buffer[1].bitstream_bytes = size; mark("vdp_decoder_render: %d\n", video[vframe]); ret = vdp_decoder_render(dec, video[vframe], (void*)&info, 2, buffer); assert(ret == VDP_STATUS_OK); mark("vdp_video_mixer_render\n"); ret = vdp_video_mixer_render( mixer, VDP_INVALID_HANDLE, NULL, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, NULL, video[vframe], 0, NULL, NULL, output, NULL, NULL, 0, NULL); assert(ret == VDP_STATUS_OK); t += 1000000000ULL; mark("vdp_presentation_queue_display\n"); ret = vdp_presentation_queue_display(queue, output, 1280, 544, t); assert(ret == VDP_STATUS_OK); addr += size; /* uint32_t pitches[2] = {1280, 640 * 2}; uint8_t *data[2]; for (i = 0; i < 2; i++) { data[i] = malloc(1280 * 544 / (i ? 2 : 1)); assert(data[i]); } ret = vdp_video_surface_get_bits_ycbcr(video[vframe], VDP_YCBCR_FORMAT_NV12, (void **)data, pitches); assert(ret == VDP_STATUS_OK); write(1, data[0], 1280 * 544); for (i = 0; i < 1280 * 544 / 2; i+=2) write(1, data[1] + i, 1); for (i = 0; i < 1280 * 544 / 2; i+=2) write(1, data[1] + i + 1, 1); */ if (info.is_reference) { for (j = 5; j > 0; --j) memcpy(&info.referenceFrames[j], &info.referenceFrames[j-1], sizeof(info.referenceFrames[0])); info.referenceFrames[0].surface = video[vframe]; memcpy(info.referenceFrames[0].field_order_cnt, info.field_order_cnt, 2 * sizeof(uint32_t)); info.referenceFrames[0].frame_idx = info.frame_num; info.referenceFrames[0].top_is_reference = 1; info.referenceFrames[0].bottom_is_reference = 1; } vframe = (vframe + 1) % 16; //if (vframe > 10) break; } return 0; }
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); }