Subversion Repositories Kolibri OS

Rev

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