Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a .yuv file, which contains frames 560x320 in YUV420p format and i want to play it, by decoding each frame to RGB using opencv. I counted, that size of the one frame must be 268800 bytes (560x320x12 bits /8 because YUV420p have 12 bit per pixel).

So i opening file and reading it frame by frame, storing each 268800 bytes in QByteArray:

qint64 SIZE_OF_YUV420p_FRAME = 268800;
QByteArray  sendBuffer;
   QFile file("/home/YUVdecoding/small.yuv");
if(file.open(QIODevice::ReadOnly))
       while (!file.atEnd()) {
             sendBuffer = file.read(SIZE_OF_YUV420p_FRAME); //capture one frame
             cv::Mat yuvImg = cv::Mat(560+280,320,CV_8UC1,sendBuffer.data()); //translating QByteArray to Mat
             cv::Mat rgbImage;
             cv::cvtColor(yuvImg,rgbImage,cv::COLOR_YUV420p2RGB);// converting to RGB
             cv::imshow("bgr",rgbImage);
             cv::waitKey(30);
    file.close();

Why yuvImg rows are 560+280? Because with 560 its fatal error, and i dont know why.Then i found this code snippet in the internet:

QVideoFrame copy(frame);
if (frame.isValid() && copy.map(QAbstractVideoBuffer::ReadOnly)) {
  Mat frameYUV=Mat(copy.height() + copy.height()/2, copy.width(),CV_8UC1, (void*)copy.bits() );
  Mat frameRGB;
  cvtColor(frameYUV, frameRGB, CV_YUV2BGRA_I420);
  imshow("Video", frameRGB);

So here its height + height/2 and i tried it (560 / 2 = 280). Suddenly, it works, video playing well, but all frames looks like this:

It even have a wrong resolution.

Original frame,in .yuv file looks like this:

I played wit another Mat sizes and yes, it afffects on how properly image is showing, but i can't reach original frame look. How to create Mat from QByteArray properly? How to count proper Mat size?

Check the image format (channels) - the errors you are seeing seems to be something like trying to display an RGBA mat as a RGB, for instance. That could mess up with your image's width and height, and also cause this mess with pixels you are seeing... – Leonardo Alves Machado Dec 29, 2017 at 11:32 @ZubkoArtyom See @ Leonardo's reply. And another problem is that you say your image depth is 12 byte, so it shouldn't be convert mat directly. You may transfer it to 8 byte arrays by hand(or by Qt if exists API), then to Mat. Look for Mat constuctor to make sure width/height order. May be swap height() and width(). – Kinght 金 Dec 29, 2017 at 12:02 @Silencer, @ Leonardo thanks for answers, i carefully inspect cv::Mat and it ws my mistake – Zubko Artyom Dec 29, 2017 at 19:55

Founded solution: cv::Mat rows and cols must be cv::Mat yuvImg = cv::Mat(320+320/2,560,CV_8UC1,sendBuffer.data());instead of 560+280,320. Strange that it decoding 12bit image properly with 8bit setup, but its working perfect

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.