FFMpeg笔记(七) 代码结构分析,以HLS为例

HLS流在播放时是先解协议(hls.c)后解封装(mpegts.c),libavformat下的hls.c和mpegts.c实际上是同一个级别的,同属于demuxer。

一、解HLS协议

1. FFmpeg代码分析    

    首先看一下ff_hls_demuxer的定义:

AVInputFormat ff_hls_demuxer = {
    .name           = "hls,applehttp",
    .long_name      = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
    .priv_class     = &hls_class,
    .priv_data_size = sizeof(HLSContext),
    .read_probe     = hls_probe,
    .read_header    = hls_read_header,
    .read_packet    = hls_read_packet,
    .read_close     = hls_close,
    .read_seek      = hls_read_seek,
};

(1)FFmpeg在拿到hls流后,它一开始并不知道该用哪个demuxer,这个时候它会进行probe,即依次调用demuxer的read_probe函数,选择返回分数最高的一个demuxer,最后选定ff_hls_demuxer。AVFormatContext中的s->iformat->priv_data一般是指demuxer内部的结构体,在解HLS协议时,这个priv_data就是HLSContext;

(2)之后FFmpeg会调用read_header函数,即执行hls_read_header,获取hls的播放列表,并赋值到HLSContext结构体中;

(3)当准备工作妥当后,FFmpeg会调用hls_read_packet读取数据,传递给上层;

(4)如果有seek操作会执行hls_read_seek;

(5)视频关闭时,FFmpeg会调用hls_close;

2. discontinue字段

    FFmpeg3.4没有支持HLS标准的discontinue字段。discontinue字段常用于ts播放列表里插入一段广告,这段广告的参数可以与正片的参数不一致。上层在识别到这个参数后,可以重置解码器。对于iOS,需要重新创建解码器,对于Android,解码器兼容了这种情况,无需重新创建解码器。

二、解ts封装 

以mpegts.c为例,probe一般是将读取到的probe数据与ts格式对比,如果是ts格式则返回高分数,上层选择最高的分数的demuxer;

PES包:分割打包的ES流,加入了PES头。

struct MpegTSFilter {
    int pid;
    int es_id;
    int last_cc; /* last cc code (-1 if first packet) */
    int64_t last_pcr;
    enum MpegTSFilterType type;
    union {// 一个Filter是下边的一种类型
        MpegTSPESFilter pes_filter;
        MpegTSSectionFilter section_filter;
    } u;
};

handle_packet函数处理一个ts包,在函数中switch case语句中处理ts包。一般是先处理ts header, 之后是pes header,代码中状态定义:

/* TS stream handling */
// 标识TS流状态
enum MpegTSState {
    MPEGTS_HEADER = 0,
    MPEGTS_PESHEADER,
    MPEGTS_PESHEADER_FILL,
    MPEGTS_PAYLOAD,
    MPEGTS_SKIP,
};

 从av_read_frame读到的pkt,其音频和视频的pts是连续的,但是两者之间不是连续的,因为pts乘以时基才是真正的显示时间,比如如下打印日志,pkt时间进行换算后,可以看到其整体pts是连续的。

martinjia time_base:1 30000, pkt index:0, pkt pts:83083(pts换算后:2.76s)
martinjia martinjia time_base:1 48000, pkt index:1, pkt pts:118784(pts换算后:2.47s)

原文地址:https://www.cnblogs.com/jiayayao/p/9381744.html