/** * Create a VdpPresentationQueue. */ VdpStatus vlVdpPresentationQueueCreate(VdpDevice device, VdpPresentationQueueTarget presentation_queue_target, VdpPresentationQueue *presentation_queue) { vlVdpPresentationQueue *pq = NULL; VdpStatus ret; if (!presentation_queue) return VDP_STATUS_INVALID_POINTER; vlVdpDevice *dev = vlGetDataHTAB(device); if (!dev) return VDP_STATUS_INVALID_HANDLE; vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target); if (!pqt) return VDP_STATUS_INVALID_HANDLE; if (dev != pqt->device) return VDP_STATUS_HANDLE_DEVICE_MISMATCH; pq = CALLOC(1, sizeof(vlVdpPresentationQueue)); if (!pq) return VDP_STATUS_RESOURCES; DeviceReference(&pq->device, dev); pq->drawable = pqt->drawable; pipe_mutex_lock(dev->mutex); if (!vl_compositor_init_state(&pq->cstate, dev->context)) { pipe_mutex_unlock(dev->mutex); ret = VDP_STATUS_ERROR; goto no_compositor; } pipe_mutex_unlock(dev->mutex); *presentation_queue = vlAddDataHTAB(pq); if (*presentation_queue == 0) { ret = VDP_STATUS_ERROR; goto no_handle; } return VDP_STATUS_OK; no_handle: no_compositor: DeviceReference(&pq->device, NULL); FREE(pq); return ret; }
static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) { vid_dec_PrivateType*priv = ap_obj; struct pipe_screen *screen; vl_csc_matrix csc; assert (priv); priv->screen = omx_get_screen(); if (!priv->screen) return OMX_ErrorInsufficientResources; screen = priv->screen->pscreen; priv->pipe = screen->context_create(screen, priv->screen, 0); if (!priv->pipe) return OMX_ErrorInsufficientResources; if (!vl_compositor_init(&priv->compositor, priv->pipe)) { priv->pipe->destroy(priv->pipe); priv->pipe = NULL; return OMX_ErrorInsufficientResources; } if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { vl_compositor_cleanup(&priv->compositor); priv->pipe->destroy(priv->pipe); priv->pipe = NULL; return OMX_ErrorInsufficientResources; } vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &csc); if (!vl_compositor_set_csc_matrix(&priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f)) { vl_compositor_cleanup(&priv->compositor); priv->pipe->destroy(priv->pipe); priv->pipe = NULL; return OMX_ErrorInsufficientResources; } LIST_INITHEAD(&priv->codec_data.h264.dpb_list); priv->video_buffer_map = util_hash_table_create(handle_hash, handle_compare); return OMX_ErrorNone; }
static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) { vid_dec_PrivateType *priv; omx_base_video_PortType *port; struct pipe_screen *screen; OMX_ERRORTYPE r; int i; assert(!comp->pComponentPrivate); priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType)); if (!priv) return OMX_ErrorInsufficientResources; r = omx_base_filter_Constructor(comp, name); if (r) return r; priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN; if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME)) priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; if (!strcmp(name, OMX_VID_DEC_AVC_NAME)) priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; if (!strcmp(name, OMX_VID_DEC_HEVC_NAME)) priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; priv->BufferMgmtCallback = vid_dec_FrameDecoded; priv->messageHandler = vid_dec_MessageHandler; priv->destructor = vid_dec_Destructor; comp->SetParameter = vid_dec_SetParameter; comp->GetParameter = vid_dec_GetParameter; priv->screen = omx_get_screen(); if (!priv->screen) return OMX_ErrorInsufficientResources; screen = priv->screen->pscreen; priv->pipe = screen->context_create(screen, NULL, 0); if (!priv->pipe) return OMX_ErrorInsufficientResources; if (!vl_compositor_init(&priv->compositor, priv->pipe)) { priv->pipe->destroy(priv->pipe); priv->pipe = NULL; return OMX_ErrorInsufficientResources; } if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { vl_compositor_cleanup(&priv->compositor); priv->pipe->destroy(priv->pipe); priv->pipe = NULL; return OMX_ErrorInsufficientResources; } priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); if (!priv->ports) return OMX_ErrorInsufficientResources; for (i = 0; i < 2; ++i) { priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); if (!priv->ports[i]) return OMX_ErrorInsufficientResources; base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); } port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2"); port->sPortParam.nBufferCountMin = 8; port->sPortParam.nBufferCountActual = 8; port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; port->sPortParam.format.video.nFrameWidth = 176; port->sPortParam.format.video.nFrameHeight = 144; port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2; port->Port_SendBufferFunction = vid_dec_DecodeBuffer; port->Port_FreeBuffer = vid_dec_FreeDecBuffer; port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; port->sPortParam.nBufferCountActual = 8; port->sPortParam.nBufferCountMin = 4; port->sPortParam.format.video.nFrameWidth = 176; port->sPortParam.format.video.nFrameHeight = 144; port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; return OMX_ErrorNone; }
PUBLIC VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx) { vlVaDriver *drv; struct drm_state *drm_info; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; drv = CALLOC(1, sizeof(vlVaDriver)); if (!drv) return VA_STATUS_ERROR_ALLOCATION_FAILED; switch (ctx->display_type) { case VA_DISPLAY_ANDROID: FREE(drv); return VA_STATUS_ERROR_UNIMPLEMENTED; case VA_DISPLAY_GLX: case VA_DISPLAY_X11: #if defined(HAVE_DRI3) drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); #endif if (!drv->vscreen) drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); if (!drv->vscreen) goto error_screen; break; case VA_DISPLAY_WAYLAND: case VA_DISPLAY_DRM: case VA_DISPLAY_DRM_RENDERNODES: { drm_info = (struct drm_state *) ctx->drm_state; if (!drm_info || drm_info->fd < 0) { FREE(drv); return VA_STATUS_ERROR_INVALID_PARAMETER; } drv->vscreen = vl_drm_screen_create(drm_info->fd); if (!drv->vscreen) goto error_screen; } break; default: FREE(drv); return VA_STATUS_ERROR_INVALID_DISPLAY; } drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen, drv->vscreen, 0); if (!drv->pipe) goto error_pipe; drv->htab = handle_table_create(); if (!drv->htab) goto error_htab; if (!vl_compositor_init(&drv->compositor, drv->pipe)) goto error_compositor; if (!vl_compositor_init_state(&drv->cstate, drv->pipe)) goto error_compositor_state; vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc); if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f)) goto error_csc_matrix; pipe_mutex_init(drv->mutex); ctx->pDriverData = (void *)drv; ctx->version_major = 0; ctx->version_minor = 1; *ctx->vtable = vtable; *ctx->vtable_vpp = vtable_vpp; ctx->max_profiles = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH - PIPE_VIDEO_PROFILE_UNKNOWN; ctx->max_entrypoints = 1; ctx->max_attributes = 1; ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS; ctx->max_subpic_formats = 1; ctx->max_display_attributes = 1; ctx->str_vendor = "mesa gallium vaapi"; return VA_STATUS_SUCCESS; error_csc_matrix: vl_compositor_cleanup_state(&drv->cstate); error_compositor_state: vl_compositor_cleanup(&drv->compositor); error_compositor: handle_table_destroy(drv->htab); error_htab: drv->pipe->destroy(drv->pipe); error_pipe: drv->vscreen->destroy(drv->vscreen); error_screen: FREE(drv); return VA_STATUS_ERROR_ALLOCATION_FAILED; }
/** * Create a VdpOutputSurface. */ VdpStatus vlVdpOutputSurfaceCreate(VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpOutputSurface *surface) { struct pipe_context *pipe; struct pipe_resource res_tmpl, *res; struct pipe_sampler_view sv_templ; struct pipe_surface surf_templ; vlVdpOutputSurface *vlsurface = NULL; if (!(width && height)) return VDP_STATUS_INVALID_SIZE; vlVdpDevice *dev = vlGetDataHTAB(device); if (!dev) return VDP_STATUS_INVALID_HANDLE; pipe = dev->context; if (!pipe) return VDP_STATUS_INVALID_HANDLE; vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); if (!vlsurface) return VDP_STATUS_RESOURCES; vlsurface->device = dev; memset(&res_tmpl, 0, sizeof(res_tmpl)); res_tmpl.target = PIPE_TEXTURE_2D; res_tmpl.format = FormatRGBAToPipe(rgba_format); res_tmpl.width0 = width; res_tmpl.height0 = height; res_tmpl.depth0 = 1; res_tmpl.array_size = 1; res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; res_tmpl.usage = PIPE_USAGE_STATIC; pipe_mutex_lock(dev->mutex); res = pipe->screen->resource_create(pipe->screen, &res_tmpl); if (!res) { pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } vlVdpDefaultSamplerViewTemplate(&sv_templ, res); vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); if (!vlsurface->sampler_view) { pipe_resource_reference(&res, NULL); pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } memset(&surf_templ, 0, sizeof(surf_templ)); surf_templ.format = res->format; vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); if (!vlsurface->surface) { pipe_resource_reference(&res, NULL); pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } *surface = vlAddDataHTAB(vlsurface); if (*surface == 0) { pipe_resource_reference(&res, NULL); pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } pipe_resource_reference(&res, NULL); vl_compositor_init_state(&vlsurface->cstate, pipe); vl_compositor_reset_dirty_area(&vlsurface->dirty_area); pipe_mutex_unlock(dev->mutex); return VDP_STATUS_OK; }
/** * Create a VdpVideoMixer. */ VdpStatus vlVdpVideoMixerCreate(VdpDevice device, uint32_t feature_count, VdpVideoMixerFeature const *features, uint32_t parameter_count, VdpVideoMixerParameter const *parameters, void const *const *parameter_values, VdpVideoMixer *mixer) { vlVdpVideoMixer *vmixer = NULL; VdpStatus ret; struct pipe_screen *screen; uint32_t max_2d_texture_level; unsigned max_size, i; vlVdpDevice *dev = vlGetDataHTAB(device); if (!dev) return VDP_STATUS_INVALID_HANDLE; screen = dev->vscreen->pscreen; vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); if (!vmixer) return VDP_STATUS_RESOURCES; DeviceReference(&vmixer->device, dev); pipe_mutex_lock(dev->mutex); vl_compositor_init_state(&vmixer->cstate, dev->context); vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &vmixer->csc); if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc); *mixer = vlAddDataHTAB(vmixer); if (*mixer == 0) { ret = VDP_STATUS_ERROR; goto no_handle; } ret = VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; for (i = 0; i < feature_count; ++i) { switch (features[i]) { /* they are valid, but we doesn't support them */ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: break; case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: vmixer->deint.supported = true; break; case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: vmixer->sharpness.supported = true; break; case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: vmixer->noise_reduction.supported = true; break; default: goto no_params; } } vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; for (i = 0; i < parameter_count; ++i) { switch (parameters[i]) { case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: vmixer->video_width = *(uint32_t*)parameter_values[i]; break; case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: vmixer->video_height = *(uint32_t*)parameter_values[i]; break; case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]); break; case VDP_VIDEO_MIXER_PARAMETER_LAYERS: vmixer->max_layers = *(uint32_t*)parameter_values[i]; break; default: goto no_params; } } ret = VDP_STATUS_INVALID_VALUE; if (vmixer->max_layers > 4) { VDPAU_MSG(VDPAU_WARN, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers); goto no_params; } max_2d_texture_level = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); max_size = pow(2, max_2d_texture_level-1); if (vmixer->video_width < 48 || vmixer->video_width > max_size) { VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer->video_width, max_size); goto no_params; } if (vmixer->video_height < 48 || vmixer->video_height > max_size) { VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer->video_height, max_size); goto no_params; } vmixer->luma_key_min = 0.f; vmixer->luma_key_max = 1.f; pipe_mutex_unlock(dev->mutex); return VDP_STATUS_OK; no_params: vlRemoveDataHTAB(*mixer); no_handle: vl_compositor_cleanup_state(&vmixer->cstate); pipe_mutex_unlock(dev->mutex); DeviceReference(&vmixer->device, NULL); FREE(vmixer); return ret; }
PUBLIC Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context) { bool found_port; int scrn = 0; int chroma_format = 0; int mc_type = 0; int surface_flags = 0; unsigned short subpic_max_w = 0; unsigned short subpic_max_h = 0; Status ret; struct vl_screen *vscreen; struct pipe_context *pipe; struct pipe_video_codec templat = {0}; XvMCContextPrivate *context_priv; vl_csc_matrix csc; XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context); assert(dpy); if (!context) return XvMCBadContext; ret = Validate(dpy, port, surface_type_id, width, height, flags, &found_port, &scrn, &chroma_format, &mc_type, &surface_flags, &subpic_max_w, &subpic_max_h); /* Success and XvBadPort have the same value */ if (ret != Success || !found_port) return ret; /* XXX: Current limits */ if (chroma_format != XVMC_CHROMA_FORMAT_420) { XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n"); return BadImplementation; } if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) { XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n"); return BadImplementation; } if (surface_flags & XVMC_INTRA_UNSIGNED) { XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n"); return BadImplementation; } context_priv = CALLOC(1, sizeof(XvMCContextPrivate)); if (!context_priv) return BadAlloc; /* TODO: Reuse screen if process creates another context */ vscreen = vl_screen_create(dpy, scrn); if (!vscreen) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n"); FREE(context_priv); return BadAlloc; } pipe = vscreen->pscreen->context_create(vscreen->pscreen, vscreen, 0); if (!pipe) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n"); vl_screen_destroy(vscreen); FREE(context_priv); return BadAlloc; } templat.profile = ProfileToPipe(mc_type); templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC; templat.chroma_format = FormatToPipe(chroma_format); templat.width = width; templat.height = height; templat.max_references = 2; templat.expect_chunked_decode = true; context_priv->decoder = pipe->create_video_codec(pipe, &templat); if (!context_priv->decoder) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n"); pipe->destroy(pipe); vl_screen_destroy(vscreen); FREE(context_priv); return BadAlloc; } if (!vl_compositor_init(&context_priv->compositor, pipe)) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n"); context_priv->decoder->destroy(context_priv->decoder); pipe->destroy(pipe); vl_screen_destroy(vscreen); FREE(context_priv); return BadAlloc; } if (!vl_compositor_init_state(&context_priv->cstate, pipe)) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n"); vl_compositor_cleanup(&context_priv->compositor); context_priv->decoder->destroy(context_priv->decoder); pipe->destroy(pipe); vl_screen_destroy(vscreen); FREE(context_priv); return BadAlloc; } context_priv->color_standard = debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601; context_priv->procamp = vl_default_procamp; vl_csc_get_matrix ( context_priv->color_standard, &context_priv->procamp, true, &csc ); vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc); context_priv->vscreen = vscreen; context_priv->pipe = pipe; context_priv->subpicture_max_width = subpic_max_w; context_priv->subpicture_max_height = subpic_max_h; context->context_id = XAllocID(dpy); context->surface_type_id = surface_type_id; context->width = width; context->height = height; context->flags = flags; context->port = port; context->privData = context_priv; SyncHandle(); XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context); return Success; }