嵌入式linux中mplayer播放視頻編程實踐

    用android或是QT來開發視頻播放程序相對來說比較簡單,如果是在linux用純C語言來進行開發,就顯得比較麻煩,好在現在有很多開源項目能夠幫助我們做什麼事情,mplayer就是音視頻播放開源項目中典型的例子。

    首先需要去mplayer官方網站mplayer下載地址下載源代碼,然後使用你的交叉編譯工具進行編譯,編譯完成後會生成一個mplayer執行程序,在命令行執行mplayer就可以進行播放了。

    但是,用c語言編程來實現mplayer的播放功能怎麼實現呢,本文就來講講一個簡單的mplayer播放器的實現。

一 、 創建一個管道,進行進程間通信

int fd_fifo;
int g_sock_pair[2]; //全雙工管道標識符
int sock_stop_mplay[2];
char video_list[VIDEO_MAX_NUM][30];


void mplayer_init(void)
{
	int sockID;
	
	sockID=socketpair(AF_UNIX, SOCK_STREAM, 0, g_sock_pair);//建立全雙工管道
	if(sockID)
	{
	    printf("the pipe is not contructed\n");
	    exit(0);
	}
	else
	{
	    IfPlay = FALSE;//設置標識符初始狀態
	    IfStop = TRUE;
	    IfPause = FALSE;
	    IfQuit = TRUE;
	    video_over = FALSE;
	}
	
	if(pipe(sock_stop_mplay)<0)
	{
        printf("stop mplay pipe create error\n");
        return ;
    }
    
}

二 、 獲得視頻播放目錄的文件個數

int mplayer_get_video_name(void)
{
    int i;
    int num;
	int total_num;
	struct dirent **namelist;
    char *filepath = "usr/video/";
	memset(&video_list,0,sizeof(video_list));
	num = scandir(filepath,&namelist,0,alphasort);
	printf("the video num is: %d\n",num);
	if(num < 0)return -1;
	if(num > VIDEO_MAX_NUM)
	{
	    num = VIDEO_MAX_NUM;
	}
    for(i=0;i<num-2;i++)
    {
        strcpy(video_list[i],namelist[i+2]->d_name);
    }
	total_num = num-2;
	return total_num;
	printf("video name:%s \n",video_list[0]);
}

三 、 mplayer播放器的實現

void video_play(void)
{
    pid_t pid;
	pid_t pid1;
	FILE * fp;
	
	char buf[1024];
	
	int mark = 0; //播放標誌
    printf("the pid is %d\n",getpid());

	mplayer_init();
	 
	unlink("/usr/my_fifo");                 //如果管道存在,則先刪除  
    mkfifo("/usr/my_fifo",O_CREAT|0666);  
    perror("mkfifo"); 
	fd_fifo=open("/usr/my_fifo",O_RDWR);
	  

	int pipe_fd[2]; //用於進程ID通信
	int r_num;
	char pipe_buf[100]; 
	memset(pipe_buf,0,100);
	
	if(pipe(pipe_fd)<0)
	{
        printf("pipe create error\n");
        return ;
    }
	
    pid = fork();
	if(pid == 0)
	{
	    char temp[100];
		memset(temp,0,sizeof(temp));
		printf("pid xxx= %d\n",getpid());
	    sprintf(temp,"%d",getpid());
		close(pipe_fd[0]);
        if(write(pipe_fd[1],temp,strlen(temp))!=-1)
        printf("child write success!\n");
		
	   
	    if((pid1=fork())==0)
	    {	

	        //close(g_sock_pair[0]);  
            //dup2(g_sock_pair[1],1); //將子進程的標準輸出重定向到管道的寫端
            
            int video_num = 0;
			char *videoname;
			int total_num;
			char stop_cmd[20];
            total_num = mplayer_get_video_name();		
            while(1)
            {
                if(mark)
		        {
		            
		            video_num++;	
					printf("video_num = %d\n",video_num);
	                if(video_num >= total_num)
		            {
		                video_num = 0;
						printf("video_num more than total_num\n");
	                }
		        }			
		        videoname = video_list[video_num];
				char videopath[50] = "/storage/unit_app/video/";
	            char sPlay[100]="mplayer -ao alsa -vo fbdev -vc on28190 -fs -slave -quiet -input file=/storage/my_fifo ";
		        strcat(videopath,videoname);
			    strcat(sPlay,videopath);
	            mplayer_background_pic();
			
	            memset(stop_cmd,0,20);
	            printf("begin play the video!\n");
				fp = popen(sPlay, "r"); 
	            if(fp ==NULL)
	            {
	                perror("popen");
		            exit(-1);
	            }
	            else
	            {
	                while(fgets(buf, sizeof(buf), fp)) 
	                {
	                    printf("%s", buf);
	                }
					printf("one video end play\n");
		            pclose(fp);
				    mark = 1;
	            }
				
				usleep(30000);
				fcntl(sock_stop_mplay[0], F_SETFL, O_NONBLOCK);
				read(sock_stop_mplay[0],stop_cmd,20);
				if(strcmp(stop_cmd,"stop")==0)
		        {
		            mark = 0;
					printf("rev the stop cmd \n");
                    break;	    
                }	
				printf("end the play pthread\n");
            }
			exit(0);
	    }
		if (waitpid(pid1, NULL, 0) != pid1) 
        {   
            fprintf(stderr,"Waitpid error!\n");   
            exit(-1);   
        }
        exit(0);
	}
	else if(pid >0)
	{
	    close(pipe_fd[1]);
        usleep(30000);
        if((r_num=read(pipe_fd[0],pipe_buf,100))>0)
		{
            printf("%d numbers read from be pipe is %s\n",r_num,pipe_buf);
		    childs_pid = atoi(&pipe_buf);
        }	
	}
}

四、 mplayer的結束程序

void video_stop(void)
{
    pid_t pid;
    char cmd[100];
	memset(cmd,0,100);
	sprintf(cmd,"kill -9 %d",childs_pid);
	
    char stop_cmd[20];
	memset(stop_cmd,0,20);
	sprintf(stop_cmd,"stop");
	
	mplayer_send_cmd("quit\n");

	if(write(sock_stop_mplay[1],stop_cmd,strlen(stop_cmd))!=-1)
    printf("write stop cmd success!\n");
	//clear_fb();
	printf("kill childs_pid %d\n",childs_pid);
    system(cmd); 
	mplayer_del();
	
}

void mplayer_send_cmd(char *cmd)
{
    write(fd_fifo,cmd,strlen(cmd));
}


void mplayer_del(void)
{
    close(g_sock_pair[0]);//關閉管道
    close(g_sock_pair[1]);
    close(sock_stop_mplay[0]);
    close(sock_stop_mplay[2]);
    wait(NULL);//收集子進程信息
}


OK,只要實現上述代碼,基本的mplayer播放器就可以實現了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章