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 VMWARE 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
;
54 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
56 return VDP_STATUS_INVALID_HANDLE
;
57 screen
= dev
->vscreen
->pscreen
;
59 vmixer
= CALLOC(1, sizeof(vlVdpVideoMixer
));
61 return VDP_STATUS_RESOURCES
;
65 pipe_mutex_lock(dev
->mutex
);
67 vl_compositor_init_state(&vmixer
->cstate
, dev
->context
);
69 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, true, &vmixer
->csc
);
70 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
71 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
);
73 *mixer
= vlAddDataHTAB(vmixer
);
75 ret
= VDP_STATUS_ERROR
;
79 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
80 for (i
= 0; i
< feature_count
; ++i
) {
81 switch (features
[i
]) {
82 /* they are valid, but we doesn't support them */
83 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
84 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
85 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
86 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
87 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
88 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
89 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
90 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
91 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
92 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
93 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
94 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
95 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
98 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
99 vmixer
->sharpness
.supported
= true;
102 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
103 vmixer
->noise_reduction
.supported
= true;
106 default: goto no_params
;
110 vmixer
->chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
111 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
112 for (i
= 0; i
< parameter_count
; ++i
) {
113 switch (parameters
[i
]) {
114 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
115 vmixer
->video_width
= *(uint32_t*)parameter_values
[i
];
117 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
118 vmixer
->video_height
= *(uint32_t*)parameter_values
[i
];
120 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
121 vmixer
->chroma_format
= ChromaToPipe(*(VdpChromaType
*)parameter_values
[i
]);
123 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
124 vmixer
->max_layers
= *(uint32_t*)parameter_values
[i
];
126 default: goto no_params
;
129 ret
= VDP_STATUS_INVALID_VALUE
;
130 if (vmixer
->max_layers
> 4) {
131 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] Max layers > 4 not supported\n", vmixer
->max_layers
);
134 max_width
= screen
->get_video_param(screen
, PIPE_VIDEO_PROFILE_UNKNOWN
,
135 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
, PIPE_VIDEO_CAP_MAX_WIDTH
);
136 max_height
= screen
->get_video_param(screen
, PIPE_VIDEO_PROFILE_UNKNOWN
,
137 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
, PIPE_VIDEO_CAP_MAX_HEIGHT
);
138 if (vmixer
->video_width
< 48 ||
139 vmixer
->video_width
> max_width
) {
140 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer
->video_width
, max_width
);
143 if (vmixer
->video_height
< 48 ||
144 vmixer
->video_height
> max_height
) {
145 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer
->video_height
, max_height
);
148 vmixer
->luma_key_min
= 0.f
;
149 vmixer
->luma_key_max
= 1.f
;
150 pipe_mutex_unlock(dev
->mutex
);
152 return VDP_STATUS_OK
;
155 vlRemoveDataHTAB(*mixer
);
158 vl_compositor_cleanup_state(&vmixer
->cstate
);
159 pipe_mutex_unlock(dev
->mutex
);
165 * Destroy a VdpVideoMixer.
168 vlVdpVideoMixerDestroy(VdpVideoMixer mixer
)
170 vlVdpVideoMixer
*vmixer
;
172 vmixer
= vlGetDataHTAB(mixer
);
174 return VDP_STATUS_INVALID_HANDLE
;
176 pipe_mutex_lock(vmixer
->device
->mutex
);
178 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
180 vlRemoveDataHTAB(mixer
);
182 vl_compositor_cleanup_state(&vmixer
->cstate
);
184 if (vmixer
->noise_reduction
.filter
) {
185 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
186 FREE(vmixer
->noise_reduction
.filter
);
189 if (vmixer
->sharpness
.filter
) {
190 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
191 FREE(vmixer
->sharpness
.filter
);
193 pipe_mutex_unlock(vmixer
->device
->mutex
);
197 return VDP_STATUS_OK
;
201 * Perform a video post-processing and compositing operation.
203 VdpStatus
vlVdpVideoMixerRender(VdpVideoMixer mixer
,
204 VdpOutputSurface background_surface
,
205 VdpRect
const *background_source_rect
,
206 VdpVideoMixerPictureStructure current_picture_structure
,
207 uint32_t video_surface_past_count
,
208 VdpVideoSurface
const *video_surface_past
,
209 VdpVideoSurface video_surface_current
,
210 uint32_t video_surface_future_count
,
211 VdpVideoSurface
const *video_surface_future
,
212 VdpRect
const *video_source_rect
,
213 VdpOutputSurface destination_surface
,
214 VdpRect
const *destination_rect
,
215 VdpRect
const *destination_video_rect
,
216 uint32_t layer_count
,
217 VdpLayer
const *layers
)
219 enum vl_compositor_deinterlace deinterlace
;
220 struct u_rect rect
, clip
, *prect
;
221 unsigned i
, layer
= 0;
223 vlVdpVideoMixer
*vmixer
;
225 vlVdpOutputSurface
*dst
, *bg
= NULL
;
227 struct vl_compositor
*compositor
;
229 vmixer
= vlGetDataHTAB(mixer
);
231 return VDP_STATUS_INVALID_HANDLE
;
233 compositor
= &vmixer
->device
->compositor
;
235 surf
= vlGetDataHTAB(video_surface_current
);
237 return VDP_STATUS_INVALID_HANDLE
;
239 if (surf
->device
!= vmixer
->device
)
240 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
242 if (vmixer
->video_width
> surf
->video_buffer
->width
||
243 vmixer
->video_height
> surf
->video_buffer
->height
||
244 vmixer
->chroma_format
!= surf
->video_buffer
->chroma_format
)
245 return VDP_STATUS_INVALID_SIZE
;
247 if (layer_count
> vmixer
->max_layers
)
248 return VDP_STATUS_INVALID_VALUE
;
250 dst
= vlGetDataHTAB(destination_surface
);
252 return VDP_STATUS_INVALID_HANDLE
;
254 if (background_surface
!= VDP_INVALID_HANDLE
) {
255 bg
= vlGetDataHTAB(background_surface
);
257 return VDP_STATUS_INVALID_HANDLE
;
260 pipe_mutex_lock(vmixer
->device
->mutex
);
261 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
263 vl_compositor_clear_layers(&vmixer
->cstate
);
266 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
++, bg
->sampler_view
,
267 RectToPipe(background_source_rect
, &rect
), NULL
, NULL
);
269 switch (current_picture_structure
) {
270 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD
:
271 deinterlace
= VL_COMPOSITOR_BOB_TOP
;
274 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD
:
275 deinterlace
= VL_COMPOSITOR_BOB_BOTTOM
;
278 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
:
279 deinterlace
= VL_COMPOSITOR_WEAVE
;
283 pipe_mutex_unlock(vmixer
->device
->mutex
);
284 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE
;
286 prect
= RectToPipe(video_source_rect
, &rect
);
290 rect
.x1
= surf
->templat
.width
;
291 rect
.y1
= surf
->templat
.height
;
294 vl_compositor_set_buffer_layer(&vmixer
->cstate
, compositor
, layer
, surf
->video_buffer
, prect
, NULL
, deinterlace
);
295 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(destination_video_rect
, &rect
));
297 for (i
= 0; i
< layer_count
; ++i
) {
298 vlVdpOutputSurface
*src
= vlGetDataHTAB(layers
->source_surface
);
300 pipe_mutex_unlock(vmixer
->device
->mutex
);
301 return VDP_STATUS_INVALID_HANDLE
;
304 assert(layers
->struct_version
== VDP_LAYER_VERSION
);
306 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
, src
->sampler_view
,
307 RectToPipe(layers
->source_rect
, &rect
), NULL
, NULL
);
308 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(layers
->destination_rect
, &rect
));
313 vl_compositor_set_dst_clip(&vmixer
->cstate
, RectToPipe(destination_rect
, &clip
));
314 if (!vmixer
->noise_reduction
.filter
&& !vmixer
->sharpness
.filter
)
315 vlVdpSave4DelayedRendering(vmixer
->device
, destination_surface
, &vmixer
->cstate
);
317 vl_compositor_render(&vmixer
->cstate
, compositor
, dst
->surface
, &dst
->dirty_area
, true);
319 /* applying the noise reduction after scaling is actually not very
320 clever, but currently we should avoid to copy around the image
322 if (vmixer
->noise_reduction
.filter
)
323 vl_median_filter_render(vmixer
->noise_reduction
.filter
,
324 dst
->sampler_view
, dst
->surface
);
326 if (vmixer
->sharpness
.filter
)
327 vl_matrix_filter_render(vmixer
->sharpness
.filter
,
328 dst
->sampler_view
, dst
->surface
);
330 pipe_mutex_unlock(vmixer
->device
->mutex
);
332 return VDP_STATUS_OK
;
336 * Update the noise reduction setting
339 vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer
*vmixer
)
343 /* if present remove the old filter first */
344 if (vmixer
->noise_reduction
.filter
) {
345 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
346 FREE(vmixer
->noise_reduction
.filter
);
347 vmixer
->noise_reduction
.filter
= NULL
;
350 /* and create a new filter as needed */
351 if (vmixer
->noise_reduction
. enabled
&& vmixer
->noise_reduction
.level
> 0) {
352 vmixer
->noise_reduction
.filter
= MALLOC(sizeof(struct vl_median_filter
));
353 vl_median_filter_init(vmixer
->noise_reduction
.filter
, vmixer
->device
->context
,
354 vmixer
->video_width
, vmixer
->video_height
,
355 vmixer
->noise_reduction
.level
+ 1,
356 VL_MEDIAN_FILTER_CROSS
);
361 vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer
*vmixer
)
365 /* if present remove the old filter first */
366 if (vmixer
->sharpness
.filter
) {
367 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
368 FREE(vmixer
->sharpness
.filter
);
369 vmixer
->sharpness
.filter
= NULL
;
372 /* and create a new filter as needed */
373 if (vmixer
->sharpness
.enabled
&& vmixer
->sharpness
.value
!= 0.0f
) {
377 if (vmixer
->sharpness
.value
> 0.0f
) {
378 matrix
[0] = -1.0f
; matrix
[1] = -1.0f
; matrix
[2] = -1.0f
;
379 matrix
[3] = -1.0f
; matrix
[4] = 8.0f
; matrix
[5] = -1.0f
;
380 matrix
[6] = -1.0f
; matrix
[7] = -1.0f
; matrix
[8] = -1.0f
;
382 for (i
= 0; i
< 9; ++i
)
383 matrix
[i
] *= vmixer
->sharpness
.value
;
388 matrix
[0] = 1.0f
; matrix
[1] = 2.0f
; matrix
[2] = 1.0f
;
389 matrix
[3] = 2.0f
; matrix
[4] = 4.0f
; matrix
[5] = 2.0f
;
390 matrix
[6] = 1.0f
; matrix
[7] = 2.0f
; matrix
[8] = 1.0f
;
392 for (i
= 0; i
< 9; ++i
)
393 matrix
[i
] *= fabsf(vmixer
->sharpness
.value
) / 16.0f
;
395 matrix
[4] += 1.0f
- fabsf(vmixer
->sharpness
.value
);
398 vmixer
->sharpness
.filter
= MALLOC(sizeof(struct vl_matrix_filter
));
399 vl_matrix_filter_init(vmixer
->sharpness
.filter
, vmixer
->device
->context
,
400 vmixer
->video_width
, vmixer
->video_height
,
406 * Retrieve whether features were requested at creation time.
409 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer
,
410 uint32_t feature_count
,
411 VdpVideoMixerFeature
const *features
,
412 VdpBool
*feature_supports
)
414 vlVdpVideoMixer
*vmixer
;
417 if (!(features
&& feature_supports
))
418 return VDP_STATUS_INVALID_POINTER
;
420 vmixer
= vlGetDataHTAB(mixer
);
422 return VDP_STATUS_INVALID_HANDLE
;
424 for (i
= 0; i
< feature_count
; ++i
) {
425 switch (features
[i
]) {
426 /* they are valid, but we doesn't support them */
427 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
428 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
429 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
430 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
431 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
432 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
433 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
434 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
435 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
436 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
437 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
438 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
439 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
440 feature_supports
[i
] = false;
443 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
444 feature_supports
[i
] = vmixer
->sharpness
.supported
;
447 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
448 feature_supports
[i
] = vmixer
->noise_reduction
.supported
;
452 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
456 return VDP_STATUS_OK
;
460 * Enable or disable features.
463 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer
,
464 uint32_t feature_count
,
465 VdpVideoMixerFeature
const *features
,
466 VdpBool
const *feature_enables
)
468 vlVdpVideoMixer
*vmixer
;
471 if (!(features
&& feature_enables
))
472 return VDP_STATUS_INVALID_POINTER
;
474 vmixer
= vlGetDataHTAB(mixer
);
476 return VDP_STATUS_INVALID_HANDLE
;
478 pipe_mutex_lock(vmixer
->device
->mutex
);
479 for (i
= 0; i
< feature_count
; ++i
) {
480 switch (features
[i
]) {
481 /* they are valid, but we doesn't support them */
482 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
483 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
484 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
485 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
486 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
487 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
488 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
489 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
490 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
491 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
492 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
493 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
494 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
497 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
498 vmixer
->sharpness
.enabled
= feature_enables
[i
];
499 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
502 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
503 vmixer
->noise_reduction
.enabled
= feature_enables
[i
];
504 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
508 pipe_mutex_unlock(vmixer
->device
->mutex
);
509 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
512 pipe_mutex_unlock(vmixer
->device
->mutex
);
514 return VDP_STATUS_OK
;
518 * Retrieve whether features are enabled.
521 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer
,
522 uint32_t feature_count
,
523 VdpVideoMixerFeature
const *features
,
524 VdpBool
*feature_enables
)
526 vlVdpVideoMixer
*vmixer
;
529 if (!(features
&& feature_enables
))
530 return VDP_STATUS_INVALID_POINTER
;
532 vmixer
= vlGetDataHTAB(mixer
);
534 return VDP_STATUS_INVALID_HANDLE
;
536 for (i
= 0; i
< feature_count
; ++i
) {
537 switch (features
[i
]) {
538 /* they are valid, but we doesn't support them */
539 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
540 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
541 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
542 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
543 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
544 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
545 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
546 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
547 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
548 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
549 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
550 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
551 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
554 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
555 feature_enables
[i
] = vmixer
->sharpness
.enabled
;
558 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
559 feature_enables
[i
] = vmixer
->noise_reduction
.enabled
;
563 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
567 return VDP_STATUS_OK
;
571 * Set attribute values.
574 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer
,
575 uint32_t attribute_count
,
576 VdpVideoMixerAttribute
const *attributes
,
577 void const *const *attribute_values
)
579 const VdpColor
*background_color
;
580 union pipe_color_union color
;
581 const float *vdp_csc
;
585 if (!(attributes
&& attribute_values
))
586 return VDP_STATUS_INVALID_POINTER
;
588 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
590 return VDP_STATUS_INVALID_HANDLE
;
592 pipe_mutex_lock(vmixer
->device
->mutex
);
593 for (i
= 0; i
< attribute_count
; ++i
) {
594 switch (attributes
[i
]) {
595 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
596 background_color
= attribute_values
[i
];
597 color
.f
[0] = background_color
->red
;
598 color
.f
[1] = background_color
->green
;
599 color
.f
[2] = background_color
->blue
;
600 color
.f
[3] = background_color
->alpha
;
601 vl_compositor_set_clear_color(&vmixer
->cstate
, &color
);
603 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
604 vdp_csc
= attribute_values
[i
];
605 vmixer
->custom_csc
= !!vdp_csc
;
607 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, 1, &vmixer
->csc
);
609 memcpy(vmixer
->csc
, vdp_csc
, sizeof(vl_csc_matrix
));
610 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
611 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
);
614 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
616 val
= *(float*)attribute_values
[i
];
617 if (val
< 0.f
|| val
> 1.f
)
618 return VDP_STATUS_INVALID_VALUE
;
620 vmixer
->noise_reduction
.level
= val
* 10;
621 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
624 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
625 val
= *(float*)attribute_values
[i
];
626 if (val
< 0.f
|| val
> 1.f
)
627 return VDP_STATUS_INVALID_VALUE
;
628 vmixer
->luma_key_min
= val
;
630 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
631 val
= *(float*)attribute_values
[i
];
632 if (val
< 0.f
|| val
> 1.f
)
633 return VDP_STATUS_INVALID_VALUE
;
634 vmixer
->luma_key_max
= val
;
637 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
639 val
= *(float*)attribute_values
[i
];
640 if (val
< -1.f
|| val
> 1.f
)
641 return VDP_STATUS_INVALID_VALUE
;
643 vmixer
->sharpness
.value
= val
;
644 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
647 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
648 if (*(uint8_t*)attribute_values
[i
] > 1)
649 return VDP_STATUS_INVALID_VALUE
;
650 vmixer
->skip_chroma_deint
= *(uint8_t*)attribute_values
[i
];
653 pipe_mutex_unlock(vmixer
->device
->mutex
);
654 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
657 pipe_mutex_unlock(vmixer
->device
->mutex
);
659 return VDP_STATUS_OK
;
663 * Retrieve parameter values given at creation time.
666 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer
,
667 uint32_t parameter_count
,
668 VdpVideoMixerParameter
const *parameters
,
669 void *const *parameter_values
)
671 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
674 return VDP_STATUS_INVALID_HANDLE
;
676 if (!parameter_count
)
677 return VDP_STATUS_OK
;
678 if (!(parameters
&& parameter_values
))
679 return VDP_STATUS_INVALID_POINTER
;
680 for (i
= 0; i
< parameter_count
; ++i
) {
681 switch (parameters
[i
]) {
682 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
683 *(uint32_t*)parameter_values
[i
] = vmixer
->video_width
;
685 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
686 *(uint32_t*)parameter_values
[i
] = vmixer
->video_height
;
688 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
689 *(VdpChromaType
*)parameter_values
[i
] = PipeToChroma(vmixer
->chroma_format
);
691 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
692 *(uint32_t*)parameter_values
[i
] = vmixer
->max_layers
;
695 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
698 return VDP_STATUS_OK
;
702 * Retrieve current attribute values.
705 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer
,
706 uint32_t attribute_count
,
707 VdpVideoMixerAttribute
const *attributes
,
708 void *const *attribute_values
)
711 VdpCSCMatrix
**vdp_csc
;
713 if (!(attributes
&& attribute_values
))
714 return VDP_STATUS_INVALID_POINTER
;
716 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
718 return VDP_STATUS_INVALID_HANDLE
;
720 pipe_mutex_lock(vmixer
->device
->mutex
);
721 for (i
= 0; i
< attribute_count
; ++i
) {
722 switch (attributes
[i
]) {
723 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
724 vl_compositor_get_clear_color(&vmixer
->cstate
, attribute_values
[i
]);
726 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
727 vdp_csc
= attribute_values
[i
];
728 if (!vmixer
->custom_csc
) {
732 memcpy(*vdp_csc
, vmixer
->csc
, sizeof(float)*12);
735 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
736 *(float*)attribute_values
[i
] = (float)vmixer
->noise_reduction
.level
/ 10.0f
;
739 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
740 *(float*)attribute_values
[i
] = vmixer
->luma_key_min
;
742 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
743 *(float*)attribute_values
[i
] = vmixer
->luma_key_max
;
745 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
746 *(float*)attribute_values
[i
] = vmixer
->sharpness
.value
;
748 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
749 *(uint8_t*)attribute_values
[i
] = vmixer
->skip_chroma_deint
;
752 pipe_mutex_unlock(vmixer
->device
->mutex
);
753 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
756 pipe_mutex_unlock(vmixer
->device
->mutex
);
757 return VDP_STATUS_OK
;
761 * Generate a color space conversion matrix.
764 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
765 VdpColorStandard standard
,
766 VdpCSCMatrix
*csc_matrix
)
768 enum VL_CSC_COLOR_STANDARD vl_std
;
769 struct vl_procamp camp
;
772 return VDP_STATUS_INVALID_POINTER
;
775 case VDP_COLOR_STANDARD_ITUR_BT_601
: vl_std
= VL_CSC_COLOR_STANDARD_BT_601
; break;
776 case VDP_COLOR_STANDARD_ITUR_BT_709
: vl_std
= VL_CSC_COLOR_STANDARD_BT_709
; break;
777 case VDP_COLOR_STANDARD_SMPTE_240M
: vl_std
= VL_CSC_COLOR_STANDARD_SMPTE_240M
; break;
778 default: return VDP_STATUS_INVALID_COLOR_STANDARD
;
782 if (procamp
->struct_version
> VDP_PROCAMP_VERSION
)
783 return VDP_STATUS_INVALID_STRUCT_VERSION
;
784 camp
.brightness
= procamp
->brightness
;
785 camp
.contrast
= procamp
->contrast
;
786 camp
.saturation
= procamp
->saturation
;
787 camp
.hue
= procamp
->hue
;
790 vl_csc_get_matrix(vl_std
, procamp
? &camp
: NULL
, true, csc_matrix
);
791 return VDP_STATUS_OK
;