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