📄 vdpau_video.c
字号:
/* * vdpau_video.c - VDPAU backend for VA API * * vdpau-video (C) 2009 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */#include "sysdeps.h"#include "vdpau_video.h"#include <va/va_backend.h>#include <stdarg.h>#define DEBUG 1#include "debug.h"#define ASSERT assert#define INIT_DRIVER_DATA \ struct vdpau_driver_data *driver_data = (struct vdpau_driver_data *)ctx->pDriverData#define CONFIG(id) \ ((object_config_p)object_heap_lookup(&driver_data->config_heap, id))#define CONTEXT(id) \ ((object_context_p)object_heap_lookup(&driver_data->context_heap, id))#define SURFACE(id) \ ((object_surface_p)object_heap_lookup(&driver_data->surface_heap, id))#define BUFFER(id) \ ((object_buffer_p)object_heap_lookup(&driver_data->buffer_heap, id))#define OUTPUT(id) \ ((object_output_p)object_heap_lookup(&driver_data->output_heap, id))#define CONFIG_ID_OFFSET 0x01000000#define CONTEXT_ID_OFFSET 0x02000000#define SURFACE_ID_OFFSET 0x04000000#define BUFFER_ID_OFFSET 0x08000000#define OUTPUT_ID_OFFSET 0x10000000/* ====================================================================== *//* === Helpers === *//* ====================================================================== */// Returns X drawable dimensionsstatic void get_drawable_size(Display *display, Drawable drawable, uint32_t *pwidth, uint32_t *pheight){ Window rootwin; int x, y; unsigned int width, height, border_width, depth; XGetGeometry(display, drawable, &rootwin, &x, &y, &width, &height, &border_width, &depth); if (pwidth) *pwidth = width; if (pheight) *pheight = height;}// Returns string representation of VABufferTypestatic const char *string_of_VABufferType(VABufferType type){ const char *str = NULL; switch (type) {#define _(X) case X: str = #X; break _(VAPictureParameterBufferType); _(VAIQMatrixBufferType); _(VABitPlaneBufferType); _(VASliceGroupMapBufferType); _(VASliceParameterBufferType); _(VASliceDataBufferType); _(VAMacroblockParameterBufferType); _(VAResidualDataBufferType); _(VADeblockingParameterBufferType); _(VAImageBufferType);#undef _ } return str;}// Translates VdpStatus to VAStatusstatic VAStatus get_VAStatus(VdpStatus status){ VAStatus va_status; switch (status) { case VDP_STATUS_OK: va_status = VA_STATUS_SUCCESS; break; case VDP_STATUS_INVALID_DECODER_PROFILE: va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; break; default: D(bug("WARNING: unknown VdpStatus %d\n", status)); va_status = VA_STATUS_ERROR_UNKNOWN; break; } return va_status;}// Returns string representation of VdpCodecstatic const char *string_of_VdpCodec(VdpCodec codec){ const char *str = NULL; switch (codec) {#define _(X) case VDP_CODEC_##X: str = #X; break _(MPEG1); _(MPEG2); _(MPEG4); _(H264); _(VC1);#undef _ } return str;}// Translates VdpDecoderProfile to VdpCodecstatic VdpCodec get_VdpCodec(VdpDecoderProfile profile){ switch (profile) { case VDP_DECODER_PROFILE_MPEG1: return VDP_CODEC_MPEG1; case VDP_DECODER_PROFILE_MPEG2_SIMPLE: case VDP_DECODER_PROFILE_MPEG2_MAIN: return VDP_CODEC_MPEG2; case VDP_DECODER_PROFILE_H264_BASELINE: case VDP_DECODER_PROFILE_H264_MAIN: case VDP_DECODER_PROFILE_H264_HIGH: return VDP_CODEC_H264; case VDP_DECODER_PROFILE_VC1_SIMPLE: case VDP_DECODER_PROFILE_VC1_MAIN: case VDP_DECODER_PROFILE_VC1_ADVANCED: return VDP_CODEC_VC1; } ASSERT(profile); return 0;}// Computes value for VdpDecoderCreate()::max_references parameterstatic int get_VdpDecoder_max_references(VdpDecoderProfile profile, uint32_t width, uint32_t height){ int max_references = 2; switch (profile) { case VDP_DECODER_PROFILE_H264_MAIN: case VDP_DECODER_PROFILE_H264_HIGH: { /* level 4.1 limits */ uint32_t aligned_width = (width + 15) & -16; uint32_t aligned_height = (height + 15) & -16; uint32_t surface_size = (aligned_width * aligned_height * 3) / 2; if ((max_references = (12 * 1024 * 1024) / surface_size) > 16) max_references = 16; break; } } return max_references;}// Translates VA API chroma format to VdpChromaTypestatic VdpChromaType get_VdpChromaType(int format){ switch (format) { case VA_RT_FORMAT_YUV420: return VDP_CHROMA_TYPE_420; case VA_RT_FORMAT_YUV422: return VDP_CHROMA_TYPE_422; case VA_RT_FORMAT_YUV444: return VDP_CHROMA_TYPE_444; } ASSERT(format); return (VdpChromaType)-1;}// Translates VAProfile to VdpDecoderProfilestatic VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile){ switch (profile) { case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE; case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN; case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE; case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN; case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH; case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE; case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN; case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED; } ASSERT(profile); return (VdpDecoderProfile)-1;}/* ====================================================================== *//* === VDPAU Gate === *//* ====================================================================== */// VdpVideoSurfaceCreatestatic inline VdpStatusvdpau_video_surface_create(vdpau_driver_data_t *driver_data, VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height, VdpVideoSurface *surface){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_video_surface_create == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_video_surface_create(device, chroma_type, width, height, surface);}// VdpVideoSurfaceDestroystatic inline VdpStatusvdpau_video_surface_destroy(vdpau_driver_data_t *driver_data, VdpVideoSurface surface){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_video_surface_destroy == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_video_surface_destroy(surface);}// VdpOutputSurfaceCreatestatic inline VdpStatusvdpau_output_surface_create(vdpau_driver_data_t *driver_data, VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpOutputSurface *surface){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_output_surface_create == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_output_surface_create(device, rgba_format, width, height, surface);}// VdpOutputSurfaceDestroystatic inline VdpStatusvdpau_output_surface_destroy(vdpau_driver_data_t *driver_data, VdpOutputSurface surface){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_output_surface_destroy == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_output_surface_destroy(surface);}// VdpVideoMixerCreatestatic inline VdpStatusvdpau_video_mixer_create(vdpau_driver_data_t *driver_data, VdpDevice device, uint32_t feature_count, VdpVideoMixerFeature const *features, uint32_t parameter_count, VdpVideoMixerParameter const *parameters, const void *parameter_values, VdpVideoMixer *mixer){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_video_mixer_create == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_video_mixer_create(device, feature_count, features, parameter_count, parameters, parameter_values, mixer);}// VdpVideoMixerDestroystatic inline VdpStatusvdpau_video_mixer_destroy(vdpau_driver_data_t *driver_data, VdpVideoMixer mixer){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_video_mixer_destroy == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_video_mixer_destroy(mixer);}// VdpVideoMixerRenderstatic inline VdpStatusvdpau_video_mixer_render(vdpau_driver_data_t *driver_data, VdpVideoMixer mixer, VdpOutputSurface background_surface, const VdpRect *background_source_rect, VdpVideoMixerPictureStructure current_picture_structure, uint32_t video_surface_past_count, const VdpVideoSurface *video_surface_past, VdpVideoSurface video_surface_current, uint32_t video_surface_future_count, const VdpVideoSurface *video_surface_future, const VdpRect *video_source_rect, VdpOutputSurface destination_surface, const VdpRect *destination_rect, const VdpRect *destination_video_rect, uint32_t layer_count, const VdpLayer *layers){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_video_mixer_render == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_video_mixer_render(mixer, background_surface, background_source_rect, current_picture_structure, video_surface_past_count, video_surface_past, video_surface_current, video_surface_future_count, video_surface_future, video_source_rect, destination_surface, destination_rect, destination_video_rect, layer_count, layers);}// VdpPresentationQueueCreatestatic inline VdpStatusvdpau_presentation_queue_create(vdpau_driver_data_t *driver_data, VdpDevice device, VdpPresentationQueueTarget presentation_queue_target, VdpPresentationQueue *presentation_queue){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_presentation_queue_create == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_presentation_queue_create(device, presentation_queue_target, presentation_queue);}// VdpPresentationQueueDestroystatic inline VdpStatusvdpau_presentation_queue_destroy(vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_presentation_queue_destroy == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_presentation_queue_destroy(presentation_queue);}// VdpPresentationQueueDisplaystatic inline VdpStatusvdpau_presentation_queue_display(vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, uint32_t clip_width, uint32_t clip_height, VdpTime earliest_presentation_time){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_presentation_queue_display == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_presentation_queue_display(presentation_queue, surface, clip_width, clip_height, earliest_presentation_time);}// VdpPresentationQueueBlockUntilSurfaceIdlestatic inline VdpStatusvdpau_presentation_queue_block_until_surface_idle(vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, VdpTime *first_presentation_time){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_presentation_queue_block_until_surface_idle == NULL) return VDP_STATUS_INVALID_POINTER; return driver_data->vdp_vtable.vdp_presentation_queue_block_until_surface_idle(presentation_queue, surface, first_presentation_time);}// VdpPresentationQueueTargetCreateX11static inline VdpStatusvdpau_presentation_queue_target_create_x11(vdpau_driver_data_t *driver_data, VdpDevice device, Drawable drawable, VdpPresentationQueueTarget *target){ if (driver_data == NULL) return VDP_STATUS_INVALID_POINTER; if (driver_data->vdp_vtable.vdp_presentation_queue_target_create_x11 == NULL) return VDP_STATUS_INVALID_POINTER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -