/***********************************************************************************
* 作者:韦访
* 创建日期:2014.6.3
* 说明: 本程序为基于opencv2.4.4的简易yuv420播放器,目的是完成老师安排的任务,拿到实验分
* 使用方法:yuv格式自行去了解,值得注意的是要根据文件名改变帧大小
* 格式: Sub-QCIF 亮度分辨率: 128*96 每帧使用的位: 147456
* 格式: QCIF 亮度分辨率: 176*144 每帧使用的位: 304128
* 格式: CIF 亮度分辨率: 352*288 每帧使用的位: 1216512
* 格式: 4CIF 亮度分辨率: 704*576 每帧使用的位: 4866048
*
* 按ESC退出播放,S暂停播放,左键快退,右键快进,在暂停模式下,L显示前一帧,R显示后一帧,G继续播放,ESC退出
* 可以拖动进度条播放指定位置
在S暂停模式下,按B,出现一个新的滑动窗口,选择将剩下视频分割成n段,按回车键即可出现n个窗口,选择要播放的窗口号码,
回车即可从该窗口开始播放
* 注:本程序是基于opencv的,至于opencv如何安装自己上网查
*
***********************************************************************************/
#include <opencv/highgui.h>
#include <stdio.h>
#include <cv.h>
#include<conio.h>
#define nWidth 352
#define nHeight 288
#define FrameSize ( nWidth*nHeight*3/2) //YUV一帧图像大小
using namespace cv;
int time_slider; //进度条变量
int window_num; //创建窗口数
int pos = 0; //用于寻找下一帧位置
const int ratio_max = 6; //最大分割窗口数
int frame_count; //帧数
int pos_tmp[15];
int pos_step; //分割步长
const char *win_name[]= {"win0","win1","win2","win3","win4","win5","win6"};
//yuv420转rgb函数
void YUV420_2_RGB( unsigned char* pYUV, unsigned char* pRGB , int width, int height);
//进度条反馈函数
void time_trackbar( int, void* );
void ratio_trackbar( int, void* );
int main(int argc, char * argv[])
{
int key;
int save_win = 33;
int win_tmp = -1;
//打开文件
FILE *f ;
if(!(f = fopen("mobile_cif.yuv","rb")))
{
printf("file open error!");
}
//计算有多少帧图像
fseek(f, 0, SEEK_END);
frame_count = (int) ((int)ftell(f)/((nWidth * nHeight * 3) / 2));
printf("tell1 = %d\n",ftell(f));
fseek(f, 0, SEEK_SET);//文件位置定位到文件头
printf("tell2 = %d\n",ftell(f));
//开辟缓冲区存放一帧图片信息
unsigned char *pBuf = new unsigned char[nWidth*nHeight*3/2];
unsigned char *pRGB = new unsigned char[3*nWidth*nHeight];
//创建image,大小为nWidth*nHeight,数据类型为IPL_DEPTH_8U,3通道
IplImage * image = cvCreateImageHeader(cvSize(nWidth, nHeight),IPL_DEPTH_8U,3);
//进度条名称定义
char TrackbarName[50];
char TrackbarName2[50];
sprintf( TrackbarName, "进度%d", frame_count );
sprintf(TrackbarName2, "分割%d", ratio_max );
//创建窗口并命名
cvNamedWindow("wf_yuv_player");
//视频的播放,循环播放
while(1)
{
//借助变量pos准确找到每帧图片的开头位置,并读入pBuf
fseek(f, pos, SEEK_SET);
fread(pBuf,1 , FrameSize, f );
//yuv转rgb,然后将rgb转换进image
YUV420_2_RGB(pBuf,pRGB,nWidth,nHeight);
cvSetData(image,pRGB,nWidth*3);
//显示图片
cvShowImage("wf_yuv_player", image);
//创建进度条
createTrackbar( TrackbarName, "wf_yuv_player", &time_slider, frame_count, time_trackbar );
//等待按键事件发生
key=cvWaitKey(33);
//以下操作位根据按键值做出相应的动作
//ESC按键按下,退出程序
if(key == 27)
{
break;
}
//左键按下,快退,步长为5帧
if ( key == 0x250000 && (time_slider > 5) )
{
pos -= (5*FrameSize);
time_slider -= 5;
}
// 右键按下,快进,步长为5帧
if(key == 0x270000&&(time_slider < frame_count - 5))
{
pos += (5*FrameSize);
time_slider += 5;
}
//如果按下s键则暂停
if(key == 's' || key == 'S')
{
//因为要有单帧播放,所以进入死循环方便单帧操作
while(1)
{
key = cvWaitKey(33);
//如果按下g则继续播放
if(key == 'g'|| key == 'G')
{
break;
}
//ESC按键按下,退出程序
if(key == 27)
{
goto end;
}
//按下l按键,显示上一帧
if((key =='l'|| key =='L') && (time_slider > 0))
{
pos -= FrameSize;
time_slider--;
}
//按下r按键,显示下一帧
if((key =='r' || key =='R') && (time_slider < frame_count ))
{
pos += FrameSize;
time_slider++;
}
// 左键按下,快退
if( key == 0x250000 && (time_slider > 5) )
{
pos -= (5*FrameSize);
time_slider -= 5 ;
}
// 右键按下,快进
if( key == 0x270000 && (time_slider < frame_count - 5) )
{
pos += (5*FrameSize);
time_slider +=5 ;
}
//如果按下B,出现一个滑动条,分割视频
if( key == 'b'|| key == 'B' )
{
save_win = -1;
if(win_tmp >= 0)
cvDestroyWindow(win_name[win_tmp]);
pos_tmp[0] = pos;
createTrackbar( TrackbarName2, "wf_yuv_player", &window_num, ratio_max, ratio_trackbar );
//等待确认
while(key != 0xd)
{
key = cvWaitKey(10);
}
if(window_num < 1)
window_num = 1;
//创建window_num个窗口并显示
for( int a = 0; a < window_num ; a++ )
{
cvNamedWindow(win_name[a]);
if( a )
pos_tmp[a] = pos_tmp[ a - 1] + (pos_step * FrameSize);
fseek(f, pos_tmp[a], SEEK_SET);
fread(pBuf,1 , FrameSize, f );
YUV420_2_RGB(pBuf,pRGB,nWidth,nHeight);
cvSetData(image,pRGB,nWidth*3);
cvShowImage(win_name[a], image);
}
printf("请输入您选中的窗口号: \n");
while(1)
{
save_win = cvWaitKey(10);
if(save_win > 47 && save_win < 48 + window_num)
{
break;
}
}
//printf("pos_step = %d\n", pos_step);
for( int a = 0; a < window_num ; a++)
{
if(a != (save_win - 48))
cvDestroyWindow(win_name[a]);
else
{
pos = pos_tmp[a];
if(pos > frame_count * FrameSize)
pos = frame_count * FrameSize;
win_tmp = a;
time_slider = pos / FrameSize;
}
}
}
//创建进度条
createTrackbar( TrackbarName, "wf_yuv_player", &time_slider, frame_count, time_trackbar );
fseek(f, pos, SEEK_SET);
fread(pBuf,1 , FrameSize, f );
YUV420_2_RGB(pBuf,pRGB,nWidth,nHeight);
cvSetData(image,pRGB,nWidth*3);
cvShowImage("wf_yuv_player", image);
}
}
//每播放一帧,time_slider自加
time_slider++;
pos += FrameSize;
// printf("pos = %d\n", pos);
//播放完后,重新开始播放
if(time_slider > frame_count - 1)
{
pos = 0;
time_slider= 0;
}
}
end:
//释放内存
cvDestroyWindow("yuv_player");
cvReleaseImage(&image);
delete pBuf;
delete pRGB;
fclose(f);
return 0;
}
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 ;
}
}
}
void time_trackbar( int, void* )
{
pos = time_slider * FrameSize;
}
void ratio_trackbar( int, void* )
{
pos_step = (frame_count - time_slider) / ( window_num + 1);
}
Python用OpenCV播放视频迟缓 opencv视频播放器
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。

提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
flv视频流播放
前端播放视频流
ide 视频流 Events -
Opencv 简单视频播放器
最近看了一下[1]_2011_OpenCV 2 Computer Vision Application Programming Cookbook.pdf,写了一个利用Opencv
视频 opencv video ide #include -
opencv播放avi python opencv播放视频速率
1、VideoCapture()括号中写视频文件的名字,在播放每一帧的时候,使用cv2.waitKey()设置适当的持续时间,太低会播放的很快,太高会很慢,通常情况下25毫秒就行了。
opencv播放avi python ide 视频流 编解码器