static int Open(vlc_va_t *va, AVCodecContext *ctx, const es_format_t *fmt) { VdpStatus err; VdpDecoderProfile profile; int level = fmt->i_level; if (av_vdpau_get_profile(ctx, &profile)) { msg_Err(va, "unsupported codec %d or profile %d", ctx->codec_id, fmt->i_profile); return VLC_EGENERIC; } switch (ctx->codec_id) { case AV_CODEC_ID_MPEG1VIDEO: level = VDP_DECODER_LEVEL_MPEG1_NA; break; case AV_CODEC_ID_MPEG2VIDEO: level = VDP_DECODER_LEVEL_MPEG2_HL; break; case AV_CODEC_ID_H263: level = VDP_DECODER_LEVEL_MPEG4_PART2_ASP_L5; break; case AV_CODEC_ID_H264: if ((fmt->i_profile & FF_PROFILE_H264_INTRA) && (fmt->i_level == 11)) level = VDP_DECODER_LEVEL_H264_1b; default: break; } if (!vlc_xlib_init(VLC_OBJECT(va))) { msg_Err(va, "Xlib is required for VDPAU"); return VLC_EGENERIC; } vlc_va_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->context = av_vdpau_alloc_context(); if (unlikely(sys->context == NULL)) { free(sys); return VLC_ENOMEM; } err = vdp_get_x11(NULL, -1, &sys->vdp, &sys->device); if (err != VDP_STATUS_OK) { free(sys->context); free(sys); return VLC_EGENERIC; } void *func; err = vdp_get_proc_address(sys->vdp, sys->device, VDP_FUNC_ID_DECODER_RENDER, &func); if (err != VDP_STATUS_OK) goto error; sys->context->decoder = VDP_INVALID_HANDLE; sys->context->render = func; sys->profile = profile; /* Check capabilities */ VdpBool support; uint32_t l, mb, w, h; if (vdp_video_surface_query_capabilities(sys->vdp, sys->device, VDP_CHROMA_TYPE_420, &support, &w, &h) != VDP_STATUS_OK) support = VDP_FALSE; if (!support) { msg_Err(va, "video surface format not supported: %s", "YUV 4:2:0"); goto error; } msg_Dbg(va, "video surface limits: %"PRIu32"x%"PRIu32, w, h); if (w < fmt->video.i_width || h < fmt->video.i_height) { msg_Err(va, "video surface above limits: %ux%u", fmt->video.i_width, fmt->video.i_height); goto error; } if (vdp_decoder_query_capabilities(sys->vdp, sys->device, profile, &support, &l, &mb, &w, &h) != VDP_STATUS_OK) support = VDP_FALSE; if (!support) { msg_Err(va, "decoder profile not supported: %u", profile); goto error; } msg_Dbg(va, "decoder profile limits: level %"PRIu32" mb %"PRIu32" " "%"PRIu32"x%"PRIu32, l, mb, w, h); if ((int)l < level || w < fmt->video.i_width || h < fmt->video.i_height) { msg_Err(va, "decoder profile above limits: level %d %ux%u", level, fmt->video.i_width, fmt->video.i_height); goto error; } const char *infos; if (vdp_get_information_string(sys->vdp, &infos) != VDP_STATUS_OK) infos = "VDPAU"; va->sys = sys; va->description = (char *)infos; va->pix_fmt = AV_PIX_FMT_VDPAU; va->setup = Setup; va->get = Lock; va->release = Unlock; va->extract = Copy; return VLC_SUCCESS; error: vdp_release_x11(sys->vdp); av_free(sys->context); free(sys); return VLC_EGENERIC; }
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 ""; }
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; }