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