首页 > 代码库 > 解构ffmpeg(二)

解构ffmpeg(二)

通过比较DirectShow和ffmpeg两者的FilterGraph,分析ffmpeg的FilterGraph运作。

首先FilterGraph是一个图,图由点和边构成。在FilterGraph中的点就是Filter。在DirectShow中,没有边对象,Filter的连接依赖Pin组件以及IPin接口,一对InputPin和OutputPin构成一条边。每个Filter可以有至少一个Pin,即每个点有至少一条边,(排除只有一个点的图,和没有邻接边的点的情况)。构成连接的InputPin和OutputPin互相持有对方的引用。FilterGraph的运作依赖IPin接口的三个方法read,async_read以及receive。上流数据通过出边(OutputPin)调用对端的入边(InputPin)的receive推送到下游。逆过来,下游通过入边(InputPin)调用对端的出边(OutputPin)的read或async_read向上流拉数据。上游源数据得以经过图中某条路径到达下游目的地。

在ffmpeg里,AVFilterContext则是点,AVFilterLink则是边。AVFilterLink是AVFilterContext的出入边,AVFilterContext则是AVFilterLink的邻点。AVFilterPad是相当于Pin的部件,使FilterGraph可以运行起来。AVFilterPad主要功能是三个接口函数,poll_frame,request_frame以及filter_frame。

通过递归向下游“先序”遍历,推送帧数据

filter_frame (link, frame) {
  filter (frame);
  input_pad->filter_frame (link, frame);
}

通过递归向上游“后序”遍历,拉帧数据

request_frame (link, frame) {
  output_pad->request_frame (link, frame);
  filter (frame);
}

对象图请参看上一篇《解构ffmpeg(一)》。

解构ffmpeg(二)