FFmpeg hls.c分析

转载自https://blog.csdn.net/wzw88486969/article/details/78821068

FFmpeg hls.c分析_第1张图片

avformat_open_input(http.xxx.m3u8)  
    init_input(s, filename, &tmp))  
        //提供的文件名信息不能探测格式  
        av_probe_input_format2(&pd, 0, &score)))  
        io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)  
            io_open_default  
                ffio_open_whitelist  
                    ffurl_alloc  
                        //探测是HTTP协议 URLProtocol ff_http_protocol  
                        url_find_protocol(filename);    
                    ffurl_connect    //发送HTTP报文头,下载http.xxx.m3u8文件  
        //读m3u8文件探测解复用是AVInputFormat *iformat ="hls,applehttp"  
        *fmt = av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize);  
        s->iformat->read_header(s);  //iformat iformat  hls.c-->hls_read_header  
  
  
  
s->iformat->read_header(s);  
static int hls_read_header(AVFormatContext *s){  
    //解析m3u8文件,把相应字段放在playlist结构体中,playlist结构体就相当于index.m3u8的数组形式  
    parse_playlist    
    ffio_init_context(read_data);  
     //用read_data读第0片,探测视频文件的解复用是AVInputFormat ff_mpegts_demuxer  
    av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url, NULL, 0, 0);    
    avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL); //打开第0片视频文件  
}  
  
s->iformat->read_packet(s, pkt);  
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt){  
    while(1){  
        ret = av_read_frame(pls->ctx, &pls->pkt);  
        if(ret >0){  
            //没有SEEK的话,读包成功直接退出循环  
            if (pls->seek_timestamp == AV_NOPTS_VALUE) break;     
  
            //有SEEK操作  
            if (pls->seek_stream_index == pls->pkt.stream_index) {   
                tb = get_timebase(pls);  
                ts_diff = av_rescale_rnd(pls->pkt.dts) -  pls->seek_timestamp;  
  
                //本片中通过比较pkt.dts,seek_timestamp接近了SEEK点,本次SEEK成功  
                if (ts_diff >= 0 && (pls->pkt.flags & AV_PKT_FLAG_KEY)) {  
                    pls->seek_timestamp = AV_NOPTS_VALUE;    
                    break;  
                }  
            }  
        }  
    }  
}  
  
  
static int hls_read_seek(AVFormatContext *s, int stream_index,  
                               int64_t timestamp, int flags){  
    //根据timestamp在playlist查找是第几片  
    find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no)   
    pls->cur_seq_no = seq_no; // read_data会调用current_segment方法,下次下载第seq_no片  
    pls->seek_stream_index = stream_subdemuxer_index;  
  
    ff_format_io_close(pls->parent, &pls->input); //关闭现在正在下载的片input  
    pls->pb.eof_reached = 0;  
    /* Clear any buffered data */  
    pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer;  
    //hls_read_packet 里面会根据这个seek_timestamp判断下载seq_no片中,第多少帧刚好是这个SEEK点  
    pls->seek_timestamp = seek_timestamp;    
    pls->seek_flags = flags;  
}  
  
static int hls_close(AVFormatContext *s)  
                avformat_close_input(&pls->ctx);  
  
  
static int read_data(void *opaque, uint8_t *buf, int buf_size){ //核心方法  
    if (!v->input){ //v->input 判断本片是否打开过  
        seg = current_segment(v);  
        ret = open_input(c, v, seg);  
                //http.aaa.x.ts  
                open_url(v->parent, &v->input, seg->url, c->avio_opts, opts, &is_http)  
                    avio_find_protocol_name(url);  
                    //走HTTP协议,发送HTTP报文头,下载x.ts文件  
                    io_open(s, pb, url, AVIO_FLAG_READ, &tmp)  
    }  
    //读HTTP报文体剩下的x.ts文件字节  
    ret = read_from_url(v, current_segment(v), buf, buf_size, READ_NORMAL);  
    if (ret > 0){  
        return ret;  
    }else{ //本片下载完  
        ff_format_io_close(v->parent, &v->input);   //v->input = NULL  
        v->cur_seq_no++;  
    }  
}  
  
  
  
const URLProtocol ff_http_protocol = {  
    .name                = "http",  
    .url_open2           = http_open,  
    .url_accept          = http_accept,  
    .url_handshake       = http_handshake,  
    .url_read            = http_read,  
    .url_write           = http_write,  
    .url_seek            = http_seek,  
    .url_close           = http_close,  
    .url_get_file_handle = http_get_file_handle,  
    .url_shutdown        = http_shutdown,  
    .priv_data_size      = sizeof(HTTPContext),  
    .priv_data_class     = &http_context_class,  
    .flags               = URL_PROTOCOL_FLAG_NETWORK,  
    .default_whitelist   = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"  
};  
  
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,  
};  
  
AVInputFormat ff_mpegts_demuxer = {  
    .name           = "mpegts",  
    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),  
    .priv_data_size = sizeof(MpegTSContext),  
    .read_probe     = mpegts_probe,  
    .read_header    = mpegts_read_header,  
    .read_packet    = mpegts_read_packet,  
    .read_close     = mpegts_read_close,  
    .read_timestamp = mpegts_get_dts,  
    .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,  
    .priv_class     = &mpegts_class,  
};  
  
  
  
HTTP报文件:  
  
(3671754)request: GET /2017127/5de/529/zehBOsrZo57vbeJy/index.m3u8 HTTP/1.1  
User-Agent: Lavf/57.41.100  
Accept: */* 
Range: bytes=0- 
Connection: close 
Host: xxxcdn.hls.yyy.tv 
Icy-MetaData: 1 
 
 
[http @ 0x102708000] (3671754)header='HTTP/1.1 206 Partial Content' 
[http @ 0x102708000] (3671754)header='Server: Tengine' 
[http @ 0x102708000] (3671754)header='Content-Type: application/x-mpegURL' 
[http @ 0x102708000] (3671754)header='Content-Length: 36072' 
[http @ 0x102708000] (3671754)header='Connection: close' 
[http @ 0x102708000] (3671754)header='Date: Thu, 07 Dec 2017 13:20:30 GMT' 
[http @ 0x102708000] (3671754)header='x-oss-request-id: 5A29401E5FB1640973AC7221' 
[http @ 0x102708000] (3671754)header='Accept-Ranges: bytes' 
[http @ 0x102708000] (3671754)header='ETag: "5DBE181ACD4B983E026E19C50BFF23DD"' 
[http @ 0x102708000] (3671754)header='Last-Modified: Thu, 07 Dec 2017 13:20:04 GMT' 
[http @ 0x102708000] (3671754)header='x-oss-object-type: Normal' 
[http @ 0x102708000] (3671754)header='x-oss-hash-crc64ecma: 17784356933318823809' 
[http @ 0x102708000] (3671754)header='x-oss-storage-class: Standard' 
[http @ 0x102708000] (3671754)header='Content-MD5: Xb4YGs1LmD4CbhnFC/8j3Q==' 
[http @ 0x102708000] (3671754)header='x-oss-server-time: 3' 
[http @ 0x102708000] (3671754)header='Via: cache25.l2nu20-2[0,200-0,H], cache1.l2nu20-2[0,0], cache8.cn307[0,206-0,H], cache6.cn307[3,0]' 
[http @ 0x102708000] (3671754)header='Age: 763084' 
[http @ 0x102708000] (3671754)header='X-Cache: HIT TCP_HIT dirn:17:96357170 mlen:-1' 
[http @ 0x102708000] (3671754)header='X-Swift-SaveTime: Thu, 07 Dec 2017 15:58:04 GMT' 
[http @ 0x102708000] (3671754)header='X-Swift-CacheTime: 2592000' 
[http @ 0x102708000] (3671754)header='Content-Range: bytes 0-36071/36072' 
[http @ 0x102708000] (3671754)header='access-control-allow-origin: *' 
[http @ 0x102708000] (3671754)header='Timing-Allow-Origin: *' 
[http @ 0x102708000] (3671754)header='EagleId: 7b81d7ce15134159145938051e' 
[http @ 0x102708000] (3671754)header='' 
[hls,applehttp @ 0x104007000] Format hls,applehttp probed with size=2048 and score=100 
[hls,applehttp @ 0x104007000] Opening 'http://xxxcdn.hls.yyy.tv/2017127/5de/529/zehBOsrZo57vbeJy/0.ts' for reading 
[http @ 0x1026275e0]  
 
 
(3671754)request: GET /2017127/5de/529/zehBOsrZo57vbeJy/0.ts HTTP/1.1 
User-Agent: Lavf/57.41.100 
Accept: */*  
Connection: close  
Host: xxxcdn.hls.yyy.tv  
Icy-MetaData: 1  
  
  
[http @ 0x1026275e0] (3671754)header='HTTP/1.1 200 OK'  
[http @ 0x1026275e0] (3671754)header='Server: Tengine'  
[http @ 0x1026275e0] (3671754)header='Content-Type: video/MP2T'  
[http @ 0x1026275e0] (3671754)header='Content-Length: 1233656'  
[http @ 0x1026275e0] (3671754)header='Connection: close'  
[http @ 0x1026275e0] (3671754)header='Date: Thu, 07 Dec 2017 13:20:31 GMT'  
[http @ 0x1026275e0] (3671754)header='x-oss-request-id: 5A29401FF43DB73D87B40E71'  
[http @ 0x1026275e0] (3671754)header='Accept-Ranges: bytes'  
[http @ 0x1026275e0] (3671754)header='ETag: "8C8A9CAC5FC40404D629A2AF19B84A6F"'  
[http @ 0x1026275e0] (3671754)header='Last-Modified: Thu, 07 Dec 2017 10:58:38 GMT'  
[http @ 0x1026275e0] (3671754)header='x-oss-object-type: Normal'  
[http @ 0x1026275e0] (3671754)header='x-oss-hash-crc64ecma: 13525335145074164730'  
[http @ 0x1026275e0] (3671754)header='x-oss-storage-class: Standard'  
[http @ 0x1026275e0] (3671754)header='Content-MD5: jIqcrF/EBATWKaKvGbhKbw=='  
[http @ 0x1026275e0] (3671754)header='x-oss-server-time: 29'  
[http @ 0x1026275e0] (3671754)header='Via: cache42.l2nu20-2[0,200-0,H], cache2.l2nu20-2[0,0], cache2.cn307[0,200-0,H], cache8.cn307[3,0]'  
[http @ 0x1026275e0] (3671754)header='Age: 763086'  
[http @ 0x1026275e0] (3671754)header='X-Cache: HIT TCP_HIT dirn:15:118266541 mlen:-1'  
[http @ 0x1026275e0] (3671754)header='X-Swift-SaveTime: Thu, 07 Dec 2017 13:21:58 GMT'  
[http @ 0x1026275e0] (3671754)header='X-Swift-CacheTime: 2592000'  
[http @ 0x1026275e0] (3671754)header='access-control-allow-origin: *'  
[http @ 0x1026275e0] (3671754)header='Timing-Allow-Origin: *'  
[http @ 0x1026275e0] (3671754)header='EagleId: 7b81d7d015134159179953085e'  
[http @ 0x1026275e0] (3671754)header=''  
..........................................  
.......................................... //下载0.ts文件  
  
Format mpegts probed with size=2048 and score=50  
  
  
(3671754)request: GET /2017127/5de/529/zehBOsrZo57vbeJy/1.ts HTTP/1.1  
User-Agent: Lavf/57.41.100  
Accept: */*  
Connection: close  
Host: xxxcdn.hls.yyy.tv  
Icy-MetaData: 1  
  
  
[http @ 0x102509500] (3671754)header='HTTP/1.1 200 OK'  
[http @ 0x102509500] (3671754)header='Server: Tengine'  
[http @ 0x102509500] (3671754)header='Content-Type: video/MP2T'  
[http @ 0x102509500] (3671754)header='Content-Length: 1162028'  
[http @ 0x102509500] (3671754)header='Connection: close'  
[http @ 0x102509500] (3671754)header='Date: Thu, 07 Dec 2017 13:20:31 GMT'  
[http @ 0x102509500] (3671754)header='x-oss-request-id: 5A29401F83B4CE0AA7B40025'  
[http @ 0x102509500] (3671754)header='Accept-Ranges: bytes'  
[http @ 0x102509500] (3671754)header='ETag: "95EFDEADB86482C551F1BCF868ECEA41"'  
[http @ 0x102509500] (3671754)header='Last-Modified: Thu, 07 Dec 2017 10:58:49 GMT'  
[http @ 0x102509500] (3671754)header='x-oss-object-type: Normal'  
[http @ 0x102509500] (3671754)header='x-oss-hash-crc64ecma: 5079365695105828960'  
[http @ 0x102509500] (3671754)header='x-oss-storage-class: Standard'  
[http @ 0x102509500] (3671754)header='Content-MD5: le/erbhkgsVR8bz4aOzqQQ=='  
[http @ 0x102509500] (3671754)header='x-oss-server-time: 33'  
[http @ 0x102509500] (3671754)header='Via: cache31.l2nu20-2[0,200-0,H], cache10.l2nu20-2[2,0], cache7.cn307[0,200-0,H], cache3.cn307[28,0]'  
[http @ 0x102509500] (3671754)header='Age: 763096'  
[http @ 0x102509500] (3671754)header='X-Cache: HIT TCP_HIT dirn:5:256912714 mlen:-1'  
[http @ 0x102509500] (3671754)header='X-Swift-SaveTime: Thu, 07 Dec 2017 15:58:06 GMT'  
[http @ 0x102509500] (3671754)header='X-Swift-CacheTime: 2592000'  
[http @ 0x102509500] (3671754)header='access-control-allow-origin: *'  
[http @ 0x102509500] (3671754)header='Timing-Allow-Origin: *'  
[http @ 0x102509500] (3671754)header='EagleId: 7b81d7cb15134159275121813e'  
[http @ 0x102509500] (3671754)header=''  
..........................................  
.......................................... //下载1.ts文件  

你可能感兴趣的:(流媒体,FFmpeg)