1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
28 #include <vdpau/vdpau.h>
30 #include "util/u_memory.h"
31 #include "util/u_debug.h"
33 #include "vl/vl_csc.h"
35 #include "vdpau_private.h"
38 * Create a VdpVideoMixer.
41 vlVdpVideoMixerCreate(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
,
49 vlVdpVideoMixer
*vmixer
= NULL
;
51 struct pipe_screen
*screen
;
52 unsigned max_width
, max_height
, i
;
53 enum pipe_video_profile prof
= PIPE_VIDEO_PROFILE_UNKNOWN
;
55 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
57 return VDP_STATUS_INVALID_HANDLE
;
58 screen
= dev
->vscreen
->pscreen
;
60 vmixer
= CALLOC(1, sizeof(vlVdpVideoMixer
));
62 return VDP_STATUS_RESOURCES
;
65 vl_compositor_init_state(&vmixer
->cstate
, dev
->context
);
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
, (const vl_csc_matrix
*)&vmixer
->csc
);
71 *mixer
= vlAddDataHTAB(vmixer
);
73 ret
= VDP_STATUS_ERROR
;
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
:
96 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
97 vmixer
->sharpness
.supported
= true;
100 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
101 vmixer
->noise_reduction
.supported
= true;
104 default: goto no_params
;
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
];
115 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
116 vmixer
->video_height
= *(uint32_t*)parameter_values
[i
];
118 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
119 vmixer
->chroma_format
= ChromaToPipe(*(VdpChromaType
*)parameter_values
[i
]);
121 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
122 vmixer
->max_layers
= *(uint32_t*)parameter_values
[i
];
124 default: goto no_params
;
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
);
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
);
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
);
144 vmixer
->luma_key_min
= 0.f
;
145 vmixer
->luma_key_max
= 1.f
;
147 return VDP_STATUS_OK
;
150 vlRemoveDataHTAB(*mixer
);
153 vl_compositor_cleanup_state(&vmixer
->cstate
);
159 * Destroy a VdpVideoMixer.
162 vlVdpVideoMixerDestroy(VdpVideoMixer mixer
)
164 vlVdpVideoMixer
*vmixer
;
166 vmixer
= vlGetDataHTAB(mixer
);
168 return VDP_STATUS_INVALID_HANDLE
;
170 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
172 vlRemoveDataHTAB(mixer
);
174 vl_compositor_cleanup_state(&vmixer
->cstate
);
176 if (vmixer
->noise_reduction
.filter
) {
177 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
178 FREE(vmixer
->noise_reduction
.filter
);
181 if (vmixer
->sharpness
.filter
) {
182 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
183 FREE(vmixer
->sharpness
.filter
);
188 return VDP_STATUS_OK
;
192 * Perform a video post-processing and compositing operation.
194 VdpStatus
vlVdpVideoMixerRender(VdpVideoMixer mixer
,
195 VdpOutputSurface background_surface
,
196 VdpRect
const *background_source_rect
,
197 VdpVideoMixerPictureStructure current_picture_structure
,
198 uint32_t video_surface_past_count
,
199 VdpVideoSurface
const *video_surface_past
,
200 VdpVideoSurface video_surface_current
,
201 uint32_t video_surface_future_count
,
202 VdpVideoSurface
const *video_surface_future
,
203 VdpRect
const *video_source_rect
,
204 VdpOutputSurface destination_surface
,
205 VdpRect
const *destination_rect
,
206 VdpRect
const *destination_video_rect
,
207 uint32_t layer_count
,
208 VdpLayer
const *layers
)
210 struct u_rect src_rect
, dst_rect
, dst_clip
;
211 enum vl_compositor_deinterlace deinterlace
;
214 vlVdpVideoMixer
*vmixer
;
216 vlVdpOutputSurface
*dst
;
218 struct vl_compositor
*compositor
;
220 vmixer
= vlGetDataHTAB(mixer
);
222 return VDP_STATUS_INVALID_HANDLE
;
224 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
226 compositor
= &vmixer
->device
->compositor
;
228 surf
= vlGetDataHTAB(video_surface_current
);
230 return VDP_STATUS_INVALID_HANDLE
;
232 if (surf
->device
!= vmixer
->device
)
233 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
235 if (vmixer
->video_width
> surf
->video_buffer
->width
||
236 vmixer
->video_height
> surf
->video_buffer
->height
||
237 vmixer
->chroma_format
!= surf
->video_buffer
->chroma_format
)
238 return VDP_STATUS_INVALID_SIZE
;
240 if (layer_count
> vmixer
->max_layers
)
241 return VDP_STATUS_INVALID_VALUE
;
243 dst
= vlGetDataHTAB(destination_surface
);
245 return VDP_STATUS_INVALID_HANDLE
;
247 if (background_surface
!= VDP_INVALID_HANDLE
) {
248 vlVdpOutputSurface
*bg
= vlGetDataHTAB(background_surface
);
250 return VDP_STATUS_INVALID_HANDLE
;
251 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
++, bg
->sampler_view
,
252 RectToPipe(background_source_rect
, &src_rect
), NULL
, NULL
);
255 vl_compositor_clear_layers(&vmixer
->cstate
);
257 switch (current_picture_structure
) {
258 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD
:
259 deinterlace
= VL_COMPOSITOR_BOB_TOP
;
262 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD
:
263 deinterlace
= VL_COMPOSITOR_BOB_BOTTOM
;
266 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
:
267 deinterlace
= VL_COMPOSITOR_WEAVE
;
271 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE
;
273 vl_compositor_set_buffer_layer(&vmixer
->cstate
, compositor
, layer
, surf
->video_buffer
,
274 RectToPipe(video_source_rect
, &src_rect
), NULL
, deinterlace
);
275 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(destination_video_rect
, &dst_rect
));
276 vl_compositor_set_dst_clip(&vmixer
->cstate
, RectToPipe(destination_rect
, &dst_clip
));
277 if (!vmixer
->noise_reduction
.filter
&& !vmixer
->sharpness
.filter
)
278 vlVdpSave4DelayedRendering(vmixer
->device
, destination_surface
, &vmixer
->cstate
);
280 vl_compositor_render(&vmixer
->cstate
, compositor
, dst
->surface
, &dst
->dirty_area
);
282 /* applying the noise reduction after scaling is actually not very
283 clever, but currently we should avoid to copy around the image
285 if (vmixer
->noise_reduction
.filter
)
286 vl_median_filter_render(vmixer
->noise_reduction
.filter
,
287 dst
->sampler_view
, dst
->surface
);
289 if (vmixer
->sharpness
.filter
)
290 vl_matrix_filter_render(vmixer
->sharpness
.filter
,
291 dst
->sampler_view
, dst
->surface
);
294 return VDP_STATUS_OK
;
298 * Update the noise reduction setting
301 vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer
*vmixer
)
305 /* if present remove the old filter first */
306 if (vmixer
->noise_reduction
.filter
) {
307 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
308 FREE(vmixer
->noise_reduction
.filter
);
309 vmixer
->noise_reduction
.filter
= NULL
;
312 /* and create a new filter as needed */
313 if (vmixer
->noise_reduction
. enabled
&& vmixer
->noise_reduction
.level
> 0) {
314 vmixer
->noise_reduction
.filter
= MALLOC(sizeof(struct vl_median_filter
));
315 vl_median_filter_init(vmixer
->noise_reduction
.filter
, vmixer
->device
->context
,
316 vmixer
->video_width
, vmixer
->video_height
,
317 vmixer
->noise_reduction
.level
+ 1,
318 VL_MEDIAN_FILTER_CROSS
);
323 vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer
*vmixer
)
327 /* if present remove the old filter first */
328 if (vmixer
->sharpness
.filter
) {
329 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
330 FREE(vmixer
->sharpness
.filter
);
331 vmixer
->sharpness
.filter
= NULL
;
334 /* and create a new filter as needed */
335 if (vmixer
->sharpness
.enabled
&& vmixer
->sharpness
.value
!= 0.0f
) {
339 if (vmixer
->sharpness
.value
> 0.0f
) {
340 matrix
[0] = -1.0f
; matrix
[1] = -1.0f
; matrix
[2] = -1.0f
;
341 matrix
[3] = -1.0f
; matrix
[4] = 8.0f
; matrix
[5] = -1.0f
;
342 matrix
[6] = -1.0f
; matrix
[7] = -1.0f
; matrix
[8] = -1.0f
;
344 for (i
= 0; i
< 9; ++i
)
345 matrix
[i
] *= vmixer
->sharpness
.value
;
350 matrix
[0] = 1.0f
; matrix
[1] = 2.0f
; matrix
[2] = 1.0f
;
351 matrix
[3] = 2.0f
; matrix
[4] = 4.0f
; matrix
[5] = 2.0f
;
352 matrix
[6] = 1.0f
; matrix
[7] = 2.0f
; matrix
[8] = 1.0f
;
354 for (i
= 0; i
< 9; ++i
)
355 matrix
[i
] *= fabsf(vmixer
->sharpness
.value
) / 16.0f
;
357 matrix
[4] += 1.0f
- fabsf(vmixer
->sharpness
.value
);
360 vmixer
->sharpness
.filter
= MALLOC(sizeof(struct vl_matrix_filter
));
361 vl_matrix_filter_init(vmixer
->sharpness
.filter
, vmixer
->device
->context
,
362 vmixer
->video_width
, vmixer
->video_height
,
368 * Retrieve whether features were requested at creation time.
371 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer
,
372 uint32_t feature_count
,
373 VdpVideoMixerFeature
const *features
,
374 VdpBool
*feature_supports
)
376 vlVdpVideoMixer
*vmixer
;
379 if (!(features
&& feature_supports
))
380 return VDP_STATUS_INVALID_POINTER
;
382 vmixer
= vlGetDataHTAB(mixer
);
384 return VDP_STATUS_INVALID_HANDLE
;
386 for (i
= 0; i
< feature_count
; ++i
) {
387 switch (features
[i
]) {
388 /* they are valid, but we doesn't support them */
389 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
390 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
391 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
392 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
393 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
394 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
395 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
396 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
397 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
398 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
399 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
400 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
401 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
402 feature_supports
[i
] = false;
405 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
406 feature_supports
[i
] = vmixer
->sharpness
.supported
;
409 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
410 feature_supports
[i
] = vmixer
->noise_reduction
.supported
;
414 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
418 return VDP_STATUS_OK
;
422 * Enable or disable features.
425 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer
,
426 uint32_t feature_count
,
427 VdpVideoMixerFeature
const *features
,
428 VdpBool
const *feature_enables
)
430 vlVdpVideoMixer
*vmixer
;
433 if (!(features
&& feature_enables
))
434 return VDP_STATUS_INVALID_POINTER
;
436 vmixer
= vlGetDataHTAB(mixer
);
438 return VDP_STATUS_INVALID_HANDLE
;
440 for (i
= 0; i
< feature_count
; ++i
) {
441 switch (features
[i
]) {
442 /* they are valid, but we doesn't support them */
443 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
444 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
445 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
446 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
447 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
448 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
449 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
450 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
451 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
452 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
453 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
454 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
455 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
458 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
459 vmixer
->sharpness
.enabled
= feature_enables
[i
];
460 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
463 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
464 vmixer
->noise_reduction
.enabled
= feature_enables
[i
];
465 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
469 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
473 return VDP_STATUS_OK
;
477 * Retrieve whether features are enabled.
480 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer
,
481 uint32_t feature_count
,
482 VdpVideoMixerFeature
const *features
,
483 VdpBool
*feature_enables
)
485 vlVdpVideoMixer
*vmixer
;
488 if (!(features
&& feature_enables
))
489 return VDP_STATUS_INVALID_POINTER
;
491 vmixer
= vlGetDataHTAB(mixer
);
493 return VDP_STATUS_INVALID_HANDLE
;
495 for (i
= 0; i
< feature_count
; ++i
) {
496 switch (features
[i
]) {
497 /* they are valid, but we doesn't support them */
498 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
499 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
500 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
501 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
502 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
503 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
504 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
505 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
506 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
507 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
508 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
509 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
510 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
513 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
514 feature_enables
[i
] = vmixer
->sharpness
.enabled
;
517 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
518 feature_enables
[i
] = vmixer
->noise_reduction
.enabled
;
522 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
526 return VDP_STATUS_OK
;
530 * Set attribute values.
533 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer
,
534 uint32_t attribute_count
,
535 VdpVideoMixerAttribute
const *attributes
,
536 void const *const *attribute_values
)
538 const VdpColor
*background_color
;
539 union pipe_color_union color
;
540 const float *vdp_csc
;
544 if (!(attributes
&& attribute_values
))
545 return VDP_STATUS_INVALID_POINTER
;
547 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
549 return VDP_STATUS_INVALID_HANDLE
;
551 for (i
= 0; i
< attribute_count
; ++i
) {
552 switch (attributes
[i
]) {
553 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
554 background_color
= attribute_values
[i
];
555 color
.f
[0] = background_color
->red
;
556 color
.f
[1] = background_color
->green
;
557 color
.f
[2] = background_color
->blue
;
558 color
.f
[3] = background_color
->alpha
;
559 vl_compositor_set_clear_color(&vmixer
->cstate
, &color
);
561 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
562 vdp_csc
= attribute_values
[i
];
563 vmixer
->custom_csc
= !!vdp_csc
;
565 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, 1, &vmixer
->csc
);
567 memcpy(vmixer
->csc
, vdp_csc
, sizeof(vl_csc_matrix
));
568 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
569 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
);
572 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
574 val
= *(float*)attribute_values
[i
];
575 if (val
< 0.f
|| val
> 1.f
)
576 return VDP_STATUS_INVALID_VALUE
;
578 vmixer
->noise_reduction
.level
= val
* 10;
579 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
582 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
583 val
= *(float*)attribute_values
[i
];
584 if (val
< 0.f
|| val
> 1.f
)
585 return VDP_STATUS_INVALID_VALUE
;
586 vmixer
->luma_key_min
= val
;
588 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
589 val
= *(float*)attribute_values
[i
];
590 if (val
< 0.f
|| val
> 1.f
)
591 return VDP_STATUS_INVALID_VALUE
;
592 vmixer
->luma_key_max
= val
;
595 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
597 val
= *(float*)attribute_values
[i
];
598 if (val
< -1.f
|| val
> 1.f
)
599 return VDP_STATUS_INVALID_VALUE
;
601 vmixer
->sharpness
.value
= val
;
602 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
605 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
606 if (*(uint8_t*)attribute_values
[i
] > 1)
607 return VDP_STATUS_INVALID_VALUE
;
608 vmixer
->skip_chroma_deint
= *(uint8_t*)attribute_values
[i
];
611 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
615 return VDP_STATUS_OK
;
619 * Retrieve parameter values given at creation time.
622 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer
,
623 uint32_t parameter_count
,
624 VdpVideoMixerParameter
const *parameters
,
625 void *const *parameter_values
)
627 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
630 return VDP_STATUS_INVALID_HANDLE
;
632 if (!parameter_count
)
633 return VDP_STATUS_OK
;
634 if (!(parameters
&& parameter_values
))
635 return VDP_STATUS_INVALID_POINTER
;
636 for (i
= 0; i
< parameter_count
; ++i
) {
637 switch (parameters
[i
]) {
638 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
639 *(uint32_t*)parameter_values
[i
] = vmixer
->video_width
;
641 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
642 *(uint32_t*)parameter_values
[i
] = vmixer
->video_height
;
644 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
645 *(VdpChromaType
*)parameter_values
[i
] = PipeToChroma(vmixer
->chroma_format
);
647 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
648 *(uint32_t*)parameter_values
[i
] = vmixer
->max_layers
;
651 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
654 return VDP_STATUS_OK
;
658 * Retrieve current attribute values.
661 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer
,
662 uint32_t attribute_count
,
663 VdpVideoMixerAttribute
const *attributes
,
664 void *const *attribute_values
)
667 VdpCSCMatrix
**vdp_csc
;
669 if (!(attributes
&& attribute_values
))
670 return VDP_STATUS_INVALID_POINTER
;
672 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
674 return VDP_STATUS_INVALID_HANDLE
;
676 for (i
= 0; i
< attribute_count
; ++i
) {
677 switch (attributes
[i
]) {
678 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
679 vl_compositor_get_clear_color(&vmixer
->cstate
, attribute_values
[i
]);
681 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
682 vdp_csc
= attribute_values
[i
];
683 if (!vmixer
->custom_csc
) {
687 memcpy(*vdp_csc
, vmixer
->csc
, sizeof(float)*12);
690 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
691 *(float*)attribute_values
[i
] = (float)vmixer
->noise_reduction
.level
/ 10.0f
;
694 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
695 *(float*)attribute_values
[i
] = vmixer
->luma_key_min
;
697 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
698 *(float*)attribute_values
[i
] = vmixer
->luma_key_max
;
700 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
701 *(float*)attribute_values
[i
] = vmixer
->sharpness
.value
;
703 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
704 *(uint8_t*)attribute_values
[i
] = vmixer
->skip_chroma_deint
;
707 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
710 return VDP_STATUS_OK
;
714 * Generate a color space conversion matrix.
717 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
718 VdpColorStandard standard
,
719 VdpCSCMatrix
*csc_matrix
)
721 enum VL_CSC_COLOR_STANDARD vl_std
;
722 struct vl_procamp camp
;
724 if (!(csc_matrix
&& procamp
))
725 return VDP_STATUS_INVALID_POINTER
;
727 if (procamp
->struct_version
> VDP_PROCAMP_VERSION
)
728 return VDP_STATUS_INVALID_STRUCT_VERSION
;
731 case VDP_COLOR_STANDARD_ITUR_BT_601
: vl_std
= VL_CSC_COLOR_STANDARD_BT_601
; break;
732 case VDP_COLOR_STANDARD_ITUR_BT_709
: vl_std
= VL_CSC_COLOR_STANDARD_BT_709
; break;
733 case VDP_COLOR_STANDARD_SMPTE_240M
: vl_std
= VL_CSC_COLOR_STANDARD_SMPTE_240M
; break;
734 default: return VDP_STATUS_INVALID_COLOR_STANDARD
;
736 camp
.brightness
= procamp
->brightness
;
737 camp
.contrast
= procamp
->contrast
;
738 camp
.saturation
= procamp
->saturation
;
739 camp
.hue
= procamp
->hue
;
740 vl_csc_get_matrix(vl_std
, &camp
, true, csc_matrix
);
741 return VDP_STATUS_OK
;