mixer.c revision e8e0756bd35e5e3b70a0eee323f5aaa3707fe11d
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include <vdpau/vdpau.h> 29 30#include "util/u_memory.h" 31#include "util/u_debug.h" 32 33#include "vl/vl_csc.h" 34 35#include "vdpau_private.h" 36 37/** 38 * Create a VdpVideoMixer. 39 */ 40VdpStatus 41vlVdpVideoMixerCreate(VdpDevice device, 42 uint32_t feature_count, 43 VdpVideoMixerFeature const *features, 44 uint32_t parameter_count, 45 VdpVideoMixerParameter const *parameters, 46 void const *const *parameter_values, 47 VdpVideoMixer *mixer) 48{ 49 vlVdpVideoMixer *vmixer = NULL; 50 VdpStatus ret; 51 struct pipe_screen *screen; 52 unsigned max_width, max_height, i; 53 enum pipe_video_profile prof = PIPE_VIDEO_PROFILE_UNKNOWN; 54 55 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating VideoMixer\n"); 56 57 vlVdpDevice *dev = vlGetDataHTAB(device); 58 if (!dev) 59 return VDP_STATUS_INVALID_HANDLE; 60 screen = dev->vscreen->pscreen; 61 62 vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); 63 if (!vmixer) 64 return VDP_STATUS_RESOURCES; 65 66 vmixer->device = dev; 67 vl_compositor_init(&vmixer->compositor, dev->context->pipe); 68 69 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, vmixer->csc); 70 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) 71 vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc); 72 73 /* 74 * TODO: Handle features 75 */ 76 77 *mixer = vlAddDataHTAB(vmixer); 78 if (*mixer == 0) { 79 ret = VDP_STATUS_ERROR; 80 goto no_handle; 81 } 82 vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 83 ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; 84 for (i = 0; i < parameter_count; ++i) { 85 switch (parameters[i]) { 86 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: 87 vmixer->video_width = *(uint32_t*)parameter_values[i]; 88 break; 89 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: 90 vmixer->video_height = *(uint32_t*)parameter_values[i]; 91 break; 92 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: 93 vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]); 94 break; 95 case VDP_VIDEO_MIXER_PARAMETER_LAYERS: 96 vmixer->max_layers = *(uint32_t*)parameter_values[i]; 97 break; 98 default: goto no_params; 99 } 100 } 101 ret = VDP_STATUS_INVALID_VALUE; 102 if (vmixer->max_layers > 4) { 103 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers); 104 goto no_params; 105 } 106 max_width = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_WIDTH); 107 max_height = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_HEIGHT); 108 if (vmixer->video_width < 48 || 109 vmixer->video_width > max_width) { 110 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer->video_width, max_width); 111 goto no_params; 112 } 113 if (vmixer->video_height < 48 || 114 vmixer->video_height > max_height) { 115 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer->video_height, max_height); 116 goto no_params; 117 } 118 vmixer->luma_key_min = 0.f; 119 vmixer->luma_key_max = 1.f; 120 vmixer->noise_reduction_level = 0.f; 121 vmixer->sharpness = 0.f; 122 return VDP_STATUS_OK; 123 124no_params: 125 vlRemoveDataHTAB(*mixer); 126no_handle: 127 vl_compositor_cleanup(&vmixer->compositor); 128 FREE(vmixer); 129 return ret; 130} 131 132/** 133 * Destroy a VdpVideoMixer. 134 */ 135VdpStatus 136vlVdpVideoMixerDestroy(VdpVideoMixer mixer) 137{ 138 vlVdpVideoMixer *vmixer; 139 140 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying VideoMixer\n"); 141 142 vmixer = vlGetDataHTAB(mixer); 143 if (!vmixer) 144 return VDP_STATUS_INVALID_HANDLE; 145 vlRemoveDataHTAB(mixer); 146 147 vl_compositor_cleanup(&vmixer->compositor); 148 149 FREE(vmixer); 150 151 return VDP_STATUS_OK; 152} 153 154/** 155 * Enable or disable features. 156 */ 157VdpStatus 158vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, 159 uint32_t feature_count, 160 VdpVideoMixerFeature const *features, 161 VdpBool const *feature_enables) 162{ 163 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Setting VideoMixer features\n"); 164 165 if (!(features && feature_enables)) 166 return VDP_STATUS_INVALID_POINTER; 167 168 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 169 if (!vmixer) 170 return VDP_STATUS_INVALID_HANDLE; 171 172 /* 173 * TODO: Set features 174 */ 175 176 return VDP_STATUS_OK; 177} 178 179/** 180 * Perform a video post-processing and compositing operation. 181 */ 182VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, 183 VdpOutputSurface background_surface, 184 VdpRect const *background_source_rect, 185 VdpVideoMixerPictureStructure current_picture_structure, 186 uint32_t video_surface_past_count, 187 VdpVideoSurface const *video_surface_past, 188 VdpVideoSurface video_surface_current, 189 uint32_t video_surface_future_count, 190 VdpVideoSurface const *video_surface_future, 191 VdpRect const *video_source_rect, 192 VdpOutputSurface destination_surface, 193 VdpRect const *destination_rect, 194 VdpRect const *destination_video_rect, 195 uint32_t layer_count, 196 VdpLayer const *layers) 197{ 198 struct pipe_video_rect src_rect, dst_rect, dst_clip; 199 200 vlVdpVideoMixer *vmixer; 201 vlVdpSurface *surf; 202 vlVdpOutputSurface *dst; 203 204 vmixer = vlGetDataHTAB(mixer); 205 if (!vmixer) 206 return VDP_STATUS_INVALID_HANDLE; 207 208 surf = vlGetDataHTAB(video_surface_current); 209 if (!surf) 210 return VDP_STATUS_INVALID_HANDLE; 211 212 if (surf->device != vmixer->device) 213 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 214 215 if (vmixer->video_width > surf->video_buffer->width || 216 vmixer->video_height > surf->video_buffer->height || 217 vmixer->chroma_format != surf->video_buffer->chroma_format) 218 return VDP_STATUS_INVALID_SIZE; 219 220 if (layer_count > vmixer->max_layers) 221 return VDP_STATUS_INVALID_VALUE; 222 223 dst = vlGetDataHTAB(destination_surface); 224 if (!dst) 225 return VDP_STATUS_INVALID_HANDLE; 226 227 vl_compositor_clear_layers(&vmixer->compositor); 228 vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer, 229 RectToPipe(video_source_rect, &src_rect), NULL); 230 vl_compositor_render(&vmixer->compositor, dst->surface, 231 RectToPipe(destination_video_rect, &dst_rect), 232 RectToPipe(destination_rect, &dst_clip), 233 &dst->dirty_area); 234 235 return VDP_STATUS_OK; 236} 237 238/** 239 * Set attribute values. 240 */ 241VdpStatus 242vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer, 243 uint32_t attribute_count, 244 VdpVideoMixerAttribute const *attributes, 245 void const *const *attribute_values) 246{ 247 const VdpColor *background_color; 248 union pipe_color_union color; 249 const float *vdp_csc; 250 float val; 251 unsigned i; 252 253 if (!(attributes && attribute_values)) 254 return VDP_STATUS_INVALID_POINTER; 255 256 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 257 if (!vmixer) 258 return VDP_STATUS_INVALID_HANDLE; 259 260 for (i = 0; i < attribute_count; ++i) { 261 switch (attributes[i]) { 262 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: 263 background_color = attribute_values[i]; 264 color.f[0] = background_color->red; 265 color.f[1] = background_color->green; 266 color.f[2] = background_color->blue; 267 color.f[3] = background_color->alpha; 268 vl_compositor_set_clear_color(&vmixer->compositor, &color); 269 break; 270 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: 271 vdp_csc = attribute_values[i]; 272 vmixer->custom_csc = !!vdp_csc; 273 if (!vdp_csc) 274 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, vmixer->csc); 275 else 276 memcpy(vmixer->csc, vdp_csc, sizeof(float)*12); 277 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) 278 vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc); 279 break; 280 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: 281 val = *(float*)attribute_values[i]; 282 if (val < 0.f || val > 1.f) 283 return VDP_STATUS_INVALID_VALUE; 284 vmixer->noise_reduction_level = val; 285 break; 286 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: 287 val = *(float*)attribute_values[i]; 288 if (val < 0.f || val > 1.f) 289 return VDP_STATUS_INVALID_VALUE; 290 vmixer->luma_key_min = val; 291 break; 292 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: 293 val = *(float*)attribute_values[i]; 294 if (val < 0.f || val > 1.f) 295 return VDP_STATUS_INVALID_VALUE; 296 vmixer->luma_key_max = val; 297 break; 298 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: 299 val = *(float*)attribute_values[i]; 300 if (val < -1.f || val > 1.f) 301 return VDP_STATUS_INVALID_VALUE; 302 vmixer->sharpness = val; 303 break; 304 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: 305 if (*(uint8_t*)attribute_values[i] > 1) 306 return VDP_STATUS_INVALID_VALUE; 307 vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i]; 308 break; 309 default: 310 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; 311 } 312 } 313 314 return VDP_STATUS_OK; 315} 316 317/** 318 * Retrieve whether features were requested at creation time. 319 */ 320VdpStatus 321vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, 322 uint32_t feature_count, 323 VdpVideoMixerFeature const *features, 324 VdpBool *feature_supports) 325{ 326 return VDP_STATUS_NO_IMPLEMENTATION; 327} 328 329/** 330 * Retrieve whether features are enabled. 331 */ 332VdpStatus 333vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, 334 uint32_t feature_count, 335 VdpVideoMixerFeature const *features, 336 VdpBool *feature_enables) 337{ 338 return VDP_STATUS_NO_IMPLEMENTATION; 339} 340 341/** 342 * Retrieve parameter values given at creation time. 343 */ 344VdpStatus 345vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer, 346 uint32_t parameter_count, 347 VdpVideoMixerParameter const *parameters, 348 void *const *parameter_values) 349{ 350 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 351 unsigned i; 352 if (!vmixer) 353 return VDP_STATUS_INVALID_HANDLE; 354 355 if (!parameter_count) 356 return VDP_STATUS_OK; 357 if (!(parameters && parameter_values)) 358 return VDP_STATUS_INVALID_POINTER; 359 for (i = 0; i < parameter_count; ++i) { 360 switch (parameters[i]) { 361 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: 362 *(uint32_t*)parameter_values[i] = vmixer->video_width; 363 break; 364 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: 365 *(uint32_t*)parameter_values[i] = vmixer->video_height; 366 break; 367 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: 368 *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format); 369 break; 370 case VDP_VIDEO_MIXER_PARAMETER_LAYERS: 371 *(uint32_t*)parameter_values[i] = vmixer->max_layers; 372 break; 373 default: 374 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; 375 } 376 } 377 return VDP_STATUS_OK; 378} 379 380/** 381 * Retrieve current attribute values. 382 */ 383VdpStatus 384vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer, 385 uint32_t attribute_count, 386 VdpVideoMixerAttribute const *attributes, 387 void *const *attribute_values) 388{ 389 unsigned i; 390 VdpCSCMatrix **vdp_csc; 391 392 if (!(attributes && attribute_values)) 393 return VDP_STATUS_INVALID_POINTER; 394 395 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 396 if (!vmixer) 397 return VDP_STATUS_INVALID_HANDLE; 398 399 for (i = 0; i < attribute_count; ++i) { 400 switch (attributes[i]) { 401 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: 402 vl_compositor_get_clear_color(&vmixer->compositor, attribute_values[i]); 403 break; 404 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: 405 vdp_csc = attribute_values[i]; 406 if (!vmixer->custom_csc) { 407 *vdp_csc = NULL; 408 break; 409 } 410 memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12); 411 break; 412 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: 413 *(float*)attribute_values[i] = vmixer->noise_reduction_level; 414 break; 415 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: 416 *(float*)attribute_values[i] = vmixer->luma_key_min; 417 break; 418 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: 419 *(float*)attribute_values[i] = vmixer->luma_key_max; 420 break; 421 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: 422 *(float*)attribute_values[i] = vmixer->sharpness; 423 break; 424 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: 425 *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint; 426 break; 427 default: 428 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; 429 } 430 } 431 return VDP_STATUS_OK; 432} 433 434/** 435 * Generate a color space conversion matrix. 436 */ 437VdpStatus 438vlVdpGenerateCSCMatrix(VdpProcamp *procamp, 439 VdpColorStandard standard, 440 VdpCSCMatrix *csc_matrix) 441{ 442 float matrix[16]; 443 enum VL_CSC_COLOR_STANDARD vl_std; 444 struct vl_procamp camp; 445 446 if (!(csc_matrix && procamp)) 447 return VDP_STATUS_INVALID_POINTER; 448 449 if (procamp->struct_version > VDP_PROCAMP_VERSION) 450 return VDP_STATUS_INVALID_STRUCT_VERSION; 451 452 switch (standard) { 453 case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break; 454 case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break; 455 case VDP_COLOR_STANDARD_SMPTE_240M: vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break; 456 default: return VDP_STATUS_INVALID_COLOR_STANDARD; 457 } 458 camp.brightness = procamp->brightness; 459 camp.contrast = procamp->contrast; 460 camp.saturation = procamp->saturation; 461 camp.hue = procamp->hue; 462 vl_csc_get_matrix(vl_std, &camp, 1, matrix); 463 memcpy(csc_matrix, matrix, sizeof(float)*12); 464 return VDP_STATUS_OK; 465} 466