#include "vaapi_jpeg_decoder.h"
+#include "jpeg_destroyer.h"
+#include "jpeg_frame.h"
+#include "memcpy_interleaved.h"
+
#include <X11/Xlib.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <jpeglib.h>
+#include <list>
+#include <mutex>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <string>
#include <unistd.h>
#include <va/va.h>
#include <va/va_drm.h>
#include <va/va_x11.h>
-#include <list>
-#include <mutex>
-#include <string>
-
-#include "jpeg_frame.h"
-#include "memcpy_interleaved.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;
public:
ReleaseVAResources(const VAResources &resources)
: resources(resources) {}
- ~ReleaseVAResources() {
+ ~ReleaseVAResources()
+ {
if (!committed) {
release_va_resources(resources);
}
{
unique_ptr<VADisplayWithCleanup> va_dpy = va_open_display(va_display);
if (va_dpy == nullptr) {
- if (error) *error = "Opening VA display failed";
+ if (error)
+ *error = "Opening VA display failed";
return nullptr;
}
int major_ver, minor_ver;
if (va_status != VA_STATUS_SUCCESS) {
char buf[256];
snprintf(buf, sizeof(buf), "vaInitialize() failed with status %d\n", va_status);
- if (error != nullptr) *error = buf;
+ if (error != nullptr)
+ *error = buf;
return nullptr;
}
int num_entrypoints = vaMaxNumEntrypoints(va_dpy->va_dpy);
unique_ptr<VAEntrypoint[]> entrypoints(new VAEntrypoint[num_entrypoints]);
if (entrypoints == nullptr) {
- if (error != nullptr) *error = "Failed to allocate memory for VA entry points";
+ if (error != nullptr)
+ *error = "Failed to allocate memory for VA entry points";
return nullptr;
}
return va_dpy;
}
- if (error != nullptr) *error = "Can't find VAEntrypointVLD for the JPEG profile";
+ if (error != nullptr)
+ *error = "Can't find VAEntrypointVLD for the JPEG profile";
return nullptr;
}
vaapi_jpeg_decoding_usable = true;
}
+class VABufferDestroyer {
+public:
+ VABufferDestroyer(VADisplay dpy, VABufferID buf)
+ : dpy(dpy), buf(buf) {}
+
+ ~VABufferDestroyer() {
+ VAStatus va_status = vaDestroyBuffer(dpy, buf);
+ CHECK_VASTATUS(va_status, "vaDestroyBuffer");
+ }
+
+private:
+ VADisplay dpy;
+ VABufferID buf;
+};
+
shared_ptr<Frame> decode_jpeg_vaapi(const string &filename)
{
jpeg_decompress_struct dinfo;
jpeg_error_mgr jerr;
dinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&dinfo);
+ JPEGDestroyer destroy_dinfo(&dinfo);
FILE *fp = fopen(filename.c_str(), "rb");
if (fp == nullptr) {
return nullptr;
}
if (dinfo.comp_info[0].h_samp_factor != 2 ||
- dinfo.comp_info[0].v_samp_factor != 2 ||
dinfo.comp_info[1].h_samp_factor != 1 ||
- dinfo.comp_info[1].v_samp_factor != 2 ||
+ dinfo.comp_info[1].v_samp_factor != dinfo.comp_info[0].v_samp_factor ||
dinfo.comp_info[2].h_samp_factor != 1 ||
- dinfo.comp_info[2].v_samp_factor != 2) {
+ dinfo.comp_info[2].v_samp_factor != dinfo.comp_info[0].v_samp_factor) {
fprintf(stderr, "Not 4:2:2. (Y=%dx%d, Cb=%dx%d, Cr=%dx%d)\n",
dinfo.comp_info[0].h_samp_factor, dinfo.comp_info[0].v_samp_factor,
dinfo.comp_info[1].h_samp_factor, dinfo.comp_info[1].v_samp_factor,
VABufferID pic_param_buffer;
VAStatus va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAPictureParameterBufferType, sizeof(pic_param), 1, &pic_param, &pic_param_buffer);
CHECK_VASTATUS_RET(va_status, "vaCreateBuffer");
+ VABufferDestroyer destroy_pic_param(va_dpy->va_dpy, pic_param_buffer);
// Quantization matrices.
VAIQMatrixBufferJPEGBaseline iq;
VABufferID iq_buffer;
va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAIQMatrixBufferType, sizeof(iq), 1, &iq, &iq_buffer);
CHECK_VASTATUS_RET(va_status, "vaCreateBuffer");
+ VABufferDestroyer destroy_iq(va_dpy->va_dpy, iq_buffer);
// Huffman tables (arithmetic is not supported).
VAHuffmanTableBufferJPEGBaseline huff;
VABufferID huff_buffer;
va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAHuffmanTableBufferType, sizeof(huff), 1, &huff, &huff_buffer);
CHECK_VASTATUS_RET(va_status, "vaCreateBuffer");
+ VABufferDestroyer destroy_huff(va_dpy->va_dpy, huff_buffer);
// Slice parameters (metadata about the slice).
VASliceParameterBufferJPEGBaseline parms;
memset(&parms, 0, sizeof(parms));
parms.slice_data_size = str.size();
parms.slice_data_offset = 0;
- parms.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
+ parms.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
parms.slice_horizontal_position = 0;
parms.slice_vertical_position = 0;
for (int component_idx = 0; component_idx < dinfo.num_components; ++component_idx) {
parms.components[component_idx].dc_table_selector = comp->dc_tbl_no;
parms.components[component_idx].ac_table_selector = comp->ac_tbl_no;
if (parms.components[component_idx].dc_table_selector > 1 ||
- parms.components[component_idx].ac_table_selector > 1) {
+ parms.components[component_idx].ac_table_selector > 1) {
fprintf(stderr, "Uses too many Huffman tables\n");
return nullptr;
}
VABufferID slice_param_buffer;
va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VASliceParameterBufferType, sizeof(parms), 1, &parms, &slice_param_buffer);
CHECK_VASTATUS_RET(va_status, "vaCreateBuffer");
+ VABufferDestroyer destroy_slice_param(va_dpy->va_dpy, slice_param_buffer);
// The actual data.
VABufferID data_buffer;
va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VASliceDataBufferType, str.size(), 1, &str[0], &data_buffer);
CHECK_VASTATUS_RET(va_status, "vaCreateBuffer");
+ VABufferDestroyer destroy_data(va_dpy->va_dpy, data_buffer);
VAResources resources = get_va_resources(dinfo.image_width, dinfo.image_height);
ReleaseVAResources release(resources);