mixer.c revision e8e0756bd35e5e3b70a0eee323f5aaa3707fe11d
1/**************************************************************************
2 *
3 * Copyright 2010 Thomas Balling Sørensen.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28#include <vdpau/vdpau.h>
29
30#include "util/u_memory.h"
31#include "util/u_debug.h"
32
33#include "vl/vl_csc.h"
34
35#include "vdpau_private.h"
36
37/**
38 * Create a VdpVideoMixer.
39 */
40VdpStatus
41vlVdpVideoMixerCreate(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,
47                      VdpVideoMixer *mixer)
48{
49   vlVdpVideoMixer *vmixer = NULL;
50   VdpStatus ret;
51   struct pipe_screen *screen;
52   unsigned max_width, max_height, i;
53   enum pipe_video_profile prof = PIPE_VIDEO_PROFILE_UNKNOWN;
54
55   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating VideoMixer\n");
56
57   vlVdpDevice *dev = vlGetDataHTAB(device);
58   if (!dev)
59      return VDP_STATUS_INVALID_HANDLE;
60   screen = dev->vscreen->pscreen;
61
62   vmixer = CALLOC(1, sizeof(vlVdpVideoMixer));
63   if (!vmixer)
64      return VDP_STATUS_RESOURCES;
65
66   vmixer->device = dev;
67   vl_compositor_init(&vmixer->compositor, dev->context->pipe);
68
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->compositor, vmixer->csc);
72
73   /*
74    * TODO: Handle features
75    */
76
77   *mixer = vlAddDataHTAB(vmixer);
78   if (*mixer == 0) {
79      ret = VDP_STATUS_ERROR;
80      goto no_handle;
81   }
82   vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
83   ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
84   for (i = 0; i < parameter_count; ++i) {
85      switch (parameters[i]) {
86      case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
87         vmixer->video_width = *(uint32_t*)parameter_values[i];
88         break;
89      case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
90         vmixer->video_height = *(uint32_t*)parameter_values[i];
91         break;
92      case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
93         vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]);
94         break;
95      case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
96         vmixer->max_layers = *(uint32_t*)parameter_values[i];
97         break;
98      default: goto no_params;
99      }
100   }
101   ret = VDP_STATUS_INVALID_VALUE;
102   if (vmixer->max_layers > 4) {
103      VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers);
104      goto no_params;
105   }
106   max_width = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_WIDTH);
107   max_height = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_HEIGHT);
108   if (vmixer->video_width < 48 ||
109       vmixer->video_width > max_width) {
110      VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer->video_width, max_width);
111      goto no_params;
112   }
113   if (vmixer->video_height < 48 ||
114       vmixer->video_height > max_height) {
115      VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u  not valid for height\n", vmixer->video_height, max_height);
116      goto no_params;
117   }
118   vmixer->luma_key_min = 0.f;
119   vmixer->luma_key_max = 1.f;
120   vmixer->noise_reduction_level = 0.f;
121   vmixer->sharpness = 0.f;
122   return VDP_STATUS_OK;
123
124no_params:
125   vlRemoveDataHTAB(*mixer);
126no_handle:
127   vl_compositor_cleanup(&vmixer->compositor);
128   FREE(vmixer);
129   return ret;
130}
131
132/**
133 * Destroy a VdpVideoMixer.
134 */
135VdpStatus
136vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
137{
138   vlVdpVideoMixer *vmixer;
139
140   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying VideoMixer\n");
141
142   vmixer = vlGetDataHTAB(mixer);
143   if (!vmixer)
144      return VDP_STATUS_INVALID_HANDLE;
145   vlRemoveDataHTAB(mixer);
146
147   vl_compositor_cleanup(&vmixer->compositor);
148
149   FREE(vmixer);
150
151   return VDP_STATUS_OK;
152}
153
154/**
155 * Enable or disable features.
156 */
157VdpStatus
158vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
159                                 uint32_t feature_count,
160                                 VdpVideoMixerFeature const *features,
161                                 VdpBool const *feature_enables)
162{
163   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Setting VideoMixer features\n");
164
165   if (!(features && feature_enables))
166      return VDP_STATUS_INVALID_POINTER;
167
168   vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
169   if (!vmixer)
170      return VDP_STATUS_INVALID_HANDLE;
171
172   /*
173    * TODO: Set features
174    */
175
176   return VDP_STATUS_OK;
177}
178
179/**
180 * Perform a video post-processing and compositing operation.
181 */
182VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
183                                VdpOutputSurface background_surface,
184                                VdpRect const *background_source_rect,
185                                VdpVideoMixerPictureStructure current_picture_structure,
186                                uint32_t video_surface_past_count,
187                                VdpVideoSurface const *video_surface_past,
188                                VdpVideoSurface video_surface_current,
189                                uint32_t video_surface_future_count,
190                                VdpVideoSurface const *video_surface_future,
191                                VdpRect const *video_source_rect,
192                                VdpOutputSurface destination_surface,
193                                VdpRect const *destination_rect,
194                                VdpRect const *destination_video_rect,
195                                uint32_t layer_count,
196                                VdpLayer const *layers)
197{
198   struct pipe_video_rect src_rect, dst_rect, dst_clip;
199
200   vlVdpVideoMixer *vmixer;
201   vlVdpSurface *surf;
202   vlVdpOutputSurface *dst;
203
204   vmixer = vlGetDataHTAB(mixer);
205   if (!vmixer)
206      return VDP_STATUS_INVALID_HANDLE;
207
208   surf = vlGetDataHTAB(video_surface_current);
209   if (!surf)
210      return VDP_STATUS_INVALID_HANDLE;
211
212   if (surf->device != vmixer->device)
213      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
214
215   if (vmixer->video_width > surf->video_buffer->width ||
216       vmixer->video_height > surf->video_buffer->height ||
217       vmixer->chroma_format != surf->video_buffer->chroma_format)
218      return VDP_STATUS_INVALID_SIZE;
219
220   if (layer_count > vmixer->max_layers)
221      return VDP_STATUS_INVALID_VALUE;
222
223   dst = vlGetDataHTAB(destination_surface);
224   if (!dst)
225      return VDP_STATUS_INVALID_HANDLE;
226
227   vl_compositor_clear_layers(&vmixer->compositor);
228   vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer,
229                                  RectToPipe(video_source_rect, &src_rect), NULL);
230   vl_compositor_render(&vmixer->compositor, dst->surface,
231                        RectToPipe(destination_video_rect, &dst_rect),
232                        RectToPipe(destination_rect, &dst_clip),
233                        &dst->dirty_area);
234
235   return VDP_STATUS_OK;
236}
237
238/**
239 * Set attribute values.
240 */
241VdpStatus
242vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
243                                  uint32_t attribute_count,
244                                  VdpVideoMixerAttribute const *attributes,
245                                  void const *const *attribute_values)
246{
247   const VdpColor *background_color;
248   union pipe_color_union color;
249   const float *vdp_csc;
250   float val;
251   unsigned i;
252
253   if (!(attributes && attribute_values))
254      return VDP_STATUS_INVALID_POINTER;
255
256   vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
257   if (!vmixer)
258      return VDP_STATUS_INVALID_HANDLE;
259
260   for (i = 0; i < attribute_count; ++i) {
261      switch (attributes[i]) {
262      case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
263         background_color = attribute_values[i];
264         color.f[0] = background_color->red;
265         color.f[1] = background_color->green;
266         color.f[2] = background_color->blue;
267         color.f[3] = background_color->alpha;
268         vl_compositor_set_clear_color(&vmixer->compositor, &color);
269         break;
270      case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
271         vdp_csc = attribute_values[i];
272         vmixer->custom_csc = !!vdp_csc;
273         if (!vdp_csc)
274            vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, vmixer->csc);
275         else
276            memcpy(vmixer->csc, vdp_csc, sizeof(float)*12);
277         if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
278            vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc);
279         break;
280      case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
281         val = *(float*)attribute_values[i];
282         if (val < 0.f || val > 1.f)
283            return VDP_STATUS_INVALID_VALUE;
284         vmixer->noise_reduction_level = val;
285         break;
286      case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
287         val = *(float*)attribute_values[i];
288         if (val < 0.f || val > 1.f)
289            return VDP_STATUS_INVALID_VALUE;
290         vmixer->luma_key_min = val;
291         break;
292      case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
293         val = *(float*)attribute_values[i];
294         if (val < 0.f || val > 1.f)
295            return VDP_STATUS_INVALID_VALUE;
296         vmixer->luma_key_max = val;
297         break;
298      case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
299         val = *(float*)attribute_values[i];
300         if (val < -1.f || val > 1.f)
301            return VDP_STATUS_INVALID_VALUE;
302         vmixer->sharpness = val;
303         break;
304      case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
305         if (*(uint8_t*)attribute_values[i] > 1)
306            return VDP_STATUS_INVALID_VALUE;
307         vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i];
308         break;
309      default:
310         return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
311      }
312   }
313
314   return VDP_STATUS_OK;
315}
316
317/**
318 * Retrieve whether features were requested at creation time.
319 */
320VdpStatus
321vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
322                                 uint32_t feature_count,
323                                 VdpVideoMixerFeature const *features,
324                                 VdpBool *feature_supports)
325{
326   return VDP_STATUS_NO_IMPLEMENTATION;
327}
328
329/**
330 * Retrieve whether features are enabled.
331 */
332VdpStatus
333vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
334                                 uint32_t feature_count,
335                                 VdpVideoMixerFeature const *features,
336                                 VdpBool *feature_enables)
337{
338   return VDP_STATUS_NO_IMPLEMENTATION;
339}
340
341/**
342 * Retrieve parameter values given at creation time.
343 */
344VdpStatus
345vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer,
346                                  uint32_t parameter_count,
347                                  VdpVideoMixerParameter const *parameters,
348                                  void *const *parameter_values)
349{
350   vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
351   unsigned i;
352   if (!vmixer)
353      return VDP_STATUS_INVALID_HANDLE;
354
355   if (!parameter_count)
356      return VDP_STATUS_OK;
357   if (!(parameters && parameter_values))
358      return VDP_STATUS_INVALID_POINTER;
359   for (i = 0; i < parameter_count; ++i) {
360      switch (parameters[i]) {
361      case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
362         *(uint32_t*)parameter_values[i] = vmixer->video_width;
363         break;
364      case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
365         *(uint32_t*)parameter_values[i] = vmixer->video_height;
366         break;
367      case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
368         *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format);
369         break;
370      case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
371         *(uint32_t*)parameter_values[i] = vmixer->max_layers;
372         break;
373      default:
374         return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
375      }
376   }
377   return VDP_STATUS_OK;
378}
379
380/**
381 * Retrieve current attribute values.
382 */
383VdpStatus
384vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer,
385                                  uint32_t attribute_count,
386                                  VdpVideoMixerAttribute const *attributes,
387                                  void *const *attribute_values)
388{
389   unsigned i;
390   VdpCSCMatrix **vdp_csc;
391
392   if (!(attributes && attribute_values))
393      return VDP_STATUS_INVALID_POINTER;
394
395   vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
396   if (!vmixer)
397      return VDP_STATUS_INVALID_HANDLE;
398
399   for (i = 0; i < attribute_count; ++i) {
400      switch (attributes[i]) {
401      case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
402         vl_compositor_get_clear_color(&vmixer->compositor, attribute_values[i]);
403         break;
404      case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
405         vdp_csc = attribute_values[i];
406         if (!vmixer->custom_csc) {
407             *vdp_csc = NULL;
408            break;
409         }
410         memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12);
411         break;
412      case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
413         *(float*)attribute_values[i] = vmixer->noise_reduction_level;
414         break;
415      case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
416         *(float*)attribute_values[i] = vmixer->luma_key_min;
417         break;
418      case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
419         *(float*)attribute_values[i] = vmixer->luma_key_max;
420         break;
421      case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
422         *(float*)attribute_values[i] = vmixer->sharpness;
423         break;
424      case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
425         *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint;
426         break;
427      default:
428         return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
429      }
430   }
431   return VDP_STATUS_OK;
432}
433
434/**
435 * Generate a color space conversion matrix.
436 */
437VdpStatus
438vlVdpGenerateCSCMatrix(VdpProcamp *procamp,
439                       VdpColorStandard standard,
440                       VdpCSCMatrix *csc_matrix)
441{
442   float matrix[16];
443   enum VL_CSC_COLOR_STANDARD vl_std;
444   struct vl_procamp camp;
445
446   if (!(csc_matrix && procamp))
447      return VDP_STATUS_INVALID_POINTER;
448
449   if (procamp->struct_version > VDP_PROCAMP_VERSION)
450      return VDP_STATUS_INVALID_STRUCT_VERSION;
451
452   switch (standard) {
453      case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break;
454      case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break;
455      case VDP_COLOR_STANDARD_SMPTE_240M:  vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break;
456      default: return VDP_STATUS_INVALID_COLOR_STANDARD;
457   }
458   camp.brightness = procamp->brightness;
459   camp.contrast = procamp->contrast;
460   camp.saturation = procamp->saturation;
461   camp.hue = procamp->hue;
462   vl_csc_get_matrix(vl_std, &camp, 1, matrix);
463   memcpy(csc_matrix, matrix, sizeof(float)*12);
464   return VDP_STATUS_OK;
465}
466