mixer.c revision 553e8203879d163e6fe2f3a8f6b80a44749514c1
1eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey/************************************************************************** 2eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * 3eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * Copyright 2010 Thomas Balling Sørensen. 4eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * All Rights Reserved. 5eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * 6eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * Permission is hereby granted, free of charge, to any person obtaining a 7eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * copy of this software and associated documentation files (the 8eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * "Software"), to deal in the Software without restriction, including 9eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * without limitation the rights to use, copy, modify, merge, publish, 10eb47a8c4f989358eb087720918ff77a8e1e6f260Rich Humphrey * 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 *mixer = vlAddDataHTAB(vmixer); 74 if (*mixer == 0) { 75 ret = VDP_STATUS_ERROR; 76 goto no_handle; 77 } 78 79 ret = VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; 80 for (i = 0; i < feature_count; ++i) { 81 switch (features[i]) { 82 /* they are valid, but we doesn't support them */ 83 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: 84 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: 85 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: 86 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: 87 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: 88 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: 89 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: 90 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: 91 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: 92 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: 93 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: 94 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: 95 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: 96 break; 97 98 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: 99 vmixer->sharpness.supported = true; 100 break; 101 102 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: 103 vmixer->noise_reduction.supported = true; 104 break; 105 106 default: goto no_params; 107 } 108 } 109 110 vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 111 ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; 112 for (i = 0; i < parameter_count; ++i) { 113 switch (parameters[i]) { 114 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: 115 vmixer->video_width = *(uint32_t*)parameter_values[i]; 116 break; 117 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: 118 vmixer->video_height = *(uint32_t*)parameter_values[i]; 119 break; 120 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: 121 vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]); 122 break; 123 case VDP_VIDEO_MIXER_PARAMETER_LAYERS: 124 vmixer->max_layers = *(uint32_t*)parameter_values[i]; 125 break; 126 default: goto no_params; 127 } 128 } 129 ret = VDP_STATUS_INVALID_VALUE; 130 if (vmixer->max_layers > 4) { 131 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers); 132 goto no_params; 133 } 134 max_width = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_WIDTH); 135 max_height = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_HEIGHT); 136 if (vmixer->video_width < 48 || 137 vmixer->video_width > max_width) { 138 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer->video_width, max_width); 139 goto no_params; 140 } 141 if (vmixer->video_height < 48 || 142 vmixer->video_height > max_height) { 143 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer->video_height, max_height); 144 goto no_params; 145 } 146 vmixer->luma_key_min = 0.f; 147 vmixer->luma_key_max = 1.f; 148 149 return VDP_STATUS_OK; 150 151no_params: 152 vlRemoveDataHTAB(*mixer); 153no_handle: 154 vl_compositor_cleanup(&vmixer->compositor); 155 FREE(vmixer); 156 return ret; 157} 158 159/** 160 * Destroy a VdpVideoMixer. 161 */ 162VdpStatus 163vlVdpVideoMixerDestroy(VdpVideoMixer mixer) 164{ 165 vlVdpVideoMixer *vmixer; 166 167 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying VideoMixer\n"); 168 169 vmixer = vlGetDataHTAB(mixer); 170 if (!vmixer) 171 return VDP_STATUS_INVALID_HANDLE; 172 vlRemoveDataHTAB(mixer); 173 174 vl_compositor_cleanup(&vmixer->compositor); 175 176 if (vmixer->noise_reduction.filter) { 177 vl_median_filter_cleanup(vmixer->noise_reduction.filter); 178 FREE(vmixer->noise_reduction.filter); 179 } 180 181 FREE(vmixer); 182 183 return VDP_STATUS_OK; 184} 185 186/** 187 * Perform a video post-processing and compositing operation. 188 */ 189VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, 190 VdpOutputSurface background_surface, 191 VdpRect const *background_source_rect, 192 VdpVideoMixerPictureStructure current_picture_structure, 193 uint32_t video_surface_past_count, 194 VdpVideoSurface const *video_surface_past, 195 VdpVideoSurface video_surface_current, 196 uint32_t video_surface_future_count, 197 VdpVideoSurface const *video_surface_future, 198 VdpRect const *video_source_rect, 199 VdpOutputSurface destination_surface, 200 VdpRect const *destination_rect, 201 VdpRect const *destination_video_rect, 202 uint32_t layer_count, 203 VdpLayer const *layers) 204{ 205 struct pipe_video_rect src_rect, dst_rect, dst_clip; 206 unsigned layer = 0; 207 208 vlVdpVideoMixer *vmixer; 209 vlVdpSurface *surf; 210 vlVdpOutputSurface *dst; 211 212 vmixer = vlGetDataHTAB(mixer); 213 if (!vmixer) 214 return VDP_STATUS_INVALID_HANDLE; 215 216 surf = vlGetDataHTAB(video_surface_current); 217 if (!surf) 218 return VDP_STATUS_INVALID_HANDLE; 219 220 if (surf->device != vmixer->device) 221 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 222 223 if (vmixer->video_width > surf->video_buffer->width || 224 vmixer->video_height > surf->video_buffer->height || 225 vmixer->chroma_format != surf->video_buffer->chroma_format) 226 return VDP_STATUS_INVALID_SIZE; 227 228 if (layer_count > vmixer->max_layers) 229 return VDP_STATUS_INVALID_VALUE; 230 231 dst = vlGetDataHTAB(destination_surface); 232 if (!dst) 233 return VDP_STATUS_INVALID_HANDLE; 234 235 if (background_surface != VDP_INVALID_HANDLE) { 236 vlVdpOutputSurface *bg = vlGetDataHTAB(background_surface); 237 if (!bg) 238 return VDP_STATUS_INVALID_HANDLE; 239 vl_compositor_set_rgba_layer(&vmixer->compositor, layer++, bg->sampler_view, 240 RectToPipe(background_source_rect, &src_rect), NULL); 241 } 242 243 vl_compositor_clear_layers(&vmixer->compositor); 244 vl_compositor_set_buffer_layer(&vmixer->compositor, layer++, surf->video_buffer, 245 RectToPipe(video_source_rect, &src_rect), NULL); 246 vl_compositor_render(&vmixer->compositor, dst->surface, 247 RectToPipe(destination_video_rect, &dst_rect), 248 RectToPipe(destination_rect, &dst_clip), 249 &dst->dirty_area); 250 251 /* applying the noise reduction after scaling is actually not very 252 clever, but currently we should avoid to copy around the image 253 data once more. */ 254 if (vmixer->noise_reduction.filter) 255 vl_median_filter_render(vmixer->noise_reduction.filter, 256 dst->sampler_view, dst->surface); 257 258 if (vmixer->sharpness.filter) 259 vl_matrix_filter_render(vmixer->sharpness.filter, 260 dst->sampler_view, dst->surface); 261 262 return VDP_STATUS_OK; 263} 264 265/** 266 * Update the noise reduction setting 267 */ 268static void 269vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer *vmixer) 270{ 271 assert(vmixer); 272 273 /* if present remove the old filter first */ 274 if (vmixer->noise_reduction.filter) { 275 vl_median_filter_cleanup(vmixer->noise_reduction.filter); 276 FREE(vmixer->noise_reduction.filter); 277 vmixer->noise_reduction.filter = NULL; 278 } 279 280 /* and create a new filter as needed */ 281 if (vmixer->noise_reduction. enabled && vmixer->noise_reduction.level > 0) { 282 vmixer->noise_reduction.filter = MALLOC(sizeof(struct vl_median_filter)); 283 vl_median_filter_init(vmixer->noise_reduction.filter, 284 vmixer->device->context->pipe, 285 vmixer->video_width, vmixer->video_height, 286 vmixer->noise_reduction.level + 1, 287 VL_MEDIAN_FILTER_CROSS); 288 } 289} 290 291static void 292vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer) 293{ 294 assert(vmixer); 295 296 /* if present remove the old filter first */ 297 if (vmixer->sharpness.filter) { 298 vl_matrix_filter_cleanup(vmixer->sharpness.filter); 299 FREE(vmixer->sharpness.filter); 300 vmixer->sharpness.filter = NULL; 301 } 302 303 /* and create a new filter as needed */ 304 if (vmixer->sharpness.enabled && vmixer->sharpness.value != 0.0f) { 305 float matrix[9]; 306 unsigned i; 307 308 if (vmixer->sharpness.value > 0.0f) { 309 matrix[0] = -1.0f; matrix[1] = -1.0f; matrix[2] = -1.0f; 310 matrix[3] = -1.0f; matrix[4] = 8.0f; matrix[5] = -1.0f; 311 matrix[6] = -1.0f; matrix[7] = -1.0f; matrix[8] = -1.0f; 312 313 for (i = 0; i < 9; ++i) 314 matrix[i] *= vmixer->sharpness.value; 315 316 matrix[4] += 1.0f; 317 318 } else { 319 matrix[0] = 1.0f; matrix[1] = 2.0f; matrix[2] = 1.0f; 320 matrix[3] = 2.0f; matrix[4] = 4.0f; matrix[5] = 2.0f; 321 matrix[6] = 1.0f; matrix[7] = 2.0f; matrix[8] = 1.0f; 322 323 for (i = 0; i < 9; ++i) 324 matrix[i] *= fabsf(vmixer->sharpness.value) / 16.0f; 325 326 matrix[4] += 1.0f - fabsf(vmixer->sharpness.value); 327 } 328 329 vmixer->sharpness.filter = MALLOC(sizeof(struct vl_matrix_filter)); 330 vl_matrix_filter_init(vmixer->sharpness.filter, 331 vmixer->device->context->pipe, 332 vmixer->video_width, vmixer->video_height, 333 3, 3, matrix); 334 } 335} 336 337/** 338 * Retrieve whether features were requested at creation time. 339 */ 340VdpStatus 341vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, 342 uint32_t feature_count, 343 VdpVideoMixerFeature const *features, 344 VdpBool *feature_supports) 345{ 346 vlVdpVideoMixer *vmixer; 347 unsigned i; 348 349 if (!(features && feature_supports)) 350 return VDP_STATUS_INVALID_POINTER; 351 352 vmixer = vlGetDataHTAB(mixer); 353 if (!vmixer) 354 return VDP_STATUS_INVALID_HANDLE; 355 356 for (i = 0; i < feature_count; ++i) { 357 switch (features[i]) { 358 /* they are valid, but we doesn't support them */ 359 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: 360 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: 361 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: 362 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: 363 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: 364 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: 365 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: 366 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: 367 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: 368 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: 369 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: 370 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: 371 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: 372 feature_supports[i] = false; 373 break; 374 375 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: 376 feature_supports[i] = vmixer->sharpness.supported; 377 break; 378 379 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: 380 feature_supports[i] = vmixer->noise_reduction.supported; 381 break; 382 383 default: 384 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; 385 } 386 } 387 388 return VDP_STATUS_OK; 389} 390 391/** 392 * Enable or disable features. 393 */ 394VdpStatus 395vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, 396 uint32_t feature_count, 397 VdpVideoMixerFeature const *features, 398 VdpBool const *feature_enables) 399{ 400 vlVdpVideoMixer *vmixer; 401 unsigned i; 402 403 if (!(features && feature_enables)) 404 return VDP_STATUS_INVALID_POINTER; 405 406 vmixer = vlGetDataHTAB(mixer); 407 if (!vmixer) 408 return VDP_STATUS_INVALID_HANDLE; 409 410 for (i = 0; i < feature_count; ++i) { 411 switch (features[i]) { 412 /* they are valid, but we doesn't support them */ 413 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: 414 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: 415 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: 416 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: 417 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: 418 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: 419 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: 420 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: 421 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: 422 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: 423 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: 424 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: 425 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: 426 break; 427 428 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: 429 vmixer->sharpness.enabled = feature_enables[i]; 430 vlVdpVideoMixerUpdateSharpnessFilter(vmixer); 431 break; 432 433 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: 434 vmixer->noise_reduction.enabled = feature_enables[i]; 435 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); 436 break; 437 438 default: 439 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; 440 } 441 } 442 443 return VDP_STATUS_OK; 444} 445 446/** 447 * Retrieve whether features are enabled. 448 */ 449VdpStatus 450vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, 451 uint32_t feature_count, 452 VdpVideoMixerFeature const *features, 453 VdpBool *feature_enables) 454{ 455 vlVdpVideoMixer *vmixer; 456 unsigned i; 457 458 if (!(features && feature_enables)) 459 return VDP_STATUS_INVALID_POINTER; 460 461 vmixer = vlGetDataHTAB(mixer); 462 if (!vmixer) 463 return VDP_STATUS_INVALID_HANDLE; 464 465 for (i = 0; i < feature_count; ++i) { 466 switch (features[i]) { 467 /* they are valid, but we doesn't support them */ 468 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: 469 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: 470 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: 471 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: 472 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: 473 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: 474 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: 475 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: 476 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: 477 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: 478 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: 479 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: 480 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: 481 break; 482 483 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: 484 feature_enables[i] = vmixer->sharpness.enabled; 485 break; 486 487 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: 488 feature_enables[i] = vmixer->noise_reduction.enabled; 489 break; 490 491 default: 492 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; 493 } 494 } 495 496 return VDP_STATUS_OK; 497} 498 499/** 500 * Set attribute values. 501 */ 502VdpStatus 503vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer, 504 uint32_t attribute_count, 505 VdpVideoMixerAttribute const *attributes, 506 void const *const *attribute_values) 507{ 508 const VdpColor *background_color; 509 union pipe_color_union color; 510 const float *vdp_csc; 511 float val; 512 unsigned i; 513 514 if (!(attributes && attribute_values)) 515 return VDP_STATUS_INVALID_POINTER; 516 517 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 518 if (!vmixer) 519 return VDP_STATUS_INVALID_HANDLE; 520 521 for (i = 0; i < attribute_count; ++i) { 522 switch (attributes[i]) { 523 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: 524 background_color = attribute_values[i]; 525 color.f[0] = background_color->red; 526 color.f[1] = background_color->green; 527 color.f[2] = background_color->blue; 528 color.f[3] = background_color->alpha; 529 vl_compositor_set_clear_color(&vmixer->compositor, &color); 530 break; 531 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: 532 vdp_csc = attribute_values[i]; 533 vmixer->custom_csc = !!vdp_csc; 534 if (!vdp_csc) 535 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, vmixer->csc); 536 else 537 memcpy(vmixer->csc, vdp_csc, sizeof(float)*12); 538 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) 539 vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc); 540 break; 541 542 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: 543 544 val = *(float*)attribute_values[i]; 545 if (val < 0.f || val > 1.f) 546 return VDP_STATUS_INVALID_VALUE; 547 548 vmixer->noise_reduction.level = val * 10; 549 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); 550 break; 551 552 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: 553 val = *(float*)attribute_values[i]; 554 if (val < 0.f || val > 1.f) 555 return VDP_STATUS_INVALID_VALUE; 556 vmixer->luma_key_min = val; 557 break; 558 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: 559 val = *(float*)attribute_values[i]; 560 if (val < 0.f || val > 1.f) 561 return VDP_STATUS_INVALID_VALUE; 562 vmixer->luma_key_max = val; 563 break; 564 565 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: 566 567 val = *(float*)attribute_values[i]; 568 if (val < -1.f || val > 1.f) 569 return VDP_STATUS_INVALID_VALUE; 570 571 vmixer->sharpness.value = val; 572 vlVdpVideoMixerUpdateSharpnessFilter(vmixer); 573 break; 574 575 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: 576 if (*(uint8_t*)attribute_values[i] > 1) 577 return VDP_STATUS_INVALID_VALUE; 578 vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i]; 579 break; 580 default: 581 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; 582 } 583 } 584 585 return VDP_STATUS_OK; 586} 587 588/** 589 * Retrieve parameter values given at creation time. 590 */ 591VdpStatus 592vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer, 593 uint32_t parameter_count, 594 VdpVideoMixerParameter const *parameters, 595 void *const *parameter_values) 596{ 597 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 598 unsigned i; 599 if (!vmixer) 600 return VDP_STATUS_INVALID_HANDLE; 601 602 if (!parameter_count) 603 return VDP_STATUS_OK; 604 if (!(parameters && parameter_values)) 605 return VDP_STATUS_INVALID_POINTER; 606 for (i = 0; i < parameter_count; ++i) { 607 switch (parameters[i]) { 608 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: 609 *(uint32_t*)parameter_values[i] = vmixer->video_width; 610 break; 611 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: 612 *(uint32_t*)parameter_values[i] = vmixer->video_height; 613 break; 614 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: 615 *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format); 616 break; 617 case VDP_VIDEO_MIXER_PARAMETER_LAYERS: 618 *(uint32_t*)parameter_values[i] = vmixer->max_layers; 619 break; 620 default: 621 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; 622 } 623 } 624 return VDP_STATUS_OK; 625} 626 627/** 628 * Retrieve current attribute values. 629 */ 630VdpStatus 631vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer, 632 uint32_t attribute_count, 633 VdpVideoMixerAttribute const *attributes, 634 void *const *attribute_values) 635{ 636 unsigned i; 637 VdpCSCMatrix **vdp_csc; 638 639 if (!(attributes && attribute_values)) 640 return VDP_STATUS_INVALID_POINTER; 641 642 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); 643 if (!vmixer) 644 return VDP_STATUS_INVALID_HANDLE; 645 646 for (i = 0; i < attribute_count; ++i) { 647 switch (attributes[i]) { 648 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: 649 vl_compositor_get_clear_color(&vmixer->compositor, attribute_values[i]); 650 break; 651 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: 652 vdp_csc = attribute_values[i]; 653 if (!vmixer->custom_csc) { 654 *vdp_csc = NULL; 655 break; 656 } 657 memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12); 658 break; 659 660 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: 661 *(float*)attribute_values[i] = (float)vmixer->noise_reduction.level / 10.0f; 662 break; 663 664 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: 665 *(float*)attribute_values[i] = vmixer->luma_key_min; 666 break; 667 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: 668 *(float*)attribute_values[i] = vmixer->luma_key_max; 669 break; 670 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: 671 *(float*)attribute_values[i] = vmixer->sharpness.value; 672 break; 673 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: 674 *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint; 675 break; 676 default: 677 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; 678 } 679 } 680 return VDP_STATUS_OK; 681} 682 683/** 684 * Generate a color space conversion matrix. 685 */ 686VdpStatus 687vlVdpGenerateCSCMatrix(VdpProcamp *procamp, 688 VdpColorStandard standard, 689 VdpCSCMatrix *csc_matrix) 690{ 691 float matrix[16]; 692 enum VL_CSC_COLOR_STANDARD vl_std; 693 struct vl_procamp camp; 694 695 if (!(csc_matrix && procamp)) 696 return VDP_STATUS_INVALID_POINTER; 697 698 if (procamp->struct_version > VDP_PROCAMP_VERSION) 699 return VDP_STATUS_INVALID_STRUCT_VERSION; 700 701 switch (standard) { 702 case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break; 703 case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break; 704 case VDP_COLOR_STANDARD_SMPTE_240M: vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break; 705 default: return VDP_STATUS_INVALID_COLOR_STANDARD; 706 } 707 camp.brightness = procamp->brightness; 708 camp.contrast = procamp->contrast; 709 camp.saturation = procamp->saturation; 710 camp.hue = procamp->hue; 711 vl_csc_get_matrix(vl_std, &camp, 1, matrix); 712 memcpy(csc_matrix, matrix, sizeof(float)*12); 713 return VDP_STATUS_OK; 714} 715