最近对mpv的源码产生了兴趣,打算研究研究。

mpv是属于一个大型的C语言的跨平台的播放器项目,其代码源自MPlayer和mplayer2,是一个历史非常悠久的项目了。

先来分析一下此项目大致存在的难点:

  • 针对跨平台的编译处理。
  • 运用了C语言的奇淫巧技。
  • 图形学的一些专业知识,主要是编解码、图形渲染等。

先从github上下载了mpv的源码,然后进行编译,整个过程比较人性化。

waf编译系统

mpv项目自己定制了一个叫waf的编译系统,至于为什么使用waf编译系统在他们的项目文档里有做介绍why waf,总结下来大致以下几点:

  • 编译脚本 在跨平台时比较保持一致的代码,并且尽量减少重复和胶水代码。
  • 配置(configuration)步骤 和 编译(buid)步骤必须是分离的。
  • 脚本比较好理解、好修改。(waf使用python编写)

源码编译

(本文的编译过程基于Mac)先从github上下载了mpv的源码。

第一步先跑个脚本下载最新的waf执行文件。

1
./bootstrap.py

第二步跑一下waf的configuration步骤,这个过程会告诉你缺少哪些组件。

1
./waf configure

根据第二步的结果,对一些缺少的组件进行安装。

1
2
brew install libass
brew install ffmpeg

然后 再跑一遍 ./waf configure 就成功生成了config.h,用于最后的编译过程。

在configure阶段可以使用下列选项,不进行代码优化,便于后续调试。

--disable-optimize

第三部 跑一下build步骤,这样就生成了最终的执行文件了。

1
./waf

最后一步 运行一下 安装步骤,就把mpv 放到了 /usr/local/bin/mpv 系统目录。

1
./waf install

代码调试

安装好mpv之后,就可以先尝试运行一下程序,可以正常的播放视频。

1
mpv  xx/xx.mp4

接下来尝试用lldb来调试一下代码。由于mpv在mac系统上运行,所以代码的入口在 xx/mpv/osdep/macosx_application.m 这个文件。所以先用lldb在这里设置一个断点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#Launch a process for with arguments a.out 1 2 3 without having to supply the args every time
lldb -- mpv xx/xx.mp4

#enter lldb env then set breakpoint
breakpoint set --name cocoa_main

#star debug
run

#运行结果
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x00000001000d711b mpv`cocoa_main(argc=2, argv=0x00007ffeefbff940) at macosx_application.m:338 [opt]
335
336 int cocoa_main(int argc, char *argv[])
337 {
-> 338 @autoreleasepool {
339 application_instantiated = true;
340 [[EventsResponder sharedInstance] setIsApplication:YES];
341
Target 0: (mpv) stopped.

这之后 就可以一边看代码一边通过调试来理解代码行为了。

最后再补充几条常用lldb的命令,更多内容可以查看lldb的官方文档。

1
2
3
4
5
6
7
8
9
10
# Show the stack backtrace for the current thread
thread backtrace

# List all breakpoints
breakpoint list

# Delete a breakpoint
breakpoint delete 1

breakpoint disable/enable