VdpStatus softVdpDecoderRender(VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffer_count, VdpBitstreamBuffer const *bitstream_buffers) { VdpStatus err_code; if (!picture_info || !bitstream_buffers) return VDP_STATUS_INVALID_POINTER; VdpDecoderData *decoderData = handle_acquire(decoder, HANDLETYPE_DECODER); VdpVideoSurfaceData *dstSurfData = handle_acquire(target, HANDLETYPE_VIDEO_SURFACE); if (NULL == decoderData || NULL == dstSurfData) { err_code = VDP_STATUS_INVALID_HANDLE; goto quit; } if (VDP_DECODER_PROFILE_H264_BASELINE == decoderData->profile || VDP_DECODER_PROFILE_H264_MAIN == decoderData->profile || VDP_DECODER_PROFILE_H264_HIGH == decoderData->profile) { // TODO: check exit code softVdpDecoderRender_h264(decoder, decoderData, dstSurfData, picture_info, bitstream_buffer_count, bitstream_buffers); } else { traceError("error (softVdpDecoderRender): no implementation for profile %s\n", reverse_decoder_profile(decoderData->profile)); err_code = VDP_STATUS_NO_IMPLEMENTATION; goto quit; } err_code = VDP_STATUS_OK; quit: handle_release(decoder); handle_release(target); return err_code; }
void traceVdpDecoderCreate(const char *impl_state, VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder) { (void)decoder; if (!enabled) return; fprintf(tlog, "%s%s VdpDecoderCreate device=%d, profile=%s, width=%d, height=%d, " "max_references=%d\n", trace_header, impl_state, device, reverse_decoder_profile(profile), width, height, max_references); }
void traceVdpDecoderQueryCapabilities(const char *impl_state, VdpDevice device, VdpDecoderProfile profile, VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, uint32_t *max_width, uint32_t *max_height) { (void)is_supported; (void)max_level; (void)max_macroblocks; (void)max_width; (void)max_height; if (!enabled) return; fprintf(tlog, "%s%s VdpDecoderQueryCapabilities device=%d, profile=%s\n", trace_header, impl_state, device, reverse_decoder_profile(profile)); }
VdpStatus softVdpDecoderCreate(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder) { VdpStatus err_code; if (!decoder) return VDP_STATUS_INVALID_POINTER; VdpDeviceData *deviceData = handle_acquire(device, HANDLETYPE_DEVICE); if (NULL == deviceData) return VDP_STATUS_INVALID_HANDLE; if (!deviceData->va_available) { err_code = VDP_STATUS_INVALID_DECODER_PROFILE; goto quit; } VADisplay va_dpy = deviceData->va_dpy; VdpDecoderData *data = calloc(1, sizeof(VdpDecoderData)); if (NULL == data) { err_code = VDP_STATUS_RESOURCES; goto quit; } data->type = HANDLETYPE_DECODER; data->device = deviceData; data->profile = profile; data->width = width; data->height = height; data->max_references = max_references; // initialize free_list. Initially they all free data->free_list_head = -1; for (int k = 0; k < MAX_RENDER_TARGETS; k ++) { free_list_push(data->free_list, &data->free_list_head, k); } VAProfile va_profile; VAStatus status; int final_try = 0; VdpDecoderProfile next_profile = profile; // Try to create decoder for asked profile. On failure try to create more advanced one while (! final_try) { profile = next_profile; switch (profile) { case VDP_DECODER_PROFILE_H264_BASELINE: va_profile = VAProfileH264Baseline; data->num_render_targets = NUM_RENDER_TARGETS_H264; next_profile = VDP_DECODER_PROFILE_H264_MAIN; break; case VDP_DECODER_PROFILE_H264_MAIN: va_profile = VAProfileH264Main; data->num_render_targets = NUM_RENDER_TARGETS_H264; next_profile = VDP_DECODER_PROFILE_H264_HIGH; break; case VDP_DECODER_PROFILE_H264_HIGH: va_profile = VAProfileH264High; data->num_render_targets = NUM_RENDER_TARGETS_H264; // there is no more advanced profile, so it's final try final_try = 1; break; default: traceError("error (softVdpDecoderCreate): decoder %s not implemented\n", reverse_decoder_profile(profile)); err_code = VDP_STATUS_INVALID_DECODER_PROFILE; goto quit_free_data; } status = vaCreateConfig(va_dpy, va_profile, VAEntrypointVLD, NULL, 0, &data->config_id); if (VA_STATUS_SUCCESS == status) // break loop if decoder created break; } if (VA_STATUS_SUCCESS != status) { err_code = VDP_STATUS_ERROR; goto quit_free_data; } // Create surfaces. All video surfaces created here, rather than in VdpVideoSurfaceCreate. // VAAPI requires surfaces to be bound with context on its creation time, while VDPAU allows // to do it later. So here is a trick: VDP video surfaces get their va_surf dynamically in // DecoderRender. // TODO: check format of surfaces created #if VA_CHECK_VERSION(0, 34, 0) status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, width, height, data->render_targets, data->num_render_targets, NULL, 0); #else status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, data->num_render_targets, data->render_targets); #endif if (VA_STATUS_SUCCESS != status) { err_code = VDP_STATUS_ERROR; goto quit_free_data; } status = vaCreateContext(va_dpy, data->config_id, width, height, VA_PROGRESSIVE, data->render_targets, data->num_render_targets, &data->context_id); if (VA_STATUS_SUCCESS != status) { err_code = VDP_STATUS_ERROR; goto quit_free_data; } deviceData->refcount ++; *decoder = handle_insert(data); err_code = VDP_STATUS_OK; goto quit; quit_free_data: free(data); quit: handle_release(device); return err_code; }