1
0
Fork 0
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:
winlin 2021-10-10 12:05:26 +08:00
parent 6c597facfb
commit a81aa2edc5
65 changed files with 276 additions and 5990 deletions

View file

@ -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

View file

@ -5,3 +5,4 @@ letsencrypt.cache
*.key
objs
.format.txt
.DS_Store

View file

@ -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

View file

@ -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
}

View file

@ -35,7 +35,7 @@ func VersionMinor() int {
}
func VersionRevision() int {
return 5
return 18
}
func Version() string {

View file

@ -16,3 +16,4 @@
.format.txt
objs
.DS_Store

View file

@ -6,3 +6,4 @@ objs
.DS_Store
.format.txt
.DS_Store

View file

@ -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"]

View file

@ -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;
}
}

View file

@ -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.

View file

@ -11,8 +11,6 @@ http_api {
raw_api {
enabled on;
allow_reload on;
allow_query on;
allow_update on;
}
}
http_server {

View file

@ -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

View file

@ -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
View file

@ -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")

View file

@ -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

View file

@ -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].

View file

@ -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

View file

@ -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">

View file

@ -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"});
}]);

View file

@ -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 + "&param=" + 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 + "&param=" + 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;

View file

@ -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"});
}]);

View file

@ -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

View file

@ -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的侦听地址格式是&lt;[address:]port&gt;。默认: 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服务格式是&lt;[address:]port&gt;[,&lt;addressN&gt;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获取集群信息格式是&lt;ip:port&gt;。">
</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="设备IDSRS会写入汇报信息中。"
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服务器侦听的地址格式是&lt;[address:]port&gt;。默认: 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="转换器侦听的地址,格式是&lt;port&gt;"
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>

View file

@ -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 &lt;[address:]port&gt;. 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 &lt;[address:]port&gt;[,&lt;addressN&gt;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 &lt;ip:port&gt;">
</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 &lt;[address:]port&gt;. 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 &lt;port&gt;"
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>

View file

@ -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>

View file

@ -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>

View file

@ -1 +0,0 @@
DVR信息请在每个Stream中单独配置, 请前往<a href="javascript:void(0)" ng-click="gogogo('/streams/')">Streams</a>配置。

View file

@ -1 +0,0 @@
Please config DVR in each stream by <a href="javascript:void(0)" ng-click="gogogo('/streams/')">here</a>.

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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:

View file

@ -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.

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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());
}

View file

@ -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");
}

View file

@ -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

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -16,7 +16,6 @@
class SrsConfDirective;
// The security apply on vhost.
// @see https://github.com/ossrs/srs/issues/211
class SrsSecurity
{
public:

View file

@ -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 {

View file

@ -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
{

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 4
#define VERSION_MINOR 0
#define VERSION_REVISION 167
#define VERSION_REVISION 171
#endif

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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;
/**

View file

@ -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:

View file

@ -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) {

View file

@ -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));
}

View file

@ -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"));

View file

@ -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;