Subversion Repositories Kolibri OS

Rev

Rev 6298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6117 serge 1
#include 
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
#include 
9
#include 
10
#include 
11
#include 
6298 serge 12
#include 
6117 serge 13
#include 
14
#include "winlib/winlib.h"
15
#include "fplay.h"
16
 
17
struct hw_profile
18
{
19
    enum AVCodecID av_codec;
20
    int ff_profile;
6133 serge 21
    VAProfile va_profile;
6117 serge 22
};
23
 
24
 
25
#define ENTER()   printf("enter %s\n",__FUNCTION__)
26
#define LEAVE()   printf("leave %s\n",__FUNCTION__)
27
#define FAIL()    printf("fail %s\n",__FUNCTION__)
28
 
29
 
30
#if DEBUG
31
# define D(x) x
32
# define bug printf
33
#else
34
# define D(x)
35
#endif
36
 
37
#undef  ARRAY_ELEMS
38
#define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
39
 
40
static int drm_fd = 0;
41
static struct vaapi_context *v_context;
42
 
6136 serge 43
static VASurfaceID v_surface_id[16];
6117 serge 44
 
45
#define HAS_HEVC VA_CHECK_VERSION(0, 38, 0)
46
#define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0))
47
 
48
#define PE(av_codec_id, ff_profile, vdp_profile)                \
49
    {AV_CODEC_ID_ ## av_codec_id, FF_PROFILE_ ## ff_profile,    \
50
     VAProfile ## vdp_profile}
51
 
6133 serge 52
static const struct hw_profile hw_profiles[] = {
6117 serge 53
    PE(MPEG2VIDEO,  MPEG2_MAIN,         MPEG2Main),
54
    PE(MPEG2VIDEO,  MPEG2_SIMPLE,       MPEG2Simple),
55
    PE(MPEG4,       MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple),
56
    PE(MPEG4,       MPEG4_MAIN,         MPEG4Main),
57
    PE(MPEG4,       MPEG4_SIMPLE,       MPEG4Simple),
58
    PE(H264,        H264_HIGH,          H264High),
59
    PE(H264,        H264_MAIN,          H264Main),
6298 serge 60
    PE(H264,        H264_CONSTRAINED_BASELINE, H264ConstrainedBaseline),
6117 serge 61
    PE(VC1,         VC1_ADVANCED,       VC1Advanced),
62
    PE(VC1,         VC1_MAIN,           VC1Main),
63
    PE(VC1,         VC1_SIMPLE,         VC1Simple),
64
    PE(WMV3,        VC1_ADVANCED,       VC1Advanced),
65
    PE(WMV3,        VC1_MAIN,           VC1Main),
66
    PE(WMV3,        VC1_SIMPLE,         VC1Simple),
67
#if HAS_HEVC
68
    PE(HEVC,        HEVC_MAIN,          HEVCMain),
69
    PE(HEVC,        HEVC_MAIN_10,       HEVCMain10),
70
#endif
71
#if HAS_VP9
72
    PE(VP9,         VP9_0,              VP9Profile0),
73
#endif
74
    {0}
75
};
76
 
77
int va_check_codec_support(enum AVCodecID id)
78
{
6133 serge 79
    for (int n = 0; hw_profiles[n].av_codec; n++) {
80
        if (hw_profiles[n].av_codec == id)
6117 serge 81
            return 1;
82
    }
83
    return 0;
84
}
85
 
86
static int vaapi_check_status(VAStatus status, const char *msg)
87
{
88
    if (status != VA_STATUS_SUCCESS) {
89
        fprintf(stderr, "[%s] %s: %s\n", PACKAGE_NAME, msg, vaErrorStr(status));
90
        return 0;
91
    }
92
    return 1;
93
};
94
 
95
static const char *string_of_VADisplayAttribType(VADisplayAttribType type)
96
{
97
    switch (type) {
98
#define TYPE(type) \
99
        case VADisplayAttrib##type: return "VADisplayAttrib" #type
100
        TYPE(Brightness);
101
        TYPE(Contrast);
102
        TYPE(Hue);
103
        TYPE(Saturation);
104
        TYPE(BackgroundColor);
105
#if !VA_CHECK_VERSION(0,34,0)
106
        TYPE(DirectSurface);
107
#endif
108
#if VA_CHECK_VERSION(0,32,0)
109
        TYPE(Rotation);
110
#endif
111
#undef TYPE
112
    default: break;
113
    }
114
    return "";
115
}
116
 
117
static const char *string_of_VAProfile(VAProfile profile)
118
{
119
    switch (profile) {
120
#define PROFILE(profile) \
121
        case VAProfile##profile: return "VAProfile" #profile
122
        PROFILE(MPEG2Simple);
123
        PROFILE(MPEG2Main);
124
        PROFILE(MPEG4Simple);
125
        PROFILE(MPEG4AdvancedSimple);
126
        PROFILE(MPEG4Main);
127
#if VA_CHECK_VERSION(0,32,0)
128
        PROFILE(JPEGBaseline);
129
        PROFILE(H263Baseline);
130
        PROFILE(H264ConstrainedBaseline);
131
#endif
132
        PROFILE(H264Baseline);
133
        PROFILE(H264Main);
134
        PROFILE(H264High);
135
        PROFILE(VC1Simple);
136
        PROFILE(VC1Main);
137
        PROFILE(VC1Advanced);
138
#undef PROFILE
139
    default: break;
140
    }
141
    return "";
142
}
143
 
144
static const char *string_of_VAEntrypoint(VAEntrypoint entrypoint)
145
{
146
    switch (entrypoint) {
147
#define ENTRYPOINT(entrypoint) \
148
        case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint
149
        ENTRYPOINT(VLD);
150
        ENTRYPOINT(IZZ);
151
        ENTRYPOINT(IDCT);
152
        ENTRYPOINT(MoComp);
153
        ENTRYPOINT(Deblocking);
154
#if VA_CHECK_VERSION(0,32,0)
155
        ENTRYPOINT(EncSlice);
156
        ENTRYPOINT(EncPicture);
157
#endif
158
#undef ENTRYPOINT
159
    default: break;
160
    }
161
    return "";
162
}
163
 
164
 
6121 serge 165
void *vaapi_init(VADisplay display)
6117 serge 166
{
167
    struct vaapi_context *vaapi;
168
    int major_version, minor_version;
169
    int i, num_display_attrs, max_display_attrs;
170
    VADisplayAttribute *display_attrs = NULL;
171
    VAStatus status;
172
 
173
    if (v_context)
174
        return 0;
175
 
176
    if (!display)
177
        goto error;
178
    D(bug("VA display %p\n", display));
179
 
180
    status = vaInitialize(display, &major_version, &minor_version);
181
    if (!vaapi_check_status(status, "vaInitialize()"))
182
        goto error;
183
    D(bug("VA API version %d.%d\n", major_version, minor_version));
184
 
185
    max_display_attrs = vaMaxNumDisplayAttributes(display);
186
    display_attrs = malloc(max_display_attrs * sizeof(display_attrs[0]));
187
    if (!display_attrs)
188
        goto error;
189
 
190
    num_display_attrs = 0; /* XXX: workaround old GMA500 bug */
191
    status = vaQueryDisplayAttributes(display, display_attrs, &num_display_attrs);
192
    if (!vaapi_check_status(status, "vaQueryDisplayAttributes()"))
193
        goto error;
194
    D(bug("%d display attributes available\n", num_display_attrs));
195
    for (i = 0; i < num_display_attrs; i++) {
196
        VADisplayAttribute * const display_attr = &display_attrs[i];
197
        D(bug("  %-32s (%s/%s) min %d max %d value 0x%x\n",
198
              string_of_VADisplayAttribType(display_attr->type),
199
              (display_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) ? "get" : "---",
200
              (display_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) ? "set" : "---",
201
              display_attr->min_value,
202
              display_attr->max_value,
203
              display_attr->value));
204
    }
205
 
206
    if ((vaapi = calloc(1, sizeof(*vaapi))) == NULL)
207
        goto error;
6133 serge 208
    vaapi->display    = display;
209
    vaapi->config_id  = VA_INVALID_ID;
210
    vaapi->context_id = VA_INVALID_ID;
6117 serge 211
 
212
    v_context = vaapi;
213
 
6121 serge 214
    return vaapi;
6117 serge 215
 
216
error:
217
    free(display_attrs);
6121 serge 218
    return NULL;
6117 serge 219
}
220
 
221
static int has_profile(struct vaapi_context *vaapi, VAProfile profile)
222
{
223
    VAProfile *profiles;
224
    int        n_profiles;
6298 serge 225
    size_t size;
6117 serge 226
    VAStatus   status;
227
    int i;
228
 
6298 serge 229
    size = vaMaxNumProfiles(vaapi->display) * sizeof(VAProfile);
6117 serge 230
 
6298 serge 231
    profiles = alloca(size);
232
    memset(profiles, 0, size);
233
 
6117 serge 234
    status = vaQueryConfigProfiles(vaapi->display,profiles,&n_profiles);
235
 
236
    if (!vaapi_check_status(status, "vaQueryConfigProfiles()"))
237
        return 0;
238
 
239
    D(bug("%d profiles available\n", n_profiles));
240
 
241
    for (i = 0; i < n_profiles; i++)
242
    {
243
        if (profiles[i] == profile)
244
            return 1;
245
    }
246
    return 0;
247
}
248
 
249
static int has_entrypoint(struct vaapi_context *vaapi, VAProfile profile, VAEntrypoint entrypoint)
250
{
251
    VAEntrypoint *entrypoints;
252
    int           n_entrypoints;
6298 serge 253
    size_t size;
6117 serge 254
    VAStatus      status;
255
    int i;
256
 
6298 serge 257
    size = vaMaxNumEntrypoints(vaapi->display) * sizeof(VAEntrypoint);
6117 serge 258
 
6298 serge 259
    entrypoints = alloca(size);
260
    memset(entrypoints, 0, size);
261
 
6117 serge 262
    status = vaQueryConfigEntrypoints(vaapi->display, profile,
263
                                      entrypoints, &n_entrypoints);
264
    if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()"))
265
        return 0;
266
 
267
    D(bug("%d entrypoints available for %s\n", n_entrypoints,
268
          string_of_VAProfile(profile)));
269
 
270
    for (i = 0; i < n_entrypoints; i++)
271
    {
272
        if (entrypoints[i] == entrypoint)
273
            return 1;
274
    }
275
    return 0;
276
}
277
 
6136 serge 278
static int vaapi_init_decoder(vst_t *vst,VAProfile profile,
279
                              VAEntrypoint entrypoint,
280
                              unsigned int picture_width,
281
                              unsigned int picture_height)
6117 serge 282
{
283
    struct vaapi_context* const vaapi = v_context;
284
    VAConfigAttrib attrib;
285
    VAConfigID  config_id = VA_INVALID_ID;
286
    VAContextID context_id = VA_INVALID_ID;
287
    VAStatus status;
288
 
289
ENTER();
6298 serge 290
 
291
    printf("%s profile %x width:%d height:%d\n",
292
            __FUNCTION__, profile, picture_width, picture_height);
293
 
6117 serge 294
    if (!vaapi)
295
    {
296
        FAIL();
297
        return -1;
298
    };
299
 
300
    if (!has_profile(vaapi, profile))
301
    {
302
        FAIL();
303
        return -1;
304
    };
305
 
306
    if (!has_entrypoint(vaapi, profile, entrypoint))
307
    {
308
        FAIL();
309
        return -1;
310
    };
311
 
312
    if (vaapi->config_id != VA_INVALID_ID)
313
        vaDestroyConfig(vaapi->display, vaapi->config_id);
314
 
315
    attrib.type = VAConfigAttribRTFormat;
316
 
317
    printf("vaGetConfigAttributes\n");
318
    status = vaGetConfigAttributes(vaapi->display, profile, entrypoint,
319
                                   &attrib, 1);
320
    if (!vaapi_check_status(status, "vaGetConfigAttributes()"))
321
    {
322
        FAIL();
323
        return -1;
324
    }
325
 
326
    if ((attrib.value & VA_RT_FORMAT_YUV420) == 0)
327
    {
328
        printf("Chroma format not supported.\n");
329
        FAIL();
330
        return -1;
331
    };
332
 
333
    printf("vaCreateConfig\n");
334
    status = vaCreateConfig(vaapi->display, profile, entrypoint,
335
                            &attrib, 1, &config_id);
336
    if (!vaapi_check_status(status, "vaCreateConfig()"))
337
    {
338
        FAIL();
339
        return -1;
340
    }
341
 
342
    printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
343
    status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
6144 serge 344
                              v_surface_id,vst->decoder->nframes,NULL,0);
6117 serge 345
    if (!vaapi_check_status(status, "vaCreateSurfaces()"))
346
    {
347
        FAIL();
348
        return -1;
349
    };
350
    {
351
        VAImage vaimage;
352
        VABufferInfo info = {0};
353
 
354
        vaDeriveImage(vaapi->display,v_surface_id[0],&vaimage);
355
        printf("vaDeriveImage: %x  fourcc: %x\n"
356
               "offset0: %d pitch0: %d\n"
357
               "offset1: %d pitch1: %d\n"
358
               "offset2: %d pitch2: %d\n",
359
                vaimage.buf, vaimage.format.fourcc,
360
                vaimage.offsets[0],vaimage.pitches[0],
361
                vaimage.offsets[1],vaimage.pitches[1],
362
                vaimage.offsets[2],vaimage.pitches[2]);
363
 
364
        info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
365
        vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info);
366
        printf("vaAcquireBufferHandle: %x type: %x\n"
367
                "mem type: %x mem size: %x\n",
368
                info.handle, info.type, info.mem_type, info.mem_size);
369
 
370
        vaReleaseBufferHandle(vaapi->display, vaimage.buf);
371
 
372
        vaDestroyImage(vaapi->display,vaimage.image_id);
373
    };
374
 
375
    printf("vaCreateContext %dx%d\n",picture_width,picture_height);
376
    status = vaCreateContext(vaapi->display, config_id,
377
                             picture_width, picture_height,
378
                             VA_PROGRESSIVE,
6144 serge 379
                             v_surface_id, vst->decoder->nframes,
6117 serge 380
                             &context_id);
381
    if (!vaapi_check_status(status, "vaCreateContext()"))
382
    {
383
        FAIL();
384
        return -1;
385
    };
386
 
6133 serge 387
    vaapi->config_id  = config_id;
388
    vaapi->context_id = context_id;
6117 serge 389
    LEAVE();
390
    return 0;
391
}
392
 
393
 
394
static enum PixelFormat get_format(struct AVCodecContext *avctx,
395
                                   const enum AVPixelFormat *fmt)
396
{
6136 serge 397
    vst_t *vst = (vst_t*)avctx->opaque;
6298 serge 398
    VAProfile profile = avctx->profile;
399
    enum AVCodecID codec = avctx->codec_id;
6117 serge 400
 
6298 serge 401
    if (codec == AV_CODEC_ID_H264)
402
    {
403
        if(profile == FF_PROFILE_H264_BASELINE)
404
            profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
405
    };
406
 
6438 serge 407
    if(avctx->hwaccel_context != NULL &&
408
       (vst->codec_id != codec ||
409
       vst->codec_profile != profile))
410
    {
411
        struct decoder* decoder = vst->decoder;
412
 
413
        printf("\n%s codec changed!!!\n"
414
               "old id %d profile %x new id %d profile %x\n",
415
                __FUNCTION__, vst->codec_id, vst->codec_profile,
416
                codec, profile);
417
 
418
        for(int i = 0; i < decoder->nframes; i++)
419
        {
420
            vframe_t *vframe = &decoder->vframes[i];
421
            vframe->format   = AV_PIX_FMT_NONE;
422
        };
423
    }
424
 
425
    printf("\n%s codec %d profile %x\n", __FUNCTION__,avctx->codec_id, avctx->profile);
426
 
6133 serge 427
    for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
428
    {
6117 serge 429
        if (fmt[i] != AV_PIX_FMT_VAAPI_VLD)
430
            continue;
431
 
6133 serge 432
        for (int n = 0; hw_profiles[n].av_codec; n++)
433
        {
434
            if (hw_profiles[n].av_codec   == codec &&
6298 serge 435
                hw_profiles[n].ff_profile == profile)
6117 serge 436
            {
6133 serge 437
                profile = hw_profiles[n].va_profile;
6136 serge 438
                if (vaapi_init_decoder(vst, profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
6133 serge 439
                {
440
                    avctx->hwaccel_context = v_context;
6438 serge 441
                    vst->codec_id = codec;
442
                    vst->codec_profile = profile;
6298 serge 443
                    printf("%s format: %x\n",__FUNCTION__, fmt[i]);
444
                    return fmt[i];
6133 serge 445
                }
6117 serge 446
            }
447
        }
6133 serge 448
 
6117 serge 449
    }
6298 serge 450
    printf("%s format PIX_FMT_NONE\n",__FUNCTION__);
6117 serge 451
    return PIX_FMT_NONE;
452
}
453
 
454
struct av_surface
455
{
456
    int         w;
457
    int         h;
458
    VASurfaceID id;
459
};
460
 
461
static void av_release_buffer(void *opaque, uint8_t *data)
462
{
463
}
464
 
465
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
466
{
6298 serge 467
    static struct av_surface avsurface;
6118 serge 468
    vst_t *vst = (vst_t*)avctx->opaque;
6133 serge 469
    void *surface;
6117 serge 470
 
6144 serge 471
    surface = (void *)(uintptr_t)v_surface_id[vst->decoder->active_frame->index];
6133 serge 472
 
6117 serge 473
    pic->data[3] = surface;
474
 
6298 serge 475
    pic->buf[0] = av_buffer_create((uint8_t*)&avsurface, sizeof(avsurface),
476
                                    av_release_buffer, avctx,
477
                                    AV_BUFFER_FLAG_READONLY);
6117 serge 478
    return 0;
479
}
480
 
481
 
6133 serge 482
#define EGL_TEXTURE_Y_U_V_WL            0x31D7
483
#define EGL_TEXTURE_Y_UV_WL             0x31D8
484
#define EGL_TEXTURE_Y_XUXV_WL           0x31D9
6117 serge 485
 
6133 serge 486
enum wl_drm_format {
487
    WL_DRM_FORMAT_C8 = 0x20203843,
488
    WL_DRM_FORMAT_RGB332 = 0x38424752,
489
    WL_DRM_FORMAT_BGR233 = 0x38524742,
490
    WL_DRM_FORMAT_XRGB4444 = 0x32315258,
491
    WL_DRM_FORMAT_XBGR4444 = 0x32314258,
492
    WL_DRM_FORMAT_RGBX4444 = 0x32315852,
493
    WL_DRM_FORMAT_BGRX4444 = 0x32315842,
494
    WL_DRM_FORMAT_ARGB4444 = 0x32315241,
495
    WL_DRM_FORMAT_ABGR4444 = 0x32314241,
496
    WL_DRM_FORMAT_RGBA4444 = 0x32314152,
497
    WL_DRM_FORMAT_BGRA4444 = 0x32314142,
498
    WL_DRM_FORMAT_XRGB1555 = 0x35315258,
499
    WL_DRM_FORMAT_XBGR1555 = 0x35314258,
500
    WL_DRM_FORMAT_RGBX5551 = 0x35315852,
501
    WL_DRM_FORMAT_BGRX5551 = 0x35315842,
502
    WL_DRM_FORMAT_ARGB1555 = 0x35315241,
503
    WL_DRM_FORMAT_ABGR1555 = 0x35314241,
504
    WL_DRM_FORMAT_RGBA5551 = 0x35314152,
505
    WL_DRM_FORMAT_BGRA5551 = 0x35314142,
506
    WL_DRM_FORMAT_RGB565 = 0x36314752,
507
    WL_DRM_FORMAT_BGR565 = 0x36314742,
508
    WL_DRM_FORMAT_RGB888 = 0x34324752,
509
    WL_DRM_FORMAT_BGR888 = 0x34324742,
510
    WL_DRM_FORMAT_XRGB8888 = 0x34325258,
511
    WL_DRM_FORMAT_XBGR8888 = 0x34324258,
512
    WL_DRM_FORMAT_RGBX8888 = 0x34325852,
513
    WL_DRM_FORMAT_BGRX8888 = 0x34325842,
514
    WL_DRM_FORMAT_ARGB8888 = 0x34325241,
515
    WL_DRM_FORMAT_ABGR8888 = 0x34324241,
516
    WL_DRM_FORMAT_RGBA8888 = 0x34324152,
517
    WL_DRM_FORMAT_BGRA8888 = 0x34324142,
518
    WL_DRM_FORMAT_XRGB2101010 = 0x30335258,
519
    WL_DRM_FORMAT_XBGR2101010 = 0x30334258,
520
    WL_DRM_FORMAT_RGBX1010102 = 0x30335852,
521
    WL_DRM_FORMAT_BGRX1010102 = 0x30335842,
522
    WL_DRM_FORMAT_ARGB2101010 = 0x30335241,
523
    WL_DRM_FORMAT_ABGR2101010 = 0x30334241,
524
    WL_DRM_FORMAT_RGBA1010102 = 0x30334152,
525
    WL_DRM_FORMAT_BGRA1010102 = 0x30334142,
526
    WL_DRM_FORMAT_YUYV = 0x56595559,
527
    WL_DRM_FORMAT_YVYU = 0x55595659,
528
    WL_DRM_FORMAT_UYVY = 0x59565955,
529
    WL_DRM_FORMAT_VYUY = 0x59555956,
530
    WL_DRM_FORMAT_AYUV = 0x56555941,
531
    WL_DRM_FORMAT_NV12 = 0x3231564e,
532
    WL_DRM_FORMAT_NV21 = 0x3132564e,
533
    WL_DRM_FORMAT_NV16 = 0x3631564e,
534
    WL_DRM_FORMAT_NV61 = 0x3136564e,
535
    WL_DRM_FORMAT_YUV410 = 0x39565559,
536
    WL_DRM_FORMAT_YVU410 = 0x39555659,
537
    WL_DRM_FORMAT_YUV411 = 0x31315559,
538
    WL_DRM_FORMAT_YVU411 = 0x31315659,
539
    WL_DRM_FORMAT_YUV420 = 0x32315559,
540
    WL_DRM_FORMAT_YVU420 = 0x32315659,
541
    WL_DRM_FORMAT_YUV422 = 0x36315559,
542
    WL_DRM_FORMAT_YVU422 = 0x36315659,
543
    WL_DRM_FORMAT_YUV444 = 0x34325559,
544
    WL_DRM_FORMAT_YVU444 = 0x34325659,
545
};
546
 
547
void va_create_planar(vst_t *vst, vframe_t *vframe)
6117 serge 548
{
6133 serge 549
    struct vaapi_context* const vaapi = v_context;
550
    VABufferInfo info = {0};
551
 
6117 serge 552
    VAImage vaimage;
553
    VAStatus status;
6133 serge 554
    planar_t *planar;
6117 serge 555
 
6133 serge 556
    vaSyncSurface(vaapi->display,v_surface_id[vframe->index]);
6117 serge 557
 
6133 serge 558
    if(vframe->format != AV_PIX_FMT_NONE)
559
        return;
560
 
561
    status = vaDeriveImage(vaapi->display,v_surface_id[vframe->index],&vaimage);
6117 serge 562
    if (!vaapi_check_status(status, "vaDeriveImage()"))
563
    {
564
        FAIL();
565
        return;
566
    };
6133 serge 567
/*
568
    printf("vaDeriveImage: %x  fourcc: %x\n"
569
           "offset0: %d pitch0: %d\n"
570
           "offset1: %d pitch1: %d\n"
571
           "offset2: %d pitch2: %d\n",
572
            vaimage.buf, vaimage.format.fourcc,
573
            vaimage.offsets[0],vaimage.pitches[0],
574
            vaimage.offsets[1],vaimage.pitches[1],
575
            vaimage.offsets[2],vaimage.pitches[2]);
576
*/
577
    info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
578
    status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info);
579
    if (!vaapi_check_status(status, "vaAcquireBufferHandle()"))
6117 serge 580
    {
6133 serge 581
        vaDestroyImage(vaapi->display, vaimage.image_id);
6117 serge 582
        FAIL();
583
        return;
584
    };
6133 serge 585
/*
586
    printf("vaAcquireBufferHandle: %x type: %x\n"
587
            "mem type: %x mem size: %d\n",
588
            info.handle, info.type, info.mem_type, info.mem_size);
589
*/
590
    planar = pxCreatePlanar(info.handle, WL_DRM_FORMAT_NV12,
591
                            vaimage.width, vaimage.height,
592
                            vaimage.offsets[0],vaimage.pitches[0],
593
                            vaimage.offsets[1],vaimage.pitches[1],
594
                            vaimage.offsets[2],vaimage.pitches[2]);
595
    if(planar != NULL)
6117 serge 596
    {
6133 serge 597
        vframe->planar = planar;
598
        vframe->format = AV_PIX_FMT_NV12;
6117 serge 599
    };
600
 
6133 serge 601
    vaReleaseBufferHandle(vaapi->display, vaimage.buf);
6117 serge 602
    vaDestroyImage(vaapi->display, vaimage.image_id);
6135 serge 603
 
6117 serge 604
}
6144 serge 605
 
6298 serge 606
static enum AVCodecID profile_to_codec(VAProfile profile)
607
{
608
    enum AVCodecID id;
609
 
610
    switch(profile)
611
    {
612
        case VAProfileMPEG2Simple:
613
        case VAProfileMPEG2Main:
614
            id = AV_CODEC_ID_MPEG2VIDEO;
615
            break;
616
 
617
        case VAProfileMPEG4Simple:
618
        case VAProfileMPEG4AdvancedSimple:
619
        case VAProfileMPEG4Main:
620
            id = AV_CODEC_ID_MPEG4;
621
            break;
622
 
623
        case VAProfileH264Baseline:
624
        case VAProfileH264Main:
625
        case VAProfileH264High:
626
        case VAProfileH264ConstrainedBaseline:
627
        case VAProfileH264MultiviewHigh:
628
        case VAProfileH264StereoHigh:
629
            id = AV_CODEC_ID_H264;
630
            break;
631
 
632
        case VAProfileVC1Simple:
633
        case VAProfileVC1Main:
634
        case VAProfileVC1Advanced:
635
            id = AV_CODEC_ID_VC1;
636
            break;
637
 
638
        case VAProfileHEVCMain:
639
        case VAProfileHEVCMain10:
640
            id = AV_CODEC_ID_HEVC;
641
            break;
642
 
643
        default:
644
            id = AV_CODEC_ID_NONE;
645
    };
646
    return id;
647
};
648
 
649
static VAProfile get_profile(VADisplay dpy, enum AVCodecID codec_id)
650
{
651
    VAProfile profile = VAProfileNone, *profile_list = NULL;
652
    int num_profiles, max_num_profiles;
653
    enum AVCodecID ff_id;
654
    VAStatus va_status;
655
    int i;
656
 
657
    max_num_profiles = vaMaxNumProfiles(dpy);
658
 
659
    profile_list = alloca(max_num_profiles * sizeof(VAProfile));
660
    if (!profile_list)
661
    {
662
        printf("Failed to allocate memory for profile list\n");
663
        goto err_0;
664
    }
665
 
666
    va_status = vaQueryConfigProfiles(dpy, profile_list, &num_profiles);
667
    if(!vaapi_check_status(va_status, "vaQueryConfigProfiles()"))
668
        goto err_0;
669
 
670
    if(codec_id == AV_CODEC_ID_H263)
671
        ff_id = AV_CODEC_ID_H264;
672
    else if(codec_id == AV_CODEC_ID_WMV3)
673
        ff_id = AV_CODEC_ID_VC1;
674
    else
675
        ff_id = codec_id;
676
 
677
    for (i = 0; i < num_profiles; i++)
678
    {
679
        if(ff_id == profile_to_codec(profile_list[i]))
680
        {
681
            profile = profile_list[i];
682
            break;
683
        }
684
    };
685
 
686
err_0:
687
    return profile;
688
}
689
 
6144 serge 690
struct decoder* va_init_decoder(vst_t *vst)
691
{
692
    AVCodecContext *vCtx = vst->vCtx;
693
    struct decoder *decoder;
694
    VADisplay dpy;
695
 
696
    drm_fd = get_service("DISPLAY");
697
    if (drm_fd == 0)
698
        return NULL;
699
 
700
    dpy = vaGetDisplayDRM(drm_fd);
701
    if (dpy == NULL)
702
        goto err_0;
703
 
704
    decoder = calloc(1, sizeof(struct decoder));
705
    if(decoder == NULL)
706
        goto err_0;
707
 
708
    decoder->hwctx = vaapi_init(dpy);
709
    if(decoder->hwctx == NULL)
710
        goto err_1;
711
 
6298 serge 712
    if(get_profile(dpy, vCtx->codec_id) == VAProfileNone)
713
        goto err_1;
714
 
6144 serge 715
    decoder->Frame = av_frame_alloc();
716
    if(decoder->Frame == NULL)
717
        goto err_1;
718
 
719
    if(vCtx->codec_id == AV_CODEC_ID_H264)
720
        decoder->nframes = 16;
721
    else
722
        decoder->nframes = 4;
723
 
724
    for(int i = 0; i < decoder->nframes; i++)
725
    {
726
        vframe_t *vframe = &decoder->vframes[i];
727
 
728
        vframe->format    = AV_PIX_FMT_NONE;
729
        vframe->is_hw_pic = 1;
730
        vframe->index     = i;
731
        vframe->pts       = 0;
732
        vframe->ready     = 0;
733
        list_add_tail(&vframe->list, &vst->input_list);
734
    };
735
 
736
    vCtx->opaque       = vst;
737
    vCtx->thread_count = 1;
738
    vCtx->get_format   = get_format;
739
    vCtx->get_buffer2  = get_buffer2;
740
 
741
    if(avcodec_open2(vst->vCtx, vst->vCodec, NULL) < 0)
742
    {
743
        printf("Error while opening codec for input stream %d\n",
744
                vst->vStream);
745
        goto err_2;
746
    };
747
 
748
    decoder->name     = vst->vCodec->name;
749
    decoder->codec_id = vCtx->codec_id;
750
    decoder->pix_fmt  = vCtx->pix_fmt;
751
    decoder->width    = vCtx->width;
752
    decoder->height   = vCtx->height;
753
    decoder->is_hw    = 1;
754
    decoder->frame_reorder = 1;
755
 
756
    return decoder;
757
 
758
err_2:
759
    av_frame_free(&decoder->Frame);
760
err_1:
6298 serge 761
    vaTerminate(dpy);
6144 serge 762
    free(decoder);
763
err_0:
764
    drm_fd = 0;
765
    return NULL;
766
}