小学期实践: 在S3C2440上移植Mplayer
硬件平台:
Micro2440开发板
主机系统:
RedHat Linux AS5
交叉编译器:
arm-Linux-gcc-4.3.2
源程序:
libmad-0.15.1b.tar.gz
MPlayer-1.0rc2.tar.bz2
步骤:
1、搭建交叉编译环境(略)
2、编译安装库文件libmad
3、编译安装MPlayer
-------------------------------------------------------------------------------------
2.
编译安装库文件libmad
tar zvxf libmad-0.15.1b.tar.gz
./configure CC=arm-linux-gcc --host=arm-linux --disable-shared --disable-debugging --prefix=/workspace/micro2440/libmad/mad
make
完成之后会出现“--fforce-mem”相关的错误,打开Makefile文件,并找到并删除“--fforce-mem”选项,然后重新make一次就OK了,原因是gcc4.3.2已经将“--fforce-mem”选项去除了,所以会出现上面的错误。
make install
安装完成后,在/workspace/micro2440/mad/目录下,会生产两个子目录include和lib
可能报错:
checking for C compiler default output file name... configure: error: C compiler cannot create executables
See `config.log' for more details.
----检查交叉工具的安装 我是直接root登录 重新configure一次就行了
---------------------------------------------------------------------------------------
3、编译安装MPlayer
tar jxvf MPlayer-1.0rc2.tar.bz2
cd /workspace/micro2440/mplayer/MPlayer-1.0rc2
./configure --host-cc=gcc --cc=arm-linux-gcc --target=arm --enable-static --disable-win32dll --disable-dvdread --disable-dvdread-internal --disable-dvdnav --disable-libdvdcss-internal --enable-fbdev --disable-mencoder --disable-live --enable-mad --enable-libavcodec_a --disable-live --with-extraincdir=/workspace/micro2440/libmad/mad/include --with-extralibdir=/workspace/micro2440/libmad/mad/lib 2>&1 | tee logfile
•配置项解释
ü--enable-mad 是使用libmad支持.
ü--disable-dvbhead --disable-dvdread --disable-dvdnav --disable-dvdread-internal 都是跟DVD相关库
ü--enable-fbdev 打开framebuffer支持.ARM开发板必须的.
ü--enable-static 设置静态连接,如果使用静态编译尺寸大约是8M,动态编译是6M多,这样可能是无论哪种编译方式,mplayer都把自带的解码库链接到自身,多出2M应该是系统标准库的尺寸。
ü--disable-mencoder 禁止编码功能
ü--disable-live 禁止live 555流媒体
ü--enable-libavcodec_a 启用静态的libavcodec解码
make
如果出现不支持pld[r1]指令的问题
在MPlayer-1.0rc2/libmpeg2/motion_comp_arm_s.S文件
和MPlayer-1.0rc2/libavcodec/armv4l/dsputil_arm_s.S文件的开始处写入
#ifndefHAVE_PLD
.macro pldreg
.endm
#endif
重新 make
----------------------------------------------------------------------------------------------
测试运行
•将mplayer复制到相应的nfs,确保视频文件和音频文件在同一目录
•播放视频:
./mplayer panda.mpg -framedrop -quiet -vf rotate=1
•或者:
./mplayer panda.mpg
•
•播放音频:
./mplayerNew_Soul.mp3
•如果只有视频,而没有声音,这是因为目标系统上有/dev/dsp音频设备文件,但是是OSS音频驱动需要的是/dev/sound/dsp设备文件,这问题的简单解决方法是建一个符号链接
#mkdir -p /dev/sound
#ln -s /dev/dsp /dev/sound/
----------------------------------------------------------------------------------------------
mplayer运行在slave模式下,用一个程序控制mplayer
在前面已经成功编译mplayer
的基础上,我们进一步研究mplayer
另一种重要的运行模式--slave
模式。并且编写一个多线程的程序,通过这个程序来控制mplayer
播放音视频文件
实际上,带有图形界面的mplayer播放器,例如用QT开发的mplayer播放器,就是利用mplayer运行在slave模式下的原理
•简介:
–默认mplayer是从键盘上获得控制信息
–mplayer另外提供了一种更为灵活的控制方式,用来进行播放控制——slave模式
–在slave模式下,MPlayer为后台运行其他程序,不再截获键盘事件
–MPlayer会从标准输入读一个换行符(\n)分隔开的命令。
•操作:
–#mplayer -input cmdlist
//会打印出一份当前mplayer所支持的所有slave模式的命令
方法一:从控制台输入控制命令(测试使用)
运行mplayer-slave -quiet <movie>,并在控制台窗口输入slave命令。
//-slave启动从模式
//-quiet不输出冗余的信息
例如:
./mplayernew_soul.mp3 -slave -quiet
或者:
./mplayerpanda.mpg -slave -quiet
常用的 Mplayer指令:
•loadfile string //参数string为歌曲名字。
•mute1/0//静音开关
•pause//暂停/取消暂停
•get_time_length//返回值是播放文件的长度,以秒为单位。
•seekvalue //向前查找到文件的位置播放参数value为秒数。
•get_percent_pos//返回文件的百分比(0--100)
•get_time_pos//打印出在文件的当前位置用秒表示,采用浮点数
•volume<value> [abs] //增大/减小音量,或将其设置为<value>,如果[abs]不为零
•get_file_name//打印出当前文件名
•get_meta_album//打印出当前文件的'专辑'的元数据
•get_meta_artist//打印出当前文件的'艺术家'的元数据
•get_meta_comment//打印出当前文件的'评论'的元数据
•get_meta_genre//打印出当前文件的'流派'的元数据
•get_meta_title//打印出当前文件的'标题'的元数据
•get_meta_year//打印出当前文件的'年份'的元数据
方法二:从有名管道(fifo)输入控制命令(应用编程中使用)
#mkfifo</tmp/fifofile>
#mplayer -slave -input file=</tmp/fifofile><movie>
//用户可以通过往管道里写入slave命令来实现对应的功能
-----------------------------------------------------------------
任务:
•这里给出一个原始的程序mplayer-slave-cmd.c,这个程序是个多线程的程序,该程序以slave模式启动mplayer播放器,但是这个程序本身也有些bug,我们的任务就是先仔细阅读程序,然后修改这些bug。
•注意:编译这个程序前,需要先设置交叉编译环境;运行该程序时,确保本程序、mplayer以及相应的音频或者视频文件在同一路径下。
编译命令:
arm-linux-gccmplayer-slave-cmd.c -o mplayer-slave-cmd –lpthread
提示:编译多线程的程序,参数-lpthread不能少
任务1:
1、程序运行之后,在mplayer没有信息输出的情况下,仍然不断输出“the msg read form pipe is”,怎样
修改程序,才能让程序在mplayer有信息输出的情况下,才输出该信息;而mplayer没有信息输出的情况
下,该信息不会出现?
注:这个问题有时一运行就会出现,有时在输入quit命令之后才会出现。
提示:判断管道读取的内容
任务2:
正常的信息输出顺序应该是“pleaseinput you cmd:”和“themsgread form pipe is”交替出现
(蓝色字体为用户输入的命令)
例如:
pleaseinput you cmd:get_time_pos
*get_time_pos
*
themsgread form pipe is ANS_TIME_POSITION=40.6
pleaseinput you cmd:
但是实际会出现下面这种情况:
pleaseinput you cmd:get_time_pos
*get_time_pos
*
pleaseinput you cmd:thmsgread form pipe is ANS_TIME_POSITION=40.6
请修改程序解决这个问题
提示:使用usleep函数,usleep(n)表示sleepn微秒
任务3:
•本程序并没有结束线程和退出的命令,请修改程序,在输入“quit”命令时(退出mplayer的命令),也退出本程序。
-----------------------------------------------------------
贴上修改完的C文件:mplayer-slave-cmd.c
- #include <pthread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <string.h>
-
- #define MS 1000 /*usleep()*/
- #define REC_MSG_CHNUM 100 /*received the number of characters message*/
-
-
- int fd_fifo;
- int fd_pipe[2];
-
- pthread_t tid1;
- pthread_t tid2;
-
-
- void *get_pthread(void *arg)
- {
- char buf[REC_MSG_CHNUM];
-
- while(0 != strncmp(buf, "quit", 4)) {
- printf("please input you cmd:");
- fflush(stdout);
- fgets(buf, sizeof(buf), stdin);
- buf[strlen(buf)] = '\0';
- printf("*%s*\n", buf);
-
-
- if (write(fd_fifo, buf, strlen(buf)) != strlen(buf))
- perror("write");
-
- usleep(50*MS);
- }
-
- pthread_cancel(tid2);
- printf("print pthread exit!\nget pthread exit!\n");
- }
-
-
- void *print_pthread(void *arg)
- {
- int size = 0;
- char buf[REC_MSG_CHNUM];
- close(fd_pipe[1]);
-
- while(1) {
-
-
-
-
-
-
- if ((size=read(fd_pipe[0], buf, sizeof(buf))) == -1) {
- perror("read pipe");
- exit(0);
- }
- if(size == 0)
- continue;
- buf[size] = '\0';
- printf("the msg read form pipe is: %s\n", buf);
- }
- }
-
- int main(int argc, char* argv[])
- {
- int fd, ret;
- char buf[100];
- pid_t pid;
-
- unlink("/tmp/my_fifo");
- mkfifo("/tmp/my_fifo",O_CREAT|0666);
- perror("mkfifo");
-
- if (pipe(fd_pipe)<0) {
- perror("pipe error\n");
- exit(-1);
- }
-
- pid = fork();
- if (pid < 0) {
- perror("fork");
- }
- if (pid == 0) {
- close(fd_pipe[0]);
- dup2(fd_pipe[1], 1);
- fd_fifo = open("/tmp/my_fifo",O_RDWR);
-
-
- execlp("./mplayer", "mplayer", "-slave", "-quiet", "-input", "file=/tmp/my_fifo", "new.mp3", NULL);
- } else {
- fd_fifo = open("/tmp/my_fifo", O_RDWR);
- if (fd < 0)
- perror("open");
-
- ret = pthread_create(&tid1, NULL, get_pthread, NULL);
- if (ret != 0) {
- printf("Create get thread error\n");
- return ret;
- }
-
- ret = pthread_create(&tid2, NULL, print_pthread, NULL);
- if(ret != 0)
- {
- printf("Create print thread error\n");
- return ret;
- }
-
- pthread_join(tid1, NULL);
-
-
- printf("\nprocess exit!\n");
- }
- return 0;
- }