⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 play.c

📁 fs2410下借用SDL.FFMPEG库实现一个触摸屏的播放器程序。请参照源码在相应目录下自己放置一个要播放的MPG文件。
💻 C
字号:
/****************************************************这是一个视频播放器程序,可以实现播放,暂停,停止,快进快退,全屏的功能,由触摸屏进行操作。****************************************************/#include <pthread.h>#include <stdio.h>#include <stdlib.h>
#include <unistd.h>#include "s3c2410_ts.h"#include <SDL/SDL.h>#include <avcodec.h>#include <avformat.h>#include <fcntl.h>
int STATE_GET=3;//thread1与thread2通信的全局变量int PLAY_MAX=0;//控制全屏的标志位int time_flag=0;//当前packet的时间戳SDL_Surface *screen = NULL;//指向当前显示屏幕的信息void ShowBMP(char *file, SDL_Surface *screen,int x, int y);void *thread1(void *);void *thread2(void *);/***************************************************//*主进程,生成两个线程,并等待结束**********//***************************************************/int main(void){    pthread_t t_a;    pthread_t t_b;        pthread_create(&t_a,NULL,thread1,(void *)NULL); //创建进程t_a    pthread_create(&t_b,NULL,thread2,(void *)NULL);//创建进程t_b    pthread_join(t_b, NULL);//等待线程b结束	exit(0);}/********************************************************************************//*信号控制线程,从触摸屏接受信号,并且给STATE_GET赋值**********//*对于一次触摸,仅对这次触摸产生的第一个信号处理,其他的屏蔽***//********************************************************************************/void *thread1(void *junk){   int fileno;	/*触摸屏防抖标志位*/   int fangdou_flag =1;	/*存放从触摸屏上取得的点的信息*/
	TS_EVENT ev;
   	/*初始化ev*/	memset(&ev, 0, sizeof(struct s3c2410_ts_event));
  	/*打开触摸屏设备,并判断是否打开*/
	fileno = open("/dev/ts",O_RDONLY);
	if (fileno == -1) {
		printf("open device error!\n");
		return NULL;
	}
	/*不断从触摸屏上接受信号,判断所在区域,给STATE_GET赋相应的值*/
	while(1)	{		/*从触摸屏上读取信号*/
		if(read(fileno, &ev, sizeof(struct s3c2410_ts_event)))		{ 			/*将触摸屏上的点坐标转化为LCD上的点坐标*/			double i_tmp=2.984,j_tmp=3.708;         ev.x=(unsigned int)((986-ev.x)/i_tmp);			ev.y=(unsigned int)((948-ev.y)/j_tmp);			/*判断触摸屏是否有信号产生,并且是否是产生的第一个信号*/			if ((ev.pressure)&&(fangdou_flag==1))			{				printf("x= %d, y= %d, flag=0x%04x\n", ev.x, ev.y, ev.pressure);				/*如果是非全屏模式*/				if(PLAY_MAX != 9){					/*判定取得的坐标所在的区域*/		      	if ((ev.y>=220)&&(ev.y<=240))					{						if((ev.x>=143)&&(ev.x<=190))							STATE_GET=1;						else if((ev.x>250)&&(ev.x<=275)) 							STATE_GET = 2;						else if((ev.x>50)&&(ev.x<=75))   							STATE_GET = 3;						else if((ev.x>200)&&(ev.x<=245)) 							STATE_GET = 6;						else if((ev.x>90)&&(ev.x<=130))  							STATE_GET = 7;					}					else if((ev.y>=0)&&(ev.y<=20))					{						if((ev.x>=285)&&(ev.x<=320))							STATE_GET=4;						else if((ev.x>261)&&(ev.x<=284)&&(STATE_GET != 6)&&(STATE_GET != 7)) PLAY_MAX= 9;					}			 	}								/*如果是全屏模式,再点击屏幕上的任何位置,都转化为非全屏模式*/				else{ 					if ((ev.y>=0)&&(ev.y<=240))					PLAY_MAX = 8;				}								/*对一次点击接收到的第一个信号处理完毕,此位置0,不再处理一次点击产生的其他信号*/				fangdou_flag = 0;				}			/*如果对触摸屏的触摸停止,则将防抖标志位直为1,开始准备接受信号*/			if(ev.pressure == 0)					fangdou_flag = 1;		}         	} 	/*关闭触摸屏设备*/
   close(fileno);
}/********************************************************************************//*机能控制线程,根据STATE_GET的值,执行相应的动作***************//********************************************************************************/void *thread2(void *junk){	AVFormatContext *pFormatCtx;	int i,videoStream;	AVCodecContext *pCodecCtx;	AVCodec *pCodec;		void ShowBMP(char *file, SDL_Surface *screen,int x, int y);		void mpeg_display(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);	void mpeg_display1(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);	void mpeg_pause();	void mpeg_stop(AVFormatContext *pFormatCtx,SDL_Surface *screen);	void mpeg_close();		void mpeg_back(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);	void mpeg_next(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);		/*注册所有的formats和codecs*/ 	av_register_all ();	/*打开视频文件*/	if (av_open_input_file (&pFormatCtx, "/qinbo/ice_age_short.mpg", NULL, 0, NULL) != 0)		return NULL;  	/*获取视频中的流信息*/          	if (av_find_stream_info (pFormatCtx) < 0)		return NULL;            	/*查找是否有错误信息*/	dump_format (pFormatCtx, 0, "/qinbo/ice_age_short.mpg", false);	/*从文件的流信息中获取第一个视频流*/	videoStream = -1;	for (i = 0; i < pFormatCtx->nb_streams; i++)		if (pFormatCtx->streams[i]->codec.codec_type == CODEC_TYPE_VIDEO)   			{				videoStream = i;				break;			}	if (videoStream == -1)		return NULL;            	/*得到一个指向对应视频流解码器内容的指针*/ 	pCodecCtx = &pFormatCtx->streams[videoStream]->codec;    	/* SDL初始化*/	screen =		SDL_SetVideoMode (pCodecCtx->width, pCodecCtx->height, 0, SDL_HWSURFACE);	SDL_Overlay *overlay =		SDL_CreateYUVOverlay (pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY,screen);	/*找到视频流解码器*/	pCodec = avcodec_find_decoder (pCodecCtx->codec_id);	if (pCodec == NULL)		return NULL;            	/*打开视频流的解码器*/	if (avcodec_open (pCodecCtx, pCodec) < 0)		return NULL;          	/*循环访问STATE_GET的值,并调用相应动作的函数*/	while(1)	{		if(STATE_GET == 1)			{mpeg_display(pFormatCtx,pCodecCtx,overlay,videoStream);}		if (STATE_GET == 2)			{mpeg_pause();}		if (STATE_GET == 3)			{mpeg_stop(pFormatCtx,screen);}		if (STATE_GET == 4)			{mpeg_close();break;}		if (STATE_GET == 6)			{mpeg_next(pFormatCtx,pCodecCtx,overlay,videoStream);}		if (STATE_GET == 7)			{mpeg_back(pFormatCtx,pCodecCtx,overlay,videoStream);}		}		/*释放内存,关闭文件	*/	avcodec_close (pCodecCtx);	av_close_input_file (pFormatCtx);	SDL_FreeYUVOverlay (overlay);	return 0;}  /*********************************************//*正常播放时,解码一frame,播放一次*//*********************************************/void mpeg_display(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream){	int frameFinished=0;	AVFrame *pFrame;  	AVFrame *pFrameYUV;	AVPacket packet;	void mpeg_stop(AVFormatContext *pFormatCtx,SDL_Surface *screen);		if(PLAY_MAX == 8)	{		ShowBMP("/qinbo/panasonic_black.bmp", screen,0, 0);		PLAY_MAX = 0;	}		/*设定显示区域*/	static SDL_Rect rect;	if(PLAY_MAX == 9){		rect.x = 0;		rect.y = 0;		rect.w = pCodecCtx->width;		rect.h = pCodecCtx->height;}	else{		rect.x = 0;		rect.y = 20;		rect.w = pCodecCtx->width;		rect.h = pCodecCtx->height-40;} 			/*将pFrame指针填充*/	pFrame = avcodec_alloc_frame ();	/*将pFrameYUV指针填充*/	pFrameYUV = avcodec_alloc_frame ();	if (pFrameYUV == NULL)	{		printf("error!\n");	}		int packet_STATE_GET=0;	/*从视频中读取一个包*/	packet_STATE_GET=av_read_frame (pFormatCtx, &packet);	/*如果没有读取到最后一个包*/	if(packet_STATE_GET >= 0) 	{			/*读取到的包是视频包么?*/		if (packet.stream_index == videoStream) 		{			/*利用传参的解码器解码视频包,存储在pFrame中*/			avcodec_decode_video (pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);			/*是最后一个包么?*/			if (frameFinished) {				/*将转换化完的 pFrame转化成YUV格式, 并且显示出来*/				SDL_LockYUVOverlay (overlay);				pFrameYUV->data[0] = overlay->pixels[0];				pFrameYUV->data[1] = overlay->pixels[2];				pFrameYUV->data[2] = overlay->pixels[1];				pFrameYUV->linesize[0] = overlay->pitches[0];				pFrameYUV->linesize[1] = overlay->pitches[2];				pFrameYUV->linesize[2] = overlay->pitches[1];				img_convert ((AVPicture *) pFrameYUV, PIX_FMT_YUV420P,(AVPicture *) pFrame, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height);				SDL_UnlockYUVOverlay (overlay);				SDL_DisplayYUVOverlay (overlay, &rect);				SDL_Delay (30);				/* 把当前包中的时间戳记录下来 */				if(packet.pts>0)					time_flag=packet.pts;			}    			/*释放包空间*/			av_free_packet (&packet);		}	}	/*如果视频播放完毕,设置为STOP状态*/	else STATE_GET=3;		/*释放内存*/	av_free (pFrameYUV);	av_free (pFrame);}/*****************************************************//*快进快退时,解码一个关键frame,播放一次*//*****************************************************/void mpeg_display1(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream){	int frameFinished=0;	AVFrame *pFrame;  	AVFrame *pFrameYUV;	AVPacket packet;	void mpeg_stop(AVFormatContext *pFormatCtx,SDL_Surface *screen);		/*设定显示区域*/	static SDL_Rect rect;	if(PLAY_MAX == 9){		rect.x = 0;		rect.y = 0;		rect.w = pCodecCtx->width;		rect.h = pCodecCtx->height;	}	else{		rect.x = 0;		rect.y = 20;		rect.w = pCodecCtx->width;		rect.h = pCodecCtx->height-40;	} 			/*将pFrame指针填充*/	pFrame = avcodec_alloc_frame ();	/*将pFrame指针填充*/	pFrameYUV = avcodec_alloc_frame ();	if (pFrameYUV == NULL)	{		printf("error!\n");	}		int packet_STATE_GET=0;	/*从视频中读取一个包*/   packet_STATE_GET=av_read_frame (pFormatCtx, &packet);	/*如果没有读取到最后一个包*/	if((packet_STATE_GET >= 0)) 	{		/*读取到的包是视频包么?*/		if (packet.stream_index == videoStream) 		{			/*如果是关键frame*/			if(packet.flags==PKT_FLAG_KEY)				{					/*利用传参的解码器解码视频包,存储在pFrame中*/					avcodec_decode_video (pCodecCtx, pFrame, &frameFinished,packet.data,packet.size);					/*是最后一个包么?*/					if (frameFinished) 					{						/*将转换化完的 pFrame转化成YUV格式, 并且显示出来*/						SDL_LockYUVOverlay (overlay);						pFrameYUV->data[0] = overlay->pixels[0];						pFrameYUV->data[1] = overlay->pixels[2];						pFrameYUV->data[2] = overlay->pixels[1];						pFrameYUV->linesize[0] = overlay->pitches[0];						pFrameYUV->linesize[1] = overlay->pitches[2];						pFrameYUV->linesize[2] = overlay->pitches[1];						img_convert ((AVPicture *) pFrameYUV, PIX_FMT_YUV420P,(AVPicture *) pFrame, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height);						SDL_UnlockYUVOverlay (overlay);						SDL_DisplayYUVOverlay (overlay, &rect);						SDL_Delay (200);					}					/*如果是快进状态,把当前包中的时间戳记录下来*/					if(STATE_GET==6){						if(packet.pts>0)							time_flag=packet.pts;					}				}		}		/*释放包空间*/		av_free_packet (&packet);	}		/*如果视频播放完毕,设置为STOP状态*/	else {STATE_GET =3;}	/*释放内存*/	av_free (pFrameYUV);	av_free (pFrame);}/*********************************************//*暂停功能**********************************//*********************************************/void mpeg_pause(){}/*********************************************//*显示一幅BMP图片************************//*********************************************/void ShowBMP(char *file, SDL_Surface *screen,int x, int y){		SDL_Surface *image;	SDL_Rect dest;	/* 将BMP文件加载到一个surface*/	image = SDL_LoadBMP(file);	if ( image == NULL ) {		fprintf(stderr, "无法加载 %s: %s\n", file, SDL_GetError());		 return;	}		/*设定显示区域*/	dest.x = x;	dest.y = y;	dest.w = image->w;	dest.h = image->h;	/*将image中的图片,按照设定的区域,显示到屏幕上*/	SDL_BlitSurface(image, NULL, screen, &dest);	SDL_UpdateRects(screen, 1, &dest);		/*释放image内存*/	SDL_FreeSurface(image);}/**********************************************************************//*停止功能,显示指定图片,将解码指针返回视频最开始位置*//**********************************************************************/void mpeg_stop(AVFormatContext *pFormatCtx,SDL_Surface *screen){	void ShowBMP(char *file, SDL_Surface *screen,int x, int y); 	/*显示指定的图片*/	ShowBMP("/qinbo/panasonic.bmp", screen,0, 0);	/*将解码指针返回视频最开始位置*/	time_flag=0;	av_seek_frame(pFormatCtx, -1,0);	/*控制全屏的标志位置位,设置为非全屏状态*/	PLAY_MAX=8;}/*********************************//*退出功能,将SDL显示退出*//*********************************/void mpeg_close(){	SDL_Quit();	}/**********************************//*快进功能,播放关键frame*//**********************************/void mpeg_next(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream){		void mpeg_display1(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);	mpeg_display1(pFormatCtx,pCodecCtx,overlay,videoStream);}/********************************************************************//*快退功能,通过控制当前时间戳实现,并播放关键frame*//********************************************************************/void mpeg_back(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream){	void mpeg_display1(AVFormatContext *pFormatCtx,AVCodecContext *pCodecCtx,SDL_Overlay *overlay,int videoStream);	/*如果没有退回到起始位置*/	if(time_flag>=0){		/*通过控制时间戳,将当前解码指针回退,如果成功*/		if((time_flag=time_flag-40000,av_seek_frame(pFormatCtx, videoStream,time_flag))>=0)		/*播放关键frame*/			mpeg_display1(pFormatCtx,pCodecCtx,overlay,videoStream);	}	/*如果退回到起始位置,回到stop状态*/	else {		mpeg_stop(pFormatCtx,screen)	;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -