VAStatus vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) { vlVaDriver *drv; vlVaSurface *surf; vlVaBuffer *img_buf; VAImage *img; struct pipe_surface **surfaces; int w; int h; int i; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; drv = VL_VA_DRIVER(ctx); if (!drv) return VA_STATUS_ERROR_INVALID_CONTEXT; surf = handle_table_get(drv->htab, surface); if (!surf || !surf->buffer || surf->buffer->interlaced) return VA_STATUS_ERROR_INVALID_SURFACE; surfaces = surf->buffer->get_surfaces(surf->buffer); if (!surfaces || !surfaces[0]->texture) return VA_STATUS_ERROR_ALLOCATION_FAILED; img = CALLOC(1, sizeof(VAImage)); if (!img) return VA_STATUS_ERROR_ALLOCATION_FAILED; img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); img->buf = VA_INVALID_ID; img->width = surf->buffer->width; img->height = surf->buffer->height; img->num_palette_entries = 0; img->entry_bytes = 0; w = align(surf->buffer->width, 2); h = align(surf->buffer->height, 2); for (i = 0; i < ARRAY_SIZE(formats); ++i) { if (img->format.fourcc == formats[i].fourcc) { img->format = formats[i]; break; } } switch (img->format.fourcc) { case VA_FOURCC('U','Y','V','Y'): case VA_FOURCC('Y','U','Y','V'): img->num_planes = 1; img->pitches[0] = w * 2; img->offsets[0] = 0; img->data_size = w * h * 2; break; case VA_FOURCC('B','G','R','A'): case VA_FOURCC('R','G','B','A'): case VA_FOURCC('B','G','R','X'): case VA_FOURCC('R','G','B','X'): img->num_planes = 1; img->pitches[0] = w * 4; img->offsets[0] = 0; img->data_size = w * h * 4; break; default: /* VaDeriveImage is designed for contiguous planes. */ FREE(img); return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; } img_buf = CALLOC(1, sizeof(vlVaBuffer)); if (!img_buf) { FREE(img); return VA_STATUS_ERROR_ALLOCATION_FAILED; } pipe_mutex_lock(drv->mutex); img->image_id = handle_table_add(drv->htab, img); img_buf->type = VAImageBufferType; img_buf->size = img->data_size; img_buf->num_elements = 1; pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture); img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf); pipe_mutex_unlock(drv->mutex); *image = *img; return VA_STATUS_SUCCESS; }
VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list, unsigned int *num_attribs) { vlVaDriver *drv; VASurfaceAttrib *attribs; struct pipe_screen *pscreen; int i, j; STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); if (config == VA_INVALID_ID) return VA_STATUS_ERROR_INVALID_CONFIG; if (!attrib_list && !num_attribs) return VA_STATUS_ERROR_INVALID_PARAMETER; if (!attrib_list) { *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; return VA_STATUS_SUCCESS; } if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; drv = VL_VA_DRIVER(ctx); if (!drv) return VA_STATUS_ERROR_INVALID_CONTEXT; pscreen = VL_VA_PSCREEN(ctx); if (!pscreen) return VA_STATUS_ERROR_INVALID_CONTEXT; attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, sizeof(VASurfaceAttrib)); if (!attribs) return VA_STATUS_ERROR_ALLOCATION_FAILED; i = 0; /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN * only for VAEntrypointVideoProc. */ if (config == PIPE_VIDEO_PROFILE_UNKNOWN) { for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { attribs[i].type = VASurfaceAttribPixelFormat; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); i++; } } else { /* Assume VAEntrypointVLD for now. */ attribs[i].type = VASurfaceAttribPixelFormat; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.i = VA_FOURCC_NV12; i++; } attribs[i].type = VASurfaceAttribMemoryType; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; i++; attribs[i].type = VASurfaceAttribExternalBufferDescriptor; attribs[i].value.type = VAGenericValueTypePointer; attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.p = NULL; /* ignore */ i++; attribs[i].type = VASurfaceAttribMaxWidth; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); i++; attribs[i].type = VASurfaceAttribMaxHeight; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); i++; if (i > *num_attribs) { *num_attribs = i; FREE(attribs); return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; } *num_attribs = i; memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); FREE(attribs); return VA_STATUS_SUCCESS; }