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)景包括:
- 跨平臺(tái):PC主要的直播?案是RTMP撒强,也有?些庫(kù)能播放HLS,譬如jwplayer笙什,基于osmf的hls插件也??堆飘哨。所以實(shí)際上如果選?種協(xié)議能跨PC/Android/IOS,那就是HLS琐凭。
- iOS上苛刻的穩(wěn)定性要求:IOS上最穩(wěn)定的當(dāng)然是HLS芽隆,穩(wěn)定性不差于RTMP在PC-flash上的表現(xiàn)。
- 友好的CDN分發(fā)?式:?前CDN對(duì)于RTMP也是基本協(xié)議,但是HLS分發(fā)的基礎(chǔ)是HTTP胚吁,所以CDN的接?和分發(fā)會(huì)?RTMP更加完善牙躺。能在各種CDN之間切換,RTMP也能腕扶,只是可能需要對(duì)接測(cè)試孽拷。
- 簡(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ā)?式:HLS和RTMP,什么時(shí)候?誰(shuí)衙傀,完全決定于應(yīng)?場(chǎng)景抬吟。
還有其他的分發(fā)?式,這些分發(fā)?式不屬于互聯(lián)?常?和通?的?式统抬,不予以?較:
- 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ù)端)挥下。
- 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ò)。
- RTSP:這種不是互聯(lián)?上的主要應(yīng)?解取,在其他領(lǐng)域譬如安防等有?泛應(yīng)?步责。
另外,HTTP的也分為?種:
- HTTP progressive:早期流媒體服務(wù)器分發(fā)http?件時(shí),以普通的http?件分發(fā)蔓肯,這種叫做漸進(jìn)式下載遂鹊,意思就是如果?件很?譬如1?時(shí)時(shí)?1GB??,想從中間開(kāi)始播放是不?的蔗包。但這種?式已經(jīng)是作古了秉扑,很多http服務(wù)器?持http?件的seek,就是從中間開(kāi)始播放调限。
- HTTP stream:?持seek的HTTP流舟陆,譬如各家視頻?站的點(diǎn)播分發(fā)?式〕馨或者稍微復(fù)雜點(diǎn)的秦躯,譬如把?個(gè)??件切?段之后分發(fā)。?前在pc/flash上點(diǎn)播國(guó)內(nèi)的主流分發(fā)是這種?式裆装。
- HLS:這種是現(xiàn)在適配?式最?(除了flash, 需要額外的as庫(kù)?持)踱承,在PC上有vlc,Android/IOS原?播放器就?持播放HLS哨免,HTML5??的url可以寫(xiě)HLS地址茎活。總之琢唾,在移動(dòng)端是以HLS為主载荔。
- HDS:adobe??的HLS,?坨屎采桃。
- DASH:各家提出的HLS懒熙,?前還沒(méi)有?泛應(yīng)?。
對(duì)?以下互聯(lián)?上?的流媒體分發(fā)?式:
- HLS:apple的HLS芍碧,?持點(diǎn)播和直播煌珊。
- HTTP:即HTTP stream号俐,各家??定義的http流泌豆,應(yīng)?于國(guó)內(nèi)點(diǎn)播視頻?站。
- RTMP:直播應(yīng)?吏饿,對(duì)實(shí)時(shí)性有?定要求踪危,以PC為主。
更進(jìn)?步的?較繼續(xù)參考 srs官?wiki:
https://github.com/ossrs/srs/wiki/v3_CN_RTMP.PK.HTTP
推薦的?式
- 編碼器輸出RTMP協(xié)議猪落。
- 流媒體系統(tǒng)接?使?RTMP協(xié)議贞远。
- 流媒體系統(tǒng)內(nèi)部直播分發(fā)使?RTMP。
- PC+直播+實(shí)時(shí)性要求?:使?flash播放RTMP笨忌。
- PC+直播+沒(méi)有實(shí)時(shí)性要求:使?RTMP或者HLS均可蓝仲。
- PC+點(diǎn)播:使?HTTP或者HLS。
- Apple IOS/OSX:都使?HLS(實(shí)時(shí)性要求?得??解析RTMP,或者使?外部庫(kù)袱结,譬如https://www.vitamio.org)
- 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