How to solve the problem of the color disorder of constructing QVideoFrame from YUV420P?
-
Hello,
I have an application that uses QVideoFrame to pass video stream data. The data source is YUV420p data with random width and height.
At certain sizes, there is a color distortion problem when rendering YUV constructed QVideoFrame, and I suspect it's a data alignment issue. Is there a problem with my copying method? Here is my code:QVideoFrameFormat frame_format(QSize(static_cast<int>(width), static_cast<int>(height)), QVideoFrameFormat::Format_YUV420P); frame_format.setViewport(QRect(0, 0, width, height)); frame_format.setColorRange(QVideoFrameFormat::ColorRange::ColorRange_Video); frame_format.setColorSpace(QVideoFrameFormat::ColorSpace::ColorSpace_BT601); frame_format.setColorTransfer(QVideoFrameFormat::ColorTransfer::ColorTransfer_BT601); QVideoFrame frame(frame_format) if (frame.map(QVideoFrame::MapMode::WriteOnly)) { auto src0 = reinterpret_cast<uint8_t*>(data); auto src1 = src + offset[1]; // U offset auto src2 = src + offset[2]; // V offset auto dest0 = reinterpret_cast<uint8_t*>(frame.bits(0)); auto dest1 = reinterpret_cast<uint8_t*>(frame.bits(1)); auto dest2 = reinterpret_cast<uint8_t*>(frame.bits(2)); for (int i = 0; i < frame.mappedBytes(0) / frame.bytesPerLine(0); i++) { memcpy(dest0, src0, qMin(uint32_t(frame.bytesPerLine(0)), stride[0])); dest0 += frame.bytesPerLine(0); src0 += stride[0]; } for (int i = 0; i < frame.mappedBytes(1) / frame.bytesPerLine(1); i++) { memcpy(dest1, src1, rame.bytesPerLine(1)), stride[1])); dest1 += frame.bytesPerLine(1); src1 += stride[1]; } for (int i = 0; i < frame.mappedBytes(2) / frame.bytesPerLine(2); i++) { memcpy(dest2, src2, qMin(uint32_t(frame.bytesPerLine(2)), stride[2])); dest2 += frame.bytesPerLine(2); src2 += stride[2]; } frame.setStartTime(0); frame.unmap(); }
It is worth noting that if I align the image width and height to 16 bits before building QVideoFrame, all sizes will be rendered correctly, like this:
auto adjust_width = (width + 15) & ~15; auto adjust_height = (height + 15) & ~15; QVideoFrameFormat frame_format(QSize(static_cast<int>(adjust_width), static_cast<int>(adjust_height )), QVideoFrameFormat::Format_YUV420P); frame_format.setViewport(QRect(0, 0, width, height)); frame_format.setColorRange(QVideoFrameFormat::ColorRange::ColorRange_Video); frame_format.setColorSpace(QVideoFrameFormat::ColorSpace::ColorSpace_BT601); frame_format.setColorTransfer(QVideoFrameFormat::ColorTransfer::ColorTransfer_BT601); QVideoFrame frame(frame_format) ....
Is it necessary to align the data before constructing QVideoFrame?
-
Hello Shawn and QtCommunity, I am having exactly the same problem. When I load a video it becomes recognized as a YUV420P which reduces the colorspace to 8bit and introduces color distortion. I need the original BT2020 colorspace that the file was encoded in to perform further incredibly fine adjustments. If someone could shed some light on this problem for Shawn and myself that would be great. Thank you -NetR00t