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
;
66 pipe_mutex_lock(dev
->mutex
);
68 vl_compositor_init_state(&vmixer
->cstate
, dev
->context
);
70 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, true, &vmixer
->csc
);
71 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
72 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
);
74 *mixer
= vlAddDataHTAB(vmixer
);
76 ret
= VDP_STATUS_ERROR
;
80 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
81 for (i
= 0; i
< feature_count
; ++i
) {
82 switch (features
[i
]) {
83 /* they are valid, but we doesn't support them */
84 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
85 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
86 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
87 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
88 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
89 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
90 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
91 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
92 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
93 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
94 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
95 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
96 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
99 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
100 vmixer
->sharpness
.supported
= true;
103 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
104 vmixer
->noise_reduction
.supported
= true;
107 default: goto no_params
;
111 vmixer
->chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
112 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
113 for (i
= 0; i
< parameter_count
; ++i
) {
114 switch (parameters
[i
]) {
115 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
116 vmixer
->video_width
= *(uint32_t*)parameter_values
[i
];
118 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
119 vmixer
->video_height
= *(uint32_t*)parameter_values
[i
];
121 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
122 vmixer
->chroma_format
= ChromaToPipe(*(VdpChromaType
*)parameter_values
[i
]);
124 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
125 vmixer
->max_layers
= *(uint32_t*)parameter_values
[i
];
127 default: goto no_params
;
130 ret
= VDP_STATUS_INVALID_VALUE
;
131 if (vmixer
->max_layers
> 4) {
132 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] Max layers > 4 not supported\n", vmixer
->max_layers
);
135 max_width
= screen
->get_video_param(screen
, prof
, PIPE_VIDEO_CAP_MAX_WIDTH
);
136 max_height
= screen
->get_video_param(screen
, prof
, PIPE_VIDEO_CAP_MAX_HEIGHT
);
137 if (vmixer
->video_width
< 48 ||
138 vmixer
->video_width
> max_width
) {
139 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer
->video_width
, max_width
);
142 if (vmixer
->video_height
< 48 ||
143 vmixer
->video_height
> max_height
) {
144 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer
->video_height
, max_height
);
147 vmixer
->luma_key_min
= 0.f
;
148 vmixer
->luma_key_max
= 1.f
;
149 pipe_mutex_unlock(dev
->mutex
);
151 return VDP_STATUS_OK
;
154 vlRemoveDataHTAB(*mixer
);
157 vl_compositor_cleanup_state(&vmixer
->cstate
);
158 pipe_mutex_unlock(dev
->mutex
);
164 * Destroy a VdpVideoMixer.
167 vlVdpVideoMixerDestroy(VdpVideoMixer mixer
)
169 vlVdpVideoMixer
*vmixer
;
171 vmixer
= vlGetDataHTAB(mixer
);
173 return VDP_STATUS_INVALID_HANDLE
;
175 pipe_mutex_lock(vmixer
->device
->mutex
);
177 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
179 vlRemoveDataHTAB(mixer
);
181 vl_compositor_cleanup_state(&vmixer
->cstate
);
183 if (vmixer
->noise_reduction
.filter
) {
184 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
185 FREE(vmixer
->noise_reduction
.filter
);
188 if (vmixer
->sharpness
.filter
) {
189 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
190 FREE(vmixer
->sharpness
.filter
);
192 pipe_mutex_unlock(vmixer
->device
->mutex
);
196 return VDP_STATUS_OK
;
200 * Perform a video post-processing and compositing operation.
202 VdpStatus
vlVdpVideoMixerRender(VdpVideoMixer mixer
,
203 VdpOutputSurface background_surface
,
204 VdpRect
const *background_source_rect
,
205 VdpVideoMixerPictureStructure current_picture_structure
,
206 uint32_t video_surface_past_count
,
207 VdpVideoSurface
const *video_surface_past
,
208 VdpVideoSurface video_surface_current
,
209 uint32_t video_surface_future_count
,
210 VdpVideoSurface
const *video_surface_future
,
211 VdpRect
const *video_source_rect
,
212 VdpOutputSurface destination_surface
,
213 VdpRect
const *destination_rect
,
214 VdpRect
const *destination_video_rect
,
215 uint32_t layer_count
,
216 VdpLayer
const *layers
)
218 enum vl_compositor_deinterlace deinterlace
;
219 struct u_rect rect
, clip
;
220 unsigned i
, layer
= 0;
222 vlVdpVideoMixer
*vmixer
;
224 vlVdpOutputSurface
*dst
;
226 struct vl_compositor
*compositor
;
228 vmixer
= vlGetDataHTAB(mixer
);
230 return VDP_STATUS_INVALID_HANDLE
;
232 compositor
= &vmixer
->device
->compositor
;
234 surf
= vlGetDataHTAB(video_surface_current
);
236 return VDP_STATUS_INVALID_HANDLE
;
238 if (surf
->device
!= vmixer
->device
)
239 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
241 if (vmixer
->video_width
> surf
->video_buffer
->width
||
242 vmixer
->video_height
> surf
->video_buffer
->height
||
243 vmixer
->chroma_format
!= surf
->video_buffer
->chroma_format
)
244 return VDP_STATUS_INVALID_SIZE
;
246 if (layer_count
> vmixer
->max_layers
)
247 return VDP_STATUS_INVALID_VALUE
;
249 dst
= vlGetDataHTAB(destination_surface
);
251 return VDP_STATUS_INVALID_HANDLE
;
253 pipe_mutex_lock(vmixer
->device
->mutex
);
254 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
255 if (background_surface
!= VDP_INVALID_HANDLE
) {
256 vlVdpOutputSurface
*bg
= vlGetDataHTAB(background_surface
);
258 pipe_mutex_unlock(vmixer
->device
->mutex
);
259 return VDP_STATUS_INVALID_HANDLE
;
261 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
++, bg
->sampler_view
,
262 RectToPipe(background_source_rect
, &rect
), NULL
, NULL
);
265 vl_compositor_clear_layers(&vmixer
->cstate
);
267 switch (current_picture_structure
) {
268 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD
:
269 deinterlace
= VL_COMPOSITOR_BOB_TOP
;
272 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD
:
273 deinterlace
= VL_COMPOSITOR_BOB_BOTTOM
;
276 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
:
277 deinterlace
= VL_COMPOSITOR_WEAVE
;
281 pipe_mutex_unlock(vmixer
->device
->mutex
);
282 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE
;
284 vl_compositor_set_buffer_layer(&vmixer
->cstate
, compositor
, layer
, surf
->video_buffer
,
285 RectToPipe(video_source_rect
, &rect
), NULL
, deinterlace
);
286 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(destination_video_rect
, &rect
));
288 for (i
= 0; i
< layer_count
; ++i
) {
289 vlVdpOutputSurface
*src
= vlGetDataHTAB(layers
->source_surface
);
291 pipe_mutex_unlock(vmixer
->device
->mutex
);
292 return VDP_STATUS_INVALID_HANDLE
;
295 assert(layers
->struct_version
== VDP_LAYER_VERSION
);
297 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
, src
->sampler_view
,
298 RectToPipe(layers
->source_rect
, &rect
), NULL
, NULL
);
299 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(layers
->destination_rect
, &rect
));
304 vl_compositor_set_dst_clip(&vmixer
->cstate
, RectToPipe(destination_rect
, &clip
));
305 if (!vmixer
->noise_reduction
.filter
&& !vmixer
->sharpness
.filter
)
306 vlVdpSave4DelayedRendering(vmixer
->device
, destination_surface
, &vmixer
->cstate
);
308 vl_compositor_render(&vmixer
->cstate
, compositor
, dst
->surface
, &dst
->dirty_area
);
310 /* applying the noise reduction after scaling is actually not very
311 clever, but currently we should avoid to copy around the image
313 if (vmixer
->noise_reduction
.filter
)
314 vl_median_filter_render(vmixer
->noise_reduction
.filter
,
315 dst
->sampler_view
, dst
->surface
);
317 if (vmixer
->sharpness
.filter
)
318 vl_matrix_filter_render(vmixer
->sharpness
.filter
,
319 dst
->sampler_view
, dst
->surface
);
321 pipe_mutex_unlock(vmixer
->device
->mutex
);
323 return VDP_STATUS_OK
;
327 * Update the noise reduction setting
330 vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer
*vmixer
)
334 /* if present remove the old filter first */
335 if (vmixer
->noise_reduction
.filter
) {
336 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
337 FREE(vmixer
->noise_reduction
.filter
);
338 vmixer
->noise_reduction
.filter
= NULL
;
341 /* and create a new filter as needed */
342 if (vmixer
->noise_reduction
. enabled
&& vmixer
->noise_reduction
.level
> 0) {
343 vmixer
->noise_reduction
.filter
= MALLOC(sizeof(struct vl_median_filter
));
344 vl_median_filter_init(vmixer
->noise_reduction
.filter
, vmixer
->device
->context
,
345 vmixer
->video_width
, vmixer
->video_height
,
346 vmixer
->noise_reduction
.level
+ 1,
347 VL_MEDIAN_FILTER_CROSS
);
352 vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer
*vmixer
)
356 /* if present remove the old filter first */
357 if (vmixer
->sharpness
.filter
) {
358 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
359 FREE(vmixer
->sharpness
.filter
);
360 vmixer
->sharpness
.filter
= NULL
;
363 /* and create a new filter as needed */
364 if (vmixer
->sharpness
.enabled
&& vmixer
->sharpness
.value
!= 0.0f
) {
368 if (vmixer
->sharpness
.value
> 0.0f
) {
369 matrix
[0] = -1.0f
; matrix
[1] = -1.0f
; matrix
[2] = -1.0f
;
370 matrix
[3] = -1.0f
; matrix
[4] = 8.0f
; matrix
[5] = -1.0f
;
371 matrix
[6] = -1.0f
; matrix
[7] = -1.0f
; matrix
[8] = -1.0f
;
373 for (i
= 0; i
< 9; ++i
)
374 matrix
[i
] *= vmixer
->sharpness
.value
;
379 matrix
[0] = 1.0f
; matrix
[1] = 2.0f
; matrix
[2] = 1.0f
;
380 matrix
[3] = 2.0f
; matrix
[4] = 4.0f
; matrix
[5] = 2.0f
;
381 matrix
[6] = 1.0f
; matrix
[7] = 2.0f
; matrix
[8] = 1.0f
;
383 for (i
= 0; i
< 9; ++i
)
384 matrix
[i
] *= fabsf(vmixer
->sharpness
.value
) / 16.0f
;
386 matrix
[4] += 1.0f
- fabsf(vmixer
->sharpness
.value
);
389 vmixer
->sharpness
.filter
= MALLOC(sizeof(struct vl_matrix_filter
));
390 vl_matrix_filter_init(vmixer
->sharpness
.filter
, vmixer
->device
->context
,
391 vmixer
->video_width
, vmixer
->video_height
,
397 * Retrieve whether features were requested at creation time.
400 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer
,
401 uint32_t feature_count
,
402 VdpVideoMixerFeature
const *features
,
403 VdpBool
*feature_supports
)
405 vlVdpVideoMixer
*vmixer
;
408 if (!(features
&& feature_supports
))
409 return VDP_STATUS_INVALID_POINTER
;
411 vmixer
= vlGetDataHTAB(mixer
);
413 return VDP_STATUS_INVALID_HANDLE
;
415 for (i
= 0; i
< feature_count
; ++i
) {
416 switch (features
[i
]) {
417 /* they are valid, but we doesn't support them */
418 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
419 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
420 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
421 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
422 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
423 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
424 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
425 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
426 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
427 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
428 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
429 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
430 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
431 feature_supports
[i
] = false;
434 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
435 feature_supports
[i
] = vmixer
->sharpness
.supported
;
438 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
439 feature_supports
[i
] = vmixer
->noise_reduction
.supported
;
443 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
447 return VDP_STATUS_OK
;
451 * Enable or disable features.
454 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer
,
455 uint32_t feature_count
,
456 VdpVideoMixerFeature
const *features
,
457 VdpBool
const *feature_enables
)
459 vlVdpVideoMixer
*vmixer
;
462 if (!(features
&& feature_enables
))
463 return VDP_STATUS_INVALID_POINTER
;
465 vmixer
= vlGetDataHTAB(mixer
);
467 return VDP_STATUS_INVALID_HANDLE
;
469 pipe_mutex_lock(vmixer
->device
->mutex
);
470 for (i
= 0; i
< feature_count
; ++i
) {
471 switch (features
[i
]) {
472 /* they are valid, but we doesn't support them */
473 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
474 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
475 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
476 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
477 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
478 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
479 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
480 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
481 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
482 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
483 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
484 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
485 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
488 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
489 vmixer
->sharpness
.enabled
= feature_enables
[i
];
490 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
493 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
494 vmixer
->noise_reduction
.enabled
= feature_enables
[i
];
495 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
499 pipe_mutex_unlock(vmixer
->device
->mutex
);
500 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
503 pipe_mutex_unlock(vmixer
->device
->mutex
);
505 return VDP_STATUS_OK
;
509 * Retrieve whether features are enabled.
512 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer
,
513 uint32_t feature_count
,
514 VdpVideoMixerFeature
const *features
,
515 VdpBool
*feature_enables
)
517 vlVdpVideoMixer
*vmixer
;
520 if (!(features
&& feature_enables
))
521 return VDP_STATUS_INVALID_POINTER
;
523 vmixer
= vlGetDataHTAB(mixer
);
525 return VDP_STATUS_INVALID_HANDLE
;
527 for (i
= 0; i
< feature_count
; ++i
) {
528 switch (features
[i
]) {
529 /* they are valid, but we doesn't support them */
530 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
531 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
532 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
533 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
534 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
535 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
536 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
537 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
538 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
539 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
540 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
541 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
542 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
545 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
546 feature_enables
[i
] = vmixer
->sharpness
.enabled
;
549 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
550 feature_enables
[i
] = vmixer
->noise_reduction
.enabled
;
554 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
558 return VDP_STATUS_OK
;
562 * Set attribute values.
565 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer
,
566 uint32_t attribute_count
,
567 VdpVideoMixerAttribute
const *attributes
,
568 void const *const *attribute_values
)
570 const VdpColor
*background_color
;
571 union pipe_color_union color
;
572 const float *vdp_csc
;
576 if (!(attributes
&& attribute_values
))
577 return VDP_STATUS_INVALID_POINTER
;
579 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
581 return VDP_STATUS_INVALID_HANDLE
;
583 pipe_mutex_lock(vmixer
->device
->mutex
);
584 for (i
= 0; i
< attribute_count
; ++i
) {
585 switch (attributes
[i
]) {
586 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
587 background_color
= attribute_values
[i
];
588 color
.f
[0] = background_color
->red
;
589 color
.f
[1] = background_color
->green
;
590 color
.f
[2] = background_color
->blue
;
591 color
.f
[3] = background_color
->alpha
;
592 vl_compositor_set_clear_color(&vmixer
->cstate
, &color
);
594 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
595 vdp_csc
= attribute_values
[i
];
596 vmixer
->custom_csc
= !!vdp_csc
;
598 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, 1, &vmixer
->csc
);
600 memcpy(vmixer
->csc
, vdp_csc
, sizeof(vl_csc_matrix
));
601 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
602 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
);
605 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
607 val
= *(float*)attribute_values
[i
];
608 if (val
< 0.f
|| val
> 1.f
)
609 return VDP_STATUS_INVALID_VALUE
;
611 vmixer
->noise_reduction
.level
= val
* 10;
612 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
615 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
616 val
= *(float*)attribute_values
[i
];
617 if (val
< 0.f
|| val
> 1.f
)
618 return VDP_STATUS_INVALID_VALUE
;
619 vmixer
->luma_key_min
= val
;
621 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
622 val
= *(float*)attribute_values
[i
];
623 if (val
< 0.f
|| val
> 1.f
)
624 return VDP_STATUS_INVALID_VALUE
;
625 vmixer
->luma_key_max
= val
;
628 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
630 val
= *(float*)attribute_values
[i
];
631 if (val
< -1.f
|| val
> 1.f
)
632 return VDP_STATUS_INVALID_VALUE
;
634 vmixer
->sharpness
.value
= val
;
635 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
638 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
639 if (*(uint8_t*)attribute_values
[i
] > 1)
640 return VDP_STATUS_INVALID_VALUE
;
641 vmixer
->skip_chroma_deint
= *(uint8_t*)attribute_values
[i
];
644 pipe_mutex_unlock(vmixer
->device
->mutex
);
645 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
648 pipe_mutex_unlock(vmixer
->device
->mutex
);
650 return VDP_STATUS_OK
;
654 * Retrieve parameter values given at creation time.
657 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer
,
658 uint32_t parameter_count
,
659 VdpVideoMixerParameter
const *parameters
,
660 void *const *parameter_values
)
662 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
665 return VDP_STATUS_INVALID_HANDLE
;
667 if (!parameter_count
)
668 return VDP_STATUS_OK
;
669 if (!(parameters
&& parameter_values
))
670 return VDP_STATUS_INVALID_POINTER
;
671 for (i
= 0; i
< parameter_count
; ++i
) {
672 switch (parameters
[i
]) {
673 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
674 *(uint32_t*)parameter_values
[i
] = vmixer
->video_width
;
676 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
677 *(uint32_t*)parameter_values
[i
] = vmixer
->video_height
;
679 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
680 *(VdpChromaType
*)parameter_values
[i
] = PipeToChroma(vmixer
->chroma_format
);
682 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
683 *(uint32_t*)parameter_values
[i
] = vmixer
->max_layers
;
686 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
689 return VDP_STATUS_OK
;
693 * Retrieve current attribute values.
696 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer
,
697 uint32_t attribute_count
,
698 VdpVideoMixerAttribute
const *attributes
,
699 void *const *attribute_values
)
702 VdpCSCMatrix
**vdp_csc
;
704 if (!(attributes
&& attribute_values
))
705 return VDP_STATUS_INVALID_POINTER
;
707 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
709 return VDP_STATUS_INVALID_HANDLE
;
711 pipe_mutex_lock(vmixer
->device
->mutex
);
712 for (i
= 0; i
< attribute_count
; ++i
) {
713 switch (attributes
[i
]) {
714 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
715 vl_compositor_get_clear_color(&vmixer
->cstate
, attribute_values
[i
]);
717 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
718 vdp_csc
= attribute_values
[i
];
719 if (!vmixer
->custom_csc
) {
723 memcpy(*vdp_csc
, vmixer
->csc
, sizeof(float)*12);
726 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
727 *(float*)attribute_values
[i
] = (float)vmixer
->noise_reduction
.level
/ 10.0f
;
730 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
731 *(float*)attribute_values
[i
] = vmixer
->luma_key_min
;
733 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
734 *(float*)attribute_values
[i
] = vmixer
->luma_key_max
;
736 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
737 *(float*)attribute_values
[i
] = vmixer
->sharpness
.value
;
739 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
740 *(uint8_t*)attribute_values
[i
] = vmixer
->skip_chroma_deint
;
743 pipe_mutex_unlock(vmixer
->device
->mutex
);
744 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
747 pipe_mutex_unlock(vmixer
->device
->mutex
);
748 return VDP_STATUS_OK
;
752 * Generate a color space conversion matrix.
755 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
756 VdpColorStandard standard
,
757 VdpCSCMatrix
*csc_matrix
)
759 enum VL_CSC_COLOR_STANDARD vl_std
;
760 struct vl_procamp camp
;
762 if (!(csc_matrix
&& procamp
))
763 return VDP_STATUS_INVALID_POINTER
;
765 if (procamp
->struct_version
> VDP_PROCAMP_VERSION
)
766 return VDP_STATUS_INVALID_STRUCT_VERSION
;
769 case VDP_COLOR_STANDARD_ITUR_BT_601
: vl_std
= VL_CSC_COLOR_STANDARD_BT_601
; break;
770 case VDP_COLOR_STANDARD_ITUR_BT_709
: vl_std
= VL_CSC_COLOR_STANDARD_BT_709
; break;
771 case VDP_COLOR_STANDARD_SMPTE_240M
: vl_std
= VL_CSC_COLOR_STANDARD_SMPTE_240M
; break;
772 default: return VDP_STATUS_INVALID_COLOR_STANDARD
;
774 camp
.brightness
= procamp
->brightness
;
775 camp
.contrast
= procamp
->contrast
;
776 camp
.saturation
= procamp
->saturation
;
777 camp
.hue
= procamp
->hue
;
778 vl_csc_get_matrix(vl_std
, &camp
, true, csc_matrix
);
779 return VDP_STATUS_OK
;