Subversion Repositories Kolibri OS

Rev

Rev 6144 | Rev 6438 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <libavcodec/avcodec.h>
  6. #include <libavformat/avformat.h>
  7. #include <libswscale/swscale.h>
  8. #include <libavcodec/vaapi.h>
  9. #include <va/va.h>
  10. #include <va/va_drmcommon.h>
  11. #include <va/drm/va_drm.h>
  12. #include <alloca.h>
  13. #include <kos32sys.h>
  14. #include "winlib/winlib.h"
  15. #include "fplay.h"
  16.  
  17. struct hw_profile
  18. {
  19.     enum AVCodecID av_codec;
  20.     int ff_profile;
  21.     VAProfile va_profile;
  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.  
  43. static VASurfaceID v_surface_id[16];
  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.  
  52. static const struct hw_profile hw_profiles[] = {
  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),
  60.     PE(H264,        H264_CONSTRAINED_BASELINE, H264ConstrainedBaseline),
  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. {
  79.     for (int n = 0; hw_profiles[n].av_codec; n++) {
  80.         if (hw_profiles[n].av_codec == id)
  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 "<unknown>";
  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 "<unknown>";
  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 "<unknown>";
  162. }
  163.  
  164.  
  165. void *vaapi_init(VADisplay display)
  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;
  208.     vaapi->display    = display;
  209.     vaapi->config_id  = VA_INVALID_ID;
  210.     vaapi->context_id = VA_INVALID_ID;
  211.  
  212.     v_context = vaapi;
  213.  
  214.     return vaapi;
  215.  
  216. error:
  217.     free(display_attrs);
  218.     return NULL;
  219. }
  220.  
  221. static int has_profile(struct vaapi_context *vaapi, VAProfile profile)
  222. {
  223.     VAProfile *profiles;
  224.     int        n_profiles;
  225.     size_t size;
  226.     VAStatus   status;
  227.     int i;
  228.  
  229.     size = vaMaxNumProfiles(vaapi->display) * sizeof(VAProfile);
  230.  
  231.     profiles = alloca(size);
  232.     memset(profiles, 0, size);
  233.  
  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;
  253.     size_t size;
  254.     VAStatus      status;
  255.     int i;
  256.  
  257.     size = vaMaxNumEntrypoints(vaapi->display) * sizeof(VAEntrypoint);
  258.  
  259.     entrypoints = alloca(size);
  260.     memset(entrypoints, 0, size);
  261.  
  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.  
  278. static int vaapi_init_decoder(vst_t *vst,VAProfile profile,
  279.                               VAEntrypoint entrypoint,
  280.                               unsigned int picture_width,
  281.                               unsigned int picture_height)
  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();
  290.  
  291.     printf("%s profile %x width:%d height:%d\n",
  292.             __FUNCTION__, profile, picture_width, picture_height);
  293.  
  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,
  344.                               v_surface_id,vst->decoder->nframes,NULL,0);
  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,
  379.                              v_surface_id, vst->decoder->nframes,
  380.                              &context_id);
  381.     if (!vaapi_check_status(status, "vaCreateContext()"))
  382.     {
  383.         FAIL();
  384.         return -1;
  385.     };
  386.  
  387.     vaapi->config_id  = config_id;
  388.     vaapi->context_id = context_id;
  389.     LEAVE();
  390.     return 0;
  391. }
  392.  
  393.  
  394. static enum PixelFormat get_format(struct AVCodecContext *avctx,
  395.                                    const enum AVPixelFormat *fmt)
  396. {
  397.     vst_t *vst = (vst_t*)avctx->opaque;
  398.     VAProfile profile = avctx->profile;
  399.     enum AVCodecID codec = avctx->codec_id;
  400.  
  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.  
  409.     for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
  410.     {
  411.         if (fmt[i] != AV_PIX_FMT_VAAPI_VLD)
  412.             continue;
  413.  
  414.         for (int n = 0; hw_profiles[n].av_codec; n++)
  415.         {
  416.             if (hw_profiles[n].av_codec   == codec &&
  417.                 hw_profiles[n].ff_profile == profile)
  418.             {
  419.                 profile = hw_profiles[n].va_profile;
  420.                 if (vaapi_init_decoder(vst, profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
  421.                 {
  422.                     avctx->hwaccel_context = v_context;
  423.                     printf("%s format: %x\n",__FUNCTION__, fmt[i]);
  424.                     return fmt[i];
  425.                 }
  426.             }
  427.         }
  428.  
  429.     }
  430.     printf("%s format PIX_FMT_NONE\n",__FUNCTION__);
  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. {
  447.     static struct av_surface avsurface;
  448.     vst_t *vst = (vst_t*)avctx->opaque;
  449.     void *surface;
  450.  
  451.     surface = (void *)(uintptr_t)v_surface_id[vst->decoder->active_frame->index];
  452.  
  453.     pic->data[3] = surface;
  454.  
  455.     pic->buf[0] = av_buffer_create((uint8_t*)&avsurface, sizeof(avsurface),
  456.                                     av_release_buffer, avctx,
  457.                                     AV_BUFFER_FLAG_READONLY);
  458.     return 0;
  459. }
  460.  
  461. struct vaapi_context va_context_storage;
  462.  
  463.  
  464.  
  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
  468.  
  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)
  531. {
  532.     struct vaapi_context* const vaapi = v_context;
  533.     VABufferInfo info = {0};
  534.  
  535.     VAImage vaimage;
  536.     VAStatus status;
  537.     planar_t *planar;
  538.  
  539.     vaSyncSurface(vaapi->display,v_surface_id[vframe->index]);
  540.  
  541.     if(vframe->format != AV_PIX_FMT_NONE)
  542.         return;
  543.  
  544.     status = vaDeriveImage(vaapi->display,v_surface_id[vframe->index],&vaimage);
  545.     if (!vaapi_check_status(status, "vaDeriveImage()"))
  546.     {
  547.         FAIL();
  548.         return;
  549.     };
  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()"))
  563.     {
  564.         vaDestroyImage(vaapi->display, vaimage.image_id);
  565.         FAIL();
  566.         return;
  567.     };
  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)
  579.     {
  580.         vframe->planar = planar;
  581.         vframe->format = AV_PIX_FMT_NV12;
  582.     };
  583.  
  584.     vaReleaseBufferHandle(vaapi->display, vaimage.buf);
  585.     vaDestroyImage(vaapi->display, vaimage.image_id);
  586.  
  587. }
  588.  
  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.  
  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.  
  695.     if(get_profile(dpy, vCtx->codec_id) == VAProfileNone)
  696.         goto err_1;
  697.  
  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:
  744.     vaTerminate(dpy);
  745.     free(decoder);
  746. err_0:
  747.     drm_fd = 0;
  748.     return NULL;
  749. }
  750.