音視頻流媒體開(kāi)發(fā)【六十五】RTMP/HLS/HTTP-FLV流媒體服務(wù)器分8-SRS流媒體框架-HLS?件配置和測(cè)試

HLS原理簡(jiǎn)介

RTMP指Adobe的RTMP(Realtime Message Protocol)逻住,?泛應(yīng)?于低延時(shí)直播支子,也是編碼器和服務(wù)器對(duì)接的實(shí)際標(biāo)準(zhǔn)協(xié)議创肥,在PC(Flash)上有最佳觀看體驗(yàn)和最佳穩(wěn)定性。

HLS指Apple的HLS(Http Live Streaming)值朋,本身就是Live(直播)的叹侄,不過(guò)Vod(點(diǎn)播)也能?持。
HLS是Apple平臺(tái)的標(biāo)準(zhǔn)流媒體協(xié)議昨登,和RTMP在PC上?樣?持得天??縫趾代。
HLS和RTMP兩種分發(fā)?式,就可以?持所有的終端丰辣。

應(yīng)?場(chǎng)景

HLS主要的應(yīng)?場(chǎng)景包括:

  1. 跨平臺(tái):PC主要的直播?案是RTMP撒强,也有?些庫(kù)能播放HLS,譬如jwplayer笙什,基于osmf的hls插件也??堆飘哨。所以實(shí)際上如果選?種協(xié)議能跨PC/Android/IOS,那就是HLS琐凭。
  2. iOS上苛刻的穩(wěn)定性要求:IOS上最穩(wěn)定的當(dāng)然是HLS芽隆,穩(wěn)定性不差于RTMP在PC-flash上的表現(xiàn)。
  3. 友好的CDN分發(fā)?式:?前CDN對(duì)于RTMP也是基本協(xié)議,但是HLS分發(fā)的基礎(chǔ)是HTTP胚吁,所以CDN的接?和分發(fā)會(huì)?RTMP更加完善牙躺。能在各種CDN之間切換,RTMP也能腕扶,只是可能需要對(duì)接測(cè)試孽拷。
  4. 簡(jiǎn)單:HLS作為流媒體協(xié)議?常簡(jiǎn)單,apple?持得也很完善蕉毯。Android對(duì)HLS的?持也會(huì)越來(lái)越完善乓搬。?于DASH/HDS,好像沒(méi)有什么特別的理由代虾,就像linux已經(jīng)??其道?且開(kāi)放进肯,其他的系統(tǒng)很難再?泛應(yīng)?。

總之棉磨,SRS?持HLS主要是作為輸出的分發(fā)協(xié)議江掩,直播以RTMP+HLS分發(fā),滿(mǎn)?各種應(yīng)?場(chǎng)景乘瓤。點(diǎn)播以HLS為主环形。

分發(fā)?式?較

互聯(lián)?上的兩種主要的分發(fā)?式:HLSRTMP,什么時(shí)候?誰(shuí)衙傀,完全決定于應(yīng)?場(chǎng)景抬吟。

還有其他的分發(fā)?式,這些分發(fā)?式不屬于互聯(lián)?常?和通?的?式统抬,不予以?較:
  1. UDP:譬如YY的實(shí)時(shí)應(yīng)?火本,視頻會(huì)議等等,或者RTSP之類(lèi)聪建。這類(lèi)應(yīng)?的特點(diǎn)就是實(shí)時(shí)性要求特別?钙畔,以毫秒計(jì)算。TCP家族協(xié)議根本就滿(mǎn)?不了要求金麸,所以HTTP/TCP都不靠譜擎析。這類(lèi)應(yīng)?沒(méi)有通?的?案,必須??實(shí)現(xiàn)分發(fā)(服務(wù)端)和播放(客戶(hù)端)挥下。
  2. P2P:譬如RTMFP或者各家??的協(xié)議揍魂。這類(lèi)應(yīng)?的特點(diǎn)是節(jié)省帶寬。?前PC/flash上的RTMFP?較成熟棚瘟,Android上的P2P屬于起步群雄紛爭(zhēng)標(biāo)準(zhǔn)不?现斋,IOS上P2P應(yīng)該沒(méi)有聽(tīng)說(shuō)過(guò)。
  3. RTSP:這種不是互聯(lián)?上的主要應(yīng)?解取,在其他領(lǐng)域譬如安防等有?泛應(yīng)?步责。
另外,HTTP的也分為?種:
  1. HTTP progressive:早期流媒體服務(wù)器分發(fā)http?件時(shí),以普通的http?件分發(fā)蔓肯,這種叫做漸進(jìn)式下載遂鹊,意思就是如果?件很?譬如1?時(shí)時(shí)?1GB??,想從中間開(kāi)始播放是不?的蔗包。但這種?式已經(jīng)是作古了秉扑,很多http服務(wù)器?持http?件的seek,就是從中間開(kāi)始播放调限。
  2. HTTP stream:?持seek的HTTP流舟陆,譬如各家視頻?站的點(diǎn)播分發(fā)?式〕馨或者稍微復(fù)雜點(diǎn)的秦躯,譬如把?個(gè)??件切?段之后分發(fā)。?前在pc/flash上點(diǎn)播國(guó)內(nèi)的主流分發(fā)是這種?式裆装。
  3. HLS:這種是現(xiàn)在適配?式最?(除了flash, 需要額外的as庫(kù)?持)踱承,在PC上有vlc,Android/IOS原?播放器就?持播放HLS哨免,HTML5??的url可以寫(xiě)HLS地址茎活。總之琢唾,在移動(dòng)端是以HLS為主载荔。
  4. HDS:adobe??的HLS,?坨屎采桃。
  5. DASH:各家提出的HLS懒熙,?前還沒(méi)有?泛應(yīng)?。
對(duì)?以下互聯(lián)?上?的流媒體分發(fā)?式:
  1. HLS:apple的HLS芍碧,?持點(diǎn)播和直播煌珊。
  2. HTTP:即HTTP stream号俐,各家??定義的http流泌豆,應(yīng)?于國(guó)內(nèi)點(diǎn)播視頻?站。
  3. RTMP:直播應(yīng)?吏饿,對(duì)實(shí)時(shí)性有?定要求踪危,以PC為主。

更進(jìn)?步的?較繼續(xù)參考 srs官?wiki:

https://github.com/ossrs/srs/wiki/v3_CN_RTMP.PK.HTTP

推薦的?式

  1. 編碼器輸出RTMP協(xié)議猪落。
  2. 流媒體系統(tǒng)接?使?RTMP協(xié)議贞远。
  3. 流媒體系統(tǒng)內(nèi)部直播分發(fā)使?RTMP。
  4. PC+直播+實(shí)時(shí)性要求?:使?flash播放RTMP笨忌。
  5. PC+直播+沒(méi)有實(shí)時(shí)性要求:使?RTMP或者HLS均可蓝仲。
  6. PC+點(diǎn)播:使?HTTP或者HLS。
  7. Apple IOS/OSX:都使?HLS(實(shí)時(shí)性要求?得??解析RTMP,或者使?外部庫(kù)袱结,譬如https://www.vitamio.org
  8. Andorid:和IOS?樣亮隙,不過(guò)可以確定的是可以??開(kāi)發(fā)?持RTMP。

HLS部署

第?步垢夹,編寫(xiě)SRS配置?件溢吻。詳細(xì)參考HLS分發(fā)

將以下內(nèi)容保存為?件,譬如 conf/hls.conf 果元,服務(wù)器啟動(dòng)時(shí)指定該配置?件(srs的conf?件夾有該?件)促王。

# conf/hls.conf
listen 1935;
max_connections 1000;
http_server {
  enabled on;
  listen 8081;
  dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
  hls {
    enabled on;
    hls_path ./objs/nginx/html;
    hls_fragment 10; # 分?時(shí)?
    hls_window 60; # 窗?時(shí)?
  }
}

備注:我們使?SRS內(nèi)置的HTTP服務(wù)器分發(fā)HLS切?,也可以使?Nginx等Web服務(wù)器分發(fā)而晒。
備注:hls_path必須存在蝇狼,srs只會(huì)?動(dòng)創(chuàng)建${hls_path}下的app的?錄。參考:HLS分發(fā)流程

第?步倡怎,啟動(dòng)SRS题翰。詳細(xì)參考HLS分發(fā)
./objs/srs -c conf/hls.conf

完整的hls配置?件說(shuō)明

# the vhost with hls specified.
vhost hls.srs.com {
  hls {
    # whether the hls is enabled.
    # if off, do not write hls(ts and m3u8) when publish.
    # default: off
    enabled on;
    # the hls fragment in seconds, the duration of a piece of ts.
    # default: 10
    hls_fragment 10;
    # the hls m3u8 target duration ratio,
    # EXT-X-TARGETDURATION = hls_td_ratio * hls_fragment // init
    # EXT-X-TARGETDURATION = max(ts_duration, EXT-X-
    TARGETDURATION) // for each ts
    # @see https://github.com/ossrs/srs/issues/304#issuecomment-74000081
    # default: 1.5
    hls_td_ratio 1.5;
    # the audio overflow ratio.
    # for pure audio, the duration to reap the segment.
    # for example, the hls_fragment is 10s, hls_aof_ratio is 2.0,
    # the segment will reap to 20s for pure audio.
    # default: 2.0
    hls_aof_ratio 2.0;
    # the hls window in seconds, the number of ts in m3u8.
    # default: 60
    hls_window 60;
    # the error strategy. can be:
    # ignore, disable the hls.
    # disconnect, require encoder republish.
    # continue, ignore failed try to continue output hls.
    # @see https://github.com/ossrs/srs/issues/264
    # default: continue
    hls_on_error continue;
    # the hls output path.
    # the m3u8 file is configured by hls_path/hls_m3u8_file, the default is:
    # ./objs/nginx/html/[app]/[stream].m3u8
    # the ts file is configured by hls_path/hls_ts_file, the default is:
    # ./objs/nginx/html/[app]/[stream]-[seq].ts
    # @remark the hls_path is compatible with srs v1 config.
    # default: ./objs/nginx/html
    hls_path ./objs/nginx/html;
    # the hls m3u8 file name.
    # we supports some variables to generate the filename.
    # [vhost], the vhost of stream.
    # [app], the app of stream.
    # [stream], the stream name of stream.
    # default: [app]/[stream].m3u8
    hls_m3u8_file [app]/[stream].m3u8;
    # the hls ts file name.
    # we supports some variables to generate the filename.
    # [vhost], the vhost of stream.
    # [app], the app of stream.
    # [stream], the stream name of stream.
    # [2006], replace this const to current year.
    # [01], replace this const to current month.
    # [02], replace this const to current date.
    # [15], replace this const to current hour.
    # [04], replace this const to current minute.
    # [05], replace this const to current second.
    # [999], replace this const to current millisecond.
    # [timestamp],replace this const to current UNIX timestamp in ms.
    # [seq], the sequence number of ts.
    # [duration], replace this const to current ts duration.
    # @see https://github.com/ossrs/srs/wiki/v2_CN_DVR#custom-path
    # @see https://github.com/ossrs/srs/wiki/v2_CN_DeliveryHLS#hls-config
    # default: [app]/[stream]-[seq].ts
    hls_ts_file [app]/[stream]-[seq].ts;
    # whether use floor for the hls_ts_file path generation.
    # if on, use floor(timestamp/hls_fragment) as the variable
    [timestamp],
    # and use enhanced algorithm to calc deviation for segment.
    # @remark when floor on, recommend the hls_segment>=2*gop.
    # default: off
    hls_ts_floor off;
    # the hls entry prefix, which is base url of ts url.
    # for example, the prefix is:
    # http://your-server/
    # then, the ts path in m3u8 will be like:
    # http://your-server/live/livestream-0.ts
    # http://your-server/live/livestream-1.ts
    # ...
    # optional, default to empty string.
    hls_entry_prefix http://your-server;
    # the default audio codec of hls.
    # when codec changed, write the PAT/PMT table, but maybe ok util next ts.
    # so user can set the default codec for mp3.
    # the available audio codec:
    # aac, mp3, an
    # default: aac
    hls_acodec aac;
    # the default video codec of hls.
    # when codec changed, write the PAT/PMT table, but maybe ok util next ts.
    # so user can set the default codec for pure audio(without video) to vn.
    # the available video codec:
    # h264, vn
    # default: h264
    hls_vcodec h264;
    # whether cleanup the old expired ts files.
    # default: on
    hls_cleanup on;
    # If there is no incoming packets, dispose HLS in this timeout in seconds,
    # which removes all HLS files including m3u8 and ts files.
    # @remark 0 to disable dispose for publisher.
    # @remark apply for publisher timeout only, while "etc/init.d/srs stop" always dispose hls.
    # default: 0
    hls_dispose 0;
    # the max size to notify hls,
    # to read max bytes from ts of specified cdn network,
    # @remark only used when on_hls_notify is config.
    # default: 64
    hls_nb_notify 64;
    # whether wait keyframe to reap segment,
    # if off, reap segment when duration exceed the fragment,
    # if on, reap segment when duration exceed and got keyframe.
    # default: on
    hls_wait_keyframe on;
    # whether using AES encryption.
    # default: off
    hls_keys on;
    # the number of clear ts which one key can encrypt.
    # default: 5
    hls_fragments_per_key 5;
    # the hls key file name.
    # we supports some variables to generate the filename.
    # [vhost], the vhost of stream.
    # [app], the app of stream.
    # [stream], the stream name of stream.
    # [seq], the sequence number of key corresponding to the ts.
    hls_key_file [app]/[stream]-[seq].key;
    # the key output path.
    # the key file is configed by hls_path/hls_key_file, the default is:
    # ./objs/nginx/html/[app]/[stream]-[seq].key
    hls_key_file_path ./objs/nginx/html;
    # the key root URL, use this can support https.
    # @remark It's optional.
    hls_key_url https://localhost:8080;
    # Special control controls.
    ###########################################
    # Whether calculate the DTS of audio frame directly.
    # If on, guess the specific DTS by AAC samples, please read https://github.com/ossrs/srs/issues/547#issuecomment-294350544
    # If off, directly turn the FLV timestamp to DTS, which might cause corrupt audio stream.
    # @remark Recommend to set to off, unless your audio stream sample-rate and timestamp is not correct.
    # Default: on
    hls_dts_directly on;
    # on_hls, never config in here, should config in http_hooks.
    # for the hls http callback, @see http_hooks.on_hls of vhost hooks.callback.srs.com
    # @read https://github.com/ossrs/srs/wiki/v2_CN_DeliveryHLS#http-callback
    # @read https://github.com/ossrs/srs/wiki/v2_EN_DeliveryHLS#http-callback
    # on_hls_notify, never config in here, should config in http_hooks.
    # we support the variables to generate the notify url:
    # [app], replace with the app.
    # [stream], replace with the stream.
    # [param], replace with the param.
    # [ts_url], replace with the ts url.
    # for the hls http callback, @see http_hooks.on_hls_notify of vhost hooks.callback.srs.com
    # @read https://github.com/ossrs/srs/wiki/v2_CN_DeliveryHLS#on-hls-notify
    # @read https://github.com/ossrs/srs/wiki/v2_EN_DeliveryHLS#on-hls-notify
  }
}

源碼分析

數(shù)據(jù)從哪?來(lái) 怎么創(chuàng)建源
怎么切?
怎么更新數(shù)據(jù)
怎么提供分發(fā)

推流斷點(diǎn)
SrsConfig::get_hls_fragment
沒(méi)有推流的時(shí)候不會(huì)觸發(fā),rtmp推流后觸發(fā)

#0 SrsConfig::get_hls_fragment (this=0xa0fcf0, vhost="__defaultVhost__") at
src/app/srs_app_config.cpp:6102
#1 0x00000000004f3ee9 in SrsHlsController::on_publish (this=0xa3b560, req=0xa3bcb0) at src/app/srs_app_hls.cpp:885
#2 0x00000000004f5be2 in SrsHls::on_publish (this=0xa3b030) at src/app/srs_app_hls.cpp:1181
#3 0x00000000004e0603 in SrsOriginHub::on_publish (this=0xa3b670) at src/app/srs_app_source.cpp:1129
#4 0x00000000004e6a0b in SrsSource::on_publish (this=0xa3b1e0) at src/app/srs_app_source.cpp:2460
#5 0x00000000004d89f2 in SrsRtmpConn::acquire_publish (this=0xa30d60, source=0xa3b1e0) at src/app/srs_app_rtmp_conn.cpp:940
#6 0x00000000004d7a74 in SrsRtmpConn::publishing (this=0xa30d60, source=0xa3b1e0) at src/app/srs_app_rtmp_conn.cpp:822
#7 0x00000000004d5229 in SrsRtmpConn::stream_service_cycle (this=0xa30d60) at src/app/srs_app_rtmp_conn.cpp:534
#8 0x00000000004d4141 in SrsRtmpConn::service_cycle (this=0xa30d60) at src/app/srs_app_rtmp_conn.cpp:388
#9 0x00000000004d2f09 in SrsRtmpConn::do_cycle (this=0xa30d60) at src/app/srs_app_rtmp_conn.cpp:209
#10 0x00000000004d10fb in SrsConnection::cycle (this=0xa30dd8) at src/app/srs_app_conn.cpp:171
#11 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa31010) at src/app/srs_app_st.cpp:198
#12 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa31010) at src/app/srs_app_st.cpp:213
#13 0x00000000005bdd9d in _st_thread_main () at sched.c:337
#14 0x00000000005be515 in st_thread_create (start=0x5bd719 <_st_vp_schedule+170>,arg=0x700000001,

從這?可以看出來(lái) hls相關(guān)的業(yè)務(wù)都在:srs_app_hls.cpp ?件诈胜,以及SrsHlsMuxer是核?所在豹障。

SrsHlsMuxer::_refresh_m3u8

SrsHlsMuxer::update_config

配置hls

SrsTsMessageCache::cache_audio
#0 SrsTsMessageCache::cache_audio (this=0xa3b580, frame=0xa41640, dts=5130) at src/kernel/srs_kernel_ts.cpp:2716
#1 0x00000000004f4f18 in SrsHlsController::write_audio (this=0xa3b560, frame=0xa41640, pts=5130) at src/app/srs_app_hls.cpp:971
#2 0x00000000004f613c in SrsHls::on_audio (this=0xa3b030, shared_audio=0x7ffff7ee8b10,format=0xa3bad0) at src/app/srs_app_hls.cpp:1290
#3 0x00000000004deeaf in SrsOriginHub::on_audio (this=0xa3b670,shared_audio=0x7ffff7ee8b10)at src/app/srs_app_source.cpp:969
#4 0x00000000004e579a in SrsSource::on_audio_imp (this=0xa3b1e0, msg=0x7ffff7ee8b10)at src/app/srs_app_source.cpp:2191
#5 0x00000000004e539d in SrsSource::on_audio (this=0xa3b1e0, shared_audio=0xa3dfa0)at src/app/srs_app_source.cpp:2141
#6 0x00000000004d8f28 in SrsRtmpConn::process_publish_message (this=0xa30d60,source=0xa3b1e0,msg=0xa3dfa0) at src/app/srs_app_rtmp_conn.cpp:1014
#7 0x00000000004d8dce in SrsRtmpConn::handle_publish_message (this=0xa30d60,source=0xa3b1e0, msg=0xa3dfa0)at src/app/srs_app_rtmp_conn.cpp:993
#8 0x00000000005810b6 in SrsPublishRecvThread::consume (this=0x7ffff7f42800,msg=0xa3dfa0)at src/app/srs_app_recv_thread.cpp:389
#9 0x000000000057fbd4 in SrsRecvThread::do_cycle (this=0x7ffff7f42808)at src/app/srs_app_recv_thread.cpp:146
---Type <return> to continue, or q <return> to quit---
#10 0x000000000057fa25 in SrsRecvThread::cycle (this=0x7ffff7f42808) at src/app/srs_app_recv_thread.cpp:115
#11 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa3de00) at src/app/srs_app_st.cpp:198
#12 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa3de00) at src/app/srs_app_st.cpp:213
#13 0x00000000005bdd9d in _st_thread_main () at sched.c:337
SrsTsContextWriter::SrsTsContextWriter

對(duì)應(yīng)的writer 實(shí)際是SrsFileWriter ,也就是說(shuō)SrsFileWriter 負(fù)責(zé)?件的寫(xiě)?

SrsTsContextWriter::write_audio 寫(xiě)?TS的audio
#0 SrsTsContextWriter::write_audio (this=0xa3c770, audio=0xa45bf0) at
src/kernel/srs_kernel_ts.cpp:2582
#1 0x00000000004f1858 in SrsHlsMuxer::flush_audio (this=0xa3b6f0, cache=0xa3b580)at src/app/srs_app_hls.cpp:552
#2 0x00000000004f5089 in SrsHlsController::write_audio (this=0xa3b560, frame=0xa41640,pts=3060)at src/app/srs_app_hls.cpp:1001
#3 0x00000000004f613c in SrsHls::on_audio (this=0xa3b030, shared_audio=0x7ffff7ee8b10,format=0xa3bad0)at src/app/srs_app_hls.cpp:1290
#4 0x00000000004deeaf in SrsOriginHub::on_audio (this=0xa3b670,shared_audio=0x7ffff7ee8b10)at src/app/srs_app_source.cpp:969
#5 0x00000000004e579a in SrsSource::on_audio_imp (this=0xa3b1e0, msg=0x7ffff7ee8b10)at src/app/srs_app_source.cpp:2191
#6 0x00000000004e539d in SrsSource::on_audio (this=0xa3b1e0, shared_audio=0xa3dfa0)at src/app/srs_app_source.cpp:2141
#7 0x00000000004d8f28 in SrsRtmpConn::process_publish_message (this=0xa30d60,source=0xa3b1e0,msg=0xa3dfa0) at src/app/srs_app_rtmp_conn.cpp:1014
#8 0x00000000004d8dce in SrsRtmpConn::handle_publish_message (this=0xa30d60,source=0xa3b1e0, msg=0xa3dfa0)at src/app/srs_app_rtmp_conn.cpp:993
#9 0x00000000005810b6 in SrsPublishRecvThread::consume (this=0x7ffff7f42800,msg=0xa3dfa0)at src/app/srs_app_recv_thread.cpp:389
#10 0x000000000057fbd4 in SrsRecvThread::do_cycle (this=0x7ffff7f42808)at src/app/srs_app_recv_thread.cpp:146
---Type <return> to continue, or q <return> to quit---
#11 0x000000000057fa25 in SrsRecvThread::cycle (this=0x7ffff7f42808) at src/app/srs_app_recv_thread.cpp:115
#12 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa3de00) at src/app/srs_app_st.cpp:198
#13 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa3de00) at src/app/srs_app_st.cpp:213
SrsTsContextWriter::write_video 寫(xiě)?TS的video

在調(diào)?write_video之前是先要 SrsTsMessageCache::cache_video 緩存video

#0 SrsTsContextWriter::write_video (this=0xa3c770, video=0xa45bf0) atsrc/kernel/srs_kernel_ts.cpp:2597
#1 0x00000000004f1a67 in SrsHlsMuxer::flush_video (this=0xa3b6f0, cache=0xa3b580)at src/app/srs_app_hls.cpp:581
#2 0x00000000004f523a in SrsHlsController::write_video (this=0xa3b560, frame=0xa3fdb0,dts=0)at src/app/srs_app_hls.cpp:1031
#3 0x00000000004f63c3 in SrsHls::on_video (this=0xa3b030, shared_video=0x7ffff7ee8b00,format=0xa3bad0)at src/app/srs_app_hls.cpp:1340
#4 0x00000000004dfbef in SrsOriginHub::on_video (this=0xa3b670,shared_video=0x7ffff7ee8b00,is_sequence_header=false) at src/app/srs_app_source.cpp:1062
#5 0x00000000004e5fa5 in SrsSource::on_video_imp (this=0xa3b1e0, msg=0x7ffff7ee8b00)at src/app/srs_app_source.cpp:2306
#6 0x00000000004e5bf9 in SrsSource::on_video (this=0xa3b1e0, shared_video=0xa3dfa0)at src/app/srs_app_source.cpp:2261
#7 0x00000000004d8fa7 in SrsRtmpConn::process_publish_message (this=0xa30d60,source=0xa3b1e0,msg=0xa3dfa0) at src/app/srs_app_rtmp_conn.cpp:1021
#8 0x00000000004d8dce in SrsRtmpConn::handle_publish_message (this=0xa30d60,source=0xa3b1e0, msg=0xa3dfa0)at src/app/srs_app_rtmp_conn.cpp:993
#9 0x00000000005810b6 in SrsPublishRecvThread::consume (this=0x7ffff7f42800,msg=0xa3dfa0)at src/app/srs_app_recv_thread.cpp:389
#10 0x000000000057fbd4 in SrsRecvThread::do_cycle (this=0x7ffff7f42808)at src/app/srs_app_recv_thread.cpp:146
---Type <return> to continue, or q <return> to quit---
#11 0x000000000057fa25 in SrsRecvThread::cycle (this=0x7ffff7f42808) at src/app/srs_app_recv_thread.cpp:115
#12 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa3de00) at src/app/srs_app_st.cpp:198
#13 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa3de00) at src/app/srs_app_st.cpp:213
SrsHlsMuxer::segment_open 開(kāi)始?個(gè)segment
#0 SrsHlsMuxer::segment_open (this=0xa3b6d0) at src/app/srs_app_hls.cpp:353
#1 0x00000000004f5406 in SrsHlsController::reap_segment (this=0xa3b540) at src/app/srs_app_hls.cpp:1058
#2 0x00000000004f51d2 in SrsHlsController::write_video (this=0xa3b540, frame=0xa3fd90,dts=2379600)at src/app/srs_app_hls.cpp:1024
#3 0x00000000004f63c3 in SrsHls::on_video (this=0xa3b010, shared_video=0x7ffff7ee8b00,format=0xa3bab0)at src/app/srs_app_hls.cpp:1340
#4 0x00000000004dfbef in SrsOriginHub::on_video (this=0xa3b650,shared_video=0x7ffff7ee8b00,is_sequence_header=false) at src/app/srs_app_source.cpp:1062
#5 0x00000000004e5fa5 in SrsSource::on_video_imp (this=0xa3b1c0, msg=0x7ffff7ee8b00)at src/app/srs_app_source.cpp:2306
#6 0x00000000004e5bf9 in SrsSource::on_video (this=0xa3b1c0, shared_video=0xa3df80)at src/app/srs_app_source.cpp:2261
#7 0x00000000004d8fa7 in SrsRtmpConn::process_publish_message (this=0xa30d60,source=0xa3b1c0,msg=0xa3df80) at src/app/srs_app_rtmp_conn.cpp:1021
#8 0x00000000004d8dce in SrsRtmpConn::handle_publish_message (this=0xa30d60,source=0xa3b1c0, msg=0xa3df80)at src/app/srs_app_rtmp_conn.cpp:993
#9 0x00000000005810b6 in SrsPublishRecvThread::consume (this=0x7ffff7f42800,msg=0xa3df80)at src/app/srs_app_recv_thread.cpp:389
#10 0x000000000057fbd4 in SrsRecvThread::do_cycle (this=0x7ffff7f42808)at src/app/srs_app_recv_thread.cpp:146
---Type <return> to continue, or q <return> to quit---
#11 0x000000000057fa25 in SrsRecvThread::cycle (this=0x7ffff7f42808) at src/app/srs_app_recv_thread.cpp:115
#12 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa3dde0) at src/app/srs_app_st.cpp:198
#13 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa3dde0) at src/app/srs_app_st.cpp:213
#14 0x00000000005bdd9d in _st_thread_main () at sched.c:337
SrsHlsMuxer::do_segment_close 結(jié)束?個(gè)segment的寫(xiě)?
#0 SrsHlsMuxer::do_segment_close (this=0xa3b6f0) at src/app/srs_app_hls.cpp:602
#1 0x00000000004f1b19 in SrsHlsMuxer::segment_close (this=0xa3b6f0) at src/app/srs_app_hls.cpp:593
#2 0x00000000004f52c4 in SrsHlsController::reap_segment (this=0xa3b560) at
src/app/srs_app_hls.cpp:1046
#3 0x00000000004f51d2 in SrsHlsController::write_video (this=0xa3b560, frame=0xa3fdb0,dts=1328400)at src/app/srs_app_hls.cpp:1024
#4 0x00000000004f63c3 in SrsHls::on_video (this=0xa3b030, shared_video=0x7ffff7ee8b00,format=0xa3bad0)at src/app/srs_app_hls.cpp:1340
#5 0x00000000004dfbef in SrsOriginHub::on_video (this=0xa3b670,shared_video=0x7ffff7ee8b00,is_sequence_header=false) at src/app/srs_app_source.cpp:1062
#6 0x00000000004e5fa5 in SrsSource::on_video_imp (this=0xa3b1e0, msg=0x7ffff7ee8b00)at src/app/srs_app_source.cpp:2306
#7 0x00000000004e5bf9 in SrsSource::on_video (this=0xa3b1e0, shared_video=0xa3dfa0)at src/app/srs_app_source.cpp:2261
#8 0x00000000004d8fa7 in SrsRtmpConn::process_publish_message (this=0xa30d60,source=0xa3b1e0,msg=0xa3dfa0) at src/app/srs_app_rtmp_conn.cpp:1021
#9 0x00000000004d8dce in SrsRtmpConn::handle_publish_message (this=0xa30d60,source=0xa3b1e0, msg=0xa3dfa0)at src/app/srs_app_rtmp_conn.cpp:993
#10 0x00000000005810b6 in SrsPublishRecvThread::consume (this=0x7ffff7f42800, msg=0xa3dfa0)at src/app/srs_app_recv_thread.cpp:389
#11 0x000000000057fbd4 in SrsRecvThread::do_cycle (this=0x7ffff7f42808)at src/app/srs_app_recv_thread.cpp:146
---Type <return> to continue, or q <return> to quit--- 
#12 0x000000000057fa25 in SrsRecvThread::cycle (this=0x7ffff7f42808) at src/app/srs_app_recv_thread.cpp:115
#13 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa3de00) at src/app/srs_app_st.cpp:198
SrsAsyncCallWorker::execute push了什么任務(wù)

在SrsAsyncCallWorker::flush_tasks??執(zhí)?

SrsFragment::unlink_file刪除?個(gè)segment

拉流斷點(diǎn)

SrsFileReader::SrsFileReader 讀取ts?件
394 if ((err = fs->open(fullpath)) != srs_success) {
(gdb) print fullpath
$1 = "./objs/nginx/html/live/livestream.m3u8"
請(qǐng)求m3u8?件
#0 SrsFileReader::SrsFileReader (this=0xa7ac50, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)at src/kernel/srs_kernel_file.cpp:195
#1 0x0000000000459258 in ISrsFileReaderFactory::create_file_reader (this=0xa122f0)at src/kernel/srs_kernel_file.cpp:192
#2 0x0000000000499842 in SrsHttpFileServer::serve_file (this=0xa12310, w=0x7ffff7f0cbd0,r=0xa77130,fullpath="./objs/nginx/html/live/livestream.m3u8") at src/protocol/srs_http_stack.cpp:391
#3 0x000000000049957e in SrsHttpFileServer::serve_http (this=0xa12310, w=0x7ffff7f0cbd0,r=0xa77130)at src/protocol/srs_http_stack.cpp:384
#4 0x000000000049c86f in SrsHttpServeMux::serve_http (this=0xa10420, w=0x7ffff7f0cbd0,r=0xa77130)at src/protocol/srs_http_stack.cpp:711
#5 0x00000000005620a1 in SrsHttpServer::serve_http (this=0xa11e60, w=0x7ffff7f0cbd0,r=0xa77130)at src/app/srs_app_http_conn.cpp:303
#6 0x000000000049d6be in SrsHttpCorsMux::serve_http (this=0xa59bb0, w=0x7ffff7f0cbd0,r=0xa77130)at src/protocol/srs_http_stack.cpp:859
#7 0x0000000000561086 in SrsHttpConn::process_request (this=0xa76ea0, w=0x7ffff7f0cbd0,r=0xa77130)at src/app/srs_app_http_conn.cpp:161
#8 0x0000000000560ce8 in SrsHttpConn::do_cycle (this=0xa76ea0) at src/app/srs_app_http_conn.cpp:133
#9 0x00000000004d10fb in SrsConnection::cycle (this=0xa76ea0) at src/app/srs_app_conn.cpp:171
#10 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa5aa20) at src/app/srs_app_st.cpp:198
#11 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa5aa20) at src/app/srs_app_st.cpp:213
---Type <return> to continue, or q <return> to quit---
#12 0x00000000005bdd9d in _st_thread_main () at sched.c:337
#13 0x00000000005be515 in st_thread_create (start=0x5bd719 <_st_vp_schedule+170>,arg=0x900000001,joinable=1, stk_size=1) at sched.c:616
請(qǐng)求ts?件
#0 SrsFileReader::SrsFileReader (this=0xa3e030, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)at src/kernel/srs_kernel_file.cpp:195
#1 0x0000000000459258 in ISrsFileReaderFactory::create_file_reader (this=0xa122f0)at src/kernel/srs_kernel_file.cpp:192
#2 0x0000000000499842 in SrsHttpFileServer::serve_file (this=0xa12310, w=0x7ffff7f42bd0,r=0xa7c6d0,fullpath="./objs/nginx/html/live/livestream-31.ts") at src/protocol/srs_http_stack.cpp:391
#3 0x000000000049957e in SrsHttpFileServer::serve_http (this=0xa12310, w=0x7ffff7f42bd0,r=0xa7c6d0)at src/protocol/srs_http_stack.cpp:384
#4 0x000000000049c86f in SrsHttpServeMux::serve_http (this=0xa10420, w=0x7ffff7f42bd0,r=0xa7c6d0)at src/protocol/srs_http_stack.cpp:711
#5 0x00000000005620a1 in SrsHttpServer::serve_http (this=0xa11e60, w=0x7ffff7f42bd0,r=0xa7c6d0)at src/app/srs_app_http_conn.cpp:303
#6 0x000000000049d6be in SrsHttpCorsMux::serve_http (this=0xa77c70, w=0x7ffff7f42bd0,r=0xa7c6d0)at src/protocol/srs_http_stack.cpp:859
#7 0x0000000000561086 in SrsHttpConn::process_request (this=0xa7bbc0, w=0x7ffff7f42bd0,r=0xa7c6d0)at src/app/srs_app_http_conn.cpp:161
#8 0x0000000000560ce8 in SrsHttpConn::do_cycle (this=0xa7bbc0) at src/app/srs_app_http_conn.cpp:133
#9 0x00000000004d10fb in SrsConnection::cycle (this=0xa7bbc0) at src/app/srs_app_conn.cpp:171
#10 0x0000000000509c88 in SrsSTCoroutine::cycle (this=0xa30430) at src/app/srs_app_st.cpp:198
#11 0x0000000000509cfd in SrsSTCoroutine::pfn (arg=0xa30430) at src/app/srs_app_st.cpp:213

類(lèi)解析

SrsHls 對(duì)于HLS業(yè)務(wù)的封裝
SrsHlsController The hls stream cache
SrsHlsMuxer 負(fù)責(zé)?產(chǎn)m3u8和ts?件
SrsHlsSegment 負(fù)責(zé)分?焦匈,?件創(chuàng)建血公、刪除等
SrsFragment 對(duì)?件的處理,是SrsHlsSegment 的基類(lèi)
SrsFragmentWindow 管理segment

SrsAsyncCallWorker::cycle

SrsAsyncCallWorker::flush_tasks

SrsHlsController::write_audio

SrsHlsController::write_video

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缓熟,一起剝皮案震驚了整個(gè)濱河市累魔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌够滑,老刑警劉巖垦写,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異彰触,居然都是意外死亡梯投,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)况毅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人尔许,你說(shuō)我怎么就攤上這事么鹤。” “怎么了味廊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蒸甜,是天一觀的道長(zhǎng)棠耕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)柠新,這世上最難降的妖魔是什么昧辽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮登颓,結(jié)果婚禮上搅荞,老公的妹妹穿的比我還像新娘。我一直安慰自己框咙,他們只是感情好咕痛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著喇嘱,像睡著了一般茉贡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上者铜,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天腔丧,我揣著相機(jī)與錄音,去河邊找鬼作烟。 笑死愉粤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拿撩。 我是一名探鬼主播衣厘,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼压恒!你這毒婦竟也來(lái)了影暴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤探赫,失蹤者是張志新(化名)和其女友劉穎型宙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伦吠,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妆兑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了讨勤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箭跳。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晨另,死狀恐怖潭千,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情借尿,我是刑警寧澤刨晴,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布屉来,位于F島的核電站,受9級(jí)特大地震影響狈癞,放射性物質(zhì)發(fā)生泄漏茄靠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一蝶桶、第九天 我趴在偏房一處隱蔽的房頂上張望慨绳。 院中可真熱鬧,春花似錦真竖、人聲如沸脐雪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)战秋。三九已至,卻和暖如春讨韭,著一層夾襖步出監(jiān)牢的瞬間脂信,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工透硝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狰闪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓濒生,卻偏偏與公主長(zhǎng)得像尝哆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甜攀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容