]> git.sesse.net Git - nageru/blobdiff - futatabi/vaapi_jpeg_decoder.cpp
Move VAResourcePool into a shared class between MJPEGEncoder in Nageru and the VA...
[nageru] / futatabi / vaapi_jpeg_decoder.cpp
index 0540db7da82061ff314ad26bdba2c76cb2cdca5a..8fe1ac88f7fc46f4ddb0af10895115bd52a05dd7 100644 (file)
@@ -6,6 +6,7 @@
 #include "pbo_pool.h"
 #include "shared/memcpy_interleaved.h"
 #include "shared/va_display.h"
+#include "shared/va_resource_pool.h"
 
 #include <X11/Xlib.h>
 #include <assert.h>
 using namespace std;
 
 static unique_ptr<VADisplayWithCleanup> va_dpy;
-static VAConfigID config_id;
-static VAImageFormat uyvy_format;
-bool vaapi_jpeg_decoding_usable = false;
-
-struct VAResources {
-       unsigned width, height;
-       VASurfaceID surface;
-       VAContextID context;
-       VAImage image;
-};
-static list<VAResources> va_resources_freelist;
-static mutex va_resources_mutex;
-
-#define CHECK_VASTATUS(va_status, func) \
-       if (va_status != VA_STATUS_SUCCESS) { \
-               fprintf(stderr, "%s:%d (%s) failed with %d\n", __func__, __LINE__, func, va_status); \
-               abort(); \
-       }
+static unique_ptr<VAResourcePool> va_pool;
 
-#define CHECK_VASTATUS_RET(va_status, func) \
-       if (va_status != VA_STATUS_SUCCESS) { \
-               fprintf(stderr, "%s:%d (%s) failed with %d\n", __func__, __LINE__, func, va_status); \
-               return nullptr; \
-       }
+bool vaapi_jpeg_decoding_usable = false;
 
 // From libjpeg (although it's of course identical between implementations).
 static const int jpeg_natural_order[DCTSIZE2] = {
@@ -66,85 +46,24 @@ static const int jpeg_natural_order[DCTSIZE2] = {
        53, 60, 61, 54, 47, 55, 62, 63,
 };
 
-VAResources get_va_resources(unsigned width, unsigned height)
-{
-       {
-               lock_guard<mutex> lock(va_resources_mutex);
-               for (auto it = va_resources_freelist.begin(); it != va_resources_freelist.end(); ++it) {
-                       if (it->width == width && it->height == height) {
-                               VAResources ret = *it;
-                               va_resources_freelist.erase(it);
-                               return ret;
-                       }
-               }
-       }
-
-       VAResources ret;
-
-       ret.width = width;
-       ret.height = height;
-
-       VAStatus va_status = vaCreateSurfaces(va_dpy->va_dpy, VA_RT_FORMAT_YUV422,
-                                             width, height,
-                                             &ret.surface, 1, nullptr, 0);
-       CHECK_VASTATUS(va_status, "vaCreateSurfaces");
-
-       va_status = vaCreateContext(va_dpy->va_dpy, config_id, width, height, 0, &ret.surface, 1, &ret.context);
-       CHECK_VASTATUS(va_status, "vaCreateContext");
-
-       va_status = vaCreateImage(va_dpy->va_dpy, &uyvy_format, width, height, &ret.image);
-       CHECK_VASTATUS(va_status, "vaCreateImage");
-
-       return ret;
-}
-
-void release_va_resources(VAResources resources)
+static unique_ptr<VADisplayWithCleanup> try_open_va_mjpeg(const string &va_display)
 {
-       lock_guard<mutex> lock(va_resources_mutex);
-       if (va_resources_freelist.size() > 10) {
-               auto it = va_resources_freelist.end();
-               --it;
-
-               VAStatus va_status = vaDestroyImage(va_dpy->va_dpy, it->image.image_id);
-               CHECK_VASTATUS(va_status, "vaDestroyImage");
-
-               va_status = vaDestroyContext(va_dpy->va_dpy, it->context);
-               CHECK_VASTATUS(va_status, "vaDestroyContext");
-
-               va_status = vaDestroySurfaces(va_dpy->va_dpy, &it->surface, 1);
-               CHECK_VASTATUS(va_status, "vaDestroySurfaces");
+       VAConfigID config_id_422, config_id_420;
+       VAImageFormat uyvy_format, nv12_format;
 
-               va_resources_freelist.erase(it);
-       }
-
-       va_resources_freelist.push_front(resources);
-}
-
-// RAII wrapper to release VAResources on return (even on error).
-class ReleaseVAResources {
-public:
-       ReleaseVAResources(const VAResources &resources)
-               : resources(resources) {}
-       ~ReleaseVAResources()
-       {
-               if (!committed) {
-                       release_va_resources(resources);
-               }
+       // Seemingly VA_FOURCC_422H is no good for vaGetImage(). :-/
+       unique_ptr<VADisplayWithCleanup> va_dpy =
+               try_open_va(va_display, { VAProfileJPEGBaseline }, VAEntrypointVLD,
+                       { { "4:2:2", VA_RT_FORMAT_YUV422, VA_FOURCC_UYVY, &config_id_422, &uyvy_format },
+                         { "4:2:0", VA_RT_FORMAT_YUV420, VA_FOURCC_NV12, &config_id_420, &nv12_format } },
+                       /*chosen_profile=*/nullptr, /*error=*/nullptr);
+       if (va_dpy == nullptr) {
+               return va_dpy;
        }
 
-       void commit() { committed = true; }
-
-private:
-       const VAResources &resources;
-       bool committed = false;
-};
+       va_pool.reset(new VAResourcePool(va_dpy->va_dpy, uyvy_format, nv12_format, config_id_422, config_id_420, /*with_data_buffer=*/false));
 
-static unique_ptr<VADisplayWithCleanup> try_open_va_mjpeg(const string &va_display)
-{
-       // Seemingly VA_FOURCC_422H is no good for vaGetImage(). :-/
-       return try_open_va(va_display, { VAProfileJPEGBaseline }, VAEntrypointVLD,
-               { { "4:2:2", VA_RT_FORMAT_YUV422, VA_FOURCC_UYVY, &config_id, &uyvy_format } },
-               /*chosen_profile=*/nullptr, /*error=*/nullptr);
+       return va_dpy;
 }
 
 string get_usable_va_display()
@@ -280,8 +199,8 @@ shared_ptr<Frame> decode_jpeg_vaapi(const string &jpeg)
        pic_param.color_space = 0;  // YUV.
        pic_param.rotation = VA_ROTATION_NONE;
 
-       VAResources resources = get_va_resources(dinfo.image_width, dinfo.image_height);
-       ReleaseVAResources release(resources);
+       VAResourcePool::VAResources resources = va_pool->get_va_resources(dinfo.image_width, dinfo.image_height, VA_FOURCC_UYVY);
+       ReleaseVAResources release(va_pool.get(), resources);
 
        VABufferID pic_param_buffer;
        VAStatus va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, VAPictureParameterBufferType, sizeof(pic_param), 1, &pic_param, &pic_param_buffer);