- JSAMPROW yptr[8], cbptr[8], crptr[8];
- JSAMPARRAY data[3] = { yptr, cbptr, crptr };
- for (unsigned y = 0; y < qf.video_format.height; y += 8) {
- const uint8_t *src = qf.frame->data_copy + field_start + y * qf.video_format.width * 2;
-
- memcpy_interleaved(tmp_y, tmp_cbcr, src, qf.video_format.width * 8 * 2);
- memcpy_interleaved(tmp_cb, tmp_cr, tmp_cbcr, qf.video_format.width * 8);
- for (unsigned yy = 0; yy < 8; ++yy) {
- yptr[yy] = tmp_y + yy * width;
- cbptr[yy] = tmp_cb + yy * width / 2;
- crptr[yy] = tmp_cr + yy * width / 2;
+ PBOFrameAllocator::Userdata *userdata = (PBOFrameAllocator::Userdata *)qf.frame->userdata;
+ if (userdata->pixel_format == PixelFormat_8BitYCbCr) {
+ init_jpeg(width, height, qf.white_balance, &dest, &cinfo, /*y_h_samp_factor=*/2, /*y_v_samp_factor=*/1);
+
+ assert(qf.frame->interleaved);
+ size_t field_start = qf.cbcr_offset * 2 + qf.video_format.width * field_start_line * 2;
+
+ JSAMPROW yptr[8], cbptr[8], crptr[8];
+ JSAMPARRAY data[3] = { yptr, cbptr, crptr };
+ for (unsigned y = 0; y < qf.video_format.height; y += 8) {
+ const uint8_t *src;
+ src = qf.frame->data_copy + field_start + y * qf.video_format.width * 2;
+
+ memcpy_interleaved(tmp_cbcr, tmp_y, src, qf.video_format.width * 8 * 2);
+ memcpy_interleaved(tmp_cb, tmp_cr, tmp_cbcr, qf.video_format.width * 8);
+ for (unsigned yy = 0; yy < 8; ++yy) {
+ yptr[yy] = tmp_y + yy * width;
+ cbptr[yy] = tmp_cb + yy * width / 2;
+ crptr[yy] = tmp_cr + yy * width / 2;
+ }
+ jpeg_write_raw_data(&cinfo, data, /*num_lines=*/8);
+ }
+ } else {
+ assert(userdata->pixel_format == PixelFormat_8BitYCbCrPlanar);
+
+ const movit::YCbCrFormat &ycbcr = userdata->ycbcr_format;
+ init_jpeg(width, height, qf.white_balance, &dest, &cinfo, ycbcr.chroma_subsampling_x, ycbcr.chroma_subsampling_y);
+ assert(ycbcr.chroma_subsampling_y <= 2); // Or we'd need larger JSAMPROW arrays below.
+
+ size_t field_start_line = qf.video_format.extra_lines_top; // No interlacing support.
+ const uint8_t *y_start = qf.frame->data + qf.video_format.width * field_start_line;
+ const uint8_t *cb_start = y_start + width * height;
+ const uint8_t *cr_start = cb_start + (width / ycbcr.chroma_subsampling_x) * (height / ycbcr.chroma_subsampling_y);
+
+ size_t block_height_y = 8 * ycbcr.chroma_subsampling_y;
+ size_t block_height_cbcr = 8;
+
+ JSAMPROW yptr[16], cbptr[16], crptr[16];
+ JSAMPARRAY data[3] = { yptr, cbptr, crptr };
+ for (unsigned y = 0; y < qf.video_format.height; y += block_height_y) {
+ for (unsigned yy = 0; yy < block_height_y; ++yy) {
+ yptr[yy] = const_cast<JSAMPROW>(y_start) + (y + yy) * width;
+ }
+ unsigned cbcr_y = y / ycbcr.chroma_subsampling_y;
+ for (unsigned yy = 0; yy < block_height_cbcr; ++yy) {
+ cbptr[yy] = const_cast<JSAMPROW>(cb_start) + (cbcr_y + yy) * width / ycbcr.chroma_subsampling_x;
+ crptr[yy] = const_cast<JSAMPROW>(cr_start) + (cbcr_y + yy) * width / ycbcr.chroma_subsampling_x;
+ }
+ jpeg_write_raw_data(&cinfo, data, block_height_y);