Subversion Repositories Kolibri OS

Rev

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