]> git.sesse.net Git - nageru/blob - shared/va_resource_pool.cpp
Move VAResourcePool into a shared class between MJPEGEncoder in Nageru and the VA...
[nageru] / shared / va_resource_pool.cpp
1
2 #include <assert.h>
3
4 #include "shared/va_resource_pool.h"
5
6 using namespace std;
7
8 VAResourcePool::VAResources VAResourcePool::get_va_resources(unsigned width, unsigned height, uint32_t fourcc)
9 {
10         {
11                 lock_guard<mutex> lock(mu);
12                 for (auto it = freelist.begin(); it != freelist.end(); ++it) {
13                         if (it->width == width && it->height == height && it->fourcc == fourcc) {
14                                 VAResources ret = *it;
15                                 freelist.erase(it);
16                                 return ret;
17                         }
18                 }
19         }
20
21         VAResources ret;
22
23         ret.width = width;
24         ret.height = height;
25         ret.fourcc = fourcc;
26
27         VASurfaceAttrib attrib;
28         attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
29         attrib.type = VASurfaceAttribPixelFormat;
30         attrib.value.type = VAGenericValueTypeInteger;
31         attrib.value.value.i = fourcc;
32
33         VAStatus va_status;
34         VAConfigID config_id;
35         if (fourcc == VA_FOURCC_UYVY) {
36                 va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV422, width, height, &ret.surface, 1, &attrib, 1);
37                 config_id = config_id_422;
38         } else {
39                 assert(fourcc == VA_FOURCC_NV12);
40                 va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, width, height, &ret.surface, 1, &attrib, 1);
41                 config_id = config_id_420;
42         }
43
44         va_status = vaCreateContext(va_dpy, config_id, width, height, 0, &ret.surface, 1, &ret.context);
45         CHECK_VASTATUS(va_status, "vaCreateContext");
46
47         if (with_data_buffer) {
48                 va_status = vaCreateBuffer(va_dpy, ret.context, VAEncCodedBufferType, width * height * 3 + 8192, 1, nullptr, &ret.data_buffer);
49                 CHECK_VASTATUS(va_status, "vaCreateBuffer");
50         }
51
52         if (fourcc == VA_FOURCC_UYVY) {
53                 va_status = vaCreateImage(va_dpy, &uyvy_format, width, height, &ret.image);
54                 CHECK_VASTATUS(va_status, "vaCreateImage");
55         } else {
56                 assert(fourcc == VA_FOURCC_NV12);
57                 va_status = vaCreateImage(va_dpy, &nv12_format, width, height, &ret.image);
58                 CHECK_VASTATUS(va_status, "vaCreateImage");
59         }
60
61         return ret;
62 }
63
64 void VAResourcePool::release_va_resources(VAResourcePool::VAResources resources)
65 {
66         lock_guard<mutex> lock(mu);
67         if (freelist.size() > 50) {
68                 auto it = freelist.end();
69                 --it;
70
71                 VAStatus va_status;
72
73                 if (with_data_buffer) {
74                         va_status = vaDestroyBuffer(va_dpy, it->data_buffer);
75                         CHECK_VASTATUS(va_status, "vaDestroyBuffer");
76                 }
77
78                 va_status = vaDestroyContext(va_dpy, it->context);
79                 CHECK_VASTATUS(va_status, "vaDestroyContext");
80
81                 va_status = vaDestroySurfaces(va_dpy, &it->surface, 1);
82                 CHECK_VASTATUS(va_status, "vaDestroySurfaces");
83
84                 va_status = vaDestroyImage(va_dpy, it->image.image_id);
85                 CHECK_VASTATUS(va_status, "vaDestroyImage");
86
87                 freelist.erase(it);
88         }
89
90         freelist.push_front(resources);
91 }
92