- unsigned luma_height_blocks = mcu_height_blocks * dinfo.comp_info[0].v_samp_factor;
- unsigned chroma_height_blocks = mcu_height_blocks * dinfo.comp_info[1].v_samp_factor;
-
- // TODO: Decode into a PBO.
- frame->y.reset(new uint8_t[luma_width_blocks * luma_height_blocks * DCTSIZE2]);
- frame->cb.reset(new uint8_t[chroma_width_blocks * chroma_height_blocks * DCTSIZE2]);
- frame->cr.reset(new uint8_t[chroma_width_blocks * chroma_height_blocks * DCTSIZE2]);
- frame->pitch_y = luma_width_blocks * DCTSIZE;
- frame->pitch_chroma = chroma_width_blocks * DCTSIZE;
-
- if (!error_mgr.run([&dinfo, &frame, v_mcu_size, mcu_height_blocks] {
- JSAMPROW yptr[v_mcu_size], cbptr[v_mcu_size], crptr[v_mcu_size];
- JSAMPARRAY data[3] = { yptr, cbptr, crptr };
+
+ PBO pbo = global_pbo_pool->alloc_pbo();
+ const size_t chroma_width = dinfo.image_width / frame->chroma_subsampling_x;
+ const size_t chroma_height = dinfo.image_height / frame->chroma_subsampling_y;
+ size_t cb_offset = dinfo.image_width * dinfo.image_height;
+ size_t cr_offset = cb_offset + chroma_width * chroma_height;
+ uint8_t *y_pix = pbo.ptr;
+ uint8_t *cb_pix = pbo.ptr + cb_offset;
+ uint8_t *cr_pix = pbo.ptr + cr_offset;
+ unsigned pitch_y = luma_width_blocks * DCTSIZE;
+ unsigned pitch_chroma = chroma_width_blocks * DCTSIZE;
+
+ 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<char *>(dinfo.marker_list->data),
+ dinfo.marker_list->data_length);
+ }
+
+ if (!error_mgr.run([&dinfo, &y_pix, &cb_pix, &cr_pix, pitch_y, pitch_chroma, v_mcu_size, mcu_height_blocks] {
+ unique_ptr<JSAMPROW[]> yptr(new JSAMPROW[v_mcu_size]);
+ unique_ptr<JSAMPROW[]> cbptr(new JSAMPROW[v_mcu_size]);
+ unique_ptr<JSAMPROW[]> crptr(new JSAMPROW[v_mcu_size]);
+ JSAMPARRAY data[3] = { yptr.get(), cbptr.get(), crptr.get() };