用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播放器就可以實現了。