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