]> git.sesse.net Git - nageru/blobdiff - shared/va_resource_pool.h
Move VAResourcePool into a shared class between MJPEGEncoder in Nageru and the VA...
[nageru] / shared / va_resource_pool.h
diff --git a/shared/va_resource_pool.h b/shared/va_resource_pool.h
new file mode 100644 (file)
index 0000000..e8f276f
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef _VA_RESOURCE_POOL
+#define _VA_RESOURCE_POOL 1
+
+#include <inttypes.h>
+#include <va/va.h>
+
+#include <list>
+#include <mutex>
+
+#define CHECK_VASTATUS(va_status, func) \
+       if (va_status != VA_STATUS_SUCCESS) { \
+               fprintf(stderr, "%s:%d (%s) failed: %s\n", __func__, __LINE__, func, vaErrorStr(va_status)); \
+               exit(1); \
+       }
+
+#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; \
+       }
+
+class VAResourcePool {
+public:
+       struct VAResources {
+               unsigned width, height;
+               uint32_t fourcc;
+               VASurfaceID surface;
+               VAContextID context;
+               VABufferID data_buffer;
+               VAImage image;
+       };
+
+       VAResourcePool(VADisplay va_dpy, VAImageFormat uyvy_format, VAImageFormat nv12_format, VAConfigID config_id_422, VAConfigID config_id_420, bool with_data_buffer)
+               : va_dpy(va_dpy),
+                 uyvy_format(uyvy_format),
+                 nv12_format(nv12_format),
+                 config_id_422(config_id_422),
+                 config_id_420(config_id_420),
+                 with_data_buffer(with_data_buffer) {}
+       VAResources get_va_resources(unsigned width, unsigned height, uint32_t fourcc);
+       void release_va_resources(VAResources resources);
+
+private:
+       const VADisplay va_dpy;
+       VAImageFormat uyvy_format, nv12_format;
+       const VAConfigID config_id_422, config_id_420;
+       const bool with_data_buffer;
+
+       std::mutex mu;
+       std::list<VAResources> freelist;  // Under mu.
+};
+
+// RAII wrapper to release VAResources on return (even on error).
+class ReleaseVAResources {
+public:
+       ReleaseVAResources() : committed(true) {}
+
+       ReleaseVAResources(VAResourcePool *pool, const VAResourcePool::VAResources &resources)
+               : pool(pool), resources(resources) {}
+
+       ReleaseVAResources(ReleaseVAResources &) = delete;
+
+       ReleaseVAResources(ReleaseVAResources &&other)
+               : pool(other.pool), resources(other.resources), committed(other.committed) {
+               other.commit();
+       }
+
+       ReleaseVAResources &operator= (ReleaseVAResources &) = delete;
+
+       ReleaseVAResources &operator= (ReleaseVAResources &&other) {
+               if (!committed) {
+                       pool->release_va_resources(resources);
+               }
+               pool = other.pool;
+               resources = std::move(other.resources);
+               committed = other.committed;
+               other.commit();
+               return *this;
+       }
+
+       ~ReleaseVAResources()
+       {
+               if (!committed) {
+                       pool->release_va_resources(resources);
+               }
+       }
+
+       void commit() { committed = true; }
+
+private:
+       VAResourcePool *pool = nullptr;
+       VAResourcePool::VAResources resources;
+       bool committed = false;
+};
+
+#endif  // !defined(_VA_RESOURCE_POOL)