Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
0
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");
}
Exemple #5
0
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;
}
Exemple #6
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 "";
}
Exemple #8
0
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);
}