落鹤生 发布于 2012-06-11 11:20 点击:2318次 | 原文 | 来自:CSDN博客
最近在看 ffmpeg 源码,希望多了解下底层的东西, mplayer 源码太过庞大,不利于快速的分析关键代码。 ffmpeg 恰好满足需要。 主要的分析内容包括如下两个方面: demuxer 相关,解码器选取相关 mpegts_read_header(***)-->handle_packets(**)-->handle_packet(**) , 其中在 mpegts_read_header ( ** )中首先通过 pegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); 挂接 sdt 以及 pat 的处理函数,即 sdt 和 pat 是最初始的信息,在 pat 中才能得到 pmt 的 pid 以便进一步分析。在 handle_packets 中读取一个包然后调用 handle_packet(**) 处理。处理过程中调用 write_section_data 接收 pat 等信息,当一个完整的 pat 接收完毕后,调用 tss->section_cb(tss1, tss->section_buf, tss->section_h_size); 来解析,此处 section_cb 便是通过 mpegts_open_section_filter 挂接的 pat_cb( 以 pat 为例, sdt 分析方式一样 ) 。分析过程得到 pmt 的 pid 并通过 mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); 将 pmt 的解析函数挂接上来,之后便可以读取 pmt 包并处理了。通过分析 pmt 便可以得到具体的媒体流并通过 add_pes_stream(ts, pid, pcr_pid); 函数来建立各个媒体流的信息,也得到了此 ts 中包含的媒体流的数量和 id ,在 pmt_cb 中还有一个很重要的函数是 mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc); 此函数通过 mpegts_find_stream_type(st, pes->stream_type, MISC_types); 可以定位到每个媒体流的具体解码器(主要是存储 codec_id, 其他在后面初始化),之后解码的时候便可以通过 codec_id 来选择具体的解码器了。增加流的操作中会调用 tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); 来挂接实际的解析 pes 的函数,之后便可以接收具体的 pes 包并解析实际的媒体数据。以上内容并不保证准确,需进一步确认。 经过此过程,便得到了基本的流信息( video audio 数量及相应的 ID ),在读包后分析 ID 即可相应处理,达到解复用的目的了。分析参数得到流信息的过程描述如下:主要是两个表 PAT 和 PMT ,其中 PAT 存 储的频道信息,一个频道便有一个 PMT ,而 PMT 存储的是此频道由哪些流组成(视频流 音频流 以及相应的 PID ),以及流的具体格式( h264 等),通过分析完每个 PMT 便得到了总的视频流及频道等信息。具体的关于sdt和pat、pmt的介绍可参照网上信息或查阅标准文档。 2 、解码器相关 2.1 解码器选择: 通过如上分析,已经得到了解码器的 codec_id ,根据 codec_id 选择即可 (allen_young_yang) |