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