#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] = {
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()
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);