View | Details | Raw Unified | Return to bug 155871
Collapse All | Expand All

(-)Makefile (-1 / +9 lines)
Lines 7-13 Link Here
7
7
8
PORTNAME=	xine
8
PORTNAME=	xine
9
PORTVERSION=	1.1.19
9
PORTVERSION=	1.1.19
10
PORTREVISION=	2
10
PORTREVISION=	3
11
CATEGORIES=	multimedia ipv6
11
CATEGORIES=	multimedia ipv6
12
MASTER_SITES=	SF/${PORTNAME}/${PORTNAME}-lib/${PORTVERSION}
12
MASTER_SITES=	SF/${PORTNAME}/${PORTNAME}-lib/${PORTVERSION}
13
PKGNAMEPREFIX=	lib
13
PKGNAMEPREFIX=	lib
Lines 80-85 OPTIONS= ARTS "Enable aRts support" off Link Here
80
		IMAGEMAGICK "Enable ImageMagick support" off \
80
		IMAGEMAGICK "Enable ImageMagick support" off \
81
		GTK2 "Enable gdkpixbuf support" off \
81
		GTK2 "Enable gdkpixbuf support" off \
82
		WAVPACK "Enable WavPack support" off \
82
		WAVPACK "Enable WavPack support" off \
83
		VAAPI "Enable VAAPI support" off \
83
		VDPAU "Enable VDPAU support" on
84
		VDPAU "Enable VDPAU support" on
84
85
85
MAN1=	xine-config.1 xine-list-1.1.1
86
MAN1=	xine-config.1 xine-list-1.1.1
Lines 208-213 PLIST_SUB+= WITH_WAVPACK="@comment " Link Here
208
CONFIGURE_ARGS+=	--without-wavpack
209
CONFIGURE_ARGS+=	--without-wavpack
209
.endif
210
.endif
210
211
212
.if defined(WITH_VAAPI)
213
LIB_DEPENDS+=	va.1:${PORTSDIR}/multimedia/libva
214
.endif
215
211
.if defined(WITH_VDPAU)
216
.if defined(WITH_VDPAU)
212
PATCHFILES+=	xine-vdpau.bz2
217
PATCHFILES+=	xine-vdpau.bz2
213
USE_AUTOTOOLS=	autoconf
218
USE_AUTOTOOLS=	autoconf
Lines 231-236 CONFIGURE_ARGS+= --disable-vidix Link Here
231
.endif
236
.endif
232
237
233
post-patch:
238
post-patch:
239
.if defined(WITH_VAAPI)
240
	${PATCH} ${PATCH_DIST_ARGS} <${FILESDIR}/ffmpeg-vaapi_xine-lib-1.1.19-initerrorhack.diff
241
.endif
234
.if defined(WITH_VDPAU)
242
.if defined(WITH_VDPAU)
235
	for i in `${LS} ${FILESDIR}/extrapatch-vdpau*`; do \
243
	for i in `${LS} ${FILESDIR}/extrapatch-vdpau*`; do \
236
		${PATCH} ${PATCH_DIST_ARGS} <$$i ;\
244
		${PATCH} ${PATCH_DIST_ARGS} <$$i ;\
(-)files/extrapatch-vdpau-src-video_out-video_out_vdpau.c (+91 lines)
Line 0 Link Here
1
--- a/src/video_out/video_out_vdpau.c
2
+++ b/src/video_out/video_out_vdpau.c
3
@@ -53,6 +53,8 @@
4
 
5
 #define NUM_FRAMES_BACK 1
6
 
7
+#define LOCKDISPLAY /*define this if you have a buggy libX11/xcb*/
8
+
9
 #define DEINT_BOB                    1
10
 #define DEINT_HALF_TEMPORAL          2
11
 #define DEINT_HALF_TEMPORAL_SPATIAL  3
12
@@ -167,12 +169,30 @@ static void vdpau_reinit( vo_driver_t *t
13
 static VdpVideoSurfaceCreate *orig_vdp_video_surface_create;
14
 static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy;
15
 
16
+static VdpVideoSurfaceCreate *orig_vdp_output_surface_create;
17
+static VdpVideoSurfaceDestroy *orig_vdp_output_surface_destroy;
18
+
19
+static VdpVideoSurfacePutBitsYCbCr *orig_vdp_video_surface_putbits_ycbcr;
20
+
21
 static VdpDecoderCreate *orig_vdp_decoder_create;
22
 static VdpDecoderDestroy *orig_vdp_decoder_destroy;
23
 static VdpDecoderRender *orig_vdp_decoder_render;
24
 
25
 static Display *guarded_display;
26
 
27
+static VdpStatus guarded_vdp_video_surface_putbits_ycbcr(VdpVideoSurface surface, VdpYCbCrFormat source_ycbcr_format, void const *const *source_data, uint32_t const *source_pitches)
28
+{
29
+  VdpStatus r;
30
+#ifdef LOCKDISPLAY
31
+  XLockDisplay(guarded_display);
32
+#endif
33
+  r = orig_vdp_video_surface_putbits_ycbcr(surface, source_ycbcr_format, source_data, source_pitches);
34
+#ifdef LOCKDISPLAY
35
+  XUnlockDisplay(guarded_display);
36
+#endif
37
+  return r;
38
+}
39
+
40
 static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface)
41
 {
42
   VdpStatus r;
43
@@ -195,6 +215,28 @@ static VdpStatus guarded_vdp_video_surfa
44
   return r;
45
 }
46
 
47
+static VdpStatus guarded_vdp_output_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface)
48
+{
49
+  VdpStatus r;
50
+#ifdef LOCKDISPLAY
51
+  XLockDisplay(guarded_display);
52
+#endif
53
+  r = orig_vdp_output_surface_create(device, chroma_type, width, height, surface);
54
+#ifdef LOCKDISPLAY
55
+  XUnlockDisplay(guarded_display);
56
+#endif
57
+  return r;
58
+}
59
+
60
+static VdpStatus guarded_vdp_output_surface_destroy(VdpVideoSurface surface)
61
+{
62
+  VdpStatus r;
63
+  XLockDisplay(guarded_display);
64
+  r = orig_vdp_output_surface_destroy(surface);
65
+  XUnlockDisplay(guarded_display);
66
+  return r;
67
+}
68
+
69
 static VdpStatus guarded_vdp_decoder_create(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder)
70
 {
71
   VdpStatus r;
72
@@ -2324,16 +2366,16 @@ static vo_driver_t *vdpau_open_plugin (v
73
   st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&orig_vdp_video_surface_destroy ); vdp_video_surface_destroy = guarded_vdp_video_surface_destroy;
74
   if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) )
75
     return NULL;
76
-  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr );
77
+  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&orig_vdp_video_surface_putbits_ycbcr ); vdp_video_surface_putbits_ycbcr = guarded_vdp_video_surface_putbits_ycbcr;
78
   if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_PUT_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) )
79
     return NULL;
80
   st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , (void*)&vdp_video_surface_getbits_ycbcr );
81
   if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_GET_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) )
82
     return NULL;
83
-  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&vdp_output_surface_create );
84
+  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&orig_vdp_output_surface_create ); vdp_output_surface_create = guarded_vdp_output_surface_create;
85
   if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) )
86
     return NULL;
87
-  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&vdp_output_surface_destroy );
88
+  st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&orig_vdp_output_surface_destroy ); vdp_output_surface_destroy = guarded_vdp_output_surface_destroy;
89
   if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) )
90
     return NULL;
91
   st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void*)&vdp_output_surface_render_bitmap_surface );
(-)files/ffmpeg-vaapi_xine-lib-1.1.19-initerrorhack.diff (+871 lines)
Line 0 Link Here
1
diff -Naur xine-lib-1.1.19.orig/src/combined/ffmpeg/ff_video_decoder.c xine-lib-1.1.19/src/combined/ffmpeg/ff_video_decoder.c
2
--- xine-lib-1.1.19.orig/src/combined/ffmpeg/ff_video_decoder.c
3
+++ xine-lib-1.1.19/src/combined/ffmpeg/ff_video_decoder.c
4
@@ -51,6 +51,21 @@
5
 #  include <libpostproc/postprocess.h>
6
 #endif
7
 
8
+#include <va/va_x11.h>
9
+#include <libavcodec/vaapi.h>
10
+//#include <X11/Xutil.h>
11
+
12
+typedef struct ff_va_surfaces_s ff_va_surfaces_t;
13
+
14
+struct ff_va_surfaces_s
15
+{
16
+  int count;
17
+  VASurfaceID **free;
18
+  VASurfaceID **used;
19
+};
20
+
21
+#define NUM_SURFACES 21
22
+
23
 #define VIDEOBUFSIZE        (128*1024)
24
 #define SLICE_BUFFER_SIZE   (1194*1024)
25
 
26
@@ -73,6 +88,7 @@ typedef struct ff_video_class_s {
27
   int                     thread_count;
28
   int8_t                  skip_loop_filter_enum;
29
   int8_t                  choose_speed_over_accuracy;
30
+  int                     enable_vaapi;
31
 
32
   xine_t                 *xine;
33
 } ff_video_class_t;
34
@@ -111,6 +127,7 @@ struct ff_video_decoder_s {
35
   int               slice_offset_size;
36
 
37
   AVFrame          *av_frame;
38
+  //AVPacket         av_pkt;
39
   AVCodecContext   *context;
40
   AVCodec          *codec;
41
 
42
@@ -138,8 +155,31 @@ struct ff_video_decoder_s {
43
 #ifdef LOG
44
   enum PixelFormat  debug_fmt;
45
 #endif
46
+
47
+};
48
+
49
+typedef struct ff_vaapi_context_s ff_vaapi_context_t;
50
+
51
+struct ff_vaapi_context_s {
52
+  VAImage           va_image;
53
+  Display           *display;
54
+  VADisplay         *va_display;
55
+  VAImageFormat     *va_ifmts;
56
+  uint8_t           *va_image_data;
57
+  VAContextID       va_context_id;
58
+  VAConfigID        va_config_id;
59
+  VASurfaceID       *va_surface_id;
60
+  struct ff_va_surfaces_s va_surfaces;
61
+  int               width;
62
+  int               height;
63
+  int               va_profile;
64
+  struct vaapi_context *vaapi_context;
65
+  int               use_vaapi;
66
 };
67
 
68
+static struct ff_vaapi_context_s *va_context;
69
+
70
+static VAStatus init_vaapi(struct ff_vaapi_context_s *va_context, int va_profile, int width, int height);
71
 
72
 static void set_stream_info(ff_video_decoder_t *this) {
73
   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,  this->bih.biWidth);
74
@@ -147,7 +187,70 @@ static void set_stream_info(ff_video_dec
75
   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_RATIO,  this->aspect_ratio * 10000);
76
 }
77
 
78
+/*
79
+ * XXX Error on init_vaapi() didn't cause fall back to standard rendering,
80
+ * so do a crude test on plugin open.
81
+ */
82
+#define INIT_ERROR_HACK
83
+
84
 #ifdef ENABLE_DIRECT_RENDERING
85
+
86
+static void draw_slice(struct AVCodecContext *context, const AVFrame *src, int offset[4], int y, int type, int height) {
87
+  uint8_t *source[4]= {src->data[0] + offset[0], src->data[1] + offset[1], src->data[2] + offset[2], src->data[3] + offset[3]};
88
+  int strides[4] = {src->linesize[0], src->linesize[1], src->linesize[2]};
89
+
90
+  if (height < 0) {
91
+    int i;
92
+    height = -height;
93
+    y -= height;
94
+    for (i = 0; i < 4; i++) {
95
+      strides[i] = -strides[i];
96
+      source[i] -= strides[i];
97
+    }
98
+  }
99
+}
100
+
101
+static VAProfile* find_profile(VAProfile* p, int np, int codec)
102
+{
103
+  int i;
104
+  
105
+  for(i = 0; i < np; i++)
106
+  {
107
+    if(p[i] == codec)
108
+      return &p[i];
109
+  }
110
+
111
+  return NULL;
112
+}
113
+
114
+int get_profile(int codec_id) {
115
+  int profile;
116
+
117
+  switch (codec_id) {
118
+    case CODEC_ID_MPEG2VIDEO:
119
+      profile = VAProfileMPEG2Main;
120
+      break;
121
+    case CODEC_ID_MPEG4:
122
+    case CODEC_ID_H263:
123
+      profile = VAProfileMPEG4AdvancedSimple;
124
+      break;
125
+    case CODEC_ID_H264:
126
+      profile = VAProfileH264High;
127
+      break;
128
+    case CODEC_ID_WMV3:
129
+      profile = VAProfileVC1Main;
130
+      break;
131
+    case CODEC_ID_VC1:
132
+      profile = VAProfileVC1Advanced;
133
+      break;
134
+    default:
135
+      profile = -1;
136
+      break;
137
+  }
138
+
139
+  return profile;
140
+}
141
+
142
 /* called from ffmpeg to do direct rendering method 1 */
143
 static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
144
   ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
145
@@ -169,6 +272,43 @@ static int get_buffer(AVCodecContext *co
146
 
147
   avcodec_align_dimensions(context, &width, &height);
148
 
149
+  if( va_context->use_vaapi ) {
150
+    int i = 0;
151
+    struct ff_va_surfaces_s *va_surfaces = &va_context->va_surfaces;
152
+
153
+    for(i = 0; i < va_surfaces->count; i++)
154
+    {
155
+      //printf("srfc #%d %p\n",i,va_srfcs->srfc_free[i]);
156
+      if(va_surfaces->free[i])
157
+      {
158
+        va_surfaces->used[i] = va_surfaces->free[i];
159
+        va_surfaces->free[i] = NULL;
160
+        break;
161
+      }
162
+    }
163
+    if(i == va_surfaces->count)
164
+    {
165
+      printf("ERROR get surface\n");
166
+      return -1;
167
+    }
168
+  
169
+  
170
+    av_frame->type = FF_BUFFER_TYPE_USER;
171
+    av_frame->age = 256*256*256*64; // FIXME FIXME from ffmpeg
172
+    av_frame->data[0] = (void*)va_surfaces->used[i];
173
+    av_frame->data[1] = NULL;
174
+    av_frame->data[2] = NULL;
175
+    av_frame->data[3] = (void*)(size_t)*va_surfaces->used[i];
176
+    av_frame->linesize[0] = 0;
177
+    av_frame->linesize[1] = 0;
178
+    av_frame->linesize[2] = 0;
179
+    av_frame->linesize[3] = 0;
180
+
181
+    this->is_direct_rendering_disabled = 1;
182
+  
183
+    return 0;
184
+  }
185
+
186
   if( this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P ) {
187
     if (!this->is_direct_rendering_disabled) {
188
       xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
189
@@ -238,10 +378,33 @@ static int get_buffer(AVCodecContext *co
190
 static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){
191
   ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
192
 
193
+  if( va_context->use_vaapi ) {
194
+    struct ff_va_surfaces_s *va_surfaces = &va_context->va_surfaces;
195
+    VASurfaceID va_surface_id = (VASurfaceID)(size_t)av_frame->data[3];
196
+    int i = 0;
197
+
198
+    for(i = 0; i < va_surfaces->count; i++)
199
+    {
200
+      //printf("srfc #%d %p 0x%08X\n",i,va_srfcs->srfc_used[i], va_srfcs->srfc_used[i] ? *va_srfcs->srfc_used[i] : -1);
201
+      if(va_surfaces->used[i] && (*va_surfaces->used[i] == va_surface_id))
202
+      {
203
+        va_surfaces->free[i] = va_surfaces->used[i];
204
+        va_surfaces->used[i] = NULL;
205
+        break;
206
+      }
207
+    }
208
+
209
+    av_frame->data[0] = NULL;
210
+    av_frame->data[1] = NULL;
211
+    av_frame->data[2] = NULL;
212
+    av_frame->data[3] = NULL;
213
+    return;
214
+  }
215
+
216
   if (av_frame->type == FF_BUFFER_TYPE_USER) {
217
     if ( av_frame->opaque ) {
218
-      vo_frame_t *img = (vo_frame_t *)av_frame->opaque;
219
-
220
+        vo_frame_t *img = (vo_frame_t *)av_frame->opaque;
221
+  
222
       img->free(img);
223
     }
224
 
225
@@ -283,13 +446,272 @@ static const int skip_loop_filter_enum_v
226
   AVDISCARD_ALL
227
 };
228
 
229
+static const char *VAProfile2string(VAProfile profile)
230
+{
231
+  switch(profile) {
232
+#define PROFILE(profile) \
233
+    case VAProfile##profile: return "VAProfile" #profile
234
+      PROFILE(MPEG2Simple);
235
+      PROFILE(MPEG2Main);
236
+      PROFILE(MPEG4Simple);
237
+      PROFILE(MPEG4AdvancedSimple);
238
+      PROFILE(MPEG4Main);
239
+      PROFILE(H264Baseline);
240
+      PROFILE(H264Main);
241
+      PROFILE(H264High);
242
+      PROFILE(VC1Simple);
243
+      PROFILE(VC1Main);
244
+      PROFILE(VC1Advanced);
245
+#undef PROFILE
246
+    default: break;
247
+  }
248
+  return "<unknown>";
249
+}
250
+
251
+static const char *VAEntrypoint2string(VAEntrypoint entrypoint)
252
+{
253
+  switch(entrypoint)
254
+  {
255
+#define ENTRYPOINT(entrypoint) \
256
+    case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint
257
+      ENTRYPOINT(VLD);
258
+      ENTRYPOINT(IZZ);
259
+      ENTRYPOINT(IDCT);
260
+      ENTRYPOINT(MoComp);
261
+      ENTRYPOINT(Deblocking);
262
+#undef ENTRYPOINT
263
+    default: break;
264
+  }
265
+  return "<unknown>";
266
+}
267
+
268
+static enum PixelFormat get_format(struct AVCodecContext *context, const enum PixelFormat *fmt)
269
+{
270
+    int i, profile;
271
+
272
+    for (i = 0; fmt[i] != PIX_FMT_NONE; i++) {
273
+        if (fmt[i] != PIX_FMT_VAAPI_VLD)
274
+            continue;
275
+
276
+        profile = get_profile(context->codec_id);
277
+
278
+        if (profile >= 0) {
279
+          VAStatus status;
280
+
281
+          status = init_vaapi(va_context, profile, context->width, context->height);
282
+
283
+          if( status == VA_STATUS_SUCCESS ) {
284
+
285
+            //context->draw_horiz_band = draw_slice;
286
+            context->draw_horiz_band = NULL;
287
+            context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
288
+            context->dsp_mask = FF_MM_FORCE | FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE;
289
+
290
+            va_context->vaapi_context->config_id   = va_context->va_config_id;
291
+            va_context->vaapi_context->context_id  = va_context->va_context_id;
292
+            context->hwaccel_context     = va_context->vaapi_context;
293
+            printf("init vaapi successfully\n");
294
+            va_context->use_vaapi = 1;
295
+            return fmt[i];
296
+          } else {
297
+            va_context->use_vaapi = 0;
298
+            printf("vaapi init error\n");
299
+          }
300
+        } else {
301
+          va_context->use_vaapi = 0;
302
+        }
303
+    }
304
+    return PIX_FMT_NONE;
305
+}
306
+
307
+static void close_vaapi(ff_vaapi_context_t *va_context) {
308
+  if (va_context->use_vaapi == 0);
309
+    return;
310
+
311
+  if(va_context->va_context_id) { 
312
+    if(va_context->va_image.image_id != VA_INVALID_ID ) { 
313
+      vaDestroyImage(va_context->va_display, va_context->va_image.image_id );
314
+    }
315
+    if(va_context->va_context_id != VA_INVALID_ID) {
316
+      vaDestroyContext(va_context->va_display, va_context->va_context_id);
317
+    }
318
+
319
+    int i = 0;
320
+    for( i = 0; i < va_context->va_surfaces.count; i++ ) {
321
+      if( va_context->va_surface_id[i] != VA_INVALID_SURFACE) {
322
+        vaDestroySurfaces(va_context->va_display, &va_context->va_surface_id[i], 1);
323
+      }
324
+    }
325
+
326
+    if(va_context->va_config_id)
327
+      vaDestroyConfig(va_context->va_display, va_context->va_config_id);
328
+
329
+    vaTerminate(va_context->va_display);
330
+    XCloseDisplay(va_context->display);
331
+
332
+    free(va_context->va_surfaces.free);
333
+    free(va_context->va_surfaces.used);
334
+    free(va_context->va_surface_id);
335
+    free(va_context->vaapi_context);
336
+    free(va_context);
337
+
338
+    va_context = NULL;
339
+  }
340
+}
341
+
342
+static VAStatus create_vaapi_image(struct ff_vaapi_context_s *va_context) {
343
+  int i;
344
+  int fmt_count = vaMaxNumImageFormats( va_context->va_display );
345
+  VAImageFormat *va_p_fmt = calloc( fmt_count, sizeof(*va_p_fmt) );
346
+  VAImageFormat va_fmt;
347
+
348
+  if( vaQueryImageFormats( va_context->va_display , va_p_fmt, &fmt_count ) ) {
349
+    free(va_p_fmt);
350
+    goto error;
351
+  }
352
+
353
+  for( i = 0; i < fmt_count; i++ ) {
354
+    if ( va_p_fmt[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
355
+         va_p_fmt[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ||
356
+         va_p_fmt[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) ) {
357
+         
358
+      if( vaCreateImage( va_context->va_display, &va_p_fmt[i], va_context->width, va_context->height, &va_context->va_image) ) {
359
+          va_context->va_image.image_id = VA_INVALID_ID;
360
+          continue;
361
+       }
362
+       if( vaGetImage(va_context->va_display, va_context->va_surface_id[0], 0, 0, 
363
+                      va_context->width, va_context->height, va_context->va_image.image_id) ) {
364
+         vaDestroyImage( va_context->va_display, va_context->va_image.image_id );
365
+         va_context->va_image.image_id = VA_INVALID_ID;
366
+         continue;
367
+       }
368
+       printf("found valid image format\n");
369
+       va_fmt = va_p_fmt[i];
370
+       break;
371
+    }
372
+  }
373
+  free(va_p_fmt);
374
+
375
+  if(va_context->va_image.image_id == VA_INVALID_ID)
376
+    goto error;
377
+
378
+  return VA_STATUS_SUCCESS;
379
+
380
+error:
381
+  return VA_STATUS_ERROR_UNKNOWN;
382
+}
383
+
384
+static VAStatus init_vaapi(struct ff_vaapi_context_s *va_context, int va_profile, int width, int height) {
385
+  size_t              i;
386
+  VAStatus            status = VA_STATUS_ERROR_UNKNOWN;
387
+  int                 surface_count   = NUM_SURFACES;
388
+  VAConfigAttrib      va_attrib;
389
+  int                 maj, min;
390
+  VAProfile           *va_profiles = NULL;
391
+  VAProfile           *va_profile_search = NULL;
392
+  int                 number_profiles;
393
+
394
+  va_context->width = width;
395
+  va_context->height = height;
396
+  va_context->va_profile = va_profile;
397
+
398
+  va_context->va_surfaces.free = NULL;
399
+  va_context->va_surfaces.used = NULL;
400
+
401
+  va_context->va_display = NULL;
402
+  va_context->va_config_id = VA_INVALID_ID;
403
+  va_context->va_context_id = VA_INVALID_ID;
404
+  va_context->va_image.image_id = VA_INVALID_ID;
405
+
406
+  va_context->display = XOpenDisplay(NULL);
407
+  if(!va_context->display)
408
+    goto error;
409
+
410
+  va_context->va_display = vaGetDisplay(va_context->display);
411
+  va_context->vaapi_context->display = va_context->va_display;
412
+
413
+  if(!va_context->va_display)
414
+    goto error;
415
+
416
+  if(vaInitialize(va_context->va_display, &maj, &min))
417
+    goto error;
418
+
419
+  printf("libva: %d.%d\n", maj, min);
420
+
421
+  printf("AvCodecContext w %d h %d\n", va_context->width, va_context->height);
422
+
423
+  memset( &va_attrib, 0, sizeof(va_attrib) );
424
+  va_attrib.type = VAConfigAttribRTFormat;
425
+
426
+  va_profiles = malloc(vaMaxNumProfiles(va_context->va_display) * sizeof(VAProfile));
427
+
428
+  if(vaQueryConfigProfiles(va_context->va_display, va_profiles, &number_profiles)) {
429
+    free(va_profiles);
430
+    goto error;
431
+  }
432
+
433
+  free(va_profiles);
434
+
435
+
436
+  va_profile_search = find_profile(va_profiles, number_profiles, va_profile);
437
+
438
+  if(!va_profile_search)
439
+    goto error;
440
+
441
+  printf("Profile: %d (%s) Entrypoint %d (%s)\n", va_context->va_profile, VAProfile2string(va_context->va_profile), VAEntrypointVLD, VAEntrypoint2string(VAEntrypointVLD));
442
+
443
+  if( vaGetConfigAttributes(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1) )
444
+    goto error;
445
+  
446
+  if( (va_attrib.value & VA_RT_FORMAT_YUV420) == 0 )
447
+    goto error;
448
+
449
+  if( vaCreateConfig(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1, &va_context->va_config_id) ) {
450
+    va_context->va_config_id = VA_INVALID_ID;
451
+    goto error;
452
+  }
453
+
454
+  if(va_context->va_surface_id == NULL) {
455
+    va_context->va_surface_id = malloc(sizeof(VASurfaceID) * surface_count);
456
+    va_context->va_surfaces.free = malloc(sizeof(VASurfaceID*) * surface_count);
457
+    va_context->va_surfaces.used = malloc(sizeof(VASurfaceID*) * surface_count);
458
+  }
459
+
460
+  if( vaCreateSurfaces(va_context->va_display, va_context->width, va_context->height, VA_RT_FORMAT_YUV420, surface_count, va_context->va_surface_id) )
461
+    goto error;
462
+
463
+  for(i = 0; i < surface_count; i++) {
464
+    va_context->va_surfaces.free[i] = &va_context->va_surface_id[i];
465
+    va_context->va_surfaces.used[i] = NULL;
466
+  }
467
+
468
+  va_context->va_surfaces.count = surface_count;
469
+
470
+  if(vaCreateContext(va_context->va_display, va_context->va_config_id, va_context->width, va_context->height,
471
+                     VA_PROGRESSIVE, va_context->va_surface_id, surface_count, &va_context->va_context_id) ) {
472
+    va_context->va_context_id = VA_INVALID_ID;
473
+    goto error;
474
+  }
475
+
476
+  status = create_vaapi_image(va_context);
477
+  if(status != VA_STATUS_SUCCESS)
478
+    goto error;
479
+
480
+  va_context->use_vaapi = 1;
481
+  return VA_STATUS_SUCCESS;
482
+
483
+error:
484
+  va_context->use_vaapi = 0;
485
+  return VA_STATUS_ERROR_UNKNOWN;
486
+}
487
+
488
 static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) {
489
   size_t i;
490
 
491
   /* find the decoder */
492
   this->codec = NULL;
493
 
494
-  for(i = 0; i < sizeof(ff_video_lookup)/sizeof(ff_codec_t); i++)
495
+  for(i = 0; i < sizeof(ff_video_lookup)/sizeof(ff_codec_t); i++) {
496
     if(ff_video_lookup[i].type == codec_type) {
497
       pthread_mutex_lock(&ffmpeg_lock);
498
       this->codec = avcodec_find_decoder(ff_video_lookup[i].id);
499
@@ -298,6 +720,8 @@ static void init_video_codec (ff_video_d
500
                             ff_video_lookup[i].name);
501
       break;
502
     }
503
+  }
504
+  
505
 
506
   if (!this->codec) {
507
     xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
508
@@ -311,9 +735,11 @@ static void init_video_codec (ff_video_d
509
 
510
   this->context->width = this->bih.biWidth;
511
   this->context->height = this->bih.biHeight;
512
+
513
   this->context->stream_codec_tag = this->context->codec_tag =
514
     _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC);
515
 
516
+  //av_init_packet(&this->av_pkt);
517
 
518
   /* Some codecs (eg rv10) copy flags in init so it's necessary to set
519
    * this flag here in case we are going to use direct rendering */
520
@@ -323,7 +749,6 @@ static void init_video_codec (ff_video_d
521
 
522
   if (this->class->choose_speed_over_accuracy)
523
     this->context->flags2 |= CODEC_FLAG2_FAST;
524
-
525
   pthread_mutex_lock(&ffmpeg_lock);
526
   if (avcodec_open (this->context, this->codec) < 0) {
527
     pthread_mutex_unlock(&ffmpeg_lock);
528
@@ -337,7 +762,6 @@ static void init_video_codec (ff_video_d
529
 
530
   if (this->codec->id == CODEC_ID_VC1 &&
531
       (!this->bih.biWidth || !this->bih.biHeight)) {
532
-    /* VC1 codec must be re-opened with correct width and height. */
533
     avcodec_close(this->context);
534
 
535
     if (avcodec_open (this->context, this->codec) < 0) {
536
@@ -390,6 +814,13 @@ static void init_video_codec (ff_video_d
537
     xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
538
 	    _("ffmpeg_video_dec: direct rendering enabled\n"));
539
   }
540
+  if( this->class->enable_vaapi && !this->is_mpeg12) {
541
+    this->context->get_buffer = get_buffer;
542
+    this->context->reget_buffer = get_buffer;
543
+    this->context->release_buffer = release_buffer;
544
+    this->context->get_format = get_format;
545
+    this->context->thread_count = 1;
546
+  }
547
 #endif
548
 
549
   /* flag for interlaced streams */
550
@@ -413,7 +844,13 @@ static void init_video_codec (ff_video_d
551
       this->frame_flags |= VO_INTERLACED_FLAG;
552
       break;
553
   }
554
+}
555
+
556
 
557
+static void enable_vaapi(void *user_data, xine_cfg_entry_t *entry) {
558
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
559
+
560
+  class->enable_vaapi = entry->num_value;
561
 }
562
 
563
 static void choose_speed_over_accuracy_cb(void *user_data, xine_cfg_entry_t *entry) {
564
@@ -542,6 +979,36 @@ static int ff_handle_mpeg_sequence(ff_vi
565
   return 1;
566
 }
567
 
568
+/*
569
+*/
570
+
571
+static int nv12_to_yv12(ff_video_decoder_t *this, uint8_t  *data, int len, vo_frame_t *img) {
572
+    unsigned int Y_size  = img->width * this->bih.biHeight;
573
+    unsigned int UV_size = img->width * this->bih.biHeight / 4;
574
+    unsigned int idx;
575
+    unsigned char *dst_Y = img->base[0];
576
+    unsigned char *dst_U = img->base[1];
577
+    unsigned char *dst_V = img->base[2];
578
+    unsigned char *src   = data + Y_size;
579
+
580
+    // sanity check raw stream
581
+    if ( (len != (Y_size + (UV_size<<1))) ) {
582
+        printf("hmblck: Image size inconsistent with data size.\n");
583
+        return 0;
584
+    }
585
+
586
+    // luma data is easy, just copy it
587
+    xine_fast_memcpy(dst_Y, data, Y_size);
588
+
589
+    // chroma data is interlaced UVUV... so deinterlace it
590
+    for(idx=0; idx<UV_size; idx++ ) {
591
+        *(dst_U + idx) = *(src + (idx<<1) + 0); 
592
+        *(dst_V + idx) = *(src + (idx<<1) + 1);
593
+    }
594
+
595
+    return 1;
596
+}
597
+
598
 static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
599
   int         y;
600
   uint8_t    *dy, *du, *dv, *sy, *su, *sv;
601
@@ -551,6 +1018,49 @@ static void ff_convert_frame(ff_video_de
602
     printf ("frame format == %08x\n", this->debug_fmt = this->context->pix_fmt);
603
 #endif
604
 
605
+  if(this->context->pix_fmt == PIX_FMT_VAAPI_VLD && va_context->va_image.image_id != VA_INVALID_ID) {
606
+    void *p_base;
607
+    const uint32_t fourcc = va_context->va_image.format.fourcc;
608
+    VAStatus status;
609
+
610
+    if( !vaGetImage( va_context->va_display, (VASurfaceID)(size_t)this->av_frame->data[3],
611
+                            0, 0, img->width, this->bih.biHeight, va_context->va_image.image_id) ) {
612
+
613
+      status = vaMapBuffer( va_context->va_display, va_context->va_image.buf, &p_base ) ;
614
+      if ( status == VA_STATUS_SUCCESS ) {
615
+        if( fourcc == VA_FOURCC('Y','V','1','2') ||
616
+          fourcc == VA_FOURCC('I','4','2','0') ) {
617
+
618
+            lprintf("VAAPI YV12 image\n");
619
+
620
+            yv12_to_yv12(
621
+            /* Y */
622
+              (uint8_t*)p_base, img->width,
623
+              img->base[0], img->pitches[0],
624
+            /* U */
625
+              (uint8_t*)p_base + (img->width * img->height * 5/4), img->width/2,
626
+              img->base[1], img->pitches[1],
627
+            /* V */
628
+              (uint8_t*)p_base + (img->width * img->height), img->width/2,
629
+              img->base[2], img->pitches[2],
630
+            /* width x height */
631
+              img->width, img->height);
632
+
633
+        }
634
+        if( fourcc == VA_FOURCC('N','V','1','2') ) {
635
+
636
+          lprintf("VAAPI NV12 image\n");
637
+
638
+          nv12_to_yv12(this, (uint8_t*)p_base, va_context->va_image.data_size,  img);
639
+
640
+        }
641
+
642
+        status = vaUnmapBuffer( va_context->va_display, va_context->va_image.buf );
643
+      }
644
+    }
645
+    return;
646
+  }
647
+
648
   dy = img->base[0];
649
   du = img->base[1];
650
   dv = img->base[2];
651
@@ -1022,6 +1532,11 @@ static void ff_handle_mpeg12_buffer (ff_
652
 
653
   lprintf("handle_mpeg12_buffer\n");
654
 
655
+  if (buf->decoder_flags & BUF_FLAG_FRAME_START) {
656
+    lprintf("BUF_FLAG_FRAME_START\n");
657
+    this->size = 0;
658
+  }
659
+
660
   while ((size > 0) || (flush == 1)) {
661
 
662
     uint8_t *current;
663
@@ -1307,10 +1822,19 @@ static void ff_handle_buffer (ff_video_d
664
         this->context->hurry_up = (this->skipframes > 0);
665
 
666
         lprintf("buffer size: %d\n", this->size);
667
+
668
+        //this->av_pkt.size = this->size;
669
+        //this->av_pkt.data = &chunk_buf[offset];
670
+        //this->av_pkt.data = this->buf;
671
+
672
+        //len = avcodec_decode_video2 (this->context, this->av_frame, &got_picture, &this->av_pkt);
673
+
674
         len = avcodec_decode_video (this->context, this->av_frame,
675
                                     &got_picture, &chunk_buf[offset],
676
                                     this->size);
677
 
678
+        //av_free_packet(&this->av_pkt);
679
+
680
 #ifdef AVCODEC_HAS_REORDERED_OPAQUE
681
         /* reset consumed pts value */
682
         this->context->reordered_opaque = ff_tag_pts(this, 0);
683
@@ -1355,47 +1879,48 @@ static void ff_handle_buffer (ff_video_d
684
 
685
       /* aspect ratio provided by ffmpeg, override previous setting */
686
       if ((this->aspect_ratio_prio < 2) &&
687
-	  av_cmp_q(this->context->sample_aspect_ratio, avr00)) {
688
+        av_cmp_q(this->context->sample_aspect_ratio, avr00)) {
689
 
690
         if (!this->bih.biWidth || !this->bih.biHeight) {
691
           this->bih.biWidth  = this->context->width;
692
           this->bih.biHeight = this->context->height;
693
         }
694
 
695
-	this->aspect_ratio = av_q2d(this->context->sample_aspect_ratio) *
696
-	  (double)this->bih.biWidth / (double)this->bih.biHeight;
697
-	this->aspect_ratio_prio = 2;
698
-	lprintf("ffmpeg aspect ratio: %f\n", this->aspect_ratio);
699
-	set_stream_info(this);
700
+	      this->aspect_ratio = av_q2d(this->context->sample_aspect_ratio) *
701
+	                                 (double)this->bih.biWidth / (double)this->bih.biHeight;
702
+	      this->aspect_ratio_prio = 2;
703
+	      lprintf("ffmpeg aspect ratio: %f\n", this->aspect_ratio);
704
+	      set_stream_info(this);
705
       }
706
 
707
       if (got_picture && this->av_frame->data[0]) {
708
         /* got a picture, draw it */
709
         got_one_picture = 1;
710
+
711
         if(!this->av_frame->opaque) {
712
-	  /* indirect rendering */
713
+	        /* indirect rendering */
714
 
715
-	  /* initialize the colorspace converter */
716
-	  if (!this->cs_convert_init) {
717
-	    if ((this->context->pix_fmt == PIX_FMT_RGB32) ||
718
-	        (this->context->pix_fmt == PIX_FMT_RGB565) ||
719
-	        (this->context->pix_fmt == PIX_FMT_RGB555) ||
720
-	        (this->context->pix_fmt == PIX_FMT_BGR24) ||
721
-	        (this->context->pix_fmt == PIX_FMT_RGB24) ||
722
-	        (this->context->pix_fmt == PIX_FMT_PAL8)) {
723
-	      this->output_format = XINE_IMGFMT_YUY2;
724
-	      init_yuv_planes(&this->yuv, (this->bih.biWidth + 15) & ~15, this->bih.biHeight);
725
-	      this->yuv_init = 1;
726
-	    }
727
-	    this->cs_convert_init = 1;
728
-	  }
729
-
730
-	  if (this->aspect_ratio_prio == 0) {
731
-	    this->aspect_ratio = (double)this->bih.biWidth / (double)this->bih.biHeight;
732
-	    this->aspect_ratio_prio = 1;
733
-	    lprintf("default aspect ratio: %f\n", this->aspect_ratio);
734
-	    set_stream_info(this);
735
-	  }
736
+	        /* initialize the colorspace converter */
737
+	        if (!this->cs_convert_init) {
738
+	          if ((this->context->pix_fmt == PIX_FMT_RGB32) ||
739
+	            (this->context->pix_fmt == PIX_FMT_RGB565) ||
740
+	            (this->context->pix_fmt == PIX_FMT_RGB555) ||
741
+	            (this->context->pix_fmt == PIX_FMT_BGR24) ||
742
+	            (this->context->pix_fmt == PIX_FMT_RGB24) ||
743
+	            (this->context->pix_fmt == PIX_FMT_PAL8)) {
744
+	              this->output_format = XINE_IMGFMT_YUY2;
745
+	              init_yuv_planes(&this->yuv, (this->bih.biWidth + 15) & ~15, this->bih.biHeight);
746
+	              this->yuv_init = 1;
747
+	          }
748
+	          this->cs_convert_init = 1;
749
+	        }
750
+
751
+	        if (this->aspect_ratio_prio == 0) {
752
+	          this->aspect_ratio = (double)this->bih.biWidth / (double)this->bih.biHeight;
753
+	          this->aspect_ratio_prio = 1;
754
+	          lprintf("default aspect ratio: %f\n", this->aspect_ratio);
755
+	          set_stream_info(this);
756
+	        }
757
 
758
           /* xine-lib expects the framesize to be a multiple of 16x16 (macroblock) */
759
           img = this->stream->video_out->get_frame (this->stream->video_out,
760
@@ -1436,7 +1961,7 @@ static void ff_handle_buffer (ff_video_d
761
                         this->av_frame->pict_type);
762
 
763
         } else if (!this->av_frame->opaque) {
764
-	  /* colorspace conversion or copy */
765
+	        /* colorspace conversion or copy */
766
           ff_convert_frame(this, img);
767
         }
768
 
769
@@ -1524,6 +2049,15 @@ static void ff_decode_data (video_decode
770
     _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, (this->reported_video_step = this->video_step));
771
   }
772
 
773
+  int codec_type = buf->type & 0xFFFF0000;
774
+  if (codec_type == BUF_VIDEO_MPEG) {
775
+    this->is_mpeg12 = 1;
776
+    if ( this->mpeg_parser == NULL ) {
777
+      this->mpeg_parser = calloc(1, sizeof(mpeg_parser_t));
778
+      mpeg_parser_init(this->mpeg_parser);
779
+    }
780
+  }
781
+
782
   if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
783
 
784
     ff_handle_preview_buffer(this, buf);
785
@@ -1541,24 +2075,24 @@ static void ff_decode_data (video_decode
786
       ff_handle_header_buffer(this, buf);
787
 
788
       if (buf->decoder_flags & BUF_FLAG_ASPECT) {
789
-	if (this->aspect_ratio_prio < 3) {
790
-	  this->aspect_ratio = (double)buf->decoder_info[1] / (double)buf->decoder_info[2];
791
-	  this->aspect_ratio_prio = 3;
792
-	  lprintf("aspect ratio: %f\n", this->aspect_ratio);
793
-	  set_stream_info(this);
794
-	}
795
+      	if (this->aspect_ratio_prio < 3) {
796
+          this->aspect_ratio = (double)buf->decoder_info[1] / (double)buf->decoder_info[2];
797
+          this->aspect_ratio_prio = 3;
798
+          lprintf("aspect ratio: %f\n", this->aspect_ratio);
799
+          set_stream_info(this);
800
+        }
801
       }
802
 
803
     } else {
804
 
805
       /* decode */
806
       if (buf->pts)
807
-	this->pts = buf->pts;
808
+      	this->pts = buf->pts;
809
 
810
       if (this->is_mpeg12) {
811
-	ff_handle_mpeg12_buffer(this, buf);
812
+	      ff_handle_mpeg12_buffer(this, buf);
813
       } else {
814
-	ff_handle_buffer(this, buf);
815
+	      ff_handle_buffer(this, buf);
816
       }
817
 
818
     }
819
@@ -1637,6 +2171,8 @@ static void ff_dispose (video_decoder_t 
820
 
821
   lprintf ("ff_dispose\n");
822
 
823
+  close_vaapi(va_context);
824
+
825
   if (this->decoder_ok) {
826
     xine_list_iterator_t it;
827
     AVFrame *av_frame;
828
@@ -1728,10 +2264,31 @@ static video_decoder_t *ff_video_open_pl
829
 
830
   this->dr1_frames        = xine_list_new();
831
 
832
+  va_context              = calloc(1, sizeof(ff_vaapi_context_t));
833
+  va_context->vaapi_context = calloc(1, sizeof(struct vaapi_context));
834
+
835
 #ifdef LOG
836
   this->debug_fmt = -1;
837
 #endif
838
 
839
+  this->class->enable_vaapi = this->class->xine->config->register_bool(this->class->xine->config, "video.processing.ffmpeg_enable_vaapi", 1,
840
+      _("Enable usage of VAAPI"),
841
+      _("Let you enable the usage of VAAPI.\n"),
842
+      10, enable_vaapi, this->class);
843
+
844
+#ifdef INIT_ERROR_HACK
845
+  if ((init_vaapi(va_context, VAProfileH264High, 1280, 720) == VA_STATUS_SUCCESS )) {
846
+    close_vaapi(va_context);
847
+  } else {
848
+    this->class->enable_vaapi = 0;
849
+    xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled in config, but output video out driver does not support vaapi.\n"));
850
+  }
851
+  free(va_context->vaapi_context);
852
+  free(va_context);
853
+  va_context              = calloc(1, sizeof(ff_vaapi_context_t));
854
+  va_context->vaapi_context = calloc(1, sizeof(struct vaapi_context));
855
+#endif
856
+
857
   return &this->video_decoder;
858
 }
859
 
860
diff -Naur xine-lib-1.1.19.orig/src/combined/ffmpeg/Makefile.am xine-lib-1.1.19/src/combined/ffmpeg/Makefile.am
861
--- xine-lib-1.1.19.orig/src/combined/ffmpeg/Makefile.am	2010-03-09 23:17:05.000000000 +0100
862
+++ xine-lib-1.1.19/src/combined/ffmpeg/Makefile.am	2010-10-14 14:49:01.000000000 +0200
863
@@ -43,7 +43,7 @@
864
 
865
 xineplug_decode_ff_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS)
866
 xineplug_decode_ff_la_LDFLAGS = $(xineplug_ldflags) $(IMPURE_TEXT_LDFLAGS)
867
-xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm $(ZLIB_LIBS) \
868
+xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm -lva-x11 -lva -lX11 $(ZLIB_LIBS) \
869
 	$(link_ffmpeg) $(PTHREAD_LIBS) $(LTLIBINTL)
870
 
871
 xineplug_decode_dvaudio_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS)

Return to bug 155871