mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 20:31:56 +00:00
Squash: Merge SRS 4.0
This commit is contained in:
parent
6c597facfb
commit
a81aa2edc5
65 changed files with 276 additions and 5990 deletions
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -84,6 +84,8 @@ jobs:
|
|||
run: |
|
||||
docker tag ossrs/srs:$SRS_TAG registry.cn-hangzhou.aliyuncs.com/ossrs/srs:$SRS_TAG
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/ossrs/srs:$SRS_TAG
|
||||
docker tag ossrs/srs:$SRS_TAG registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v$SRS_MAJOR
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v$SRS_MAJOR
|
||||
docker tag ossrs/srs:$SRS_TAG registry.cn-hangzhou.aliyuncs.com/ossrs/srs:$SRS_MAJOR
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/ossrs/srs:$SRS_MAJOR
|
||||
|
||||
|
|
1
trunk/3rdparty/httpx-static/.gitignore
vendored
1
trunk/3rdparty/httpx-static/.gitignore
vendored
|
@ -5,3 +5,4 @@ letsencrypt.cache
|
|||
*.key
|
||||
objs
|
||||
.format.txt
|
||||
.DS_Store
|
||||
|
|
6
trunk/3rdparty/httpx-static/README.md
vendored
6
trunk/3rdparty/httpx-static/README.md
vendored
|
@ -2,6 +2,12 @@
|
|||
|
||||
A HTTP/HTTPS Server, support letsencrypt or self-sign HTTPS and proxying HTTP as HTTPS.
|
||||
|
||||
Docker for https://github.com/ossrs/go-oryx
|
||||
|
||||
Build at https://code.aliyun.com/ossrs/go-oryx
|
||||
|
||||
Images at https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/httpx/images
|
||||
|
||||
> Remark: Requires GO1.8+
|
||||
|
||||
## Usage
|
||||
|
|
161
trunk/3rdparty/httpx-static/main.go
vendored
161
trunk/3rdparty/httpx-static/main.go
vendored
|
@ -36,6 +36,7 @@ import (
|
|||
oh "github.com/ossrs/go-oryx-lib/http"
|
||||
"github.com/ossrs/go-oryx-lib/https"
|
||||
ol "github.com/ossrs/go-oryx-lib/logger"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -77,8 +78,77 @@ func shouldProxyURL(srcPath, proxyPath string) bool {
|
|||
return strings.HasPrefix(srcPath, proxyPath)
|
||||
}
|
||||
|
||||
func NewComplexProxy(ctx context.Context, proxyUrl *url.URL, originalRequest *http.Request) http.Handler {
|
||||
// about x-real-ip and x-forwarded-for or
|
||||
// about X-Real-IP and X-Forwarded-For or
|
||||
// https://segmentfault.com/q/1010000002409659
|
||||
// https://distinctplace.com/2014/04/23/story-behind-x-forwarded-for-and-x-real-ip-headers/
|
||||
// @remark http proxy will set the X-Forwarded-For.
|
||||
func addProxyAddToHeader(remoteAddr, realIP string, fwd []string, header http.Header, omitForward bool) {
|
||||
rip, _, err := net.SplitHostPort(remoteAddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if realIP != "" {
|
||||
header.Set("X-Real-IP", realIP)
|
||||
} else {
|
||||
header.Set("X-Real-IP", rip)
|
||||
}
|
||||
|
||||
if !omitForward {
|
||||
header["X-Forwarded-For"] = fwd[:]
|
||||
header.Add("X-Forwarded-For", rip)
|
||||
}
|
||||
}
|
||||
|
||||
func filterByPreHook(ctx context.Context, preHook *url.URL, req *http.Request) error {
|
||||
target := *preHook
|
||||
target.RawQuery = strings.Join([]string{target.RawQuery, req.URL.RawQuery}, "&")
|
||||
|
||||
api := target.String()
|
||||
r, err := http.NewRequestWithContext(ctx, req.Method, api, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add real ip and forwarded for to header.
|
||||
// We should append the forward for pass-by.
|
||||
addProxyAddToHeader(req.RemoteAddr, req.Header.Get("X-Real-IP"), req.Header["X-Forwarded-For"], r.Header, false)
|
||||
ol.Tf(ctx, "Pre-hook proxy addr req=%v, r=%v", req.Header, r.Header)
|
||||
|
||||
r2, err := http.DefaultClient.Do(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r2.Body.Close()
|
||||
|
||||
if r2.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("Pre-hook HTTP StatusCode=%v %v", r2.StatusCode, r2.Status)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(r2.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ol.Tf(ctx, "Pre-hook %v url=%v, res=%v, headers=%v", req.Method, api, string(b), r.Header)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewComplexProxy(ctx context.Context, proxyUrl, preHook *url.URL, originalRequest *http.Request) http.Handler {
|
||||
// Hook before proxy it.
|
||||
if preHook != nil {
|
||||
if err := filterByPreHook(ctx, preHook, originalRequest); err != nil {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ol.Ef(ctx, "Pre-hook err %+v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Start proxy it.
|
||||
proxy := &httputil.ReverseProxy{}
|
||||
proxyUrlQuery := proxyUrl.Query()
|
||||
|
||||
// Create a proxy which attach a isolate logger.
|
||||
elogger := log.New(os.Stderr, fmt.Sprintf("%v ", originalRequest.RemoteAddr), log.LstdFlags)
|
||||
|
@ -94,27 +164,47 @@ func NewComplexProxy(ctx context.Context, proxyUrl *url.URL, originalRequest *ht
|
|||
}
|
||||
}
|
||||
|
||||
// about x-real-ip and x-forwarded-for or
|
||||
// about X-Real-IP and X-Forwarded-For or
|
||||
// https://segmentfault.com/q/1010000002409659
|
||||
// https://distinctplace.com/2014/04/23/story-behind-x-forwarded-for-and-x-real-ip-headers/
|
||||
// @remark http proxy will set the X-Forwarded-For.
|
||||
if rip := r.Header.Get("X-Real-IP"); rip == "" {
|
||||
if rip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
|
||||
r.Header.Set("X-Real-IP", rip)
|
||||
}
|
||||
}
|
||||
// Add real ip and forwarded for to header.
|
||||
// We should omit the forward header, because the ReverseProxy will doit.
|
||||
addProxyAddToHeader(r.RemoteAddr, r.Header.Get("X-Real-IP"), r.Header["X-Forwarded-For"], r.Header, true)
|
||||
ol.Tf(ctx, "Proxy addr header %v", r.Header)
|
||||
|
||||
r.URL.Scheme = proxyUrl.Scheme
|
||||
r.URL.Host = proxyUrl.Host
|
||||
|
||||
// Trim the prefix path.
|
||||
if trimPrefix := proxyUrlQuery.Get("trimPrefix"); trimPrefix != "" {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, trimPrefix)
|
||||
}
|
||||
// Aadd the prefix to path.
|
||||
if addPrefix := proxyUrlQuery.Get("addPrefix"); addPrefix != "" {
|
||||
r.URL.Path = addPrefix + r.URL.Path
|
||||
}
|
||||
|
||||
// The original request.Host requested by the client.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host
|
||||
if r.Header.Get("X-Forwarded-Host") == "" {
|
||||
r.Header.Set("X-Forwarded-Host", r.Host)
|
||||
}
|
||||
|
||||
// Set the Host of client request to the upstream server's, to act as client
|
||||
// directly access the upstream server.
|
||||
if proxyUrlQuery.Get("modifyRequestHost") != "false" {
|
||||
r.Host = proxyUrl.Host
|
||||
}
|
||||
|
||||
ra, url, rip := r.RemoteAddr, r.URL.String(), r.Header.Get("X-Real-Ip")
|
||||
ol.Tf(ctx, "proxy http rip=%v, addr=%v %v %v with headers %v", rip, ra, r.Method, url, r.Header)
|
||||
}
|
||||
|
||||
proxy.ModifyResponse = func(w *http.Response) error {
|
||||
// we already added this header, it will cause chrome failed when duplicated.
|
||||
if w.Header.Get("Access-Control-Allow-Origin") == "*" {
|
||||
// We have already set the server, so remove the upstream one.
|
||||
if proxyUrlQuery.Get("keepUpsreamServer") != "true" {
|
||||
w.Header.Del("Server")
|
||||
}
|
||||
|
||||
// We already added this header, it will cause chrome failed when duplicated.
|
||||
if w.Header.Get("Access-Control-Allow-Origin") != "" {
|
||||
w.Header.Del("Access-Control-Allow-Origin")
|
||||
}
|
||||
|
||||
|
@ -164,6 +254,9 @@ func run(ctx context.Context) error {
|
|||
flag.Var(&oproxies, "p", "proxy ruler")
|
||||
flag.Var(&oproxies, "proxy", "one or more proxy the matched path to backend, for example, -proxy http://127.0.0.1:8888/api/webrtc")
|
||||
|
||||
var oprehooks Strings
|
||||
flag.Var(&oprehooks, "pre-hook", "the pre-hook ruler, with request")
|
||||
|
||||
var sdomains, skeys, scerts Strings
|
||||
flag.Var(&sdomains, "sdomain", "the SSL hostname")
|
||||
flag.Var(&skeys, "skey", "the SSL key for domain")
|
||||
|
@ -181,6 +274,12 @@ func run(ctx context.Context) error {
|
|||
fmt.Println(fmt.Sprintf(" The www root path. Supports relative to argv[0]=%v. Default: ./html", path.Dir(os.Args[0])))
|
||||
fmt.Println(fmt.Sprintf(" -p, -proxy string"))
|
||||
fmt.Println(fmt.Sprintf(" Proxy path to backend. For example: http://127.0.0.1:8888/api/webrtc"))
|
||||
fmt.Println(fmt.Sprintf(" Proxy path to backend. For example: http://127.0.0.1:8888/api/webrtc?modifyRequestHost=false"))
|
||||
fmt.Println(fmt.Sprintf(" Proxy path to backend. For example: http://127.0.0.1:8888/api/webrtc?keepUpsreamServer=true"))
|
||||
fmt.Println(fmt.Sprintf(" Proxy path to backend. For example: http://127.0.0.1:8888/api/webrtc?trimPrefix=/ffmpeg"))
|
||||
fmt.Println(fmt.Sprintf(" Proxy path to backend. For example: http://127.0.0.1:8888/api/webrtc?addPrefix=/release"))
|
||||
fmt.Println(fmt.Sprintf(" -pre-hook string"))
|
||||
fmt.Println(fmt.Sprintf(" Pre-hook to backend, with request. For example: http://127.0.0.1:8888/api/stat"))
|
||||
fmt.Println(fmt.Sprintf("Options for HTTPS(letsencrypt cert):"))
|
||||
fmt.Println(fmt.Sprintf(" -l, -lets=bool"))
|
||||
fmt.Println(fmt.Sprintf(" Whether use letsencrypt CA. Default: false"))
|
||||
|
@ -239,6 +338,27 @@ func run(ctx context.Context) error {
|
|||
ol.Tf(ctx, "Proxy %v to %v", proxyUrl.Path, oproxy)
|
||||
}
|
||||
|
||||
var preHookUrls []*url.URL
|
||||
preHooks := make(map[string]*url.URL)
|
||||
for _, oprehook := range []string(oprehooks) {
|
||||
if oprehook == "" {
|
||||
return oe.Errorf("empty pre-hook in %v", oprehooks)
|
||||
}
|
||||
|
||||
preHookUrl, err := url.Parse(oprehook)
|
||||
if err != nil {
|
||||
return oe.Wrapf(err, "parse pre-hook %v", oprehook)
|
||||
}
|
||||
|
||||
if _, ok := preHooks[preHookUrl.Path]; ok {
|
||||
return oe.Errorf("pre-hook %v duplicated", preHookUrl.Path)
|
||||
}
|
||||
|
||||
preHookUrls = append(preHookUrls, preHookUrl)
|
||||
preHooks[preHookUrl.Path] = preHookUrl
|
||||
ol.Tf(ctx, "pre-hook %v to %v", preHookUrl.Path, oprehook)
|
||||
}
|
||||
|
||||
if !path.IsAbs(cacheFile) && path.IsAbs(os.Args[0]) {
|
||||
cacheFile = path.Join(path.Dir(os.Args[0]), cacheFile)
|
||||
}
|
||||
|
@ -272,13 +392,26 @@ func run(ctx context.Context) error {
|
|||
return
|
||||
}
|
||||
|
||||
// Find pre-hook to serve with proxy.
|
||||
var preHook *url.URL
|
||||
for _, preHookUrl := range preHookUrls {
|
||||
if !shouldProxyURL(r.URL.Path, preHookUrl.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
if p, ok := preHooks[preHookUrl.Path]; ok {
|
||||
preHook = p
|
||||
}
|
||||
}
|
||||
|
||||
// Find proxy to serve it.
|
||||
for _, proxyUrl := range proxyUrls {
|
||||
if !shouldProxyURL(r.URL.Path, proxyUrl.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
if proxy, ok := proxies[proxyUrl.Path]; ok {
|
||||
p := NewComplexProxy(ctx, proxy, r)
|
||||
p := NewComplexProxy(ctx, proxy, preHook, r)
|
||||
p.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
|
2
trunk/3rdparty/httpx-static/version.go
vendored
2
trunk/3rdparty/httpx-static/version.go
vendored
|
@ -35,7 +35,7 @@ func VersionMinor() int {
|
|||
}
|
||||
|
||||
func VersionRevision() int {
|
||||
return 5
|
||||
return 18
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
|
|
1
trunk/3rdparty/signaling/.gitignore
vendored
1
trunk/3rdparty/signaling/.gitignore
vendored
|
@ -16,3 +16,4 @@
|
|||
|
||||
.format.txt
|
||||
objs
|
||||
.DS_Store
|
||||
|
|
1
trunk/3rdparty/srs-bench/.gitignore
vendored
1
trunk/3rdparty/srs-bench/.gitignore
vendored
|
@ -6,3 +6,4 @@ objs
|
|||
.DS_Store
|
||||
|
||||
.format.txt
|
||||
.DS_Store
|
||||
|
|
|
@ -32,4 +32,4 @@ COPY --from=build /usr/local/srs /usr/local/srs
|
|||
|
||||
# Default workdir and command.
|
||||
WORKDIR /usr/local/srs
|
||||
CMD ["./objs/srs", "-c", "conf/srs.conf"]
|
||||
CMD ["./objs/srs", "-c", "conf/docker.conf"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# main config for srs.
|
||||
# docker config for srs.
|
||||
# @see full.conf for detail config.
|
||||
|
||||
listen 1935;
|
||||
|
@ -14,20 +14,10 @@ http_server {
|
|||
listen 8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
stats {
|
||||
network 0;
|
||||
disk sda sdb xvda xvdb;
|
||||
}
|
||||
rtc_server {
|
||||
enabled on;
|
||||
# Listen at udp://8000
|
||||
listen 8000;
|
||||
#
|
||||
# The $CANDIDATE means fetch from env, if not configed, use * as default.
|
||||
#
|
||||
# The * means retrieving server IP automatically, from all network interfaces,
|
||||
# @see https://github.com/ossrs/srs/issues/307#issuecomment-599028124
|
||||
candidate $CANDIDATE;
|
||||
enabled on;
|
||||
listen 8000;
|
||||
candidate $CANDIDATE;
|
||||
}
|
||||
vhost __defaultVhost__ {
|
||||
hls {
|
||||
|
@ -39,6 +29,5 @@ vhost __defaultVhost__ {
|
|||
}
|
||||
rtc {
|
||||
enabled on;
|
||||
bframe discard;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,11 +230,11 @@ http_api {
|
|||
# default: off
|
||||
allow_reload off;
|
||||
# whether enable rpc query.
|
||||
# default: off
|
||||
allow_query off;
|
||||
# Always off by https://github.com/ossrs/srs/issues/2653
|
||||
#allow_query off;
|
||||
# whether enable rpc update.
|
||||
# default: off
|
||||
allow_update off;
|
||||
# Always off by https://github.com/ossrs/srs/issues/2653
|
||||
#allow_update off;
|
||||
}
|
||||
# For https_api or HTTPS API.
|
||||
https {
|
||||
|
@ -323,33 +323,6 @@ stream_caster {
|
|||
listen 8935;
|
||||
}
|
||||
|
||||
# RTSP
|
||||
# It's deprecated and will be removed in the future, see [#2304](https://github.com/ossrs/srs/issues/2304#issuecomment-826009290).
|
||||
stream_caster {
|
||||
# whether stream caster is enabled.
|
||||
# default: off
|
||||
enabled on;
|
||||
# the caster type of stream, the casters:
|
||||
# rtsp, Real Time Streaming Protocol (RTSP).
|
||||
caster rtsp;
|
||||
# the output rtmp url.
|
||||
# for rtsp caster, the typically output url:
|
||||
# rtmp://127.0.0.1/[app]/[stream]
|
||||
# for example, the rtsp url:
|
||||
# rtsp://192.168.1.173:8544/live/livestream.sdp
|
||||
# where the [app] is "live" and [stream] is "livestream", output is:
|
||||
# rtmp://127.0.0.1/live/livestream
|
||||
output rtmp://127.0.0.1/[app]/[stream];
|
||||
# the listen port for stream caster.
|
||||
# for rtsp caster, listen at tcp port. for example, 554.
|
||||
listen 554;
|
||||
# for the rtsp caster, the rtp server local port over udp,
|
||||
# which reply the rtsp setup request message, the port will be used:
|
||||
# [rtp_port_min, rtp_port_max)
|
||||
rtp_port_min 57200;
|
||||
rtp_port_max 57300;
|
||||
}
|
||||
|
||||
# FLV
|
||||
stream_caster {
|
||||
# whether stream caster is enabled.
|
||||
|
|
|
@ -11,8 +11,6 @@ http_api {
|
|||
raw_api {
|
||||
enabled on;
|
||||
allow_reload on;
|
||||
allow_query on;
|
||||
allow_update on;
|
||||
}
|
||||
}
|
||||
http_server {
|
||||
|
|
|
@ -1,19 +1,2 @@
|
|||
# push MPEG-TS over UDP to SRS.
|
||||
# @see https://github.com/ossrs/srs/wiki/v2_CN_Streamer#push-mpeg-ts-over-udp
|
||||
# @see https://github.com/ossrs/srs/issues/250#issuecomment-72321769
|
||||
# @see full.conf for detail config.
|
||||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
daemon off;
|
||||
srs_log_tank console;
|
||||
stream_caster {
|
||||
enabled on;
|
||||
caster rtsp;
|
||||
output rtmp://127.0.0.1/[app]/[stream];
|
||||
listen 554;
|
||||
rtp_port_min 57200;
|
||||
rtp_port_max 57300;
|
||||
}
|
||||
vhost __defaultVhost__ {
|
||||
}
|
||||
# @note Removed for https://github.com/ossrs/srs/issues/2304#issuecomment-826009290
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
srs_log_tank file;
|
||||
srs_log_file ./objs/srs.log;
|
||||
#srs_log_tank file;
|
||||
#srs_log_file ./objs/srs.log;
|
||||
daemon on;
|
||||
http_api {
|
||||
enabled on;
|
||||
|
@ -15,6 +15,11 @@ http_server {
|
|||
listen 8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
rtc_server {
|
||||
enabled on;
|
||||
listen 8000;
|
||||
candidate $CANDIDATE;
|
||||
}
|
||||
vhost __defaultVhost__ {
|
||||
hls {
|
||||
enabled on;
|
||||
|
@ -23,4 +28,7 @@ vhost __defaultVhost__ {
|
|||
enabled on;
|
||||
mount [vhost]/[app]/[stream].flv;
|
||||
}
|
||||
rtc {
|
||||
enabled on;
|
||||
}
|
||||
}
|
||||
|
|
2
trunk/configure
vendored
2
trunk/configure
vendored
|
@ -269,7 +269,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_sourc
|
|||
"srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_edge"
|
||||
"srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
|
||||
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
|
||||
"srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
|
||||
"srs_app_mpegts_udp" "srs_app_listener" "srs_app_async_call"
|
||||
"srs_app_caster_flv" "srs_app_latest_version" "srs_app_uuid" "srs_app_process" "srs_app_ng_exec"
|
||||
"srs_app_hourglass" "srs_app_dash" "srs_app_fragment" "srs_app_dvr"
|
||||
"srs_app_coworkers" "srs_app_hybrid" "srs_app_threads")
|
||||
|
|
|
@ -27,6 +27,10 @@ The changelog for SRS.
|
|||
|
||||
## SRS 4.0 Changelog
|
||||
|
||||
* v4.0, 2021-10-10, Fix [#2304](https://github.com/ossrs/srs/issues/2304) Remove Push RTSP feature. v4.0.171
|
||||
* v4.0, 2021-10-10, Fix [#2653](https://github.com/ossrs/srs/issues/2653) Remove HTTP RAW API. v4.0.170
|
||||
* v4.0, 2021-10-08, Merge [#2654](https://github.com/ossrs/srs/pull/2654): Parse width and width from SPS/PPS. v4.0.169
|
||||
* v4.0, 2021-10-08, Default to log to console for docker. v4.0.168
|
||||
* v4.0, 2021-10-07, Fix bugs #2648, #2415. v4.0.167
|
||||
* v4.0, 2021-10-03, Support --arch and --cross-prefix for cross compile. 4.0.166
|
||||
* v4.0, 2021-10-03, Actions: Create source tar file srs-server-4.0.165.tar.gz
|
||||
|
|
|
@ -52,13 +52,13 @@ The features of SRS.
|
|||
- [x] [Experimental] Support MPEG-DASH, the future live streaming protocol, read [#299][bug #299].
|
||||
- [x] [Experimental] Support pushing MPEG-TS over UDP, please read [bug #250][bug #250].
|
||||
- [x] [Experimental] Support pushing FLV over HTTP POST, please read wiki([CN][v4_CN_Streamer2], [EN][v4_EN_Streamer2]).
|
||||
- [x] [Experimental] Support HTTP RAW API, please read [#459][bug #459], [#470][bug #470], [#319][bug #319].
|
||||
- [x] [Experimental] Support SRT server, read [#1147][bug #1147].
|
||||
- [x] [Experimental] Support transmux RTC to RTMP, [#2093][bug #2093].
|
||||
- [x] [Deprecated] Support pushing RTSP, please read [bug #2304][bug #2304].
|
||||
- [x] [Deprecated] Support Adobe HDS(f4m), please read wiki([CN][v4_CN_DeliveryHDS], [EN][v4_EN_DeliveryHDS]) and [#1535][bug #1535].
|
||||
- [x] [Deprecated] Support bandwidth testing, please read [#1535][bug #1535].
|
||||
- [x] [Deprecated] Support Adobe FMS/AMS token traverse([CN][v4_CN_DRM2], [EN][v4_EN_DRM2]) authentication, please read [#1535][bug #1535].
|
||||
- [x] [Removed] Support pushing RTSP, please read [#2304](https://github.com/ossrs/srs/issues/2304#issuecomment-826009290).
|
||||
- [x] [Removed] Support HTTP RAW API, please read [#2653](https://github.com/ossrs/srs/issues/2653).
|
||||
- [x] [Removed] Support RTMP client library: [srs-librtmp](https://github.com/ossrs/srs-librtmp).
|
||||
- [ ] Support Windows/Cygwin 64bits, [#2532](https://github.com/ossrs/srs/issues/2532).
|
||||
- [ ] Support push stream by GB28181, [#1500][bug #1500].
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/*
|
||||
# see: https://github.com/ossrs/srs/issues/190
|
||||
# see: https://github.com/ossrs/srs/wiki/v1_CN_SrsLinuxArm
|
||||
g++ -g -O0 -o jmp_sp jmp_sp.cpp
|
||||
arm-linux-gnueabi-g++ -g -o jmp_sp jmp_sp.cpp -static
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
<li class="{{'/streams'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/streams')">Streams</a></li>
|
||||
<li class="{{'/clients'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/clients')">Clients</a></li>
|
||||
<li class="{{'/configs'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/configs')">Config</a></li>
|
||||
<li class="{{'/dvr'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/dvr')">DVR</a></li>
|
||||
<li><a href="javascript:void(0)" ng-click="redirect('en_index.html', 'ng_index.html')">Chinese</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs-console">
|
||||
|
|
|
@ -12,9 +12,6 @@ scApp.config(["$routeProvider", function($routeProvider){
|
|||
.when("/clients", {templateUrl:"views/clients.html", controller:"CSCClients"})
|
||||
.when("/clients/:id", {templateUrl:"views/client.html", controller:"CSCClient"})
|
||||
.when("/configs", {templateUrl:"views/configs.html", controller:"CSCConfigs"})
|
||||
.when("/configs/:id", {templateUrl:"views/config.html", controller:"CSCConfig"})
|
||||
.when("/dvr", {templateUrl:"views/dvrs.html", controller:"CSCDvrs"})
|
||||
.when("/dvr/:vid/:sid/:app/:stream", {templateUrl:"views/dvr.html", controller:"CSCDvr"})
|
||||
.when("/summaries", {templateUrl:"views/summary.html", controller:"CSCSummary"});
|
||||
}]);
|
||||
|
||||
|
|
|
@ -296,268 +296,18 @@ scApp.controller("CSCClient", ["$scope", "$routeParams", "MSCApi", "$sc_nav", "$
|
|||
$sc_utility.log("trace", "Retrieve client info from SRS");
|
||||
}]);
|
||||
|
||||
scApp.controller("CSCDvrs", ['$scope', '$routeParams', 'MSCApi', '$sc_nav', '$sc_utility', function($scope, $routeParams, MSCApi, $sc_nav, $sc_utility){
|
||||
$sc_nav.in_dvr();
|
||||
|
||||
$sc_utility.log("trace", "Please use DVR in streams.");
|
||||
}]);
|
||||
|
||||
scApp.controller("CSCDvr", ['$scope', '$routeParams', 'MSCApi', '$sc_nav', '$sc_utility', function($scope, $routeParams, MSCApi, $sc_nav, $sc_utility){
|
||||
$sc_nav.in_dvr();
|
||||
|
||||
$scope.vid = $routeParams.vid;
|
||||
$scope.sid = $routeParams.sid;
|
||||
$scope.app = $routeParams.app.replace('___', '/');
|
||||
$scope.stream = $routeParams.stream.replace('___', '/');
|
||||
|
||||
$sc_utility.refresh.stop();
|
||||
|
||||
$scope.dvr = function(conf) {
|
||||
//console.log(apply); return;
|
||||
|
||||
// submit to server.
|
||||
$sc_utility.log("trace", "Submit to server for dvr apply=" + conf.value);
|
||||
MSCApi.clients_update3("dvr", $scope.vid, $scope.app + '/' + $scope.stream, conf.value? 'enable':'disable', function(data){
|
||||
$sc_utility.log("trace", "Server accepted, dvr apply=" + conf.value);
|
||||
conf.error = false;
|
||||
}, function(){
|
||||
conf.error = true;
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
MSCApi.configs_get2($scope.vid, function(data){
|
||||
data.vhost.stream = $scope.stream;
|
||||
data.vhost.app = $scope.app;
|
||||
data.vhost.vid = $scope.vid;
|
||||
data.vhost.sid = $scope.sid;
|
||||
|
||||
var dvr = data.vhost.dvr;
|
||||
if (!dvr) {
|
||||
dvr = {
|
||||
enabled: false
|
||||
};
|
||||
}
|
||||
if (dvr.dvr_apply) {
|
||||
if (dvr.dvr_apply.length === 1 && dvr.dvr_apply[0] === "all") {
|
||||
dvr.apply = true;
|
||||
} else {
|
||||
dvr.apply = system_array_contains(dvr.dvr_apply, $scope.app + '/' + $scope.stream);
|
||||
}
|
||||
} else {
|
||||
dvr.apply = true;
|
||||
}
|
||||
console.log(data.vhost);
|
||||
|
||||
$scope.global = $sc_utility.object2complex({}, data.vhost, null);
|
||||
console.log($scope.global);
|
||||
});
|
||||
|
||||
$sc_utility.log("trace", "Retrieve vhost config info from SRS");
|
||||
}]);
|
||||
|
||||
scApp.controller("CSCConfigs", ["$scope", "$location", "MSCApi", "$sc_nav", "$sc_utility", "$sc_server", function($scope, $location, MSCApi, $sc_nav, $sc_utility, $sc_server){
|
||||
$sc_nav.in_configs();
|
||||
|
||||
$sc_utility.refresh.stop();
|
||||
|
||||
$scope.support_raw_api = false;
|
||||
$scope.warn_raw_api = false;
|
||||
|
||||
MSCApi.configs_raw(function(data){
|
||||
$scope.http_api = data.http_api;
|
||||
$scope.support_raw_api = $sc_utility.raw_api_enabled(data);
|
||||
if (!$scope.support_raw_api) {
|
||||
$scope.warn_raw_api = true;
|
||||
return;
|
||||
}
|
||||
|
||||
MSCApi.configs_get(function(data){
|
||||
//console.log(data.global);
|
||||
$scope.global = $sc_utility.object2complex({}, data.global, null);
|
||||
//console.log($scope.global);
|
||||
});
|
||||
}, function(data){
|
||||
$scope.warn_raw_api = true;
|
||||
});
|
||||
|
||||
// operate vhost in client.
|
||||
$scope.new_vhost = function() {
|
||||
$scope.global.vhosts.push({
|
||||
editable: true
|
||||
});
|
||||
};
|
||||
|
||||
$scope.edit_vhost = function(vhost) {
|
||||
vhost.editable = true;
|
||||
};
|
||||
|
||||
$scope.cancel_vhost = function(vhost) {
|
||||
vhost.editable = false;
|
||||
vhost.name = vhost.vid;
|
||||
};
|
||||
|
||||
$scope.abort_vhost = function(vhost) {
|
||||
system_array_remove($scope.global.vhosts, vhost);
|
||||
};
|
||||
|
||||
// submit vhost to server
|
||||
$scope.add_vhost = function(vhost) {
|
||||
if (system_array_contains($scope.global.vhosts, function(e){ return vhost !== e && vhost.name === e.name; })) {
|
||||
$sc_utility.log("warn", "vhost " + vhost.name + "已经存在");
|
||||
return;
|
||||
}
|
||||
|
||||
MSCApi.clients_update2("vhost", vhost.name, "create", function(data){
|
||||
$sc_utility.copy_object(vhost, data.data);
|
||||
vhost.enabled = true;
|
||||
vhost.editable = false;
|
||||
|
||||
$sc_utility.log("trace", "创建vhost成功");
|
||||
});
|
||||
|
||||
$sc_utility.log("trace", "提交vhost到服务器");
|
||||
};
|
||||
|
||||
$scope.update_vhost = function(vhost) {
|
||||
if (vhost.vid === vhost.name) {
|
||||
$sc_utility.log("warn", "Vhost没有任何改变");
|
||||
return;
|
||||
}
|
||||
|
||||
MSCApi.clients_update3("vhost", vhost.vid, vhost.name, "update", function(data){
|
||||
vhost.vid = vhost.name;
|
||||
vhost.editable = false;
|
||||
$sc_utility.log("trace", "修改vhost成功");
|
||||
});
|
||||
$sc_utility.log("trace", "提交修改vhost请求到服务器");
|
||||
};
|
||||
|
||||
$scope.delete_vhost= function(vhost) {
|
||||
MSCApi.clients_update2("vhost", vhost.vid, "delete", function(data){
|
||||
system_array_remove($scope.global.vhosts, vhost);
|
||||
$sc_utility.log("trace", "删除vhost成功");
|
||||
});
|
||||
$sc_utility.log("trace", "提交删除vhost请求到服务器");
|
||||
};
|
||||
|
||||
$scope.disable_vhost = function(vhost) {
|
||||
MSCApi.clients_update2("vhost", vhost.vid, "disable", function(data){
|
||||
vhost.enabled = false;
|
||||
$sc_utility.log("trace", "禁用vhost成功");
|
||||
});
|
||||
$sc_utility.log("trace", "提交禁用vhost请求到服务器");
|
||||
};
|
||||
|
||||
$scope.enable_vhost = function(vhost) {
|
||||
MSCApi.clients_update2("vhost", vhost.vid, "enable", function(data){
|
||||
vhost.enabled = true;
|
||||
$sc_utility.log("trace", "启用vhost成功");
|
||||
});
|
||||
$sc_utility.log("trace", "提交启用vhost请求到服务器");
|
||||
};
|
||||
|
||||
// submit global config to server.
|
||||
$scope.submit = function(conf) {
|
||||
if (typeof conf.value !== "boolean" && !conf.value) {
|
||||
$sc_utility.log("warn", "global." + conf.key + " should not be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
var v = conf.value;
|
||||
if (conf.key === "listen") {
|
||||
if (!system_array_foreach(v, function(e){ return e; })) {
|
||||
$sc_utility.log("warn", "listen should not be empty");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "pid") {
|
||||
if (!system_string_startswith(v, ['./', '/var/', '/tmp/'])) {
|
||||
$sc_utility.log("warn", "pid should starts with ./, /var/ or /tmp/");
|
||||
return false;
|
||||
}
|
||||
if (!system_string_endswith(v, '.pid')) {
|
||||
$sc_utility.log("warn", "pid should be *.pid");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "chunk_size") {
|
||||
if (parseInt(v) < 128 || parseInt(v) > 65535) {
|
||||
$sc_utility.log("warn", "chunk_size should in [128, 65535], value=" + v);
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "ff_log_dir") {
|
||||
if (v !== '/dev/null' && !system_string_startswith(v, ['/var/', '/tmp/', './'])) {
|
||||
$sc_utility.log("warn", "ff_log_dir should be /dev/null or in ./, /var/ or /tmp/");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "srs_log_tank") {
|
||||
if (v !== "file" && v !== "console") {
|
||||
$sc_utility.log("warn", "srs_log_tank should be file or console");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "srs_log_level") {
|
||||
if (v !== "verbose" && v !== "info" && v !== "trace" && v !== "warn" && v !== "error") {
|
||||
$sc_utility.log("warn", "srs_log_level should be verbose, info, trace, warn, error");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "srs_log_file") {
|
||||
if (!system_string_startswith(v, ['./', '/var/', '/tmp/'])) {
|
||||
$sc_utility.log("warn", "srs_log_file should be in ./, /var/ or /tmp/");
|
||||
return false;
|
||||
}
|
||||
if (!system_string_endswith(v, '.log')) {
|
||||
$sc_utility.log("warn", "srs_log_file should be *.log");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "max_connections") {
|
||||
if (parseInt(v) < 10 || parseInt(v) > 65535) {
|
||||
$sc_utility.log("warn", "max_connections should in [10, 65535], value=" + v);
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "utc_time") {
|
||||
if (v === undefined) {
|
||||
$sc_utility.log("warn", "utc_time invalid");
|
||||
return false;
|
||||
}
|
||||
} else if (conf.key === "pithy_print_ms") {
|
||||
if (parseInt(v) < 100 || parseInt(v) > 300000) {
|
||||
$sc_utility.log("warn", "pithy_print_ms invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// submit to server.
|
||||
$sc_utility.log("trace", "Submit to server ok, " + conf.key + "=" + conf.value);
|
||||
MSCApi.clients_update(conf.key, conf.value, function(data){
|
||||
$sc_utility.log("trace", "Server accepted, " + conf.key + "=" + conf.value);
|
||||
conf.error = false;
|
||||
|
||||
// reload the rtmp service port when port changed.
|
||||
if (conf.key === "listen") {
|
||||
$sc_server.init($location, MSCApi);
|
||||
}
|
||||
}, function(){
|
||||
conf.error = true;
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$sc_utility.log("trace", "Retrieve config info from SRS");
|
||||
}]);
|
||||
|
||||
scApp.controller("CSCConfig", ["$scope", "$routeParams", "MSCApi", "$sc_nav", "$sc_utility", function($scope, $routeParams, MSCApi, $sc_nav, $sc_utility){
|
||||
$sc_nav.in_configs();
|
||||
|
||||
$sc_utility.refresh.stop();
|
||||
|
||||
MSCApi.configs_get2($routeParams.id, function(data){
|
||||
$scope.vhost = data.vhost;
|
||||
});
|
||||
|
||||
$sc_utility.log("trace", "Retrieve vhost config info from SRS");
|
||||
}]);
|
||||
|
||||
scApp.factory("MSCApi", ["$http", "$sc_server", function($http, $sc_server){
|
||||
return {
|
||||
versions_get: function(success) {
|
||||
|
@ -607,38 +357,6 @@ scApp.factory("MSCApi", ["$http", "$sc_server", function($http, $sc_server){
|
|||
var url = $sc_server.jsonp_query("/api/v1/raw", "rpc=query&scope=global");
|
||||
$http.jsonp(url).success(success);
|
||||
},
|
||||
configs_get2: function(id, success) {
|
||||
var url = $sc_server.jsonp_query("/api/v1/raw", "rpc=query&scope=vhost&vhost=" + id);
|
||||
$http.jsonp(url).success(success);
|
||||
},
|
||||
configs_get3: function(success) {
|
||||
var url = $sc_server.jsonp_query("/api/v1/raw", "rpc=query&scope=minimal");
|
||||
$http.jsonp(url).success(success);
|
||||
},
|
||||
clients_update: function(scope, value, success, error) {
|
||||
var query = "rpc=update&scope=" + scope + "&value=" + value;
|
||||
var url = $sc_server.jsonp_query("/api/v1/raw", query);
|
||||
var obj = $http.jsonp(url).success(success);
|
||||
if (error) {
|
||||
obj.error(error);
|
||||
}
|
||||
},
|
||||
clients_update2: function(scope, value, param, success, error) {
|
||||
var query = "rpc=update&scope=" + scope + "&value=" + value + "¶m=" + param;
|
||||
var url = $sc_server.jsonp_query("/api/v1/raw", query);
|
||||
var obj = $http.jsonp(url).success(success);
|
||||
if (error) {
|
||||
obj.error(error);
|
||||
}
|
||||
},
|
||||
clients_update3: function(scope, value, data, param, success, error) {
|
||||
var query = "rpc=update&scope=" + scope + "&value=" + value + "¶m=" + param + "&data=" + data;
|
||||
var url = $sc_server.jsonp_query("/api/v1/raw", query);
|
||||
var obj = $http.jsonp(url).success(success);
|
||||
if (error) {
|
||||
obj.error(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
@ -883,9 +601,6 @@ scApp.provider("$sc_nav", function(){
|
|||
in_configs: function(){
|
||||
this.selected = "/configs";
|
||||
},
|
||||
in_dvr: function(){
|
||||
this.selected = "/dvr";
|
||||
},
|
||||
go_summary: function($location){
|
||||
$location.path("/summaries");
|
||||
},
|
||||
|
@ -970,13 +685,6 @@ scApp.provider("$sc_server", [function(){
|
|||
} else {
|
||||
self.port = $location.port();
|
||||
}
|
||||
|
||||
// optional, init the rtmp port.
|
||||
MSCApi.configs_get3(function(data){
|
||||
if (data.minimal) {
|
||||
self.rtmp = data.minimal.listen;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return self;
|
||||
|
|
|
@ -12,9 +12,6 @@ scApp.config(["$routeProvider", function($routeProvider){
|
|||
.when("/clients", {templateUrl:"views/clients_en.html", controller:"CSCClients"})
|
||||
.when("/clients/:id", {templateUrl:"views/client_en.html", controller:"CSCClient"})
|
||||
.when("/configs", {templateUrl:"views/configs_en.html", controller:"CSCConfigs"})
|
||||
.when("/configs/:id", {templateUrl:"views/config_en.html", controller:"CSCConfig"})
|
||||
.when("/dvr", {templateUrl:"views/dvrs_en.html", controller:"CSCDvrs"})
|
||||
.when("/dvr/:vid/:sid/:app/:stream", {templateUrl:"views/dvr_en.html", controller:"CSCDvr"})
|
||||
.when("/summaries", {templateUrl:"views/summary_en.html", controller:"CSCSummary"});
|
||||
}]);
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
<li class="{{'/streams'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/streams')">视频流</a></li>
|
||||
<li class="{{'/clients'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/clients')">客户端</a></li>
|
||||
<li class="{{'/configs'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/configs')">配置</a></li>
|
||||
<li class="{{'/dvr'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/dvr')">DVR</a></li>
|
||||
<li><a href="javascript:void(0)" ng-click="redirect('ng_index.html', 'en_index.html')">English</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs-console">
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -8,10 +8,10 @@
|
|||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="alert alert-block alert-danger" ng-show="warn_raw_api">
|
||||
该服务器不支持HTTP RAW API,或者配置中禁用了该功能。参考<a href='https://github.com/ossrs/srs/wiki/v3_CN_HTTPApi#http-raw-api'>WIKI</a>。
|
||||
<div class="alert alert-block alert-danger">
|
||||
SRS 4.0不再支持HTTP RAW API。参考<a href='https://github.com/ossrs/srs/issues/2653'>#2653</a>。
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-bordered" ng-show="http_api">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
|
@ -43,410 +43,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器API配置(http_api)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP API,开启后就可以访问SRS提供的API管理服务器。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.listen.value"
|
||||
scp-desc="HTTP API的侦听地址,格式是<[address:]port>。默认: 1985">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="是否允许JS跨域,开启后JS可以直接跨域(还可以通过JSONP访问)。默认: {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP RAW API,允许API修改服务器配置。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="是否允许API进行Reload操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="是否允许API进行Query查询操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="是否允许API进行Update更新操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器全局配置
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.listen" scd-span="span3"
|
||||
scd-desc="RTMP服务器侦听的端口,提供RTMP服务,格式是<[address:]port>[,<addressN>portN]"
|
||||
scd-array="true" scd-default="1935"
|
||||
scd-submit="submit(global.listen)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pid" scd-span="span3"
|
||||
scd-desc="服务器使用的PID文件,每个进程必须用一个,否则无法启动。默认: ./objs/srs.pid"
|
||||
scd-default="./objs/srs.pid"
|
||||
scd-submit="submit(global.pid)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.chunk_size" scd-span="span3"
|
||||
scd-desc="默认的ChunkSize,即RTMP分包的大小。默认: 60000"
|
||||
scd-default="60000"
|
||||
scd-submit="submit(global.chunk_size)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.ff_log_dir" scd-span="span4"
|
||||
scd-desc="默认的FFMPEG日志目录,/dev/null禁用日志。默认: ./objs"
|
||||
scd-default="./objs"
|
||||
scd-submit="submit(global.ff_log_dir)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_tank" scd-span="span3"
|
||||
scd-desc="系统的日志容器,即存储方式。默认: file"
|
||||
scd-default="file", scd-select="file,console"
|
||||
scd-submit="submit(global.srs_log_tank)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_level" scd-span="span3"
|
||||
scd-desc="系统的日志级别,低于该级别的日志不会打印。默认: trace"
|
||||
scd-default="trace" scd-select="verbose,info,trace,warn,error"
|
||||
scd-submit="submit(global.srs_log_level)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_file" scd-span="span4"
|
||||
scd-desc="当日志容器为file,即日志写入文件时,日志文件的路径。默认: ./objs/srs.log"
|
||||
scd-default="./objs/srs.log"
|
||||
scd-submit="submit(global.srs_log_file)"
|
||||
ng-if="global.srs_log_tank.value == 'file'">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.max_connections" scd-span="span3"
|
||||
scd-desc="系统的最大连接数,超过后将拒绝新连接。默认: 1000"
|
||||
scd-default="1000"
|
||||
scd-submit="submit(global.max_connections)">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.daemon" scp-bool="true"
|
||||
scp-desc="是否以后台启动SRS。默认: {{true| sc_filter_yesno}}">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.utc_time" scd-span="span4"
|
||||
scd-desc="是否启用UTC时间格式,影响日志的时间和路径中包含时间变量的配置。默认: {{false| sc_filter_yesno}}"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="submit(global.utc_time)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pithy_print_ms" scd-span="span3"
|
||||
scd-desc="简化形式的日志打印间隔,单位: 毫秒。默认: 10000"
|
||||
scd-default="10000" scd-select="1000,3000,5000,10000,30000"
|
||||
scd-submit="submit(global.pithy_print_ms)">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
虚拟主机(Vhosts)列表, 共配置有{{global.nb_vhosts.value}}个Vhost
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>
|
||||
<a href="javscript:void(0)" ng-click="new_vhost()" class="icon-plus"></a>
|
||||
</th>
|
||||
<th>主机名称</th>
|
||||
<th>开启</th>
|
||||
<th>源</th>
|
||||
<th>DVR</th>
|
||||
<th>HTTP</th>
|
||||
<th>FLV</th>
|
||||
<th>HLS</th>
|
||||
<th>HDS</th>
|
||||
<th>回调</th>
|
||||
<th ng-show="false">Exec</th>
|
||||
<th ng-show="false">BWT</th>
|
||||
<th>转发</th>
|
||||
<th>安全</th>
|
||||
<th ng-show="false">盗链</th>
|
||||
<th ng-show="false">MR</th>
|
||||
<th ng-show="false">RTC</th>
|
||||
<th ng-show="false">GOP</th>
|
||||
<th ng-show="false">TcpNoDelay</th>
|
||||
<th ng-show="false">MixCorrect</th>
|
||||
<th ng-show="false">TimeJitter</th>
|
||||
<th ng-show="false">ATC</th>
|
||||
<th>转码</th>
|
||||
<th>采集</th>
|
||||
<th>
|
||||
<a href="javascript:void(0)" ng-click="new_vhost()">添加</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in global.vhosts">
|
||||
<td><a href="#/vhosts/{{vhost.id}}" ng-show="vhost.id">{{vhost.id}}</a><span ng-show="!vhost.id">无流</span> </td>
|
||||
<td colspan="{{vhost.editable?13:1}}">
|
||||
<span ng-show="!vhost.editable">{{vhost.name}}</span>
|
||||
<span ng-show="vhost.editable">
|
||||
<input class="text span5" ng-model="vhost.name"><br/>
|
||||
请输入vhost的名称。
|
||||
</span>
|
||||
</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.enabled| sc_filter_yesno}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.origin| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.dvr| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_static| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_remux| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hls| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hds| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_hooks| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.exec| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.bandcheck| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.forward| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.security| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.refer| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mr| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.min_latency| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.gop_cache| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.tcp_nodelay| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mix_correct| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.time_jitter| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.atc| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.transcode| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.ingest| sc_filter_yn}}</td>
|
||||
<td>
|
||||
<span ng-show="vhost.editable">
|
||||
<!-- vhost exists in server -->
|
||||
<span ng-show="vhost.enabled != undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否提交{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="update_vhost(vhost)">
|
||||
提交
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="cancel_vhost(vhost)">放弃</a>
|
||||
</span>
|
||||
<!-- vhost in adding. -->
|
||||
<span ng-show="vhost.enabled == undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否提交{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="add_vhost(vhost)">
|
||||
提交
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="abort_vhost(vhost)">放弃</a>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.editable">
|
||||
<span ng-show="vhost.enabled">
|
||||
<span>编辑</span>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否禁用{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="disable_vhost(vhost)">
|
||||
禁用
|
||||
</a>
|
||||
<span>删除</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.enabled">
|
||||
<a href="javascript:void(0)" ng-click="edit_vhost(vhost)">编辑</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否启用{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="enable_vhost(vhost)">
|
||||
启用
|
||||
</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否删除{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="delete_vhost(vhost)">
|
||||
删除
|
||||
</a>
|
||||
</span>
|
||||
<a href="#/configs/{{vhost.name}}" ng-show="!vhost.editable">详细</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Kafka集群配置(kafka)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.enabled" scp-bool="true"
|
||||
scp-desc="是否开启Kafka,开启后SRS将数据汇报给Kafka集群。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.brokers"
|
||||
scp-desc="Broker列表,首次连接到Broker获取集群信息,格式是<ip:port>。">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器心跳汇报(heartbeat)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.enabled"
|
||||
scp-desc="是否开启服务器心跳,向外部系统汇报。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.interval"
|
||||
scp-desc="心跳间隔的时间,单位: 秒。默认: 9.9"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.url"
|
||||
scp-desc="汇报的HTTP服务器地址,汇报信息格式是JSON。默认: http://127.0.0.1:8085/api/v1/servers"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.device_id"
|
||||
scp-desc="设备ID,SRS会写入汇报信息中。"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.smmaries"
|
||||
scp-desc="是否汇报摘要,即服务器的summaries信息。默认: {{false| sc_filter_yesno}}"
|
||||
scd-bool="true"
|
||||
scd-submit="submit(global.heartbeat.summaries)"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器统计信息配置(stats)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.network"
|
||||
scp-desc="统计的网卡索引,从0开始算第一块网卡。默认: 0">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.disk"
|
||||
scp-desc="统计的磁盘名称,可以在/proc/diskstats中查看。"
|
||||
scd-array="true">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP服务器配置(http_server)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.enabled"
|
||||
scp-desc="是否开启HTTP文件服务器和HTTP流服务器。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.listen"
|
||||
scp-desc="HTTP服务器侦听的地址,格式是<[address:]port>。默认: 8080"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.dir"
|
||||
scp-desc="HTTP服务器的主目录。默认: ./objs/nginx/html"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
StreamCaster流转换器(stream_caster)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<td>Opt</td>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.enabled"
|
||||
scp-desc="是否开启StreamCaster,即接收特殊的流后转换成RTMP送到SRS。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.caster"
|
||||
scp-desc="转换器的类型,不同的类型需要不同的配置,mpegts_over_udp,rtsp,flv"
|
||||
scd-select="mpegts_over_udp,rtsp,flv"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.output"
|
||||
scp-desc="输出的RTMP地址,转换器侦听端口,接收特定的流,转换成RTMP后送到SRS。"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.listen"
|
||||
scp-desc="转换器侦听的地址,格式是<port>"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_min"
|
||||
scp-desc="转换器会在[rtp_port_min, rtp_port_max]中间选择一个新端口并侦听,参考RTP协议。"
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_max"
|
||||
scp-desc="转换器会在[rtp_port_min, rtp_port_max]中间选择一个新端口并侦听,参考RTP协议。"
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -8,10 +8,10 @@
|
|||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="alert alert-block alert-danger" ng-show="warn_raw_api">
|
||||
HTTP RAW API is not supported or disabled. Read <a href='https://github.com/ossrs/srs/wiki/v3_EN_HTTPApi#http-raw-api'>WIKI</a>。
|
||||
<div class="alert alert-block alert-danger">
|
||||
HTTP RAW API is removed, please read <a href='https://github.com/ossrs/srs/issues/2653'>#2653</a>。
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-bordered" ng-show="http_api">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
|
@ -43,410 +43,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP API Server
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enabel HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.listen.value"
|
||||
scp-desc="The HTTP API listen port, format is <[address:]port>. Default is 1985">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="Whether allow CORS for js(JSONP). Default is {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable HTTP RAW API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="Whether allow reload by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="Whether allow query by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="Whether allow update by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
SRS Global Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.listen" scd-span="span3"
|
||||
scd-desc="RTMP listen port, format is <[address:]port>[,<addressN>portN]"
|
||||
scd-array="true" scd-default="1935"
|
||||
scd-submit="submit(global.listen)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pid" scd-span="span3"
|
||||
scd-desc="The pid file for SRS. Default is ./objs/srs.pid"
|
||||
scd-default="./objs/srs.pid"
|
||||
scd-submit="submit(global.pid)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.chunk_size" scd-span="span3"
|
||||
scd-desc="RTMP chunk size. Default is 60000"
|
||||
scd-default="60000"
|
||||
scd-submit="submit(global.chunk_size)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.ff_log_dir" scd-span="span4"
|
||||
scd-desc="FFMPEG log directory, use /dev/null to disable log. Default is ./objs"
|
||||
scd-default="./objs"
|
||||
scd-submit="submit(global.ff_log_dir)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_tank" scd-span="span3"
|
||||
scd-desc="System log store. Default is file"
|
||||
scd-default="file", scd-select="file,console"
|
||||
scd-submit="submit(global.srs_log_tank)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_level" scd-span="span3"
|
||||
scd-desc="System log level. Default is trace"
|
||||
scd-default="trace" scd-select="verbose,info,trace,warn,error"
|
||||
scd-submit="submit(global.srs_log_level)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_file" scd-span="span4"
|
||||
scd-desc="When log store is file, the log path. Default is ./objs/srs.log"
|
||||
scd-default="./objs/srs.log"
|
||||
scd-submit="submit(global.srs_log_file)"
|
||||
ng-if="global.srs_log_tank.value == 'file'">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.max_connections" scd-span="span3"
|
||||
scd-desc="System maximum connections. Default is 1000"
|
||||
scd-default="1000"
|
||||
scd-submit="submit(global.max_connections)">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.daemon" scp-bool="true"
|
||||
scp-desc="Whether start SRS as daemon. Default is {{true| sc_filter_yesno}}">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.utc_time" scd-span="span4"
|
||||
scd-desc="Whether use UTC time. Default is {{false| sc_filter_yesno}}"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="submit(global.utc_time)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pithy_print_ms" scd-span="span3"
|
||||
scd-desc="Pithy log print interval in ms. Default is 10000"
|
||||
scd-default="10000" scd-select="1000,3000,5000,10000,30000"
|
||||
scd-submit="submit(global.pithy_print_ms)">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
System Vhosts, total {{global.nb_vhosts.value}} vhosts configed.
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>
|
||||
<a href="javscript:void(0)" ng-click="new_vhost()" class="icon-plus"></a>
|
||||
</th>
|
||||
<th>Name</th>
|
||||
<th title="Whether Enabled">E</th>
|
||||
<th title="Whether Origin Server">O</th>
|
||||
<th title="DVR Configed">D</th>
|
||||
<th title="HTTP Server Configed">H</th>
|
||||
<th title="HTTP FLV Configed">FLV</th>
|
||||
<th title="HLS Configed">HLS</th>
|
||||
<th title="HDS Configed">HDS</th>
|
||||
<th title="HTTP Callback">CB</th>
|
||||
<th ng-show="false">Exec</th>
|
||||
<th ng-show="false">BWT</th>
|
||||
<th title="Forwarder">F</th>
|
||||
<th title="Security Configed">S</th>
|
||||
<th ng-show="false">Referer</th>
|
||||
<th ng-show="false">MR</th>
|
||||
<th ng-show="false">RTC</th>
|
||||
<th ng-show="false">GOP</th>
|
||||
<th ng-show="false">TcpNoDelay</th>
|
||||
<th ng-show="false">MixCorrect</th>
|
||||
<th ng-show="false">TimeJitter</th>
|
||||
<th ng-show="false">ATC</th>
|
||||
<th title="Transcode Configied">T</th>
|
||||
<th title="Ingester Configed">I</th>
|
||||
<th>
|
||||
<a href="javascript:void(0)" ng-click="new_vhost()">Add</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in global.vhosts">
|
||||
<td><a href="#/vhosts/{{vhost.id}}" ng-show="vhost.id">{{vhost.id}}</a><span ng-show="!vhost.id">No Stream</span> </td>
|
||||
<td colspan="{{vhost.editable?13:1}}">
|
||||
<span ng-show="!vhost.editable">{{vhost.name}}</span>
|
||||
<span ng-show="vhost.editable">
|
||||
<input class="text span5" ng-model="vhost.name"><br/>
|
||||
Please input vhost name.
|
||||
</span>
|
||||
</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.enabled| sc_filter_yesno}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.origin| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.dvr| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_static| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_remux| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hls| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hds| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_hooks| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.exec| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.bandcheck| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.forward| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.security| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.refer| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mr| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.min_latency| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.gop_cache| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.tcp_nodelay| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mix_correct| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.time_jitter| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.atc| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.transcode| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.ingest| sc_filter_yn}}</td>
|
||||
<td>
|
||||
<span ng-show="vhost.editable">
|
||||
<!-- vhost exists in server -->
|
||||
<span ng-show="vhost.enabled != undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm submit vhost {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="update_vhost(vhost)">
|
||||
Submit
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="cancel_vhost(vhost)">Cancel</a>
|
||||
</span>
|
||||
<!-- vhost in adding. -->
|
||||
<span ng-show="vhost.enabled == undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm submit vhost{{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="add_vhost(vhost)">
|
||||
Submit
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="abort_vhost(vhost)">Cancel</a>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.editable">
|
||||
<span ng-show="vhost.enabled">
|
||||
<span>Update</span>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to disable {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="disable_vhost(vhost)">
|
||||
Disable
|
||||
</a>
|
||||
<span>Delete</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.enabled">
|
||||
<a href="javascript:void(0)" ng-click="edit_vhost(vhost)">编辑</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to enable {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="enable_vhost(vhost)">
|
||||
Enable
|
||||
</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to delete {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="delete_vhost(vhost)">
|
||||
Delete
|
||||
</a>
|
||||
</span>
|
||||
<a href="#/configs/{{vhost.name}}" ng-show="!vhost.editable">Detail</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Config KAFKA
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable KAFKA. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.brokers"
|
||||
scp-desc="The broker list, format is <ip:port>">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
SRS Heartbeat
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.enabled"
|
||||
scp-desc="Whether enable heartbet. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.interval"
|
||||
scp-desc="The interval in seconds. Default is 9.9"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.url"
|
||||
scp-desc="The report url in json. Default is http://127.0.0.1:8085/api/v1/servers"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.device_id"
|
||||
scp-desc="The device ID."
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.smmaries"
|
||||
scp-desc="Whether report summaries. Default is {{false| sc_filter_yesno}}"
|
||||
scd-bool="true"
|
||||
scd-submit="submit(global.heartbeat.summaries)"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
STAT Hardward Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.network"
|
||||
scp-desc="The stat network index. Default is 0">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.disk"
|
||||
scp-desc="The stat disk name."
|
||||
scd-array="true">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP Server Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.enabled"
|
||||
scp-desc="Whether enable HTTP Server. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.listen"
|
||||
scp-desc="The HTTP Server listen port, format is <[address:]port>. Default is 8080"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.dir"
|
||||
scp-desc="The HTTP Server root directory. Default is ./objs/nginx/html"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Stream Caster Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<td>Opt</td>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.enabled"
|
||||
scp-desc="Whether enable StreamCaster. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.caster"
|
||||
scp-desc="The type of StreamCaster. For example, mpegts_over_udp,rtsp,flv"
|
||||
scd-select="mpegts_over_udp,rtsp,flv"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.output"
|
||||
scp-desc="The output RTMP url."
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.listen"
|
||||
scp-desc="The listen port, format is <port>"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_min"
|
||||
scp-desc="The RTP min port."
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_max"
|
||||
scp-desc="The RTP max port."
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,62 +0,0 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Vhost({{global.vid.value}})录制(DVR)配置
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.name" scp-link="#/vhosts/{{global.id.value}}"
|
||||
scp-desc="录制的流所属的Vhost的名称">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.app"
|
||||
scp-desc="录制的流所属的App的名称">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream" scp-link="#/streams/{{global.sid.value}}"
|
||||
scp-desc="录制的流的Stream地址,即流名称">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.dvr.apply" scd-span="span4"
|
||||
scd-desc="是否开始录制该流。"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="dvr(global.dvr.apply)"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.enabled"
|
||||
scp-desc="是否对Vhost启用DVR配置。默认: {{false| sc_filter_yesno}}"
|
||||
scp-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_plan"
|
||||
scp-desc="录制计划,session按会话,segment分段,append单文件。默认: session"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_path"
|
||||
scp-desc="录制文件的路径模板。默认: ./objs/nginx/html/[app]/[stream].[timestamp].flv"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_duration"
|
||||
scp-desc="单位:秒。录制文件的时长。默认: 30"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_wait_keyframe"
|
||||
scp-desc="是否等待关键帧。默认: {{true| sc_filter_yesno}}"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.time_jitter"
|
||||
scp-desc="录制的时间戳校正算法。full完全,zero置零,off关闭。默认: full"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,62 +0,0 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Vhost({{global.vid.value}}) DVR Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.name" scp-link="#/vhosts/{{global.id.value}}"
|
||||
scp-desc="The vhost name to DVR.">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.app"
|
||||
scp-desc="The app name to DVR.">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream" scp-link="#/streams/{{global.sid.value}}"
|
||||
scp-desc="The stream url to DVR.">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.dvr.apply" scd-span="span4"
|
||||
scd-desc="Whether record this stream."
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="dvr(global.dvr.apply)"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.enabled"
|
||||
scp-desc="Whether enable DVR for vhost. Default is {{false| sc_filter_yesno}}"
|
||||
scp-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_plan"
|
||||
scp-desc="The DVR plan, can be session, segment or append. Default is session."
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_path"
|
||||
scp-desc="The DVR file path template. Default is ./objs/nginx/html/[app]/[stream].[timestamp].flv"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_duration"
|
||||
scp-desc="The DVR file duration in seconds. Default is 30"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_wait_keyframe"
|
||||
scp-desc="Whether wait for keyframe when DVR. Default is {{true| sc_filter_yesno}}"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.time_jitter"
|
||||
scp-desc="The time jitter algorithm for DVR, can be full, zero or off. Default is full."
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
DVR信息请在每个Stream中单独配置, 请前往<a href="javascript:void(0)" ng-click="gogogo('/streams/')">Streams</a>配置。
|
|
@ -1 +0,0 @@
|
|||
Please config DVR in each stream by <a href="javascript:void(0)" ng-click="gogogo('/streams/')">here</a>.
|
|
@ -15,11 +15,17 @@ if [[ ! -f ~/git/srs-bench/go.mod ]]; then
|
|||
fi
|
||||
|
||||
echo "Copy signaling"
|
||||
cp -R 3rdparty/signaling/* ~/git/signaling/ && (cd ~/git/signaling && git st)
|
||||
cp -R 3rdparty/signaling/* ~/git/signaling/ &&
|
||||
cp -R 3rdparty/signaling/.gitignore ~/git/signaling/ &&
|
||||
(cd ~/git/signaling && git st)
|
||||
|
||||
echo "Copy httpx-static"
|
||||
cp -R 3rdparty/httpx-static/* ~/git/go-oryx/httpx-static/ && (cd ~/git/go-oryx && git st)
|
||||
cp -R 3rdparty/httpx-static/* ~/git/go-oryx/httpx-static/ &&
|
||||
cp -R 3rdparty/httpx-static/.gitignore ~/git/go-oryx/httpx-static/ &&
|
||||
(cd ~/git/go-oryx && git st)
|
||||
|
||||
echo "Copy srs-bench"
|
||||
cp -R 3rdparty/srs-bench/* ~/git/srs-bench/ && (cd ~/git/srs-bench && git st)
|
||||
cp -R 3rdparty/srs-bench/* ~/git/srs-bench/ &&
|
||||
cp -R 3rdparty/srs-bench/.gitignore ~/git/srs-bench/ &&
|
||||
(cd ~/git/srs-bench && git st)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -100,7 +100,6 @@ extern bool srs_config_ingest_is_stream(std::string type);
|
|||
extern bool srs_config_dvr_is_plan_segment(std::string plan);
|
||||
extern bool srs_config_dvr_is_plan_session(std::string plan);
|
||||
extern bool srs_stream_caster_is_udp(std::string caster);
|
||||
extern bool srs_stream_caster_is_rtsp(std::string caster);
|
||||
extern bool srs_stream_caster_is_flv(std::string caster);
|
||||
// Whether the dvr_apply active the stream specified by req.
|
||||
extern bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req);
|
||||
|
@ -333,44 +332,8 @@ public:
|
|||
private:
|
||||
virtual srs_error_t do_persistence(SrsFileWriter* fw);
|
||||
public:
|
||||
// Dumps the global sections to json.
|
||||
virtual srs_error_t global_to_json(SrsJsonObject* obj);
|
||||
// Dumps the minimal sections to json.
|
||||
virtual srs_error_t minimal_to_json(SrsJsonObject* obj);
|
||||
// Dumps the vhost section to json.
|
||||
virtual srs_error_t vhost_to_json(SrsConfDirective* vhost, SrsJsonObject* obj);
|
||||
// Dumps the http_api sections to json for raw api info.
|
||||
virtual srs_error_t raw_to_json(SrsJsonObject* obj);
|
||||
// RAW set the global listen.
|
||||
virtual srs_error_t raw_set_listen(const std::vector<std::string>& eps, bool& applied);
|
||||
// RAW set the global pid.
|
||||
virtual srs_error_t raw_set_pid(std::string pid, bool& applied);
|
||||
// RAW set the global chunk size.
|
||||
virtual srs_error_t raw_set_chunk_size(std::string chunk_size, bool& applied);
|
||||
// RAW set the global ffmpeg log dir.
|
||||
virtual srs_error_t raw_set_ff_log_dir(std::string ff_log_dir, bool& applied);
|
||||
// RAW set the global log tank.
|
||||
virtual srs_error_t raw_set_srs_log_tank(std::string srs_log_tank, bool& applied);
|
||||
// RAW set the global log level.
|
||||
virtual srs_error_t raw_set_srs_log_level(std::string srs_log_level, bool& applied);
|
||||
// RAW set the global log file path for file tank.
|
||||
virtual srs_error_t raw_set_srs_log_file(std::string srs_log_file, bool& applied);
|
||||
// RAW set the global max connections of srs.
|
||||
virtual srs_error_t raw_set_max_connections(std::string max_connections, bool& applied);
|
||||
// RAW set the global whether use utc time.
|
||||
virtual srs_error_t raw_set_utc_time(std::string utc_time, bool& applied);
|
||||
// RAW set the global pithy print interval in ms.
|
||||
virtual srs_error_t raw_set_pithy_print_ms(std::string pithy_print_ms, bool& applied);
|
||||
// RAW create the new vhost.
|
||||
virtual srs_error_t raw_create_vhost(std::string vhost, bool& applied);
|
||||
// RAW update the disabled vhost name.
|
||||
virtual srs_error_t raw_update_vhost(std::string vhost, std::string name, bool& applied);
|
||||
// RAW delete the disabled vhost.
|
||||
virtual srs_error_t raw_delete_vhost(std::string vhost, bool& applied);
|
||||
// RAW disable the enabled vhost.
|
||||
virtual srs_error_t raw_disable_vhost(std::string vhost, bool& applied);
|
||||
// RAW enable the disabled vhost.
|
||||
virtual srs_error_t raw_enable_vhost(std::string vhost, bool& applied);
|
||||
private:
|
||||
virtual srs_error_t do_reload_listen();
|
||||
virtual srs_error_t do_reload_pid();
|
||||
|
@ -750,7 +713,6 @@ public:
|
|||
// all clients connected to edge must be tranverse to origin to verify.
|
||||
virtual bool get_vhost_edge_token_traverse(std::string vhost);
|
||||
// Get the transformed vhost for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
virtual std::string get_vhost_edge_transform_vhost(std::string vhost);
|
||||
// Whether enable the origin cluster.
|
||||
// @see https://github.com/ossrs/srs/wiki/v3_EN_OriginCluster
|
||||
|
@ -925,7 +887,6 @@ public:
|
|||
// Get the hls hls_on_error config.
|
||||
// The ignore will ignore error and disable hls.
|
||||
// The disconnect will disconnect publish connection.
|
||||
// @see https://github.com/ossrs/srs/issues/264
|
||||
virtual std::string get_hls_on_error(std::string vhost);
|
||||
// Get the HLS default audio codec.
|
||||
virtual std::string get_hls_acodec(std::string vhost);
|
||||
|
|
|
@ -71,7 +71,6 @@ srs_error_t SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
|
|||
if (true) {
|
||||
SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(req->vhost);
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/79
|
||||
// when origin is error, for instance, server is shutdown,
|
||||
// then user remove the vhost then reload, the conf is empty.
|
||||
if (!conf) {
|
||||
|
@ -98,7 +97,6 @@ srs_error_t SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
|
|||
selected_port = port;
|
||||
|
||||
// support vhost tranform for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req->vhost);
|
||||
vhost = srs_string_replace(vhost, "[vhost]", req->vhost);
|
||||
|
||||
|
@ -724,7 +722,6 @@ srs_error_t SrsEdgeForwarder::start()
|
|||
srs_parse_hostport(server, server, port);
|
||||
|
||||
// support vhost tranform for edge,
|
||||
// @see https://github.com/ossrs/srs/issues/372
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req->vhost);
|
||||
vhost = srs_string_replace(vhost, "[vhost]", req->vhost);
|
||||
|
||||
|
@ -1005,7 +1002,6 @@ srs_error_t SrsPublishEdge::on_client_publish()
|
|||
return srs_error_new(ERROR_RTMP_EDGE_PUBLISH_STATE, "invalid state");
|
||||
}
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/180
|
||||
// to avoid multiple publish the same stream on the same edge,
|
||||
// directly enter the publish stage.
|
||||
if (true) {
|
||||
|
@ -1017,7 +1013,6 @@ srs_error_t SrsPublishEdge::on_client_publish()
|
|||
// start to forward stream to origin.
|
||||
err = forwarder->start();
|
||||
|
||||
// @see https://github.com/ossrs/srs/issues/180
|
||||
// when failed, revert to init
|
||||
if (err != srs_success) {
|
||||
SrsEdgeState pstate = state;
|
||||
|
|
|
@ -40,7 +40,6 @@ private:
|
|||
SrsRtmpJitter* jitter;
|
||||
SrsMessageQueue* queue;
|
||||
// Cache the sequence header for retry when slave is failed.
|
||||
// @see https://github.com/ossrs/srs/issues/150
|
||||
SrsSharedPtrMessage* sh_audio;
|
||||
SrsSharedPtrMessage* sh_video;
|
||||
public:
|
||||
|
|
|
@ -153,7 +153,6 @@ private:
|
|||
// The current writing segment.
|
||||
SrsHlsSegment* current;
|
||||
// The ts context, to keep cc continous between ts.
|
||||
// @see https://github.com/ossrs/srs/issues/375
|
||||
SrsTsContext* context;
|
||||
public:
|
||||
SrsHlsMuxer();
|
||||
|
@ -187,7 +186,6 @@ public:
|
|||
virtual bool wait_keyframe();
|
||||
// Whether segment absolutely overflow, for pure audio to reap segment,
|
||||
// that is whether the current segment duration>=2*(the segment in config)
|
||||
// @see https://github.com/ossrs/srs/issues/151#issuecomment-71155184
|
||||
virtual bool is_segment_absolutely_overflow();
|
||||
public:
|
||||
// Whether current hls muxer is pure audio mode.
|
||||
|
|
|
@ -902,7 +902,7 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// the rpc is required.
|
||||
// the allowd rpc method check.
|
||||
if (rpc.empty() || (rpc != "reload" && rpc != "query" && rpc != "raw" && rpc != "update")) {
|
||||
if (rpc.empty() || rpc != "reload") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW);
|
||||
}
|
||||
|
||||
|
@ -916,312 +916,6 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
|
|||
return srs_api_response_code(w, r, ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// for rpc=query, to get the configs of server.
|
||||
// @param scope the scope to query for config, it can be:
|
||||
// global, the configs belongs to the root, donot includes any sub directives.
|
||||
// minimal, the minimal summary of server, for preview stream to got the port serving.
|
||||
// vhost, the configs for specified vhost by @param vhost.
|
||||
// @param vhost the vhost name for @param scope is vhost to query config.
|
||||
// for the default vhost, must be __defaultVhost__
|
||||
if (rpc == "query") {
|
||||
if (!allow_query) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_DISABLED);
|
||||
}
|
||||
|
||||
std::string scope = r->query_get("scope");
|
||||
std::string vhost = r->query_get("vhost");
|
||||
if (scope.empty() || (scope != "global" && scope != "vhost" && scope != "minimal")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
if (scope == "vhost") {
|
||||
// query vhost scope.
|
||||
if (vhost.empty()) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
SrsConfDirective* root = _srs_config->get_root();
|
||||
SrsConfDirective* conf = root->get("vhost", vhost);
|
||||
if (!conf) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("vhost", data);
|
||||
if ((err = _srs_config->vhost_to_json(conf, data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "minimal") {
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("minimal", data);
|
||||
|
||||
// query minimal scope.
|
||||
if ((err = _srs_config->minimal_to_json(data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else {
|
||||
SrsJsonObject* data = SrsJsonAny::object();
|
||||
obj->set("global", data);
|
||||
|
||||
// query global scope.
|
||||
if ((err = _srs_config->global_to_json(data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
}
|
||||
|
||||
return srs_api_response(w, r, obj->dumps());
|
||||
}
|
||||
|
||||
// for rpc=update, to update the configs of server.
|
||||
// @scope the scope to update for config.
|
||||
// @value the updated value for scope.
|
||||
// @param the extra param for scope.
|
||||
// @data the extra data for scope.
|
||||
// possible updates:
|
||||
// @scope @value value-description
|
||||
// listen 1935,1936 the port list.
|
||||
// pid ./objs/srs.pid the pid file of srs.
|
||||
// chunk_size 60000 the global RTMP chunk_size.
|
||||
// ff_log_dir ./objs the dir for ffmpeg log.
|
||||
// srs_log_tank file the tank to log, file or console.
|
||||
// srs_log_level trace the level of log, verbose, info, trace, warn, error.
|
||||
// srs_log_file ./objs/srs.log the log file when tank is file.
|
||||
// max_connections 1000 the max connections of srs.
|
||||
// utc_time false whether enable utc time.
|
||||
// pithy_print_ms 10000 the pithy print interval in ms.
|
||||
// vhost specified updates:
|
||||
// @scope @value @param @data description
|
||||
// vhost ossrs.net create - create vhost ossrs.net
|
||||
// vhost ossrs.net update new.ossrs.net the new name to update vhost
|
||||
// dvr specified updates:
|
||||
// @scope @value @param @data description
|
||||
// dvr ossrs.net enable live/livestream enable the dvr of stream
|
||||
// dvr ossrs.net disable live/livestream disable the dvr of stream
|
||||
if (rpc == "update") {
|
||||
if (!allow_update) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_DISABLED);
|
||||
}
|
||||
|
||||
std::string scope = r->query_get("scope");
|
||||
std::string value = r->query_get("value");
|
||||
if (scope.empty()) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
if (scope != "listen" && scope != "pid" && scope != "chunk_size"
|
||||
&& scope != "ff_log_dir" && scope != "srs_log_tank" && scope != "srs_log_level"
|
||||
&& scope != "srs_log_file" && scope != "max_connections" && scope != "utc_time"
|
||||
&& scope != "pithy_print_ms" && scope != "vhost" && scope != "dvr"
|
||||
) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
bool applied = false;
|
||||
string extra = "";
|
||||
if (scope == "listen") {
|
||||
vector<string> eps = srs_string_split(value, ",");
|
||||
|
||||
bool invalid = eps.empty();
|
||||
for (int i = 0; i < (int)eps.size(); i++) {
|
||||
string ep = eps.at(i);
|
||||
int port = ::atoi(ep.c_str());
|
||||
if (port <= 2 || port >= 65535) {
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_listen(eps, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "pid") {
|
||||
if (value.empty() || !srs_string_starts_with(value, "./", "/tmp/", "/var/") || !srs_string_ends_with(value, ".pid")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_pid(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "chunk_size") {
|
||||
int csv = ::atoi(value.c_str());
|
||||
if (csv < 128 || csv > 65535 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_chunk_size(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "ff_log_dir") {
|
||||
if (value.empty() || (value != "/dev/null" && !srs_string_starts_with(value, "./", "/tmp/", "/var/"))) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_ff_log_dir(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_tank") {
|
||||
if (value.empty() || (value != "file" && value != "console")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_tank(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_level") {
|
||||
if (value != "verbose" && value != "info" && value != "trace" && value != "warn" && value != "error") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_level(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "srs_log_file") {
|
||||
if (value.empty() || !srs_string_starts_with(value, "./", "/tmp/", "/var/") || !srs_string_ends_with(value, ".log")) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_srs_log_file(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "max_connections") {
|
||||
int mcv = ::atoi(value.c_str());
|
||||
if (mcv < 10 || mcv > 65535 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_max_connections(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "utc_time") {
|
||||
if (!srs_is_boolean(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_utc_time(srs_config_bool2switch(value), applied)) != srs_success) {
|
||||
return srs_api_response_code(w, r, srs_error_wrap(err, "raw api update utc_time=%s", value.c_str()));
|
||||
}
|
||||
} else if (scope == "pithy_print_ms") {
|
||||
int ppmv = ::atoi(value.c_str());
|
||||
if (ppmv < 100 || ppmv > 300000 || !srs_is_digit_number(value)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_set_pithy_print_ms(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (scope == "vhost") {
|
||||
std::string param = r->query_get("param");
|
||||
std::string data = r->query_get("data");
|
||||
if (param != "create" && param != "update" && param != "delete" && param != "disable" && param != "enable") {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_NOT_ALLOWED);
|
||||
}
|
||||
extra += " " + param;
|
||||
|
||||
if (param == "create") {
|
||||
// when create, the vhost must not exists.
|
||||
if (param.empty() || _srs_config->get_vhost(value, false)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_create_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "update") {
|
||||
extra += " to " + data;
|
||||
|
||||
// when update, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (data.empty() || data == value || param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_update_vhost(value, data, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "delete") {
|
||||
// when delete, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_delete_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "disable") {
|
||||
// when disable, the vhost must exists and enabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || !_srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_disable_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else if (param == "enable") {
|
||||
// when enable, the vhost must exists and disabled.
|
||||
SrsConfDirective* vhost = _srs_config->get_vhost(value, false);
|
||||
if (param.empty() || !vhost || _srs_config->get_vhost_enabled(vhost)) {
|
||||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_PARAMS);
|
||||
}
|
||||
|
||||
if ((err = _srs_config->raw_enable_vhost(value, applied)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_error_reset(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
}
|
||||
} else {
|
||||
// TODO: support other param.
|
||||
}
|
||||
} else {
|
||||
// TODO: support other scope.
|
||||
}
|
||||
|
||||
// whether the config applied.
|
||||
if (applied) {
|
||||
server->on_signal(SRS_SIGNAL_PERSISTENCE_CONFIG);
|
||||
srs_trace("raw api update %s=%s%s ok.", scope.c_str(), value.c_str(), extra.c_str());
|
||||
} else {
|
||||
srs_warn("raw api update not applied %s=%s%s.", scope.c_str(), value.c_str(), extra.c_str());
|
||||
}
|
||||
|
||||
return srs_api_response(w, r, obj->dumps());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -509,7 +509,6 @@ srs_error_t SrsHttpHooks::do_post(SrsHttpClient* hc, std::string url, std::strin
|
|||
}
|
||||
|
||||
// ensure the http status is ok.
|
||||
// https://github.com/ossrs/srs/issues/158
|
||||
if (code != SRS_CONSTS_HTTP_OK && code != SRS_CONSTS_HTTP_Created) {
|
||||
return srs_error_new(ERROR_HTTP_STATUS_INVALID, "http: status %d", code);
|
||||
}
|
||||
|
|
|
@ -928,7 +928,6 @@ srs_error_t SrsHttpStreamServer::http_mount(SrsLiveSource* s, SrsRequest* r)
|
|||
// mount the http flv stream.
|
||||
// we must register the handler, then start the thread,
|
||||
// for the thread will cause thread switch context.
|
||||
// @see https://github.com/ossrs/srs/issues/404
|
||||
if ((err = mux.handle(mount, entry->stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: mount flv stream for vhost=%s failed", sid.c_str());
|
||||
}
|
||||
|
|
|
@ -449,7 +449,6 @@ srs_error_t SrsMpegtsOverUdp::write_h264_ipb_frame(char* frame, int frame_size,
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// when sps or pps not sent, ignore the packet.
|
||||
// @see https://github.com/ossrs/srs/issues/203
|
||||
if (!h264_sps_pps_sent) {
|
||||
return srs_error_new(ERROR_H264_DROP_BEFORE_SPS_PPS, "drop sps/pps");
|
||||
}
|
||||
|
|
|
@ -93,8 +93,6 @@ srs_error_t SrsRecvThread::cycle()
|
|||
// the multiple messages writev improve performance large,
|
||||
// but the timeout recv will cause 33% sys call performance,
|
||||
// to use isolate thread to recv, can improve about 33% performance.
|
||||
// @see https://github.com/ossrs/srs/issues/194
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
rtmp->set_recv_timeout(SRS_UTIME_NO_TIMEOUT);
|
||||
|
||||
pumper->on_start();
|
||||
|
@ -279,7 +277,6 @@ SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest*
|
|||
mr_fd = mr_sock_fd;
|
||||
|
||||
// the mr settings,
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
mr = _srs_config->get_mr_enabled(req->vhost);
|
||||
mr_sleep = _srs_config->get_mr_sleep(req->vhost);
|
||||
|
||||
|
@ -405,7 +402,6 @@ void SrsPublishRecvThread::interrupt(srs_error_t err)
|
|||
recv_error = srs_error_copy(err);
|
||||
|
||||
// when recv thread error, signal the conn thread to process it.
|
||||
// @see https://github.com/ossrs/srs/issues/244
|
||||
srs_cond_signal(error);
|
||||
}
|
||||
|
||||
|
@ -420,7 +416,6 @@ void SrsPublishRecvThread::on_start()
|
|||
set_socket_buffer(mr_sleep);
|
||||
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(true, this);
|
||||
}
|
||||
#endif
|
||||
|
@ -432,13 +427,11 @@ void SrsPublishRecvThread::on_stop()
|
|||
// for we donot set to false yet.
|
||||
|
||||
// when thread stop, signal the conn thread which wait.
|
||||
// @see https://github.com/ossrs/srs/issues/244
|
||||
srs_cond_signal(error);
|
||||
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
if (mr) {
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(false, NULL);
|
||||
}
|
||||
#endif
|
||||
|
@ -459,7 +452,6 @@ void SrsPublishRecvThread::on_read(ssize_t nread)
|
|||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
if (nread < SRS_MR_SMALL_BYTES) {
|
||||
srs_usleep(mr_sleep);
|
||||
|
@ -476,7 +468,6 @@ srs_error_t SrsPublishRecvThread::on_reload_vhost_publish(string vhost)
|
|||
}
|
||||
|
||||
// the mr settings,
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
bool mr_enabled = _srs_config->get_mr_enabled(req->vhost);
|
||||
srs_utime_t sleep_v = _srs_config->get_mr_sleep(req->vhost);
|
||||
|
||||
|
@ -489,13 +480,11 @@ srs_error_t SrsPublishRecvThread::on_reload_vhost_publish(string vhost)
|
|||
// mr enabled=>disabled
|
||||
if (mr && !mr_enabled) {
|
||||
// disable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(false, NULL);
|
||||
}
|
||||
// mr disabled=>enabled
|
||||
if (!mr && mr_enabled) {
|
||||
// enable the merge read
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
rtmp->set_merge_read(true, this);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -75,7 +75,6 @@ private:
|
|||
// when source id changed, notice all consumers
|
||||
bool should_update_source_id;
|
||||
// The cond wait for mw.
|
||||
// @see https://github.com/ossrs/srs/issues/251
|
||||
srs_cond_t mw_wait;
|
||||
bool mw_waiting;
|
||||
int mw_min_msgs;
|
||||
|
|
|
@ -429,7 +429,6 @@ srs_error_t SrsRtmpConn::service_cycle()
|
|||
// logical accept and retry stream service.
|
||||
if (srs_error_code(err) == ERROR_CONTROL_RTMP_CLOSE) {
|
||||
// TODO: FIXME: use ping message to anti-death of socket.
|
||||
// @see: https://github.com/ossrs/srs/issues/39
|
||||
// set timeout to a larger value, for user paused.
|
||||
rtmp->set_recv_timeout(SRS_PAUSED_RECV_TIMEOUT);
|
||||
rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT);
|
||||
|
@ -670,7 +669,6 @@ srs_error_t SrsRtmpConn::playing(SrsLiveSource* source)
|
|||
}
|
||||
|
||||
// Use receiving thread to receive packets from peer.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
SrsQueueRecvThread trd(consumer, rtmp, SRS_PERF_MW_SLEEP, _srs_context->get_id());
|
||||
|
||||
if ((err = trd.start()) != srs_success) {
|
||||
|
@ -731,8 +729,6 @@ srs_error_t SrsRtmpConn::do_playing(SrsLiveSource* source, SrsLiveConsumer* cons
|
|||
pprint->elapse();
|
||||
|
||||
// to use isolate thread to recv, can improve about 33% performance.
|
||||
// @see: https://github.com/ossrs/srs/issues/196
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
while (!rtrd->empty()) {
|
||||
SrsCommonMessage* msg = rtrd->pump();
|
||||
if ((err = process_play_control_msg(consumer, msg)) != srs_success) {
|
||||
|
@ -1114,7 +1110,6 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer* consumer, Srs
|
|||
SrsAutoFree(SrsPacket, pkt);
|
||||
|
||||
// for jwplayer/flowplayer, which send close as pause message.
|
||||
// @see https://github.com/ossrs/srs/issues/6
|
||||
SrsCloseStreamPacket* close = dynamic_cast<SrsCloseStreamPacket*>(pkt);
|
||||
if (close) {
|
||||
return srs_error_new(ERROR_CONTROL_RTMP_CLOSE, "rtmp: close stream");
|
||||
|
@ -1122,7 +1117,6 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer* consumer, Srs
|
|||
|
||||
// call msg,
|
||||
// support response null first,
|
||||
// @see https://github.com/ossrs/srs/issues/106
|
||||
// TODO: FIXME: response in right way, or forward in edge mode.
|
||||
SrsCallPacket* call = dynamic_cast<SrsCallPacket*>(pkt);
|
||||
if (call) {
|
||||
|
|
|
@ -82,7 +82,6 @@ private:
|
|||
ISrsWakable* wakable;
|
||||
// The elapsed duration in srs_utime_t
|
||||
// For live play duration, for instance, rtmpdump to record.
|
||||
// @see https://github.com/ossrs/srs/issues/47
|
||||
srs_utime_t duration;
|
||||
// The MR(merged-write) sleep time in srs_utime_t.
|
||||
srs_utime_t mw_sleep;
|
||||
|
|
|
@ -1,785 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2013-2021 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#include <srs_app_rtsp.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_rtsp_stack.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_protocol_amf0.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_raw_avc.hpp>
|
||||
#include <srs_kernel_codec.hpp>
|
||||
#include <srs_app_pithy_print.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_protocol_format.hpp>
|
||||
|
||||
SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p, int sid)
|
||||
{
|
||||
rtsp = r;
|
||||
_port = p;
|
||||
stream_id = sid;
|
||||
// TODO: support listen at <[ip:]port>
|
||||
listener = new SrsUdpListener(this, srs_any_address_for_listener(), p);
|
||||
cache = new SrsRtspPacket();
|
||||
pprint = SrsPithyPrint::create_caster();
|
||||
}
|
||||
|
||||
SrsRtpConn::~SrsRtpConn()
|
||||
{
|
||||
srs_freep(listener);
|
||||
srs_freep(cache);
|
||||
srs_freep(pprint);
|
||||
}
|
||||
|
||||
int SrsRtpConn::port()
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpConn::listen()
|
||||
{
|
||||
return listener->listen();
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpConn::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
pprint->elapse();
|
||||
|
||||
if (true) {
|
||||
SrsBuffer stream(buf, nb_buf);
|
||||
|
||||
SrsRtspPacket pkt;
|
||||
if ((err = pkt.decode(&stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "decode");
|
||||
}
|
||||
|
||||
if (pkt.chunked) {
|
||||
if (!cache) {
|
||||
cache = new SrsRtspPacket();
|
||||
}
|
||||
cache->copy(&pkt);
|
||||
cache->payload->append(pkt.payload->bytes(), pkt.payload->length());
|
||||
if (pprint->can_print()) {
|
||||
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp chunked %dB, age=%d, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB",
|
||||
nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
||||
cache->payload->length()
|
||||
);
|
||||
}
|
||||
|
||||
if (!cache->completed){
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
srs_freep(cache);
|
||||
cache = new SrsRtspPacket();
|
||||
cache->reap(&pkt);
|
||||
}
|
||||
}
|
||||
|
||||
if (pprint->can_print()) {
|
||||
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp #%d %dB, age=%d, vt=%d/%u, sts=%u/%u/%#x, paylod=%dB, chunked=%d",
|
||||
stream_id, nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
||||
cache->payload->length(), cache->chunked
|
||||
);
|
||||
}
|
||||
|
||||
// always free it.
|
||||
SrsAutoFree(SrsRtspPacket, cache);
|
||||
|
||||
err = rtsp->on_rtp_packet(cache, stream_id);
|
||||
if (err != srs_success) {
|
||||
srs_warn("ignore RTP packet err %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsRtspAudioCache::SrsRtspAudioCache()
|
||||
{
|
||||
dts = 0;
|
||||
audio = NULL;
|
||||
payload = NULL;
|
||||
}
|
||||
|
||||
SrsRtspAudioCache::~SrsRtspAudioCache()
|
||||
{
|
||||
srs_freep(audio);
|
||||
srs_freep(payload);
|
||||
}
|
||||
|
||||
SrsRtspJitter::SrsRtspJitter()
|
||||
{
|
||||
delta = 0;
|
||||
previous_timestamp = 0;
|
||||
pts = 0;
|
||||
}
|
||||
|
||||
SrsRtspJitter::~SrsRtspJitter()
|
||||
{
|
||||
}
|
||||
|
||||
int64_t SrsRtspJitter::timestamp()
|
||||
{
|
||||
return pts;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspJitter::correct(int64_t& ts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (previous_timestamp == 0) {
|
||||
previous_timestamp = ts;
|
||||
}
|
||||
|
||||
delta = srs_max(0, (int)(ts - previous_timestamp));
|
||||
if (delta > 90000) {
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
previous_timestamp = ts;
|
||||
|
||||
ts = pts + delta;
|
||||
pts = ts;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, srs_netfd_t fd, std::string o)
|
||||
{
|
||||
output_template = o;
|
||||
|
||||
session = "";
|
||||
video_rtp = NULL;
|
||||
audio_rtp = NULL;
|
||||
|
||||
caster = c;
|
||||
stfd = fd;
|
||||
skt = new SrsStSocket();
|
||||
rtsp = new SrsRtspStack(skt);
|
||||
trd = new SrsSTCoroutine("rtsp", this);
|
||||
|
||||
audio_id = 0;
|
||||
video_id = 0;
|
||||
audio_sample_rate = 0;
|
||||
audio_channel = 0;
|
||||
|
||||
req = NULL;
|
||||
sdk = NULL;
|
||||
vjitter = new SrsRtspJitter();
|
||||
ajitter = new SrsRtspJitter();
|
||||
|
||||
avc = new SrsRawH264Stream();
|
||||
aac = new SrsRawAacStream();
|
||||
acodec = new SrsRawAacStreamCodec();
|
||||
acache = new SrsRtspAudioCache();
|
||||
}
|
||||
|
||||
SrsRtspConn::~SrsRtspConn()
|
||||
{
|
||||
close();
|
||||
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
srs_freep(video_rtp);
|
||||
srs_freep(audio_rtp);
|
||||
|
||||
srs_freep(trd);
|
||||
srs_freep(skt);
|
||||
srs_freep(rtsp);
|
||||
|
||||
srs_freep(sdk);
|
||||
srs_freep(req);
|
||||
|
||||
srs_freep(vjitter);
|
||||
srs_freep(ajitter);
|
||||
|
||||
srs_freep(avc);
|
||||
srs_freep(aac);
|
||||
srs_freep(acodec);
|
||||
srs_freep(acache);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::serve()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = skt->initialize(stfd)) != srs_success) {
|
||||
return srs_error_wrap(err, "socket initialize");
|
||||
}
|
||||
|
||||
if ((err = trd->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp connection");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string SrsRtspConn::remote_ip()
|
||||
{
|
||||
// TODO: FIXME: Implement it.
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string SrsRtspConn::desc()
|
||||
{
|
||||
return "RtspConn";
|
||||
}
|
||||
|
||||
const SrsContextId& SrsRtspConn::get_id()
|
||||
{
|
||||
return _srs_context->get_id();
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::do_cycle()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// retrieve ip of client.
|
||||
int fd = srs_netfd_fileno(stfd);
|
||||
std::string ip = srs_get_peer_ip(fd);
|
||||
int port = srs_get_peer_port(fd);
|
||||
|
||||
if (ip.empty() && !_srs_config->empty_ip_ok()) {
|
||||
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
|
||||
}
|
||||
srs_trace("rtsp: serve %s:%d", ip.c_str(), port);
|
||||
|
||||
// consume all rtsp messages.
|
||||
while (true) {
|
||||
if ((err = trd->pull()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp cycle");
|
||||
}
|
||||
|
||||
SrsRtspRequest* req = NULL;
|
||||
if ((err = rtsp->recv_message(&req)) != srs_success) {
|
||||
return srs_error_wrap(err, "recv message");
|
||||
}
|
||||
SrsAutoFree(SrsRtspRequest, req);
|
||||
srs_info("rtsp: got rtsp request");
|
||||
|
||||
if (req->is_options()) {
|
||||
SrsRtspOptionsResponse* res = new SrsRtspOptionsResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response option");
|
||||
}
|
||||
} else if (req->is_announce()) {
|
||||
if (rtsp_tcUrl.empty()) {
|
||||
rtsp_tcUrl = req->uri;
|
||||
}
|
||||
size_t pos = string::npos;
|
||||
if ((pos = rtsp_tcUrl.rfind(".sdp")) != string::npos) {
|
||||
rtsp_tcUrl = rtsp_tcUrl.substr(0, pos);
|
||||
}
|
||||
srs_parse_rtmp_url(rtsp_tcUrl, rtsp_tcUrl, rtsp_stream);
|
||||
|
||||
srs_assert(req->sdp);
|
||||
video_id = ::atoi(req->sdp->video_stream_id.c_str());
|
||||
audio_id = ::atoi(req->sdp->audio_stream_id.c_str());
|
||||
video_codec = req->sdp->video_codec;
|
||||
audio_codec = req->sdp->audio_codec;
|
||||
audio_sample_rate = ::atoi(req->sdp->audio_sample_rate.c_str());
|
||||
audio_channel = ::atoi(req->sdp->audio_channel.c_str());
|
||||
h264_sps = req->sdp->video_sps;
|
||||
h264_pps = req->sdp->video_pps;
|
||||
aac_specific_config = req->sdp->audio_sh;
|
||||
srs_trace("rtsp: video(#%d, %s, %s/%s), audio(#%d, %s, %s/%s, %dHZ %dchannels), %s/%s",
|
||||
video_id, video_codec.c_str(), req->sdp->video_protocol.c_str(), req->sdp->video_transport_format.c_str(),
|
||||
audio_id, audio_codec.c_str(), req->sdp->audio_protocol.c_str(), req->sdp->audio_transport_format.c_str(),
|
||||
audio_sample_rate, audio_channel, rtsp_tcUrl.c_str(), rtsp_stream.c_str()
|
||||
);
|
||||
|
||||
SrsRtspResponse* res = new SrsRtspResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response announce");
|
||||
}
|
||||
} else if (req->is_setup()) {
|
||||
srs_assert(req->transport);
|
||||
int lpm = 0;
|
||||
if ((err = caster->alloc_port(&lpm)) != srs_success) {
|
||||
return srs_error_wrap(err, "alloc port");
|
||||
}
|
||||
|
||||
SrsRtpConn* rtp = NULL;
|
||||
if (req->stream_id == video_id) {
|
||||
srs_freep(video_rtp);
|
||||
rtp = video_rtp = new SrsRtpConn(this, lpm, video_id);
|
||||
} else {
|
||||
srs_freep(audio_rtp);
|
||||
rtp = audio_rtp = new SrsRtpConn(this, lpm, audio_id);
|
||||
}
|
||||
if ((err = rtp->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtp listen");
|
||||
}
|
||||
srs_trace("rtsp: #%d %s over %s/%s/%s %s client-port=%d-%d, server-port=%d-%d",
|
||||
req->stream_id, (req->stream_id == video_id)? "Video":"Audio",
|
||||
req->transport->transport.c_str(), req->transport->profile.c_str(), req->transport->lower_transport.c_str(),
|
||||
req->transport->cast_type.c_str(), req->transport->client_port_min, req->transport->client_port_max,
|
||||
lpm, lpm + 1);
|
||||
|
||||
// create session.
|
||||
if (session.empty()) {
|
||||
session = "O9EaZ4bf"; // TODO: FIXME: generate session id.
|
||||
}
|
||||
|
||||
SrsRtspSetupResponse* res = new SrsRtspSetupResponse((int)req->seq);
|
||||
res->client_port_min = req->transport->client_port_min;
|
||||
res->client_port_max = req->transport->client_port_max;
|
||||
res->local_port_min = lpm;
|
||||
res->local_port_max = lpm + 1;
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response setup");
|
||||
}
|
||||
} else if (req->is_record()) {
|
||||
SrsRtspResponse* res = new SrsRtspResponse((int)req->seq);
|
||||
res->session = session;
|
||||
if ((err = rtsp->send_message(res)) != srs_success) {
|
||||
return srs_error_wrap(err, "response record");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_packet(SrsRtspPacket* pkt, int stream_id)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// ensure rtmp connected.
|
||||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
|
||||
if (stream_id == video_id) {
|
||||
// rtsp tbn is ts tbn.
|
||||
int64_t pts = pkt->timestamp;
|
||||
if ((err = vjitter->correct(pts)) != srs_success) {
|
||||
return srs_error_wrap(err, "jitter");
|
||||
}
|
||||
|
||||
// TODO: FIXME: set dts to pts, please finger out the right dts.
|
||||
int64_t dts = pts;
|
||||
|
||||
return on_rtp_video(pkt, dts, pts);
|
||||
} else {
|
||||
// rtsp tbn is ts tbn.
|
||||
int64_t pts = pkt->timestamp;
|
||||
if ((err = ajitter->correct(pts)) != srs_success) {
|
||||
return srs_error_wrap(err, "jitter");
|
||||
}
|
||||
|
||||
return on_rtp_audio(pkt, pts);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::cycle()
|
||||
{
|
||||
// serve the rtsp client.
|
||||
srs_error_t err = do_cycle();
|
||||
|
||||
caster->remove(this);
|
||||
|
||||
if (err == srs_success) {
|
||||
srs_trace("client finished.");
|
||||
} else if (srs_is_client_gracefully_close(err)) {
|
||||
srs_warn("client disconnect peer. code=%d", srs_error_code(err));
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
if (video_rtp) {
|
||||
caster->free_port(video_rtp->port(), video_rtp->port() + 1);
|
||||
}
|
||||
|
||||
if (audio_rtp) {
|
||||
caster->free_port(audio_rtp->port(), audio_rtp->port() + 1);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_video(SrsRtspPacket* pkt, int64_t dts, int64_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = kickoff_audio_cache(pkt, dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "kickoff audio cache");
|
||||
}
|
||||
|
||||
char* bytes = pkt->payload->bytes();
|
||||
int length = pkt->payload->length();
|
||||
uint32_t fdts = (uint32_t)(dts / 90);
|
||||
uint32_t fpts = (uint32_t)(pts / 90);
|
||||
if ((err = write_h264_ipb_frame(bytes, length, fdts, fpts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write ibp frame");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::on_rtp_audio(SrsRtspPacket* pkt, int64_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = kickoff_audio_cache(pkt, dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "kickoff audio cache");
|
||||
}
|
||||
|
||||
// cache current audio to kickoff.
|
||||
acache->dts = dts;
|
||||
acache->audio = pkt->audio;
|
||||
acache->payload = pkt->payload;
|
||||
|
||||
pkt->audio = NULL;
|
||||
pkt->payload = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::kickoff_audio_cache(SrsRtspPacket* pkt, int64_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// nothing to kick off.
|
||||
if (!acache->payload) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (dts - acache->dts > 0 && acache->audio->nb_samples > 0) {
|
||||
int64_t delta = (dts - acache->dts) / acache->audio->nb_samples;
|
||||
for (int i = 0; i < acache->audio->nb_samples; i++) {
|
||||
char* frame = acache->audio->samples[i].bytes;
|
||||
int nb_frame = acache->audio->samples[i].size;
|
||||
int64_t timestamp = (acache->dts + delta * i) / 90;
|
||||
acodec->aac_packet_type = 1;
|
||||
if ((err = write_audio_raw_frame(frame, nb_frame, acodec, (uint32_t)timestamp)) != srs_success) {
|
||||
return srs_error_wrap(err, "write audio raw frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acache->dts = 0;
|
||||
srs_freep(acache->audio);
|
||||
srs_freep(acache->payload);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_sequence_header()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// use the current dts.
|
||||
int64_t dts = vjitter->timestamp() / 90;
|
||||
|
||||
// send video sps/pps
|
||||
if ((err = write_h264_sps_pps((uint32_t)dts, (uint32_t)dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write sps/pps");
|
||||
}
|
||||
|
||||
// generate audio sh by audio specific config.
|
||||
if (aac_specific_config.empty()) {
|
||||
srs_warn("no audio asc");
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string sh = aac_specific_config;
|
||||
|
||||
SrsFormat* format = new SrsFormat();
|
||||
SrsAutoFree(SrsFormat, format);
|
||||
|
||||
if ((err = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != srs_success) {
|
||||
return srs_error_wrap(err, "on aac sequence header");
|
||||
}
|
||||
|
||||
SrsAudioCodecConfig* dec = format->acodec;
|
||||
|
||||
acodec->sound_format = SrsAudioCodecIdAAC;
|
||||
acodec->sound_type = (dec->aac_channels == 2)? SrsAudioChannelsStereo : SrsAudioChannelsMono;
|
||||
acodec->sound_size = SrsAudioSampleBits16bit;
|
||||
acodec->aac_packet_type = 0;
|
||||
|
||||
static int srs_aac_srates[] = {
|
||||
96000, 88200, 64000, 48000,
|
||||
44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000,
|
||||
7350, 0, 0, 0
|
||||
};
|
||||
switch (srs_aac_srates[dec->aac_sample_rate]) {
|
||||
case 11025:
|
||||
acodec->sound_rate = SrsAudioSampleRate11025;
|
||||
break;
|
||||
case 22050:
|
||||
acodec->sound_rate = SrsAudioSampleRate22050;
|
||||
break;
|
||||
case 44100:
|
||||
acodec->sound_rate = SrsAudioSampleRate44100;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if ((err = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), acodec, (uint32_t)dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "write audio raw frame");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_h264_sps_pps(uint32_t dts, uint32_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (h264_sps.empty() || h264_pps.empty()) {
|
||||
srs_warn("no sps=%dB or pps=%dB", (int)h264_sps.size(), (int)h264_pps.size());
|
||||
return err;
|
||||
}
|
||||
|
||||
// h264 raw to h264 packet.
|
||||
std::string sh;
|
||||
if ((err = avc->mux_sequence_header(h264_sps, h264_pps, dts, pts, sh)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux sequence header");
|
||||
}
|
||||
|
||||
// h264 packet to flv packet.
|
||||
int8_t frame_type = SrsVideoAvcFrameTypeKeyFrame;
|
||||
int8_t avc_packet_type = SrsVideoAvcFrameTraitSequenceHeader;
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(sh, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux avc to flv");
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
if ((err = rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "write packet");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// ISO_IEC_14496-10-AVC-2003.pdf, page 44.
|
||||
// 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
|
||||
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(frame[0] & 0x1f);
|
||||
|
||||
// for IDR frame, the frame is keyframe.
|
||||
SrsVideoAvcFrameType frame_type = SrsVideoAvcFrameTypeInterFrame;
|
||||
if (nal_unit_type == SrsAvcNaluTypeIDR) {
|
||||
frame_type = SrsVideoAvcFrameTypeKeyFrame;
|
||||
}
|
||||
|
||||
std::string ibp;
|
||||
if ((err = avc->mux_ipb_frame(frame, frame_size, ibp)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux ibp frame");
|
||||
}
|
||||
|
||||
int8_t avc_packet_type = SrsVideoAvcFrameTraitNALU;
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(ibp, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux avc to flv");
|
||||
}
|
||||
|
||||
// the timestamp in rtmp message header is dts.
|
||||
uint32_t timestamp = dts;
|
||||
return rtmp_write_packet(SrsFrameTypeVideo, timestamp, flv, nb_flv);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
char* data = NULL;
|
||||
int size = 0;
|
||||
if ((err = aac->mux_aac2flv(frame, frame_size, codec, dts, &data, &size)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux aac to flv");
|
||||
}
|
||||
|
||||
return rtmp_write_packet(SrsFrameTypeAudio, dts, data, size);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::rtmp_write_packet(char type, uint32_t timestamp, char* data, int size)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect");
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage* msg = NULL;
|
||||
|
||||
if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != srs_success) {
|
||||
return srs_error_wrap(err, "create message");
|
||||
}
|
||||
srs_assert(msg);
|
||||
|
||||
// send out encoded msg.
|
||||
if ((err = sdk->send_and_free_message(msg)) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "write message");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConn::connect()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Ignore when connected.
|
||||
if (sdk) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// generate rtmp url to connect to.
|
||||
std::string url;
|
||||
if (!req) {
|
||||
std::string schema, host, vhost, app, param;
|
||||
int port;
|
||||
srs_discovery_tc_url(rtsp_tcUrl, schema, host, vhost, app, rtsp_stream, port, param);
|
||||
|
||||
// generate output by template.
|
||||
std::string output = output_template;
|
||||
output = srs_string_replace(output, "[app]", app);
|
||||
output = srs_string_replace(output, "[stream]", rtsp_stream);
|
||||
url = output;
|
||||
}
|
||||
|
||||
// connect host.
|
||||
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk = new SrsSimpleRtmpClient(url, cto, sto);
|
||||
|
||||
if ((err = sdk->connect()) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "connect %s failed, cto=%dms, sto=%dms.", url.c_str(), srsu2msi(cto), srsu2msi(sto));
|
||||
}
|
||||
|
||||
// publish.
|
||||
if ((err = sdk->publish(SRS_CONSTS_RTMP_PROTOCOL_CHUNK_SIZE)) != srs_success) {
|
||||
close();
|
||||
return srs_error_wrap(err, "publish %s failed", url.c_str());
|
||||
}
|
||||
|
||||
return write_sequence_header();
|
||||
}
|
||||
|
||||
void SrsRtspConn::close()
|
||||
{
|
||||
srs_freep(sdk);
|
||||
}
|
||||
|
||||
SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
|
||||
{
|
||||
// TODO: FIXME: support reload.
|
||||
engine = _srs_config->get_stream_caster_engine(c);
|
||||
output = _srs_config->get_stream_caster_output(c);
|
||||
local_port_min = _srs_config->get_stream_caster_rtp_port_min(c);
|
||||
local_port_max = _srs_config->get_stream_caster_rtp_port_max(c);
|
||||
manager = new SrsResourceManager("CRTSP");
|
||||
}
|
||||
|
||||
SrsRtspCaster::~SrsRtspCaster()
|
||||
{
|
||||
std::vector<SrsRtspConn*>::iterator it;
|
||||
for (it = clients.begin(); it != clients.end(); ++it) {
|
||||
SrsRtspConn* conn = *it;
|
||||
manager->remove(conn);
|
||||
}
|
||||
clients.clear();
|
||||
used_ports.clear();
|
||||
|
||||
srs_freep(manager);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::initialize()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
if ((err = manager->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start manager");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::alloc_port(int* pport)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// use a pair of port.
|
||||
for (int i = local_port_min; i < local_port_max - 1; i += 2) {
|
||||
if (!used_ports[i]) {
|
||||
used_ports[i] = true;
|
||||
used_ports[i + 1] = true;
|
||||
*pport = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
srs_trace("rtsp: %s alloc port=%d-%d", engine.c_str(), *pport, *pport + 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsRtspCaster::free_port(int lpmin, int lpmax)
|
||||
{
|
||||
for (int i = lpmin; i < lpmax; i++) {
|
||||
used_ports[i] = false;
|
||||
}
|
||||
srs_trace("rtsp: %s free rtp port=%d-%d", engine.c_str(), lpmin, lpmax);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspCaster::on_tcp_client(srs_netfd_t stfd)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsRtspConn* conn = new SrsRtspConn(this, stfd, output);
|
||||
|
||||
if ((err = conn->serve()) != srs_success) {
|
||||
srs_freep(conn);
|
||||
return srs_error_wrap(err, "serve conn");
|
||||
}
|
||||
|
||||
clients.push_back(conn);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsRtspCaster::remove(SrsRtspConn* conn)
|
||||
{
|
||||
std::vector<SrsRtspConn*>::iterator it = find(clients.begin(), clients.end(), conn);
|
||||
if (it != clients.end()) {
|
||||
clients.erase(it);
|
||||
}
|
||||
srs_info("rtsp: remove connection from caster.");
|
||||
|
||||
manager->remove(conn);
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2013-2021 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_APP_RTSP_HPP
|
||||
#define SRS_APP_RTSP_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_service_conn.hpp>
|
||||
|
||||
class SrsStSocket;
|
||||
class SrsRtspConn;
|
||||
class SrsRtspStack;
|
||||
class SrsRtspCaster;
|
||||
class SrsConfDirective;
|
||||
class SrsRtspPacket;
|
||||
class SrsRequest;
|
||||
class SrsStSocket;
|
||||
class SrsRtmpClient;
|
||||
class SrsRawH264Stream;
|
||||
class SrsRawAacStream;
|
||||
struct SrsRawAacStreamCodec;
|
||||
class SrsSharedPtrMessage;
|
||||
class SrsAudioFrame;
|
||||
class SrsSimpleStream;
|
||||
class SrsPithyPrint;
|
||||
class SrsSimpleRtmpClient;
|
||||
class SrsResourceManager;
|
||||
|
||||
// A rtp connection which transport a stream.
|
||||
class SrsRtpConn: public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsPithyPrint* pprint;
|
||||
SrsUdpListener* listener;
|
||||
SrsRtspConn* rtsp;
|
||||
SrsRtspPacket* cache;
|
||||
int stream_id;
|
||||
int _port;
|
||||
public:
|
||||
SrsRtpConn(SrsRtspConn* r, int p, int sid);
|
||||
virtual ~SrsRtpConn();
|
||||
public:
|
||||
virtual int port();
|
||||
virtual srs_error_t listen();
|
||||
// Interface ISrsUdpHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||
};
|
||||
|
||||
// The audio cache, audio is grouped by frames.
|
||||
struct SrsRtspAudioCache
|
||||
{
|
||||
int64_t dts;
|
||||
SrsAudioFrame* audio;
|
||||
SrsSimpleStream* payload;
|
||||
|
||||
SrsRtspAudioCache();
|
||||
virtual ~SrsRtspAudioCache();
|
||||
};
|
||||
|
||||
// The time jitter correct for rtsp.
|
||||
class SrsRtspJitter
|
||||
{
|
||||
private:
|
||||
int64_t previous_timestamp;
|
||||
int64_t pts;
|
||||
int delta;
|
||||
public:
|
||||
SrsRtspJitter();
|
||||
virtual ~SrsRtspJitter();
|
||||
public:
|
||||
virtual int64_t timestamp();
|
||||
virtual srs_error_t correct(int64_t& ts);
|
||||
};
|
||||
|
||||
// The rtsp connection serve the fd.
|
||||
class SrsRtspConn : public ISrsCoroutineHandler, public ISrsConnection
|
||||
{
|
||||
private:
|
||||
std::string output_template;
|
||||
std::string rtsp_tcUrl;
|
||||
std::string rtsp_stream;
|
||||
private:
|
||||
std::string session;
|
||||
// video stream.
|
||||
int video_id;
|
||||
std::string video_codec;
|
||||
SrsRtpConn* video_rtp;
|
||||
// audio stream.
|
||||
int audio_id;
|
||||
std::string audio_codec;
|
||||
int audio_sample_rate;
|
||||
int audio_channel;
|
||||
SrsRtpConn* audio_rtp;
|
||||
private:
|
||||
srs_netfd_t stfd;
|
||||
SrsStSocket* skt;
|
||||
SrsRtspStack* rtsp;
|
||||
SrsRtspCaster* caster;
|
||||
SrsCoroutine* trd;
|
||||
private:
|
||||
SrsRequest* req;
|
||||
SrsSimpleRtmpClient* sdk;
|
||||
SrsRtspJitter* vjitter;
|
||||
SrsRtspJitter* ajitter;
|
||||
private:
|
||||
SrsRawH264Stream* avc;
|
||||
std::string h264_sps;
|
||||
std::string h264_pps;
|
||||
private:
|
||||
SrsRawAacStream* aac;
|
||||
SrsRawAacStreamCodec* acodec;
|
||||
std::string aac_specific_config;
|
||||
SrsRtspAudioCache* acache;
|
||||
public:
|
||||
SrsRtspConn(SrsRtspCaster* c, srs_netfd_t fd, std::string o);
|
||||
virtual ~SrsRtspConn();
|
||||
public:
|
||||
virtual srs_error_t serve();
|
||||
// Interface ISrsConnection.
|
||||
public:
|
||||
virtual std::string remote_ip();
|
||||
virtual const SrsContextId& get_id();
|
||||
virtual std::string desc();
|
||||
private:
|
||||
virtual srs_error_t do_cycle();
|
||||
// internal methods
|
||||
public:
|
||||
virtual srs_error_t on_rtp_packet(SrsRtspPacket* pkt, int stream_id);
|
||||
// Interface ISrsOneCycleThreadHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
private:
|
||||
virtual srs_error_t on_rtp_video(SrsRtspPacket* pkt, int64_t dts, int64_t pts);
|
||||
virtual srs_error_t on_rtp_audio(SrsRtspPacket* pkt, int64_t dts);
|
||||
virtual srs_error_t kickoff_audio_cache(SrsRtspPacket* pkt, int64_t dts);
|
||||
private:
|
||||
virtual srs_error_t write_sequence_header();
|
||||
virtual srs_error_t write_h264_sps_pps(uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_h264_ipb_frame(char* frame, int frame_size, uint32_t dts, uint32_t pts);
|
||||
virtual srs_error_t write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, uint32_t dts);
|
||||
virtual srs_error_t rtmp_write_packet(char type, uint32_t timestamp, char* data, int size);
|
||||
private:
|
||||
// Connect to RTMP server.
|
||||
virtual srs_error_t connect();
|
||||
// Close the connection to RTMP server.
|
||||
virtual void close();
|
||||
};
|
||||
|
||||
// The caster for rtsp.
|
||||
class SrsRtspCaster : public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
std::string engine;
|
||||
std::string output;
|
||||
int local_port_min;
|
||||
int local_port_max;
|
||||
// The key: port, value: whether used.
|
||||
std::map<int, bool> used_ports;
|
||||
private:
|
||||
std::vector<SrsRtspConn*> clients;
|
||||
SrsResourceManager* manager;
|
||||
public:
|
||||
SrsRtspCaster(SrsConfDirective* c);
|
||||
virtual ~SrsRtspCaster();
|
||||
public:
|
||||
// Alloc a rtp port from local ports pool.
|
||||
// @param pport output the rtp port.
|
||||
virtual srs_error_t alloc_port(int* pport);
|
||||
// Free the alloced rtp port.
|
||||
virtual void free_port(int lpmin, int lpmax);
|
||||
virtual srs_error_t initialize();
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
// internal methods.
|
||||
public:
|
||||
virtual void remove(SrsRtspConn* conn);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
class SrsConfDirective;
|
||||
|
||||
// The security apply on vhost.
|
||||
// @see https://github.com/ossrs/srs/issues/211
|
||||
class SrsSecurity
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -30,7 +30,6 @@ using namespace std;
|
|||
#include <srs_app_utility.hpp>
|
||||
#include <srs_app_heartbeat.hpp>
|
||||
#include <srs_app_mpegts_udp.hpp>
|
||||
#include <srs_app_rtsp.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
#include <srs_app_caster_flv.hpp>
|
||||
#include <srs_kernel_consts.hpp>
|
||||
|
@ -53,8 +52,6 @@ std::string srs_listener_type2string(SrsListenerType type)
|
|||
return "HTTP-Server";
|
||||
case SrsListenerMpegTsOverUdp:
|
||||
return "MPEG-TS over UDP";
|
||||
case SrsListenerRtsp:
|
||||
return "RTSP";
|
||||
case SrsListenerFlv:
|
||||
return "HTTP-FLV";
|
||||
default:
|
||||
|
@ -119,62 +116,6 @@ srs_error_t SrsBufferListener::on_tcp_client(srs_netfd_t stfd)
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
SrsRtspListener::SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
|
||||
{
|
||||
listener = NULL;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(type == SrsListenerRtsp);
|
||||
if (type == SrsListenerRtsp) {
|
||||
caster = new SrsRtspCaster(c);
|
||||
|
||||
// TODO: FIXME: Must check error.
|
||||
caster->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
SrsRtspListener::~SrsRtspListener()
|
||||
{
|
||||
srs_freep(caster);
|
||||
srs_freep(listener);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspListener::listen(string i, int p)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// the caller already ensure the type is ok,
|
||||
// we just assert here for unknown stream caster.
|
||||
srs_assert(type == SrsListenerRtsp);
|
||||
|
||||
ip = i;
|
||||
port = p;
|
||||
|
||||
srs_freep(listener);
|
||||
listener = new SrsTcpListener(this, ip, port);
|
||||
|
||||
if ((err = listener->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp listen %s:%d", ip.c_str(), port);
|
||||
}
|
||||
|
||||
string v = srs_listener_type2string(type);
|
||||
srs_trace("%s listen at tcp://%s:%d, fd=%d", v.c_str(), ip.c_str(), port, listener->fd());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspListener::on_tcp_client(srs_netfd_t stfd)
|
||||
{
|
||||
srs_error_t err = caster->on_tcp_client(stfd);
|
||||
if (err != srs_success) {
|
||||
srs_warn("accept client failed, err is %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
|
||||
{
|
||||
listener = NULL;
|
||||
|
@ -629,7 +570,6 @@ void SrsServer::dispose()
|
|||
close_listeners(SrsListenerHttpStream);
|
||||
close_listeners(SrsListenerHttpsStream);
|
||||
close_listeners(SrsListenerMpegTsOverUdp);
|
||||
close_listeners(SrsListenerRtsp);
|
||||
close_listeners(SrsListenerFlv);
|
||||
|
||||
// Fast stop to notify FFMPEG to quit, wait for a while then fast kill.
|
||||
|
@ -656,7 +596,6 @@ void SrsServer::gracefully_dispose()
|
|||
close_listeners(SrsListenerHttpStream);
|
||||
close_listeners(SrsListenerHttpsStream);
|
||||
close_listeners(SrsListenerMpegTsOverUdp);
|
||||
close_listeners(SrsListenerRtsp);
|
||||
close_listeners(SrsListenerFlv);
|
||||
srs_trace("listeners closed");
|
||||
|
||||
|
@ -1359,9 +1298,6 @@ srs_error_t SrsServer::listen_stream_caster()
|
|||
std::string caster = _srs_config->get_stream_caster_engine(stream_caster);
|
||||
if (srs_stream_caster_is_udp(caster)) {
|
||||
listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster);
|
||||
} else if (srs_stream_caster_is_rtsp(caster)) {
|
||||
srs_warn("It's deprecated and will be removed in the future, see https://github.com/ossrs/srs/issues/2304#issuecomment-826009290");
|
||||
listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster);
|
||||
} else if (srs_stream_caster_is_flv(caster)) {
|
||||
listener = new SrsHttpFlvListener(this, SrsListenerFlv, stream_caster);
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,6 @@ class ISrsUdpHandler;
|
|||
class SrsUdpListener;
|
||||
class SrsTcpListener;
|
||||
class SrsAppCasterFlv;
|
||||
class SrsRtspCaster;
|
||||
class SrsResourceManager;
|
||||
class SrsLatestVersion;
|
||||
|
||||
|
@ -50,8 +49,6 @@ enum SrsListenerType
|
|||
SrsListenerHttpStream = 2,
|
||||
// UDP stream, MPEG-TS over udp.
|
||||
SrsListenerMpegTsOverUdp = 3,
|
||||
// TCP stream, RTSP stream.
|
||||
SrsListenerRtsp = 4,
|
||||
// TCP stream, FLV stream over HTTP.
|
||||
SrsListenerFlv = 5,
|
||||
// HTTPS api,
|
||||
|
@ -92,22 +89,6 @@ public:
|
|||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// A TCP listener, for rtsp server.
|
||||
class SrsRtspListener : public SrsListener, public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
SrsTcpListener* listener;
|
||||
SrsRtspCaster* caster;
|
||||
public:
|
||||
SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
|
||||
virtual ~SrsRtspListener();
|
||||
public:
|
||||
virtual srs_error_t listen(std::string i, int p);
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// A TCP listener, for flv stream server.
|
||||
class SrsHttpFlvListener : public SrsListener, public ISrsTcpHandler
|
||||
{
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 4
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 167
|
||||
#define VERSION_REVISION 171
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1078,10 +1078,57 @@ srs_error_t SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp)
|
|||
if ((err = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != srs_success) {
|
||||
return srs_error_wrap(err, "read pic_height_in_map_units_minus1");;
|
||||
}
|
||||
|
||||
vcodec->width = (int)(pic_width_in_mbs_minus1 + 1) * 16;
|
||||
vcodec->height = (int)(pic_height_in_map_units_minus1 + 1) * 16;
|
||||
|
||||
|
||||
int8_t frame_mbs_only_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, frame_mbs_only_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_mbs_only_flag");;
|
||||
}
|
||||
if(!frame_mbs_only_flag) {
|
||||
/* Skip mb_adaptive_frame_field_flag */
|
||||
int8_t mb_adaptive_frame_field_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, mb_adaptive_frame_field_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read mb_adaptive_frame_field_flag");;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip direct_8x8_inference_flag */
|
||||
int8_t direct_8x8_inference_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, direct_8x8_inference_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read direct_8x8_inference_flag");;
|
||||
}
|
||||
|
||||
/* We need the following value to evaluate offsets, if any */
|
||||
int8_t frame_cropping_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, frame_cropping_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_cropping_flag");;
|
||||
}
|
||||
int32_t frame_crop_left_offset = 0, frame_crop_right_offset = 0,
|
||||
frame_crop_top_offset = 0, frame_crop_bottom_offset = 0;
|
||||
if(frame_cropping_flag) {
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_left_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_left_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_right_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_right_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_top_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_top_offset");;
|
||||
}
|
||||
if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_bottom_offset)) != srs_success) {
|
||||
return srs_error_wrap(err, "read frame_crop_bottom_offset");;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip vui_parameters_present_flag */
|
||||
int8_t vui_parameters_present_flag = -1;
|
||||
if ((err = srs_avc_nalu_read_bit(&bs, vui_parameters_present_flag)) != srs_success) {
|
||||
return srs_error_wrap(err, "read vui_parameters_present_flag");;
|
||||
}
|
||||
|
||||
vcodec->width = ((pic_width_in_mbs_minus1 + 1) * 16) - frame_crop_left_offset * 2 - frame_crop_right_offset * 2;
|
||||
vcodec->height = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) \
|
||||
- (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_kernel_mp3.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
@ -120,7 +119,6 @@ srs_utime_t srs_update_system_time()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// @see: https://github.com/ossrs/srs/issues/35
|
||||
// we must convert the tv_sec/tv_usec to int64_t.
|
||||
int64_t now_us = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec;
|
||||
|
||||
|
@ -140,7 +138,6 @@ srs_utime_t srs_update_system_time()
|
|||
diff = srs_max(0, diff);
|
||||
if (diff < 0 || diff > 1000 * SYS_TIME_RESOLUTION_US) {
|
||||
srs_warn("clock jump, history=%" PRId64 "us, now=%" PRId64 "us, diff=%" PRId64 "us", _srs_system_time_us_cache, now_us, diff);
|
||||
// @see: https://github.com/ossrs/srs/issues/109
|
||||
_srs_system_time_startup_time += diff;
|
||||
}
|
||||
|
||||
|
@ -580,7 +577,6 @@ int srs_do_create_dir_recursively(string dir)
|
|||
}
|
||||
|
||||
// create curren dir.
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifdef _WIN32
|
||||
if (::_mkdir(dir.c_str()) < 0) {
|
||||
#else
|
||||
|
|
|
@ -49,6 +49,7 @@ using namespace std;
|
|||
|
||||
// pre-declare
|
||||
srs_error_t run_directly_or_daemon();
|
||||
srs_error_t srs_detect_docker();
|
||||
srs_error_t run_hybrid_server();
|
||||
void show_macro_features();
|
||||
|
||||
|
@ -95,6 +96,11 @@ srs_error_t do_main(int argc, char** argv)
|
|||
#ifdef SRS_GPERF_MP
|
||||
#warning "gmp is not used for memory leak, please use gmc instead."
|
||||
#endif
|
||||
|
||||
// Ignore any error while detecting docker.
|
||||
if ((err = srs_detect_docker()) != srs_success) {
|
||||
srs_error_reset(err);
|
||||
}
|
||||
|
||||
// never use srs log(srs_trace, srs_error, etc) before config parse the option,
|
||||
// which will load the log config and apply it.
|
||||
|
@ -378,11 +384,6 @@ srs_error_t run_directly_or_daemon()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Ignore any error while detecting docker.
|
||||
if ((err = srs_detect_docker()) != srs_success) {
|
||||
srs_error_reset(err);
|
||||
}
|
||||
|
||||
// Load daemon from config, disable it for docker.
|
||||
// @see https://github.com/ossrs/srs/issues/1594
|
||||
bool run_as_daemon = _srs_config->get_daemon();
|
||||
|
|
|
@ -167,7 +167,6 @@ srs_error_t SrsFastStream::grow(ISrsReader* reader, int required_size)
|
|||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
if (merged_read && _handler) {
|
||||
_handler->on_read(nread);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
@ -349,7 +348,6 @@ srs_error_t srs_write_large_iovs(ISrsProtocolReadWriter* skt, iovec* iovs, int s
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// the limits of writev iovs.
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
// for linux, generally it's 1024.
|
||||
static int limits = (int)sysconf(_SC_IOV_MAX);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
|
|
@ -281,7 +281,6 @@ srs_error_t SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* p
|
|||
// decode the ADTS.
|
||||
// @see ISO_IEC_13818-7-AAC-2004.pdf, page 26
|
||||
// 6.2 Audio Data Transport Stream, ADTS
|
||||
// @see https://github.com/ossrs/srs/issues/212#issuecomment-64145885
|
||||
// byte_alignment()
|
||||
|
||||
// adts_fixed_header:
|
||||
|
@ -342,7 +341,7 @@ srs_error_t SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* p
|
|||
int8_t channel_configuration = (sfiv >> 6) & 0x07;
|
||||
/*int8_t original = (sfiv >> 5) & 0x01;*/
|
||||
/*int8_t home = (sfiv >> 4) & 0x01;*/
|
||||
//int8_t Emphasis; @remark, Emphasis is removed, @see https://github.com/ossrs/srs/issues/212#issuecomment-64154736
|
||||
//int8_t Emphasis; @remark, Emphasis is removed
|
||||
// 4bits left.
|
||||
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
||||
// copyright_identification_bit 1 bslbf
|
||||
|
|
|
@ -571,7 +571,6 @@ namespace srs_internal
|
|||
}
|
||||
|
||||
// directly generate the public key.
|
||||
// @see: https://github.com/ossrs/srs/issues/148
|
||||
int pkey_size = 128;
|
||||
if ((err = dh.copy_shared_key(c1->get_key(), 128, key.key, pkey_size)) != srs_success) {
|
||||
return srs_error_wrap(err, "copy shared key");
|
||||
|
|
|
@ -1036,7 +1036,6 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
// 0x04 where: message_type=4(protocol control user-control message)
|
||||
// 0x00 0x06 where: event Ping(0x06)
|
||||
// 0x00 0x00 0x0d 0x0f where: event data 4bytes ping timestamp.
|
||||
// @see: https://github.com/ossrs/srs/issues/98
|
||||
if (fmt == RTMP_FMT_TYPE1) {
|
||||
srs_warn("fresh chunk starts with fmt=1");
|
||||
} else {
|
||||
|
@ -1175,7 +1174,6 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
pp[0] = *p++;
|
||||
|
||||
// always use 31bits timestamp, for some server may use 32bits extended timestamp.
|
||||
// @see https://github.com/ossrs/srs/issues/111
|
||||
timestamp &= 0x7fffffff;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// For srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
@ -161,7 +160,6 @@ private:
|
|||
std::map<int, SrsChunkStream*> chunk_streams;
|
||||
// Cache some frequently used chunk header.
|
||||
// cs_cache, the chunk stream cache.
|
||||
// @see https://github.com/ossrs/srs/issues/249
|
||||
SrsChunkStream** cs_cache;
|
||||
// The bytes buffer cache, recv from skt, provide services for stream.
|
||||
SrsFastStream* in_buffer;
|
||||
|
@ -179,7 +177,6 @@ private:
|
|||
bool show_debug_info;
|
||||
// Whether auto response when recv messages.
|
||||
// default to true for it's very easy to use the protocol stack.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
bool auto_response_when_recv;
|
||||
// When not auto response message, manual flush the messages in queue.
|
||||
std::vector<SrsPacket*> manual_response_queue;
|
||||
|
@ -208,7 +205,6 @@ public:
|
|||
public:
|
||||
// Set the auto response message when recv for protocol stack.
|
||||
// @param v, whether auto response message when recv message.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
virtual void set_auto_response(bool v);
|
||||
// Flush for manual response when the auto response is disabled
|
||||
// by set_auto_response(false), we default use auto response, so donot
|
||||
|
@ -222,13 +218,11 @@ public:
|
|||
// that is, we merge some data to read together.
|
||||
// @param v true to ename merged read.
|
||||
// @param handler the handler when merge read is enabled.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_merge_read(bool v, IMergeReadHandler* handler);
|
||||
// Create buffer with specifeid size.
|
||||
// @param buffer the size of buffer.
|
||||
// @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
// @remark when buffer changed, the previous ptr maybe invalid.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_recv_buffer(int buffer_size);
|
||||
#endif
|
||||
public:
|
||||
|
@ -429,7 +423,6 @@ public:
|
|||
std::string stream;
|
||||
// For play live stream,
|
||||
// used to specified the stop when exceed the duration.
|
||||
// @see https://github.com/ossrs/srs/issues/45
|
||||
// in srs_utime_t.
|
||||
srs_utime_t duration;
|
||||
// The token in the connect request,
|
||||
|
@ -620,7 +613,6 @@ public:
|
|||
public:
|
||||
// Set the auto response message when recv for protocol stack.
|
||||
// @param v, whether auto response message when recv message.
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
virtual void set_auto_response(bool v);
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
// To improve read performance, merge some packets then read,
|
||||
|
@ -628,13 +620,11 @@ public:
|
|||
// that is, we merge some data to read together.
|
||||
// @param v true to ename merged read.
|
||||
// @param handler the handler when merge read is enabled.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_merge_read(bool v, IMergeReadHandler* handler);
|
||||
// Create buffer with specifeid size.
|
||||
// @param buffer the size of buffer.
|
||||
// @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
// @remark when buffer changed, the previous ptr maybe invalid.
|
||||
// @see https://github.com/ossrs/srs/issues/241
|
||||
virtual void set_recv_buffer(int buffer_size);
|
||||
#endif
|
||||
// To set/get the recv timeout in srs_utime_t.
|
||||
|
@ -675,7 +665,6 @@ public:
|
|||
// @param stream_id, the stream id of packet to send over, 0 for control message.
|
||||
//
|
||||
// @remark performance issue, to support 6k+ 250kbps client,
|
||||
// @see https://github.com/ossrs/srs/issues/194
|
||||
virtual srs_error_t send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id);
|
||||
// Send the RTMP packet and always free it.
|
||||
// user must never free or use the packet after this method,
|
||||
|
@ -1336,11 +1325,9 @@ public:
|
|||
// Name of command. Set to "|RtmpSampleAccess".
|
||||
std::string command_name;
|
||||
// Whether allow access the sample of video.
|
||||
// @see: https://github.com/ossrs/srs/issues/49
|
||||
// @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#videoSampleAccess
|
||||
bool video_sample_access;
|
||||
// Whether allow access the sample of audio.
|
||||
// @see: https://github.com/ossrs/srs/issues/49
|
||||
// @see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#audioSampleAccess
|
||||
bool audio_sample_access;
|
||||
public:
|
||||
|
|
|
@ -97,7 +97,6 @@ srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug)
|
|||
}
|
||||
|
||||
// notify server the edge identity,
|
||||
// @see https://github.com/ossrs/srs/issues/147
|
||||
SrsAmf0Object* data = req->args;
|
||||
data->set("srs_sig", SrsAmf0Any::str(RTMP_SIG_SRS_KEY));
|
||||
data->set("srs_server", SrsAmf0Any::str(RTMP_SIG_SRS_SERVER));
|
||||
|
@ -121,7 +120,6 @@ srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug)
|
|||
req->tcUrl = tc_url;
|
||||
|
||||
// upnode server identity will show in the connect_app of client.
|
||||
// @see https://github.com/ossrs/srs/issues/160
|
||||
// the debug_srs_upnode is config in vhost and default to true.
|
||||
SrsServerInfo si;
|
||||
if ((err = client->connect_app(req->app, tc_url, req, debug, &si)) != srs_success) {
|
||||
|
|
|
@ -41,7 +41,6 @@ srs_error_t srs_st_init()
|
|||
{
|
||||
#ifdef __linux__
|
||||
// check epoll, some old linux donot support epoll.
|
||||
// @see https://github.com/ossrs/srs/issues/162
|
||||
if (!srs_st_epoll_is_supported()) {
|
||||
return srs_error_new(ERROR_ST_SET_EPOLL, "linux epoll disabled");
|
||||
}
|
||||
|
@ -510,7 +509,6 @@ srs_error_t SrsStSocket::read(void* buf, size_t size, ssize_t* nread)
|
|||
// (a value of 0 means the network connection is closed or end of file is reached).
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_read <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_read < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "timeout %d ms", srsu2msi(rtm));
|
||||
}
|
||||
|
@ -546,7 +544,6 @@ srs_error_t SrsStSocket::read_fully(void* buf, size_t size, ssize_t* nread)
|
|||
// (a value less than nbyte means the network connection is closed or end of file is reached)
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_read != (ssize_t)size) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_read < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "timeout %d ms", srsu2msi(rtm));
|
||||
}
|
||||
|
@ -581,7 +578,6 @@ srs_error_t SrsStSocket::write(void* buf, size_t size, ssize_t* nwrite)
|
|||
// On success a non-negative integer equal to nbyte is returned.
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_write <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_write < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "write timeout %d ms", srsu2msi(stm));
|
||||
}
|
||||
|
@ -612,7 +608,6 @@ srs_error_t SrsStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
|||
// On success a non-negative integer equal to nbyte is returned.
|
||||
// Otherwise, a value of -1 is returned and errno is set to indicate the error.
|
||||
if (nb_write <= 0) {
|
||||
// @see https://github.com/ossrs/srs/issues/200
|
||||
if (nb_write < 0 && errno == ETIME) {
|
||||
return srs_error_new(ERROR_SOCKET_TIMEOUT, "writev timeout %d ms", srsu2msi(stm));
|
||||
}
|
||||
|
|
|
@ -2162,9 +2162,6 @@ VOID TEST(ConfigUnitTest, OperatorEquals)
|
|||
EXPECT_TRUE(srs_stream_caster_is_udp("mpegts_over_udp"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_udp("xxx"));
|
||||
|
||||
EXPECT_TRUE(srs_stream_caster_is_rtsp("rtsp"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_rtsp("xxx"));
|
||||
|
||||
EXPECT_TRUE(srs_stream_caster_is_flv("flv"));
|
||||
EXPECT_FALSE(srs_stream_caster_is_flv("xxx"));
|
||||
|
||||
|
|
|
@ -727,7 +727,6 @@ VOID TEST(ProtocolStackTest, ProtocolRecvMessage)
|
|||
// 0x04 where: message_type=4(protocol control user-control message)
|
||||
// 0x00 0x06 where: event Ping(0x06)
|
||||
// 0x00 0x00 0x0d 0x0f where: event data 4bytes ping timestamp.
|
||||
// @see: https://github.com/ossrs/srs/issues/98
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvMessageBug98)
|
||||
{
|
||||
MockBufferIO bio;
|
||||
|
@ -3824,7 +3823,6 @@ VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage2)
|
|||
* always use 31bits timestamp.
|
||||
*/
|
||||
// always use 31bits timestamp, for some server may use 32bits extended timestamp.
|
||||
// @see https://github.com/ossrs/srs/issues/111
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage3)
|
||||
{
|
||||
MockBufferIO bio;
|
||||
|
|
Loading…
Reference in a new issue