VAStatus vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats) { struct pipe_screen *pscreen; enum pipe_format format; int i; STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS); if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; if (!(format_list && num_formats)) return VA_STATUS_ERROR_INVALID_PARAMETER; *num_formats = 0; pscreen = VL_VA_PSCREEN(ctx); for (i = 0; i < ARRAY_SIZE(formats); ++i) { format = VaFourccToPipeFormat(formats[i].fourcc); if (pscreen->is_video_format_supported(pscreen, format, PIPE_VIDEO_PROFILE_UNKNOWN, PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) format_list[(*num_formats)++] = formats[i]; } return VA_STATUS_SUCCESS; }
VAStatus vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints) { struct pipe_screen *pscreen; enum pipe_video_profile p; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; *num_entrypoints = 0; if (profile == VAProfileNone) { entrypoint_list[(*num_entrypoints)++] = VAEntrypointVideoProc; return VA_STATUS_SUCCESS; } p = ProfileToPipe(profile); if (p == PIPE_VIDEO_PROFILE_UNKNOWN) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; pscreen = VL_VA_PSCREEN(ctx); if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) entrypoint_list[(*num_entrypoints)++] = VAEntrypointVLD; if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) entrypoint_list[(*num_entrypoints)++] = VAEntrypointEncSlice; if (num_entrypoints == 0) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; return VA_STATUS_SUCCESS; }
VAStatus vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_profiles) { struct pipe_screen *pscreen; enum pipe_video_profile p; VAProfile vap; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; *num_profiles = 0; pscreen = VL_VA_PSCREEN(ctx); for (p = PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; p <= PIPE_VIDEO_PROFILE_HEVC_MAIN_444; ++p) { if (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && !debug_get_option_mpeg4()) continue; if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) { vap = PipeToProfile(p); if (vap != VAProfileNone) profile_list[(*num_profiles)++] = vap; } } /* Support postprocessing through vl_compositor */ profile_list[(*num_profiles)++] = VAProfileNone; return VA_STATUS_SUCCESS; }
VAStatus vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) { struct pipe_screen *pscreen; enum pipe_video_profile p; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; if (profile == VAProfileNone && entrypoint == VAEntrypointVideoProc) { *config_id = PIPE_VIDEO_PROFILE_UNKNOWN; return VA_STATUS_SUCCESS; } p = ProfileToPipe(profile); if (p == PIPE_VIDEO_PROFILE_UNKNOWN) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; pscreen = VL_VA_PSCREEN(ctx); if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; if (entrypoint != VAEntrypointVLD) return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; *config_id = p; return VA_STATUS_SUCCESS; }
VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned int width, unsigned int height, VASurfaceID *surfaces, unsigned int num_surfaces, VASurfaceAttrib *attrib_list, unsigned int num_attribs) { vlVaDriver *drv; VASurfaceAttribExternalBuffers *memory_attibute; struct pipe_video_buffer templat; struct pipe_screen *pscreen; int i; int memory_type; int expected_fourcc; VAStatus vaStatus; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; if (!(width && height)) return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 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; /* Default. */ memory_attibute = NULL; memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; expected_fourcc = 0; for (i = 0; i < num_attribs && attrib_list; i++) { if ((attrib_list[i].type == VASurfaceAttribPixelFormat) && (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { if (attrib_list[i].value.type != VAGenericValueTypeInteger) return VA_STATUS_ERROR_INVALID_PARAMETER; expected_fourcc = attrib_list[i].value.value.i; } if ((attrib_list[i].type == VASurfaceAttribMemoryType) && (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { if (attrib_list[i].value.type != VAGenericValueTypeInteger) return VA_STATUS_ERROR_INVALID_PARAMETER; switch (attrib_list[i].value.value.i) { case VA_SURFACE_ATTRIB_MEM_TYPE_VA: case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: memory_type = attrib_list[i].value.value.i; break; default: return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; } } if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) && (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) { if (attrib_list[i].value.type != VAGenericValueTypePointer) return VA_STATUS_ERROR_INVALID_PARAMETER; memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; } } if (VA_RT_FORMAT_YUV420 != format && VA_RT_FORMAT_YUV422 != format && VA_RT_FORMAT_YUV444 != format && VA_RT_FORMAT_RGB32 != format) { return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; } switch (memory_type) { case VA_SURFACE_ATTRIB_MEM_TYPE_VA: break; case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: if (!memory_attibute) return VA_STATUS_ERROR_INVALID_PARAMETER; expected_fourcc = memory_attibute->pixel_format; break; default: assert(0); } memset(&templat, 0, sizeof(templat)); if (expected_fourcc) { templat.buffer_format = VaFourccToPipeFormat(expected_fourcc); templat.interlaced = 0; } else { templat.buffer_format = pscreen->get_video_param ( pscreen, PIPE_VIDEO_PROFILE_UNKNOWN, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_PREFERED_FORMAT ); templat.interlaced = pscreen->get_video_param ( pscreen, PIPE_VIDEO_PROFILE_UNKNOWN, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_PREFERS_INTERLACED ); } templat.chroma_format = ChromaToPipe(format); templat.width = width; templat.height = height; memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); for (i = 0; i < num_surfaces; i++) { vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface)); if (!surf) goto no_res; surf->templat = templat; switch (memory_type) { case VA_SURFACE_ATTRIB_MEM_TYPE_VA: surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat); if (!surf->buffer) goto no_res; util_dynarray_init(&surf->subpics); surfaces[i] = handle_table_add(drv->htab, surf); break; case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat); if (vaStatus != VA_STATUS_SUCCESS) goto no_res; break; default: assert(0); } } return VA_STATUS_SUCCESS; no_res: if (i) vlVaDestroySurfaces(ctx, surfaces, i); return VA_STATUS_ERROR_ALLOCATION_FAILED; }
static VAStatus suface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, VASurfaceAttribExternalBuffers *memory_attibute, int index, VASurfaceID *surfaces, struct pipe_video_buffer *templat) { vlVaDriver *drv; struct pipe_screen *pscreen; struct pipe_resource *resource; struct pipe_resource res_templ; struct winsys_handle whandle; struct pipe_resource *resources[VL_NUM_COMPONENTS]; if (!ctx) return VA_STATUS_ERROR_INVALID_PARAMETER; pscreen = VL_VA_PSCREEN(ctx); drv = VL_VA_DRIVER(ctx); if (!memory_attibute || !memory_attibute->buffers || index > memory_attibute->num_buffers) return VA_STATUS_ERROR_INVALID_PARAMETER; if (surface->templat.width != memory_attibute->width || surface->templat.height != memory_attibute->height || memory_attibute->num_planes < 1) return VA_STATUS_ERROR_INVALID_PARAMETER; switch (memory_attibute->pixel_format) { case VA_FOURCC_RGBA: case VA_FOURCC_RGBX: case VA_FOURCC_BGRA: case VA_FOURCC_BGRX: if (memory_attibute->num_planes != 1) return VA_STATUS_ERROR_INVALID_PARAMETER; break; default: return VA_STATUS_ERROR_INVALID_PARAMETER; } memset(&res_templ, 0, sizeof(res_templ)); res_templ.target = PIPE_TEXTURE_2D; res_templ.last_level = 0; res_templ.depth0 = 1; res_templ.array_size = 1; res_templ.width0 = memory_attibute->width; res_templ.height0 = memory_attibute->height; res_templ.format = surface->templat.buffer_format; res_templ.bind = PIPE_BIND_SAMPLER_VIEW; res_templ.usage = PIPE_USAGE_DEFAULT; memset(&whandle, 0, sizeof(struct winsys_handle)); whandle.type = DRM_API_HANDLE_TYPE_FD; whandle.handle = memory_attibute->buffers[index]; whandle.stride = memory_attibute->pitches[index]; resource = pscreen->resource_from_handle(pscreen, &res_templ, &whandle); if (!resource) return VA_STATUS_ERROR_ALLOCATION_FAILED; memset(resources, 0, sizeof resources); resources[0] = resource; surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); if (!surface->buffer) return VA_STATUS_ERROR_ALLOCATION_FAILED; util_dynarray_init(&surface->subpics); surfaces[index] = handle_table_add(drv->htab, surface); if (!surfaces[index]) return VA_STATUS_ERROR_ALLOCATION_FAILED; 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; 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 = 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(VASurfaceAttribCount, sizeof(VASurfaceAttrib)); if (!attribs) return VA_STATUS_ERROR_ALLOCATION_FAILED; i = 0; if (config == PIPE_VIDEO_PROFILE_UNKNOWN) { /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN only for VAEntrypointVideoProc. */ 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_BGRA; i++; 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_RGBA; 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; }
VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info) { uint32_t i; uint32_t mem_type; vlVaBuffer *buf ; struct pipe_screen *screen; /* List of supported memory types, in preferred order. */ static const uint32_t mem_types[] = { VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, 0 }; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); if (!buf) return VA_STATUS_ERROR_INVALID_BUFFER; /* Only VA surface|image like buffers are supported for now .*/ if (buf->type != VAImageBufferType) return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; if (!out_buf_info) return VA_STATUS_ERROR_INVALID_PARAMETER; if (!out_buf_info->mem_type) mem_type = mem_types[0]; else { mem_type = 0; for (i = 0; mem_types[i] != 0; i++) { if (out_buf_info->mem_type & mem_types[i]) { mem_type = out_buf_info->mem_type; break; } } if (!mem_type) return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; } if (!buf->derived_surface.resource) return VA_STATUS_ERROR_INVALID_BUFFER; screen = VL_VA_PSCREEN(ctx); if (buf->derived_surface.fence) { screen->fence_finish(screen, buf->derived_surface.fence, PIPE_TIMEOUT_INFINITE); screen->fence_reference(screen, &buf->derived_surface.fence, NULL); } if (buf->export_refcount > 0) { if (buf->export_state.mem_type != mem_type) return VA_STATUS_ERROR_INVALID_PARAMETER; } else { VABufferInfo * const buf_info = &buf->export_state; switch (mem_type) { case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: { struct winsys_handle whandle; memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_FD; if (!screen->resource_get_handle(screen, buf->derived_surface.resource, &whandle)) return VA_STATUS_ERROR_INVALID_BUFFER; buf_info->handle = (intptr_t)whandle.handle; break; } default: return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; } buf_info->type = buf->type; buf_info->mem_type = mem_type; buf_info->mem_size = buf->num_elements * buf->size; } buf->export_refcount++; *out_buf_info = buf->export_state; return VA_STATUS_SUCCESS; }
VAStatus vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) { vlVaDriver *drv; vlVaConfig *config; struct pipe_screen *pscreen; enum pipe_video_profile p; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; drv = VL_VA_DRIVER(ctx); if (!drv) return VA_STATUS_ERROR_INVALID_CONTEXT; config = CALLOC(1, sizeof(vlVaConfig)); if (!config) return VA_STATUS_ERROR_ALLOCATION_FAILED; if (profile == VAProfileNone && entrypoint == VAEntrypointVideoProc) { config->entrypoint = VAEntrypointVideoProc; config->profile = PIPE_VIDEO_PROFILE_UNKNOWN; for (int i = 0; i < num_attribs; i++) { if (attrib_list[i].type == VAConfigAttribRTFormat) { if (attrib_list[i].value & (VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_RGB32)) { config->rt_format = attrib_list[i].value; } else { FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; } } } /* Default value if not specified in the input attributes. */ if (!config->rt_format) config->rt_format = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_RGB32; pipe_mutex_lock(drv->mutex); *config_id = handle_table_add(drv->htab, config); pipe_mutex_unlock(drv->mutex); return VA_STATUS_SUCCESS; } p = ProfileToPipe(profile); if (p == PIPE_VIDEO_PROFILE_UNKNOWN) { FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } pscreen = VL_VA_PSCREEN(ctx); switch (entrypoint) { case VAEntrypointVLD: if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) { FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } config->entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; break; case VAEntrypointEncSlice: if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) { FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } config->entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; break; default: FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; } config->profile = p; for (int i = 0; i <num_attribs ; i++) { if (attrib_list[i].type == VAConfigAttribRateControl) { if (attrib_list[i].value == VA_RC_CBR) config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; else if (attrib_list[i].value == VA_RC_VBR) config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; else config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; } if (attrib_list[i].type == VAConfigAttribRTFormat) { if (attrib_list[i].value == VA_RT_FORMAT_YUV420) { config->rt_format = attrib_list[i].value; } else { FREE(config); return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; } } } /* Default value if not specified in the input attributes. */ if (!config->rt_format) config->rt_format = VA_RT_FORMAT_YUV420; pipe_mutex_lock(drv->mutex); *config_id = handle_table_add(drv->htab, config); pipe_mutex_unlock(drv->mutex); return VA_STATUS_SUCCESS; }
VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, VASurfaceAttrib *attrib_list, unsigned int *num_attribs) { vlVaDriver *drv; vlVaConfig *config; VASurfaceAttrib *attribs; struct pipe_screen *pscreen; int i, j; STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); if (config_id == 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; pipe_mutex_lock(drv->mutex); config = handle_table_get(drv->htab, config_id); pipe_mutex_unlock(drv->mutex); if (!config) return VA_STATUS_ERROR_INVALID_CONFIG; 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->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { if (config->rt_format & VA_RT_FORMAT_RGB32) { 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++; } } if (config->rt_format & VA_RT_FORMAT_YUV420) { 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++; } } 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; }