Subversion Repositories Kolibri OS

Rev

Rev 6144 | Rev 6438 | 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
    printf("%s codec %d profile %x\n", __FUNCTION__,avctx->codec_id, avctx->profile);
402
 
403
    if (codec == AV_CODEC_ID_H264)
404
    {
405
        if(profile == FF_PROFILE_H264_BASELINE)
406
            profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
407
    };
408
 
6133 serge 409
    for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
410
    {
6117 serge 411
        if (fmt[i] != AV_PIX_FMT_VAAPI_VLD)
412
            continue;
413
 
6133 serge 414
        for (int n = 0; hw_profiles[n].av_codec; n++)
415
        {
416
            if (hw_profiles[n].av_codec   == codec &&
6298 serge 417
                hw_profiles[n].ff_profile == profile)
6117 serge 418
            {
6133 serge 419
                profile = hw_profiles[n].va_profile;
6136 serge 420
                if (vaapi_init_decoder(vst, profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
6133 serge 421
                {
422
                    avctx->hwaccel_context = v_context;
6298 serge 423
                    printf("%s format: %x\n",__FUNCTION__, fmt[i]);
424
                    return fmt[i];
6133 serge 425
                }
6117 serge 426
            }
427
        }
6133 serge 428
 
6117 serge 429
    }
6298 serge 430
    printf("%s format PIX_FMT_NONE\n",__FUNCTION__);
6117 serge 431
    return PIX_FMT_NONE;
432
}
433
 
434
struct av_surface
435
{
436
    int         w;
437
    int         h;
438
    VASurfaceID id;
439
};
440
 
441
static void av_release_buffer(void *opaque, uint8_t *data)
442
{
443
}
444
 
445
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
446
{
6298 serge 447
    static struct av_surface avsurface;
6118 serge 448
    vst_t *vst = (vst_t*)avctx->opaque;
6133 serge 449
    void *surface;
6117 serge 450
 
6144 serge 451
    surface = (void *)(uintptr_t)v_surface_id[vst->decoder->active_frame->index];
6133 serge 452
 
6117 serge 453
    pic->data[3] = surface;
454
 
6298 serge 455
    pic->buf[0] = av_buffer_create((uint8_t*)&avsurface, sizeof(avsurface),
456
                                    av_release_buffer, avctx,
457
                                    AV_BUFFER_FLAG_READONLY);
6117 serge 458
    return 0;
459
}
460
 
461
struct vaapi_context va_context_storage;
462
 
463
 
6136 serge 464
 
6133 serge 465
#define EGL_TEXTURE_Y_U_V_WL            0x31D7
466
#define EGL_TEXTURE_Y_UV_WL             0x31D8
467
#define EGL_TEXTURE_Y_XUXV_WL           0x31D9
6117 serge 468
 
6133 serge 469
enum wl_drm_format {
470
    WL_DRM_FORMAT_C8 = 0x20203843,
471
    WL_DRM_FORMAT_RGB332 = 0x38424752,
472
    WL_DRM_FORMAT_BGR233 = 0x38524742,
473
    WL_DRM_FORMAT_XRGB4444 = 0x32315258,
474
    WL_DRM_FORMAT_XBGR4444 = 0x32314258,
475
    WL_DRM_FORMAT_RGBX4444 = 0x32315852,
476
    WL_DRM_FORMAT_BGRX4444 = 0x32315842,
477
    WL_DRM_FORMAT_ARGB4444 = 0x32315241,
478
    WL_DRM_FORMAT_ABGR4444 = 0x32314241,
479
    WL_DRM_FORMAT_RGBA4444 = 0x32314152,
480
    WL_DRM_FORMAT_BGRA4444 = 0x32314142,
481
    WL_DRM_FORMAT_XRGB1555 = 0x35315258,
482
    WL_DRM_FORMAT_XBGR1555 = 0x35314258,
483
    WL_DRM_FORMAT_RGBX5551 = 0x35315852,
484
    WL_DRM_FORMAT_BGRX5551 = 0x35315842,
485
    WL_DRM_FORMAT_ARGB1555 = 0x35315241,
486
    WL_DRM_FORMAT_ABGR1555 = 0x35314241,
487
    WL_DRM_FORMAT_RGBA5551 = 0x35314152,
488
    WL_DRM_FORMAT_BGRA5551 = 0x35314142,
489
    WL_DRM_FORMAT_RGB565 = 0x36314752,
490
    WL_DRM_FORMAT_BGR565 = 0x36314742,
491
    WL_DRM_FORMAT_RGB888 = 0x34324752,
492
    WL_DRM_FORMAT_BGR888 = 0x34324742,
493
    WL_DRM_FORMAT_XRGB8888 = 0x34325258,
494
    WL_DRM_FORMAT_XBGR8888 = 0x34324258,
495
    WL_DRM_FORMAT_RGBX8888 = 0x34325852,
496
    WL_DRM_FORMAT_BGRX8888 = 0x34325842,
497
    WL_DRM_FORMAT_ARGB8888 = 0x34325241,
498
    WL_DRM_FORMAT_ABGR8888 = 0x34324241,
499
    WL_DRM_FORMAT_RGBA8888 = 0x34324152,
500
    WL_DRM_FORMAT_BGRA8888 = 0x34324142,
501
    WL_DRM_FORMAT_XRGB2101010 = 0x30335258,
502
    WL_DRM_FORMAT_XBGR2101010 = 0x30334258,
503
    WL_DRM_FORMAT_RGBX1010102 = 0x30335852,
504
    WL_DRM_FORMAT_BGRX1010102 = 0x30335842,
505
    WL_DRM_FORMAT_ARGB2101010 = 0x30335241,
506
    WL_DRM_FORMAT_ABGR2101010 = 0x30334241,
507
    WL_DRM_FORMAT_RGBA1010102 = 0x30334152,
508
    WL_DRM_FORMAT_BGRA1010102 = 0x30334142,
509
    WL_DRM_FORMAT_YUYV = 0x56595559,
510
    WL_DRM_FORMAT_YVYU = 0x55595659,
511
    WL_DRM_FORMAT_UYVY = 0x59565955,
512
    WL_DRM_FORMAT_VYUY = 0x59555956,
513
    WL_DRM_FORMAT_AYUV = 0x56555941,
514
    WL_DRM_FORMAT_NV12 = 0x3231564e,
515
    WL_DRM_FORMAT_NV21 = 0x3132564e,
516
    WL_DRM_FORMAT_NV16 = 0x3631564e,
517
    WL_DRM_FORMAT_NV61 = 0x3136564e,
518
    WL_DRM_FORMAT_YUV410 = 0x39565559,
519
    WL_DRM_FORMAT_YVU410 = 0x39555659,
520
    WL_DRM_FORMAT_YUV411 = 0x31315559,
521
    WL_DRM_FORMAT_YVU411 = 0x31315659,
522
    WL_DRM_FORMAT_YUV420 = 0x32315559,
523
    WL_DRM_FORMAT_YVU420 = 0x32315659,
524
    WL_DRM_FORMAT_YUV422 = 0x36315559,
525
    WL_DRM_FORMAT_YVU422 = 0x36315659,
526
    WL_DRM_FORMAT_YUV444 = 0x34325559,
527
    WL_DRM_FORMAT_YVU444 = 0x34325659,
528
};
529
 
530
void va_create_planar(vst_t *vst, vframe_t *vframe)
6117 serge 531
{
6133 serge 532
    struct vaapi_context* const vaapi = v_context;
533
    VABufferInfo info = {0};
534
 
6117 serge 535
    VAImage vaimage;
536
    VAStatus status;
6133 serge 537
    planar_t *planar;
6117 serge 538
 
6133 serge 539
    vaSyncSurface(vaapi->display,v_surface_id[vframe->index]);
6117 serge 540
 
6133 serge 541
    if(vframe->format != AV_PIX_FMT_NONE)
542
        return;
543
 
544
    status = vaDeriveImage(vaapi->display,v_surface_id[vframe->index],&vaimage);
6117 serge 545
    if (!vaapi_check_status(status, "vaDeriveImage()"))
546
    {
547
        FAIL();
548
        return;
549
    };
6133 serge 550
/*
551
    printf("vaDeriveImage: %x  fourcc: %x\n"
552
           "offset0: %d pitch0: %d\n"
553
           "offset1: %d pitch1: %d\n"
554
           "offset2: %d pitch2: %d\n",
555
            vaimage.buf, vaimage.format.fourcc,
556
            vaimage.offsets[0],vaimage.pitches[0],
557
            vaimage.offsets[1],vaimage.pitches[1],
558
            vaimage.offsets[2],vaimage.pitches[2]);
559
*/
560
    info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
561
    status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info);
562
    if (!vaapi_check_status(status, "vaAcquireBufferHandle()"))
6117 serge 563
    {
6133 serge 564
        vaDestroyImage(vaapi->display, vaimage.image_id);
6117 serge 565
        FAIL();
566
        return;
567
    };
6133 serge 568
/*
569
    printf("vaAcquireBufferHandle: %x type: %x\n"
570
            "mem type: %x mem size: %d\n",
571
            info.handle, info.type, info.mem_type, info.mem_size);
572
*/
573
    planar = pxCreatePlanar(info.handle, WL_DRM_FORMAT_NV12,
574
                            vaimage.width, vaimage.height,
575
                            vaimage.offsets[0],vaimage.pitches[0],
576
                            vaimage.offsets[1],vaimage.pitches[1],
577
                            vaimage.offsets[2],vaimage.pitches[2]);
578
    if(planar != NULL)
6117 serge 579
    {
6133 serge 580
        vframe->planar = planar;
581
        vframe->format = AV_PIX_FMT_NV12;
6117 serge 582
    };
583
 
6133 serge 584
    vaReleaseBufferHandle(vaapi->display, vaimage.buf);
6117 serge 585
    vaDestroyImage(vaapi->display, vaimage.image_id);
6135 serge 586
 
6117 serge 587
}
6144 serge 588
 
6298 serge 589
static enum AVCodecID profile_to_codec(VAProfile profile)
590
{
591
    enum AVCodecID id;
592
 
593
    switch(profile)
594
    {
595
        case VAProfileMPEG2Simple:
596
        case VAProfileMPEG2Main:
597
            id = AV_CODEC_ID_MPEG2VIDEO;
598
            break;
599
 
600
        case VAProfileMPEG4Simple:
601
        case VAProfileMPEG4AdvancedSimple:
602
        case VAProfileMPEG4Main:
603
            id = AV_CODEC_ID_MPEG4;
604
            break;
605
 
606
        case VAProfileH264Baseline:
607
        case VAProfileH264Main:
608
        case VAProfileH264High:
609
        case VAProfileH264ConstrainedBaseline:
610
        case VAProfileH264MultiviewHigh:
611
        case VAProfileH264StereoHigh:
612
            id = AV_CODEC_ID_H264;
613
            break;
614
 
615
        case VAProfileVC1Simple:
616
        case VAProfileVC1Main:
617
        case VAProfileVC1Advanced:
618
            id = AV_CODEC_ID_VC1;
619
            break;
620
 
621
        case VAProfileHEVCMain:
622
        case VAProfileHEVCMain10:
623
            id = AV_CODEC_ID_HEVC;
624
            break;
625
 
626
        default:
627
            id = AV_CODEC_ID_NONE;
628
    };
629
    return id;
630
};
631
 
632
static VAProfile get_profile(VADisplay dpy, enum AVCodecID codec_id)
633
{
634
    VAProfile profile = VAProfileNone, *profile_list = NULL;
635
    int num_profiles, max_num_profiles;
636
    enum AVCodecID ff_id;
637
    VAStatus va_status;
638
    int i;
639
 
640
    max_num_profiles = vaMaxNumProfiles(dpy);
641
 
642
    profile_list = alloca(max_num_profiles * sizeof(VAProfile));
643
    if (!profile_list)
644
    {
645
        printf("Failed to allocate memory for profile list\n");
646
        goto err_0;
647
    }
648
 
649
    va_status = vaQueryConfigProfiles(dpy, profile_list, &num_profiles);
650
    if(!vaapi_check_status(va_status, "vaQueryConfigProfiles()"))
651
        goto err_0;
652
 
653
    if(codec_id == AV_CODEC_ID_H263)
654
        ff_id = AV_CODEC_ID_H264;
655
    else if(codec_id == AV_CODEC_ID_WMV3)
656
        ff_id = AV_CODEC_ID_VC1;
657
    else
658
        ff_id = codec_id;
659
 
660
    for (i = 0; i < num_profiles; i++)
661
    {
662
        if(ff_id == profile_to_codec(profile_list[i]))
663
        {
664
            profile = profile_list[i];
665
            break;
666
        }
667
    };
668
 
669
err_0:
670
    return profile;
671
}
672
 
6144 serge 673
struct decoder* va_init_decoder(vst_t *vst)
674
{
675
    AVCodecContext *vCtx = vst->vCtx;
676
    struct decoder *decoder;
677
    VADisplay dpy;
678
 
679
    drm_fd = get_service("DISPLAY");
680
    if (drm_fd == 0)
681
        return NULL;
682
 
683
    dpy = vaGetDisplayDRM(drm_fd);
684
    if (dpy == NULL)
685
        goto err_0;
686
 
687
    decoder = calloc(1, sizeof(struct decoder));
688
    if(decoder == NULL)
689
        goto err_0;
690
 
691
    decoder->hwctx = vaapi_init(dpy);
692
    if(decoder->hwctx == NULL)
693
        goto err_1;
694
 
6298 serge 695
    if(get_profile(dpy, vCtx->codec_id) == VAProfileNone)
696
        goto err_1;
697
 
6144 serge 698
    decoder->Frame = av_frame_alloc();
699
    if(decoder->Frame == NULL)
700
        goto err_1;
701
 
702
    if(vCtx->codec_id == AV_CODEC_ID_H264)
703
        decoder->nframes = 16;
704
    else
705
        decoder->nframes = 4;
706
 
707
    for(int i = 0; i < decoder->nframes; i++)
708
    {
709
        vframe_t *vframe = &decoder->vframes[i];
710
 
711
        vframe->format    = AV_PIX_FMT_NONE;
712
        vframe->is_hw_pic = 1;
713
        vframe->index     = i;
714
        vframe->pts       = 0;
715
        vframe->ready     = 0;
716
        list_add_tail(&vframe->list, &vst->input_list);
717
    };
718
 
719
    vCtx->opaque       = vst;
720
    vCtx->thread_count = 1;
721
    vCtx->get_format   = get_format;
722
    vCtx->get_buffer2  = get_buffer2;
723
 
724
    if(avcodec_open2(vst->vCtx, vst->vCodec, NULL) < 0)
725
    {
726
        printf("Error while opening codec for input stream %d\n",
727
                vst->vStream);
728
        goto err_2;
729
    };
730
 
731
    decoder->name     = vst->vCodec->name;
732
    decoder->codec_id = vCtx->codec_id;
733
    decoder->pix_fmt  = vCtx->pix_fmt;
734
    decoder->width    = vCtx->width;
735
    decoder->height   = vCtx->height;
736
    decoder->is_hw    = 1;
737
    decoder->frame_reorder = 1;
738
 
739
    return decoder;
740
 
741
err_2:
742
    av_frame_free(&decoder->Frame);
743
err_1:
6298 serge 744
    vaTerminate(dpy);
6144 serge 745
    free(decoder);
746
err_0:
747
    drm_fd = 0;
748
    return NULL;
749
}