Subversion Repositories Kolibri OS

Rev

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