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 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating VideoMixer\n");
57 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
59 return VDP_STATUS_INVALID_HANDLE
;
60 screen
= dev
->vscreen
->pscreen
;
62 vmixer
= CALLOC(1, sizeof(vlVdpVideoMixer
));
64 return VDP_STATUS_RESOURCES
;
69 * TODO: Handle features
72 *mixer
= vlAddDataHTAB(vmixer
);
74 ret
= VDP_STATUS_ERROR
;
77 vmixer
->chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
78 ret
= VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
79 for (i
= 0; i
< parameter_count
; ++i
) {
80 switch (parameters
[i
]) {
81 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
82 vmixer
->video_width
= *(uint32_t*)parameter_values
[i
];
84 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
85 vmixer
->video_height
= *(uint32_t*)parameter_values
[i
];
87 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
88 vmixer
->chroma_format
= ChromaToPipe(*(VdpChromaType
*)parameter_values
[i
]);
90 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
91 vmixer
->max_layers
= *(uint32_t*)parameter_values
[i
];
93 default: goto no_params
;
96 ret
= VDP_STATUS_INVALID_VALUE
;
97 if (vmixer
->max_layers
> 4) {
98 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Max layers > 4 not supported\n", vmixer
->max_layers
);
101 max_width
= screen
->get_video_param(screen
, prof
, PIPE_VIDEO_CAP_MAX_WIDTH
);
102 max_height
= screen
->get_video_param(screen
, prof
, PIPE_VIDEO_CAP_MAX_HEIGHT
);
103 if (vmixer
->video_width
< 48 ||
104 vmixer
->video_width
> max_width
) {
105 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer
->video_width
, max_width
);
108 if (vmixer
->video_height
< 48 ||
109 vmixer
->video_height
> max_height
) {
110 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer
->video_height
, max_height
);
113 vmixer
->luma_key_min
= 0.f
;
114 vmixer
->luma_key_max
= 1.f
;
115 vmixer
->noise_reduction_level
= 0.f
;
116 vmixer
->sharpness
= 0.f
;
118 ret
= VDP_STATUS_RESOURCES
;
119 if (!vl_compositor_init_video(&vmixer
->compositor
, dev
->context
->pipe
, vmixer
->chroma_format
, vmixer
->video_width
, vmixer
->video_height
))
122 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, true, vmixer
->csc
);
123 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
124 vl_compositor_set_csc_matrix(&vmixer
->compositor
, vmixer
->csc
);
126 return VDP_STATUS_OK
;
130 vlRemoveDataHTAB(*mixer
);
137 * Destroy a VdpVideoMixer.
140 vlVdpVideoMixerDestroy(VdpVideoMixer mixer
)
142 vlVdpVideoMixer
*vmixer
;
144 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying VideoMixer\n");
146 vmixer
= vlGetDataHTAB(mixer
);
148 return VDP_STATUS_INVALID_HANDLE
;
149 vlRemoveDataHTAB(mixer
);
151 vl_compositor_cleanup(&vmixer
->compositor
);
155 return VDP_STATUS_OK
;
159 * Enable or disable features.
162 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer
,
163 uint32_t feature_count
,
164 VdpVideoMixerFeature
const *features
,
165 VdpBool
const *feature_enables
)
167 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Setting VideoMixer features\n");
169 if (!(features
&& feature_enables
))
170 return VDP_STATUS_INVALID_POINTER
;
172 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
174 return VDP_STATUS_INVALID_HANDLE
;
180 return VDP_STATUS_OK
;
184 vl_check_video_surface(vlVdpVideoMixer
*mixer
, vlVdpSurface
*surf
)
186 if (surf
->device
!= mixer
->device
)
187 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
188 if (mixer
->video_width
!= surf
->video_buffer
->width
||
189 mixer
->video_height
!= surf
->video_buffer
->height
||
190 mixer
->chroma_format
!= surf
->video_buffer
->chroma_format
)
191 return VDP_STATUS_INVALID_SIZE
;
192 return VDP_STATUS_OK
;
196 * Perform a video post-processing and compositing operation.
198 VdpStatus
vlVdpVideoMixerRender(VdpVideoMixer mixer
,
199 VdpOutputSurface background_surface
,
200 VdpRect
const *background_source_rect
,
201 VdpVideoMixerPictureStructure current_picture_structure
,
202 uint32_t video_surface_past_count
,
203 VdpVideoSurface
const *video_surface_past
,
204 VdpVideoSurface video_surface_current
,
205 uint32_t video_surface_future_count
,
206 VdpVideoSurface
const *video_surface_future
,
207 VdpRect
const *video_source_rect
,
208 VdpOutputSurface destination_surface
,
209 VdpRect
const *destination_rect
,
210 VdpRect
const *destination_video_rect
,
211 uint32_t layer_count
,
212 VdpLayer
const *layers
)
214 struct pipe_video_buffer
*future
[video_surface_future_count
];
215 struct pipe_video_buffer
*past
[video_surface_past_count
];
216 struct pipe_video_rect src_rect
, dst_rect
;
218 enum pipe_video_picture_structure ps
;
219 switch (current_picture_structure
) {
220 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD
:
221 ps
= PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP
;
223 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD
:
224 ps
= PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_BOTTOM
;
226 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
:
227 ps
= PIPE_VIDEO_PICTURE_STRUCTURE_FRAME
;
230 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE
;
233 vlVdpVideoMixer
*vmixer
;
234 vlVdpSurface
*surf
, *tmp
;
235 vlVdpOutputSurface
*dst
, *bg
;
236 unsigned i
, layer
= 0;
238 vmixer
= vlGetDataHTAB(mixer
);
240 return VDP_STATUS_INVALID_HANDLE
;
242 surf
= vlGetDataHTAB(video_surface_current
);
244 return VDP_STATUS_INVALID_HANDLE
;
245 ret
= vl_check_video_surface(vmixer
, surf
);
248 if (layer_count
> vmixer
->max_layers
)
249 return VDP_STATUS_INVALID_VALUE
;
251 dst
= vlGetDataHTAB(destination_surface
);
253 return VDP_STATUS_INVALID_HANDLE
;
254 for (i
= 0; i
< video_surface_past_count
; ++i
) {
255 if (video_surface_past
[i
] != VDP_INVALID_HANDLE
) {
256 tmp
= vlGetDataHTAB(video_surface_past
[i
]);
258 return VDP_STATUS_INVALID_HANDLE
;
259 ret
= vl_check_video_surface(vmixer
, tmp
);
262 past
[i
] = tmp
->video_buffer
;
266 for (i
= 0; i
< video_surface_future_count
; ++i
) {
267 if (video_surface_future
[i
] != VDP_INVALID_HANDLE
) {
268 tmp
= vlGetDataHTAB(video_surface_future
[i
]);
270 return VDP_STATUS_INVALID_HANDLE
;
271 ret
= vl_check_video_surface(vmixer
, tmp
);
274 future
[i
] = tmp
->video_buffer
;
279 vl_compositor_clear_layers(&vmixer
->compositor
);
280 vl_compositor_reset_dirty_area(&vmixer
->compositor
);
281 if (background_surface
!= VDP_INVALID_HANDLE
) {
282 bg
= vlGetDataHTAB(background_surface
);
284 return VDP_STATUS_INVALID_HANDLE
;
285 vl_compositor_set_rgba_layer(&vmixer
->compositor
, layer
++, bg
->sampler_view
,
286 RectToPipe(background_source_rect
, &src_rect
), NULL
);
288 vl_compositor_set_buffer_layer(&vmixer
->compositor
, layer
, ps
,
290 RectToPipe(video_source_rect
, &src_rect
),
291 RectToPipe(destination_video_rect
, &dst_rect
),
292 video_surface_past_count
, past
,
293 video_surface_future_count
, future
);
294 vl_compositor_render(&vmixer
->compositor
, dst
->surface
, NULL
,
295 RectToPipe(destination_rect
, &dst_rect
), !layer
);
297 assert(!layer_count
);
298 return VDP_STATUS_OK
;
302 * Set attribute values.
305 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer
,
306 uint32_t attribute_count
,
307 VdpVideoMixerAttribute
const *attributes
,
308 void const *const *attribute_values
)
310 const VdpColor
*background_color
;
311 union pipe_color_union color
;
312 const float *vdp_csc
;
316 if (!(attributes
&& attribute_values
))
317 return VDP_STATUS_INVALID_POINTER
;
319 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
321 return VDP_STATUS_INVALID_HANDLE
;
323 for (i
= 0; i
< attribute_count
; ++i
) {
324 switch (attributes
[i
]) {
325 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
326 background_color
= attribute_values
[i
];
327 color
.f
[0] = background_color
->red
;
328 color
.f
[1] = background_color
->green
;
329 color
.f
[2] = background_color
->blue
;
330 color
.f
[3] = background_color
->alpha
;
331 vl_compositor_set_clear_color(&vmixer
->compositor
, &color
);
333 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
334 vdp_csc
= attribute_values
[i
];
335 vmixer
->custom_csc
= !!vdp_csc
;
337 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601
, NULL
, 1, vmixer
->csc
);
339 memcpy(vmixer
->csc
, vdp_csc
, sizeof(float)*12);
340 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE
))
341 vl_compositor_set_csc_matrix(&vmixer
->compositor
, vmixer
->csc
);
343 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
344 val
= *(float*)attribute_values
[i
];
345 if (val
< 0.f
|| val
> 1.f
)
346 return VDP_STATUS_INVALID_VALUE
;
347 vmixer
->noise_reduction_level
= val
;
349 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
350 val
= *(float*)attribute_values
[i
];
351 if (val
< 0.f
|| val
> 1.f
)
352 return VDP_STATUS_INVALID_VALUE
;
353 vmixer
->luma_key_min
= val
;
355 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
356 val
= *(float*)attribute_values
[i
];
357 if (val
< 0.f
|| val
> 1.f
)
358 return VDP_STATUS_INVALID_VALUE
;
359 vmixer
->luma_key_max
= val
;
361 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
362 val
= *(float*)attribute_values
[i
];
363 if (val
< -1.f
|| val
> 1.f
)
364 return VDP_STATUS_INVALID_VALUE
;
365 vmixer
->sharpness
= val
;
367 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
368 if (*(uint8_t*)attribute_values
[i
] > 1)
369 return VDP_STATUS_INVALID_VALUE
;
370 vmixer
->skip_chroma_deint
= *(uint8_t*)attribute_values
[i
];
373 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
377 return VDP_STATUS_OK
;
381 * Retrieve whether features were requested at creation time.
384 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer
,
385 uint32_t feature_count
,
386 VdpVideoMixerFeature
const *features
,
387 VdpBool
*feature_supports
)
389 return VDP_STATUS_NO_IMPLEMENTATION
;
393 * Retrieve whether features are enabled.
396 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer
,
397 uint32_t feature_count
,
398 VdpVideoMixerFeature
const *features
,
399 VdpBool
*feature_enables
)
401 return VDP_STATUS_NO_IMPLEMENTATION
;
405 * Retrieve parameter values given at creation time.
408 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer
,
409 uint32_t parameter_count
,
410 VdpVideoMixerParameter
const *parameters
,
411 void *const *parameter_values
)
413 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
416 return VDP_STATUS_INVALID_HANDLE
;
418 if (!parameter_count
)
419 return VDP_STATUS_OK
;
420 if (!(parameters
&& parameter_values
))
421 return VDP_STATUS_INVALID_POINTER
;
422 for (i
= 0; i
< parameter_count
; ++i
) {
423 switch (parameters
[i
]) {
424 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
:
425 *(uint32_t*)parameter_values
[i
] = vmixer
->video_width
;
427 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
:
428 *(uint32_t*)parameter_values
[i
] = vmixer
->video_height
;
430 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
:
431 *(VdpChromaType
*)parameter_values
[i
] = PipeToChroma(vmixer
->chroma_format
);
433 case VDP_VIDEO_MIXER_PARAMETER_LAYERS
:
434 *(uint32_t*)parameter_values
[i
] = vmixer
->max_layers
;
437 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER
;
440 return VDP_STATUS_OK
;
444 * Retrieve current attribute values.
447 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer
,
448 uint32_t attribute_count
,
449 VdpVideoMixerAttribute
const *attributes
,
450 void *const *attribute_values
)
453 VdpCSCMatrix
**vdp_csc
;
455 if (!(attributes
&& attribute_values
))
456 return VDP_STATUS_INVALID_POINTER
;
458 vlVdpVideoMixer
*vmixer
= vlGetDataHTAB(mixer
);
460 return VDP_STATUS_INVALID_HANDLE
;
462 for (i
= 0; i
< attribute_count
; ++i
) {
463 switch (attributes
[i
]) {
464 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR
:
465 vl_compositor_get_clear_color(&vmixer
->compositor
, attribute_values
[i
]);
467 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
:
468 vdp_csc
= attribute_values
[i
];
469 if (!vmixer
->custom_csc
) {
473 memcpy(*vdp_csc
, vmixer
->csc
, sizeof(float)*12);
475 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL
:
476 *(float*)attribute_values
[i
] = vmixer
->noise_reduction_level
;
478 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
:
479 *(float*)attribute_values
[i
] = vmixer
->luma_key_min
;
481 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
:
482 *(float*)attribute_values
[i
] = vmixer
->luma_key_max
;
484 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
:
485 *(float*)attribute_values
[i
] = vmixer
->sharpness
;
487 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
:
488 *(uint8_t*)attribute_values
[i
] = vmixer
->skip_chroma_deint
;
491 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE
;
494 return VDP_STATUS_OK
;
498 * Generate a color space conversion matrix.
501 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
502 VdpColorStandard standard
,
503 VdpCSCMatrix
*csc_matrix
)
506 enum VL_CSC_COLOR_STANDARD vl_std
;
507 struct vl_procamp camp
;
509 if (!(csc_matrix
&& procamp
))
510 return VDP_STATUS_INVALID_POINTER
;
512 if (procamp
->struct_version
> VDP_PROCAMP_VERSION
)
513 return VDP_STATUS_INVALID_STRUCT_VERSION
;
516 case VDP_COLOR_STANDARD_ITUR_BT_601
: vl_std
= VL_CSC_COLOR_STANDARD_BT_601
; break;
517 case VDP_COLOR_STANDARD_ITUR_BT_709
: vl_std
= VL_CSC_COLOR_STANDARD_BT_709
; break;
518 case VDP_COLOR_STANDARD_SMPTE_240M
: vl_std
= VL_CSC_COLOR_STANDARD_SMPTE_240M
; break;
519 default: return VDP_STATUS_INVALID_COLOR_STANDARD
;
521 camp
.brightness
= procamp
->brightness
;
522 camp
.contrast
= procamp
->contrast
;
523 camp
.saturation
= procamp
->saturation
;
524 camp
.hue
= procamp
->hue
;
525 vl_csc_get_matrix(vl_std
, &camp
, 1, matrix
);
526 memcpy(csc_matrix
, matrix
, sizeof(float)*12);
527 return VDP_STATUS_OK
;