这个播放器挺神奇的,要说不带界面也不是不行。可以在有做播放器需求的时候,把它拿来套个壳,当作播放器内核来使用。
最近有一个需求,要做个播放视频的功能。但是这东西,有音画同步,有缓冲,什么什么的各种要做的。要搞的东西挺多也比较复杂,讲真我是很不想去弄。但是需求还是要做的,就找各种各样现成的东西来试试看能不能套进去用。
我最初从文件到解码后的视频数据和音频数据这一部分,调用FFMPEG来做,它提供了从读取文件、拆分文件中的数据流、解码数据流整个过程中所需要的功能。但是得到解码后的数据之后,想要播放它还是要做缓冲和音画同步这类事情,在这个时候,我感到里面的不确定因素有点多,需要经验,可能会有卡个很久才能搞定的坑;这个坑自己挖有点太大了,就希望能有更直接的、套上去就能用的东西……
然后这个时候就想起了这么件事。很早以前大概高中的时候吧,用过一个叫MPlayer的播放器。它给我印象比较深的原因,是我用Windows下其他的播放器(当时用的那些播放器都是DirectShow的,然后FFDShow来解码)播放720p XviD的动画片,机器带不动,声音和画面不同步,画面越来越慢。但是MPlayer可以音画同步地播放。但是MPlayer的界面不太好看和方便,后来也用了个叫SMPlayer的播放器,这个播放器和普通的播放器长得差不多,但是它却是调用单独的exe程序来播放,这个播放器做了个图形界面。但是它却能把播放的视频的画面显示在自己的界面上面。界面的exe和播放器核心的exe之间是怎么通信的,以前也没有注意或者留意过,现在有这样需求了,我就琢磨着是不是可以学它做,用来实现这个做播放器的需求。
从网上下了一个SMPlayer以后,启动起来以后打开一个视频文件,然后就开了ProcessExplorer工具来看进程,果然看到了SMPlayer起了一个进程……但是叫MPV.exe而不是MPlayer.exe。(想起之前要做播放器的时候,问过隔壁部门的人。得到的建议是用MPV,不过在那会儿,我的理解是要找MPV的代码来修改或者什么的拿来用,没想到还有直接起exe这种方便的方法……)
ProcessExplorer里面看到SMPlayer执行的MPV的进程的参数列表里,看到了好多东西。有一个 --wid= 在网上查了之后,得知这个参数是指定把画面显示在哪个窗口上。我开了个记事本,用Spy++工具得到窗口句柄的值,然后把值通过这个参数送进去启动MPV,果然画面在记事本的窗口里播出了视频画面……不过在Windows的声音混合器里,看到实际发出声音的是MPV.exe进程而不是Notepad.exe进程。
然后就是怎么控制播放状态的问题。MPV.exe带有参数 --input-file=/dev/stdin (在Windows下也是这么写)的时候,控制是通过标准输入stdin给它送命令,比如 cycle pause up 可以控制视频的播放和暂停,seek可以控制跳转到哪里,这些命令后面带上换行 (\n)送进stdin就可以了。MPV可以把播放过程中的一些状态信息输出到标准错误输出(stderr)。要指定让MPV输出一些视频信息,可以通过 --term-status-msg 这样的参数给它一个输出格式。具体的说明可以在官网这里 https://mpv.io/manual/stable 找到。
所以最后,我在要播放的时候,用 --wid= 指定自己界面上一个空的窗口的句柄给它,然后用匿名管道(通过CreatePipe创建,在STARTUPINFO里面指定)重定向它的标准输入和标准错误输出,把它标准错误输出的文本分析之后显示在界面上,然后把界面上的例如拖动进度条、点击播放暂停这类的操作,用给它标准输入写入字符串的方式来控制它。就简单地做了个“播放器”。
具体的一些参数如果看说明还不太了解的,可以模仿SMPlayer的命令行来写。
最后说一下,这个播放器是GPL协议的。对于GPL协议的东西,如果只是通过运行exe的方式来调用它,不知道能允许做到什么样、是不是强制自己的程序要开源。