X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fvaapi_jpeg_decoder.cpp;h=0441514a8b815efe62509e45490b595cc0a4562b;hb=0da2817ad80aeab299902c55b306f57376054a7e;hp=1d0f771cddb2d2f27d414b7393320df44799b51b;hpb=4a9e97065dade428e373a83618bc973cd93cbe52;p=nageru diff --git a/futatabi/vaapi_jpeg_decoder.cpp b/futatabi/vaapi_jpeg_decoder.cpp index 1d0f771c..0441514 100644 --- a/futatabi/vaapi_jpeg_decoder.cpp +++ b/futatabi/vaapi_jpeg_decoder.cpp @@ -3,6 +3,7 @@ #include "jpeg_destroyer.h" #include "jpeg_frame.h" #include "jpeglib_error_wrapper.h" +#include "pbo_pool.h" #include "shared/memcpy_interleaved.h" #include @@ -22,6 +23,8 @@ #include #include +#define BUFFER_OFFSET(i) ((char *)nullptr + (i)) + using namespace std; static unique_ptr va_dpy; @@ -41,7 +44,7 @@ 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); \ - exit(1); \ + abort(); \ } #define CHECK_VASTATUS_RET(va_status, func) \ @@ -337,6 +340,8 @@ shared_ptr decode_jpeg_vaapi(const string &jpeg) } JPEGDestroyer destroy_dinfo(&dinfo); + jpeg_save_markers(&dinfo, JPEG_APP0 + 1, 0xFFFF); + jpeg_mem_src(&dinfo, reinterpret_cast(jpeg.data()), jpeg.size()); if (!error_mgr.run([&dinfo] { jpeg_read_header(&dinfo, true); })) { return nullptr; @@ -378,8 +383,11 @@ shared_ptr 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); + VABufferID pic_param_buffer; - VAStatus va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAPictureParameterBufferType, sizeof(pic_param), 1, &pic_param, &pic_param_buffer); + VAStatus va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, 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); @@ -404,7 +412,7 @@ shared_ptr decode_jpeg_vaapi(const string &jpeg) } VABufferID iq_buffer; - va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAIQMatrixBufferType, sizeof(iq), 1, &iq, &iq_buffer); + va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, VAIQMatrixBufferType, sizeof(iq), 1, &iq, &iq_buffer); CHECK_VASTATUS_RET(va_status, "vaCreateBuffer"); VABufferDestroyer destroy_iq(va_dpy->va_dpy, iq_buffer); @@ -438,7 +446,7 @@ shared_ptr decode_jpeg_vaapi(const string &jpeg) } VABufferID huff_buffer; - va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VAHuffmanTableBufferType, sizeof(huff), 1, &huff, &huff_buffer); + va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, VAHuffmanTableBufferType, sizeof(huff), 1, &huff, &huff_buffer); CHECK_VASTATUS_RET(va_status, "vaCreateBuffer"); VABufferDestroyer destroy_huff(va_dpy->va_dpy, huff_buffer); @@ -468,19 +476,16 @@ shared_ptr decode_jpeg_vaapi(const string &jpeg) parms.num_mcus = horiz_mcus * vert_mcus; VABufferID slice_param_buffer; - va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VASliceParameterBufferType, sizeof(parms), 1, &parms, &slice_param_buffer); + va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, 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. VA-API will destuff and all for us. VABufferID data_buffer; - va_status = vaCreateBuffer(va_dpy->va_dpy, config_id, VASliceDataBufferType, dinfo.src->bytes_in_buffer, 1, const_cast(dinfo.src->next_input_byte), &data_buffer); + va_status = vaCreateBuffer(va_dpy->va_dpy, resources.context, VASliceDataBufferType, dinfo.src->bytes_in_buffer, 1, const_cast(dinfo.src->next_input_byte), &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); - va_status = vaBeginPicture(va_dpy->va_dpy, resources.context, resources.surface); CHECK_VASTATUS_RET(va_status, "vaBeginPicture"); va_status = vaRenderPicture(va_dpy->va_dpy, resources.context, &pic_param_buffer, 1); @@ -547,24 +552,46 @@ shared_ptr decode_jpeg_vaapi(const string &jpeg) #else // Convert Y'CbCr to separate Y' and CbCr. frame->is_semiplanar = true; - frame->y.reset(new uint8_t[dinfo.image_width * dinfo.image_height]); - frame->cbcr.reset(new uint8_t[dinfo.image_width * dinfo.image_height]); + + PBO pbo = global_pbo_pool->alloc_pbo(); + size_t cbcr_offset = dinfo.image_width * dinfo.image_height; + uint8_t *y_pix = pbo.ptr; + uint8_t *cbcr_pix = pbo.ptr + cbcr_offset; + const uint8_t *src = (const uint8_t *)mapped + resources.image.offsets[0]; if (resources.image.pitches[0] == dinfo.image_width * 2) { - memcpy_interleaved(frame->cbcr.get(), frame->y.get(), src, dinfo.image_width * dinfo.image_height * 2); + memcpy_interleaved(cbcr_pix, y_pix, src, dinfo.image_width * dinfo.image_height * 2); } else { for (unsigned y = 0; y < dinfo.image_height; ++y) { - memcpy_interleaved(frame->cbcr.get() + y * dinfo.image_width, frame->y.get() + y * dinfo.image_width, + memcpy_interleaved(cbcr_pix + y * dinfo.image_width, y_pix + y * dinfo.image_width, src + y * resources.image.pitches[0], dinfo.image_width * 2); } } + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.pbo); + frame->y = create_texture_2d(dinfo.image_width, dinfo.image_height, GL_R8, GL_RED, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); + frame->cbcr = create_texture_2d(dinfo.image_width / 2, dinfo.image_height, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, BUFFER_OFFSET(cbcr_offset)); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glFlushMappedNamedBufferRange(pbo.pbo, 0, dinfo.image_width * dinfo.image_height * 2); + glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); + pbo.upload_done = RefCountedGLsync(GL_SYNC_GPU_COMMANDS_COMPLETE, /*flags=*/0); + frame->uploaded_ui_thread = pbo.upload_done; + frame->uploaded_interpolation = pbo.upload_done; + global_pbo_pool->release_pbo(move(pbo)); #endif frame->width = dinfo.image_width; frame->height = dinfo.image_height; frame->chroma_subsampling_x = 2; frame->chroma_subsampling_y = 1; - frame->pitch_y = dinfo.image_width; - frame->pitch_chroma = dinfo.image_width / 2; + + if (dinfo.marker_list != nullptr && + dinfo.marker_list->marker == JPEG_APP0 + 1 && + dinfo.marker_list->data_length >= 4 && + memcmp(dinfo.marker_list->data, "Exif", 4) == 0) { + frame->exif_data.assign(reinterpret_cast(dinfo.marker_list->data), + dinfo.marker_list->data_length); + } va_status = vaUnmapBuffer(va_dpy->va_dpy, resources.image.buf); CHECK_VASTATUS_RET(va_status, "vaUnmapBuffer");