视觉媒体通信作业记录(一) 简易yuv420视频播放器

作业要求
编程实现YUV420格式视频(无压缩)播放器
输入:YUV420格式视频
关键技术:视频源格式、视频显示格式、格式转换
yuv420格式视频下载
地址链接:
http://trace.eas.asu.edu/yuv/index.html
http://media.xiph.org/
实现方案
本方案基于opencv3.4.4,采用c++开发完成;
1.首先打开yuv420文件,通过总数据量与一帧数据量之比,求得视频总的帧数;
2.然后循环读取每一帧的数据进入缓冲区,通过编写yuv转rgb的函数,将缓冲区内一帧的数据转换为Mat类数据类型,并进行显示;
3.每一帧同时检测按键事件,并对视频进行对应的操作,之后循环读取下一帧,存储、转换并显示。
实现重点
1.yuv420格式到RGB格式的转换;
事实上,opencv已经提供了yuv420到rgb的格式转换函数,但老师为了让我们更好的理解其中的原理,还是让我们自己写一下;
其实原理还是很容易弄懂得,这儿就不详细说了,网上相关的解释很多,一搜就行,
主要就是这3个公式:

  R = Y + 1.402* (V - 128); //R
  G = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128); //G
  B = Y + 1.772 * (U - 128); //B

在这里插入图片描述

贴一下转换代码,自己写对于我们这个专业来说确实不好写,但看懂还是挺容易的,建议大家最好看懂哦,别答辩时候让老师问住了;

//公式计算
void YUV420_2_RGB( unsigned char* pYUV, unsigned char* pRGB , int width, int height)  
{  
	//找到Y、U、V在内存中的首地址
    unsigned char* pY = pYUV;   
    unsigned char* pU = pYUV+height*width;  
    unsigned char* pV = pU+(height*width/4);  
    
    unsigned char* pBGR = NULL;  
    unsigned char R = 0;  
    unsigned char G = 0;  
    unsigned char B = 0;  
    unsigned char Y = 0;  
    unsigned char U = 0;  
    unsigned char V = 0;  
    double temp = 0;  
    for ( int i = 0; i < height; i++ )  
    {  
        for ( int j = 0; j < width; j++ )  
        {  
            //找到相应的RGB首地址
			pBGR = pRGB+ i*width*3+j*3;  
  
			//取Y、U、V的数据值
            Y = *(pY+i*width+j);  
            U = *pU;  
            V = *pV;  
  
          //yuv转rgb公式
            //yuv转rgb公式
            temp = Y + ((1.773) * (U-128));  
            B = temp<0?0:(temp>255?255:(unsigned char)temp);
         
            temp = (Y - (0.344) * (U-128) - (0.714) * (V-128) )  ;  
            G= temp<0?0:(temp>255?255:(unsigned char)temp);
 
            temp =(Y + (1.403)*(V-128))  ;  
            R =temp<0?0:(temp>255?255:(unsigned char)temp);
           
			//将转化后的rgb保存在rgb内存中,注意放入的顺序b是最低位
            *pBGR     = B;              
            *(pBGR+1) = G;          
            *(pBGR+2) = R;  
           
            if (  j % 2 != 0)  
            {  
                *pU++;  
				*pV++; 
            }  
           
        }  
      if(i % 2 == 0)
	  {
			pU = pU -  width/2 ;
			pV = pV -  width/2 ;
	  }
    }  
}  

2.支持的播放帧
这个用opencv自带的函数测一下就行了,第一次用opencv的话,可能不知道;

 time1 = static_cast<double>(cv::getTickCount());
 time2 = static_cast<double>(cv::getTickCount());
 frame_num = frame_count/((time2 - time1)/cv::getTickFrequency());

注意问题
说一下我以及我同学遇到的一些问题:
(1)opencv建议装3.x.x的,别太新(这我倒是一直都清楚,只是他们没问我),可以避免一些问题吧;
(2)网上找的代码,改了半小时还跑不通的话,那应该是你环境有问题;
(3)推荐一手vscode,比vs好用多了,又小又方便,再顺便vscode上的彩虹屁插件,直接起飞好吧!!!

大致就这些,暂时没想到其他东西了,,,相关内容,网上资料还是很丰富的。
顺便祝大家写作业愉快!!!

猜你喜欢

转载自blog.csdn.net/weixin_45774698/article/details/123965078