1 /***************************************************************************
2     \file             : ADM_coreVdpau.cpp
3     \brief            : Wrapper around vdpau functions
4     \author           : (C) 2010 by mean fixounet@free.fr
5  ***************************************************************************/
6 
7 /***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 #include "ADM_default.h"
16 #include "../include/ADM_coreVdpau.h"
17 
18 #if defined(USE_VDPAU)
19 #include "../include/ADM_coreVdpauInternal.h"
20 #include "ADM_dynamicLoading.h"
21 
22 #if 0
23     #define aprintf ADM_info
24 #else
25     #define aprintf(...) {}
26 #endif
27 //GUI_WindowInfo      admVdpau::myWindowInfo;
28 
29 /**
30     \fn    mixerIsFeatureEnabled
31     \brief
32 */
mixerIsFeatureEnabled(VdpVideoMixer mixer,VdpVideoMixerFeature feature)33 bool admVdpau::mixerIsFeatureEnabled( VdpVideoMixer mixer,VdpVideoMixerFeature feature)
34 {
35     VdpBool enabledFeature=true;
36     CHECKBOOL(ADM_coreVdpau::funcs.mixerGetFeaturesEnabled(mixer,1,&feature,&enabledFeature));
37     if(enabledFeature) return true;
38     return false;
39 }
40 /**
41     \fn    mixerEnableFeature
42     \brief enable mixer feature
43 */
44 
mixerEnableFeature(VdpVideoMixer mixer,uint32_t nbFeature,VdpVideoMixerFeature * feature,VdpBool * enabledFeature)45 VdpStatus admVdpau::mixerEnableFeature( VdpVideoMixer mixer,uint32_t nbFeature,VdpVideoMixerFeature *feature,VdpBool *enabledFeature)
46 {
47     aprintf("Enabling %d features\n",nbFeature);
48     CHECK(ADM_coreVdpau::funcs.mixerEnableFeatures(mixer,nbFeature,feature,enabledFeature));
49 }
50 /**
51     \fn mixerFeatureSupported
52     \brief Check a feature is supported by VDPAU
53 */
mixerFeatureSupported(VdpVideoMixerFeature attribute)54 bool admVdpau::mixerFeatureSupported(VdpVideoMixerFeature attribute)
55 {
56 VdpBool supported=VDP_TRUE;
57     CHECKBOOL(ADM_coreVdpau::funcs.mixerQueryFeatureSupported(ADM_coreVdpau::vdpDevice,attribute,&supported));
58     if(VDP_TRUE==supported) return true;
59     return false;
60 }
61 /**
62     \fn mixerCreate
63 */
mixerCreate(uint32_t width,uint32_t height,VdpVideoMixer * mixer,bool deinterlace,bool ivtc)64 VdpStatus admVdpau::mixerCreate(uint32_t width,uint32_t height, VdpVideoMixer *mixer,bool deinterlace,bool ivtc)
65 {
66 #define MIXER_NB_PARAM 3
67 #define MIXER_NB_FEATURE_MAX 7
68 
69 VdpVideoMixerParameter parameters[MIXER_NB_PARAM]=
70                                               {VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
71                                                VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
72                                                VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
73                                                };
74     VdpVideoMixerFeature features[MIXER_NB_FEATURE_MAX];
75     VdpBool              enabledFeatures[MIXER_NB_FEATURE_MAX]={VDP_TRUE,VDP_TRUE,VDP_TRUE,VDP_TRUE,VDP_TRUE,VDP_TRUE,VDP_TRUE};
76     uint32_t color=VDP_CHROMA_TYPE_420;
77     void    *values[MIXER_NB_PARAM]={&width,&height,&color};
78     int nbFeature=0;
79     ADM_info("Creating vdpauMixer with width=%d, height=%d color=%d\n",width,height,color);
80     //features[nbFeature++]=VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5;
81 
82     if(ivtc)
83     {
84         ADM_info("Vdpau: Enabling ivtc\n");
85         features[nbFeature++]=VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE;
86         deinterlace=true; // we need a sort of deinterlacing
87     }
88     if(deinterlace)
89     {
90         ADM_info("Vdpau: Enabling temporal spatial deint\n");
91         features[nbFeature++]=VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL;
92     }
93     int nbParam=MIXER_NB_PARAM;
94 
95     VdpStatus e=ADM_coreVdpau::funcs.mixerCreate(ADM_coreVdpau::vdpDevice,
96                         nbFeature,features,
97                         nbParam,parameters,values,
98                         mixer);
99     if(VDP_STATUS_OK!=e)
100     {
101         ADM_warning("MixerCreate  failed :%s\n",getErrorString(e));
102 
103     }else
104     {
105         ADM_info("Vdpau Mixer : Enabling %d features\n",nbFeature);
106         mixerEnableFeature(*mixer, nbFeature, features, enabledFeatures);
107     }
108     return e;
109 }
110 /**
111     \fn mixerDestroy
112 */
113 
mixerDestroy(VdpVideoMixer mixer)114 VdpStatus admVdpau::mixerDestroy(VdpVideoMixer mixer)
115 {
116     CHECK(ADM_coreVdpau::funcs.mixerDestroy(mixer));
117 }
118 /**
119     \fn mixerRender
120 */
121 
mixerRender(VdpVideoMixer mixer,VdpVideoSurface sourceSurface,VdpOutputSurface targetOutputSurface,uint32_t targetWidth,uint32_t targetHeight)122 VdpStatus admVdpau::mixerRender(VdpVideoMixer mixer,
123                                 VdpVideoSurface sourceSurface,
124                                 VdpOutputSurface targetOutputSurface,
125                                 uint32_t targetWidth,
126                                 uint32_t targetHeight )
127 {
128 const VdpVideoSurface listOfInvalidSurface[1]={VDP_INVALID_HANDLE};
129       VdpStatus e=ADM_coreVdpau::funcs.mixerRender(mixer,
130                 VDP_INVALID_HANDLE,NULL,    // Background
131                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
132 
133                 0,            listOfInvalidSurface, // Past...
134                 sourceSurface,                      // current
135                 0,            listOfInvalidSurface, // Future
136                 NULL,                               // source RECT
137                 targetOutputSurface,
138                 NULL,                               // dest Rec
139                 NULL,                               // dest video Rec
140                 0,NULL);                            // Layers
141 
142 #if 0
143   ADM_info("Target width=%d height=%d\n", targetWidth,targetHeight);
144   VdpRGBAFormat fmt;
145   VdpChromaType chroma;
146   uint32_t tw,th;
147 
148   if(VDP_STATUS_OK!=ADM_coreVdpau::funcs.mixerGetOutputSurfaceParameters(targetOutputSurface,&fmt,&tw,&th))
149   {
150       ADM_warning("VdpOutputSurfaceGetParameters failed\n");
151   }
152   ADM_info("output surface width=%d height=%d fmt=%d\n", tw,th,fmt);
153   if(VDP_STATUS_OK!=ADM_coreVdpau::funcs.mixerGetSurfaceParameters(sourceSurface,&chroma,&tw,&th))
154   {
155         ADM_warning("mixerGetSurfaceParameters failed\n");
156   }
157   ADM_info("input surface width=%d height=%d fmt=%d\n", tw,th,chroma);
158 #endif
159   if(VDP_STATUS_OK!=e)
160     {
161 
162         ADM_warning("MixerRender  failed :%s\n",getErrorString(e));
163 
164     }
165     return e;
166 }
167 /**
168  * \fn mixerRenderWithCropping
169  * \brief Same as above but allow to take only top/left of the input image
170  * @param mixer
171  * @param sourceSurface
172  * @param targetOutputSurface
173  * @param targetWidth
174  * @param targetHeight
175  * @param sourceWidth
176  * @param sourceHeight
177  * @return
178  */
mixerRenderWithCropping(VdpVideoMixer mixer,VdpVideoSurface sourceSurface,VdpOutputSurface targetOutputSurface,uint32_t targetWidth,uint32_t targetHeight,uint32_t sourceWidth,uint32_t sourceHeight)179 VdpStatus admVdpau::mixerRenderWithCropping(VdpVideoMixer mixer,
180                                 VdpVideoSurface sourceSurface,
181                                 VdpOutputSurface targetOutputSurface,
182                                 uint32_t targetWidth,
183                                 uint32_t targetHeight,uint32_t sourceWidth, uint32_t sourceHeight )
184 {
185 const VdpVideoSurface listOfInvalidSurface[1]={VDP_INVALID_HANDLE};
186 
187     VdpRect rect;
188     rect.x0=rect.y0=0;
189     rect.x1=sourceWidth;
190     rect.y1=sourceHeight;
191 #if 0
192     VdpChromaType sourceChroma;
193     uint32_t sourceW,sourceH;
194     ADM_coreVdpau::funcs.mixerGetSurfaceParameters(sourceSurface,&sourceChroma,&sourceW,&sourceH);
195     ADM_info("Source is %d %d x %d\n",sourceChroma,sourceW,sourceH);
196     VdpRGBAFormat rgb;
197     ADM_coreVdpau::funcs.mixerGetOutputSurfaceParameters(targetOutputSurface,&rgb,&sourceW,&sourceH);
198     ADM_info("Target is %d %d x %d\n",rgb,sourceW,sourceH);
199     ADM_info("Cropped to %d x %d ==> %d x %d\n",sourceWidth,sourceHeight,targetWidth,targetHeight);
200     ADM_info("Rect %d %d %d %d\n",rect.x0,rect.y0,rect.x1,rect.y1);
201 #endif
202       VdpStatus e=ADM_coreVdpau::funcs.mixerRender(mixer,
203                 VDP_INVALID_HANDLE,NULL,    // Background
204                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
205 
206                 0,            listOfInvalidSurface, // Past...
207                 sourceSurface,                      // current
208                 0,            listOfInvalidSurface, // Future
209                 &rect,                               // source RECT
210                 targetOutputSurface,
211                 NULL,                               // dest Rec
212                 NULL,                               // dest video Rec
213                 0,NULL);                            // Layers
214 
215 
216   if(VDP_STATUS_OK!=e)
217     {
218 
219         ADM_warning("MixerCreate  failed :%s\n",getErrorString(e));
220 
221     }
222     return e;
223 }
224 
225 /**
226     \fn mixerGetAttributesValue
227 */
228 
mixerGetAttributesValue(VdpVideoMixer mixer,uint32_t attrCount,const VdpVideoMixerAttribute * keys,void * const * values)229 VdpStatus admVdpau::mixerGetAttributesValue(VdpVideoMixer mixer,
230                                 uint32_t attrCount,
231                                 const  VdpVideoMixerAttribute  *keys,
232                                   void * const *         values)
233 {
234 
235     VdpStatus e=ADM_coreVdpau::funcs.mixerGetAttributesValue(mixer,attrCount,keys,values);
236     if(VDP_STATUS_OK!=e)
237     {
238 
239         ADM_warning("MixerGetAttributes  failed :%s\n",getErrorString(e));
240 
241     }
242     return e;
243 }
244 /**
245     \fn mixerSetAttributesValue
246 */
mixerSetAttributesValue(VdpVideoMixer mixer,uint32_t attrCount,const VdpVideoMixerAttribute * xkeys,void * const * values)247 VdpStatus admVdpau::mixerSetAttributesValue(VdpVideoMixer mixer,
248                                 uint32_t attrCount,
249                                 const  VdpVideoMixerAttribute *xkeys,
250                                 void * const* values)
251 {
252     VdpStatus e=ADM_coreVdpau::funcs.mixerSetAttributesValue(mixer,attrCount,xkeys,values);
253     if(VDP_STATUS_OK!=e)
254     {
255 
256         ADM_warning("MixerSetAttributes  failed :%s\n",getErrorString(e));
257 
258     }
259     return e;
260 }
261 
queryDecoderCapabilities(VdpDecoderProfile profile,int * maxWidth,int * maxHeight)262 bool admVdpau::queryDecoderCapabilities(
263                                                     VdpDecoderProfile profile,
264                                                     int *        maxWidth,
265                                                     int *        maxHeight)
266   {
267     VdpBool is_supported=false;
268     uint32_t max_level,max_macroblocks,max_width,max_height;
269     VdpStatus e=ADM_coreVdpau::funcs.queryDecoderCapabilities(ADM_coreVdpau::vdpDevice,
270                                                               profile,
271                                                               &is_supported,
272                                                               &max_level,
273                                                               &max_macroblocks,
274                                                               &max_width,
275                                                               &max_height);
276     if(VDP_STATUS_OK!=e)
277     {
278         ADM_warning("queryDecoderCapabilities  failed :%s\n",getErrorString(e));
279         return false;
280     }
281     *maxWidth=max_width;
282     *maxHeight=max_height;
283     return is_supported;
284   }
285 
286 /**
287     \fn mixerRenderWithPastAndFuture
288 */
289 
mixerRenderFieldWithPastAndFuture(bool topField,VdpVideoMixer mixer,VdpVideoSurface sourceSurface[3],VdpOutputSurface targetOutputSurface,uint32_t targetWidth,uint32_t targetHeight,uint32_t sourceWidth,uint32_t sourceHeight)290 VdpStatus admVdpau::mixerRenderFieldWithPastAndFuture(
291                                 bool topField,
292                                 VdpVideoMixer mixer,
293                                 VdpVideoSurface sourceSurface[3], // Past present future
294                                 VdpOutputSurface targetOutputSurface,
295                                 uint32_t targetWidth,
296                                 uint32_t targetHeight,
297                                 uint32_t sourceWidth,
298                                 uint32_t sourceHeight        )
299 {
300     int nbPrev=2,nbNext=2;
301     VdpVideoMixerPictureStructure fieldType=VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
302     if(!topField) fieldType=VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
303 
304 
305     VdpVideoSurface past[2]={VDP_INVALID_HANDLE,VDP_INVALID_HANDLE};
306     VdpVideoSurface future[2]={VDP_INVALID_HANDLE,VDP_INVALID_HANDLE};
307     VdpVideoSurface present;
308 
309     VdpRect rect;
310     rect.x0=rect.y0=0;
311     rect.x1=sourceWidth;
312     rect.y1=sourceHeight;
313 
314     present=sourceSurface[1];
315     int index=0;
316     if(!topField) index=1;
317 
318     if(VDP_INVALID_HANDLE==sourceSurface[0] ) nbPrev=0;
319     else
320     {
321 
322             past[0]=sourceSurface[index];
323             past[1]=sourceSurface[0];
324     }
325     if(VDP_INVALID_HANDLE==sourceSurface[2] ) nbNext=0;
326     else
327     {
328             future[0]=sourceSurface[1+index];
329             future[1]=sourceSurface[2];
330     }
331     // 0 & 1 p
332     //ADM_info("Deint : %d\n",(int)mixerIsFeatureEnabled(mixer,VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL));
333 
334       VdpStatus e=ADM_coreVdpau::funcs.mixerRender(mixer,
335                 VDP_INVALID_HANDLE,NULL,    // Background
336                 fieldType,
337                 nbPrev,       past, // Past...
338                               present, // current
339                 nbNext,       future, // Future
340                 &rect,                               // source RECT
341                 targetOutputSurface,
342                 NULL,                               // dest Rec
343                 NULL,                               // dest video Rec
344                 0,NULL);                            // Layers
345 
346 
347   if(VDP_STATUS_OK!=e)
348     {
349 
350         ADM_warning("mixerRenderWithPastAndFuture  failed :%s\n",getErrorString(e));
351 
352     }
353     return e;
354 }
355 
356 /**
357     \fn mixerRenderWithPastAndFuture
358 */
359 
mixerRenderFrameWithPastAndFuture(VdpVideoMixer mixer,VdpVideoSurface sourceSurface[3],VdpOutputSurface targetOutputSurface,uint32_t targetWidth,uint32_t targetHeight,uint32_t sourceWidth,uint32_t sourceHeight)360 VdpStatus admVdpau::mixerRenderFrameWithPastAndFuture(
361                                 VdpVideoMixer mixer,
362                                 VdpVideoSurface sourceSurface[3], // Past present future
363                                 VdpOutputSurface targetOutputSurface,
364                                 uint32_t targetWidth,
365                                 uint32_t targetHeight,
366                                 uint32_t sourceWidth,
367                                 uint32_t sourceHeight        )
368 {
369     VdpVideoSurface past=VDP_INVALID_HANDLE;
370     VdpVideoSurface future=VDP_INVALID_HANDLE;
371     VdpVideoSurface present;
372 
373     VdpRect rect;
374     rect.x0=rect.y0=0;
375     rect.x1=sourceWidth;
376     rect.y1=sourceHeight;
377 
378     present=sourceSurface[1];
379 
380     int nbPrev=0,nbNext=0;
381 
382     if(VDP_INVALID_HANDLE!=sourceSurface[0] )
383     {
384         nbPrev=1;
385         past=sourceSurface[0];
386     }
387     if(VDP_INVALID_HANDLE!=sourceSurface[2] )
388     {
389         nbNext=1;
390         future=sourceSurface[2];
391     }
392     // 0 & 1 p
393     //ADM_info("Deint : %d\n",(int)mixerIsFeatureEnabled(mixer,VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL));
394 
395     VdpStatus e=ADM_coreVdpau::funcs.mixerRender(mixer,
396                 VDP_INVALID_HANDLE,NULL,    // Background
397                 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
398                 nbPrev,       &past, // Past...
399                               present, // current
400                 nbNext,       &future, // Future
401                 &rect,                               // source RECT
402                 targetOutputSurface,
403                 NULL,                               // dest Rec
404                 NULL,                               // dest video Rec
405                 0,NULL);                            // Layers
406 
407 
408   if(VDP_STATUS_OK!=e)
409     {
410         ADM_warning("mixerRenderIvtcWithPastAndFuture  failed :%s\n",getErrorString(e));
411     }
412     return e;
413 }
414 #endif
415 // EOF
416