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 uint32_t max_2d_texture_level
;
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
;
64 DeviceReference(&vmixer
->device
, dev
);
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
, 1.0f
, 0.0f
);
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_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
:
97 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
98 vmixer
->deint
.supported
= true;
101 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
102 vmixer
->sharpness
.supported
= true;
105 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
106 vmixer
->noise_reduction
.supported
= true;
109 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
110 vmixer
->luma_key
.supported
= true;
113 default: goto no_params
;
117 vmixer
->chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
118 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
119 for (i
= 0; i
< parameter_count
; ++i
) {
120 switch (parameters
[i
]) {
121 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
122 vmixer
->video_width
= *(uint32_t*)parameter_values
[i
];
124 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
125 vmixer
->video_height
= *(uint32_t*)parameter_values
[i
];
127 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
128 vmixer
->chroma_format
= ChromaToPipe(*(VdpChromaType
*)parameter_values
[i
]);
130 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
131 vmixer
->max_layers
= *(uint32_t*)parameter_values
[i
];
133 default: goto no_params
;
136 ret
= VDP_STATUS_INVALID_VALUE
;
137 if (vmixer
->max_layers
> 4) {
138 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] Max layers > 4 not supported\n", vmixer
->max_layers
);
142 max_2d_texture_level
= screen
->get_param(screen
, PIPE_CAP_MAX_TEXTURE_2D_LEVELS
);
143 max_size
= pow(2, max_2d_texture_level
-1);
144 if (vmixer
->video_width
< 48 || vmixer
->video_width
> max_size
) {
145 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for width\n",
146 vmixer
->video_width
, max_size
);
149 if (vmixer
->video_height
< 48 || vmixer
->video_height
> max_size
) {
150 VDPAU_MSG(VDPAU_WARN
, "[VDPAU] 48 < %u < %u not valid for height\n",
151 vmixer
->video_height
, max_size
);
154 vmixer
->luma_key
.luma_min
= 1.0f
;
155 vmixer
->luma_key
.luma_max
= 0.0f
;
156 pipe_mutex_unlock(dev
->mutex
);
158 return VDP_STATUS_OK
;
161 vlRemoveDataHTAB(*mixer
);
164 vl_compositor_cleanup_state(&vmixer
->cstate
);
165 pipe_mutex_unlock(dev
->mutex
);
166 DeviceReference(&vmixer
->device
, NULL
);
172 * Destroy a VdpVideoMixer.
175 vlVdpVideoMixerDestroy(VdpVideoMixer mixer
)
177 vlVdpVideoMixer
*vmixer
;
179 vmixer
= vlGetDataHTAB(mixer
);
181 return VDP_STATUS_INVALID_HANDLE
;
183 pipe_mutex_lock(vmixer
->device
->mutex
);
185 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
187 vlRemoveDataHTAB(mixer
);
189 vl_compositor_cleanup_state(&vmixer
->cstate
);
191 if (vmixer
->deint
.filter
) {
192 vl_deint_filter_cleanup(vmixer
->deint
.filter
);
193 FREE(vmixer
->deint
.filter
);
196 if (vmixer
->noise_reduction
.filter
) {
197 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
198 FREE(vmixer
->noise_reduction
.filter
);
201 if (vmixer
->sharpness
.filter
) {
202 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
203 FREE(vmixer
->sharpness
.filter
);
205 pipe_mutex_unlock(vmixer
->device
->mutex
);
206 DeviceReference(&vmixer
->device
, NULL
);
210 return VDP_STATUS_OK
;
214 * Perform a video post-processing and compositing operation.
216 VdpStatus
vlVdpVideoMixerRender(VdpVideoMixer mixer
,
217 VdpOutputSurface background_surface
,
218 VdpRect
const *background_source_rect
,
219 VdpVideoMixerPictureStructure current_picture_structure
,
220 uint32_t video_surface_past_count
,
221 VdpVideoSurface
const *video_surface_past
,
222 VdpVideoSurface video_surface_current
,
223 uint32_t video_surface_future_count
,
224 VdpVideoSurface
const *video_surface_future
,
225 VdpRect
const *video_source_rect
,
226 VdpOutputSurface destination_surface
,
227 VdpRect
const *destination_rect
,
228 VdpRect
const *destination_video_rect
,
229 uint32_t layer_count
,
230 VdpLayer
const *layers
)
232 enum vl_compositor_deinterlace deinterlace
;
233 struct u_rect rect
, clip
, *prect
;
234 unsigned i
, layer
= 0;
235 struct pipe_video_buffer
*video_buffer
;
237 vlVdpVideoMixer
*vmixer
;
239 vlVdpOutputSurface
*dst
, *bg
= NULL
;
241 struct vl_compositor
*compositor
;
243 vmixer
= vlGetDataHTAB(mixer
);
245 return VDP_STATUS_INVALID_HANDLE
;
247 compositor
= &vmixer
->device
->compositor
;
249 surf
= vlGetDataHTAB(video_surface_current
);
251 return VDP_STATUS_INVALID_HANDLE
;
252 video_buffer
= surf
->video_buffer
;
254 if (surf
->device
!= vmixer
->device
)
255 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
257 if (vmixer
->video_width
> video_buffer
->width
||
258 vmixer
->video_height
> video_buffer
->height
||
259 vmixer
->chroma_format
!= video_buffer
->chroma_format
)
260 return VDP_STATUS_INVALID_SIZE
;
262 if (layer_count
> vmixer
->max_layers
)
263 return VDP_STATUS_INVALID_VALUE
;
265 dst
= vlGetDataHTAB(destination_surface
);
267 return VDP_STATUS_INVALID_HANDLE
;
269 if (background_surface
!= VDP_INVALID_HANDLE
) {
270 bg
= vlGetDataHTAB(background_surface
);
272 return VDP_STATUS_INVALID_HANDLE
;
275 pipe_mutex_lock(vmixer
->device
->mutex
);
276 vlVdpResolveDelayedRendering(vmixer
->device
, NULL
, NULL
);
278 vl_compositor_clear_layers(&vmixer
->cstate
);
281 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
++, bg
->sampler_view
,
282 RectToPipe(background_source_rect
, &rect
), NULL
, NULL
);
284 switch (current_picture_structure
) {
285 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD
:
286 deinterlace
= VL_COMPOSITOR_BOB_TOP
;
289 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD
:
290 deinterlace
= VL_COMPOSITOR_BOB_BOTTOM
;
293 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
:
294 deinterlace
= VL_COMPOSITOR_WEAVE
;
298 pipe_mutex_unlock(vmixer
->device
->mutex
);
299 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE
;
302 if (deinterlace
!= VL_COMPOSITOR_WEAVE
&& vmixer
->deint
.enabled
&&
303 video_surface_past_count
> 1 && video_surface_future_count
> 0) {
304 vlVdpSurface
*prevprev
= vlGetDataHTAB(video_surface_past
[1]);
305 vlVdpSurface
*prev
= vlGetDataHTAB(video_surface_past
[0]);
306 vlVdpSurface
*next
= vlGetDataHTAB(video_surface_future
[0]);
307 if (prevprev
&& prev
&& next
&&
308 vl_deint_filter_check_buffers(vmixer
->deint
.filter
,
309 prevprev
->video_buffer
, prev
->video_buffer
, surf
->video_buffer
, next
->video_buffer
)) {
310 vl_deint_filter_render(vmixer
->deint
.filter
, prevprev
->video_buffer
,
311 prev
->video_buffer
, surf
->video_buffer
,
313 deinterlace
== VL_COMPOSITOR_BOB_BOTTOM
);
314 deinterlace
= VL_COMPOSITOR_WEAVE
;
315 video_buffer
= vmixer
->deint
.filter
->video_buffer
;
319 prect
= RectToPipe(video_source_rect
, &rect
);
323 rect
.x1
= surf
->templat
.width
;
324 rect
.y1
= surf
->templat
.height
;
327 vl_compositor_set_buffer_layer(&vmixer
->cstate
, compositor
, layer
, video_buffer
, prect
, NULL
, deinterlace
);
328 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(destination_video_rect
, &rect
));
330 for (i
= 0; i
< layer_count
; ++i
) {
331 vlVdpOutputSurface
*src
= vlGetDataHTAB(layers
->source_surface
);
333 pipe_mutex_unlock(vmixer
->device
->mutex
);
334 return VDP_STATUS_INVALID_HANDLE
;
337 assert(layers
->struct_version
== VDP_LAYER_VERSION
);
339 vl_compositor_set_rgba_layer(&vmixer
->cstate
, compositor
, layer
, src
->sampler_view
,
340 RectToPipe(layers
->source_rect
, &rect
), NULL
, NULL
);
341 vl_compositor_set_layer_dst_area(&vmixer
->cstate
, layer
++, RectToPipe(layers
->destination_rect
, &rect
));
346 vl_compositor_set_dst_clip(&vmixer
->cstate
, RectToPipe(destination_rect
, &clip
));
347 if (!vmixer
->noise_reduction
.filter
&& !vmixer
->sharpness
.filter
)
348 vlVdpSave4DelayedRendering(vmixer
->device
, destination_surface
, &vmixer
->cstate
);
350 vl_compositor_render(&vmixer
->cstate
, compositor
, dst
->surface
, &dst
->dirty_area
, true);
352 /* applying the noise reduction after scaling is actually not very
353 clever, but currently we should avoid to copy around the image
355 if (vmixer
->noise_reduction
.filter
)
356 vl_median_filter_render(vmixer
->noise_reduction
.filter
,
357 dst
->sampler_view
, dst
->surface
);
359 if (vmixer
->sharpness
.filter
)
360 vl_matrix_filter_render(vmixer
->sharpness
.filter
,
361 dst
->sampler_view
, dst
->surface
);
363 pipe_mutex_unlock(vmixer
->device
->mutex
);
365 return VDP_STATUS_OK
;
369 vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer
*vmixer
)
371 struct pipe_context
*pipe
= vmixer
->device
->context
;
374 /* remove existing filter */
375 if (vmixer
->deint
.filter
) {
376 vl_deint_filter_cleanup(vmixer
->deint
.filter
);
377 FREE(vmixer
->deint
.filter
);
378 vmixer
->deint
.filter
= NULL
;
381 /* create a new filter if requested */
382 if (vmixer
->deint
.enabled
&& vmixer
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
383 vmixer
->deint
.filter
= MALLOC(sizeof(struct vl_deint_filter
));
384 vmixer
->deint
.enabled
= vl_deint_filter_init(vmixer
->deint
.filter
, pipe
,
385 vmixer
->video_width
, vmixer
->video_height
,
386 vmixer
->skip_chroma_deint
, vmixer
->deint
.spatial
);
387 if (!vmixer
->deint
.enabled
) {
388 FREE(vmixer
->deint
.filter
);
394 * Update the noise reduction setting
397 vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer
*vmixer
)
401 /* if present remove the old filter first */
402 if (vmixer
->noise_reduction
.filter
) {
403 vl_median_filter_cleanup(vmixer
->noise_reduction
.filter
);
404 FREE(vmixer
->noise_reduction
.filter
);
405 vmixer
->noise_reduction
.filter
= NULL
;
408 /* and create a new filter as needed */
409 if (vmixer
->noise_reduction
. enabled
&& vmixer
->noise_reduction
.level
> 0) {
410 vmixer
->noise_reduction
.filter
= MALLOC(sizeof(struct vl_median_filter
));
411 vl_median_filter_init(vmixer
->noise_reduction
.filter
, vmixer
->device
->context
,
412 vmixer
->video_width
, vmixer
->video_height
,
413 vmixer
->noise_reduction
.level
+ 1,
414 VL_MEDIAN_FILTER_CROSS
);
419 vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer
*vmixer
)
423 /* if present remove the old filter first */
424 if (vmixer
->sharpness
.filter
) {
425 vl_matrix_filter_cleanup(vmixer
->sharpness
.filter
);
426 FREE(vmixer
->sharpness
.filter
);
427 vmixer
->sharpness
.filter
= NULL
;
430 /* and create a new filter as needed */
431 if (vmixer
->sharpness
.enabled
&& vmixer
->sharpness
.value
!= 0.0f
) {
435 if (vmixer
->sharpness
.value
> 0.0f
) {
436 matrix
[0] = -1.0f
; matrix
[1] = -1.0f
; matrix
[2] = -1.0f
;
437 matrix
[3] = -1.0f
; matrix
[4] = 8.0f
; matrix
[5] = -1.0f
;
438 matrix
[6] = -1.0f
; matrix
[7] = -1.0f
; matrix
[8] = -1.0f
;
440 for (i
= 0; i
< 9; ++i
)
441 matrix
[i
] *= vmixer
->sharpness
.value
;
446 matrix
[0] = 1.0f
; matrix
[1] = 2.0f
; matrix
[2] = 1.0f
;
447 matrix
[3] = 2.0f
; matrix
[4] = 4.0f
; matrix
[5] = 2.0f
;
448 matrix
[6] = 1.0f
; matrix
[7] = 2.0f
; matrix
[8] = 1.0f
;
450 for (i
= 0; i
< 9; ++i
)
451 matrix
[i
] *= fabsf(vmixer
->sharpness
.value
) / 16.0f
;
453 matrix
[4] += 1.0f
- fabsf(vmixer
->sharpness
.value
);
456 vmixer
->sharpness
.filter
= MALLOC(sizeof(struct vl_matrix_filter
));
457 vl_matrix_filter_init(vmixer
->sharpness
.filter
, vmixer
->device
->context
,
458 vmixer
->video_width
, vmixer
->video_height
,
464 * Retrieve whether features were requested at creation time.
467 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer
,
468 uint32_t feature_count
,
469 VdpVideoMixerFeature
const *features
,
470 VdpBool
*feature_supports
)
472 vlVdpVideoMixer
*vmixer
;
475 if (!(features
&& feature_supports
))
476 return VDP_STATUS_INVALID_POINTER
;
478 vmixer
= vlGetDataHTAB(mixer
);
480 return VDP_STATUS_INVALID_HANDLE
;
482 for (i
= 0; i
< feature_count
; ++i
) {
483 switch (features
[i
]) {
484 /* they are valid, but we doesn't support them */
485 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
486 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
487 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
488 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
489 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
490 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
491 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
492 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
493 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
494 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
495 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
496 feature_supports
[i
] = false;
499 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
500 feature_supports
[i
] = vmixer
->deint
.supported
;
503 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
504 feature_supports
[i
] = vmixer
->sharpness
.supported
;
507 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
508 feature_supports
[i
] = vmixer
->noise_reduction
.supported
;
511 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
512 feature_supports
[i
] = vmixer
->luma_key
.supported
;
516 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
520 return VDP_STATUS_OK
;
524 * Enable or disable features.
527 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer
,
528 uint32_t feature_count
,
529 VdpVideoMixerFeature
const *features
,
530 VdpBool
const *feature_enables
)
532 vlVdpVideoMixer
*vmixer
;
535 if (!(features
&& feature_enables
))
536 return VDP_STATUS_INVALID_POINTER
;
538 vmixer
= vlGetDataHTAB(mixer
);
540 return VDP_STATUS_INVALID_HANDLE
;
542 pipe_mutex_lock(vmixer
->device
->mutex
);
543 for (i
= 0; i
< feature_count
; ++i
) {
544 switch (features
[i
]) {
545 /* they are valid, but we doesn't support them */
546 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
547 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
548 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
549 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
550 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
551 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
552 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
553 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
554 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
555 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
556 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
559 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
560 vmixer
->deint
.enabled
= feature_enables
[i
];
561 vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer
);
564 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
565 vmixer
->sharpness
.enabled
= feature_enables
[i
];
566 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
569 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
570 vmixer
->noise_reduction
.enabled
= feature_enables
[i
];
571 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
574 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
575 vmixer
->luma_key
.enabled
= feature_enables
[i
];
576 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
577 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
,
578 vmixer
->luma_key
.luma_min
, vmixer
->luma_key
.luma_max
);
582 pipe_mutex_unlock(vmixer
->device
->mutex
);
583 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
586 pipe_mutex_unlock(vmixer
->device
->mutex
);
588 return VDP_STATUS_OK
;
592 * Retrieve whether features are enabled.
595 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer
,
596 uint32_t feature_count
,
597 VdpVideoMixerFeature
const *features
,
598 VdpBool
*feature_enables
)
600 vlVdpVideoMixer
*vmixer
;
603 if (!(features
&& feature_enables
))
604 return VDP_STATUS_INVALID_POINTER
;
606 vmixer
= vlGetDataHTAB(mixer
);
608 return VDP_STATUS_INVALID_HANDLE
;
610 for (i
= 0; i
< feature_count
; ++i
) {
611 switch (features
[i
]) {
612 /* they are valid, but we doesn't support them */
613 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL
:
614 case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL
:
615 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
:
616 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2
:
617 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3
:
618 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4
:
619 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5
:
620 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6
:
621 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7
:
622 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8
:
623 case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9
:
624 case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE
:
627 case VDP_VIDEO_MIXER_FEATURE_SHARPNESS
:
628 feature_enables
[i
] = vmixer
->sharpness
.enabled
;
631 case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION
:
632 feature_enables
[i
] = vmixer
->noise_reduction
.enabled
;
635 case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY
:
636 feature_enables
[i
] = vmixer
->luma_key
.enabled
;
640 return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE
;
644 return VDP_STATUS_OK
;
648 * Set attribute values.
651 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer
,
652 uint32_t attribute_count
,
653 VdpVideoMixerAttribute
const *attributes
,
654 void const *const *attribute_values
)
656 const VdpColor
*background_color
;
657 union pipe_color_union color
;
658 const float *vdp_csc
;
663 if (!(attributes
&& attribute_values
))
664 return VDP_STATUS_INVALID_POINTER
;
666 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
668 return VDP_STATUS_INVALID_HANDLE
;
670 pipe_mutex_lock(vmixer
->device
->mutex
);
671 for (i
= 0; i
< attribute_count
; ++i
) {
672 switch (attributes
[i
]) {
673 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
674 background_color
= attribute_values
[i
];
675 color
.f
[0] = background_color
->red
;
676 color
.f
[1] = background_color
->green
;
677 color
.f
[2] = background_color
->blue
;
678 color
.f
[3] = background_color
->alpha
;
679 vl_compositor_set_clear_color(&vmixer
->cstate
, &color
);
681 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
682 vdp_csc
= attribute_values
[i
];
683 vmixer
->custom_csc
= !!vdp_csc
;
685 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, 1, &vmixer
->csc
);
687 memcpy(vmixer
->csc
, vdp_csc
, sizeof(vl_csc_matrix
));
688 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
689 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
,
690 vmixer
->luma_key
.luma_min
, vmixer
->luma_key
.luma_max
);
693 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
695 val
= *(float*)attribute_values
[i
];
696 if (val
< 0.f
|| val
> 1.f
) {
697 ret
= VDP_STATUS_INVALID_VALUE
;
701 vmixer
->noise_reduction
.level
= val
* 10;
702 vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer
);
705 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
706 val
= *(float*)attribute_values
[i
];
707 if (val
< 0.f
|| val
> 1.f
) {
708 ret
= VDP_STATUS_INVALID_VALUE
;
711 vmixer
->luma_key
.luma_min
= val
;
712 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
713 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
,
714 vmixer
->luma_key
.luma_min
, vmixer
->luma_key
.luma_max
);
717 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
718 val
= *(float*)attribute_values
[i
];
719 if (val
< 0.f
|| val
> 1.f
) {
720 ret
= VDP_STATUS_INVALID_VALUE
;
723 vmixer
->luma_key
.luma_max
= val
;
724 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
725 vl_compositor_set_csc_matrix(&vmixer
->cstate
, (const vl_csc_matrix
*)&vmixer
->csc
,
726 vmixer
->luma_key
.luma_min
, vmixer
->luma_key
.luma_max
);
729 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
731 val
= *(float*)attribute_values
[i
];
732 if (val
< -1.f
|| val
> 1.f
) {
733 ret
= VDP_STATUS_INVALID_VALUE
;
737 vmixer
->sharpness
.value
= val
;
738 vlVdpVideoMixerUpdateSharpnessFilter(vmixer
);
741 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
742 if (*(uint8_t*)attribute_values
[i
] > 1) {
743 ret
= VDP_STATUS_INVALID_VALUE
;
746 vmixer
->skip_chroma_deint
= *(uint8_t*)attribute_values
[i
];
747 vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer
);
750 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
754 pipe_mutex_unlock(vmixer
->device
->mutex
);
756 return VDP_STATUS_OK
;
758 pipe_mutex_unlock(vmixer
->device
->mutex
);
763 * Retrieve parameter values given at creation time.
766 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer
,
767 uint32_t parameter_count
,
768 VdpVideoMixerParameter
const *parameters
,
769 void *const *parameter_values
)
771 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
774 return VDP_STATUS_INVALID_HANDLE
;
776 if (!parameter_count
)
777 return VDP_STATUS_OK
;
778 if (!(parameters
&& parameter_values
))
779 return VDP_STATUS_INVALID_POINTER
;
780 for (i
= 0; i
< parameter_count
; ++i
) {
781 switch (parameters
[i
]) {
782 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
783 *(uint32_t*)parameter_values
[i
] = vmixer
->video_width
;
785 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
786 *(uint32_t*)parameter_values
[i
] = vmixer
->video_height
;
788 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
789 *(VdpChromaType
*)parameter_values
[i
] = PipeToChroma(vmixer
->chroma_format
);
791 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
792 *(uint32_t*)parameter_values
[i
] = vmixer
->max_layers
;
795 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
798 return VDP_STATUS_OK
;
802 * Retrieve current attribute values.
805 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer
,
806 uint32_t attribute_count
,
807 VdpVideoMixerAttribute
const *attributes
,
808 void *const *attribute_values
)
811 VdpCSCMatrix
**vdp_csc
;
813 if (!(attributes
&& attribute_values
))
814 return VDP_STATUS_INVALID_POINTER
;
816 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
818 return VDP_STATUS_INVALID_HANDLE
;
820 pipe_mutex_lock(vmixer
->device
->mutex
);
821 for (i
= 0; i
< attribute_count
; ++i
) {
822 switch (attributes
[i
]) {
823 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
824 vl_compositor_get_clear_color(&vmixer
->cstate
, attribute_values
[i
]);
826 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
827 vdp_csc
= attribute_values
[i
];
828 if (!vmixer
->custom_csc
) {
832 memcpy(*vdp_csc
, vmixer
->csc
, sizeof(float)*12);
835 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
836 *(float*)attribute_values
[i
] = (float)vmixer
->noise_reduction
.level
/ 10.0f
;
839 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
840 *(float*)attribute_values
[i
] = vmixer
->luma_key
.luma_min
;
842 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
843 *(float*)attribute_values
[i
] = vmixer
->luma_key
.luma_max
;
845 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
846 *(float*)attribute_values
[i
] = vmixer
->sharpness
.value
;
848 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
849 *(uint8_t*)attribute_values
[i
] = vmixer
->skip_chroma_deint
;
852 pipe_mutex_unlock(vmixer
->device
->mutex
);
853 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
856 pipe_mutex_unlock(vmixer
->device
->mutex
);
857 return VDP_STATUS_OK
;
861 * Generate a color space conversion matrix.
864 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
865 VdpColorStandard standard
,
866 VdpCSCMatrix
*csc_matrix
)
868 enum VL_CSC_COLOR_STANDARD vl_std
;
869 struct vl_procamp camp
;
872 return VDP_STATUS_INVALID_POINTER
;
875 case VDP_COLOR_STANDARD_ITUR_BT_601
: vl_std
= VL_CSC_COLOR_STANDARD_BT_601
; break;
876 case VDP_COLOR_STANDARD_ITUR_BT_709
: vl_std
= VL_CSC_COLOR_STANDARD_BT_709
; break;
877 case VDP_COLOR_STANDARD_SMPTE_240M
: vl_std
= VL_CSC_COLOR_STANDARD_SMPTE_240M
; break;
878 default: return VDP_STATUS_INVALID_COLOR_STANDARD
;
882 if (procamp
->struct_version
> VDP_PROCAMP_VERSION
)
883 return VDP_STATUS_INVALID_STRUCT_VERSION
;
884 camp
.brightness
= procamp
->brightness
;
885 camp
.contrast
= procamp
->contrast
;
886 camp
.saturation
= procamp
->saturation
;
887 camp
.hue
= procamp
->hue
;
890 vl_csc_get_matrix(vl_std
, procamp
? &camp
: NULL
, true, csc_matrix
);
891 return VDP_STATUS_OK
;