zoukankan      html  css  js  c++  java
  • Linux下使用被动模式调用MPlayer

      首先说明,虽然我已经成功地做到了调用MPlayer并给它发送命令然后读取结果,但是具体的过程细节到底是怎样的我还不是很清楚。同样是因为这样的原因,我在文中的叙述可能有技术上的错误,欢迎指正

    popen()函数用于打开一个进程,返回结果是一个FILE*类型,这个返回值根据打开方式的不同,分别指向使用popen()打开的程序的输入流或输出流,可以直接当成一个普通文件来使用。

    popen()的第一个函数是命令行,就是要执行的程序的命令,第二个参数可以是"r“或"w",这和fopen是差不多的,一个是读取,这时候返回结果可以当成打开的进程的输出流,另一个w就是输入,返回结果可以当成打开进程的输入流

    popen()函数实际上是一个封装好的用于进程间管道通信的函数,可惜的是它的第二个参数不能是"rw",只能是r或w。因为我们要从MPlayer的输出流读取返回的信息,所以这里要使用"r“参数。

    这样我们就不能直接从标准输入给MPlayer输入指令了。不过没关系,MPlayer提供了被动模式,可以从一个FIFO文件中给MPlayer输入指令。只要在调用MPlayer的时候使用 -slave -input file=path 参数就可以了

    因为 -input file=path 里面的path是一个FIFO文件,所以我们必须先创建一个这样的管道。使用unlink()和mkfifo()函数就可以做到。这里我们使用/tmp/cmd作为FIFO文件,代码如下

    1. unlink("/tmp/cmd");  
    2. mkfifo("/tmp/cmd", 0777);  

    之后就可以使用popen()来打开MPlayer了,代码如下

    1. FILE* mp;  
    2. mp = popen("mplayer '/home/xx/video.mkv' -quiet -slave -input file=/tmp/cmd""r");  

    其中的-quiet参数是让MPlayer以静默模式运行,不要输出太多的信息,这样方便我们获取输入指令后返回的结果

    MPlayer提供了一些指令,利用这些指令我们可以得到当前播放的信息和控制播放器,这些指令可以在终端中输入下面的指令查看

    mplayer -input cmdlist

    接下来就应该给MPlayer输入指令了。刚才已经使用mkfifo建立了管道,现在我们就把指令输入到这个管道里面,这样MPlayer就能收到指令,并输入结果了。结果我们可以在mp这个变量中通过普通的文件操作来读取出来。

    在终端中输入 echo command > /tmp/cmd ,这样就可以将command写入/tmp/cmd这个FIFO文件。我们要在程序中进行写入,可以使用system()函数。现在我想给MPlayer发送一个get_time_pos指令,这个指令可以获取当前影片的播放时间,代码如下

    1. system("echo \"get_time_pos\" > /tmp/cmd");  

    这样指令就发送给MPlayer了,之后我们就可以从通过mp变量这个文件指针读出MPlayer的返回信息。因为MPlayer可能返回其他不相关的播放信息,我们要精确获取get_time_pos指令返回的结果,所以不能直接就把mp中的内容读取出来,这里需要做一些判断。在终端中调用MPlayer以后试着输入get_time_pos指令,可以看到返回的结果是 ANS_TIME_POSITION=%f 这样的形式,于是代码就可以这样写

    1. double timepos;  
    2. char buf[1000];  
    3. do{  
    4.     fgets(buf, 1000, mp);  
    5. }while((strncmp(buf, "ANS_TIME_POSITION=", strlen("ANS_TIME_POSITION=")) != 0);  
    6. timepos = atof(buf + strlen("ANS_TIME_POSITION="));  

    这样就完成了被动调用MPlayer,并给MPlayer发送指令然后读取信息。

    实际上这就是我正在开发的字幕软件ytsub所用的方法。

    最后完整的代码如下,这段代码很简单,只实现了使用被动模式调用MPlayer,然后输出当前的播放时间。头文件我忘记要包含哪些了,这里就省略了。

    1. FILE* mp;  
    2. char buf[1000];  
    3. float timepos;  
    4.   
    5. unlink("/tmp/cmd");  
    6. mkfifo("/tmp/cmd", 0777);  
    7. popen("mplayer -quiet -slave -input file=/tmp/cmd '/home/gs/test.mkv'");  
    8. //这里可能要停顿一下等待MPlayer开始播放,可以利用sleep()函数,我就不停顿了,直接输入命令了  
    9.   
    10. system("echo \"get_time_pos\" > /tmp/cmd");  
    11. do{  
    12.     fgets(buf, 1000, mp);  
    13. }while((strncmp(buf, "ANS_TIME_POSITION=", strlen("ANS_TIME_POSITION=")) != 0);  
    14. timepos = atof(buf + strlen("ANS_TIME_POSITION="));  
    15.   
    16. printf("%lf\n", timepos);  

    好吧我连main()都省略了……好孩子别学我这样子

  • 相关阅读:
    TDengine社区版
    进程&线程
    I2总线
    S3C2440的GPIO编程
    NPN&PNP
    旁路电容和去耦电容
    战胜C语言中令人头疼的问题
    今天神经有点大。。
    JZs3c2440裸板程序GPIO操作总结
    JZs3c2440学习笔记一
  • 原文地址:https://www.cnblogs.com/hnrainll/p/2028848.html
Copyright © 2011-2022 走看看