Merge branch 'develop' into pr-fix_bridge
This commit is contained in:
commit
5466d99c9c
|
|
@ -301,6 +301,58 @@ code_patterns:
|
|||
exceptions: "Only applies to SRS-defined classes/structs - do NOT change 3rd party code like llhttp"
|
||||
rationale: "Consistent naming convention across SRS codebase for better code readability and maintenance - underscore distinguishes member variables from local variables and parameters"
|
||||
|
||||
access_specifiers_for_testing:
|
||||
- pattern: "SRS_DECLARE_PRIVATE and SRS_DECLARE_PROTECTED macros"
|
||||
description: "MANDATORY - Always use SRS_DECLARE_PRIVATE instead of 'private' and SRS_DECLARE_PROTECTED instead of 'protected' in class definitions"
|
||||
purpose: "Enables unit tests to access private and protected members for dependency injection and mocking"
|
||||
|
||||
macro_definition: |
|
||||
#ifdef SRS_FORCE_PUBLIC4UTEST
|
||||
#define SRS_DECLARE_PRIVATE public
|
||||
#define SRS_DECLARE_PROTECTED public
|
||||
#else
|
||||
#define SRS_DECLARE_PRIVATE private
|
||||
#define SRS_DECLARE_PROTECTED protected
|
||||
#endif
|
||||
|
||||
usage: |
|
||||
WRONG: Using standard C++ access specifiers
|
||||
class SrsBufferCache {
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
ISrsRequest *req_;
|
||||
protected:
|
||||
virtual srs_error_t do_start();
|
||||
public:
|
||||
srs_error_t start();
|
||||
};
|
||||
|
||||
CORRECT: Using SRS access specifier macros
|
||||
class SrsBufferCache {
|
||||
SRS_DECLARE_PRIVATE:
|
||||
ISrsAppConfig *config_;
|
||||
ISrsRequest *req_;
|
||||
SRS_DECLARE_PROTECTED:
|
||||
virtual srs_error_t do_start();
|
||||
public:
|
||||
srs_error_t start();
|
||||
};
|
||||
|
||||
rules:
|
||||
- "ALWAYS use SRS_DECLARE_PRIVATE instead of 'private' keyword"
|
||||
- "ALWAYS use SRS_DECLARE_PROTECTED instead of 'protected' keyword"
|
||||
- "Use standard 'public' keyword for public members (no macro needed)"
|
||||
- "This applies to ALL production code classes in trunk/src/"
|
||||
- "When SRS_FORCE_PUBLIC4UTEST is defined, all private/protected members become public for testing"
|
||||
|
||||
benefits:
|
||||
- "Enables unit tests to inject mock dependencies into private member fields"
|
||||
- "Allows tests to access and verify internal state"
|
||||
- "Makes classes fully testable without breaking encapsulation in production"
|
||||
- "Provides clean separation between production and test builds"
|
||||
|
||||
rationale: "This pattern allows unit tests to access private/protected members for dependency injection and mocking, while maintaining proper encapsulation in production builds. It's essential for writing comprehensive unit tests that can mock all dependencies."
|
||||
|
||||
commenting_style:
|
||||
- pattern: "C++ style comments"
|
||||
description: "MANDATORY - Use C++ style comments (//) instead of C style comments (/* */)"
|
||||
|
|
@ -570,6 +622,82 @@ build_and_development:
|
|||
description: "Run the unit tests for SRS"
|
||||
working_directory: "trunk"
|
||||
|
||||
run_blackbox_tests:
|
||||
description: "Blackbox tests are integration tests that test SRS as a complete system using FFmpeg as client"
|
||||
location: "trunk/3rdparty/srs-bench/blackbox/"
|
||||
|
||||
prerequisites:
|
||||
- "SRS server binary must be built first (make -j in trunk/)"
|
||||
- "FFmpeg and FFprobe must be available in PATH"
|
||||
- "Test media files (avatar.flv, etc.) must be present in srs-bench directory"
|
||||
|
||||
build_blackbox_tests:
|
||||
command: "cd trunk/3rdparty/srs-bench && make"
|
||||
description: "Build the blackbox test binary"
|
||||
output: "./objs/srs_blackbox_test"
|
||||
|
||||
run_all_tests:
|
||||
command: "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout"
|
||||
description: "Run all blackbox tests with verbose output and detailed SRS logs"
|
||||
working_directory: "trunk/3rdparty/srs-bench"
|
||||
|
||||
run_specific_test:
|
||||
command: "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run TestName"
|
||||
description: "Run a specific test by name (e.g., TestFast_RtmpPublish_DvrFlv_Basic)"
|
||||
examples:
|
||||
- "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run TestFast_RtmpPublish_DvrFlv_Basic"
|
||||
- "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run TestFast_RtmpPublish_RtmpPlay_Basic"
|
||||
- "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run 'TestFast_RtmpPublish_Dvr.*'"
|
||||
|
||||
test_options:
|
||||
- flag: "-test.v"
|
||||
description: "Verbose output showing test progress (recommended)"
|
||||
- flag: "-test.run <pattern>"
|
||||
description: "Run only tests matching the pattern (Go regex)"
|
||||
- flag: "-srs-log"
|
||||
description: "Enable detailed SRS log output (recommended for debugging)"
|
||||
- flag: "-srs-stdout"
|
||||
description: "Show SRS stdout logs (recommended for debugging)"
|
||||
- flag: "-srs-ffmpeg-stderr"
|
||||
description: "Show FFmpeg stderr logs"
|
||||
- flag: "-srs-ffprobe-stdout"
|
||||
description: "Show FFprobe stdout logs"
|
||||
- flag: "-srs-binary <path>"
|
||||
description: "Specify custom SRS binary path (default: ../../objs/srs)"
|
||||
- flag: "-srs-timeout <ms>"
|
||||
description: "Timeout for each test case in milliseconds (default: 64000)"
|
||||
|
||||
how_it_works:
|
||||
- "Each blackbox test automatically starts a fresh SRS server instance"
|
||||
- "SRS is configured via environment variables (e.g., SRS_VHOST_DVR_ENABLED=on)"
|
||||
- "Tests use FFmpeg to publish streams and FFprobe to verify output"
|
||||
- "SRS server is automatically stopped when test completes"
|
||||
- "Each test runs in isolation with its own SRS instance and random ports"
|
||||
- "No need to manually start or stop SRS server"
|
||||
|
||||
test_categories:
|
||||
rtmp: "TestFast_RtmpPublish_RtmpPlay_*, TestFast_RtmpPublish_HttpFlvPlay_*"
|
||||
dvr: "TestFast_RtmpPublish_DvrFlv_*, TestFast_RtmpPublish_DvrMp4_*"
|
||||
hls: "TestFast_RtmpPublish_HlsPlay_*"
|
||||
hevc: "TestSlow_RtmpPublish_*_HEVC_*, TestSlow_SrtPublish_*_HEVC_*"
|
||||
srt: "TestFast_SrtPublish_SrtPlay_*"
|
||||
rtsp: "TestFast_RtmpPublish_RtspPlay_*"
|
||||
http_api: "TestFast_Http_Api_*"
|
||||
mp3: "TestFast_RtmpPublish_*_CodecMP3_*"
|
||||
|
||||
common_workflows:
|
||||
quick_test:
|
||||
description: "Run a single fast test to verify basic functionality"
|
||||
command: "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run TestFast_RtmpPublish_RtmpPlay_Basic"
|
||||
|
||||
dvr_tests:
|
||||
description: "Run all DVR-related tests"
|
||||
command: "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -test.run 'TestFast_RtmpPublish_Dvr.*'"
|
||||
|
||||
debug_test:
|
||||
description: "Run test with full logging including FFmpeg stderr for debugging"
|
||||
command: "./objs/srs_blackbox_test -test.v -srs-log -srs-stdout -srs-ffmpeg-stderr -test.run TestName"
|
||||
|
||||
testing:
|
||||
test_patterns:
|
||||
- Note that private and protected members are accessible in utests, as there is a macro to convert them to public
|
||||
|
|
@ -579,6 +707,66 @@ testing:
|
|||
- Verify edge cases like sequence number wrap-around, cache overflow, and null inputs
|
||||
- Use existing mock helper functions for consistency and maintainability
|
||||
|
||||
mock_interface_fields:
|
||||
principle: "MANDATORY - Always mock all private/protected interface member fields (ISrs* types) in the class under test"
|
||||
description: |
|
||||
When writing unit tests, ALWAYS identify and mock ALL interface member fields in the class under test.
|
||||
Interface fields are those with ISrs* prefix (e.g., ISrsAppConfig*, ISrsBasicRtmpClient*, ISrsRequest*).
|
||||
This enables proper dependency injection and isolation of the unit under test.
|
||||
|
||||
process:
|
||||
- "Step 1: View the class header file to identify all private/protected member fields"
|
||||
- "Step 2: Identify which fields are interfaces (start with ISrs prefix)"
|
||||
- "Step 3: Create or reuse mock classes for each interface type"
|
||||
- "Step 4: In the test, inject mock instances into the class under test by setting the private fields directly"
|
||||
- "Step 5: After test completes, set injected fields to NULL before object destruction to avoid double-free"
|
||||
|
||||
example: |
|
||||
// Class under test has these private fields:
|
||||
class SrsEdgeRtmpUpstream {
|
||||
private:
|
||||
ISrsAppConfig *config_; // Interface - MUST mock
|
||||
ISrsBasicRtmpClient *sdk_; // Interface - MUST mock
|
||||
std::string redirect_; // Not interface - no need to mock
|
||||
int selected_port_; // Not interface - no need to mock
|
||||
};
|
||||
|
||||
// In unit test:
|
||||
VOID TEST(EdgeRtmpUpstreamTest, ConnectToOrigin) {
|
||||
// Create mocks for ALL interface fields
|
||||
SrsUniquePtr<MockEdgeConfig> mock_config(new MockEdgeConfig());
|
||||
MockEdgeRtmpClient *mock_sdk = new MockEdgeRtmpClient();
|
||||
|
||||
// Create object under test
|
||||
SrsUniquePtr<SrsEdgeRtmpUpstream> upstream(new SrsEdgeRtmpUpstream(""));
|
||||
|
||||
// Inject mocks into private interface fields
|
||||
upstream->config_ = mock_config.get();
|
||||
upstream->sdk_ = mock_sdk;
|
||||
|
||||
// Run test
|
||||
err = upstream->connect(req.get(), lb.get());
|
||||
HELPER_EXPECT_SUCCESS(err);
|
||||
|
||||
// Verify mock interactions
|
||||
EXPECT_TRUE(mock_sdk->connect_called_);
|
||||
|
||||
// Clean up - set to NULL to avoid double-free
|
||||
upstream->sdk_ = NULL;
|
||||
srs_freep(mock_sdk);
|
||||
}
|
||||
|
||||
rules:
|
||||
- "ALWAYS view the class header file first to identify all member fields"
|
||||
- "ALWAYS mock ALL interface fields (ISrs* prefix) - no exceptions"
|
||||
- "Create mock classes that implement the interface if they don't exist"
|
||||
- "Reuse existing mock classes from srs_utest_app*.hpp when available"
|
||||
- "Inject mocks by directly setting private member fields (accessible in utests)"
|
||||
- "Set injected fields to NULL before object destruction to prevent double-free"
|
||||
- "Non-interface fields (std::string, int, etc.) do not need mocking"
|
||||
|
||||
rationale: "Mocking all interface dependencies ensures tests are isolated, fast, and don't require real network/file/database resources. It also makes tests deterministic and easier to debug."
|
||||
|
||||
test_object_declaration:
|
||||
- pattern: "Use unique pointers for object instantiation"
|
||||
description: "MANDATORY - Always use SrsUniquePtr for object declaration in unit tests instead of stack allocation"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
**/3rdparty/patches/**
|
||||
**/3rdparty/signaling/**
|
||||
**/3rdparty/srt-1-fit/**
|
||||
**/3rdparty/srs-bench/vendor/**
|
||||
|
||||
# Research files.
|
||||
**/tools/**
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
# ColumnLimit: 0
|
||||
# IndentWidth: 4
|
||||
# TabWidth: 4
|
||||
# Macros: SRS_DECLARE_PRIVATE=private, SRS_DECLARE_PROTECTED=protected (treat as access specifiers)
|
||||
# refer to https://clang.llvm.org/docs/ClangFormatStyleOptions.html for more details.
|
||||
---
|
||||
Language: Cpp
|
||||
|
|
@ -198,6 +199,9 @@ LambdaBodyIndentation: Signature
|
|||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
Macros:
|
||||
- 'SRS_DECLARE_PRIVATE=private:'
|
||||
- 'SRS_DECLARE_PROTECTED=protected:'
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
|
|
|
|||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
|
@ -208,8 +208,10 @@ jobs:
|
|||
echo "Release ossrs/srs:$SRS_TAG"
|
||||
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 \
|
||||
--output "type=image,push=true" \
|
||||
-t ossrs/srs:$SRS_TAG --build-arg SRS_AUTO_PACKAGER=$PACKAGER \
|
||||
--build-arg CONFARGS='--sanitizer=off --gb28181=on' \
|
||||
-t ossrs/srs:$SRS_TAG \
|
||||
--build-arg SRS_AUTO_PACKAGER=$PACKAGER \
|
||||
--build-arg IMAGE=ossrs/srs:ubuntu20 \
|
||||
--build-arg CONFARGS='--sanitizer=off --gb28181=on --rtsp=on' \
|
||||
-f Dockerfile .
|
||||
# Docker alias images
|
||||
# TODO: FIXME: If stable, please set the latest from 5.0 to 6.0
|
||||
|
|
|
|||
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
|
|
@ -180,6 +180,7 @@ jobs:
|
|||
--output "type=image,push=false" \
|
||||
--build-arg IMAGE=ossrs/srs:ubuntu20-cache \
|
||||
--build-arg INSTALLDEPENDS="NO" \
|
||||
--build-arg CONFARGS="--sanitizer=on" \
|
||||
-f Dockerfile .
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
|
|
@ -201,6 +202,7 @@ jobs:
|
|||
--output "type=image,push=false" \
|
||||
--build-arg IMAGE=ossrs/srs:ubuntu20-cache \
|
||||
--build-arg INSTALLDEPENDS="NO" \
|
||||
--build-arg CONFARGS="--sanitizer=on" \
|
||||
-f Dockerfile .
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
|
|
@ -221,6 +223,7 @@ jobs:
|
|||
docker buildx build --platform linux/amd64 \
|
||||
--output "type=image,push=false" \
|
||||
--build-arg IMAGE=ossrs/srs:ubuntu20-cache \
|
||||
--build-arg CONFARGS="--sanitizer=on" \
|
||||
-f Dockerfile .
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,7 @@ COPY --from=build /usr/local/srs /usr/local/srs
|
|||
# Test the version of binaries.
|
||||
RUN ldd /usr/local/srs/objs/ffmpeg/bin/ffmpeg && \
|
||||
/usr/local/srs/objs/ffmpeg/bin/ffmpeg -version && \
|
||||
ldd /usr/local/srs/objs/srs && \
|
||||
/usr/local/srs/objs/srs -v
|
||||
ldd /usr/local/srs/objs/srs
|
||||
|
||||
# Default workdir and command.
|
||||
WORKDIR /usr/local/srs
|
||||
|
|
|
|||
10
trunk/3rdparty/srs-bench/blackbox/rtsp_test.go
vendored
10
trunk/3rdparty/srs-bench/blackbox/rtsp_test.go
vendored
|
|
@ -113,7 +113,7 @@ func TestFast_RtmpPublish_RtspPlay_Basic(t *testing.T) {
|
|||
if ts := 80; m.Format.ProbeScore < ts {
|
||||
r4 = errors.Errorf("low score=%v < %v, %v, %v", m.Format.ProbeScore, ts, m.String(), str)
|
||||
}
|
||||
if dv := m.Duration(); dv < duration {
|
||||
if dv := m.Duration(); dv < duration/2 {
|
||||
r5 = errors.Errorf("short duration=%v < %v, %v, %v", dv, duration, m.String(), str)
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ func TestFast_RtmpPublish_RtspPlay_MultipleClients(t *testing.T) {
|
|||
if ts := 80; m.Format.ProbeScore < ts {
|
||||
r5 = errors.Errorf("client1: low score=%v < %v, %v, %v", m.Format.ProbeScore, ts, m.String(), str)
|
||||
}
|
||||
if dv := m.Duration(); dv < duration {
|
||||
if dv := m.Duration(); dv < duration/2 {
|
||||
r6 = errors.Errorf("client1: short duration=%v < %v, %v, %v", dv, duration, m.String(), str)
|
||||
}
|
||||
}
|
||||
|
|
@ -319,7 +319,7 @@ func TestFast_RtmpPublish_RtspPlay_CustomPort(t *testing.T) {
|
|||
if ts := 80; m.Format.ProbeScore < ts {
|
||||
r4 = errors.Errorf("low score=%v < %v, %v, %v", m.Format.ProbeScore, ts, m.String(), str)
|
||||
}
|
||||
if dv := m.Duration(); dv < duration {
|
||||
if dv := m.Duration(); dv < duration/2 {
|
||||
r5 = errors.Errorf("short duration=%v < %v, %v, %v", dv, duration, m.String(), str)
|
||||
}
|
||||
}
|
||||
|
|
@ -406,8 +406,8 @@ func TestFast_RtmpPublish_RtspPlay_AudioOnly(t *testing.T) {
|
|||
r4 = errors.Errorf("expected audio stream, got %v, %v, %v", m.Streams[0].CodecType, m.String(), str)
|
||||
}
|
||||
|
||||
if dv := m.Duration(); dv < duration {
|
||||
if dv := m.Duration(); dv < duration/2 {
|
||||
r5 = errors.Errorf("short duration=%v < %v, %v, %v", dv, duration, m.String(), str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +1,65 @@
|
|||
########################################################
|
||||
FROM ossrs/srs:dev-cache AS centos7-baseline
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off && make
|
||||
|
||||
FROM ossrs/srs:dev-cache AS centos7-no-webrtc
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off --rtc=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off --rtc=off && make
|
||||
|
||||
FROM ossrs/srs:dev-cache AS centos7-no-asm
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off --nasm=off --srtp-nasm=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off --nasm=off --srtp-nasm=off && make
|
||||
|
||||
FROM ossrs/srs:dev-cache AS centos7-all
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=on --gb28181=on --apm=on --h265=on && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=on --gb28181=on --apm=on --h265=on && make
|
||||
|
||||
FROM ossrs/srs:dev-cache AS centos7-ansi-no-ffmpeg
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off --cxx11=off --cxx14=off --ffmpeg-fit=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off --cxx11=off --cxx14=off --ffmpeg-fit=off && make
|
||||
|
||||
########################################################
|
||||
FROM ossrs/srs:ubuntu16-cache AS ubuntu16-baseline
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off && make
|
||||
|
||||
FROM ossrs/srs:ubuntu16-cache AS ubuntu16-all
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=on --gb28181=on && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=on --gb28181=on && make
|
||||
|
||||
########################################################
|
||||
FROM ossrs/srs:ubuntu18-cache AS ubuntu18-baseline
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off && make
|
||||
|
||||
FROM ossrs/srs:ubuntu18-cache AS ubuntu18-all
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=on --gb28181=on && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=on --gb28181=on && make
|
||||
|
||||
########################################################
|
||||
FROM ossrs/srs:ubuntu20-cache AS ubuntu20-baseline
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=off --gb28181=off && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=off --gb28181=off && make
|
||||
|
||||
FROM ossrs/srs:ubuntu20-cache AS ubuntu20-all
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --srt=on --gb28181=on --apm=on --h265=on && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --srt=on --gb28181=on --apm=on --h265=on && make
|
||||
|
||||
########################################################
|
||||
FROM ossrs/srs:ubuntu16-cache-cross-arm AS ubuntu16-cache-cross-armv7
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --cross-build --cross-prefix=arm-linux-gnueabihf- && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --cross-build --cross-prefix=arm-linux-gnueabihf- && make
|
||||
|
||||
FROM ossrs/srs:ubuntu16-cache-cross-aarch64 AS ubuntu16-cache-cross-aarch64
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --cross-build --cross-prefix=aarch64-linux-gnu- && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --cross-build --cross-prefix=aarch64-linux-gnu- && make
|
||||
|
||||
########################################################
|
||||
FROM ossrs/srs:ubuntu20-cache-cross-arm AS ubuntu20-cache-cross-armv7
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --cross-build --cross-prefix=arm-linux-gnueabihf- && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --cross-build --cross-prefix=arm-linux-gnueabihf- && make
|
||||
|
||||
FROM ossrs/srs:ubuntu20-cache-cross-aarch64 AS ubuntu20-cache-cross-aarch64
|
||||
COPY . /srs
|
||||
RUN cd /srs/trunk && ./configure --cross-build --cross-prefix=aarch64-linux-gnu- && make
|
||||
RUN cd /srs/trunk && ./configure --sanitizer=on --cross-build --cross-prefix=aarch64-linux-gnu- && make
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ COPY . /srs
|
|||
WORKDIR /srs/trunk
|
||||
|
||||
# Note that we must enable the gcc7 or link failed.
|
||||
# Enable sanitizer explicitly for coverage testing to catch memory issues.
|
||||
RUN ./configure --rtsp=on --srt=on --gb28181=on --apm=on --h265=on --utest=on --gcov=on --sanitizer=on
|
||||
RUN make utest ${MAKEARGS}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ WORKDIR /srs/trunk
|
|||
# Note that we must enable the gcc7 or link failed.
|
||||
# Please note that we must disable the ffmpeg-opus, as it negatively impacts performance. We may consider
|
||||
# enabling it in the future when support for multi-threading transcoding is available.
|
||||
RUN ./configure --srt=on --gb28181=on --srt=on --rtsp=on --apm=on --utest=on --ffmpeg-opus=off --build-cache=on
|
||||
# Enable sanitizer explicitly for CI/CD testing to catch memory issues.
|
||||
RUN ./configure --srt=on --gb28181=on --srt=on --rtsp=on --apm=on --utest=on --sanitizer=on --ffmpeg-opus=off --build-cache=on
|
||||
RUN make utest ${MAKEARGS}
|
||||
|
||||
# Build benchmark tool.
|
||||
|
|
|
|||
|
|
@ -119,6 +119,12 @@ else
|
|||
srs_undefine_macro "SRS_UTEST" $SRS_AUTO_HEADERS_H
|
||||
fi
|
||||
|
||||
if [[ $SRS_FORCE_PUBLIC4UTEST == YES ]]; then
|
||||
srs_define_macro "SRS_FORCE_PUBLIC4UTEST" $SRS_AUTO_HEADERS_H
|
||||
else
|
||||
srs_undefine_macro "SRS_FORCE_PUBLIC4UTEST" $SRS_AUTO_HEADERS_H
|
||||
fi
|
||||
|
||||
# whatever the FFMPEG tools, if transcode and ingest specified,
|
||||
# srs always compile the FFMPEG tool stub which used to start the FFMPEG process.
|
||||
if [[ $SRS_FFMPEG_STUB == YES ]]; then
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ SRS_CXX14=NO
|
|||
SRS_BACKTRACE=YES
|
||||
SRS_NGINX=NO
|
||||
SRS_UTEST=NO
|
||||
SRS_FORCE_PUBLIC4UTEST=NO
|
||||
# Always enable the bellow features.
|
||||
SRS_STREAM_CASTER=YES
|
||||
SRS_INGEST=YES
|
||||
|
|
@ -551,10 +552,11 @@ function apply_auto_options() {
|
|||
SRS_SHARED_SRTP=YES
|
||||
fi
|
||||
|
||||
# Enable asan, but disable for Centos
|
||||
# Disable sanitizer by default to avoid issues with daemon mode.
|
||||
# Enable sanitizer only for utest and when explicitly requested.
|
||||
# @see https://github.com/ossrs/srs/issues/3347
|
||||
if [[ $SRS_SANITIZER == RESERVED && $OS_IS_CENTOS != YES ]]; then
|
||||
echo "Enable asan by auto options."
|
||||
if [[ $SRS_SANITIZER == RESERVED && $SRS_UTEST == YES ]]; then
|
||||
echo "Enable asan for utest."
|
||||
SRS_SANITIZER=YES
|
||||
fi
|
||||
|
||||
|
|
@ -598,6 +600,13 @@ function apply_auto_options() {
|
|||
SRS_CXX11=NO
|
||||
fi
|
||||
|
||||
# When utest is enabled, automatically enable SRS_FORCE_PUBLIC4UTEST to make private members public
|
||||
# This ensures consistent class layout between production code and utest code with AddressSanitizer
|
||||
if [[ $SRS_UTEST == YES ]]; then
|
||||
echo "Enable SRS_FORCE_PUBLIC4UTEST for utest to make private members public."
|
||||
SRS_FORCE_PUBLIC4UTEST=YES
|
||||
fi
|
||||
|
||||
# Force disable C++14 always - C++98 compatibility is required
|
||||
if [[ $SRS_CXX14 != NO ]]; then
|
||||
echo "Warning: C++14 support has been disabled. Forcing C++98 compatibility mode."
|
||||
|
|
|
|||
|
|
@ -138,14 +138,23 @@ echo "" >> ${FILE}; echo "" >> ${FILE}
|
|||
# Depends, the depends objects
|
||||
echo "# Depends, the depends objects" >> ${FILE}
|
||||
#
|
||||
# current module header files
|
||||
echo -n "SRS_UTEST_DEPS = " >> ${FILE}
|
||||
# current SRS object files
|
||||
echo -n "SRS_SOURCE_OBJS = " >> ${FILE}
|
||||
for item in ${MODULE_OBJS[*]}; do
|
||||
FILE_NAME=${item%.*}
|
||||
echo -n "${SRS_TRUNK_PREFIX}/${SRS_OBJS}/${FILE_NAME}.o " >> ${FILE}
|
||||
done
|
||||
echo "" >> ${FILE}; echo "" >> ${FILE}
|
||||
#
|
||||
# current SRS header files
|
||||
echo -n "SRS_SOURCE_HEADERS = " >> ${FILE}
|
||||
for item in ${MODULE_OBJS[*]}; do
|
||||
FILE_NAME=${item%.*}
|
||||
echo -n "${SRS_TRUNK_PREFIX}/${FILE_NAME}.hpp " >> ${FILE}
|
||||
done
|
||||
echo "" >> ${FILE}; echo "" >> ${FILE}
|
||||
#
|
||||
# current utest header files
|
||||
echo "# Depends, utest header files" >> ${FILE}
|
||||
DEPS_NAME="UTEST_DEPS"
|
||||
echo -n "${DEPS_NAME} = " >> ${FILE}
|
||||
|
|
@ -163,7 +172,7 @@ MODULE_OBJS=()
|
|||
for item in ${MODULE_FILES[*]}; do
|
||||
MODULE_OBJS="${MODULE_OBJS[@]} ${item}.o"
|
||||
cat << END >> ${FILE}
|
||||
${item}.o : \$(${DEPS_NAME}) ${SRS_TRUNK_PREFIX}/${MODULE_DIR}/${item}.cpp \$(SRS_UTEST_DEPS)
|
||||
${item}.o : \$(${DEPS_NAME}) ${SRS_TRUNK_PREFIX}/${MODULE_DIR}/${item}.cpp \$(SRS_SOURCE_HEADERS)
|
||||
\$(CXX) \$(CPPFLAGS) \$(CXXFLAGS) \$(SRS_UTEST_INC) -c ${SRS_TRUNK_PREFIX}/${MODULE_DIR}/${item}.cpp -o \$@
|
||||
END
|
||||
done
|
||||
|
|
@ -186,7 +195,7 @@ echo "" >> ${FILE}; echo "" >> ${FILE}
|
|||
#
|
||||
echo "# generate the utest binary" >> ${FILE}
|
||||
cat << END >> ${FILE}
|
||||
${SRS_TRUNK_PREFIX}/${SRS_OBJS}/${APP_NAME} : \$(SRS_UTEST_DEPS) ${MODULE_OBJS} gtest.a
|
||||
${SRS_TRUNK_PREFIX}/${SRS_OBJS}/${APP_NAME} : \$(SRS_SOURCE_OBJS) ${MODULE_OBJS} gtest.a
|
||||
\$(CXX) -o \$@ \$(CPPFLAGS) \$(CXXFLAGS) \$^ \$(DEPS_LIBRARIES_FILES) ${LINK_OPTIONS}
|
||||
END
|
||||
|
||||
|
|
|
|||
8
trunk/configure
vendored
8
trunk/configure
vendored
|
|
@ -384,11 +384,15 @@ if [[ $SRS_UTEST == YES ]]; then
|
|||
"srs_utest_coworkers" "srs_utest_pithy_print" "srs_utest_kernel3" "srs_utest_protocol4"
|
||||
"srs_utest_protocol3" "srs_utest_app" "srs_utest_app2" "srs_utest_app3" "srs_utest_app4"
|
||||
"srs_utest_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8" "srs_utest_app9"
|
||||
"srs_utest_app10" "srs_utest_app11")
|
||||
"srs_utest_app10" "srs_utest_app11" "srs_utest_app15" "srs_utest_app16"
|
||||
"srs_utest_app17")
|
||||
# Always include SRT utest
|
||||
MODULE_FILES+=("srs_utest_srt")
|
||||
if [[ $SRS_GB28181 == YES ]]; then
|
||||
MODULE_FILES+=("srs_utest_gb28181")
|
||||
MODULE_FILES+=("srs_utest_gb28181" "srs_utest_app14")
|
||||
fi
|
||||
if [[ $SRS_RTSP == YES ]]; then
|
||||
MODULE_FILES+=("srs_utest_app12" "srs_utest_app13")
|
||||
fi
|
||||
ModuleLibIncs=(${SRS_OBJS} ${LibSTRoot} ${LibSSLRoot} ${LibSrtpRoot})
|
||||
if [[ $SRS_FFMPEG_FIT == YES ]]; then
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ The changelog for SRS.
|
|||
<a name="v7-changes"></a>
|
||||
|
||||
## SRS 7.0 Changelog
|
||||
* v7.0, 2025-10-14, Disable sanitizer by default to fix memory leak. (#4364) v7.0.96
|
||||
* v7.0, 2025-10-01, SRT: Support configurable default_streamid option. v7.0.95 (#4515)
|
||||
* v7.0, 2025-09-27, Merge [#4513](https://github.com/ossrs/srs/pull/4513): For Edge, only support RTMP or HTTP-FLV. v7.0.94 (#4513)
|
||||
* v7.0, 2025-09-21, Merge [#4505](https://github.com/ossrs/srs/pull/4505): improve blackbox test for rtsp. v7.0.93 (#4505)
|
||||
|
|
@ -109,6 +110,7 @@ The changelog for SRS.
|
|||
<a name="v6-changes"></a>
|
||||
|
||||
## SRS 6.0 Changelog
|
||||
* v6.0, 2025-10-14, Disable sanitizer by default to fix memory leak. (#4364) v6.0.181
|
||||
* v6.0, 2025-10-01, SRT: Support configurable default_streamid option. v6.0.180 (#4515)
|
||||
* v6.0, 2025-09-27, For Edge, only support RTMP or HTTP-FLV. v6.0.179 (#4512)
|
||||
* v6.0, 2025-09-21, Fix WHIP with transcoding bug. v6.0.178 (#4495)
|
||||
|
|
|
|||
|
|
@ -24,4 +24,5 @@ fi
|
|||
echo "Formatting source files in trunk directory..."
|
||||
# Exclude the 3rdparty directory and format all .cpp, and .hpp
|
||||
# Use -i to edit files in place
|
||||
find trunk/src -name "*.*pp" | xargs clang-format -style=file -i
|
||||
# Use xargs -P N to run N clang-format processes in parallel
|
||||
find trunk/src -name "*.*pp" | xargs -P 16 -n 1 clang-format -style=file -i
|
||||
|
|
|
|||
|
|
@ -53,10 +53,12 @@ public:
|
|||
// That is, the task is execute/call in async mode.
|
||||
class SrsAsyncCallWorker : public ISrsCoroutineHandler, public ISrsAsyncCallWorker
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
std::vector<ISrsAsyncCallTask *> tasks_;
|
||||
srs_cond_t wait_;
|
||||
srs_mutex_t lock_;
|
||||
|
|
@ -76,7 +78,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void flush_tasks();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_conn.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
|
|
@ -26,28 +27,41 @@ using namespace std;
|
|||
|
||||
#define SRS_HTTP_FLV_STREAM_BUFFER 4096
|
||||
|
||||
ISrsHttpFlvListener::ISrsHttpFlvListener()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpFlvListener::~ISrsHttpFlvListener()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpFlvListener::SrsHttpFlvListener()
|
||||
{
|
||||
listener_ = new SrsTcpListener(this);
|
||||
caster_ = new SrsAppCasterFlv();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsHttpFlvListener::~SrsHttpFlvListener()
|
||||
{
|
||||
srs_freep(caster_);
|
||||
srs_freep(listener_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpFlvListener::initialize(SrsConfDirective *c)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
int port = _srs_config->get_stream_caster_listen(c);
|
||||
int port = config_->get_stream_caster_listen(c);
|
||||
if (port <= 0) {
|
||||
return srs_error_new(ERROR_STREAM_CASTER_PORT, "invalid port=%d", port);
|
||||
}
|
||||
|
||||
listener_->set_endpoint(srs_net_address_any(), port)->set_label("PUSH-FLV");
|
||||
listener_->set_endpoint(srs_net_address_any(), port);
|
||||
listener_->set_label("PUSH-FLV");
|
||||
|
||||
if ((err = caster_->initialize(c)) != srs_success) {
|
||||
return srs_error_wrap(err, "init caster port=%d", port);
|
||||
|
|
@ -83,10 +97,20 @@ srs_error_t SrsHttpFlvListener::on_tcp_client(ISrsListener *listener, srs_netfd_
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsAppCasterFlv::ISrsAppCasterFlv()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsAppCasterFlv::~ISrsAppCasterFlv()
|
||||
{
|
||||
}
|
||||
|
||||
SrsAppCasterFlv::SrsAppCasterFlv()
|
||||
{
|
||||
http_mux_ = new SrsHttpServeMux();
|
||||
manager_ = new SrsResourceManager("CFLV");
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsAppCasterFlv::~SrsAppCasterFlv()
|
||||
|
|
@ -99,13 +123,15 @@ SrsAppCasterFlv::~SrsAppCasterFlv()
|
|||
ISrsConnection *conn = *it;
|
||||
srs_freep(conn);
|
||||
}
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsAppCasterFlv::initialize(SrsConfDirective *c)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
output_ = _srs_config->get_stream_caster_output(c);
|
||||
output_ = config_->get_stream_caster_output(c);
|
||||
|
||||
if ((err = http_mux_->handle("/", this)) != srs_success) {
|
||||
return srs_error_wrap(err, "handle root");
|
||||
|
|
@ -126,11 +152,11 @@ srs_error_t SrsAppCasterFlv::on_tcp_client(ISrsListener *listener, srs_netfd_t s
|
|||
string ip = srs_get_peer_ip(fd);
|
||||
int port = srs_get_peer_port(fd);
|
||||
|
||||
if (ip.empty() && !_srs_config->empty_ip_ok()) {
|
||||
if (ip.empty() && !config_->empty_ip_ok()) {
|
||||
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
|
||||
}
|
||||
|
||||
SrsDynamicHttpConn *conn = new SrsDynamicHttpConn(this, stfd, http_mux_, ip, port);
|
||||
ISrsDynamicHttpConn *conn = new SrsDynamicHttpConn(this, stfd, http_mux_, ip, port);
|
||||
conns_.push_back(conn);
|
||||
|
||||
if ((err = conn->start()) != srs_success) {
|
||||
|
|
@ -160,11 +186,41 @@ void SrsAppCasterFlv::add(ISrsResource *conn, bool *exists)
|
|||
manager_->add(conn, exists);
|
||||
}
|
||||
|
||||
void SrsAppCasterFlv::add_with_id(const std::string &id, ISrsResource *conn)
|
||||
{
|
||||
manager_->add_with_id(id, conn);
|
||||
}
|
||||
|
||||
void SrsAppCasterFlv::add_with_fast_id(uint64_t id, ISrsResource *conn)
|
||||
{
|
||||
manager_->add_with_fast_id(id, conn);
|
||||
}
|
||||
|
||||
void SrsAppCasterFlv::add_with_name(const std::string &name, ISrsResource *conn)
|
||||
{
|
||||
manager_->add_with_name(name, conn);
|
||||
}
|
||||
|
||||
ISrsResource *SrsAppCasterFlv::at(int index)
|
||||
{
|
||||
return manager_->at(index);
|
||||
}
|
||||
|
||||
ISrsResource *SrsAppCasterFlv::find_by_id(std::string id)
|
||||
{
|
||||
return manager_->find_by_id(id);
|
||||
}
|
||||
|
||||
ISrsResource *SrsAppCasterFlv::find_by_fast_id(uint64_t id)
|
||||
{
|
||||
return manager_->find_by_fast_id(id);
|
||||
}
|
||||
|
||||
ISrsResource *SrsAppCasterFlv::find_by_name(std::string name)
|
||||
{
|
||||
return manager_->find_by_name(name);
|
||||
}
|
||||
|
||||
void SrsAppCasterFlv::remove(ISrsResource *c)
|
||||
{
|
||||
ISrsConnection *conn = dynamic_cast<ISrsConnection *>(c);
|
||||
|
|
@ -223,6 +279,14 @@ srs_error_t SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsDynamicHttpConn::ISrsDynamicHttpConn()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDynamicHttpConn::~ISrsDynamicHttpConn()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDynamicHttpConn::SrsDynamicHttpConn(ISrsResourceManager *cm, srs_netfd_t fd, SrsHttpServeMux *m, string cip, int cport)
|
||||
{
|
||||
// Create a identify for this client.
|
||||
|
|
@ -236,17 +300,19 @@ SrsDynamicHttpConn::SrsDynamicHttpConn(ISrsResourceManager *cm, srs_netfd_t fd,
|
|||
ip_ = cip;
|
||||
port_ = cport;
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsDynamicHttpConn::~SrsDynamicHttpConn()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
|
||||
srs_freep(conn_);
|
||||
srs_freep(skt_);
|
||||
srs_freep(sdk_);
|
||||
srs_freep(pprint_);
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsDynamicHttpConn::proxy(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string o)
|
||||
|
|
@ -288,7 +354,7 @@ srs_error_t SrsDynamicHttpConn::do_proxy(ISrsHttpResponseReader *rr, SrsFlvDecod
|
|||
|
||||
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk_ = new SrsSimpleRtmpClient(output_, cto, sto);
|
||||
sdk_ = app_factory_->create_rtmp_client(output_, cto, sto);
|
||||
|
||||
if ((err = sdk_->connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "connect %s failed, cto=%dms, sto=%dms.", output_.c_str(), srsu2msi(cto), srsu2msi(sto));
|
||||
|
|
@ -346,12 +412,12 @@ srs_error_t SrsDynamicHttpConn::on_start()
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsDynamicHttpConn::on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w)
|
||||
srs_error_t SrsDynamicHttpConn::on_http_message(ISrsHttpMessage *r, ISrsHttpResponseWriter *w)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsDynamicHttpConn::on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w)
|
||||
srs_error_t SrsDynamicHttpConn::on_message_done(ISrsHttpMessage *r, ISrsHttpResponseWriter *w)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -384,7 +450,7 @@ srs_error_t SrsDynamicHttpConn::start()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
bool v = _srs_config->get_http_stream_crossdomain();
|
||||
bool v = config_->get_http_stream_crossdomain();
|
||||
if ((err = conn_->set_crossdomain_enabled(v)) != srs_success) {
|
||||
return srs_error_wrap(err, "set cors=%d", v);
|
||||
}
|
||||
|
|
@ -392,13 +458,23 @@ srs_error_t SrsDynamicHttpConn::start()
|
|||
return conn_->start();
|
||||
}
|
||||
|
||||
ISrsHttpFileReader::ISrsHttpFileReader()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpFileReader::~ISrsHttpFileReader()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpFileReader::SrsHttpFileReader(ISrsHttpResponseReader *h)
|
||||
{
|
||||
http_ = h;
|
||||
file_reader_ = new SrsFileReader();
|
||||
}
|
||||
|
||||
SrsHttpFileReader::~SrsHttpFileReader()
|
||||
{
|
||||
srs_freep(file_reader_);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpFileReader::open(std::string /*file*/)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,12 @@ class SrsFlvDecoder;
|
|||
class SrsTcpClient;
|
||||
class SrsSimpleRtmpClient;
|
||||
class SrsAppCasterFlv;
|
||||
class ISrsAppCasterFlv;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
class ISrsBasicRtmpClient;
|
||||
class ISrsProtocolReadWriter;
|
||||
class ISrsHttpConn;
|
||||
|
||||
#include <srs_app_http_conn.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
|
|
@ -30,12 +36,27 @@ class SrsAppCasterFlv;
|
|||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_protocol_conn.hpp>
|
||||
|
||||
// A TCP listener, for flv stream server.
|
||||
class SrsHttpFlvListener : public ISrsTcpHandler, public ISrsListener
|
||||
// The http flv listener.
|
||||
class ISrsHttpFlvListener : public ISrsTcpHandler, public ISrsListener
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsHttpFlvListener();
|
||||
virtual ~ISrsHttpFlvListener();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// A TCP listener, for flv stream server.
|
||||
class SrsHttpFlvListener : public ISrsHttpFlvListener
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsTcpListener *listener_;
|
||||
SrsAppCasterFlv *caster_;
|
||||
ISrsAppCasterFlv *caster_;
|
||||
|
||||
public:
|
||||
SrsHttpFlvListener();
|
||||
|
|
@ -50,10 +71,26 @@ public:
|
|||
virtual srs_error_t on_tcp_client(ISrsListener *listener, srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// The stream caster for flv stream over HTTP POST.
|
||||
class SrsAppCasterFlv : public ISrsTcpHandler, public ISrsResourceManager, public ISrsHttpHandler
|
||||
// The http flv caster interface.
|
||||
class ISrsAppCasterFlv : public ISrsTcpHandler, public ISrsResourceManager, public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsAppCasterFlv();
|
||||
virtual ~ISrsAppCasterFlv();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsConfDirective *c) = 0;
|
||||
};
|
||||
|
||||
// The stream caster for flv stream over HTTP POST.
|
||||
class SrsAppCasterFlv : public ISrsAppCasterFlv
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string output_;
|
||||
SrsHttpServeMux *http_mux_;
|
||||
std::vector<ISrsConnection *> conns_;
|
||||
|
|
@ -74,7 +111,13 @@ public:
|
|||
virtual bool empty();
|
||||
virtual size_t size();
|
||||
virtual void add(ISrsResource *conn, bool *exists = NULL);
|
||||
virtual void add_with_id(const std::string &id, ISrsResource *conn);
|
||||
virtual void add_with_fast_id(uint64_t id, ISrsResource *conn);
|
||||
virtual void add_with_name(const std::string &name, ISrsResource *conn);
|
||||
virtual ISrsResource *at(int index);
|
||||
virtual ISrsResource *find_by_id(std::string id);
|
||||
virtual ISrsResource *find_by_fast_id(uint64_t id);
|
||||
virtual ISrsResource *find_by_name(std::string name);
|
||||
virtual void remove(ISrsResource *c);
|
||||
virtual void subscribe(ISrsDisposingHandler *h);
|
||||
virtual void unsubscribe(ISrsDisposingHandler *h);
|
||||
|
|
@ -84,18 +127,35 @@ public:
|
|||
};
|
||||
|
||||
// The dynamic http connection, never drop the body.
|
||||
class SrsDynamicHttpConn : public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner, public ISrsReloadHandler
|
||||
class ISrsDynamicHttpConn : public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsDynamicHttpConn();
|
||||
virtual ~ISrsDynamicHttpConn();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The dynamic http connection, never drop the body.
|
||||
class SrsDynamicHttpConn : public ISrsDynamicHttpConn
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The manager object to manage the connection.
|
||||
ISrsResourceManager *manager_;
|
||||
std::string output_;
|
||||
SrsPithyPrint *pprint_;
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
SrsTcpConnection *skt_;
|
||||
SrsHttpConn *conn_;
|
||||
ISrsBasicRtmpClient *sdk_;
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
ISrsHttpConn *conn_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The ip and port of client.
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
@ -107,14 +167,15 @@ public:
|
|||
public:
|
||||
virtual srs_error_t proxy(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string o);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_proxy(ISrsHttpResponseReader *rr, SrsFlvDecoder *dec);
|
||||
// Extract APIs from SrsTcpConnection.
|
||||
// Interface ISrsHttpConnOwner.
|
||||
public:
|
||||
virtual srs_error_t on_start();
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, ISrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, ISrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_conn_done(srs_error_t r0);
|
||||
// Interface ISrsResource.
|
||||
public:
|
||||
|
|
@ -129,10 +190,22 @@ public:
|
|||
};
|
||||
|
||||
// The http wrapper for file reader, to read http post stream like a file.
|
||||
class SrsHttpFileReader : public SrsFileReader
|
||||
class ISrsHttpFileReader : public ISrsFileReader
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsHttpFileReader();
|
||||
virtual ~ISrsHttpFileReader();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The http wrapper for file reader, to read http post stream like a file.
|
||||
class SrsHttpFileReader : public ISrsHttpFileReader
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpResponseReader *http_;
|
||||
SrsFileReader *file_reader_;
|
||||
|
||||
public:
|
||||
SrsHttpFileReader(ISrsHttpResponseReader *h);
|
||||
|
|
|
|||
|
|
@ -43,27 +43,35 @@ SrsCircuitBreaker::SrsCircuitBreaker()
|
|||
hybrid_high_water_level_ = 0;
|
||||
hybrid_critical_water_level_ = 0;
|
||||
hybrid_dying_water_level_ = 0;
|
||||
|
||||
host_ = new SrsHost();
|
||||
|
||||
config_ = _srs_config;
|
||||
shared_timer_ = _srs_shared_timer;
|
||||
}
|
||||
|
||||
SrsCircuitBreaker::~SrsCircuitBreaker()
|
||||
{
|
||||
srs_freep(host_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsCircuitBreaker::initialize()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
enabled_ = _srs_config->get_circuit_breaker();
|
||||
high_threshold_ = _srs_config->get_high_threshold();
|
||||
high_pulse_ = _srs_config->get_high_pulse();
|
||||
critical_threshold_ = _srs_config->get_critical_threshold();
|
||||
critical_pulse_ = _srs_config->get_critical_pulse();
|
||||
dying_threshold_ = _srs_config->get_dying_threshold();
|
||||
dying_pulse_ = _srs_config->get_dying_pulse();
|
||||
enabled_ = config_->get_circuit_breaker();
|
||||
high_threshold_ = config_->get_high_threshold();
|
||||
high_pulse_ = config_->get_high_pulse();
|
||||
critical_threshold_ = config_->get_critical_threshold();
|
||||
critical_pulse_ = config_->get_critical_pulse();
|
||||
dying_threshold_ = config_->get_dying_threshold();
|
||||
dying_pulse_ = config_->get_dying_pulse();
|
||||
|
||||
// Update the water level for circuit breaker.
|
||||
// @see SrsCircuitBreaker::on_timer()
|
||||
_srs_shared_timer->timer1s()->subscribe(this);
|
||||
shared_timer_->timer1s()->subscribe(this);
|
||||
|
||||
srs_trace("CircuitBreaker: enabled=%d, high=%dx%d, critical=%dx%d, dying=%dx%d", enabled_,
|
||||
high_pulse_, high_threshold_, critical_pulse_, critical_threshold_,
|
||||
|
|
@ -93,7 +101,7 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
|
|||
|
||||
// Update the CPU usage.
|
||||
srs_update_proc_stat();
|
||||
SrsProcSelfStat *stat = srs_get_self_proc_stat();
|
||||
SrsProcSelfStat *stat = host_->self_proc_stat();
|
||||
|
||||
// Reset the high water-level when CPU is low for N times.
|
||||
if (stat->percent_ * 100 > high_threshold_) {
|
||||
|
|
@ -117,7 +125,7 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
|
|||
}
|
||||
|
||||
// Show statistics for RTC server.
|
||||
SrsProcSelfStat *u = srs_get_self_proc_stat();
|
||||
SrsProcSelfStat *u = host_->self_proc_stat();
|
||||
// Resident Set Size: number of pages the process has in real memory.
|
||||
int memory = (int)(u->rss_ * 4 / 1024);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
|
||||
class ISrsAppConfig;
|
||||
class ISrsSharedTimer;
|
||||
class ISrsHost;
|
||||
|
||||
// Interface for circuit breaker functionality to protect server in high load conditions.
|
||||
// The circuit breaker monitors CPU usage and enables different levels of protection:
|
||||
// - High water level: Disables some unnecessary features to reduce CPU load
|
||||
|
|
@ -48,7 +52,14 @@ public:
|
|||
|
||||
class SrsCircuitBreaker : public ISrsCircuitBreaker, public ISrsFastTimerHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsSharedTimer *shared_timer_;
|
||||
ISrsHost *host_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool enabled_;
|
||||
int high_threshold_;
|
||||
int high_pulse_;
|
||||
|
|
@ -57,7 +68,8 @@ private:
|
|||
int dying_threshold_;
|
||||
int dying_pulse_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int hybrid_high_water_level_;
|
||||
int hybrid_critical_water_level_;
|
||||
int hybrid_dying_water_level_;
|
||||
|
|
@ -74,7 +86,8 @@ public:
|
|||
bool hybrid_critical_water_level();
|
||||
bool hybrid_dying_water_level();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1878,13 +1878,6 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
|
||||
srs_trace("srs checking config...");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// check empty
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
if (!env_only_ && root_->directives_.size() == 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "conf is empty");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// check root directives.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -2010,9 +2003,6 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
if (true) {
|
||||
vector<string> listens = get_listens();
|
||||
if (!env_only_ && listens.size() <= 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "listen requires params");
|
||||
}
|
||||
for (int i = 0; i < (int)listens.size(); i++) {
|
||||
if (!srs_net_is_valid_endpoint(listens[i])) {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "rtmp.listen=%s is invalid", listens[i].c_str());
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ namespace srs_internal
|
|||
// The buffer of config content.
|
||||
class SrsConfigBuffer
|
||||
{
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The last available position.
|
||||
char *last_;
|
||||
// The end of buffer.
|
||||
|
|
@ -228,7 +229,8 @@ public:
|
|||
virtual SrsJsonAny *dumps_arg0_to_number();
|
||||
virtual SrsJsonAny *dumps_arg0_to_boolean();
|
||||
// private parse.
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The directive parsing context.
|
||||
enum SrsDirectiveContext {
|
||||
// The root directives, parsing file.
|
||||
|
|
@ -288,6 +290,8 @@ public:
|
|||
virtual srs_error_t persistence() = 0;
|
||||
virtual std::string config() = 0;
|
||||
virtual SrsConfDirective *get_root() = 0;
|
||||
// Get the current work directory.
|
||||
virtual std::string cwd() = 0;
|
||||
|
||||
public:
|
||||
// Global server config
|
||||
|
|
@ -315,6 +319,22 @@ public:
|
|||
virtual std::vector<std::string> get_https_api_listens() = 0;
|
||||
virtual std::string get_https_api_ssl_key() = 0;
|
||||
virtual std::string get_https_api_ssl_cert() = 0;
|
||||
// Whether enable the HTTP RAW API.
|
||||
virtual bool get_raw_api() = 0;
|
||||
// Whether allow rpc reload.
|
||||
virtual bool get_raw_api_allow_reload() = 0;
|
||||
// Whether allow rpc query.
|
||||
virtual bool get_raw_api_allow_query() = 0;
|
||||
// Whether allow rpc update.
|
||||
virtual bool get_raw_api_allow_update() = 0;
|
||||
// Whether http api auth enabled.
|
||||
virtual bool get_http_api_auth_enabled() = 0;
|
||||
// Get the http api auth username.
|
||||
virtual std::string get_http_api_auth_username() = 0;
|
||||
// Get the http api auth password.
|
||||
virtual std::string get_http_api_auth_password() = 0;
|
||||
// Dumps the http_api sections to json for raw api info.
|
||||
virtual srs_error_t raw_to_json(SrsJsonObject *obj) = 0;
|
||||
|
||||
public:
|
||||
// HTTP Server config
|
||||
|
|
@ -325,6 +345,7 @@ public:
|
|||
virtual std::string get_https_stream_ssl_key() = 0;
|
||||
virtual std::string get_https_stream_ssl_cert() = 0;
|
||||
virtual std::string get_http_stream_dir() = 0;
|
||||
virtual bool get_http_stream_crossdomain() = 0;
|
||||
|
||||
public:
|
||||
// WebRTC config
|
||||
|
|
@ -334,6 +355,13 @@ public:
|
|||
virtual std::string get_rtc_server_protocol() = 0;
|
||||
virtual std::vector<std::string> get_rtc_server_listens() = 0;
|
||||
virtual int get_rtc_server_reuseport() = 0;
|
||||
virtual bool get_rtc_server_encrypt() = 0;
|
||||
virtual bool get_api_as_candidates() = 0;
|
||||
virtual bool get_resolve_api_domain() = 0;
|
||||
virtual bool get_keep_api_domain() = 0;
|
||||
virtual std::string get_rtc_server_candidates() = 0;
|
||||
virtual bool get_use_auto_detect_network_ip() = 0;
|
||||
virtual std::string get_rtc_server_ip_family() = 0;
|
||||
|
||||
public:
|
||||
// RTSP config
|
||||
|
|
@ -349,11 +377,15 @@ public:
|
|||
virtual std::vector<SrsConfDirective *> get_stream_casters() = 0;
|
||||
virtual bool get_stream_caster_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_stream_caster_engine(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_stream_caster_output(SrsConfDirective *conf) = 0;
|
||||
virtual int get_stream_caster_listen(SrsConfDirective *conf) = 0;
|
||||
|
||||
public:
|
||||
// Exporter config
|
||||
virtual bool get_exporter_enabled() = 0;
|
||||
virtual std::string get_exporter_listen() = 0;
|
||||
virtual std::string get_exporter_label() = 0;
|
||||
virtual std::string get_exporter_tag() = 0;
|
||||
|
||||
public:
|
||||
// Stats config
|
||||
|
|
@ -364,6 +396,20 @@ public:
|
|||
// Heartbeat config
|
||||
virtual bool get_heartbeat_enabled() = 0;
|
||||
virtual srs_utime_t get_heartbeat_interval() = 0;
|
||||
virtual std::string get_heartbeat_url() = 0;
|
||||
virtual std::string get_heartbeat_device_id() = 0;
|
||||
virtual bool get_heartbeat_summaries() = 0;
|
||||
virtual bool get_heartbeat_ports() = 0;
|
||||
|
||||
public:
|
||||
// Circuit breaker config
|
||||
virtual bool get_circuit_breaker() = 0;
|
||||
virtual int get_high_threshold() = 0;
|
||||
virtual int get_high_pulse() = 0;
|
||||
virtual int get_critical_threshold() = 0;
|
||||
virtual int get_critical_pulse() = 0;
|
||||
virtual int get_dying_threshold() = 0;
|
||||
virtual int get_dying_pulse() = 0;
|
||||
|
||||
public:
|
||||
// RTMPS config
|
||||
|
|
@ -372,6 +418,7 @@ public:
|
|||
|
||||
public:
|
||||
// Vhost config
|
||||
virtual void get_vhosts(std::vector<SrsConfDirective *> &vhosts) = 0;
|
||||
virtual SrsConfDirective *get_vhost(std::string vhost, bool try_default_vhost = true) = 0;
|
||||
virtual bool get_vhost_enabled(std::string vhost) = 0;
|
||||
virtual bool get_vhost_enabled(SrsConfDirective *conf) = 0;
|
||||
|
|
@ -436,9 +483,13 @@ public:
|
|||
virtual bool get_rtc_twcc_enabled(std::string vhost) = 0;
|
||||
virtual bool get_srt_enabled() = 0;
|
||||
virtual bool get_srt_enabled(std::string vhost) = 0;
|
||||
virtual std::string get_srt_default_streamid() = 0;
|
||||
virtual bool get_srt_to_rtmp(std::string vhost) = 0;
|
||||
virtual bool get_rtc_to_rtmp(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_rtc_stun_timeout(std::string vhost) = 0;
|
||||
virtual bool get_rtc_stun_strict_check(std::string vhost) = 0;
|
||||
virtual std::string get_rtc_dtls_role(std::string vhost) = 0;
|
||||
virtual std::string get_rtc_dtls_version(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_vhost_on_hls(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_vhost_on_hls_notify(std::string vhost) = 0;
|
||||
virtual bool get_hls_enabled(std::string vhost) = 0;
|
||||
|
|
@ -469,6 +520,16 @@ public:
|
|||
virtual bool get_hls_ctx_enabled(std::string vhost) = 0;
|
||||
virtual bool get_hls_ts_ctx_enabled(std::string vhost) = 0;
|
||||
virtual bool get_hls_recover(std::string vhost) = 0;
|
||||
virtual bool get_dash_enabled(std::string vhost) = 0;
|
||||
virtual bool get_dash_enabled(SrsConfDirective *vhost) = 0;
|
||||
virtual srs_utime_t get_dash_fragment(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_dash_update_period(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_dash_timeshift(std::string vhost) = 0;
|
||||
virtual std::string get_dash_path(std::string vhost) = 0;
|
||||
virtual std::string get_dash_mpd_file(std::string vhost) = 0;
|
||||
virtual int get_dash_window_size(std::string vhost) = 0;
|
||||
virtual bool get_dash_cleanup(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_dash_dispose(std::string vhost) = 0;
|
||||
virtual bool get_forward_enabled(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_forwards(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_queue_length(std::string vhost) = 0;
|
||||
|
|
@ -482,6 +543,12 @@ public:
|
|||
virtual bool get_reduce_sequence_header(std::string vhost) = 0;
|
||||
virtual bool get_parse_sps(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
// DVR config
|
||||
virtual std::string get_dvr_path(std::string vhost) = 0;
|
||||
virtual int get_dvr_time_jitter(std::string vhost) = 0;
|
||||
virtual bool get_dvr_wait_keyframe(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
// HTTP remux config
|
||||
virtual bool get_vhost_http_remux_enabled(std::string vhost) = 0;
|
||||
|
|
@ -492,6 +559,63 @@ public:
|
|||
virtual bool get_vhost_http_remux_has_video(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_guess_has_av(std::string vhost) = 0;
|
||||
virtual std::string get_vhost_http_remux_mount(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
virtual std::string get_vhost_edge_protocol(std::string vhost) = 0;
|
||||
virtual bool get_vhost_edge_follow_client(std::string vhost) = 0;
|
||||
virtual std::string get_vhost_edge_transform_vhost(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_vhost_on_dvr(std::string vhost) = 0;
|
||||
virtual std::string get_dvr_plan(std::string vhost) = 0;
|
||||
virtual bool get_dvr_enabled(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_dvr_apply(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_dvr_duration(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
// Exec config
|
||||
virtual bool get_exec_enabled(std::string vhost) = 0;
|
||||
virtual std::vector<SrsConfDirective *> get_exec_publishs(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
// Ingest config
|
||||
virtual std::vector<SrsConfDirective *> get_ingesters(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_ingest_by_id(std::string vhost, std::string ingest_id) = 0;
|
||||
virtual bool get_ingest_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_ingest_ffmpeg(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_ingest_input_type(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_ingest_input_url(SrsConfDirective *conf) = 0;
|
||||
|
||||
public:
|
||||
// FFmpeg log config
|
||||
virtual bool get_ff_log_enabled() = 0;
|
||||
virtual std::string get_ff_log_dir() = 0;
|
||||
virtual std::string get_ff_log_level() = 0;
|
||||
|
||||
public:
|
||||
// Transcode/Engine config
|
||||
virtual SrsConfDirective *get_transcode(std::string vhost, std::string scope) = 0;
|
||||
virtual bool get_transcode_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_transcode_ffmpeg(SrsConfDirective *conf) = 0;
|
||||
virtual std::vector<SrsConfDirective *> get_transcode_engines(SrsConfDirective *conf) = 0;
|
||||
virtual bool get_engine_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual std::vector<std::string> get_engine_perfile(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_iformat(SrsConfDirective *conf) = 0;
|
||||
virtual std::vector<std::string> get_engine_vfilter(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_vcodec(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_vbitrate(SrsConfDirective *conf) = 0;
|
||||
virtual double get_engine_vfps(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_vwidth(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_vheight(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_vthreads(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_vprofile(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_vpreset(SrsConfDirective *conf) = 0;
|
||||
virtual std::vector<std::string> get_engine_vparams(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_acodec(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_abitrate(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_asample_rate(SrsConfDirective *conf) = 0;
|
||||
virtual int get_engine_achannels(SrsConfDirective *conf) = 0;
|
||||
virtual std::vector<std::string> get_engine_aparams(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_oformat(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_engine_output(SrsConfDirective *conf) = 0;
|
||||
};
|
||||
|
||||
// The config service provider.
|
||||
|
|
@ -503,7 +627,8 @@ class SrsConfig : public ISrsAppConfig
|
|||
{
|
||||
friend class SrsConfDirective;
|
||||
// user command
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether show help and exit.
|
||||
bool show_help_;
|
||||
// Whether test config file and exit.
|
||||
|
|
@ -516,29 +641,35 @@ private:
|
|||
// Set it by argv "-e" or env "SRS_ENV_ONLY=on".
|
||||
bool env_only_;
|
||||
// global env variables.
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The user parameters, the argc and argv.
|
||||
// The argv is " ".join(argv), where argv is from main(argc, argv).
|
||||
std::string argv_;
|
||||
// current working directory.
|
||||
std::string cwd_;
|
||||
// Config section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The last parsed config file.
|
||||
// If reload, reload the config file.
|
||||
std::string config_file_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The directive root.
|
||||
SrsConfDirective *root_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The cache for parsing the config from environment variables.
|
||||
SrsConfDirective *env_cache_;
|
||||
// Reload section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The reload subscribers, when reload, callback all handlers.
|
||||
std::vector<ISrsReloadHandler *> subscribes_;
|
||||
std::vector<ISrsReloadHandler *>
|
||||
subscribes_;
|
||||
|
||||
public:
|
||||
SrsConfig();
|
||||
|
|
@ -554,37 +685,46 @@ public:
|
|||
// @remark, user can test the config before reload it.
|
||||
virtual srs_error_t reload(SrsReloadState *pstate);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// Reload from the config.
|
||||
// @remark, use protected for the utest to override with mock.
|
||||
virtual srs_error_t reload_conf(SrsConfig *conf);
|
||||
virtual srs_error_t
|
||||
reload_conf(SrsConfig *conf);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Parse options and file
|
||||
public:
|
||||
// Parse the cli, the main(argc,argv) function.
|
||||
virtual srs_error_t parse_options(int argc, char **argv);
|
||||
virtual srs_error_t
|
||||
parse_options(int argc, char **argv);
|
||||
// initialize the cwd for server,
|
||||
// because we may change the workdir.
|
||||
virtual srs_error_t initialize_cwd();
|
||||
// Marshal current config to file.
|
||||
virtual srs_error_t persistence();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_persistence(SrsFileWriter *fw);
|
||||
|
||||
public:
|
||||
// Dumps the http_api sections to json for raw api info.
|
||||
virtual srs_error_t raw_to_json(SrsJsonObject *obj);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
public:
|
||||
// Get the config file path.
|
||||
virtual std::string config();
|
||||
virtual std::string
|
||||
config();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Parse each argv.
|
||||
virtual srs_error_t parse_argv(int &i, char **argv);
|
||||
virtual srs_error_t
|
||||
parse_argv(int &i, char **argv);
|
||||
// Print help and exit.
|
||||
virtual void print_help(char **argv);
|
||||
|
||||
|
|
@ -592,23 +732,28 @@ public:
|
|||
// Parse the config file, which is specified by cli.
|
||||
virtual srs_error_t parse_file(const char *filename);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Build a buffer from a src, which is string content or filename.
|
||||
virtual srs_error_t build_buffer(std::string src, srs_internal::SrsConfigBuffer **pbuffer);
|
||||
virtual srs_error_t
|
||||
build_buffer(std::string src, srs_internal::SrsConfigBuffer **pbuffer);
|
||||
|
||||
public:
|
||||
// Check the parsed config.
|
||||
virtual srs_error_t check_config();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t check_normal_config();
|
||||
virtual srs_error_t check_number_connections();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// Parse config from the buffer.
|
||||
// @param buffer, the config buffer, user must delete it.
|
||||
// @remark, use protected for the utest to override with mock.
|
||||
virtual srs_error_t parse_buffer(srs_internal::SrsConfigBuffer *buffer);
|
||||
virtual srs_error_t
|
||||
parse_buffer(srs_internal::SrsConfigBuffer *buffer);
|
||||
// global env
|
||||
public:
|
||||
// Get the current work directory.
|
||||
|
|
@ -628,9 +773,11 @@ public:
|
|||
// Whether srs in docker.
|
||||
virtual bool get_in_docker();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether user use full.conf
|
||||
virtual bool is_full_config();
|
||||
virtual bool
|
||||
is_full_config();
|
||||
|
||||
public:
|
||||
// Get the server id, generated a random one if not configured.
|
||||
|
|
@ -742,7 +889,8 @@ public:
|
|||
virtual bool get_rtc_server_black_hole();
|
||||
virtual std::string get_rtc_server_black_hole_addr();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual int get_rtc_server_reuseport2();
|
||||
|
||||
public:
|
||||
|
|
@ -872,9 +1020,11 @@ public:
|
|||
virtual srs_utime_t get_publish_kickoff_for_idle(std::string vhost);
|
||||
virtual srs_utime_t get_publish_kickoff_for_idle(SrsConfDirective *vhost);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the global chunk size.
|
||||
virtual int get_global_chunk_size();
|
||||
virtual int
|
||||
get_global_chunk_size();
|
||||
// forward section
|
||||
public:
|
||||
// Whether the forwarder enabled.
|
||||
|
|
@ -925,7 +1075,8 @@ public:
|
|||
// Get the default streamid when client doesn't provide one.
|
||||
virtual std::string get_srt_default_streamid();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *get_srt(std::string vhost);
|
||||
|
||||
public:
|
||||
|
|
@ -934,9 +1085,11 @@ public:
|
|||
bool get_srt_to_rtmp(std::string vhost);
|
||||
|
||||
// http_hooks section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the http_hooks directive of vhost.
|
||||
virtual SrsConfDirective *get_vhost_http_hooks(std::string vhost);
|
||||
virtual SrsConfDirective *
|
||||
get_vhost_http_hooks(std::string vhost);
|
||||
|
||||
public:
|
||||
// Whether vhost http-hooks enabled.
|
||||
|
|
@ -1082,9 +1235,11 @@ public:
|
|||
// @remark, we will use some variable, for instance, [vhost] to substitude with vhost.
|
||||
virtual std::string get_engine_output(SrsConfDirective *conf);
|
||||
// vhost exec secion
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the exec directive of vhost.
|
||||
virtual SrsConfDirective *get_exec(std::string vhost);
|
||||
virtual SrsConfDirective *
|
||||
get_exec(std::string vhost);
|
||||
|
||||
public:
|
||||
// Whether the exec is enabled of vhost.
|
||||
|
|
@ -1123,7 +1278,8 @@ public:
|
|||
// The ffmpeg log level.
|
||||
virtual std::string get_ff_log_level();
|
||||
// The MPEG-DASH section.
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual SrsConfDirective *get_dash(std::string vhost);
|
||||
|
||||
public:
|
||||
|
|
@ -1147,9 +1303,11 @@ public:
|
|||
// The timeout in srs_utime_t to dispose the dash.
|
||||
virtual srs_utime_t get_dash_dispose(std::string vhost);
|
||||
// hls section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the hls directive of vhost.
|
||||
virtual SrsConfDirective *get_hls(std::string vhost);
|
||||
virtual SrsConfDirective *
|
||||
get_hls(std::string vhost);
|
||||
|
||||
public:
|
||||
// Whether HLS is enabled.
|
||||
|
|
@ -1216,9 +1374,11 @@ public:
|
|||
// Old fragments are kept. Default is on.
|
||||
virtual bool get_hls_recover(std::string vhost);
|
||||
// hds section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the hds directive of vhost.
|
||||
virtual SrsConfDirective *get_hds(const std::string &vhost);
|
||||
virtual SrsConfDirective *
|
||||
get_hds(const std::string &vhost);
|
||||
|
||||
public:
|
||||
// Whether HDS is enabled.
|
||||
|
|
@ -1232,9 +1392,11 @@ public:
|
|||
// a window is a set of hds fragments.
|
||||
virtual srs_utime_t get_hds_window(const std::string &vhost);
|
||||
// dvr section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the dvr directive.
|
||||
virtual SrsConfDirective *get_dvr(std::string vhost);
|
||||
virtual SrsConfDirective *
|
||||
get_dvr(std::string vhost);
|
||||
|
||||
public:
|
||||
// Whether dvr is enabled.
|
||||
|
|
@ -1254,9 +1416,11 @@ public:
|
|||
// Get the time_jitter algorithm for dvr.
|
||||
virtual int get_dvr_time_jitter(std::string vhost);
|
||||
// http api section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether http api enabled
|
||||
virtual bool get_http_api_enabled(SrsConfDirective *conf);
|
||||
virtual bool
|
||||
get_http_api_enabled(SrsConfDirective *conf);
|
||||
|
||||
public:
|
||||
// Whether http api enabled.
|
||||
|
|
@ -1280,7 +1444,8 @@ public:
|
|||
// Get the http api auth password.
|
||||
virtual std::string get_http_api_auth_password();
|
||||
// https api section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *get_https_api();
|
||||
|
||||
public:
|
||||
|
|
@ -1289,9 +1454,11 @@ public:
|
|||
virtual std::string get_https_api_ssl_key();
|
||||
virtual std::string get_https_api_ssl_cert();
|
||||
// http stream section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether http stream enabled.
|
||||
virtual bool get_http_stream_enabled(SrsConfDirective *conf);
|
||||
virtual bool
|
||||
get_http_stream_enabled(SrsConfDirective *conf);
|
||||
|
||||
public:
|
||||
// Whether http stream enabled.
|
||||
|
|
@ -1303,7 +1470,8 @@ public:
|
|||
// Whether enable crossdomain for http static and stream server.
|
||||
virtual bool get_http_stream_crossdomain();
|
||||
// https api section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *get_https_stream();
|
||||
|
||||
public:
|
||||
|
|
@ -1313,7 +1481,8 @@ public:
|
|||
virtual std::string get_https_stream_ssl_key();
|
||||
virtual std::string get_https_stream_ssl_cert();
|
||||
// rtmps section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *get_rtmps();
|
||||
|
||||
public:
|
||||
|
|
@ -1350,9 +1519,11 @@ public:
|
|||
// used to generate the flv stream mount path.
|
||||
virtual std::string get_vhost_http_remux_mount(std::string vhost);
|
||||
// http heartbeat section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the heartbeat directive.
|
||||
virtual SrsConfDirective *get_heartbeat();
|
||||
virtual SrsConfDirective *
|
||||
get_heartbeat();
|
||||
|
||||
public:
|
||||
// Whether heartbeat enabled.
|
||||
|
|
@ -1365,11 +1536,13 @@ public:
|
|||
virtual std::string get_heartbeat_device_id();
|
||||
// Whether report with summaries of http api: /api/v1/summaries.
|
||||
virtual bool get_heartbeat_summaries();
|
||||
bool get_heartbeat_ports();
|
||||
virtual bool get_heartbeat_ports();
|
||||
// stats section
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Get the stats directive.
|
||||
virtual SrsConfDirective *get_stats();
|
||||
virtual SrsConfDirective *
|
||||
get_stats();
|
||||
|
||||
public:
|
||||
// Whether enabled stats.
|
||||
|
|
|
|||
|
|
@ -19,13 +19,16 @@ class SrsLiveSource;
|
|||
// For origin cluster.
|
||||
class SrsCoWorkers
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
static SrsCoWorkers *instance_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::map<std::string, ISrsRequest *> streams_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsCoWorkers();
|
||||
virtual ~SrsCoWorkers();
|
||||
|
||||
|
|
@ -35,7 +38,8 @@ public:
|
|||
public:
|
||||
virtual SrsJsonAny *dumps(std::string vhost, std::string coworker, std::string app, std::string stream);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual ISrsRequest *find_stream_info(std::string vhost, std::string app, std::string stream);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <srs_app_dash.hpp>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
|
|
@ -35,23 +36,33 @@ string srs_time_to_utc_format_str(srs_utime_t u)
|
|||
return std::string(print_buf, ret);
|
||||
}
|
||||
|
||||
ISrsInitMp4::ISrsInitMp4()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsInitMp4::~ISrsInitMp4()
|
||||
{
|
||||
}
|
||||
|
||||
SrsInitMp4::SrsInitMp4()
|
||||
{
|
||||
fw_ = new SrsFileWriter();
|
||||
init_ = new SrsMp4M2tsInitEncoder();
|
||||
fragment_ = new SrsFragment();
|
||||
}
|
||||
|
||||
SrsInitMp4::~SrsInitMp4()
|
||||
{
|
||||
srs_freep(init_);
|
||||
srs_freep(fw_);
|
||||
srs_freep(fragment_);
|
||||
}
|
||||
|
||||
srs_error_t SrsInitMp4::write(SrsFormat *format, bool video, int tid)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
string path_tmp = tmppath();
|
||||
string path_tmp = fragment_->tmppath();
|
||||
if ((err = fw_->open(path_tmp)) != srs_success) {
|
||||
return srs_error_wrap(err, "Open init mp4 failed, path=%s", path_tmp.c_str());
|
||||
}
|
||||
|
|
@ -67,19 +78,88 @@ srs_error_t SrsInitMp4::write(SrsFormat *format, bool video, int tid)
|
|||
return err;
|
||||
}
|
||||
|
||||
void SrsInitMp4::set_path(std::string v)
|
||||
{
|
||||
fragment_->set_path(v);
|
||||
}
|
||||
|
||||
std::string SrsInitMp4::tmppath()
|
||||
{
|
||||
return fragment_->tmppath();
|
||||
}
|
||||
|
||||
srs_error_t SrsInitMp4::rename()
|
||||
{
|
||||
return fragment_->rename();
|
||||
}
|
||||
|
||||
void SrsInitMp4::append(int64_t dts)
|
||||
{
|
||||
fragment_->append(dts);
|
||||
}
|
||||
|
||||
srs_error_t SrsInitMp4::create_dir()
|
||||
{
|
||||
return fragment_->create_dir();
|
||||
}
|
||||
|
||||
void SrsInitMp4::set_number(uint64_t n)
|
||||
{
|
||||
fragment_->set_number(n);
|
||||
}
|
||||
|
||||
uint64_t SrsInitMp4::number()
|
||||
{
|
||||
return fragment_->number();
|
||||
}
|
||||
|
||||
srs_utime_t SrsInitMp4::duration()
|
||||
{
|
||||
return fragment_->duration();
|
||||
}
|
||||
|
||||
srs_error_t SrsInitMp4::unlink_tmpfile()
|
||||
{
|
||||
return fragment_->unlink_tmpfile();
|
||||
}
|
||||
|
||||
srs_utime_t SrsInitMp4::get_start_dts()
|
||||
{
|
||||
return fragment_->get_start_dts();
|
||||
}
|
||||
|
||||
srs_error_t SrsInitMp4::unlink_file()
|
||||
{
|
||||
return fragment_->unlink_file();
|
||||
}
|
||||
|
||||
ISrsFragmentedMp4::ISrsFragmentedMp4()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFragmentedMp4::~ISrsFragmentedMp4()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFragmentedMp4::SrsFragmentedMp4()
|
||||
{
|
||||
fw_ = new SrsFileWriter();
|
||||
enc_ = new SrsMp4M2tsSegmentEncoder();
|
||||
fragment_ = new SrsFragment();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsFragmentedMp4::~SrsFragmentedMp4()
|
||||
{
|
||||
srs_freep(enc_);
|
||||
srs_freep(fw_);
|
||||
srs_freep(fragment_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsFragmentedMp4::initialize(ISrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid)
|
||||
srs_error_t SrsFragmentedMp4::initialize(ISrsRequest *r, bool video, int64_t time, ISrsMpdWriter *mpd, uint32_t tid)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -91,16 +171,16 @@ srs_error_t SrsFragmentedMp4::initialize(ISrsRequest *r, bool video, int64_t tim
|
|||
(uint32_t)sequence_number, file_home.c_str(), file_name.c_str());
|
||||
}
|
||||
|
||||
string home = _srs_config->get_dash_path(r->vhost_);
|
||||
set_path(home + "/" + file_home + "/" + file_name);
|
||||
string home = config_->get_dash_path(r->vhost_);
|
||||
fragment_->set_path(home + "/" + file_home + "/" + file_name);
|
||||
// Set number of the fragment, use in mpd SegmentTemplate@startNumber later.
|
||||
set_number(sequence_number);
|
||||
fragment_->set_number(sequence_number);
|
||||
|
||||
if ((err = create_dir()) != srs_success) {
|
||||
if ((err = fragment_->create_dir()) != srs_success) {
|
||||
return srs_error_wrap(err, "create dir");
|
||||
}
|
||||
|
||||
string path_tmp = tmppath();
|
||||
string path_tmp = fragment_->tmppath();
|
||||
if ((err = fw_->open(path_tmp)) != srs_success) {
|
||||
return srs_error_wrap(err, "Open fmp4 failed, path=%s", path_tmp.c_str());
|
||||
}
|
||||
|
|
@ -136,7 +216,7 @@ srs_error_t SrsFragmentedMp4::write(SrsMediaPacket *shared_msg, SrsFormat *forma
|
|||
return err;
|
||||
}
|
||||
|
||||
append(shared_msg->timestamp_);
|
||||
fragment_->append(shared_msg->timestamp_);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -151,13 +231,76 @@ srs_error_t SrsFragmentedMp4::reap(uint64_t &dts)
|
|||
|
||||
srs_freep(fw_);
|
||||
|
||||
if ((err = rename()) != srs_success) {
|
||||
if ((err = fragment_->rename()) != srs_success) {
|
||||
return srs_error_wrap(err, "rename");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsFragmentedMp4::set_path(std::string v)
|
||||
{
|
||||
fragment_->set_path(v);
|
||||
}
|
||||
|
||||
std::string SrsFragmentedMp4::tmppath()
|
||||
{
|
||||
return fragment_->tmppath();
|
||||
}
|
||||
|
||||
srs_error_t SrsFragmentedMp4::rename()
|
||||
{
|
||||
return fragment_->rename();
|
||||
}
|
||||
|
||||
void SrsFragmentedMp4::append(int64_t dts)
|
||||
{
|
||||
fragment_->append(dts);
|
||||
}
|
||||
|
||||
srs_error_t SrsFragmentedMp4::create_dir()
|
||||
{
|
||||
return fragment_->create_dir();
|
||||
}
|
||||
|
||||
void SrsFragmentedMp4::set_number(uint64_t n)
|
||||
{
|
||||
fragment_->set_number(n);
|
||||
}
|
||||
|
||||
srs_utime_t SrsFragmentedMp4::duration()
|
||||
{
|
||||
return fragment_->duration();
|
||||
}
|
||||
|
||||
srs_error_t SrsFragmentedMp4::unlink_tmpfile()
|
||||
{
|
||||
return fragment_->unlink_tmpfile();
|
||||
}
|
||||
|
||||
uint64_t SrsFragmentedMp4::number()
|
||||
{
|
||||
return fragment_->number();
|
||||
}
|
||||
|
||||
srs_utime_t SrsFragmentedMp4::get_start_dts()
|
||||
{
|
||||
return fragment_->get_start_dts();
|
||||
}
|
||||
|
||||
srs_error_t SrsFragmentedMp4::unlink_file()
|
||||
{
|
||||
return fragment_->unlink_file();
|
||||
}
|
||||
|
||||
ISrsMpdWriter::ISrsMpdWriter()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMpdWriter::~ISrsMpdWriter()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpdWriter::SrsMpdWriter()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
@ -168,10 +311,15 @@ SrsMpdWriter::SrsMpdWriter()
|
|||
|
||||
video_number_ = 0;
|
||||
audio_number_ = 0;
|
||||
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsMpdWriter::~SrsMpdWriter()
|
||||
{
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
void SrsMpdWriter::dispose()
|
||||
|
|
@ -204,16 +352,16 @@ srs_error_t SrsMpdWriter::on_publish()
|
|||
{
|
||||
ISrsRequest *r = req_;
|
||||
|
||||
fragment_ = _srs_config->get_dash_fragment(r->vhost_);
|
||||
update_period_ = _srs_config->get_dash_update_period(r->vhost_);
|
||||
timeshit_ = _srs_config->get_dash_timeshift(r->vhost_);
|
||||
home_ = _srs_config->get_dash_path(r->vhost_);
|
||||
mpd_file_ = _srs_config->get_dash_mpd_file(r->vhost_);
|
||||
fragment_ = config_->get_dash_fragment(r->vhost_);
|
||||
update_period_ = config_->get_dash_update_period(r->vhost_);
|
||||
timeshit_ = config_->get_dash_timeshift(r->vhost_);
|
||||
home_ = config_->get_dash_path(r->vhost_);
|
||||
mpd_file_ = config_->get_dash_mpd_file(r->vhost_);
|
||||
|
||||
SrsPath path;
|
||||
string mpd_path = srs_path_build_stream(mpd_file_, req_->vhost_, req_->app_, req_->stream_);
|
||||
fragment_home_ = path.filepath_dir(mpd_path) + "/" + req_->stream_;
|
||||
window_size_ = _srs_config->get_dash_window_size(r->vhost_);
|
||||
window_size_ = config_->get_dash_window_size(r->vhost_);
|
||||
|
||||
srs_trace("DASH: Config fragment=%dms, period=%dms, window=%d, timeshit=%dms, home=%s, mpd=%s",
|
||||
srsu2msi(fragment_), srsu2msi(update_period_), window_size_, srsu2msi(timeshit_), home_.c_str(), mpd_file_.c_str());
|
||||
|
|
@ -225,7 +373,7 @@ void SrsMpdWriter::on_unpublish()
|
|||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsMpdWriter::write(SrsFormat *format, SrsFragmentWindow *afragments, SrsFragmentWindow *vfragments)
|
||||
srs_error_t SrsMpdWriter::write(SrsFormat *format, ISrsFragmentWindow *afragments, ISrsFragmentWindow *vfragments)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -305,7 +453,7 @@ srs_error_t SrsMpdWriter::write(SrsFormat *format, SrsFragmentWindow *afragments
|
|||
ss << " </Period>" << endl;
|
||||
ss << "</MPD>" << endl;
|
||||
|
||||
SrsUniquePtr<SrsFileWriter> fw(new SrsFileWriter());
|
||||
SrsUniquePtr<ISrsFileWriter> fw(app_factory_->create_file_writer());
|
||||
|
||||
string full_path_tmp = full_path + ".tmp";
|
||||
if ((err = fw->open(full_path_tmp)) != srs_success) {
|
||||
|
|
@ -357,6 +505,14 @@ srs_utime_t SrsMpdWriter::get_availability_start_time()
|
|||
return availability_start_time_;
|
||||
}
|
||||
|
||||
ISrsDashController::ISrsDashController()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDashController::~ISrsDashController()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDashController::SrsDashController()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
@ -372,6 +528,9 @@ SrsDashController::SrsDashController()
|
|||
first_dts_ = -1;
|
||||
video_reaped_ = false;
|
||||
fragment_ = 0;
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsDashController::~SrsDashController()
|
||||
|
|
@ -381,6 +540,9 @@ SrsDashController::~SrsDashController()
|
|||
srs_freep(acurrent_);
|
||||
srs_freep(vfragments_);
|
||||
srs_freep(afragments_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsDashController::dispose()
|
||||
|
|
@ -430,8 +592,8 @@ srs_error_t SrsDashController::on_publish()
|
|||
|
||||
ISrsRequest *r = req_;
|
||||
|
||||
fragment_ = _srs_config->get_dash_fragment(r->vhost_);
|
||||
home_ = _srs_config->get_dash_path(r->vhost_);
|
||||
fragment_ = config_->get_dash_fragment(r->vhost_);
|
||||
home_ = config_->get_dash_path(r->vhost_);
|
||||
|
||||
if ((err = mpd_->on_publish()) != srs_success) {
|
||||
return srs_error_wrap(err, "mpd");
|
||||
|
|
@ -439,11 +601,11 @@ srs_error_t SrsDashController::on_publish()
|
|||
|
||||
srs_freep(vcurrent_);
|
||||
srs_freep(vfragments_);
|
||||
vfragments_ = new SrsFragmentWindow();
|
||||
vfragments_ = app_factory_->create_fragment_window();
|
||||
|
||||
srs_freep(acurrent_);
|
||||
srs_freep(afragments_);
|
||||
afragments_ = new SrsFragmentWindow();
|
||||
afragments_ = app_factory_->create_fragment_window();
|
||||
|
||||
audio_dts_ = 0;
|
||||
video_dts_ = 0;
|
||||
|
|
@ -498,7 +660,7 @@ srs_error_t SrsDashController::on_audio(SrsMediaPacket *shared_audio, SrsFormat
|
|||
audio_dts_ = shared_audio->timestamp_;
|
||||
|
||||
if (!acurrent_) {
|
||||
acurrent_ = new SrsFragmentedMp4();
|
||||
acurrent_ = app_factory_->create_fragmented_mp4();
|
||||
|
||||
if ((err = acurrent_->initialize(req_, false, audio_dts_ * SRS_UTIME_MILLISECONDS, mpd_, audio_track_id_)) != srs_success) {
|
||||
return srs_error_wrap(err, "Initialize the audio fragment failed");
|
||||
|
|
@ -521,7 +683,7 @@ srs_error_t SrsDashController::on_audio(SrsMediaPacket *shared_audio, SrsFormat
|
|||
}
|
||||
|
||||
afragments_->append(acurrent_);
|
||||
acurrent_ = new SrsFragmentedMp4();
|
||||
acurrent_ = app_factory_->create_fragmented_mp4();
|
||||
|
||||
if ((err = acurrent_->initialize(req_, false, audio_dts_ * SRS_UTIME_MILLISECONDS, mpd_, audio_track_id_)) != srs_success) {
|
||||
return srs_error_wrap(err, "Initialize the audio fragment failed");
|
||||
|
|
@ -536,8 +698,8 @@ srs_error_t SrsDashController::on_audio(SrsMediaPacket *shared_audio, SrsFormat
|
|||
return srs_error_wrap(err, "Write audio to fragment failed");
|
||||
}
|
||||
|
||||
srs_utime_t fragment = _srs_config->get_dash_fragment(req_->vhost_);
|
||||
int window_size = _srs_config->get_dash_window_size(req_->vhost_);
|
||||
srs_utime_t fragment = config_->get_dash_fragment(req_->vhost_);
|
||||
int window_size = config_->get_dash_window_size(req_->vhost_);
|
||||
int dash_window = 2 * window_size * fragment;
|
||||
if (afragments_->size() > window_size) {
|
||||
int w = 0;
|
||||
|
|
@ -550,7 +712,7 @@ srs_error_t SrsDashController::on_audio(SrsMediaPacket *shared_audio, SrsFormat
|
|||
afragments_->shrink(dash_window);
|
||||
}
|
||||
|
||||
bool dash_cleanup = _srs_config->get_dash_cleanup(req_->vhost_);
|
||||
bool dash_cleanup = config_->get_dash_cleanup(req_->vhost_);
|
||||
// remove the m4s file.
|
||||
afragments_->clear_expired(dash_cleanup);
|
||||
|
||||
|
|
@ -570,7 +732,7 @@ srs_error_t SrsDashController::on_video(SrsMediaPacket *shared_video, SrsFormat
|
|||
video_dts_ = shared_video->timestamp_;
|
||||
|
||||
if (!vcurrent_) {
|
||||
vcurrent_ = new SrsFragmentedMp4();
|
||||
vcurrent_ = app_factory_->create_fragmented_mp4();
|
||||
|
||||
if ((err = vcurrent_->initialize(req_, true, video_dts_ * SRS_UTIME_MILLISECONDS, mpd_, video_track_id_)) != srs_success) {
|
||||
return srs_error_wrap(err, "Initialize the video fragment failed");
|
||||
|
|
@ -594,7 +756,7 @@ srs_error_t SrsDashController::on_video(SrsMediaPacket *shared_video, SrsFormat
|
|||
video_reaped_ = true;
|
||||
|
||||
vfragments_->append(vcurrent_);
|
||||
vcurrent_ = new SrsFragmentedMp4();
|
||||
vcurrent_ = app_factory_->create_fragmented_mp4();
|
||||
|
||||
if ((err = vcurrent_->initialize(req_, true, video_dts_ * SRS_UTIME_MILLISECONDS, mpd_, video_track_id_)) != srs_success) {
|
||||
return srs_error_wrap(err, "Initialize the video fragment failed");
|
||||
|
|
@ -609,8 +771,8 @@ srs_error_t SrsDashController::on_video(SrsMediaPacket *shared_video, SrsFormat
|
|||
return srs_error_wrap(err, "Write video to fragment failed");
|
||||
}
|
||||
|
||||
srs_utime_t fragment = _srs_config->get_dash_fragment(req_->vhost_);
|
||||
int window_size = _srs_config->get_dash_window_size(req_->vhost_);
|
||||
srs_utime_t fragment = config_->get_dash_fragment(req_->vhost_);
|
||||
int window_size = config_->get_dash_window_size(req_->vhost_);
|
||||
int dash_window = 2 * window_size * fragment;
|
||||
if (vfragments_->size() > window_size) {
|
||||
int w = 0;
|
||||
|
|
@ -623,7 +785,7 @@ srs_error_t SrsDashController::on_video(SrsMediaPacket *shared_video, SrsFormat
|
|||
vfragments_->shrink(dash_window);
|
||||
}
|
||||
|
||||
bool dash_cleanup = _srs_config->get_dash_cleanup(req_->vhost_);
|
||||
bool dash_cleanup = config_->get_dash_cleanup(req_->vhost_);
|
||||
// remove the m4s file.
|
||||
vfragments_->clear_expired(dash_cleanup);
|
||||
|
||||
|
|
@ -668,7 +830,7 @@ srs_error_t SrsDashController::refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *
|
|||
path += "/audio-init.mp4";
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsInitMp4> init_mp4(new SrsInitMp4());
|
||||
SrsUniquePtr<ISrsInitMp4> init_mp4(app_factory_->create_init_mp4());
|
||||
|
||||
init_mp4->set_path(path);
|
||||
|
||||
|
|
@ -703,11 +865,15 @@ SrsDash::SrsDash()
|
|||
enabled_ = false;
|
||||
disposable_ = false;
|
||||
last_update_time_ = 0;
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsDash::~SrsDash()
|
||||
{
|
||||
srs_freep(controller_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsDash::dispose()
|
||||
|
|
@ -717,7 +883,7 @@ void SrsDash::dispose()
|
|||
}
|
||||
|
||||
// Ignore when dash_dispose disabled.
|
||||
srs_utime_t dash_dispose = _srs_config->get_dash_dispose(req_->vhost_);
|
||||
srs_utime_t dash_dispose = config_->get_dash_dispose(req_->vhost_);
|
||||
if (!dash_dispose) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -737,7 +903,7 @@ srs_error_t SrsDash::cycle()
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_utime_t dash_dispose = _srs_config->get_dash_dispose(req_->vhost_);
|
||||
srs_utime_t dash_dispose = config_->get_dash_dispose(req_->vhost_);
|
||||
if (dash_dispose <= 0) {
|
||||
return err;
|
||||
}
|
||||
|
|
@ -760,7 +926,7 @@ srs_error_t SrsDash::cycle()
|
|||
srs_utime_t SrsDash::cleanup_delay()
|
||||
{
|
||||
// We use larger timeout to cleanup the HLS, after disposed it if required.
|
||||
return _srs_config->get_dash_dispose(req_->vhost_) * 1.1;
|
||||
return config_->get_dash_dispose(req_->vhost_) * 1.1;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -769,7 +935,7 @@ srs_utime_t SrsDash::cleanup_delay()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsDash::initialize(SrsOriginHub *h, ISrsRequest *r)
|
||||
srs_error_t SrsDash::initialize(ISrsOriginHub *h, ISrsRequest *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -792,7 +958,7 @@ srs_error_t SrsDash::on_publish()
|
|||
return err;
|
||||
}
|
||||
|
||||
if (!_srs_config->get_dash_enabled(req_->vhost_)) {
|
||||
if (!config_->get_dash_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
enabled_ = true;
|
||||
|
|
|
|||
|
|
@ -16,19 +16,44 @@
|
|||
|
||||
class ISrsRequest;
|
||||
class SrsOriginHub;
|
||||
class ISrsOriginHub;
|
||||
class SrsMediaPacket;
|
||||
class SrsFormat;
|
||||
class SrsFileWriter;
|
||||
class ISrsFileWriter;
|
||||
class SrsMpdWriter;
|
||||
class ISrsMpdWriter;
|
||||
class SrsMp4M2tsInitEncoder;
|
||||
class ISrsMp4M2tsInitEncoder;
|
||||
class SrsMp4M2tsSegmentEncoder;
|
||||
class ISrsMp4M2tsSegmentEncoder;
|
||||
class SrsFragment;
|
||||
class ISrsFragment;
|
||||
class ISrsAppFactory;
|
||||
class ISrsDashController;
|
||||
class ISrsFragmentWindow;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The init mp4 fragment interface.
|
||||
class ISrsInitMp4 : public ISrsFragment
|
||||
{
|
||||
public:
|
||||
ISrsInitMp4();
|
||||
virtual ~ISrsInitMp4();
|
||||
|
||||
public:
|
||||
// Write the init mp4 file, with the tid(track id).
|
||||
virtual srs_error_t write(SrsFormat *format, bool video, int tid) = 0;
|
||||
};
|
||||
|
||||
// The init mp4 for FMP4.
|
||||
class SrsInitMp4 : public SrsFragment
|
||||
class SrsInitMp4 : public ISrsInitMp4
|
||||
{
|
||||
private:
|
||||
SrsFileWriter *fw_;
|
||||
SrsMp4M2tsInitEncoder *init_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFileWriter *fw_;
|
||||
ISrsMp4M2tsInitEncoder *init_;
|
||||
ISrsFragment *fragment_;
|
||||
|
||||
public:
|
||||
SrsInitMp4();
|
||||
|
|
@ -37,14 +62,50 @@ public:
|
|||
public:
|
||||
// Write the init mp4 file, with the tid(track id).
|
||||
virtual srs_error_t write(SrsFormat *format, bool video, int tid);
|
||||
|
||||
public:
|
||||
// ISrsFragment interface implementations - delegate to fragment_
|
||||
virtual void set_path(std::string v);
|
||||
virtual std::string tmppath();
|
||||
virtual srs_error_t rename();
|
||||
virtual void append(int64_t dts);
|
||||
virtual srs_error_t create_dir();
|
||||
virtual void set_number(uint64_t n);
|
||||
virtual uint64_t number();
|
||||
virtual srs_utime_t duration();
|
||||
virtual srs_error_t unlink_tmpfile();
|
||||
virtual srs_utime_t get_start_dts();
|
||||
virtual srs_error_t unlink_file();
|
||||
};
|
||||
|
||||
// The FMP4(Fragmented MP4) for DASH streaming.
|
||||
class SrsFragmentedMp4 : public SrsFragment
|
||||
class ISrsFragmentedMp4 : public ISrsFragment
|
||||
{
|
||||
private:
|
||||
SrsFileWriter *fw_;
|
||||
SrsMp4M2tsSegmentEncoder *enc_;
|
||||
public:
|
||||
ISrsFragmentedMp4();
|
||||
virtual ~ISrsFragmentedMp4();
|
||||
|
||||
public:
|
||||
// Initialize the fragment, create the home dir, open the file.
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool video, int64_t time, ISrsMpdWriter *mpd, uint32_t tid) = 0;
|
||||
// Write media message to fragment.
|
||||
virtual srs_error_t write(SrsMediaPacket *shared_msg, SrsFormat *format) = 0;
|
||||
// Reap the fragment, close the fd and rename tmp to official file.
|
||||
virtual srs_error_t reap(uint64_t &dts) = 0;
|
||||
};
|
||||
|
||||
// The FMP4(Fragmented MP4) for DASH streaming.
|
||||
class SrsFragmentedMp4 : public ISrsFragmentedMp4
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFileWriter *fw_;
|
||||
ISrsMp4M2tsSegmentEncoder *enc_;
|
||||
ISrsFragment *fragment_;
|
||||
|
||||
public:
|
||||
SrsFragmentedMp4();
|
||||
|
|
@ -52,20 +113,67 @@ public:
|
|||
|
||||
public:
|
||||
// Initialize the fragment, create the home dir, open the file.
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid);
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool video, int64_t time, ISrsMpdWriter *mpd, uint32_t tid);
|
||||
// Write media message to fragment.
|
||||
virtual srs_error_t write(SrsMediaPacket *shared_msg, SrsFormat *format);
|
||||
// Reap the fragment, close the fd and rename tmp to official file.
|
||||
virtual srs_error_t reap(uint64_t &dts);
|
||||
|
||||
public:
|
||||
// ISrsFragment interface implementations - delegate to fragment_
|
||||
virtual void set_path(std::string v);
|
||||
virtual std::string tmppath();
|
||||
virtual srs_error_t rename();
|
||||
virtual void append(int64_t dts);
|
||||
virtual srs_error_t create_dir();
|
||||
virtual void set_number(uint64_t n);
|
||||
virtual uint64_t number();
|
||||
virtual srs_utime_t duration();
|
||||
virtual srs_error_t unlink_tmpfile();
|
||||
virtual srs_utime_t get_start_dts();
|
||||
virtual srs_error_t unlink_file();
|
||||
};
|
||||
|
||||
// The writer to write MPD for DASH.
|
||||
class SrsMpdWriter
|
||||
class ISrsMpdWriter
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsMpdWriter();
|
||||
virtual ~ISrsMpdWriter();
|
||||
|
||||
public:
|
||||
virtual void dispose() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
// Write MPD according to parsed format of stream.
|
||||
virtual srs_error_t write(SrsFormat *format, ISrsFragmentWindow *afragments, ISrsFragmentWindow *vfragments) = 0;
|
||||
|
||||
public:
|
||||
// Get the fragment relative home and filename.
|
||||
// The basetime is the absolute time in srs_utime_t, while the sn(sequence number) is basetime/fragment.
|
||||
virtual srs_error_t get_fragment(bool video, std::string &home, std::string &filename, int64_t time, int64_t &sn) = 0;
|
||||
// Set the availabilityStartTime once, map the timestamp in media to utc time.
|
||||
virtual void set_availability_start_time(srs_utime_t t) = 0;
|
||||
virtual srs_utime_t get_availability_start_time() = 0;
|
||||
};
|
||||
|
||||
// The writer to write MPD for DASH.
|
||||
class SrsMpdWriter : public ISrsMpdWriter
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The duration of fragment in srs_utime_t.
|
||||
srs_utime_t fragment_;
|
||||
// The period to update the mpd in srs_utime_t.
|
||||
|
|
@ -85,7 +193,8 @@ private:
|
|||
// The number of current audio segment.
|
||||
uint64_t audio_number_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The home for fragment, relative to home.
|
||||
std::string fragment_home_;
|
||||
|
||||
|
|
@ -101,7 +210,7 @@ public:
|
|||
virtual srs_error_t on_publish();
|
||||
virtual void on_unpublish();
|
||||
// Write MPD according to parsed format of stream.
|
||||
virtual srs_error_t write(SrsFormat *format, SrsFragmentWindow *afragments, SrsFragmentWindow *vfragments);
|
||||
virtual srs_error_t write(SrsFormat *format, ISrsFragmentWindow *afragments, ISrsFragmentWindow *vfragments);
|
||||
|
||||
public:
|
||||
// Get the fragment relative home and filename.
|
||||
|
|
@ -112,19 +221,44 @@ public:
|
|||
virtual srs_utime_t get_availability_start_time();
|
||||
};
|
||||
|
||||
// The controller for DASH, control the MPD and FMP4 generating system.
|
||||
class SrsDashController
|
||||
// The DASH controller interface.
|
||||
class ISrsDashController
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsDashController();
|
||||
virtual ~ISrsDashController();
|
||||
|
||||
public:
|
||||
virtual void dispose() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
};
|
||||
|
||||
// The controller for DASH, control the MPD and FMP4 generating system.
|
||||
class SrsDashController : public ISrsDashController
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsFormat *format_;
|
||||
SrsMpdWriter *mpd_;
|
||||
ISrsMpdWriter *mpd_;
|
||||
|
||||
private:
|
||||
SrsFragmentedMp4 *vcurrent_;
|
||||
SrsFragmentWindow *vfragments_;
|
||||
SrsFragmentedMp4 *acurrent_;
|
||||
SrsFragmentWindow *afragments_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFragmentedMp4 *vcurrent_;
|
||||
ISrsFragmentWindow *vfragments_;
|
||||
ISrsFragmentedMp4 *acurrent_;
|
||||
ISrsFragmentWindow *afragments_;
|
||||
// Current audio dts.
|
||||
uint64_t audio_dts_;
|
||||
// Current video dts.
|
||||
|
|
@ -134,11 +268,13 @@ private:
|
|||
// Had the video reaped, use to align audio/video segment's timestamp.
|
||||
bool video_reaped_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The fragment duration in srs_utime_t to reap it.
|
||||
srs_utime_t fragment_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string home_;
|
||||
int video_track_id_;
|
||||
int audio_track_id_;
|
||||
|
|
@ -157,7 +293,8 @@ public:
|
|||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t refresh_mpd(SrsFormat *format);
|
||||
virtual srs_error_t refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *format);
|
||||
};
|
||||
|
|
@ -175,7 +312,7 @@ public:
|
|||
virtual srs_utime_t cleanup_delay() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
|
|
@ -185,15 +322,21 @@ public:
|
|||
// The MPEG-DASH encoder, transmux RTMP to DASH.
|
||||
class SrsDash : public ISrsDash
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool enabled_;
|
||||
bool disposable_;
|
||||
srs_utime_t last_update_time_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsOriginHub *hub_;
|
||||
SrsDashController *controller_;
|
||||
ISrsOriginHub *hub_;
|
||||
ISrsDashController *controller_;
|
||||
|
||||
public:
|
||||
SrsDash();
|
||||
|
|
@ -206,7 +349,7 @@ public:
|
|||
|
||||
public:
|
||||
// Initalize the encoder.
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsRequest *r);
|
||||
// When stream start publishing.
|
||||
virtual srs_error_t on_publish();
|
||||
// When got an shared audio message.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_fragment.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
|
@ -28,6 +29,14 @@ using namespace std;
|
|||
|
||||
#define SRS_FWRITE_CACHE_SIZE 65536
|
||||
|
||||
ISrsDvrSegmenter::ISrsDvrSegmenter()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDvrSegmenter::~ISrsDvrSegmenter()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDvrSegmenter::SrsDvrSegmenter()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
@ -39,16 +48,23 @@ SrsDvrSegmenter::SrsDvrSegmenter()
|
|||
fs_ = new SrsFileWriter();
|
||||
jitter_algorithm_ = SrsRtmpJitterAlgorithmOFF;
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
void SrsDvrSegmenter::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsDvrSegmenter::~SrsDvrSegmenter()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
srs_freep(fragment_);
|
||||
srs_freep(jitter_);
|
||||
srs_freep(fs_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -57,13 +73,13 @@ SrsDvrSegmenter::~SrsDvrSegmenter()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsDvrSegmenter::initialize(SrsDvrPlan *p, ISrsRequest *r)
|
||||
srs_error_t SrsDvrSegmenter::initialize(ISrsDvrPlan *p, ISrsRequest *r)
|
||||
{
|
||||
req_ = r;
|
||||
plan_ = p;
|
||||
|
||||
jitter_algorithm_ = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(req_->vhost_);
|
||||
wait_keyframe_ = _srs_config->get_dvr_wait_keyframe(req_->vhost_);
|
||||
jitter_algorithm_ = (SrsRtmpJitterAlgorithm)config_->get_dvr_time_jitter(req_->vhost_);
|
||||
wait_keyframe_ = config_->get_dvr_wait_keyframe(req_->vhost_);
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -201,7 +217,7 @@ string SrsDvrSegmenter::generate_path()
|
|||
{
|
||||
// the path in config, for example,
|
||||
// /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv
|
||||
std::string path_config = _srs_config->get_dvr_path(req_->vhost_);
|
||||
std::string path_config = config_->get_dvr_path(req_->vhost_);
|
||||
|
||||
// add [stream].[timestamp].flv as filename for dir
|
||||
if (!srs_strings_ends_with(path_config, ".flv", ".mp4")) {
|
||||
|
|
@ -230,11 +246,15 @@ SrsDvrFlvSegmenter::SrsDvrFlvSegmenter()
|
|||
filesize_offset_ = 0;
|
||||
|
||||
has_keyframe_ = false;
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsDvrFlvSegmenter::~SrsDvrFlvSegmenter()
|
||||
{
|
||||
srs_freep(enc_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsDvrFlvSegmenter::refresh_metadata()
|
||||
|
|
@ -297,7 +317,7 @@ srs_error_t SrsDvrFlvSegmenter::open_encoder()
|
|||
filesize_offset_ = 0;
|
||||
|
||||
srs_freep(enc_);
|
||||
enc_ = new SrsFlvTransmuxer();
|
||||
enc_ = app_factory_->create_flv_transmuxer();
|
||||
|
||||
if ((err = enc_->initialize(fs_)) != srs_success) {
|
||||
return srs_error_wrap(err, "init encoder");
|
||||
|
|
@ -414,11 +434,15 @@ srs_error_t SrsDvrFlvSegmenter::close_encoder()
|
|||
SrsDvrMp4Segmenter::SrsDvrMp4Segmenter()
|
||||
{
|
||||
enc_ = new SrsMp4Encoder();
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsDvrMp4Segmenter::~SrsDvrMp4Segmenter()
|
||||
{
|
||||
srs_freep(enc_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsDvrMp4Segmenter::refresh_metadata()
|
||||
|
|
@ -431,7 +455,7 @@ srs_error_t SrsDvrMp4Segmenter::open_encoder()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
srs_freep(enc_);
|
||||
enc_ = new SrsMp4Encoder();
|
||||
enc_ = app_factory_->create_mp4_encoder();
|
||||
|
||||
if ((err = enc_->initialize(fs_)) != srs_success) {
|
||||
return srs_error_wrap(err, "init encoder");
|
||||
|
|
@ -456,10 +480,7 @@ srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsMediaPacket *audio, SrsFormat *f
|
|||
|
||||
SrsAudioAacFrameTrait ct = format->audio_->aac_packet_type_;
|
||||
if (ct == SrsAudioAacFrameTraitSequenceHeader || ct == SrsAudioMp3FrameTraitSequenceHeader) {
|
||||
enc_->acodec_ = sound_format;
|
||||
enc_->sample_rate_ = sound_rate;
|
||||
enc_->sound_bits_ = sound_size;
|
||||
enc_->channels_ = channels;
|
||||
enc_->set_audio_codec(sound_format, sound_rate, sound_size, channels);
|
||||
}
|
||||
|
||||
uint8_t *sample = (uint8_t *)format->raw_;
|
||||
|
|
@ -515,18 +536,24 @@ SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(SrsContextId c, ISrsRequest *r, strin
|
|||
cid_ = c;
|
||||
req_ = r->copy();
|
||||
path_ = p;
|
||||
|
||||
hooks_ = _srs_hooks;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsDvrAsyncCallOnDvr::~SrsDvrAsyncCallOnDvr()
|
||||
{
|
||||
srs_freep(req_);
|
||||
|
||||
hooks_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsDvrAsyncCallOnDvr::call()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +563,7 @@ srs_error_t SrsDvrAsyncCallOnDvr::call()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_dvr(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_dvr(req_->vhost_);
|
||||
if (conf) {
|
||||
hooks = conf->args_;
|
||||
}
|
||||
|
|
@ -544,7 +571,7 @@ srs_error_t SrsDvrAsyncCallOnDvr::call()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_dvr(cid_, url, req_, path_)) != srs_success) {
|
||||
if ((err = hooks_->on_dvr(cid_, url, req_, path_)) != srs_success) {
|
||||
return srs_error_wrap(err, "callback on_dvr %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -559,6 +586,14 @@ string SrsDvrAsyncCallOnDvr::to_string()
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
ISrsDvrPlan::ISrsDvrPlan()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDvrPlan::~ISrsDvrPlan()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDvrPlan::SrsDvrPlan()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
@ -566,12 +601,18 @@ SrsDvrPlan::SrsDvrPlan()
|
|||
|
||||
dvr_enabled_ = false;
|
||||
segment_ = NULL;
|
||||
|
||||
async_ = _srs_dvr_async;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsDvrPlan::~SrsDvrPlan()
|
||||
{
|
||||
srs_freep(segment_);
|
||||
srs_freep(req_);
|
||||
|
||||
async_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -580,7 +621,7 @@ SrsDvrPlan::~SrsDvrPlan()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsDvrPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r)
|
||||
srs_error_t SrsDvrPlan::initialize(ISrsOriginHub *h, ISrsDvrSegmenter *s, ISrsRequest *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -658,7 +699,7 @@ srs_error_t SrsDvrPlan::on_reap_segment()
|
|||
SrsFragment *fragment = segment_->current();
|
||||
string fullpath = fragment->fullpath();
|
||||
|
||||
if ((err = _srs_dvr_async->execute(new SrsDvrAsyncCallOnDvr(cid, req_, fullpath))) != srs_success) {
|
||||
if ((err = async_->execute(new SrsDvrAsyncCallOnDvr(cid, req_, fullpath))) != srs_success) {
|
||||
return srs_error_wrap(err, "reap segment");
|
||||
}
|
||||
|
||||
|
|
@ -671,9 +712,9 @@ srs_error_t SrsDvrPlan::on_reap_segment()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsDvrPlan::create_plan(string vhost, SrsDvrPlan **pplan)
|
||||
srs_error_t SrsDvrPlan::create_plan(ISrsAppConfig *config, string vhost, ISrsDvrPlan **pplan)
|
||||
{
|
||||
std::string plan = _srs_config->get_dvr_plan(vhost);
|
||||
std::string plan = config->get_dvr_plan(vhost);
|
||||
if (srs_config_dvr_is_plan_segment(plan)) {
|
||||
*pplan = new SrsDvrSegmentPlan();
|
||||
} else if (srs_config_dvr_is_plan_session(plan)) {
|
||||
|
|
@ -707,7 +748,7 @@ srs_error_t SrsDvrSessionPlan::on_publish(ISrsRequest *r)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (!_srs_config->get_dvr_enabled(req_->vhost_)) {
|
||||
if (!config_->get_dvr_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -734,7 +775,7 @@ void SrsDvrSessionPlan::on_unpublish()
|
|||
// ignore error.
|
||||
srs_error_t err = segment_->close();
|
||||
if (err != srs_success) {
|
||||
srs_warn("ignore flv close error %s", srs_error_desc(err).c_str());
|
||||
srs_warn("ignore dvr segment close failed. ret=%d", srs_error_code(err));
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
|
|
@ -756,7 +797,7 @@ SrsDvrSegmentPlan::~SrsDvrSegmentPlan()
|
|||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r)
|
||||
srs_error_t SrsDvrSegmentPlan::initialize(ISrsOriginHub *h, ISrsDvrSegmenter *s, ISrsRequest *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -764,9 +805,9 @@ srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, I
|
|||
return srs_error_wrap(err, "segment plan");
|
||||
}
|
||||
|
||||
wait_keyframe_ = _srs_config->get_dvr_wait_keyframe(req_->vhost_);
|
||||
wait_keyframe_ = config_->get_dvr_wait_keyframe(req_->vhost_);
|
||||
|
||||
cduration_ = _srs_config->get_dvr_duration(req_->vhost_);
|
||||
cduration_ = config_->get_dvr_duration(req_->vhost_);
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -784,7 +825,7 @@ srs_error_t SrsDvrSegmentPlan::on_publish(ISrsRequest *r)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (!_srs_config->get_dvr_enabled(req_->vhost_)) {
|
||||
if (!config_->get_dvr_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -919,15 +960,24 @@ SrsDvr::SrsDvr()
|
|||
req_ = NULL;
|
||||
actived_ = false;
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
void SrsDvr::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsDvr::~SrsDvr()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
srs_freep(plan_);
|
||||
srs_freep(req_);
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -936,28 +986,29 @@ SrsDvr::~SrsDvr()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsDvr::initialize(SrsOriginHub *h, ISrsRequest *r)
|
||||
srs_error_t SrsDvr::initialize(ISrsOriginHub *h, ISrsRequest *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
req_ = r->copy();
|
||||
hub_ = h;
|
||||
|
||||
SrsConfDirective *conf = _srs_config->get_dvr_apply(r->vhost_);
|
||||
SrsConfDirective *conf = config_->get_dvr_apply(r->vhost_);
|
||||
actived_ = srs_config_apply_filter(conf, r);
|
||||
|
||||
srs_freep(plan_);
|
||||
if ((err = SrsDvrPlan::create_plan(r->vhost_, &plan_)) != srs_success) {
|
||||
if ((err = SrsDvrPlan::create_plan(config_, r->vhost_, &plan_)) != srs_success) {
|
||||
return srs_error_wrap(err, "create plan");
|
||||
}
|
||||
|
||||
std::string path = _srs_config->get_dvr_path(r->vhost_);
|
||||
SrsDvrSegmenter *segmenter = NULL;
|
||||
std::string path = config_->get_dvr_path(r->vhost_);
|
||||
ISrsDvrSegmenter *segmenter = NULL;
|
||||
if (srs_strings_ends_with(path, ".mp4")) {
|
||||
segmenter = new SrsDvrMp4Segmenter();
|
||||
segmenter = app_factory_->create_dvr_mp4_segmenter();
|
||||
} else {
|
||||
segmenter = new SrsDvrFlvSegmenter();
|
||||
segmenter = app_factory_->create_dvr_flv_segmenter();
|
||||
}
|
||||
segmenter->assemble();
|
||||
|
||||
if ((err = plan_->initialize(hub_, segmenter, r)) != srs_success) {
|
||||
return srs_error_wrap(err, "plan initialize");
|
||||
|
|
|
|||
|
|
@ -27,37 +27,70 @@ class SrsThread;
|
|||
class SrsMp4Encoder;
|
||||
class SrsFragment;
|
||||
class SrsFormat;
|
||||
class ISrsFileWriter;
|
||||
class ISrsDvrPlan;
|
||||
class ISrsMp4Encoder;
|
||||
class ISrsOriginHub;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
class ISrsAsyncCallWorker;
|
||||
|
||||
#include <srs_app_async_call.hpp>
|
||||
#include <srs_app_reload.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
|
||||
// The segmenter for DVR, to write a segment file in flv/mp4.
|
||||
class SrsDvrSegmenter : public ISrsReloadHandler
|
||||
// The segmenter interface.
|
||||
class ISrsDvrSegmenter
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
ISrsDvrSegmenter();
|
||||
virtual void assemble() = 0;
|
||||
virtual ~ISrsDvrSegmenter();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsDvrPlan *p, ISrsRequest *r) = 0;
|
||||
virtual SrsFragment *current() = 0;
|
||||
virtual srs_error_t open() = 0;
|
||||
virtual srs_error_t write_metadata(SrsMediaPacket *metadata) = 0;
|
||||
virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
virtual srs_error_t close() = 0;
|
||||
};
|
||||
|
||||
// The segmenter for DVR, to write a segment file in flv/mp4.
|
||||
class SrsDvrSegmenter : public ISrsReloadHandler, public ISrsDvrSegmenter
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The underlayer file object.
|
||||
SrsFileWriter *fs_;
|
||||
ISrsFileWriter *fs_;
|
||||
// Whether wait keyframe to reap segment.
|
||||
bool wait_keyframe_;
|
||||
// The FLV/MP4 fragment file.
|
||||
SrsFragment *fragment_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsDvrPlan *plan_;
|
||||
ISrsDvrPlan *plan_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtmpJitter *jitter_;
|
||||
SrsRtmpJitterAlgorithm jitter_algorithm_;
|
||||
|
||||
public:
|
||||
SrsDvrSegmenter();
|
||||
void assemble();
|
||||
virtual ~SrsDvrSegmenter();
|
||||
|
||||
public:
|
||||
// Initialize the segment.
|
||||
virtual srs_error_t initialize(SrsDvrPlan *p, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(ISrsDvrPlan *p, ISrsRequest *r);
|
||||
// Get the current framgnet.
|
||||
virtual SrsFragment *current();
|
||||
// Open new segment file.
|
||||
|
|
@ -80,16 +113,19 @@ public:
|
|||
// @remark ignore when already closed.
|
||||
virtual srs_error_t close();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t open_encoder() = 0;
|
||||
virtual srs_error_t encode_metadata(SrsMediaPacket *metadata) = 0;
|
||||
virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t encode_video(SrsMediaPacket *video, SrsFormat *format) = 0;
|
||||
virtual srs_error_t close_encoder() = 0;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Generate the flv segment path.
|
||||
virtual std::string generate_path();
|
||||
virtual std::string
|
||||
generate_path();
|
||||
// When update the duration of segment by rtmp msg.
|
||||
virtual srs_error_t on_update_duration(SrsMediaPacket *msg);
|
||||
};
|
||||
|
|
@ -97,11 +133,17 @@ private:
|
|||
// The FLV segmenter to use FLV encoder to write file.
|
||||
class SrsDvrFlvSegmenter : public SrsDvrSegmenter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The FLV encoder, for FLV target.
|
||||
ISrsFlvTransmuxer *enc_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The offset of file for duration value.
|
||||
// The next 8 bytes is the double value.
|
||||
int64_t duration_offset_;
|
||||
|
|
@ -118,7 +160,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t refresh_metadata();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t open_encoder();
|
||||
virtual srs_error_t encode_metadata(SrsMediaPacket *metadata);
|
||||
virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format);
|
||||
|
|
@ -129,9 +172,14 @@ protected:
|
|||
// The MP4 segmenter to use MP4 encoder to write file.
|
||||
class SrsDvrMp4Segmenter : public SrsDvrSegmenter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The MP4 encoder, for MP4 target.
|
||||
SrsMp4Encoder *enc_;
|
||||
ISrsMp4Encoder *enc_;
|
||||
|
||||
public:
|
||||
SrsDvrMp4Segmenter();
|
||||
|
|
@ -140,7 +188,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t refresh_metadata();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t open_encoder();
|
||||
virtual srs_error_t encode_metadata(SrsMediaPacket *metadata);
|
||||
virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format);
|
||||
|
|
@ -151,7 +200,13 @@ protected:
|
|||
// the dvr async call.
|
||||
class SrsDvrAsyncCallOnDvr : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpHooks *hooks_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
std::string path_;
|
||||
ISrsRequest *req_;
|
||||
|
|
@ -165,15 +220,38 @@ public:
|
|||
virtual std::string to_string();
|
||||
};
|
||||
|
||||
// The DVR plan, when and how to reap segment.
|
||||
class SrsDvrPlan : public ISrsReloadHandler
|
||||
// The DVR plan interface.
|
||||
class ISrsDvrPlan
|
||||
{
|
||||
public:
|
||||
ISrsDvrPlan();
|
||||
virtual ~ISrsDvrPlan();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsDvrSegmenter *s, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish(ISrsRequest *r) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata) = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_reap_segment() = 0;
|
||||
};
|
||||
|
||||
// The DVR plan, when and how to reap segment.
|
||||
class SrsDvrPlan : public ISrsReloadHandler, public ISrsDvrPlan
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsAsyncCallWorker *async_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
public:
|
||||
ISrsRequest *req_;
|
||||
|
||||
protected:
|
||||
SrsOriginHub *hub_;
|
||||
SrsDvrSegmenter *segment_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsOriginHub *hub_;
|
||||
ISrsDvrSegmenter *segment_;
|
||||
bool dvr_enabled_;
|
||||
|
||||
public:
|
||||
|
|
@ -181,7 +259,7 @@ public:
|
|||
virtual ~SrsDvrPlan();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsDvrSegmenter *s, ISrsRequest *r);
|
||||
virtual srs_error_t on_publish(ISrsRequest *r);
|
||||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata);
|
||||
|
|
@ -193,7 +271,7 @@ public:
|
|||
virtual srs_error_t on_reap_segment();
|
||||
|
||||
public:
|
||||
static srs_error_t create_plan(std::string vhost, SrsDvrPlan **pplan);
|
||||
static srs_error_t create_plan(ISrsAppConfig *config, std::string vhost, ISrsDvrPlan **pplan);
|
||||
};
|
||||
|
||||
// The DVR session plan: reap flv when session complete(unpublish)
|
||||
|
|
@ -211,7 +289,8 @@ public:
|
|||
// The DVR segment plan: reap flv when duration exceed.
|
||||
class SrsDvrSegmentPlan : public SrsDvrPlan
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// in config, in srs_utime_t
|
||||
srs_utime_t cduration_;
|
||||
bool wait_keyframe_;
|
||||
|
|
@ -223,13 +302,14 @@ public:
|
|||
virtual ~SrsDvrSegmentPlan();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsDvrSegmenter *s, ISrsRequest *r);
|
||||
virtual srs_error_t on_publish(ISrsRequest *r);
|
||||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t update_duration(SrsMediaPacket *msg);
|
||||
};
|
||||
|
||||
|
|
@ -238,10 +318,11 @@ class ISrsDvr
|
|||
{
|
||||
public:
|
||||
ISrsDvr();
|
||||
virtual void assemble() = 0;
|
||||
virtual ~ISrsDvr();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish(ISrsRequest *r) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *metadata) = 0;
|
||||
|
|
@ -252,12 +333,19 @@ public:
|
|||
// DVR(Digital Video Recorder) to record RTMP stream to flv/mp4 file.
|
||||
class SrsDvr : public ISrsReloadHandler, public ISrsDvr
|
||||
{
|
||||
private:
|
||||
SrsOriginHub *hub_;
|
||||
SrsDvrPlan *plan_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsOriginHub *hub_;
|
||||
ISrsDvrPlan *plan_;
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// whether the dvr is actived by filter, which is specified by dvr_apply.
|
||||
// we always initialize the dvr, which crote plan and segment object,
|
||||
// but they never create actual piece of file util the apply active it.
|
||||
|
|
@ -265,13 +353,14 @@ private:
|
|||
|
||||
public:
|
||||
SrsDvr();
|
||||
void assemble();
|
||||
virtual ~SrsDvr();
|
||||
|
||||
public:
|
||||
// initialize dvr, create dvr plan.
|
||||
// when system initialize(encoder publish at first time, or reload),
|
||||
// initialize the dvr will reinitialize the plan, the whole dvr framework.
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(ISrsOriginHub *h, ISrsRequest *r);
|
||||
// publish stream event,
|
||||
// when encoder start to publish RTMP stream.
|
||||
// @param fetch_sequence_header whether fetch sequence from source.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using namespace std;
|
|||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_pithy_print.hpp>
|
||||
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_balance.hpp>
|
||||
|
|
@ -42,11 +43,11 @@ using namespace std;
|
|||
// when edge error, wait for quit
|
||||
#define SRS_EDGE_FORWARDER_TIMEOUT (150 * SRS_UTIME_MILLISECONDS)
|
||||
|
||||
SrsEdgeUpstream::SrsEdgeUpstream()
|
||||
ISrsEdgeUpstream::ISrsEdgeUpstream()
|
||||
{
|
||||
}
|
||||
|
||||
SrsEdgeUpstream::~SrsEdgeUpstream()
|
||||
ISrsEdgeUpstream::~ISrsEdgeUpstream()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -55,11 +56,17 @@ SrsEdgeRtmpUpstream::SrsEdgeRtmpUpstream(string r)
|
|||
redirect_ = r;
|
||||
sdk_ = NULL;
|
||||
selected_port_ = 0;
|
||||
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsEdgeRtmpUpstream::~SrsEdgeRtmpUpstream()
|
||||
{
|
||||
close();
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
||||
|
|
@ -70,7 +77,7 @@ srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
|||
|
||||
std::string url;
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_edge_origin(req->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_edge_origin(req->vhost_);
|
||||
|
||||
// when origin is error, for instance, server is shutdown,
|
||||
// then user remove the vhost then reload, the conf is empty.
|
||||
|
|
@ -95,7 +102,7 @@ srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
|||
selected_port_ = port;
|
||||
|
||||
// support vhost tranform for edge,
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req->vhost_);
|
||||
std::string vhost = config_->get_vhost_edge_transform_vhost(req->vhost_);
|
||||
vhost = srs_strings_replace(vhost, "[vhost]", req->vhost_);
|
||||
|
||||
url = srs_net_url_encode_rtmp_url(server, port, req->host_, vhost, req->app_, req->stream_, req->param_);
|
||||
|
|
@ -104,7 +111,8 @@ srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
|||
srs_freep(sdk_);
|
||||
srs_utime_t cto = SRS_EDGE_INGESTER_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk_ = new SrsSimpleRtmpClient(url, cto, sto);
|
||||
// Use factory to create client.
|
||||
sdk_ = app_factory_->create_rtmp_client(url, cto, sto);
|
||||
|
||||
if ((err = sdk_->connect()) != srs_success) {
|
||||
return srs_error_wrap(err, "edge pull %s failed, cto=%dms, sto=%dms.", url.c_str(), srsu2msi(cto), srsu2msi(sto));
|
||||
|
|
@ -113,7 +121,7 @@ srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
|||
// For RTMP client, we pass the vhost in tcUrl when connecting,
|
||||
// so we publish without vhost in stream.
|
||||
string stream;
|
||||
if ((err = sdk_->play(_srs_config->get_chunk_size(req->vhost_), false, &stream)) != srs_success) {
|
||||
if ((err = sdk_->play(config_->get_chunk_size(req->vhost_), false, &stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "edge pull %s stream failed", url.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +171,17 @@ SrsEdgeFlvUpstream::SrsEdgeFlvUpstream(std::string schema)
|
|||
reader_ = NULL;
|
||||
decoder_ = NULL;
|
||||
req_ = NULL;
|
||||
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsEdgeFlvUpstream::~SrsEdgeFlvUpstream()
|
||||
{
|
||||
close();
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsEdgeFlvUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
|
||||
|
|
@ -189,7 +203,7 @@ srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb,
|
|||
ISrsRequest *req = r;
|
||||
|
||||
if (redirect_depth == 0) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_edge_origin(req->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_edge_origin(req->vhost_);
|
||||
|
||||
// when origin is error, for instance, server is shutdown,
|
||||
// then user remove the vhost then reload, the conf is empty.
|
||||
|
|
@ -216,7 +230,7 @@ srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb,
|
|||
}
|
||||
|
||||
srs_freep(sdk_);
|
||||
sdk_ = new SrsHttpClient();
|
||||
sdk_ = app_factory_->create_http_client();
|
||||
|
||||
string path = "/" + req->app_ + "/" + req->stream_;
|
||||
if (!srs_strings_ends_with(req->stream_, ".flv")) {
|
||||
|
|
@ -275,10 +289,10 @@ srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb,
|
|||
}
|
||||
|
||||
srs_freep(reader_);
|
||||
reader_ = new SrsHttpFileReader(hr_->body_reader());
|
||||
reader_ = app_factory_->create_http_file_reader(hr_->body_reader());
|
||||
|
||||
srs_freep(decoder_);
|
||||
decoder_ = new SrsFlvDecoder();
|
||||
decoder_ = app_factory_->create_flv_decoder();
|
||||
|
||||
if ((err = decoder_->initialize(reader_)) != srs_success) {
|
||||
return srs_error_wrap(err, "init decoder");
|
||||
|
|
@ -383,6 +397,14 @@ void SrsEdgeFlvUpstream::kbps_sample(const char *label, srs_utime_t age)
|
|||
sdk_->kbps_sample(label, age);
|
||||
}
|
||||
|
||||
ISrsEdgeIngester::ISrsEdgeIngester()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsEdgeIngester::~ISrsEdgeIngester()
|
||||
{
|
||||
}
|
||||
|
||||
SrsEdgeIngester::SrsEdgeIngester()
|
||||
{
|
||||
source_ = NULL;
|
||||
|
|
@ -392,6 +414,8 @@ SrsEdgeIngester::SrsEdgeIngester()
|
|||
upstream_ = new SrsEdgeRtmpUpstream("");
|
||||
lb_ = new SrsLbRoundRobin();
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsEdgeIngester::~SrsEdgeIngester()
|
||||
|
|
@ -401,6 +425,8 @@ SrsEdgeIngester::~SrsEdgeIngester()
|
|||
srs_freep(upstream_);
|
||||
srs_freep(lb_);
|
||||
srs_freep(trd_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -409,7 +435,7 @@ SrsEdgeIngester::~SrsEdgeIngester()
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsEdgeIngester::initialize(SrsSharedPtr<SrsLiveSource> s, SrsPlayEdge *e, ISrsRequest *r)
|
||||
srs_error_t SrsEdgeIngester::initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPlayEdge *e, ISrsRequest *r)
|
||||
{
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
source_ = s.get();
|
||||
|
|
@ -490,10 +516,10 @@ srs_error_t SrsEdgeIngester::do_cycle()
|
|||
}
|
||||
|
||||
// Use protocol in config.
|
||||
string edge_protocol = _srs_config->get_vhost_edge_protocol(req_->vhost_);
|
||||
string edge_protocol = config_->get_vhost_edge_protocol(req_->vhost_);
|
||||
|
||||
// If follow client protocol, change to protocol of client.
|
||||
bool follow_client = _srs_config->get_vhost_edge_follow_client(req_->vhost_);
|
||||
bool follow_client = config_->get_vhost_edge_follow_client(req_->vhost_);
|
||||
if (follow_client && !req_->protocol_.empty()) {
|
||||
edge_protocol = req_->protocol_;
|
||||
}
|
||||
|
|
@ -676,6 +702,14 @@ srs_error_t SrsEdgeIngester::process_publish_message(SrsRtmpCommonMessage *msg,
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsEdgeForwarder::ISrsEdgeForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsEdgeForwarder::~ISrsEdgeForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
SrsEdgeForwarder::SrsEdgeForwarder()
|
||||
{
|
||||
edge_ = NULL;
|
||||
|
|
@ -687,6 +721,8 @@ SrsEdgeForwarder::SrsEdgeForwarder()
|
|||
lb_ = new SrsLbRoundRobin();
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
queue_ = new SrsMessageQueue();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsEdgeForwarder::~SrsEdgeForwarder()
|
||||
|
|
@ -696,6 +732,8 @@ SrsEdgeForwarder::~SrsEdgeForwarder()
|
|||
srs_freep(lb_);
|
||||
srs_freep(trd_);
|
||||
srs_freep(queue_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsEdgeForwarder::set_queue_size(srs_utime_t queue_size)
|
||||
|
|
@ -709,7 +747,7 @@ void SrsEdgeForwarder::set_queue_size(srs_utime_t queue_size)
|
|||
// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
|
||||
// This prevents the race condition where multiple coroutines could create duplicate sources
|
||||
// for the same stream when context switches occurred during initialization.
|
||||
srs_error_t SrsEdgeForwarder::initialize(SrsSharedPtr<SrsLiveSource> s, SrsPublishEdge *e, ISrsRequest *r)
|
||||
srs_error_t SrsEdgeForwarder::initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPublishEdge *e, ISrsRequest *r)
|
||||
{
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
source_ = s.get();
|
||||
|
|
@ -729,7 +767,7 @@ srs_error_t SrsEdgeForwarder::start()
|
|||
|
||||
std::string url;
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_edge_origin(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_edge_origin(req_->vhost_);
|
||||
srs_assert(conf);
|
||||
|
||||
// select the origin.
|
||||
|
|
@ -738,7 +776,7 @@ srs_error_t SrsEdgeForwarder::start()
|
|||
srs_net_split_hostport(server, server, port);
|
||||
|
||||
// support vhost tranform for edge,
|
||||
std::string vhost = _srs_config->get_vhost_edge_transform_vhost(req_->vhost_);
|
||||
std::string vhost = config_->get_vhost_edge_transform_vhost(req_->vhost_);
|
||||
vhost = srs_strings_replace(vhost, "[vhost]", req_->vhost_);
|
||||
|
||||
url = srs_net_url_encode_rtmp_url(server, port, req_->host_, vhost, req_->app_, req_->stream_, req_->param_);
|
||||
|
|
@ -761,7 +799,7 @@ srs_error_t SrsEdgeForwarder::start()
|
|||
// For RTMP client, we pass the vhost in tcUrl when connecting,
|
||||
// so we publish without vhost in stream.
|
||||
string stream;
|
||||
if ((err = sdk_->publish(_srs_config->get_chunk_size(req_->vhost_), false, &stream)) != srs_success) {
|
||||
if ((err = sdk_->publish(config_->get_chunk_size(req_->vhost_), false, &stream)) != srs_success) {
|
||||
return srs_error_wrap(err, "sdk publish");
|
||||
}
|
||||
|
||||
|
|
@ -905,6 +943,14 @@ srs_error_t SrsEdgeForwarder::proxy(SrsRtmpCommonMessage *msg)
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsPlayEdge::ISrsPlayEdge()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsPlayEdge::~ISrsPlayEdge()
|
||||
{
|
||||
}
|
||||
|
||||
SrsPlayEdge::SrsPlayEdge()
|
||||
{
|
||||
state_ = SrsEdgeStateInit;
|
||||
|
|
@ -983,6 +1029,14 @@ srs_error_t SrsPlayEdge::on_ingest_play()
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsPublishEdge::ISrsPublishEdge()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsPublishEdge::~ISrsPublishEdge()
|
||||
{
|
||||
}
|
||||
|
||||
SrsPublishEdge::SrsPublishEdge()
|
||||
{
|
||||
state_ = SrsEdgeStateInit;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,15 @@ class SrsHttpClient;
|
|||
class ISrsHttpMessage;
|
||||
class SrsHttpFileReader;
|
||||
class SrsFlvDecoder;
|
||||
class ISrsAppConfig;
|
||||
class ISrsBasicRtmpClient;
|
||||
class ISrsHttpClient;
|
||||
class ISrsFileReader;
|
||||
class ISrsFlvDecoder;
|
||||
class ISrsLiveSource;
|
||||
class ISrsPlayEdge;
|
||||
class ISrsPublishEdge;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The state of edge, auto machine
|
||||
enum SrsEdgeState {
|
||||
|
|
@ -57,11 +66,11 @@ enum SrsEdgeUserState {
|
|||
};
|
||||
|
||||
// The upstream of edge, can be rtmp or http.
|
||||
class SrsEdgeUpstream
|
||||
class ISrsEdgeUpstream
|
||||
{
|
||||
public:
|
||||
SrsEdgeUpstream();
|
||||
virtual ~SrsEdgeUpstream();
|
||||
ISrsEdgeUpstream();
|
||||
virtual ~ISrsEdgeUpstream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t connect(ISrsRequest *r, ISrsLbRoundRobin *lb) = 0;
|
||||
|
|
@ -75,15 +84,23 @@ public:
|
|||
virtual void kbps_sample(const char *label, srs_utime_t age) = 0;
|
||||
};
|
||||
|
||||
class SrsEdgeRtmpUpstream : public SrsEdgeUpstream
|
||||
// The RTMP upstream of edge.
|
||||
class SrsEdgeRtmpUpstream : public ISrsEdgeUpstream
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For RTMP 302, if not empty,
|
||||
// use this <ip[:port]> as upstream.
|
||||
std::string redirect_;
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
ISrsBasicRtmpClient *sdk_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Current selected server, the ip:port.
|
||||
std::string selected_ip_;
|
||||
int selected_port_;
|
||||
|
|
@ -105,18 +122,27 @@ public:
|
|||
virtual void kbps_sample(const char *label, srs_utime_t age);
|
||||
};
|
||||
|
||||
class SrsEdgeFlvUpstream : public SrsEdgeUpstream
|
||||
// The HTTP FLV upstream of edge.
|
||||
class SrsEdgeFlvUpstream : public ISrsEdgeUpstream
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string schema_;
|
||||
SrsHttpClient *sdk_;
|
||||
ISrsHttpClient *sdk_;
|
||||
ISrsHttpMessage *hr_;
|
||||
|
||||
private:
|
||||
SrsHttpFileReader *reader_;
|
||||
SrsFlvDecoder *decoder_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFileReader *reader_;
|
||||
ISrsFlvDecoder *decoder_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// We might modify the request by HTTP redirect.
|
||||
ISrsRequest *req_;
|
||||
// Current selected server, the ip:port.
|
||||
|
|
@ -130,7 +156,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t connect(ISrsRequest *r, ISrsLbRoundRobin *lb);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb, int redirect_depth);
|
||||
|
||||
public:
|
||||
|
|
@ -144,26 +171,48 @@ public:
|
|||
virtual void kbps_sample(const char *label, srs_utime_t age);
|
||||
};
|
||||
|
||||
// The edge used to ingest stream from origin.
|
||||
class SrsEdgeIngester : public ISrsCoroutineHandler
|
||||
// The interface for edge ingester.
|
||||
class ISrsEdgeIngester
|
||||
{
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsLiveSource *source_;
|
||||
public:
|
||||
ISrsEdgeIngester();
|
||||
virtual ~ISrsEdgeIngester();
|
||||
|
||||
private:
|
||||
SrsPlayEdge *edge_;
|
||||
public:
|
||||
// Initialize the ingester.
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPlayEdge *e, ISrsRequest *r) = 0;
|
||||
// Start the ingester.
|
||||
virtual srs_error_t start() = 0;
|
||||
// Stop the ingester.
|
||||
virtual void stop() = 0;
|
||||
};
|
||||
|
||||
// The edge used to ingest stream from origin.
|
||||
class SrsEdgeIngester : public ISrsCoroutineHandler, public ISrsEdgeIngester
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsPlayEdge *edge_;
|
||||
ISrsRequest *req_;
|
||||
ISrsCoroutine *trd_;
|
||||
ISrsLbRoundRobin *lb_;
|
||||
SrsEdgeUpstream *upstream_;
|
||||
ISrsEdgeUpstream *upstream_;
|
||||
|
||||
public:
|
||||
SrsEdgeIngester();
|
||||
virtual ~SrsEdgeIngester();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, SrsPlayEdge *e, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPlayEdge *e, ISrsRequest *r);
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
|
||||
|
|
@ -171,23 +220,51 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t ingest(std::string &redirect);
|
||||
virtual srs_error_t process_publish_message(SrsRtmpCommonMessage *msg, std::string &redirect);
|
||||
};
|
||||
|
||||
// The edge used to forward stream to origin.
|
||||
class SrsEdgeForwarder : public ISrsCoroutineHandler
|
||||
// The interface for edge forwarder.
|
||||
class ISrsEdgeForwarder
|
||||
{
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsLiveSource *source_;
|
||||
public:
|
||||
ISrsEdgeForwarder();
|
||||
virtual ~ISrsEdgeForwarder();
|
||||
|
||||
private:
|
||||
SrsPublishEdge *edge_;
|
||||
public:
|
||||
// Set the queue size.
|
||||
virtual void set_queue_size(srs_utime_t queue_size) = 0;
|
||||
// Initialize the forwarder.
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPublishEdge *e, ISrsRequest *r) = 0;
|
||||
// Start the forwarder.
|
||||
virtual srs_error_t start() = 0;
|
||||
// Stop the forwarder.
|
||||
virtual void stop() = 0;
|
||||
// Proxy publish stream to edge.
|
||||
virtual srs_error_t proxy(SrsRtmpCommonMessage *msg) = 0;
|
||||
};
|
||||
|
||||
// The edge used to forward stream to origin.
|
||||
class SrsEdgeForwarder : public ISrsCoroutineHandler, public ISrsEdgeForwarder
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsPublishEdge *edge_;
|
||||
ISrsRequest *req_;
|
||||
ISrsCoroutine *trd_;
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
|
|
@ -208,26 +285,40 @@ public:
|
|||
virtual void set_queue_size(srs_utime_t queue_size);
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, SrsPublishEdge *e, ISrsRequest *r);
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsPublishEdge *e, ISrsRequest *r);
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
// Interface ISrsReusableThread2Handler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
public:
|
||||
virtual srs_error_t proxy(SrsRtmpCommonMessage *msg);
|
||||
};
|
||||
|
||||
// The play edge control service.
|
||||
class SrsPlayEdge
|
||||
// The interface for play edge.
|
||||
class ISrsPlayEdge
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsPlayEdge();
|
||||
virtual ~ISrsPlayEdge();
|
||||
|
||||
public:
|
||||
// When ingester start to play stream.
|
||||
virtual srs_error_t on_ingest_play() = 0;
|
||||
};
|
||||
|
||||
// The play edge control service.
|
||||
class SrsPlayEdge : public ISrsPlayEdge
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsEdgeState state_;
|
||||
SrsEdgeIngester *ingester_;
|
||||
ISrsEdgeIngester *ingester_;
|
||||
|
||||
public:
|
||||
SrsPlayEdge();
|
||||
|
|
@ -248,12 +339,23 @@ public:
|
|||
virtual srs_error_t on_ingest_play();
|
||||
};
|
||||
|
||||
// The publish edge control service.
|
||||
class SrsPublishEdge
|
||||
// The interface for publish edge.
|
||||
class ISrsPublishEdge
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsPublishEdge();
|
||||
virtual ~ISrsPublishEdge();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The publish edge control service.
|
||||
class SrsPublishEdge : public ISrsPublishEdge
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsEdgeState state_;
|
||||
SrsEdgeForwarder *forwarder_;
|
||||
ISrsEdgeForwarder *forwarder_;
|
||||
|
||||
public:
|
||||
SrsPublishEdge();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_ffmpeg.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
|
|
@ -33,6 +34,9 @@ SrsEncoder::SrsEncoder()
|
|||
{
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
pprint_ = SrsPithyPrint::create_encoder();
|
||||
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsEncoder::~SrsEncoder()
|
||||
|
|
@ -41,6 +45,9 @@ SrsEncoder::~SrsEncoder()
|
|||
|
||||
srs_freep(trd_);
|
||||
srs_freep(pprint_);
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsEncoder::on_publish(ISrsRequest *req)
|
||||
|
|
@ -64,7 +71,7 @@ srs_error_t SrsEncoder::on_publish(ISrsRequest *req)
|
|||
|
||||
// start thread to run all encoding engines.
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsSTCoroutine("encoder", this, _srs_context->get_id());
|
||||
trd_ = app_factory_->create_coroutine("encoder", this, _srs_context->get_id());
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start encoder");
|
||||
}
|
||||
|
|
@ -102,10 +109,10 @@ srs_error_t SrsEncoder::cycle()
|
|||
}
|
||||
|
||||
// kill ffmpeg when finished and it alive
|
||||
std::vector<SrsFFMPEG *>::iterator it;
|
||||
std::vector<ISrsFFMPEG *>::iterator it;
|
||||
|
||||
for (it = ffmpegs_.begin(); it != ffmpegs_.end(); ++it) {
|
||||
SrsFFMPEG *ffmpeg = *it;
|
||||
ISrsFFMPEG *ffmpeg = *it;
|
||||
ffmpeg->stop();
|
||||
}
|
||||
|
||||
|
|
@ -116,9 +123,9 @@ srs_error_t SrsEncoder::do_cycle()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
std::vector<SrsFFMPEG *>::iterator it;
|
||||
std::vector<ISrsFFMPEG *>::iterator it;
|
||||
for (it = ffmpegs_.begin(); it != ffmpegs_.end(); ++it) {
|
||||
SrsFFMPEG *ffmpeg = *it;
|
||||
ISrsFFMPEG *ffmpeg = *it;
|
||||
|
||||
// start all ffmpegs.
|
||||
if ((err = ffmpeg->start()) != srs_success) {
|
||||
|
|
@ -139,10 +146,10 @@ srs_error_t SrsEncoder::do_cycle()
|
|||
|
||||
void SrsEncoder::clear_engines()
|
||||
{
|
||||
std::vector<SrsFFMPEG *>::iterator it;
|
||||
std::vector<ISrsFFMPEG *>::iterator it;
|
||||
|
||||
for (it = ffmpegs_.begin(); it != ffmpegs_.end(); ++it) {
|
||||
SrsFFMPEG *ffmpeg = *it;
|
||||
ISrsFFMPEG *ffmpeg = *it;
|
||||
|
||||
std::string output = ffmpeg->output();
|
||||
|
||||
|
|
@ -158,7 +165,7 @@ void SrsEncoder::clear_engines()
|
|||
ffmpegs_.clear();
|
||||
}
|
||||
|
||||
SrsFFMPEG *SrsEncoder::at(int index)
|
||||
ISrsFFMPEG *SrsEncoder::at(int index)
|
||||
{
|
||||
return ffmpegs_[index];
|
||||
}
|
||||
|
|
@ -172,14 +179,14 @@ srs_error_t SrsEncoder::parse_scope_engines(ISrsRequest *req)
|
|||
|
||||
// parse vhost scope engines
|
||||
std::string scope = "";
|
||||
if ((conf = _srs_config->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((conf = config_->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((err = parse_ffmpeg(req, conf)) != srs_success) {
|
||||
return srs_error_wrap(err, "parse ffmpeg");
|
||||
}
|
||||
}
|
||||
// parse app scope engines
|
||||
scope = req->app_;
|
||||
if ((conf = _srs_config->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((conf = config_->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((err = parse_ffmpeg(req, conf)) != srs_success) {
|
||||
return srs_error_wrap(err, "parse ffmpeg");
|
||||
}
|
||||
|
|
@ -187,7 +194,7 @@ srs_error_t SrsEncoder::parse_scope_engines(ISrsRequest *req)
|
|||
// parse stream scope engines
|
||||
scope += "/";
|
||||
scope += req->stream_;
|
||||
if ((conf = _srs_config->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((conf = config_->get_transcode(req->vhost_, scope)) != NULL) {
|
||||
if ((err = parse_ffmpeg(req, conf)) != srs_success) {
|
||||
return srs_error_wrap(err, "parse ffmpeg");
|
||||
}
|
||||
|
|
@ -203,20 +210,20 @@ srs_error_t SrsEncoder::parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf)
|
|||
srs_assert(conf);
|
||||
|
||||
// enabled
|
||||
if (!_srs_config->get_transcode_enabled(conf)) {
|
||||
if (!config_->get_transcode_enabled(conf)) {
|
||||
srs_trace("ignore the disabled transcode: %s", conf->arg0().c_str());
|
||||
return err;
|
||||
}
|
||||
|
||||
// ffmpeg
|
||||
std::string ffmpeg_bin = _srs_config->get_transcode_ffmpeg(conf);
|
||||
std::string ffmpeg_bin = config_->get_transcode_ffmpeg(conf);
|
||||
if (ffmpeg_bin.empty()) {
|
||||
srs_trace("ignore the empty ffmpeg transcode: %s", conf->arg0().c_str());
|
||||
return err;
|
||||
}
|
||||
|
||||
// get all engines.
|
||||
std::vector<SrsConfDirective *> engines = _srs_config->get_transcode_engines(conf);
|
||||
std::vector<SrsConfDirective *> engines = config_->get_transcode_engines(conf);
|
||||
if (engines.empty()) {
|
||||
srs_trace("ignore the empty transcode engine: %s", conf->arg0().c_str());
|
||||
return err;
|
||||
|
|
@ -225,12 +232,12 @@ srs_error_t SrsEncoder::parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf)
|
|||
// create engine
|
||||
for (int i = 0; i < (int)engines.size(); i++) {
|
||||
SrsConfDirective *engine = engines[i];
|
||||
if (!_srs_config->get_engine_enabled(engine)) {
|
||||
if (!config_->get_engine_enabled(engine)) {
|
||||
srs_trace("ignore the diabled transcode engine: %s %s", conf->arg0().c_str(), engine->arg0().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
SrsFFMPEG *ffmpeg = new SrsFFMPEG(ffmpeg_bin);
|
||||
ISrsFFMPEG *ffmpeg = app_factory_->create_ffmpeg(ffmpeg_bin);
|
||||
if ((err = initialize_ffmpeg(ffmpeg, req, engine)) != srs_success) {
|
||||
srs_freep(ffmpeg);
|
||||
return srs_error_wrap(err, "init ffmpeg");
|
||||
|
|
@ -242,7 +249,7 @@ srs_error_t SrsEncoder::parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf)
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsEncoder::initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine)
|
||||
srs_error_t SrsEncoder::initialize_ffmpeg(ISrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -267,7 +274,7 @@ srs_error_t SrsEncoder::initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, S
|
|||
input_stream_name_ += "/";
|
||||
input_stream_name_ += req->stream_;
|
||||
|
||||
std::string output = _srs_config->get_engine_output(engine);
|
||||
std::string output = config_->get_engine_output(engine);
|
||||
// output stream, to other/self server
|
||||
// ie. rtmp://localhost:1935/live/livestream_sd
|
||||
output = srs_strings_replace(output, "[vhost]", req->vhost_);
|
||||
|
|
@ -280,8 +287,8 @@ srs_error_t SrsEncoder::initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, S
|
|||
|
||||
std::string log_file = SRS_CONSTS_NULL_FILE; // disabled
|
||||
// write ffmpeg info to log file.
|
||||
if (_srs_config->get_ff_log_enabled()) {
|
||||
log_file = _srs_config->get_ff_log_dir();
|
||||
if (config_->get_ff_log_enabled()) {
|
||||
log_file = config_->get_ff_log_dir();
|
||||
log_file += "/";
|
||||
log_file += "ffmpeg-encoder";
|
||||
log_file += "-";
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@
|
|||
class SrsConfDirective;
|
||||
class ISrsRequest;
|
||||
class SrsPithyPrint;
|
||||
class ISrsPithyPrint;
|
||||
class SrsFFMPEG;
|
||||
class ISrsFFMPEG;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The encoder interface.
|
||||
class ISrsMediaEncoder
|
||||
|
|
@ -38,13 +42,20 @@ public:
|
|||
// ffmpegs to transcode the specified stream.
|
||||
class SrsEncoder : public ISrsCoroutineHandler, public ISrsMediaEncoder
|
||||
{
|
||||
private:
|
||||
std::string input_stream_name_;
|
||||
std::vector<SrsFFMPEG *> ffmpegs_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string input_stream_name_;
|
||||
std::vector<ISrsFFMPEG *> ffmpegs_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
SrsPithyPrint *pprint_;
|
||||
ISrsPithyPrint *pprint_;
|
||||
|
||||
public:
|
||||
SrsEncoder();
|
||||
|
|
@ -57,15 +68,17 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void clear_engines();
|
||||
virtual SrsFFMPEG *at(int index);
|
||||
virtual ISrsFFMPEG *at(int index);
|
||||
virtual srs_error_t parse_scope_engines(ISrsRequest *req);
|
||||
virtual srs_error_t parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf);
|
||||
virtual srs_error_t initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine);
|
||||
virtual srs_error_t initialize_ffmpeg(ISrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine);
|
||||
virtual void show_encode_log_message();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,21 +6,49 @@
|
|||
|
||||
#include <srs_app_factory.hpp>
|
||||
|
||||
#include <srs_app_caster_flv.hpp>
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_dash.hpp>
|
||||
#include <srs_app_dvr.hpp>
|
||||
#include <srs_app_ffmpeg.hpp>
|
||||
#include <srs_app_fragment.hpp>
|
||||
#ifdef SRS_GB28181
|
||||
#include <srs_app_gb28181.hpp>
|
||||
#endif
|
||||
#include <srs_app_ingest.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#ifdef SRS_RTSP
|
||||
#include <srs_app_rtsp_source.hpp>
|
||||
#endif
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_kernel_flv.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
#include <srs_kernel_mp4.hpp>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_http_client.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
|
||||
ISrsAppFactory::ISrsAppFactory()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsAppFactory::~ISrsAppFactory()
|
||||
{
|
||||
}
|
||||
|
||||
SrsAppFactory::SrsAppFactory()
|
||||
{
|
||||
kernel_factory_ = new SrsFinalFactory();
|
||||
}
|
||||
|
||||
SrsAppFactory::~SrsAppFactory()
|
||||
{
|
||||
srs_freep(kernel_factory_);
|
||||
}
|
||||
|
||||
ISrsFileWriter *SrsAppFactory::create_file_writer()
|
||||
|
|
@ -60,6 +88,127 @@ ISrsHourGlass *SrsAppFactory::create_hourglass(const std::string &name, ISrsHour
|
|||
return new SrsHourGlass(name, handler, interval);
|
||||
}
|
||||
|
||||
ISrsBasicRtmpClient *SrsAppFactory::create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto)
|
||||
{
|
||||
return new SrsSimpleRtmpClient(url, cto, sto);
|
||||
}
|
||||
|
||||
ISrsHttpClient *SrsAppFactory::create_http_client()
|
||||
{
|
||||
return new SrsHttpClient();
|
||||
}
|
||||
|
||||
ISrsFileReader *SrsAppFactory::create_http_file_reader(ISrsHttpResponseReader *r)
|
||||
{
|
||||
return new SrsHttpFileReader(r);
|
||||
}
|
||||
|
||||
ISrsFlvDecoder *SrsAppFactory::create_flv_decoder()
|
||||
{
|
||||
return new SrsFlvDecoder();
|
||||
}
|
||||
|
||||
#ifdef SRS_RTSP
|
||||
ISrsRtspSendTrack *SrsAppFactory::create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
{
|
||||
return new SrsRtspAudioSendTrack(session, track_desc);
|
||||
}
|
||||
|
||||
ISrsRtspSendTrack *SrsAppFactory::create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
{
|
||||
return new SrsRtspVideoSendTrack(session, track_desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
ISrsFlvTransmuxer *SrsAppFactory::create_flv_transmuxer()
|
||||
{
|
||||
return new SrsFlvTransmuxer();
|
||||
}
|
||||
|
||||
ISrsMp4Encoder *SrsAppFactory::create_mp4_encoder()
|
||||
{
|
||||
return new SrsMp4Encoder();
|
||||
}
|
||||
|
||||
ISrsDvrSegmenter *SrsAppFactory::create_dvr_flv_segmenter()
|
||||
{
|
||||
return new SrsDvrFlvSegmenter();
|
||||
}
|
||||
|
||||
ISrsDvrSegmenter *SrsAppFactory::create_dvr_mp4_segmenter()
|
||||
{
|
||||
return new SrsDvrMp4Segmenter();
|
||||
}
|
||||
|
||||
#ifdef SRS_GB28181
|
||||
ISrsGbMediaTcpConn *SrsAppFactory::create_gb_media_tcp_conn()
|
||||
{
|
||||
return new SrsGbMediaTcpConn();
|
||||
}
|
||||
|
||||
ISrsGbSession *SrsAppFactory::create_gb_session()
|
||||
{
|
||||
return new SrsGbSession();
|
||||
}
|
||||
#endif
|
||||
|
||||
ISrsInitMp4 *SrsAppFactory::create_init_mp4()
|
||||
{
|
||||
return new SrsInitMp4();
|
||||
}
|
||||
|
||||
ISrsFragmentWindow *SrsAppFactory::create_fragment_window()
|
||||
{
|
||||
return new SrsFragmentWindow();
|
||||
}
|
||||
|
||||
ISrsFragmentedMp4 *SrsAppFactory::create_fragmented_mp4()
|
||||
{
|
||||
return new SrsFragmentedMp4();
|
||||
}
|
||||
|
||||
ISrsIpListener *SrsAppFactory::create_tcp_listener(ISrsTcpHandler *handler)
|
||||
{
|
||||
return new SrsTcpListener(handler);
|
||||
}
|
||||
|
||||
ISrsRtcConnection *SrsAppFactory::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
SrsRtcConnection *session = new SrsRtcConnection(exec, cid);
|
||||
session->assemble();
|
||||
return session;
|
||||
}
|
||||
|
||||
ISrsFFMPEG *SrsAppFactory::create_ffmpeg(std::string ffmpeg_bin)
|
||||
{
|
||||
return new SrsFFMPEG(ffmpeg_bin);
|
||||
}
|
||||
|
||||
ISrsIngesterFFMPEG *SrsAppFactory::create_ingester_ffmpeg()
|
||||
{
|
||||
return new SrsIngesterFFMPEG();
|
||||
}
|
||||
|
||||
ISrsCoroutine *SrsAppFactory::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid)
|
||||
{
|
||||
return kernel_factory_->create_coroutine(name, handler, cid);
|
||||
}
|
||||
|
||||
ISrsTime *SrsAppFactory::create_time()
|
||||
{
|
||||
return kernel_factory_->create_time();
|
||||
}
|
||||
|
||||
ISrsConfig *SrsAppFactory::create_config()
|
||||
{
|
||||
return kernel_factory_->create_config();
|
||||
}
|
||||
|
||||
ISrsCond *SrsAppFactory::create_cond()
|
||||
{
|
||||
return kernel_factory_->create_cond();
|
||||
}
|
||||
|
||||
SrsFinalFactory::SrsFinalFactory()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,78 @@ class SrsLiveSource;
|
|||
class ISrsOriginHub;
|
||||
class ISrsHourGlass;
|
||||
class ISrsHourGlassHandler;
|
||||
class ISrsBasicRtmpClient;
|
||||
class ISrsHttpClient;
|
||||
class ISrsFileReader;
|
||||
class ISrsFlvDecoder;
|
||||
class ISrsHttpResponseReader;
|
||||
class ISrsRtspSendTrack;
|
||||
class ISrsRtspConnection;
|
||||
class SrsRtcTrackDescription;
|
||||
class ISrsFlvTransmuxer;
|
||||
class ISrsMp4Encoder;
|
||||
class ISrsDvrSegmenter;
|
||||
class ISrsGbMediaTcpConn;
|
||||
class ISrsGbSession;
|
||||
class ISrsFragment;
|
||||
class ISrsInitMp4;
|
||||
class ISrsFragmentWindow;
|
||||
class ISrsFragmentedMp4;
|
||||
class SrsFinalFactory;
|
||||
class ISrsIpListener;
|
||||
class ISrsTcpHandler;
|
||||
class ISrsRtcConnection;
|
||||
class ISrsExecRtcAsyncTask;
|
||||
class ISrsFFMPEG;
|
||||
class ISrsIngesterFFMPEG;
|
||||
|
||||
// The factory to create app objects.
|
||||
class SrsAppFactory
|
||||
class ISrsAppFactory : public ISrsKernelFactory
|
||||
{
|
||||
public:
|
||||
ISrsAppFactory();
|
||||
virtual ~ISrsAppFactory();
|
||||
|
||||
public:
|
||||
virtual ISrsFileWriter *create_file_writer() = 0;
|
||||
virtual ISrsFileWriter *create_enc_file_writer() = 0;
|
||||
virtual ISrsFileReader *create_file_reader() = 0;
|
||||
virtual SrsPath *create_path() = 0;
|
||||
virtual SrsLiveSource *create_live_source() = 0;
|
||||
virtual ISrsOriginHub *create_origin_hub() = 0;
|
||||
virtual ISrsHourGlass *create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval) = 0;
|
||||
virtual ISrsBasicRtmpClient *create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto) = 0;
|
||||
virtual ISrsHttpClient *create_http_client() = 0;
|
||||
virtual ISrsFileReader *create_http_file_reader(ISrsHttpResponseReader *r) = 0;
|
||||
virtual ISrsFlvDecoder *create_flv_decoder() = 0;
|
||||
#ifdef SRS_RTSP
|
||||
virtual ISrsRtspSendTrack *create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc) = 0;
|
||||
virtual ISrsRtspSendTrack *create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc) = 0;
|
||||
#endif
|
||||
virtual ISrsFlvTransmuxer *create_flv_transmuxer() = 0;
|
||||
virtual ISrsMp4Encoder *create_mp4_encoder() = 0;
|
||||
virtual ISrsDvrSegmenter *create_dvr_flv_segmenter() = 0;
|
||||
virtual ISrsDvrSegmenter *create_dvr_mp4_segmenter() = 0;
|
||||
#ifdef SRS_GB28181
|
||||
virtual ISrsGbMediaTcpConn *create_gb_media_tcp_conn() = 0;
|
||||
virtual ISrsGbSession *create_gb_session() = 0;
|
||||
#endif
|
||||
virtual ISrsInitMp4 *create_init_mp4() = 0;
|
||||
virtual ISrsFragmentWindow *create_fragment_window() = 0;
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4() = 0;
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler) = 0;
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid) = 0;
|
||||
virtual ISrsFFMPEG *create_ffmpeg(std::string ffmpeg_bin) = 0;
|
||||
virtual ISrsIngesterFFMPEG *create_ingester_ffmpeg() = 0;
|
||||
};
|
||||
|
||||
// The factory to create app objects.
|
||||
class SrsAppFactory : public ISrsAppFactory
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsKernelFactory *kernel_factory_;
|
||||
|
||||
public:
|
||||
SrsAppFactory();
|
||||
virtual ~SrsAppFactory();
|
||||
|
|
@ -34,9 +102,38 @@ public:
|
|||
virtual SrsLiveSource *create_live_source();
|
||||
virtual ISrsOriginHub *create_origin_hub();
|
||||
virtual ISrsHourGlass *create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval);
|
||||
virtual ISrsBasicRtmpClient *create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto);
|
||||
virtual ISrsHttpClient *create_http_client();
|
||||
virtual ISrsFileReader *create_http_file_reader(ISrsHttpResponseReader *r);
|
||||
virtual ISrsFlvDecoder *create_flv_decoder();
|
||||
#ifdef SRS_RTSP
|
||||
virtual ISrsRtspSendTrack *create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
virtual ISrsRtspSendTrack *create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
#endif
|
||||
virtual ISrsFlvTransmuxer *create_flv_transmuxer();
|
||||
virtual ISrsMp4Encoder *create_mp4_encoder();
|
||||
virtual ISrsDvrSegmenter *create_dvr_flv_segmenter();
|
||||
virtual ISrsDvrSegmenter *create_dvr_mp4_segmenter();
|
||||
#ifdef SRS_GB28181
|
||||
virtual ISrsGbMediaTcpConn *create_gb_media_tcp_conn();
|
||||
virtual ISrsGbSession *create_gb_session();
|
||||
#endif
|
||||
virtual ISrsInitMp4 *create_init_mp4();
|
||||
virtual ISrsFragmentWindow *create_fragment_window();
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4();
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler);
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
virtual ISrsFFMPEG *create_ffmpeg(std::string ffmpeg_bin);
|
||||
virtual ISrsIngesterFFMPEG *create_ingester_ffmpeg();
|
||||
|
||||
public:
|
||||
virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid);
|
||||
virtual ISrsTime *create_time();
|
||||
virtual ISrsConfig *create_config();
|
||||
virtual ISrsCond *create_cond();
|
||||
};
|
||||
|
||||
extern SrsAppFactory *_srs_app_factory;
|
||||
extern ISrsAppFactory *_srs_app_factory;
|
||||
|
||||
// The factory to create kernel objects.
|
||||
class SrsFinalFactory : public ISrsKernelFactory
|
||||
|
|
|
|||
|
|
@ -44,6 +44,14 @@ using namespace std;
|
|||
#define SRS_RTMP_ENCODER_LIBAACPLUS "libaacplus"
|
||||
#define SRS_RTMP_ENCODER_LIBFDKAAC "libfdk_aac"
|
||||
|
||||
ISrsFFMPEG::ISrsFFMPEG()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFFMPEG::~ISrsFFMPEG()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
|
||||
{
|
||||
ffmpeg_ = ffmpeg_bin;
|
||||
|
|
@ -58,6 +66,8 @@ SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
|
|||
achannels_ = 0;
|
||||
|
||||
process_ = new SrsProcess();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsFFMPEG::~SrsFFMPEG()
|
||||
|
|
@ -65,6 +75,8 @@ SrsFFMPEG::~SrsFFMPEG()
|
|||
stop();
|
||||
|
||||
srs_freep(process_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsFFMPEG::append_iparam(string iparam)
|
||||
|
|
@ -97,24 +109,24 @@ srs_error_t SrsFFMPEG::initialize_transcode(SrsConfDirective *engine)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
perfile_ = _srs_config->get_engine_perfile(engine);
|
||||
iformat_ = _srs_config->get_engine_iformat(engine);
|
||||
vfilter_ = _srs_config->get_engine_vfilter(engine);
|
||||
vcodec_ = _srs_config->get_engine_vcodec(engine);
|
||||
vbitrate_ = _srs_config->get_engine_vbitrate(engine);
|
||||
vfps_ = _srs_config->get_engine_vfps(engine);
|
||||
vwidth_ = _srs_config->get_engine_vwidth(engine);
|
||||
vheight_ = _srs_config->get_engine_vheight(engine);
|
||||
vthreads_ = _srs_config->get_engine_vthreads(engine);
|
||||
vprofile_ = _srs_config->get_engine_vprofile(engine);
|
||||
vpreset_ = _srs_config->get_engine_vpreset(engine);
|
||||
vparams_ = _srs_config->get_engine_vparams(engine);
|
||||
acodec_ = _srs_config->get_engine_acodec(engine);
|
||||
abitrate_ = _srs_config->get_engine_abitrate(engine);
|
||||
asample_rate_ = _srs_config->get_engine_asample_rate(engine);
|
||||
achannels_ = _srs_config->get_engine_achannels(engine);
|
||||
aparams_ = _srs_config->get_engine_aparams(engine);
|
||||
oformat_ = _srs_config->get_engine_oformat(engine);
|
||||
perfile_ = config_->get_engine_perfile(engine);
|
||||
iformat_ = config_->get_engine_iformat(engine);
|
||||
vfilter_ = config_->get_engine_vfilter(engine);
|
||||
vcodec_ = config_->get_engine_vcodec(engine);
|
||||
vbitrate_ = config_->get_engine_vbitrate(engine);
|
||||
vfps_ = config_->get_engine_vfps(engine);
|
||||
vwidth_ = config_->get_engine_vwidth(engine);
|
||||
vheight_ = config_->get_engine_vheight(engine);
|
||||
vthreads_ = config_->get_engine_vthreads(engine);
|
||||
vprofile_ = config_->get_engine_vprofile(engine);
|
||||
vpreset_ = config_->get_engine_vpreset(engine);
|
||||
vparams_ = config_->get_engine_vparams(engine);
|
||||
acodec_ = config_->get_engine_acodec(engine);
|
||||
abitrate_ = config_->get_engine_abitrate(engine);
|
||||
asample_rate_ = config_->get_engine_asample_rate(engine);
|
||||
achannels_ = config_->get_engine_achannels(engine);
|
||||
aparams_ = config_->get_engine_aparams(engine);
|
||||
oformat_ = config_->get_engine_oformat(engine);
|
||||
|
||||
// ensure the size is even.
|
||||
vwidth_ -= vwidth_ % 2;
|
||||
|
|
|
|||
|
|
@ -16,19 +16,56 @@
|
|||
|
||||
class SrsConfDirective;
|
||||
class SrsPithyPrint;
|
||||
class ISrsPithyPrint;
|
||||
class SrsProcess;
|
||||
class ISrsProcess;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The ffmpeg interface.
|
||||
class ISrsFFMPEG
|
||||
{
|
||||
public:
|
||||
ISrsFFMPEG();
|
||||
virtual ~ISrsFFMPEG();
|
||||
|
||||
public:
|
||||
virtual void append_iparam(std::string iparam) = 0;
|
||||
virtual void set_oformat(std::string format) = 0;
|
||||
virtual std::string output() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(std::string in, std::string out, std::string log) = 0;
|
||||
virtual srs_error_t initialize_transcode(SrsConfDirective *engine) = 0;
|
||||
virtual srs_error_t initialize_copy() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
public:
|
||||
virtual void fast_stop() = 0;
|
||||
virtual void fast_kill() = 0;
|
||||
};
|
||||
|
||||
// A transcode engine: ffmepg, used to transcode a stream to another.
|
||||
class SrsFFMPEG
|
||||
class SrsFFMPEG : public ISrsFFMPEG
|
||||
{
|
||||
private:
|
||||
SrsProcess *process_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsProcess *process_;
|
||||
std::vector<std::string> params_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string log_file_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string ffmpeg_;
|
||||
std::vector<std::string> iparams_;
|
||||
std::vector<std::string> perfile_;
|
||||
|
|
|
|||
|
|
@ -45,19 +45,23 @@ public:
|
|||
// Forward the stream to other servers.
|
||||
class SrsForwarder : public ISrsCoroutineHandler, public ISrsForwarder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The ep to forward, server[:port].
|
||||
std::string ep_forward_;
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The source or stream context id to bind to.
|
||||
SrsContextId source_cid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsOriginHub *hub_;
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
SrsRtmpJitter *jitter_;
|
||||
|
|
@ -90,10 +94,12 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t forward();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@
|
|||
#include <unistd.h>
|
||||
using namespace std;
|
||||
|
||||
ISrsFragment::ISrsFragment()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFragment::~ISrsFragment()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFragment::SrsFragment()
|
||||
{
|
||||
dur_ = 0;
|
||||
|
|
@ -155,22 +163,30 @@ uint64_t SrsFragment::number()
|
|||
return number_;
|
||||
}
|
||||
|
||||
ISrsFragmentWindow::ISrsFragmentWindow()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFragmentWindow::~ISrsFragmentWindow()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFragmentWindow::SrsFragmentWindow()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFragmentWindow::~SrsFragmentWindow()
|
||||
{
|
||||
vector<SrsFragment *>::iterator it;
|
||||
vector<ISrsFragment *>::iterator it;
|
||||
|
||||
for (it = fragments_.begin(); it != fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
srs_freep(fragment);
|
||||
}
|
||||
fragments_.clear();
|
||||
|
||||
for (it = expired_fragments_.begin(); it != expired_fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
srs_freep(fragment);
|
||||
}
|
||||
expired_fragments_.clear();
|
||||
|
|
@ -180,10 +196,10 @@ void SrsFragmentWindow::dispose()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
std::vector<SrsFragment *>::iterator it;
|
||||
std::vector<ISrsFragment *>::iterator it;
|
||||
|
||||
for (it = fragments_.begin(); it != fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
if ((err = fragment->unlink_file()) != srs_success) {
|
||||
srs_warn("Unlink ts failed %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
|
|
@ -193,7 +209,7 @@ void SrsFragmentWindow::dispose()
|
|||
fragments_.clear();
|
||||
|
||||
for (it = expired_fragments_.begin(); it != expired_fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
if ((err = fragment->unlink_file()) != srs_success) {
|
||||
srs_warn("Unlink ts failed %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
|
|
@ -203,7 +219,7 @@ void SrsFragmentWindow::dispose()
|
|||
expired_fragments_.clear();
|
||||
}
|
||||
|
||||
void SrsFragmentWindow::append(SrsFragment *fragment)
|
||||
void SrsFragmentWindow::append(ISrsFragment *fragment)
|
||||
{
|
||||
fragments_.push_back(fragment);
|
||||
}
|
||||
|
|
@ -215,7 +231,7 @@ void SrsFragmentWindow::shrink(srs_utime_t window)
|
|||
int remove_index = -1;
|
||||
|
||||
for (int i = (int)fragments_.size() - 1; i >= 0; i--) {
|
||||
SrsFragment *fragment = fragments_[i];
|
||||
ISrsFragment *fragment = fragments_[i];
|
||||
duration += fragment->duration();
|
||||
|
||||
if (duration > window) {
|
||||
|
|
@ -225,7 +241,7 @@ void SrsFragmentWindow::shrink(srs_utime_t window)
|
|||
}
|
||||
|
||||
for (int i = 0; i < remove_index && !fragments_.empty(); i++) {
|
||||
SrsFragment *fragment = *fragments_.begin();
|
||||
ISrsFragment *fragment = *fragments_.begin();
|
||||
fragments_.erase(fragments_.begin());
|
||||
expired_fragments_.push_back(fragment);
|
||||
}
|
||||
|
|
@ -235,10 +251,10 @@ void SrsFragmentWindow::clear_expired(bool delete_files)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
std::vector<SrsFragment *>::iterator it;
|
||||
std::vector<ISrsFragment *>::iterator it;
|
||||
|
||||
for (it = expired_fragments_.begin(); it != expired_fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
if (delete_files && (err = fragment->unlink_file()) != srs_success) {
|
||||
srs_warn("Unlink ts failed, %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
|
|
@ -253,10 +269,10 @@ srs_utime_t SrsFragmentWindow::max_duration()
|
|||
{
|
||||
srs_utime_t v = 0;
|
||||
|
||||
std::vector<SrsFragment *>::iterator it;
|
||||
std::vector<ISrsFragment *>::iterator it;
|
||||
|
||||
for (it = fragments_.begin(); it != fragments_.end(); ++it) {
|
||||
SrsFragment *fragment = *it;
|
||||
ISrsFragment *fragment = *it;
|
||||
v = srs_max(v, fragment->duration());
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +284,7 @@ bool SrsFragmentWindow::empty()
|
|||
return fragments_.empty();
|
||||
}
|
||||
|
||||
SrsFragment *SrsFragmentWindow::first()
|
||||
ISrsFragment *SrsFragmentWindow::first()
|
||||
{
|
||||
return fragments_.at(0);
|
||||
}
|
||||
|
|
@ -278,7 +294,7 @@ int SrsFragmentWindow::size()
|
|||
return (int)fragments_.size();
|
||||
}
|
||||
|
||||
SrsFragment *SrsFragmentWindow::at(int index)
|
||||
ISrsFragment *SrsFragmentWindow::at(int index)
|
||||
{
|
||||
return fragments_.at(index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,47 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Forward declarations
|
||||
class SrsFormat;
|
||||
|
||||
// The fragment interface.
|
||||
class ISrsFragment
|
||||
{
|
||||
public:
|
||||
ISrsFragment();
|
||||
virtual ~ISrsFragment();
|
||||
|
||||
public:
|
||||
// Set the full path of fragment.
|
||||
virtual void set_path(std::string v) = 0;
|
||||
// Get the temporary path for file.
|
||||
virtual std::string tmppath() = 0;
|
||||
// Rename the temp file to final file.
|
||||
virtual srs_error_t rename() = 0;
|
||||
// Append a frame with dts into fragment.
|
||||
virtual void append(int64_t dts) = 0;
|
||||
// Create the dir for file recursively.
|
||||
virtual srs_error_t create_dir() = 0;
|
||||
// Set the number of this fragment.
|
||||
virtual void set_number(uint64_t n) = 0;
|
||||
// Get the number of this fragment.
|
||||
virtual uint64_t number() = 0;
|
||||
// Get the duration of fragment in srs_utime_t.
|
||||
virtual srs_utime_t duration() = 0;
|
||||
// Unlink the temporary file.
|
||||
virtual srs_error_t unlink_tmpfile() = 0;
|
||||
// Get the start dts of fragment.
|
||||
virtual srs_utime_t get_start_dts() = 0;
|
||||
// Unlink the fragment, to delete the file.
|
||||
virtual srs_error_t unlink_file() = 0;
|
||||
};
|
||||
|
||||
// Represent a fragment, such as HLS segment, DVR segment or DASH segment.
|
||||
// It's a media file, for example FLV or MP4, with duration.
|
||||
class SrsFragment
|
||||
class SrsFragment : public ISrsFragment
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The duration in srs_utime_t.
|
||||
srs_utime_t dur_;
|
||||
// The full file path of fragment.
|
||||
|
|
@ -68,13 +104,40 @@ public:
|
|||
virtual uint64_t number();
|
||||
};
|
||||
|
||||
// The fragment window manage a series of fragment.
|
||||
class SrsFragmentWindow
|
||||
// The fragment window interface.
|
||||
class ISrsFragmentWindow
|
||||
{
|
||||
private:
|
||||
std::vector<SrsFragment *> fragments_;
|
||||
public:
|
||||
ISrsFragmentWindow();
|
||||
virtual ~ISrsFragmentWindow();
|
||||
|
||||
public:
|
||||
// Dispose all fragments, delete the files.
|
||||
virtual void dispose() = 0;
|
||||
// Append a new fragment, which is ready to delivery to client.
|
||||
virtual void append(ISrsFragment *fragment) = 0;
|
||||
// Shrink the window, push the expired fragment to a queue.
|
||||
virtual void shrink(srs_utime_t window) = 0;
|
||||
// Clear the expired fragments.
|
||||
virtual void clear_expired(bool delete_files) = 0;
|
||||
// Get the max duration in srs_utime_t of all fragments.
|
||||
virtual srs_utime_t max_duration() = 0;
|
||||
|
||||
public:
|
||||
virtual bool empty() = 0;
|
||||
virtual ISrsFragment *first() = 0;
|
||||
virtual int size() = 0;
|
||||
virtual ISrsFragment *at(int index) = 0;
|
||||
};
|
||||
|
||||
// The fragment window manage a series of fragment.
|
||||
class SrsFragmentWindow : public ISrsFragmentWindow
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<ISrsFragment *> fragments_;
|
||||
// The expired fragments, need to be free in future.
|
||||
std::vector<SrsFragment *> expired_fragments_;
|
||||
std::vector<ISrsFragment *> expired_fragments_;
|
||||
|
||||
public:
|
||||
SrsFragmentWindow();
|
||||
|
|
@ -84,7 +147,7 @@ public:
|
|||
// Dispose all fragments, delete the files.
|
||||
virtual void dispose();
|
||||
// Append a new fragment, which is ready to delivery to client.
|
||||
virtual void append(SrsFragment *fragment);
|
||||
virtual void append(ISrsFragment *fragment);
|
||||
// Shrink the window, push the expired fragment to a queue.
|
||||
virtual void shrink(srs_utime_t window);
|
||||
// Clear the expired fragments.
|
||||
|
|
@ -94,9 +157,9 @@ public:
|
|||
|
||||
public:
|
||||
virtual bool empty();
|
||||
virtual SrsFragment *first();
|
||||
virtual ISrsFragment *first();
|
||||
virtual int size();
|
||||
virtual SrsFragment *at(int index);
|
||||
virtual ISrsFragment *at(int index);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <srs_app_gb28181.hpp>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_api.hpp>
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
|
|
@ -55,6 +56,14 @@ std::string srs_gb_state(SrsGbSessionState ostate, SrsGbSessionState state)
|
|||
return srs_fmt_sprintf("%s->%s", srs_gb_session_state(ostate).c_str(), srs_gb_session_state(state).c_str());
|
||||
}
|
||||
|
||||
ISrsGbSession::ISrsGbSession()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsGbSession::~ISrsGbSession()
|
||||
{
|
||||
}
|
||||
|
||||
SrsGbSession::SrsGbSession() : media_(new SrsGbMediaTcpConn())
|
||||
{
|
||||
wrapper_ = NULL;
|
||||
|
|
@ -86,23 +95,27 @@ SrsGbSession::SrsGbSession() : media_(new SrsGbMediaTcpConn())
|
|||
|
||||
cid_ = _srs_context->generate_id();
|
||||
_srs_context->set_id(cid_); // Also change current coroutine cid as session's.
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsGbSession::~SrsGbSession()
|
||||
{
|
||||
srs_freep(muxer_);
|
||||
srs_freep(ppp_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsGbSession::setup(SrsConfDirective *conf)
|
||||
{
|
||||
std::string output = _srs_config->get_stream_caster_output(conf);
|
||||
std::string output = config_->get_stream_caster_output(conf);
|
||||
muxer_->setup(output);
|
||||
|
||||
srs_trace("Session: Start output=%s", output.c_str());
|
||||
}
|
||||
|
||||
void SrsGbSession::setup_owner(SrsSharedResource<SrsGbSession> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
void SrsGbSession::setup_owner(SrsSharedResource<ISrsGbSession> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
{
|
||||
wrapper_ = wrapper;
|
||||
owner_coroutine_ = owner_coroutine;
|
||||
|
|
@ -114,7 +127,7 @@ void SrsGbSession::on_executor_done(ISrsInterruptable *executor)
|
|||
owner_coroutine_ = NULL;
|
||||
}
|
||||
|
||||
void SrsGbSession::on_ps_pack(SrsPackContext *ctx, SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs)
|
||||
void SrsGbSession::on_ps_pack(ISrsPackContext *ctx, SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs)
|
||||
{
|
||||
// Got a new context, that is new media transport.
|
||||
if (media_id_ != ctx->media_id_) {
|
||||
|
|
@ -172,7 +185,7 @@ void SrsGbSession::on_ps_pack(SrsPackContext *ctx, SrsPsPacket *ps, const std::v
|
|||
}
|
||||
}
|
||||
|
||||
void SrsGbSession::on_media_transport(SrsSharedResource<SrsGbMediaTcpConn> media)
|
||||
void SrsGbSession::on_media_transport(SrsSharedResource<ISrsGbMediaTcpConn> media)
|
||||
{
|
||||
media_ = media;
|
||||
|
||||
|
|
@ -301,29 +314,54 @@ std::string SrsGbSession::desc()
|
|||
return "GBS";
|
||||
}
|
||||
|
||||
ISrsGbListener::ISrsGbListener()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsGbListener::~ISrsGbListener()
|
||||
{
|
||||
}
|
||||
|
||||
SrsGbListener::SrsGbListener()
|
||||
{
|
||||
conf_ = NULL;
|
||||
media_listener_ = new SrsTcpListener(this);
|
||||
|
||||
config_ = _srs_config;
|
||||
api_server_owner_ = NULL;
|
||||
gb_manager_ = _srs_gb_manager;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsGbListener::~SrsGbListener()
|
||||
{
|
||||
srs_freep(conf_);
|
||||
srs_freep(media_listener_);
|
||||
|
||||
config_ = NULL;
|
||||
api_server_owner_ = NULL;
|
||||
gb_manager_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGbListener::initialize(SrsConfDirective *conf)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// We should initialize the owner in initialize, because the SRS server
|
||||
// is not ready in the constructor.
|
||||
if (!api_server_owner_) {
|
||||
api_server_owner_ = _srs_server;
|
||||
}
|
||||
|
||||
srs_freep(conf_);
|
||||
conf_ = conf->copy();
|
||||
|
||||
string ip = srs_net_address_any();
|
||||
if (true) {
|
||||
int port = _srs_config->get_stream_caster_listen(conf);
|
||||
media_listener_->set_endpoint(ip, port)->set_label("GB-TCP");
|
||||
int port = config_->get_stream_caster_listen(conf);
|
||||
media_listener_->set_endpoint(ip, port);
|
||||
media_listener_->set_label("GB-TCP");
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
@ -348,7 +386,11 @@ srs_error_t SrsGbListener::listen_api()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
ISrsHttpServeMux *mux = _srs_server->api_server();
|
||||
ISrsCommonHttpHandler *mux = api_server_owner_->api_server();
|
||||
if (!mux) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = mux->handle("/gb/v1/publish/", new SrsGoApiGbPublish(conf_))) != srs_success) {
|
||||
return srs_error_wrap(err, "handle publish");
|
||||
}
|
||||
|
|
@ -366,13 +408,13 @@ srs_error_t SrsGbListener::on_tcp_client(ISrsListener *listener, srs_netfd_t stf
|
|||
|
||||
// Handle TCP connections.
|
||||
if (listener == media_listener_) {
|
||||
SrsGbMediaTcpConn *raw_conn = new SrsGbMediaTcpConn();
|
||||
ISrsGbMediaTcpConn *raw_conn = app_factory_->create_gb_media_tcp_conn();
|
||||
raw_conn->setup(stfd);
|
||||
|
||||
SrsSharedResource<SrsGbMediaTcpConn> *conn = new SrsSharedResource<SrsGbMediaTcpConn>(raw_conn);
|
||||
_srs_gb_manager->add(conn, NULL);
|
||||
SrsSharedResource<ISrsGbMediaTcpConn> *conn = new SrsSharedResource<ISrsGbMediaTcpConn>(raw_conn);
|
||||
gb_manager_->add(conn, NULL);
|
||||
|
||||
SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(_srs_gb_manager, conn, raw_conn, raw_conn);
|
||||
SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(gb_manager_, conn, raw_conn, raw_conn);
|
||||
raw_conn->setup_owner(conn, executor, executor);
|
||||
|
||||
if ((err = executor->start()) != srs_success) {
|
||||
|
|
@ -395,6 +437,14 @@ ISrsPsPackHandler::~ISrsPsPackHandler()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsGbMediaTcpConn::ISrsGbMediaTcpConn()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsGbMediaTcpConn::~ISrsGbMediaTcpConn()
|
||||
{
|
||||
}
|
||||
|
||||
SrsGbMediaTcpConn::SrsGbMediaTcpConn()
|
||||
{
|
||||
pack_ = new SrsPackContext(this);
|
||||
|
|
@ -409,6 +459,8 @@ SrsGbMediaTcpConn::SrsGbMediaTcpConn()
|
|||
session_ = NULL;
|
||||
connected_ = false;
|
||||
nn_rtcp_ = 0;
|
||||
|
||||
gb_manager_ = _srs_gb_manager;
|
||||
}
|
||||
|
||||
SrsGbMediaTcpConn::~SrsGbMediaTcpConn()
|
||||
|
|
@ -416,6 +468,8 @@ SrsGbMediaTcpConn::~SrsGbMediaTcpConn()
|
|||
srs_freep(conn_);
|
||||
srs_freepa(buffer_);
|
||||
srs_freep(pack_);
|
||||
|
||||
gb_manager_ = NULL;
|
||||
}
|
||||
|
||||
void SrsGbMediaTcpConn::setup(srs_netfd_t stfd)
|
||||
|
|
@ -424,7 +478,7 @@ void SrsGbMediaTcpConn::setup(srs_netfd_t stfd)
|
|||
conn_ = new SrsTcpConnection(stfd);
|
||||
}
|
||||
|
||||
void SrsGbMediaTcpConn::setup_owner(SrsSharedResource<SrsGbMediaTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
void SrsGbMediaTcpConn::setup_owner(SrsSharedResource<ISrsGbMediaTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
{
|
||||
wrapper_ = wrapper;
|
||||
owner_coroutine_ = owner_coroutine;
|
||||
|
|
@ -511,7 +565,7 @@ srs_error_t SrsGbMediaTcpConn::do_cycle()
|
|||
SrsRecoverablePsContext context;
|
||||
|
||||
// If bytes is not enough(defined by SRS_PS_MIN_REQUIRED), ignore.
|
||||
context.ctx_.set_detect_ps_integrity(true);
|
||||
context.ctx_->set_detect_ps_integrity(true);
|
||||
|
||||
// Previous left bytes, to parse in next loop.
|
||||
uint32_t reserved = 0;
|
||||
|
|
@ -538,8 +592,8 @@ srs_error_t SrsGbMediaTcpConn::do_cycle()
|
|||
}
|
||||
|
||||
if (length > SRS_GB_LARGE_PACKET) {
|
||||
const SrsPsDecodeHelper &h = context.ctx_.helper_;
|
||||
srs_warn("PS: Large length=%u, previous-seq=%u, previous-ts=%u", length, h.rtp_seq_, h.rtp_ts_);
|
||||
const SrsPsDecodeHelper *h = context.ctx_->helper();
|
||||
srs_warn("PS: Large length=%u, previous-seq=%u, previous-ts=%u", length, h->rtp_seq_, h->rtp_ts_);
|
||||
}
|
||||
|
||||
// Read length of bytes of RTP packet.
|
||||
|
|
@ -629,7 +683,7 @@ srs_error_t SrsGbMediaTcpConn::on_ps_pack(SrsPsPacket *ps, const std::vector<Srs
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsGbMediaTcpConn::bind_session(uint32_t ssrc, SrsGbSession **psession)
|
||||
srs_error_t SrsGbMediaTcpConn::bind_session(uint32_t ssrc, ISrsGbSession **psession)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -637,11 +691,11 @@ srs_error_t SrsGbMediaTcpConn::bind_session(uint32_t ssrc, SrsGbSession **psessi
|
|||
return err;
|
||||
|
||||
// Find exists session for register, might be created by another object and still alive.
|
||||
SrsSharedResource<SrsGbSession> *session = dynamic_cast<SrsSharedResource<SrsGbSession> *>(_srs_gb_manager->find_by_fast_id(ssrc));
|
||||
SrsSharedResource<ISrsGbSession> *session = dynamic_cast<SrsSharedResource<ISrsGbSession> *>(gb_manager_->find_by_fast_id(ssrc));
|
||||
if (!session)
|
||||
return err;
|
||||
|
||||
SrsGbSession *raw_session = (*session).get();
|
||||
ISrsGbSession *raw_session = (*session).get();
|
||||
srs_assert(raw_session);
|
||||
|
||||
// Notice session to use current media connection.
|
||||
|
|
@ -651,6 +705,14 @@ srs_error_t SrsGbMediaTcpConn::bind_session(uint32_t ssrc, SrsGbSession **psessi
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsMpegpsQueue::ISrsMpegpsQueue()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMpegpsQueue::~ISrsMpegpsQueue()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpegpsQueue::SrsMpegpsQueue()
|
||||
{
|
||||
nb_audios_ = nb_videos_ = 0;
|
||||
|
|
@ -725,7 +787,15 @@ SrsMediaPacket *SrsMpegpsQueue::dequeue()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SrsGbMuxer::SrsGbMuxer(SrsGbSession *session)
|
||||
ISrsGbMuxer::ISrsGbMuxer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsGbMuxer::~ISrsGbMuxer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsGbMuxer::SrsGbMuxer(ISrsGbSession *session)
|
||||
{
|
||||
sdk_ = NULL;
|
||||
session_ = session;
|
||||
|
|
@ -743,6 +813,8 @@ SrsGbMuxer::SrsGbMuxer(SrsGbSession *session)
|
|||
|
||||
queue_ = new SrsMpegpsQueue();
|
||||
pprint_ = SrsPithyPrint::create_caster();
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsGbMuxer::~SrsGbMuxer()
|
||||
|
|
@ -754,6 +826,8 @@ SrsGbMuxer::~SrsGbMuxer()
|
|||
srs_freep(aac_);
|
||||
srs_freep(queue_);
|
||||
srs_freep(pprint_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
void SrsGbMuxer::setup(std::string output)
|
||||
|
|
@ -1272,7 +1346,7 @@ srs_error_t SrsGbMuxer::connect()
|
|||
|
||||
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk_ = new SrsSimpleRtmpClient(url, cto, sto);
|
||||
sdk_ = app_factory_->create_rtmp_client(url, cto, sto);
|
||||
|
||||
if ((err = sdk_->connect()) != srs_success) {
|
||||
close();
|
||||
|
|
@ -1300,7 +1374,7 @@ void SrsGbMuxer::close()
|
|||
h264_pps_ = "";
|
||||
}
|
||||
|
||||
SrsPackContext::SrsPackContext(ISrsPsPackHandler *handler)
|
||||
ISrsPackContext::ISrsPackContext()
|
||||
{
|
||||
static uint32_t gid = 0;
|
||||
media_id_ = ++gid;
|
||||
|
|
@ -1309,7 +1383,14 @@ SrsPackContext::SrsPackContext(ISrsPsPackHandler *handler)
|
|||
media_nn_recovered_ = 0;
|
||||
media_nn_msgs_dropped_ = 0;
|
||||
media_reserved_ = 0;
|
||||
}
|
||||
|
||||
ISrsPackContext::~ISrsPackContext()
|
||||
{
|
||||
}
|
||||
|
||||
SrsPackContext::SrsPackContext(ISrsPsPackHandler *handler)
|
||||
{
|
||||
ps_ = new SrsPsPacket(NULL);
|
||||
handler_ = handler;
|
||||
}
|
||||
|
|
@ -1391,13 +1472,23 @@ void SrsPackContext::on_recover_mode(int nn_recover)
|
|||
}
|
||||
}
|
||||
|
||||
ISrsRecoverablePsContext::ISrsRecoverablePsContext()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRecoverablePsContext::~ISrsRecoverablePsContext()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRecoverablePsContext::SrsRecoverablePsContext()
|
||||
{
|
||||
recover_ = 0;
|
||||
ctx_ = new SrsPsContext();
|
||||
}
|
||||
|
||||
SrsRecoverablePsContext::~SrsRecoverablePsContext()
|
||||
{
|
||||
srs_freep(ctx_);
|
||||
}
|
||||
|
||||
srs_error_t SrsRecoverablePsContext::decode_rtp(SrsBuffer *stream, int reserved, ISrsPsMessageHandler *handler)
|
||||
|
|
@ -1434,9 +1525,9 @@ srs_error_t SrsRecoverablePsContext::decode_rtp(SrsBuffer *stream, int reserved,
|
|||
SrsBuffer b((char *)rtp_raw->payload_, rtp_raw->nn_payload_);
|
||||
// srs_trace("GB: Got RTP length=%d, payload=%d, seq=%u, ts=%d", length, rtp_raw->nn_payload, rtp.header_.get_sequence(), rtp.header_.get_timestamp());
|
||||
|
||||
ctx_.helper_.rtp_seq_ = rtp.header_.get_sequence();
|
||||
ctx_.helper_.rtp_ts_ = rtp.header_.get_timestamp();
|
||||
ctx_.helper_.rtp_pt_ = rtp.header_.get_payload_type();
|
||||
ctx_->helper()->rtp_seq_ = rtp.header_.get_sequence();
|
||||
ctx_->helper()->rtp_ts_ = rtp.header_.get_timestamp();
|
||||
ctx_->helper()->rtp_pt_ = rtp.header_.get_payload_type();
|
||||
if ((err = decode(&b, handler)) != srs_success) {
|
||||
return srs_error_wrap(err, "decode");
|
||||
}
|
||||
|
|
@ -1466,7 +1557,7 @@ srs_error_t SrsRecoverablePsContext::decode(SrsBuffer *stream, ISrsPsMessageHand
|
|||
}
|
||||
|
||||
// Got packet to decode.
|
||||
if ((err = ctx_.decode(stream, handler)) != srs_success) {
|
||||
if ((err = ctx_->decode(stream, handler)) != srs_success) {
|
||||
return enter_recover_mode(stream, handler, stream->pos(), srs_error_wrap(err, "decode pack"));
|
||||
}
|
||||
return err;
|
||||
|
|
@ -1482,13 +1573,13 @@ srs_error_t SrsRecoverablePsContext::enter_recover_mode(SrsBuffer *stream, ISrsP
|
|||
stream->skip(pos - stream->pos());
|
||||
string bytes = srs_strings_dumps_hex(stream->head(), stream->left(), 8);
|
||||
|
||||
SrsPsDecodeHelper &h = ctx_.helper_;
|
||||
uint16_t pack_seq = h.pack_first_seq_;
|
||||
uint16_t pack_msgs = h.pack_nn_msgs_;
|
||||
uint16_t lsopm = h.pack_pre_msg_last_seq_;
|
||||
SrsTsMessage *last = ctx_.last();
|
||||
SrsPsDecodeHelper *h = ctx_->helper();
|
||||
uint16_t pack_seq = h->pack_first_seq_;
|
||||
uint16_t pack_msgs = h->pack_nn_msgs_;
|
||||
uint16_t lsopm = h->pack_pre_msg_last_seq_;
|
||||
SrsTsMessage *last = ctx_->last();
|
||||
srs_warn("PS: Enter recover=%d, seq=%u, ts=%u, pt=%u, pack=%u, msgs=%u, lsopm=%u, last=%u/%u, bytes=[%s], pos=%d, left=%d for err %s",
|
||||
recover_, h.rtp_seq_, h.rtp_ts_, h.rtp_pt_, pack_seq, pack_msgs, lsopm, last->PES_packet_length_, last->payload_->length(),
|
||||
recover_, h->rtp_seq_, h->rtp_ts_, h->rtp_pt_, pack_seq, pack_msgs, lsopm, last->PES_packet_length_, last->payload_->length(),
|
||||
bytes.c_str(), npos, stream->left(), srs_error_desc(err).c_str());
|
||||
|
||||
// If RTP packet exceed SRS_GB_LARGE_PACKET, which is large packet, might be correct length and impossible to
|
||||
|
|
@ -1500,11 +1591,11 @@ srs_error_t SrsRecoverablePsContext::enter_recover_mode(SrsBuffer *stream, ISrsP
|
|||
// Sometimes, we're unable to recover it, so we limit the max retry.
|
||||
if (recover_ > SRS_GB_MAX_RECOVER) {
|
||||
return srs_error_wrap(err, "exceed max recover, pack=%u, pack-seq=%u, seq=%u",
|
||||
h.pack_id_, h.pack_first_seq_, h.rtp_seq_);
|
||||
h->pack_id_, h->pack_first_seq_, h->rtp_seq_);
|
||||
}
|
||||
|
||||
// Reap and dispose last incomplete message.
|
||||
SrsTsMessage *msg = ctx_.reap();
|
||||
SrsTsMessage *msg = ctx_->reap();
|
||||
srs_freep(msg);
|
||||
// Skip all left bytes in buffer, reset error because recovered.
|
||||
stream->skip(stream->left());
|
||||
|
|
@ -1519,7 +1610,7 @@ srs_error_t SrsRecoverablePsContext::enter_recover_mode(SrsBuffer *stream, ISrsP
|
|||
void SrsRecoverablePsContext::quit_recover_mode(SrsBuffer *stream, ISrsPsMessageHandler *handler)
|
||||
{
|
||||
string bytes = srs_strings_dumps_hex(stream->head(), stream->left(), 8);
|
||||
srs_warn("PS: Quit recover=%d, seq=%u, bytes=[%s], pos=%d, left=%d", recover_, ctx_.helper_.rtp_seq_,
|
||||
srs_warn("PS: Quit recover=%d, seq=%u, bytes=[%s], pos=%d, left=%d", recover_, ctx_->helper()->rtp_seq_,
|
||||
bytes.c_str(), stream->pos(), stream->left());
|
||||
recover_ = 0;
|
||||
}
|
||||
|
|
@ -1550,11 +1641,19 @@ bool srs_skip_util_pack(SrsBuffer *stream)
|
|||
SrsGoApiGbPublish::SrsGoApiGbPublish(SrsConfDirective *conf)
|
||||
{
|
||||
conf_ = conf->copy();
|
||||
|
||||
config_ = _srs_config;
|
||||
gb_manager_ = _srs_gb_manager;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsGoApiGbPublish::~SrsGoApiGbPublish()
|
||||
{
|
||||
srs_freep(conf_);
|
||||
|
||||
config_ = NULL;
|
||||
gb_manager_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiGbPublish::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1615,7 +1714,7 @@ srs_error_t SrsGoApiGbPublish::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttp
|
|||
}
|
||||
|
||||
res->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
int port = _srs_config->get_stream_caster_listen(conf_);
|
||||
int port = config_->get_stream_caster_listen(conf_);
|
||||
res->set("port", SrsJsonAny::integer(port));
|
||||
res->set("is_tcp", SrsJsonAny::boolean(true)); // only tcp supported
|
||||
|
||||
|
|
@ -1628,26 +1727,26 @@ srs_error_t SrsGoApiGbPublish::bind_session(std::string id, uint64_t ssrc)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsSharedResource<SrsGbSession> *session = NULL;
|
||||
session = dynamic_cast<SrsSharedResource<SrsGbSession> *>(_srs_gb_manager->find_by_id(id));
|
||||
SrsSharedResource<ISrsGbSession> *session = NULL;
|
||||
session = dynamic_cast<SrsSharedResource<ISrsGbSession> *>(gb_manager_->find_by_id(id));
|
||||
if (session) {
|
||||
return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "stream already exists");
|
||||
}
|
||||
|
||||
session = dynamic_cast<SrsSharedResource<SrsGbSession> *>(_srs_gb_manager->find_by_fast_id(ssrc));
|
||||
session = dynamic_cast<SrsSharedResource<ISrsGbSession> *>(gb_manager_->find_by_fast_id(ssrc));
|
||||
if (session) {
|
||||
return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "ssrc already exists");
|
||||
}
|
||||
|
||||
// Create new GB session.
|
||||
SrsGbSession *raw_session = new SrsGbSession();
|
||||
ISrsGbSession *raw_session = app_factory_->create_gb_session();
|
||||
raw_session->setup(conf_);
|
||||
|
||||
session = new SrsSharedResource<SrsGbSession>(raw_session);
|
||||
_srs_gb_manager->add_with_id(id, session);
|
||||
_srs_gb_manager->add_with_fast_id(ssrc, session);
|
||||
session = new SrsSharedResource<ISrsGbSession>(raw_session);
|
||||
gb_manager_->add_with_id(id, session);
|
||||
gb_manager_->add_with_fast_id(ssrc, session);
|
||||
|
||||
SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(_srs_gb_manager, session, raw_session, raw_session);
|
||||
SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(gb_manager_, session, raw_session, raw_session);
|
||||
raw_session->setup_owner(session, executor, executor);
|
||||
raw_session->device_id_ = id;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,8 @@ class SrsTcpConnection;
|
|||
class ISrsCoroutine;
|
||||
class SrsPackContext;
|
||||
class SrsBuffer;
|
||||
|
||||
class SrsGbSession;
|
||||
|
||||
class SrsGbMediaTcpConn;
|
||||
|
||||
class SrsAlonePithyPrint;
|
||||
class SrsGbMuxer;
|
||||
class SrsSimpleRtmpClient;
|
||||
|
|
@ -38,7 +35,28 @@ class SrsRawHEVCStream;
|
|||
class SrsMediaPacket;
|
||||
class SrsPithyPrint;
|
||||
class SrsRawAacStream;
|
||||
class ISrsHttpServeMux;
|
||||
class ISrsCommonHttpHandler;
|
||||
class ISrsGbMuxer;
|
||||
class ISrsGbSession;
|
||||
class ISrsPackContext;
|
||||
class ISrsMpegpsQueue;
|
||||
class ISrsPsContext;
|
||||
class ISrsListener;
|
||||
class ISrsProtocolReadWriter;
|
||||
class ISrsRawH264Stream;
|
||||
class ISrsRawHEVCStream;
|
||||
class ISrsRawAacStream;
|
||||
class ISrsPithyPrint;
|
||||
class ISrsBasicRtmpClient;
|
||||
class SrsTsMessage;
|
||||
class SrsPsPacket;
|
||||
class ISrsGbSession;
|
||||
class ISrsGbMediaTcpConn;
|
||||
class ISrsAppConfig;
|
||||
class ISrsApiServerOwner;
|
||||
class ISrsResourceManager;
|
||||
class ISrsAppFactory;
|
||||
class ISrsIpListener;
|
||||
|
||||
// The state machine for GB session.
|
||||
// init:
|
||||
|
|
@ -55,6 +73,7 @@ enum SrsGbSessionState {
|
|||
SrsGbSessionStateEstablished,
|
||||
};
|
||||
std::string srs_gb_session_state(SrsGbSessionState state);
|
||||
std::string srs_gb_state(SrsGbSessionState ostate, SrsGbSessionState state);
|
||||
|
||||
// For external SIP server mode, where SRS acts only as a media relay server
|
||||
// 1. SIP server POST request via HTTP API with stream ID and SSRC
|
||||
|
|
@ -72,7 +91,14 @@ std::string srs_gb_session_state(SrsGbSessionState state);
|
|||
// {"port":9000, "is_tcp": true}
|
||||
class SrsGoApiGbPublish : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsResourceManager *gb_manager_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *conf_;
|
||||
|
||||
public:
|
||||
|
|
@ -82,34 +108,65 @@ public:
|
|||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsJsonObject *res);
|
||||
srs_error_t bind_session(std::string stream, uint64_t ssrc);
|
||||
};
|
||||
|
||||
// The interface for GB session.
|
||||
class ISrsGbSession : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler
|
||||
{
|
||||
public:
|
||||
std::string device_id_;
|
||||
|
||||
public:
|
||||
ISrsGbSession();
|
||||
virtual ~ISrsGbSession();
|
||||
|
||||
public:
|
||||
// Initialize the GB session.
|
||||
virtual void setup(SrsConfDirective *conf) = 0;
|
||||
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
|
||||
virtual void setup_owner(SrsSharedResource<ISrsGbSession> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid) = 0;
|
||||
// Notice session to use current media connection.
|
||||
virtual void on_media_transport(SrsSharedResource<ISrsGbMediaTcpConn> media) = 0;
|
||||
|
||||
public:
|
||||
virtual void on_ps_pack(ISrsPackContext *ctx, SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs) = 0;
|
||||
};
|
||||
|
||||
// The main logic object for GB, the session.
|
||||
// Each session contains a media object, that are managed by session. This means session always
|
||||
// lives longer than media, and session will dispose media when session disposed. In another word,
|
||||
// media objects use directly pointer to session, while session use shared ptr.
|
||||
class SrsGbSession : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler
|
||||
class SrsGbSession : public ISrsGbSession
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
|
||||
SrsSharedResource<SrsGbSession> *wrapper_;
|
||||
SrsSharedResource<ISrsGbSession> *wrapper_;
|
||||
// The owner coroutine, allow user to interrupt the loop.
|
||||
ISrsInterruptable *owner_coroutine_;
|
||||
ISrsContextIdSetter *owner_cid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsGbSessionState state_;
|
||||
|
||||
SrsSharedResource<SrsGbMediaTcpConn> media_;
|
||||
SrsGbMuxer *muxer_;
|
||||
SrsSharedResource<ISrsGbMediaTcpConn> media_;
|
||||
ISrsGbMuxer *muxer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// When wait for media connecting, timeout if exceed.
|
||||
srs_utime_t connecting_starttime_;
|
||||
// The time we enter reinviting state.
|
||||
|
|
@ -117,7 +174,8 @@ private:
|
|||
// The number of timeout, dispose session if exceed.
|
||||
uint32_t nn_timeout_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsAlonePithyPrint *ppp_;
|
||||
srs_utime_t startime_;
|
||||
uint64_t total_packs_;
|
||||
|
|
@ -126,7 +184,8 @@ private:
|
|||
uint64_t total_msgs_dropped_;
|
||||
uint64_t total_reserved_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint32_t media_id_;
|
||||
srs_utime_t media_starttime_;
|
||||
uint64_t media_msgs_;
|
||||
|
|
@ -148,27 +207,29 @@ public:
|
|||
// Initialize the GB session.
|
||||
void setup(SrsConfDirective *conf);
|
||||
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
|
||||
void setup_owner(SrsSharedResource<SrsGbSession> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
void setup_owner(SrsSharedResource<ISrsGbSession> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
// Interface ISrsExecutorHandler
|
||||
public:
|
||||
virtual void on_executor_done(ISrsInterruptable *executor);
|
||||
|
||||
public:
|
||||
// When got a pack of messages.
|
||||
void on_ps_pack(SrsPackContext *ctx, SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs);
|
||||
void on_ps_pack(ISrsPackContext *ctx, SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs);
|
||||
|
||||
// When got available media transport.
|
||||
void on_media_transport(SrsSharedResource<SrsGbMediaTcpConn> media);
|
||||
void on_media_transport(SrsSharedResource<ISrsGbMediaTcpConn> media);
|
||||
|
||||
// Interface ISrsCoroutineHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
srs_error_t drive_state();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsGbSessionState set_state(SrsGbSessionState v);
|
||||
// Interface ISrsResource
|
||||
public:
|
||||
|
|
@ -176,12 +237,30 @@ public:
|
|||
virtual std::string desc();
|
||||
};
|
||||
|
||||
// The Media listener for GB.
|
||||
class SrsGbListener : public ISrsListener, public ISrsTcpHandler
|
||||
// The listener for GB.
|
||||
class ISrsGbListener : public ISrsListener
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsGbListener();
|
||||
virtual ~ISrsGbListener();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The Media listener for GB.
|
||||
class SrsGbListener : public ISrsGbListener, public ISrsTcpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsApiServerOwner *api_server_owner_;
|
||||
ISrsResourceManager *gb_manager_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsConfDirective *conf_;
|
||||
SrsTcpListener *media_listener_;
|
||||
ISrsIpListener *media_listener_;
|
||||
|
||||
public:
|
||||
SrsGbListener();
|
||||
|
|
@ -195,7 +274,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t on_tcp_client(ISrsListener *listener, srs_netfd_t stfd);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t listen_api();
|
||||
};
|
||||
|
||||
|
|
@ -212,26 +292,54 @@ public:
|
|||
virtual srs_error_t on_ps_pack(SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs) = 0;
|
||||
};
|
||||
|
||||
// A GB28181 TCP media connection, for PS stream.
|
||||
class SrsGbMediaTcpConn : public ISrsResource, public ISrsCoroutineHandler, public ISrsPsPackHandler, public ISrsExecutorHandler
|
||||
// The interface for GB media transport.
|
||||
class ISrsGbMediaTcpConn : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsGbMediaTcpConn();
|
||||
virtual ~ISrsGbMediaTcpConn();
|
||||
|
||||
public:
|
||||
// Setup object, to keep empty constructor.
|
||||
virtual void setup(srs_netfd_t stfd) = 0;
|
||||
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
|
||||
virtual void setup_owner(SrsSharedResource<ISrsGbMediaTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid) = 0;
|
||||
// Whether media is connected.
|
||||
virtual bool is_connected() = 0;
|
||||
// Interrupt transport by session.
|
||||
virtual void interrupt() = 0;
|
||||
// Set the cid of all coroutines.
|
||||
virtual void set_cid(const SrsContextId &cid) = 0;
|
||||
};
|
||||
|
||||
// A GB28181 TCP media connection, for PS stream.
|
||||
class SrsGbMediaTcpConn : public ISrsGbMediaTcpConn, // It's a resource, coroutine handler, and executor handler.
|
||||
public ISrsPsPackHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *gb_manager_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool connected_;
|
||||
// The owner session object, note that we use the raw pointer and should never free it.
|
||||
SrsGbSession *session_;
|
||||
ISrsGbSession *session_;
|
||||
uint32_t nn_rtcp_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
|
||||
SrsSharedResource<SrsGbMediaTcpConn> *wrapper_;
|
||||
SrsSharedResource<ISrsGbMediaTcpConn> *wrapper_;
|
||||
// The owner coroutine, allow user to interrupt the loop.
|
||||
ISrsInterruptable *owner_coroutine_;
|
||||
ISrsContextIdSetter *owner_cid_;
|
||||
SrsContextId cid_;
|
||||
|
||||
private:
|
||||
SrsPackContext *pack_;
|
||||
SrsTcpConnection *conn_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsPackContext *pack_;
|
||||
ISrsProtocolReadWriter *conn_;
|
||||
uint8_t *buffer_;
|
||||
|
||||
public:
|
||||
|
|
@ -242,7 +350,7 @@ public:
|
|||
// Setup object, to keep empty constructor.
|
||||
void setup(srs_netfd_t stfd);
|
||||
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
|
||||
void setup_owner(SrsSharedResource<SrsGbMediaTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
void setup_owner(SrsSharedResource<ISrsGbMediaTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
// Interface ISrsExecutorHandler
|
||||
public:
|
||||
virtual void on_executor_done(ISrsInterruptable *executor);
|
||||
|
|
@ -262,25 +370,42 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
// Interface ISrsPsPackHandler
|
||||
public:
|
||||
virtual srs_error_t on_ps_pack(SrsPsPacket *ps, const std::vector<SrsTsMessage *> &msgs);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Create session if no one, or bind to an existed session.
|
||||
srs_error_t bind_session(uint32_t ssrc, SrsGbSession **psession);
|
||||
srs_error_t
|
||||
bind_session(uint32_t ssrc, ISrsGbSession **psession);
|
||||
};
|
||||
|
||||
// The interface for mpegps queue.
|
||||
class ISrsMpegpsQueue
|
||||
{
|
||||
public:
|
||||
ISrsMpegpsQueue();
|
||||
virtual ~ISrsMpegpsQueue();
|
||||
|
||||
public:
|
||||
virtual srs_error_t push(SrsMediaPacket *msg) = 0;
|
||||
virtual SrsMediaPacket *dequeue() = 0;
|
||||
};
|
||||
|
||||
// The queue for mpegts over udp to send packets.
|
||||
// For the aac in mpegts contains many flv packets in a pes packet,
|
||||
// we must recalc the timestamp.
|
||||
class SrsMpegpsQueue
|
||||
class SrsMpegpsQueue : public ISrsMpegpsQueue
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The key: dts, value: msg.
|
||||
std::map<int64_t, SrsMediaPacket *> msgs_;
|
||||
std::map<int64_t, SrsMediaPacket *>
|
||||
msgs_;
|
||||
int nb_audios_;
|
||||
int nb_videos_;
|
||||
|
||||
|
|
@ -293,47 +418,68 @@ public:
|
|||
virtual SrsMediaPacket *dequeue();
|
||||
};
|
||||
|
||||
// Mux GB28181 to RTMP.
|
||||
class SrsGbMuxer
|
||||
// The interface for GB muxer.
|
||||
class ISrsGbMuxer
|
||||
{
|
||||
private:
|
||||
// The owner session object, note that we use the raw pointer and should never free it.
|
||||
SrsGbSession *session_;
|
||||
std::string output_;
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
public:
|
||||
ISrsGbMuxer();
|
||||
virtual ~ISrsGbMuxer();
|
||||
|
||||
private:
|
||||
SrsRawH264Stream *avc_;
|
||||
public:
|
||||
virtual void setup(std::string output) = 0;
|
||||
virtual srs_error_t on_ts_message(SrsTsMessage *msg) = 0;
|
||||
};
|
||||
|
||||
// Mux GB28181 to RTMP.
|
||||
class SrsGbMuxer : public ISrsGbMuxer
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The owner session object, note that we use the raw pointer and should never free it.
|
||||
ISrsGbSession *session_;
|
||||
std::string output_;
|
||||
ISrsBasicRtmpClient *sdk_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRawH264Stream *avc_;
|
||||
std::string h264_sps_;
|
||||
bool h264_sps_changed_;
|
||||
std::string h264_pps_;
|
||||
bool h264_pps_changed_;
|
||||
bool h264_sps_pps_sent_;
|
||||
|
||||
SrsRawHEVCStream *hevc_;
|
||||
ISrsRawHEVCStream *hevc_;
|
||||
bool vps_sps_pps_change_;
|
||||
std::string h265_vps_;
|
||||
std::string h265_sps_;
|
||||
std::string h265_pps_;
|
||||
bool vps_sps_pps_sent_;
|
||||
|
||||
private:
|
||||
SrsRawAacStream *aac_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRawAacStream *aac_;
|
||||
std::string aac_specific_config_;
|
||||
|
||||
private:
|
||||
SrsMpegpsQueue *queue_;
|
||||
SrsPithyPrint *pprint_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsMpegpsQueue *queue_;
|
||||
ISrsPithyPrint *pprint_;
|
||||
|
||||
public:
|
||||
SrsGbMuxer(SrsGbSession *session);
|
||||
SrsGbMuxer(ISrsGbSession *session);
|
||||
virtual ~SrsGbMuxer();
|
||||
|
||||
public:
|
||||
void setup(std::string output);
|
||||
srs_error_t on_ts_message(SrsTsMessage *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_ts_video(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
virtual srs_error_t mux_h264(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
virtual srs_error_t write_h264_sps_pps(uint32_t dts, uint32_t pts);
|
||||
|
|
@ -345,20 +491,33 @@ private:
|
|||
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:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Connect to RTMP server.
|
||||
virtual srs_error_t connect();
|
||||
virtual srs_error_t
|
||||
connect();
|
||||
// Close the connection to RTMP server.
|
||||
virtual void close();
|
||||
};
|
||||
|
||||
// Recoverable PS context for GB28181.
|
||||
class SrsRecoverablePsContext
|
||||
// The interface for recoverable PS context.
|
||||
class ISrsRecoverablePsContext
|
||||
{
|
||||
public:
|
||||
SrsPsContext ctx_;
|
||||
ISrsRecoverablePsContext();
|
||||
virtual ~ISrsRecoverablePsContext();
|
||||
|
||||
private:
|
||||
public:
|
||||
};
|
||||
|
||||
// Recoverable PS context for GB28181.
|
||||
class SrsRecoverablePsContext : public ISrsRecoverablePsContext
|
||||
{
|
||||
public:
|
||||
ISrsPsContext *ctx_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// If decoding error, enter the recover mode. Drop all left bytes util next pack header.
|
||||
int recover_;
|
||||
|
||||
|
|
@ -371,22 +530,19 @@ public:
|
|||
// parsed by previous decoding, we should move to the start of payload bytes.
|
||||
virtual srs_error_t decode_rtp(SrsBuffer *stream, int reserved, ISrsPsMessageHandler *handler);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Decode the RTP payload as PS pack stream.
|
||||
virtual srs_error_t decode(SrsBuffer *stream, ISrsPsMessageHandler *handler);
|
||||
virtual srs_error_t
|
||||
decode(SrsBuffer *stream, ISrsPsMessageHandler *handler);
|
||||
// When got error, drop data and enter recover mode.
|
||||
srs_error_t enter_recover_mode(SrsBuffer *stream, ISrsPsMessageHandler *handler, int pos, srs_error_t err);
|
||||
// Quit Recover mode when got pack header.
|
||||
void quit_recover_mode(SrsBuffer *stream, ISrsPsMessageHandler *handler);
|
||||
};
|
||||
|
||||
// The PS pack context, for GB28181 to process based on PS pack, which contains a video and audios messages. For large
|
||||
// video frame, it might be split to multiple PES packets, which must be group to one video frame.
|
||||
// Please note that a pack might contain multiple audio frames, so size of audio PES packet should not exceed 64KB,
|
||||
// which is limited by the 16 bits PES_packet_length.
|
||||
// We also correct the timestamp, or DTS/PTS of video frames, which might be 0 if more than one video PES packets in a
|
||||
// PS pack stream.
|
||||
class SrsPackContext : public ISrsPsMessageHandler
|
||||
// The interface for PS pack context.
|
||||
class ISrsPackContext : public ISrsPsMessageHandler
|
||||
{
|
||||
public:
|
||||
// Each media transport only use one context, so the context id is the media id.
|
||||
|
|
@ -396,7 +552,21 @@ public:
|
|||
uint64_t media_nn_msgs_dropped_;
|
||||
uint64_t media_reserved_;
|
||||
|
||||
private:
|
||||
public:
|
||||
ISrsPackContext();
|
||||
virtual ~ISrsPackContext();
|
||||
};
|
||||
|
||||
// The PS pack context, for GB28181 to process based on PS pack, which contains a video and audios messages. For large
|
||||
// video frame, it might be split to multiple PES packets, which must be group to one video frame.
|
||||
// Please note that a pack might contain multiple audio frames, so size of audio PES packet should not exceed 64KB,
|
||||
// which is limited by the 16 bits PES_packet_length.
|
||||
// We also correct the timestamp, or DTS/PTS of video frames, which might be 0 if more than one video PES packets in a
|
||||
// PS pack stream.
|
||||
class SrsPackContext : public ISrsPackContext
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// To process a pack of TS/PS messages.
|
||||
ISrsPsPackHandler *handler_;
|
||||
// Note that it might be freed, so never use its fields.
|
||||
|
|
@ -408,8 +578,9 @@ public:
|
|||
SrsPackContext(ISrsPsPackHandler *handler);
|
||||
virtual ~SrsPackContext();
|
||||
|
||||
private:
|
||||
public:
|
||||
void clear();
|
||||
|
||||
// Interface ISrsPsMessageHandler
|
||||
public:
|
||||
virtual srs_error_t on_ts_message(SrsTsMessage *msg);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,14 @@ public:
|
|||
srs_error_t on_video(SrsMediaPacket *msg);
|
||||
srs_error_t on_audio(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t flush_mainfest();
|
||||
srs_error_t flush_bootstrap();
|
||||
void adjust_windows();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::list<SrsHdsFragment *> fragments_;
|
||||
SrsHdsFragment *currentSegment_;
|
||||
int fragment_index_;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_client.hpp>
|
||||
#include <srs_app_http_conn.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
|
@ -23,10 +24,14 @@ using namespace std;
|
|||
|
||||
SrsHttpHeartbeat::SrsHttpHeartbeat()
|
||||
{
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsHttpHeartbeat::~SrsHttpHeartbeat()
|
||||
{
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
void SrsHttpHeartbeat::heartbeat()
|
||||
|
|
@ -43,7 +48,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
std::string url = _srs_config->get_heartbeat_url();
|
||||
std::string url = config_->get_heartbeat_url();
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((err = uri.initialize(url)) != srs_success) {
|
||||
|
|
@ -51,7 +56,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
}
|
||||
|
||||
string ip;
|
||||
std::string device_id = _srs_config->get_heartbeat_device_id();
|
||||
std::string device_id = config_->get_heartbeat_device_id();
|
||||
|
||||
// Try to load the ip from the environment variable.
|
||||
ip = srs_getenv("srs.device.ip"); // SRS_DEVICE_IP
|
||||
|
|
@ -60,7 +65,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
SrsProtocolUtility utility;
|
||||
vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||
if (!ips.empty()) {
|
||||
ip = ips[_srs_config->get_stats_network() % (int)ips.size()]->ip_;
|
||||
ip = ips[config_->get_stats_network() % (int)ips.size()]->ip_;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,82 +79,82 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
|
||||
if (_srs_config->get_heartbeat_summaries()) {
|
||||
if (config_->get_heartbeat_summaries()) {
|
||||
SrsJsonObject *summaries = SrsJsonAny::object();
|
||||
obj->set("summaries", summaries);
|
||||
|
||||
srs_api_dump_summaries(summaries);
|
||||
}
|
||||
|
||||
if (_srs_config->get_heartbeat_ports()) {
|
||||
if (config_->get_heartbeat_ports()) {
|
||||
// For RTMP listen endpoints.
|
||||
if (true) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("rtmp", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_listens();
|
||||
vector<string> endpoints = config_->get_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// For HTTP Stream listen endpoints.
|
||||
if (_srs_config->get_http_stream_enabled()) {
|
||||
if (config_->get_http_stream_enabled()) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("http", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_http_stream_listens();
|
||||
vector<string> endpoints = config_->get_http_stream_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// For HTTP API listen endpoints.
|
||||
if (_srs_config->get_http_api_enabled()) {
|
||||
if (config_->get_http_api_enabled()) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("api", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_http_api_listens();
|
||||
vector<string> endpoints = config_->get_http_api_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// For SRT listen endpoints.
|
||||
if (_srs_config->get_srt_enabled()) {
|
||||
if (config_->get_srt_enabled()) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("srt", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_srt_listens();
|
||||
vector<string> endpoints = config_->get_srt_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// For RTSP listen endpoints.
|
||||
if (_srs_config->get_rtsp_server_enabled()) {
|
||||
if (config_->get_rtsp_server_enabled()) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("rtsp", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_rtsp_server_listens();
|
||||
vector<string> endpoints = config_->get_rtsp_server_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// For WebRTC listen endpoints.
|
||||
if (_srs_config->get_rtc_server_enabled()) {
|
||||
if (config_->get_rtc_server_enabled()) {
|
||||
SrsJsonArray *o = SrsJsonAny::array();
|
||||
obj->set("rtc", o);
|
||||
|
||||
vector<string> endpoints = _srs_config->get_rtc_server_listens();
|
||||
vector<string> endpoints = config_->get_rtc_server_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
string endpoint = srs_fmt_sprintf("udp://%s", endpoints.at(i).c_str());
|
||||
o->append(SrsJsonAny::str(endpoint.c_str()));
|
||||
}
|
||||
|
||||
if (_srs_config->get_rtc_server_tcp_enabled()) {
|
||||
vector<string> endpoints = _srs_config->get_rtc_server_tcp_listens();
|
||||
if (config_->get_rtc_server_tcp_enabled()) {
|
||||
vector<string> endpoints = config_->get_rtc_server_tcp_listens();
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
string endpoint = srs_fmt_sprintf("tcp://%s", endpoints.at(i).c_str());
|
||||
o->append(SrsJsonAny::str(endpoint.c_str()));
|
||||
|
|
@ -158,14 +163,14 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
}
|
||||
}
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = http.initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(app_factory_->create_http_client());
|
||||
if ((err = http->initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
||||
return srs_error_wrap(err, "init uri=%s", uri.get_url().c_str());
|
||||
}
|
||||
|
||||
std::string req = obj->dumps();
|
||||
ISrsHttpMessage *msg_raw = NULL;
|
||||
if ((err = http.post(uri.get_path(), req, &msg_raw)) != srs_success) {
|
||||
if ((err = http->post(uri.get_path(), req, &msg_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "http post hartbeart uri failed. url=%s, request=%s", url.c_str(), req.c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,17 @@
|
|||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The http heartbeat to api-server to notice api that the information of SRS.
|
||||
class SrsHttpHeartbeat
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
public:
|
||||
SrsHttpHeartbeat();
|
||||
virtual ~SrsHttpHeartbeat();
|
||||
|
|
@ -19,7 +27,8 @@ public:
|
|||
public:
|
||||
virtual void heartbeat();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_heartbeat();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class SrsTsContext;
|
|||
class SrsFmp4SegmentEncoder;
|
||||
class ISrsHttpHooks;
|
||||
class ISrsAppConfig;
|
||||
class SrsAppFactory;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The wrapper of m3u8 segment from specification:
|
||||
//
|
||||
|
|
@ -73,11 +73,13 @@ public:
|
|||
|
||||
class SrsInitMp4Segment : public SrsFragment
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFileWriter *fw_;
|
||||
SrsMp4M2tsInitEncoder init_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Key ID for encryption
|
||||
unsigned char kid_[16];
|
||||
// Constant IV for encryption
|
||||
|
|
@ -96,14 +98,16 @@ public:
|
|||
virtual srs_error_t write_video_only(SrsFormat *format, int v_tid);
|
||||
virtual srs_error_t write_audio_only(SrsFormat *format, int a_tid);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t init_encoder();
|
||||
};
|
||||
|
||||
// TODO: merge this code with SrsFragmentedMp4 in dash
|
||||
class SrsHlsM4sSegment : public SrsFragment
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFileWriter *fw_;
|
||||
SrsFmp4SegmentEncoder enc_;
|
||||
|
||||
|
|
@ -130,11 +134,13 @@ public:
|
|||
// The hls async call: on_hls
|
||||
class SrsDvrAsyncCallOnHls : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
std::string path_;
|
||||
std::string ts_url_;
|
||||
|
|
@ -157,11 +163,13 @@ public:
|
|||
// The hls async call: on_hls_notify
|
||||
class SrsDvrAsyncCallOnHlsNotify : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
std::string ts_url_;
|
||||
ISrsRequest *req_;
|
||||
|
|
@ -184,14 +192,17 @@ public:
|
|||
// TODO: Rename to SrsHlsTsMuxer, for TS file only.
|
||||
class SrsHlsMuxer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
SrsAppFactory *app_factory_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string hls_entry_prefix_;
|
||||
std::string hls_path_;
|
||||
std::string hls_ts_file_;
|
||||
|
|
@ -204,7 +215,8 @@ private:
|
|||
srs_utime_t hls_window_;
|
||||
SrsAsyncCallWorker *async_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether use floor algorithm for timestamp.
|
||||
bool hls_ts_floor_;
|
||||
// The deviation in piece to adjust the fragment to be more
|
||||
|
|
@ -215,7 +227,8 @@ private:
|
|||
int64_t accept_floor_ts_;
|
||||
int64_t previous_floor_ts_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether encrypted or not
|
||||
bool hls_keys_;
|
||||
int hls_fragments_per_key_;
|
||||
|
|
@ -231,13 +244,15 @@ private:
|
|||
// The underlayer file writer.
|
||||
ISrsFileWriter *writer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int sequence_no_;
|
||||
srs_utime_t max_td_;
|
||||
std::string m3u8_;
|
||||
std::string m3u8_url_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The available cached segments in m3u8.
|
||||
SrsFragmentWindow *segments_;
|
||||
// The current writing segment.
|
||||
|
|
@ -245,7 +260,8 @@ private:
|
|||
// The ts context, to keep cc continous between ts.
|
||||
SrsTsContext *context_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Latest audio codec, parsed from stream.
|
||||
SrsAudioCodecId latest_acodec_;
|
||||
// Latest audio codec, parsed from stream.
|
||||
|
|
@ -306,7 +322,8 @@ public:
|
|||
// Close segment(ts).
|
||||
virtual srs_error_t segment_close();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_segment_close();
|
||||
virtual srs_error_t write_hls_key();
|
||||
virtual srs_error_t refresh_m3u8();
|
||||
|
|
@ -318,7 +335,8 @@ public:
|
|||
// HLS recover mode.
|
||||
srs_error_t recover_hls();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_recover_hls();
|
||||
};
|
||||
|
||||
|
|
@ -327,14 +345,17 @@ private:
|
|||
// to flush video/audio, without any mechenisms.
|
||||
class SrsHlsFmp4Muxer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
SrsAppFactory *app_factory_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string hls_entry_prefix_;
|
||||
std::string hls_path_;
|
||||
std::string hls_m4s_file_;
|
||||
|
|
@ -347,7 +368,8 @@ private:
|
|||
srs_utime_t hls_window_;
|
||||
SrsAsyncCallWorker *async_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether use floor algorithm for timestamp.
|
||||
bool hls_ts_floor_;
|
||||
// The deviation in piece to adjust the fragment to be more
|
||||
|
|
@ -359,7 +381,8 @@ private:
|
|||
int64_t previous_floor_ts_;
|
||||
bool init_mp4_ready_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether encrypted or not
|
||||
// TODO: fmp4 encryption is not yet implemented.
|
||||
// fmp4 support four kinds of protection scheme: 'cenc', 'cbc1', 'cens', 'cbcs'.
|
||||
|
|
@ -385,7 +408,8 @@ private:
|
|||
// The underlayer file writer.
|
||||
ISrsFileWriter *writer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int sequence_no_;
|
||||
srs_utime_t max_td_;
|
||||
std::string m3u8_;
|
||||
|
|
@ -395,13 +419,15 @@ private:
|
|||
int audio_track_id_;
|
||||
uint64_t video_dts_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The available cached segments in m3u8.
|
||||
SrsFragmentWindow *segments_;
|
||||
// The current writing segment.
|
||||
SrsHlsM4sSegment *current_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Latest audio codec, parsed from stream.
|
||||
SrsAudioCodecId latest_acodec_;
|
||||
// Latest audio codec, parsed from stream.
|
||||
|
|
@ -461,7 +487,8 @@ public:
|
|||
// Close segment(ts).
|
||||
virtual srs_error_t segment_close();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_segment_close();
|
||||
virtual srs_error_t write_hls_key();
|
||||
virtual srs_error_t refresh_m3u8();
|
||||
|
|
@ -513,10 +540,12 @@ public:
|
|||
// TODO: Rename to SrsHlsTsController, for TS file only.
|
||||
class SrsHlsController : public ISrsHlsController
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The HLS muxer to reap ts and m3u8.
|
||||
// The TS is cached to SrsTsMessageCache then flush to ts segment.
|
||||
SrsHlsMuxer *muxer_;
|
||||
|
|
@ -557,39 +586,47 @@ public:
|
|||
// write video to muxer.
|
||||
virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Reopen the muxer for a new hls segment,
|
||||
// close current segment, open a new segment,
|
||||
// then write the key frame to the new segment.
|
||||
// so, user must reap_segment then flush_video to hls muxer.
|
||||
virtual srs_error_t reap_segment();
|
||||
virtual srs_error_t
|
||||
reap_segment();
|
||||
};
|
||||
|
||||
// HLS controller for fMP4 (.m4s) segments with init.mp4.
|
||||
// Direct sample processing without caching, simpler than TS controller.
|
||||
class SrsHlsMp4Controller : public ISrsHlsController
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool has_video_sh_;
|
||||
bool has_audio_sh_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int video_track_id_;
|
||||
int audio_track_id_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Current audio dts.
|
||||
uint64_t audio_dts_;
|
||||
// Current video dts.
|
||||
uint64_t video_dts_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsHlsFmp4Muxer *muxer_;
|
||||
|
||||
public:
|
||||
|
|
@ -637,13 +674,16 @@ public:
|
|||
// TODO: FIXME: add utest for hls.
|
||||
class SrsHls : public ISrsHls
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHlsController *controller_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
// Whether the HLS is enabled.
|
||||
bool enabled_;
|
||||
|
|
@ -657,7 +697,8 @@ private:
|
|||
// To detect heartbeat and dispose it if configured.
|
||||
srs_utime_t last_update_time_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsOriginHub *hub_;
|
||||
SrsRtmpJitter *jitter_;
|
||||
SrsPithyPrint *pprint_;
|
||||
|
|
@ -669,7 +710,8 @@ public:
|
|||
public:
|
||||
virtual void async_reload();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t reload();
|
||||
srs_error_t do_reload(int *reloading, int *reloaded, int *refreshed);
|
||||
|
||||
|
|
@ -697,7 +739,8 @@ public:
|
|||
// TODO: FIXME: Remove param is_sps_pps.
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void hls_show_mux_log();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -170,22 +170,22 @@ srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMessage *r,
|
|||
|
||||
SrsGoApiRoot::SrsGoApiRoot()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiRoot::~SrsGoApiRoot()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiRoot::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *urls = SrsJsonAny::object();
|
||||
obj->set("urls", urls);
|
||||
|
|
@ -209,22 +209,22 @@ srs_error_t SrsGoApiRoot::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage
|
|||
|
||||
SrsGoApiApi::SrsGoApiApi()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiApi::~SrsGoApiApi()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiApi::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *urls = SrsJsonAny::object();
|
||||
obj->set("urls", urls);
|
||||
|
|
@ -236,22 +236,22 @@ srs_error_t SrsGoApiApi::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *
|
|||
|
||||
SrsGoApiV1::SrsGoApiV1()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiV1::~SrsGoApiV1()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiV1::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *urls = SrsJsonAny::object();
|
||||
obj->set("urls", urls);
|
||||
|
|
@ -292,22 +292,22 @@ srs_error_t SrsGoApiV1::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r
|
|||
|
||||
SrsGoApiVersion::SrsGoApiVersion()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiVersion::~SrsGoApiVersion()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiVersion::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -322,22 +322,22 @@ srs_error_t SrsGoApiVersion::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
SrsGoApiSummaries::SrsGoApiSummaries()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiSummaries::~SrsGoApiSummaries()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
srs_api_dump_summaries(obj.get());
|
||||
|
||||
|
|
@ -346,22 +346,22 @@ srs_error_t SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMes
|
|||
|
||||
SrsGoApiRusages::SrsGoApiRusages()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiRusages::~SrsGoApiRusages()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiRusages::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -392,22 +392,22 @@ srs_error_t SrsGoApiRusages::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
SrsGoApiSelfProcStats::SrsGoApiSelfProcStats()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -470,22 +470,22 @@ srs_error_t SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter *w, ISrsHtt
|
|||
|
||||
SrsGoApiSystemProcStats::SrsGoApiSystemProcStats()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -510,22 +510,22 @@ srs_error_t SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter *w, ISrsH
|
|||
|
||||
SrsGoApiMemInfos::SrsGoApiMemInfos()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiMemInfos::~SrsGoApiMemInfos()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -551,22 +551,22 @@ srs_error_t SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
|
||||
SrsGoApiAuthors::SrsGoApiAuthors()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiAuthors::~SrsGoApiAuthors()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -579,22 +579,22 @@ srs_error_t SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
SrsGoApiFeatures::SrsGoApiFeatures()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiFeatures::~SrsGoApiFeatures()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiFeatures::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -648,22 +648,22 @@ srs_error_t SrsGoApiFeatures::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
|
||||
SrsGoApiRequests::SrsGoApiRequests()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiRequests::~SrsGoApiRequests()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiRequests::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
obj->set("data", data);
|
||||
|
|
@ -693,40 +693,40 @@ srs_error_t SrsGoApiRequests::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
|
||||
SrsGoApiVhosts::SrsGoApiVhosts()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiVhosts::~SrsGoApiVhosts()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
// path: {pattern}{vhost_id}
|
||||
// e.g. /api/v1/vhosts/100 pattern= /api/v1/vhosts/, vhost_id=100
|
||||
string vid = r->parse_rest_id(entry_->pattern);
|
||||
SrsStatisticVhost *vhost = NULL;
|
||||
|
||||
if (!vid.empty() && (vhost = stat->find_vhost_by_id(vid)) == NULL) {
|
||||
if (!vid.empty() && (vhost = stat_->find_vhost_by_id(vid)) == NULL) {
|
||||
return srs_api_response_code(w, r, ERROR_RTMP_VHOST_NOT_FOUND);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
if (r->is_http_get()) {
|
||||
if (!vhost) {
|
||||
SrsJsonArray *data = SrsJsonAny::array();
|
||||
obj->set("vhosts", data);
|
||||
|
||||
if ((err = stat->dumps_vhosts(data)) != srs_success) {
|
||||
if ((err = stat_->dumps_vhosts(data)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
|
|
@ -751,33 +751,33 @@ srs_error_t SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessag
|
|||
|
||||
SrsGoApiStreams::SrsGoApiStreams()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiStreams::~SrsGoApiStreams()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
// path: {pattern}{stream_id}
|
||||
// e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100
|
||||
string sid = r->parse_rest_id(entry_->pattern);
|
||||
|
||||
SrsStatisticStream *stream = NULL;
|
||||
if (!sid.empty() && (stream = stat->find_stream(sid)) == NULL) {
|
||||
if (!sid.empty() && (stream = stat_->find_stream(sid)) == NULL) {
|
||||
return srs_api_response_code(w, r, ERROR_RTMP_STREAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
if (r->is_http_get()) {
|
||||
if (!stream) {
|
||||
|
|
@ -788,7 +788,7 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
std::string rcount = r->query_get("count");
|
||||
int start = srs_max(0, atoi(rstart.c_str()));
|
||||
int count = srs_max(10, atoi(rcount.c_str()));
|
||||
if ((err = stat->dumps_streams(data, start, count)) != srs_success) {
|
||||
if ((err = stat_->dumps_streams(data, start, count)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
|
|
@ -813,33 +813,33 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
SrsGoApiClients::SrsGoApiClients()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiClients::~SrsGoApiClients()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
// path: {pattern}{client_id}
|
||||
// e.g. /api/v1/clients/100 pattern= /api/v1/clients/, client_id=100
|
||||
string client_id = r->parse_rest_id(entry_->pattern);
|
||||
|
||||
SrsStatisticClient *client = NULL;
|
||||
if (!client_id.empty() && (client = stat->find_client(client_id)) == NULL) {
|
||||
if (!client_id.empty() && (client = stat_->find_client(client_id)) == NULL) {
|
||||
return srs_api_response_code(w, r, ERROR_RTMP_CLIENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
obj->set("server", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||
obj->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
obj->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
obj->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
if (r->is_http_get()) {
|
||||
if (!client) {
|
||||
|
|
@ -850,7 +850,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
std::string rcount = r->query_get("count");
|
||||
int start = srs_max(0, atoi(rstart.c_str()));
|
||||
int count = srs_max(10, atoi(rcount.c_str()));
|
||||
if ((err = stat->dumps_clients(data, start, count)) != srs_success) {
|
||||
if ((err = stat_->dumps_clients(data, start, count)) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
|
|
@ -884,21 +884,30 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
return srs_api_response(w, r, obj->dumps());
|
||||
}
|
||||
|
||||
SrsGoApiRaw::SrsGoApiRaw(SrsServer *svr)
|
||||
SrsGoApiRaw::SrsGoApiRaw(ISrsSignalHandler *handler)
|
||||
{
|
||||
server_ = svr;
|
||||
handler_ = handler;
|
||||
|
||||
raw_api_ = _srs_config->get_raw_api();
|
||||
allow_reload_ = _srs_config->get_raw_api_allow_reload();
|
||||
allow_query_ = _srs_config->get_raw_api_allow_query();
|
||||
allow_update_ = _srs_config->get_raw_api_allow_update();
|
||||
stat_ = _srs_stat;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
void SrsGoApiRaw::assemble()
|
||||
{
|
||||
raw_api_ = config_->get_raw_api();
|
||||
allow_reload_ = config_->get_raw_api_allow_reload();
|
||||
allow_query_ = config_->get_raw_api_allow_query();
|
||||
allow_update_ = config_->get_raw_api_allow_update();
|
||||
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsGoApiRaw::~SrsGoApiRaw()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
stat_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
extern srs_error_t _srs_reload_err;
|
||||
|
|
@ -918,7 +927,7 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *
|
|||
// for rpc=raw, to query the raw api config for http api.
|
||||
if (rpc == "raw") {
|
||||
// query global scope.
|
||||
if ((err = _srs_config->raw_to_json(obj.get())) != srs_success) {
|
||||
if ((err = config_->raw_to_json(obj.get())) != srs_success) {
|
||||
int code = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
return srs_api_response_code(w, r, code);
|
||||
|
|
@ -945,7 +954,7 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *
|
|||
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW_DISABLED);
|
||||
}
|
||||
|
||||
server_->on_signal(SRS_SIGNAL_RELOAD);
|
||||
handler_->on_signal(SRS_SIGNAL_RELOAD);
|
||||
return srs_api_response_code(w, r, ERROR_SUCCESS);
|
||||
} else if (rpc == "reload-fetch") {
|
||||
SrsJsonObject *data = SrsJsonAny::object();
|
||||
|
|
@ -964,10 +973,12 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *
|
|||
|
||||
SrsGoApiClusters::SrsGoApiClusters()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiClusters::~SrsGoApiClusters()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiClusters::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -997,10 +1008,12 @@ srs_error_t SrsGoApiClusters::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
|
||||
SrsGoApiError::SrsGoApiError()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiError::~SrsGoApiError()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiError::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1013,10 +1026,12 @@ srs_error_t SrsGoApiError::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage
|
|||
|
||||
SrsGoApiTcmalloc::SrsGoApiTcmalloc()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiTcmalloc::~SrsGoApiTcmalloc()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1097,11 +1112,15 @@ srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
SrsGoApiValgrind::SrsGoApiValgrind()
|
||||
{
|
||||
trd_ = NULL;
|
||||
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiValgrind::~SrsGoApiValgrind()
|
||||
{
|
||||
srs_freep(trd_);
|
||||
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiValgrind::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1199,10 +1218,12 @@ srs_error_t SrsGoApiValgrind::cycle()
|
|||
#ifdef SRS_SIGNAL_API
|
||||
SrsGoApiSignal::SrsGoApiSignal()
|
||||
{
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsGoApiSignal::~SrsGoApiSignal()
|
||||
{
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiSignal::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1244,13 +1265,21 @@ srs_error_t SrsGoApiSignal::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessag
|
|||
|
||||
SrsGoApiMetrics::SrsGoApiMetrics()
|
||||
{
|
||||
enabled_ = _srs_config->get_exporter_enabled();
|
||||
label_ = _srs_config->get_exporter_label();
|
||||
tag_ = _srs_config->get_exporter_tag();
|
||||
stat_ = _srs_stat;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
void SrsGoApiMetrics::assemble()
|
||||
{
|
||||
enabled_ = config_->get_exporter_enabled();
|
||||
label_ = config_->get_exporter_label();
|
||||
tag_ = config_->get_exporter_tag();
|
||||
}
|
||||
|
||||
SrsGoApiMetrics::~SrsGoApiMetrics()
|
||||
{
|
||||
stat_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -1273,7 +1302,6 @@ srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
* error counter
|
||||
*/
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
std::stringstream ss;
|
||||
|
||||
#if defined(__linux__) || defined(SRS_OSX)
|
||||
|
|
@ -1295,9 +1323,9 @@ srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
ss << "# HELP srs_build_info A metric with a constant '1' value labeled by build_date, version from which SRS was built.\n"
|
||||
<< "# TYPE srs_build_info gauge\n"
|
||||
<< "srs_build_info{"
|
||||
<< "server=\"" << stat->server_id() << "\","
|
||||
<< "service=\"" << stat->service_id() << "\","
|
||||
<< "pid=\"" << stat->service_pid() << "\","
|
||||
<< "server=\"" << stat_->server_id() << "\","
|
||||
<< "service=\"" << stat_->service_id() << "\","
|
||||
<< "pid=\"" << stat_->service_pid() << "\","
|
||||
<< "build_date=\"" << SRS_BUILD_DATE << "\","
|
||||
<< "major=\"" << VERSION_MAJOR << "\","
|
||||
<< "version=\"" << RTMP_SIG_SRS_VERSION << "\","
|
||||
|
|
@ -1328,7 +1356,7 @@ srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
// Dump metrics by statistic.
|
||||
int64_t send_bytes, recv_bytes, nstreams, nclients, total_nclients, nerrs;
|
||||
stat->dumps_metrics(send_bytes, recv_bytes, nstreams, nclients, total_nclients, nerrs);
|
||||
stat_->dumps_metrics(send_bytes, recv_bytes, nstreams, nclients, total_nclients, nerrs);
|
||||
|
||||
// The total of bytes sent.
|
||||
ss << "# HELP srs_send_bytes_total SRS total sent bytes.\n"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ class SrsSdp;
|
|||
class ISrsRequest;
|
||||
class ISrsHttpResponseWriter;
|
||||
class SrsHttpConn;
|
||||
class ISrsSignalHandler;
|
||||
class ISrsStatistic;
|
||||
class ISrsAppConfig;
|
||||
|
||||
#include <string>
|
||||
|
||||
|
|
@ -35,6 +38,10 @@ extern srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
// For http root.
|
||||
class SrsGoApiRoot : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiRoot();
|
||||
virtual ~SrsGoApiRoot();
|
||||
|
|
@ -45,6 +52,10 @@ public:
|
|||
|
||||
class SrsGoApiApi : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiApi();
|
||||
virtual ~SrsGoApiApi();
|
||||
|
|
@ -55,6 +66,10 @@ public:
|
|||
|
||||
class SrsGoApiV1 : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiV1();
|
||||
virtual ~SrsGoApiV1();
|
||||
|
|
@ -65,6 +80,10 @@ public:
|
|||
|
||||
class SrsGoApiVersion : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiVersion();
|
||||
virtual ~SrsGoApiVersion();
|
||||
|
|
@ -75,6 +94,10 @@ public:
|
|||
|
||||
class SrsGoApiSummaries : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiSummaries();
|
||||
virtual ~SrsGoApiSummaries();
|
||||
|
|
@ -85,6 +108,10 @@ public:
|
|||
|
||||
class SrsGoApiRusages : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiRusages();
|
||||
virtual ~SrsGoApiRusages();
|
||||
|
|
@ -95,6 +122,10 @@ public:
|
|||
|
||||
class SrsGoApiSelfProcStats : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiSelfProcStats();
|
||||
virtual ~SrsGoApiSelfProcStats();
|
||||
|
|
@ -105,6 +136,10 @@ public:
|
|||
|
||||
class SrsGoApiSystemProcStats : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiSystemProcStats();
|
||||
virtual ~SrsGoApiSystemProcStats();
|
||||
|
|
@ -115,6 +150,10 @@ public:
|
|||
|
||||
class SrsGoApiMemInfos : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiMemInfos();
|
||||
virtual ~SrsGoApiMemInfos();
|
||||
|
|
@ -125,6 +164,10 @@ public:
|
|||
|
||||
class SrsGoApiAuthors : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiAuthors();
|
||||
virtual ~SrsGoApiAuthors();
|
||||
|
|
@ -135,6 +178,10 @@ public:
|
|||
|
||||
class SrsGoApiFeatures : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiFeatures();
|
||||
virtual ~SrsGoApiFeatures();
|
||||
|
|
@ -145,6 +192,10 @@ public:
|
|||
|
||||
class SrsGoApiRequests : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiRequests();
|
||||
virtual ~SrsGoApiRequests();
|
||||
|
|
@ -155,6 +206,10 @@ public:
|
|||
|
||||
class SrsGoApiVhosts : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiVhosts();
|
||||
virtual ~SrsGoApiVhosts();
|
||||
|
|
@ -165,6 +220,10 @@ public:
|
|||
|
||||
class SrsGoApiStreams : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiStreams();
|
||||
virtual ~SrsGoApiStreams();
|
||||
|
|
@ -175,6 +234,10 @@ public:
|
|||
|
||||
class SrsGoApiClients : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiClients();
|
||||
virtual ~SrsGoApiClients();
|
||||
|
|
@ -185,17 +248,25 @@ public:
|
|||
|
||||
class SrsGoApiRaw : public ISrsHttpHandler, public ISrsReloadHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsSignalHandler *handler_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool raw_api_;
|
||||
bool allow_reload_;
|
||||
bool allow_query_;
|
||||
bool allow_update_;
|
||||
|
||||
public:
|
||||
SrsGoApiRaw(SrsServer *svr);
|
||||
SrsGoApiRaw(ISrsSignalHandler *handler);
|
||||
void assemble();
|
||||
virtual ~SrsGoApiRaw();
|
||||
|
||||
public:
|
||||
|
|
@ -204,6 +275,10 @@ public:
|
|||
|
||||
class SrsGoApiClusters : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiClusters();
|
||||
virtual ~SrsGoApiClusters();
|
||||
|
|
@ -214,6 +289,10 @@ public:
|
|||
|
||||
class SrsGoApiError : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiError();
|
||||
virtual ~SrsGoApiError();
|
||||
|
|
@ -225,6 +304,10 @@ public:
|
|||
#ifdef SRS_GPERF
|
||||
class SrsGoApiTcmalloc : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiTcmalloc();
|
||||
virtual ~SrsGoApiTcmalloc();
|
||||
|
|
@ -237,7 +320,12 @@ public:
|
|||
#ifdef SRS_VALGRIND
|
||||
class SrsGoApiValgrind : public ISrsHttpHandler, public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
std::string task_;
|
||||
|
||||
|
|
@ -256,6 +344,10 @@ public:
|
|||
#ifdef SRS_SIGNAL_API
|
||||
class SrsGoApiSignal : public ISrsHttpHandler
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsGoApiSignal();
|
||||
virtual ~SrsGoApiSignal();
|
||||
|
|
@ -267,13 +359,20 @@ public:
|
|||
|
||||
class SrsGoApiMetrics : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool enabled_;
|
||||
std::string label_;
|
||||
std::string tag_;
|
||||
|
||||
public:
|
||||
SrsGoApiMetrics();
|
||||
void assemble();
|
||||
virtual ~SrsGoApiMetrics();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -49,7 +49,15 @@ ISrsHttpConnOwner::~ISrsHttpConnOwner()
|
|||
{
|
||||
}
|
||||
|
||||
SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd, ISrsHttpServeMux *m, string cip, int cport)
|
||||
ISrsHttpConn::ISrsHttpConn()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpConn::~ISrsHttpConn()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd, ISrsCommonHttpHandler *m, string cip, int cport)
|
||||
{
|
||||
parser_ = new SrsHttpParser();
|
||||
auth_ = new SrsHttpAuthMux(m);
|
||||
|
|
@ -65,6 +73,8 @@ SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd,
|
|||
delta_ = new SrsNetworkDelta();
|
||||
delta_->set_io(skt_, skt_);
|
||||
trd_ = new SrsSTCoroutine("http", this, _srs_context->get_id());
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsHttpConn::~SrsHttpConn()
|
||||
|
|
@ -77,6 +87,8 @@ SrsHttpConn::~SrsHttpConn()
|
|||
srs_freep(auth_);
|
||||
|
||||
srs_freep(delta_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
std::string SrsHttpConn::desc()
|
||||
|
|
@ -269,8 +281,8 @@ srs_error_t SrsHttpConn::set_auth_enabled(bool auth_enabled)
|
|||
|
||||
// initialize the auth, which will proxy to mux.
|
||||
if ((err = auth_->initialize(auth_enabled,
|
||||
_srs_config->get_http_api_auth_username(),
|
||||
_srs_config->get_http_api_auth_password())) != srs_success) {
|
||||
config_->get_http_api_auth_username(),
|
||||
config_->get_http_api_auth_password())) != srs_success) {
|
||||
return srs_error_wrap(err, "init auth");
|
||||
}
|
||||
|
||||
|
|
@ -298,7 +310,15 @@ void SrsHttpConn::expire()
|
|||
trd_->interrupt();
|
||||
}
|
||||
|
||||
SrsHttpxConn::SrsHttpxConn(ISrsResourceManager *cm, ISrsProtocolReadWriter *io, ISrsHttpServeMux *m, string cip, int port, string key, string cert) : manager_(cm), io_(io), enable_stat_(false), ssl_key_file_(key), ssl_cert_file_(cert)
|
||||
ISrsHttpxConn::ISrsHttpxConn()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpxConn::~ISrsHttpxConn()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpxConn::SrsHttpxConn(ISrsResourceManager *cm, ISrsProtocolReadWriter *io, ISrsCommonHttpHandler *m, string cip, int port, string key, string cert) : manager_(cm), io_(io), enable_stat_(false), ssl_key_file_(key), ssl_cert_file_(cert)
|
||||
{
|
||||
// Create a identify for this client.
|
||||
_srs_context->set_id(_srs_context->generate_id());
|
||||
|
|
@ -312,16 +332,18 @@ SrsHttpxConn::SrsHttpxConn(ISrsResourceManager *cm, ISrsProtocolReadWriter *io,
|
|||
conn_ = new SrsHttpConn(this, io_, m, cip, port);
|
||||
}
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
config_ = _srs_config;
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsHttpxConn::~SrsHttpxConn()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
|
||||
srs_freep(conn_);
|
||||
srs_freep(ssl_);
|
||||
srs_freep(io_);
|
||||
|
||||
config_ = NULL;
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
void SrsHttpxConn::set_enable_stat(bool v)
|
||||
|
|
@ -390,7 +412,7 @@ srs_error_t SrsHttpxConn::on_start()
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpxConn::on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w)
|
||||
srs_error_t SrsHttpxConn::on_http_message(ISrsHttpMessage *r, ISrsHttpResponseWriter *w)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -407,7 +429,7 @@ srs_error_t SrsHttpxConn::on_http_message(ISrsHttpMessage *r, SrsHttpResponseWri
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpxConn::on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w)
|
||||
srs_error_t SrsHttpxConn::on_message_done(ISrsHttpMessage *r, ISrsHttpResponseWriter *w)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -416,8 +438,8 @@ srs_error_t SrsHttpxConn::on_conn_done(srs_error_t r0)
|
|||
{
|
||||
// Only stat the HTTP streaming clients, ignore all API clients.
|
||||
if (enable_stat_) {
|
||||
_srs_stat->on_disconnect(get_id().c_str(), r0);
|
||||
_srs_stat->kbps_add_delta(get_id().c_str(), conn_->delta());
|
||||
stat_->on_disconnect(get_id().c_str(), r0);
|
||||
stat_->kbps_add_delta(get_id().c_str(), conn_->delta());
|
||||
}
|
||||
|
||||
// Because we use manager to manage this object,
|
||||
|
|
@ -456,12 +478,12 @@ srs_error_t SrsHttpxConn::start()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
bool v = _srs_config->get_http_stream_crossdomain();
|
||||
bool v = config_->get_http_stream_crossdomain();
|
||||
if ((err = conn_->set_crossdomain_enabled(v)) != srs_success) {
|
||||
return srs_error_wrap(err, "set cors=%d", v);
|
||||
}
|
||||
|
||||
bool auth_enabled = _srs_config->get_http_api_auth_enabled();
|
||||
bool auth_enabled = config_->get_http_api_auth_enabled();
|
||||
if ((err = conn_->set_auth_enabled(auth_enabled)) != srs_success) {
|
||||
return srs_error_wrap(err, "set auth");
|
||||
}
|
||||
|
|
@ -474,6 +496,14 @@ ISrsKbpsDelta *SrsHttpxConn::delta()
|
|||
return conn_->delta();
|
||||
}
|
||||
|
||||
ISrsHttpServer::ISrsHttpServer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpServer::~ISrsHttpServer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpServer::SrsHttpServer()
|
||||
{
|
||||
http_stream_ = new SrsHttpStreamServer();
|
||||
|
|
@ -493,7 +523,7 @@ srs_error_t SrsHttpServer::initialize()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// for SRS go-sharp to detect the status of HTTP server of SRS HTTP FLV Cluster.
|
||||
if ((err = http_static_->mux_.handle("/api/v1/versions", new SrsGoApiVersion())) != srs_success) {
|
||||
if ((err = http_static_->mux()->handle("/api/v1/versions", new SrsGoApiVersion())) != srs_success) {
|
||||
return srs_error_wrap(err, "handle versions");
|
||||
}
|
||||
|
||||
|
|
@ -510,7 +540,7 @@ srs_error_t SrsHttpServer::initialize()
|
|||
|
||||
srs_error_t SrsHttpServer::handle(std::string pattern, ISrsHttpHandler *handler)
|
||||
{
|
||||
return http_static_->mux_.handle(pattern, handler);
|
||||
return http_static_->mux()->handle(pattern, handler);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -525,21 +555,21 @@ srs_error_t SrsHttpServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage
|
|||
bool is_api = memcmp(p, "/api/", 5) == 0;
|
||||
bool is_console = path.length() > 8 && memcmp(p, "/console/", 9) == 0;
|
||||
if (is_api || is_console) {
|
||||
return http_static_->mux_.serve_http(w, r);
|
||||
return http_static_->mux()->serve_http(w, r);
|
||||
}
|
||||
}
|
||||
|
||||
// Try http stream first, then http static if not found.
|
||||
ISrsHttpHandler *h = NULL;
|
||||
if ((err = http_stream_->mux_.find_handler(r, &h)) != srs_success) {
|
||||
if ((err = http_stream_->mux()->find_handler(r, &h)) != srs_success) {
|
||||
return srs_error_wrap(err, "find handler");
|
||||
}
|
||||
if (!h->is_not_found()) {
|
||||
return http_stream_->mux_.serve_http(w, r);
|
||||
return http_stream_->mux()->serve_http(w, r);
|
||||
}
|
||||
|
||||
// Use http static as default server.
|
||||
return http_static_->mux_.serve_http(w, r);
|
||||
return http_static_->mux()->serve_http(w, r);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpServer::http_mount(ISrsRequest *r)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class ISrsRequest;
|
|||
class SrsLiveConsumer;
|
||||
class SrsStSocket;
|
||||
class SrsHttpParser;
|
||||
class ISrsHttpParser;
|
||||
class ISrsHttpMessage;
|
||||
class SrsHttpHandler;
|
||||
class SrsMessageQueue;
|
||||
|
|
@ -34,8 +35,20 @@ class SrsFastStream;
|
|||
class SrsHttpUri;
|
||||
class SrsHttpMessage;
|
||||
class SrsHttpStreamServer;
|
||||
class ISrsHttpStreamServer;
|
||||
class SrsHttpStaticServer;
|
||||
class ISrsHttpStaticServer;
|
||||
class SrsNetworkDelta;
|
||||
class ISrsNetworkDelta;
|
||||
class SrsHttpCorsMux;
|
||||
class ISrsHttpCorsMux;
|
||||
class SrsHttpAuthMux;
|
||||
class ISrsHttpAuthMux;
|
||||
class SrsSslConnection;
|
||||
class ISrsSslConnection;
|
||||
class ISrsHttpConn;
|
||||
class ISrsAppConfig;
|
||||
class ISrsStatistic;
|
||||
|
||||
// The owner of HTTP connection.
|
||||
class ISrsHttpConnOwner
|
||||
|
|
@ -50,26 +63,52 @@ public:
|
|||
// Handle the HTTP message r, which may be parsed partially.
|
||||
// For the static service or api, discard any body.
|
||||
// For the stream caster, for instance, http flv streaming, may discard the flv header or not.
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w) = 0;
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, ISrsHttpResponseWriter *w) = 0;
|
||||
// When message is processed, we may need to do more things.
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w) = 0;
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, ISrsHttpResponseWriter *w) = 0;
|
||||
// When connection is destroy, should use manager to dispose it.
|
||||
// The r0 is the original error, we will use the returned new error.
|
||||
virtual srs_error_t on_conn_done(srs_error_t r0) = 0;
|
||||
};
|
||||
|
||||
// The HTTP connection, for HTTP stream or static file.
|
||||
class ISrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoroutineHandler, public ISrsExpire
|
||||
{
|
||||
public:
|
||||
ISrsHttpConn();
|
||||
virtual ~ISrsHttpConn();
|
||||
|
||||
public:
|
||||
// Get the delta object for statistics.
|
||||
virtual ISrsKbpsDelta *delta() = 0;
|
||||
// Whether the connection coroutine is error or terminated.
|
||||
virtual srs_error_t pull() = 0;
|
||||
// Whether enable the CORS(cross-domain).
|
||||
virtual srs_error_t set_crossdomain_enabled(bool v) = 0;
|
||||
// Whether enable the Auth.
|
||||
virtual srs_error_t set_auth_enabled(bool auth_enabled) = 0;
|
||||
// Whether enable the JSONP.
|
||||
virtual srs_error_t set_jsonp(bool v) = 0;
|
||||
};
|
||||
|
||||
// TODO: FIXME: Should rename to roundtrip or responder, not connection.
|
||||
// The http connection which request the static or stream content.
|
||||
class SrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoroutineHandler, public ISrsExpire
|
||||
class SrsHttpConn : public ISrsHttpConn
|
||||
{
|
||||
protected:
|
||||
SrsHttpParser *parser_;
|
||||
ISrsHttpServeMux *http_mux_;
|
||||
SrsHttpCorsMux *cors_;
|
||||
SrsHttpAuthMux *auth_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsHttpParser *parser_;
|
||||
ISrsCommonHttpHandler *http_mux_;
|
||||
ISrsHttpCorsMux *cors_;
|
||||
ISrsHttpAuthMux *auth_;
|
||||
ISrsHttpConnOwner *handler_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
// Each connection start a green thread,
|
||||
// when thread stop, the connection will be delete by server.
|
||||
|
|
@ -78,15 +117,16 @@ protected:
|
|||
std::string ip_;
|
||||
int port_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The delta for statistic.
|
||||
SrsNetworkDelta *delta_;
|
||||
ISrsNetworkDelta *delta_;
|
||||
// The create time in microseconds.
|
||||
// for current connection to log self create time and calculate the living time.
|
||||
srs_utime_t create_time_;
|
||||
|
||||
public:
|
||||
SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd, ISrsHttpServeMux *m, std::string cip, int port);
|
||||
SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd, ISrsCommonHttpHandler *m, std::string cip, int port);
|
||||
virtual ~SrsHttpConn();
|
||||
// Interface ISrsResource.
|
||||
public:
|
||||
|
|
@ -101,7 +141,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
virtual srs_error_t process_requests(ISrsRequest **preq);
|
||||
virtual srs_error_t process_request(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, int rid);
|
||||
|
|
@ -130,15 +171,31 @@ public:
|
|||
virtual void expire();
|
||||
};
|
||||
|
||||
// Drop body of request, only process the response.
|
||||
class SrsHttpxConn : public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner, public ISrsReloadHandler
|
||||
// The HTTP connection manager.
|
||||
class ISrsHttpxConn : public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsHttpxConn();
|
||||
virtual ~ISrsHttpxConn();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// Drop body of request, only process the response.
|
||||
class SrsHttpxConn : public ISrsHttpxConn
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The manager object to manage the connection.
|
||||
ISrsResourceManager *manager_;
|
||||
ISrsProtocolReadWriter *io_;
|
||||
SrsSslConnection *ssl_;
|
||||
SrsHttpConn *conn_;
|
||||
ISrsSslConnection *ssl_;
|
||||
ISrsHttpConn *conn_;
|
||||
// We should never enable the stat, unless HTTP stream connection requires.
|
||||
bool enable_stat_;
|
||||
// ssl key & cert file
|
||||
|
|
@ -146,7 +203,7 @@ private:
|
|||
const std::string ssl_cert_file_;
|
||||
|
||||
public:
|
||||
SrsHttpxConn(ISrsResourceManager *cm, ISrsProtocolReadWriter *io, ISrsHttpServeMux *m, std::string cip, int port, std::string key, std::string cert);
|
||||
SrsHttpxConn(ISrsResourceManager *cm, ISrsProtocolReadWriter *io, ISrsCommonHttpHandler *m, std::string cip, int port, std::string key, std::string cert);
|
||||
virtual ~SrsHttpxConn();
|
||||
|
||||
public:
|
||||
|
|
@ -161,8 +218,8 @@ public:
|
|||
// Interface ISrsHttpConnOwner.
|
||||
public:
|
||||
virtual srs_error_t on_start();
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, ISrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, ISrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_conn_done(srs_error_t r0);
|
||||
// Interface ISrsResource.
|
||||
public:
|
||||
|
|
@ -180,11 +237,22 @@ public:
|
|||
};
|
||||
|
||||
// The http server, use http stream or static server to serve requests.
|
||||
class SrsHttpServer : public ISrsHttpServeMux
|
||||
class ISrsHttpServer : public ISrsCommonHttpHandler
|
||||
{
|
||||
private:
|
||||
SrsHttpStaticServer *http_static_;
|
||||
SrsHttpStreamServer *http_stream_;
|
||||
public:
|
||||
ISrsHttpServer();
|
||||
virtual ~ISrsHttpServer();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The http server, use http stream or static server to serve requests.
|
||||
class SrsHttpServer : public ISrsHttpServer
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpStaticServer *http_static_;
|
||||
ISrsHttpStreamServer *http_stream_;
|
||||
|
||||
public:
|
||||
SrsHttpServer();
|
||||
|
|
@ -192,7 +260,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// Interface ISrsHttpServeMux
|
||||
// Interface ISrsCommonHttpHandler
|
||||
public:
|
||||
virtual srs_error_t handle(std::string pattern, ISrsHttpHandler *handler);
|
||||
// Interface ISrsHttpHandler
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using namespace std;
|
|||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_dvr.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_client.hpp>
|
||||
#include <srs_app_http_conn.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
|
|
@ -46,10 +47,16 @@ ISrsHttpHooks::~ISrsHttpHooks()
|
|||
|
||||
SrsHttpHooks::SrsHttpHooks()
|
||||
{
|
||||
factory_ = _srs_app_factory;
|
||||
stat_ = _srs_stat;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsHttpHooks::~SrsHttpHooks()
|
||||
{
|
||||
factory_ = NULL;
|
||||
stat_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req)
|
||||
|
|
@ -57,7 +64,7 @@ srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -76,8 +83,8 @@ srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req)
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: on_connect failed, client_id=%s, url=%s, request=%s, response=%s, code=%d",
|
||||
cid.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code);
|
||||
}
|
||||
|
|
@ -93,7 +100,7 @@ void SrsHttpHooks::on_close(string url, ISrsRequest *req, int64_t send_bytes, in
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -110,8 +117,8 @@ void SrsHttpHooks::on_close(string url, ISrsRequest *req, int64_t send_bytes, in
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
int ret = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
srs_warn("http: ignore on_close failed, client_id=%s, url=%s, request=%s, response=%s, code=%d, ret=%d",
|
||||
|
|
@ -130,7 +137,7 @@ srs_error_t SrsHttpHooks::on_publish(string url, ISrsRequest *req)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -154,8 +161,8 @@ srs_error_t SrsHttpHooks::on_publish(string url, ISrsRequest *req)
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: on_publish failed, client_id=%s, url=%s, request=%s, response=%s, code=%d",
|
||||
cid.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code);
|
||||
}
|
||||
|
|
@ -171,7 +178,7 @@ void SrsHttpHooks::on_unpublish(string url, ISrsRequest *req)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -195,8 +202,8 @@ void SrsHttpHooks::on_unpublish(string url, ISrsRequest *req)
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
int ret = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
srs_warn("http: ignore on_unpublish failed, client_id=%s, url=%s, request=%s, response=%s, status=%d, ret=%d",
|
||||
|
|
@ -215,7 +222,7 @@ srs_error_t SrsHttpHooks::on_play(string url, ISrsRequest *req)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -240,8 +247,8 @@ srs_error_t SrsHttpHooks::on_play(string url, ISrsRequest *req)
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: on_play failed, client_id=%s, url=%s, request=%s, response=%s, status=%d",
|
||||
cid.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code);
|
||||
}
|
||||
|
|
@ -257,7 +264,7 @@ void SrsHttpHooks::on_stop(string url, ISrsRequest *req)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -281,8 +288,8 @@ void SrsHttpHooks::on_stop(string url, ISrsRequest *req)
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
int ret = srs_error_code(err);
|
||||
srs_freep(err);
|
||||
srs_warn("http: ignore on_stop failed, client_id=%s, url=%s, request=%s, response=%s, code=%d, ret=%d",
|
||||
|
|
@ -301,9 +308,9 @@ srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, ISrsRequest *req, s
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = c;
|
||||
std::string cwd = _srs_config->cwd();
|
||||
std::string cwd = config_->cwd();
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -329,8 +336,8 @@ srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, ISrsRequest *req, s
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http post on_dvr uri failed, client_id=%s, url=%s, request=%s, response=%s, code=%d",
|
||||
cid.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code);
|
||||
}
|
||||
|
|
@ -346,7 +353,7 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = c;
|
||||
std::string cwd = _srs_config->cwd();
|
||||
std::string cwd = config_->cwd();
|
||||
|
||||
// the ts_url is under the same dir of m3u8_url.
|
||||
SrsPath path;
|
||||
|
|
@ -355,7 +362,7 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s
|
|||
ts_url = prefix + "/" + ts_url;
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str()));
|
||||
|
|
@ -386,8 +393,8 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: post %s with %s, status=%d, res=%s", url.c_str(), data.c_str(), status_code, res.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -402,13 +409,13 @@ srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, ISrsReq
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsContextId cid = c;
|
||||
std::string cwd = _srs_config->cwd();
|
||||
std::string cwd = config_->cwd();
|
||||
|
||||
if (srs_net_url_is_http(ts_url)) {
|
||||
url = ts_url;
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
|
||||
url = srs_strings_replace(url, "[server_id]", stat->server_id().c_str());
|
||||
url = srs_strings_replace(url, "[service_id]", stat->service_id().c_str());
|
||||
|
|
@ -424,8 +431,8 @@ srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, ISrsReq
|
|||
return srs_error_wrap(err, "http: init url=%s", url.c_str());
|
||||
}
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = http.initialize(uri.get_schema(), uri.get_host(), uri.get_port(), SRS_HLS_NOTIFY_TIMEOUT)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = http->initialize(uri.get_schema(), uri.get_host(), uri.get_port(), SRS_HLS_NOTIFY_TIMEOUT)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: init client for %s", url.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +447,7 @@ srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, ISrsReq
|
|||
srs_info("GET %s", path.c_str());
|
||||
|
||||
ISrsHttpMessage *msg_raw = NULL;
|
||||
if ((err = http.get(path.c_str(), "", &msg_raw)) != srs_success) {
|
||||
if ((err = http->get(path.c_str(), "", &msg_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: get %s", url.c_str());
|
||||
}
|
||||
SrsUniquePtr<ISrsHttpMessage> msg(msg_raw);
|
||||
|
|
@ -474,8 +481,8 @@ srs_error_t SrsHttpHooks::discover_co_workers(string url, string &host, int &por
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, "", status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, "", status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: post %s, status=%d, res=%s", url.c_str(), status_code, res.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +534,7 @@ srs_error_t SrsHttpHooks::on_forward_backend(string url, ISrsRequest *req, std::
|
|||
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
ISrsStatistic *stat = stat_;
|
||||
SrsUniquePtr<SrsJsonObject> obj(SrsJsonAny::object());
|
||||
|
||||
obj->set("action", SrsJsonAny::str("on_forward"));
|
||||
|
|
@ -545,8 +552,8 @@ srs_error_t SrsHttpHooks::on_forward_backend(string url, ISrsRequest *req, std::
|
|||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((err = do_post(&http, url, data, status_code, res)) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(factory_->create_http_client());
|
||||
if ((err = do_post(http.get(), url, data, status_code, res)) != srs_success) {
|
||||
return srs_error_wrap(err, "http: on_forward_backend failed, client_id=%s, url=%s, request=%s, response=%s, code=%d",
|
||||
cid.c_str(), url.c_str(), data.c_str(), res.c_str(), status_code);
|
||||
}
|
||||
|
|
@ -589,7 +596,7 @@ srs_error_t SrsHttpHooks::on_forward_backend(string url, ISrsRequest *req, std::
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpHooks::do_post(SrsHttpClient *hc, std::string url, std::string req, int &code, string &res)
|
||||
srs_error_t SrsHttpHooks::do_post(ISrsHttpClient *hc, std::string url, std::string req, int &code, string &res)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ class SrsStSocket;
|
|||
class ISrsRequest;
|
||||
class SrsHttpParser;
|
||||
class SrsHttpClient;
|
||||
class ISrsAppFactory;
|
||||
class ISrsHttpClient;
|
||||
class ISrsStatistic;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// HTTP hooks interface for SRS server event callbacks.
|
||||
//
|
||||
|
|
@ -149,6 +153,12 @@ public:
|
|||
|
||||
class SrsHttpHooks : public ISrsHttpHooks
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *factory_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
public:
|
||||
SrsHttpHooks();
|
||||
virtual ~SrsHttpHooks();
|
||||
|
|
@ -167,8 +177,9 @@ public:
|
|||
srs_error_t discover_co_workers(std::string url, std::string &host, int &port);
|
||||
srs_error_t on_forward_backend(std::string url, ISrsRequest *req, std::vector<std::string> &rtmp_urls);
|
||||
|
||||
private:
|
||||
srs_error_t do_post(SrsHttpClient *hc, std::string url, std::string req, int &code, std::string &res);
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_post(ISrsHttpClient *hc, std::string url, std::string req, int &code, std::string &res);
|
||||
};
|
||||
|
||||
// Global HTTP hooks instance
|
||||
|
|
|
|||
|
|
@ -599,14 +599,27 @@ srs_error_t SrsVodStream::serve_ts_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessag
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsHttpStaticServer::ISrsHttpStaticServer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpStaticServer::~ISrsHttpStaticServer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpStaticServer::SrsHttpStaticServer()
|
||||
{
|
||||
_srs_config->subscribe(this);
|
||||
mux_ = new SrsHttpServeMux();
|
||||
}
|
||||
|
||||
SrsHttpStaticServer::~SrsHttpStaticServer()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
srs_freep(mux_);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpStaticServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
return mux_->serve_http(w, r);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpStaticServer::initialize()
|
||||
|
|
@ -640,7 +653,7 @@ srs_error_t SrsHttpStaticServer::initialize()
|
|||
if (!default_root_exists) {
|
||||
// add root
|
||||
std::string dir = _srs_config->get_http_stream_dir();
|
||||
if ((err = mux_.handle("/", new SrsVodStream(dir))) != srs_success) {
|
||||
if ((err = mux_->handle("/", new SrsVodStream(dir))) != srs_success) {
|
||||
return srs_error_wrap(err, "mount root dir=%s", dir.c_str());
|
||||
}
|
||||
srs_trace("http: root mount to %s", dir.c_str());
|
||||
|
|
@ -649,6 +662,11 @@ srs_error_t SrsHttpStaticServer::initialize()
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsHttpServeMux *SrsHttpStaticServer::mux()
|
||||
{
|
||||
return mux_;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpStaticServer::mount_vhost(string vhost, string &pmount)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
|
@ -679,7 +697,7 @@ srs_error_t SrsHttpStaticServer::mount_vhost(string vhost, string &pmount)
|
|||
}
|
||||
|
||||
// mount the http of vhost.
|
||||
if ((err = mux_.handle(mount, new SrsVodStream(dir))) != srs_success) {
|
||||
if ((err = mux_->handle(mount, new SrsVodStream(dir))) != srs_success) {
|
||||
return srs_error_wrap(err, "mux handle");
|
||||
}
|
||||
srs_trace("http: vhost=%s mount to %s at %s", vhost.c_str(), mount.c_str(), dir.c_str());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include <srs_core.hpp>
|
||||
|
||||
class ISrsFileReaderFactory;
|
||||
class ISrsCommonHttpHandler;
|
||||
class ISrsHttpServeMux;
|
||||
|
||||
// HLS virtual connection, build on query string ctx of hls stream.
|
||||
class SrsHlsVirtualConn : public ISrsExpire
|
||||
|
|
@ -33,9 +35,11 @@ public:
|
|||
// Server HLS streaming.
|
||||
class SrsHlsStream : public ISrsFastTimerHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The period of validity of the ctx
|
||||
std::map<std::string, SrsHlsVirtualConn *> map_ctx_info_;
|
||||
std::map<std::string, SrsHlsVirtualConn *>
|
||||
map_ctx_info_;
|
||||
|
||||
public:
|
||||
SrsHlsStream();
|
||||
|
|
@ -45,7 +49,8 @@ public:
|
|||
virtual srs_error_t serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, std::string fullpath, ISrsRequest *req, bool *served);
|
||||
virtual void on_serve_ts_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsRequest *req, std::string &ctx);
|
||||
srs_error_t serve_exists_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, std::string fullpath);
|
||||
bool ctx_is_exist(std::string ctx);
|
||||
|
|
@ -54,29 +59,34 @@ private:
|
|||
void http_hooks_on_stop(ISrsRequest *req);
|
||||
bool is_interrupt(std::string id);
|
||||
// interface ISrsFastTimerHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsSecurity *security_;
|
||||
};
|
||||
|
||||
// The Vod streaming, like FLV, MP4 or HLS streaming.
|
||||
class SrsVodStream : public SrsHttpFileServer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsHlsStream hls_;
|
||||
|
||||
public:
|
||||
SrsVodStream(std::string root_dir);
|
||||
virtual ~SrsVodStream();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The flv vod stream supports flv?start=offset-bytes.
|
||||
// For example, http://server/file.flv?start=10240
|
||||
// server will write flv header and sequence header,
|
||||
// then seek(10240) and response flv tag data.
|
||||
virtual srs_error_t serve_flv_stream(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string fullpath, int64_t offset);
|
||||
virtual srs_error_t
|
||||
serve_flv_stream(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string fullpath, int64_t offset);
|
||||
// Support mp4 with start and offset in query string.
|
||||
virtual srs_error_t serve_mp4_stream(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string fullpath, int64_t start, int64_t end);
|
||||
// Support HLS streaming with pseudo session id.
|
||||
|
|
@ -86,11 +96,24 @@ protected:
|
|||
};
|
||||
|
||||
// The http static server instance,
|
||||
// serve http static file and flv/mp4 vod stream.
|
||||
class SrsHttpStaticServer : public ISrsReloadHandler
|
||||
class ISrsHttpStaticServer : public ISrsHttpHandler
|
||||
{
|
||||
public:
|
||||
SrsHttpServeMux mux_;
|
||||
ISrsHttpStaticServer();
|
||||
virtual ~ISrsHttpStaticServer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize() = 0;
|
||||
virtual ISrsHttpServeMux *mux() = 0;
|
||||
};
|
||||
|
||||
// The http static server instance,
|
||||
// serve http static file and flv/mp4 vod stream.
|
||||
class SrsHttpStaticServer : public ISrsHttpStaticServer
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpServeMux *mux_;
|
||||
|
||||
public:
|
||||
SrsHttpStaticServer();
|
||||
|
|
@ -98,8 +121,14 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
virtual ISrsHttpServeMux *mux();
|
||||
|
||||
private:
|
||||
// Interface ISrsHttpHandler
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t mount_vhost(std::string vhost, std::string &pmount);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1046,24 +1046,36 @@ bool SrsLiveEntry::is_mp3()
|
|||
return is_mp3_;
|
||||
}
|
||||
|
||||
ISrsHttpStreamServer::ISrsHttpStreamServer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpStreamServer::~ISrsHttpStreamServer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpStreamServer::SrsHttpStreamServer()
|
||||
{
|
||||
async_ = new SrsAsyncCallWorker();
|
||||
|
||||
mux_.add_dynamic_matcher(this);
|
||||
mux_ = new SrsHttpServeMux();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
void SrsHttpStreamServer::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
SrsHttpServeMux *mux = dynamic_cast<SrsHttpServeMux *>(mux_);
|
||||
if (!mux) {
|
||||
mux->add_dynamic_matcher(this);
|
||||
}
|
||||
}
|
||||
|
||||
SrsHttpStreamServer::~SrsHttpStreamServer()
|
||||
{
|
||||
mux_.remove_dynamic_matcher(this);
|
||||
config_->unsubscribe(this);
|
||||
SrsHttpServeMux *mux = dynamic_cast<SrsHttpServeMux *>(mux_);
|
||||
if (mux) {
|
||||
mux->remove_dynamic_matcher(this);
|
||||
}
|
||||
|
||||
async_->stop();
|
||||
srs_freep(async_);
|
||||
|
|
@ -1104,6 +1116,11 @@ srs_error_t SrsHttpStreamServer::initialize()
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsHttpServeMux *SrsHttpStreamServer::mux()
|
||||
{
|
||||
return mux_;
|
||||
}
|
||||
|
||||
// TODO: FIXME: rename for HTTP FLV mount.
|
||||
srs_error_t SrsHttpStreamServer::http_mount(ISrsRequest *r)
|
||||
{
|
||||
|
|
@ -1152,7 +1169,7 @@ srs_error_t SrsHttpStreamServer::http_mount(ISrsRequest *r)
|
|||
// mount the http flv stream.
|
||||
// we must register the handler, then start the thread,
|
||||
// for the thread will cause thread switch context.
|
||||
if ((err = mux_.handle(mount, entry->stream_)) != srs_success) {
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
@ -1200,7 +1217,7 @@ void SrsHttpStreamServer::http_unmount(ISrsRequest *r)
|
|||
|
||||
// Use async worker to execute the task, which will destroy the stream.
|
||||
srs_error_t err = srs_success;
|
||||
if ((err = async_->execute(new SrsHttpStreamDestroy(&mux_, &streamHandlers_, sid))) != srs_success) {
|
||||
if ((err = async_->execute(new SrsHttpStreamDestroy(mux_, &streamHandlers_, sid))) != srs_success) {
|
||||
srs_warn("http: ignore unmount stream failed, sid=%s, err=%s", sid.c_str(), srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
|
@ -1353,7 +1370,7 @@ srs_error_t SrsHttpStreamServer::initialize_flv_entry(std::string vhost)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsHttpStreamDestroy::SrsHttpStreamDestroy(SrsHttpServeMux *mux, map<std::string, SrsLiveEntry *> *handlers, string sid)
|
||||
SrsHttpStreamDestroy::SrsHttpStreamDestroy(ISrsHttpServeMux *mux, map<std::string, SrsLiveEntry *> *handlers, string sid)
|
||||
{
|
||||
mux_ = mux;
|
||||
sid_ = sid;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class ISrsTsTransmuxer;
|
|||
class ISrsAacTransmuxer;
|
||||
class ISrsBufferCache;
|
||||
class ISrsMp3Transmuxer;
|
||||
class ISrsCommonHttpHandler;
|
||||
|
||||
// The cache for HTTP Live Streaming encoder.
|
||||
class ISrsBufferCache
|
||||
|
|
@ -50,14 +51,17 @@ public:
|
|||
// A cache for HTTP Live Streaming encoder, to make android(weixin) happy.
|
||||
class SrsBufferCache : public ISrsCoroutineHandler, public ISrsBufferCache
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_utime_t fast_cache_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsMessageQueue *queue_;
|
||||
ISrsRequest *req_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
|
@ -106,7 +110,8 @@ public:
|
|||
// Transmux RTMP to HTTP Live Streaming.
|
||||
class SrsFlvStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFlvTransmuxer *enc_;
|
||||
bool header_written_;
|
||||
bool has_audio_;
|
||||
|
|
@ -137,14 +142,16 @@ public:
|
|||
// Write the tags in a time.
|
||||
virtual srs_error_t write_tags(SrsMediaPacket **msgs, int count);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t write_header(bool has_video, bool has_audio);
|
||||
};
|
||||
|
||||
// Transmux RTMP to HTTP TS Streaming.
|
||||
class SrsTsStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsTsTransmuxer *enc_;
|
||||
|
||||
public:
|
||||
|
|
@ -170,7 +177,8 @@ public:
|
|||
// Transmux RTMP with AAC stream to HTTP AAC Streaming.
|
||||
class SrsAacStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAacTransmuxer *enc_;
|
||||
ISrsBufferCache *cache_;
|
||||
|
||||
|
|
@ -192,7 +200,8 @@ public:
|
|||
// Transmux RTMP with MP3 stream to HTTP MP3 Streaming.
|
||||
class SrsMp3StreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsMp3Transmuxer *enc_;
|
||||
ISrsBufferCache *cache_;
|
||||
|
||||
|
|
@ -214,7 +223,8 @@ public:
|
|||
// Write stream to http response direclty.
|
||||
class SrsBufferWriter : public SrsFileWriter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpResponseWriter *writer_;
|
||||
|
||||
public:
|
||||
|
|
@ -250,13 +260,15 @@ public:
|
|||
// TODO: FIXME: Rename to SrsHttpLive
|
||||
class SrsLiveStream : public ISrsLiveStream
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
ISrsBufferCache *cache_;
|
||||
ISrsSecurity *security_;
|
||||
|
|
@ -273,7 +285,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
public:
|
||||
|
|
@ -282,7 +295,8 @@ public:
|
|||
public:
|
||||
virtual void expire();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(SrsLiveSource *source, ISrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
virtual srs_error_t http_hooks_on_play(ISrsHttpMessage *r);
|
||||
virtual void http_hooks_on_stop(ISrsHttpMessage *r);
|
||||
|
|
@ -291,7 +305,8 @@ private:
|
|||
|
||||
// The Live Entry, to handle HTTP Live Streaming.
|
||||
struct SrsLiveEntry {
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool is_flv_;
|
||||
bool is_ts_;
|
||||
bool is_aac_;
|
||||
|
|
@ -322,17 +337,35 @@ public:
|
|||
};
|
||||
|
||||
// The HTTP Live Streaming Server, to serve FLV/TS/MP3/AAC stream.
|
||||
// TODO: Support multiple stream.
|
||||
class SrsHttpStreamServer : public ISrsReloadHandler, public ISrsHttpDynamicMatcher
|
||||
class ISrsHttpStreamServer : public ISrsHttpDynamicMatcher
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
public:
|
||||
ISrsHttpStreamServer();
|
||||
virtual ~ISrsHttpStreamServer();
|
||||
|
||||
private:
|
||||
public:
|
||||
virtual void assemble() = 0;
|
||||
virtual srs_error_t initialize() = 0;
|
||||
// HTTP flv/ts/mp3/aac stream
|
||||
virtual srs_error_t http_mount(ISrsRequest *r) = 0;
|
||||
virtual void http_unmount(ISrsRequest *r) = 0;
|
||||
virtual ISrsHttpServeMux *mux() = 0;
|
||||
};
|
||||
|
||||
// The HTTP Live Streaming Server, to serve FLV/TS/MP3/AAC stream.
|
||||
// TODO: Support multiple stream.
|
||||
class SrsHttpStreamServer : public ISrsHttpStreamServer
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsHttpServeMux *mux_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAsyncCallWorker *async_;
|
||||
|
||||
public:
|
||||
SrsHttpServeMux mux_;
|
||||
// The http live streaming template, to create streams.
|
||||
std::map<std::string, SrsLiveEntry *> templateHandlers_;
|
||||
// The http live streaming streams, created by template.
|
||||
|
|
@ -345,6 +378,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
virtual ISrsHttpServeMux *mux();
|
||||
|
||||
public:
|
||||
// HTTP flv/ts/mp3/aac stream
|
||||
|
|
@ -355,20 +389,22 @@ public:
|
|||
public:
|
||||
virtual srs_error_t dynamic_match(ISrsHttpMessage *request, ISrsHttpHandler **ph);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t initialize_flv_streaming();
|
||||
virtual srs_error_t initialize_flv_entry(std::string vhost);
|
||||
};
|
||||
|
||||
class SrsHttpStreamDestroy : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string sid_;
|
||||
std::map<std::string, SrsLiveEntry *> *streamHandlers_;
|
||||
SrsHttpServeMux *mux_;
|
||||
ISrsHttpServeMux *mux_;
|
||||
|
||||
public:
|
||||
SrsHttpStreamDestroy(SrsHttpServeMux *mux, std::map<std::string, SrsLiveEntry *> *handlers, std::string sid);
|
||||
SrsHttpStreamDestroy(ISrsHttpServeMux *mux, std::map<std::string, SrsLiveEntry *> *handlers, std::string sid);
|
||||
virtual ~SrsHttpStreamDestroy();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_ffmpeg.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
|
|
@ -18,6 +19,14 @@ using namespace std;
|
|||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
ISrsIngesterFFMPEG::ISrsIngesterFFMPEG()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsIngesterFFMPEG::~ISrsIngesterFFMPEG()
|
||||
{
|
||||
}
|
||||
|
||||
SrsIngesterFFMPEG::SrsIngesterFFMPEG()
|
||||
{
|
||||
ffmpeg_ = NULL;
|
||||
|
|
@ -29,7 +38,7 @@ SrsIngesterFFMPEG::~SrsIngesterFFMPEG()
|
|||
srs_freep(ffmpeg_);
|
||||
}
|
||||
|
||||
srs_error_t SrsIngesterFFMPEG::initialize(SrsFFMPEG *ff, string v, string i)
|
||||
srs_error_t SrsIngesterFFMPEG::initialize(ISrsFFMPEG *ff, string v, string i)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -86,24 +95,34 @@ void SrsIngesterFFMPEG::fast_kill()
|
|||
ffmpeg_->fast_kill();
|
||||
}
|
||||
|
||||
ISrsIngester::ISrsIngester()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsIngester::~ISrsIngester()
|
||||
{
|
||||
}
|
||||
|
||||
SrsIngester::SrsIngester()
|
||||
{
|
||||
_srs_config->subscribe(this);
|
||||
|
||||
expired_ = false;
|
||||
disposed_ = false;
|
||||
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
pprint_ = SrsPithyPrint::create_ingester();
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsIngester::~SrsIngester()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
|
||||
srs_freep(trd_);
|
||||
clear_engines();
|
||||
srs_freep(pprint_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsIngester::dispose()
|
||||
|
|
@ -116,7 +135,8 @@ void SrsIngester::dispose()
|
|||
// first, use fast stop to notice all FFMPEG to quit gracefully.
|
||||
fast_stop();
|
||||
|
||||
srs_usleep(100 * SRS_UTIME_MILLISECONDS);
|
||||
SrsUniquePtr<ISrsTime> time(app_factory_->create_time());
|
||||
time->usleep(100 * SRS_UTIME_MILLISECONDS);
|
||||
|
||||
// then, use fast kill to ensure FFMPEG quit.
|
||||
fast_kill();
|
||||
|
|
@ -136,7 +156,7 @@ srs_error_t SrsIngester::start()
|
|||
|
||||
// start thread to run all encoding engines.
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsSTCoroutine("ingest", this, _srs_context->get_id());
|
||||
trd_ = app_factory_->create_coroutine("ingest", this, _srs_context->get_id());
|
||||
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start coroutine");
|
||||
|
|
@ -153,9 +173,9 @@ void SrsIngester::stop()
|
|||
|
||||
void SrsIngester::fast_stop()
|
||||
{
|
||||
std::vector<SrsIngesterFFMPEG *>::iterator it;
|
||||
std::vector<ISrsIngesterFFMPEG *>::iterator it;
|
||||
for (it = ingesters_.begin(); it != ingesters_.end(); ++it) {
|
||||
SrsIngesterFFMPEG *ingester = *it;
|
||||
ISrsIngesterFFMPEG *ingester = *it;
|
||||
ingester->fast_stop();
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +186,9 @@ void SrsIngester::fast_stop()
|
|||
|
||||
void SrsIngester::fast_kill()
|
||||
{
|
||||
std::vector<SrsIngesterFFMPEG *>::iterator it;
|
||||
std::vector<ISrsIngesterFFMPEG *>::iterator it;
|
||||
for (it = ingesters_.begin(); it != ingesters_.end(); ++it) {
|
||||
SrsIngesterFFMPEG *ingester = *it;
|
||||
ISrsIngesterFFMPEG *ingester = *it;
|
||||
ingester->fast_kill();
|
||||
}
|
||||
|
||||
|
|
@ -185,6 +205,8 @@ srs_error_t SrsIngester::cycle()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsUniquePtr<ISrsTime> time(app_factory_->create_time());
|
||||
|
||||
while (!disposed_) {
|
||||
// We always check status first.
|
||||
// @see https://github.com/ossrs/srs/issues/1634#issuecomment-597571561
|
||||
|
|
@ -197,7 +219,7 @@ srs_error_t SrsIngester::cycle()
|
|||
srs_freep(err);
|
||||
}
|
||||
|
||||
srs_usleep(SRS_INGESTER_CIMS);
|
||||
time->usleep(SRS_INGESTER_CIMS);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
@ -222,9 +244,9 @@ srs_error_t SrsIngester::do_cycle()
|
|||
}
|
||||
|
||||
// cycle exists ingesters.
|
||||
std::vector<SrsIngesterFFMPEG *>::iterator it;
|
||||
std::vector<ISrsIngesterFFMPEG *>::iterator it;
|
||||
for (it = ingesters_.begin(); it != ingesters_.end(); ++it) {
|
||||
SrsIngesterFFMPEG *ingester = *it;
|
||||
ISrsIngesterFFMPEG *ingester = *it;
|
||||
|
||||
// start all ffmpegs.
|
||||
if ((err = ingester->start()) != srs_success) {
|
||||
|
|
@ -245,10 +267,10 @@ srs_error_t SrsIngester::do_cycle()
|
|||
|
||||
void SrsIngester::clear_engines()
|
||||
{
|
||||
std::vector<SrsIngesterFFMPEG *>::iterator it;
|
||||
std::vector<ISrsIngesterFFMPEG *>::iterator it;
|
||||
|
||||
for (it = ingesters_.begin(); it != ingesters_.end(); ++it) {
|
||||
SrsIngesterFFMPEG *ingester = *it;
|
||||
ISrsIngesterFFMPEG *ingester = *it;
|
||||
srs_freep(ingester);
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +283,7 @@ srs_error_t SrsIngester::parse()
|
|||
|
||||
// parse ingesters
|
||||
std::vector<SrsConfDirective *> vhosts;
|
||||
_srs_config->get_vhosts(vhosts);
|
||||
config_->get_vhosts(vhosts);
|
||||
|
||||
for (int i = 0; i < (int)vhosts.size(); i++) {
|
||||
SrsConfDirective *vhost = vhosts[i];
|
||||
|
|
@ -278,11 +300,11 @@ srs_error_t SrsIngester::parse_ingesters(SrsConfDirective *vhost)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// when vhost disabled, ignore any ingesters.
|
||||
if (!_srs_config->get_vhost_enabled(vhost)) {
|
||||
if (!config_->get_vhost_enabled(vhost)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
std::vector<SrsConfDirective *> ingesters = _srs_config->get_ingesters(vhost->arg0());
|
||||
std::vector<SrsConfDirective *> ingesters = config_->get_ingesters(vhost->arg0());
|
||||
|
||||
// create engine
|
||||
for (int i = 0; i < (int)ingesters.size(); i++) {
|
||||
|
|
@ -299,27 +321,27 @@ srs_error_t SrsIngester::parse_engines(SrsConfDirective *vhost, SrsConfDirective
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_ingest_enabled(ingest)) {
|
||||
if (!config_->get_ingest_enabled(ingest)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
std::string ffmpeg_bin = _srs_config->get_ingest_ffmpeg(ingest);
|
||||
std::string ffmpeg_bin = config_->get_ingest_ffmpeg(ingest);
|
||||
if (ffmpeg_bin.empty()) {
|
||||
return srs_error_new(ERROR_ENCODER_PARSE, "parse ffmpeg");
|
||||
}
|
||||
|
||||
// get all engines.
|
||||
std::vector<SrsConfDirective *> engines = _srs_config->get_transcode_engines(ingest);
|
||||
std::vector<SrsConfDirective *> engines = config_->get_transcode_engines(ingest);
|
||||
|
||||
// create ingesters without engines.
|
||||
if (engines.empty()) {
|
||||
SrsFFMPEG *ffmpeg = new SrsFFMPEG(ffmpeg_bin);
|
||||
ISrsFFMPEG *ffmpeg = app_factory_->create_ffmpeg(ffmpeg_bin);
|
||||
if ((err = initialize_ffmpeg(ffmpeg, vhost, ingest, NULL)) != srs_success) {
|
||||
srs_freep(ffmpeg);
|
||||
return srs_error_wrap(err, "init ffmpeg");
|
||||
}
|
||||
|
||||
SrsIngesterFFMPEG *ingester = new SrsIngesterFFMPEG();
|
||||
ISrsIngesterFFMPEG *ingester = app_factory_->create_ingester_ffmpeg();
|
||||
if ((err = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != srs_success) {
|
||||
srs_freep(ingester);
|
||||
return srs_error_wrap(err, "init ingester");
|
||||
|
|
@ -332,13 +354,13 @@ srs_error_t SrsIngester::parse_engines(SrsConfDirective *vhost, SrsConfDirective
|
|||
// create ingesters with engine
|
||||
for (int i = 0; i < (int)engines.size(); i++) {
|
||||
SrsConfDirective *engine = engines[i];
|
||||
SrsFFMPEG *ffmpeg = new SrsFFMPEG(ffmpeg_bin);
|
||||
ISrsFFMPEG *ffmpeg = app_factory_->create_ffmpeg(ffmpeg_bin);
|
||||
if ((err = initialize_ffmpeg(ffmpeg, vhost, ingest, engine)) != srs_success) {
|
||||
srs_freep(ffmpeg);
|
||||
return srs_error_wrap(err, "init ffmpeg");
|
||||
}
|
||||
|
||||
SrsIngesterFFMPEG *ingester = new SrsIngesterFFMPEG();
|
||||
ISrsIngesterFFMPEG *ingester = app_factory_->create_ingester_ffmpeg();
|
||||
if ((err = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != srs_success) {
|
||||
srs_freep(ingester);
|
||||
return srs_error_wrap(err, "init ingester");
|
||||
|
|
@ -350,13 +372,13 @@ srs_error_t SrsIngester::parse_engines(SrsConfDirective *vhost, SrsConfDirective
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *vhost, SrsConfDirective *ingest, SrsConfDirective *engine)
|
||||
srs_error_t SrsIngester::initialize_ffmpeg(ISrsFFMPEG *ffmpeg, SrsConfDirective *vhost, SrsConfDirective *ingest, SrsConfDirective *engine)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
int port;
|
||||
if (true) {
|
||||
std::vector<std::string> ip_ports = _srs_config->get_listens();
|
||||
std::vector<std::string> ip_ports = config_->get_listens();
|
||||
srs_assert(ip_ports.size() > 0);
|
||||
|
||||
std::string ip;
|
||||
|
|
@ -364,7 +386,7 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *
|
|||
srs_net_split_for_listener(ep, ip, port);
|
||||
}
|
||||
|
||||
std::string output = _srs_config->get_engine_output(engine);
|
||||
std::string output = config_->get_engine_output(engine);
|
||||
// output stream, to other/self server
|
||||
// ie. rtmp://localhost:1935/live/livestream_sd
|
||||
output = srs_strings_replace(output, "[vhost]", vhost->arg0());
|
||||
|
|
@ -390,8 +412,8 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *
|
|||
|
||||
std::string log_file = SRS_CONSTS_NULL_FILE; // disabled
|
||||
// write ffmpeg info to log file.
|
||||
if (_srs_config->get_ff_log_enabled()) {
|
||||
log_file = _srs_config->get_ff_log_dir();
|
||||
if (config_->get_ff_log_enabled()) {
|
||||
log_file = config_->get_ff_log_dir();
|
||||
log_file += "/";
|
||||
log_file += "ffmpeg-ingest";
|
||||
log_file += "-";
|
||||
|
|
@ -403,20 +425,20 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *
|
|||
log_file += ".log";
|
||||
}
|
||||
|
||||
std::string log_level = _srs_config->get_ff_log_level();
|
||||
std::string log_level = config_->get_ff_log_level();
|
||||
if (!log_level.empty()) {
|
||||
ffmpeg->append_iparam("-loglevel");
|
||||
ffmpeg->append_iparam(log_level);
|
||||
}
|
||||
|
||||
// input
|
||||
std::string input_type = _srs_config->get_ingest_input_type(ingest);
|
||||
std::string input_type = config_->get_ingest_input_type(ingest);
|
||||
if (input_type.empty()) {
|
||||
return srs_error_new(ERROR_ENCODER_NO_INPUT, "empty intput type, ingest=%s", ingest->arg0().c_str());
|
||||
}
|
||||
|
||||
if (srs_config_ingest_is_file(input_type)) {
|
||||
std::string input_url = _srs_config->get_ingest_input_url(ingest);
|
||||
std::string input_url = config_->get_ingest_input_url(ingest);
|
||||
if (input_url.empty()) {
|
||||
return srs_error_new(ERROR_ENCODER_NO_INPUT, "empty intput url, ingest=%s", ingest->arg0().c_str());
|
||||
}
|
||||
|
|
@ -428,7 +450,7 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *
|
|||
return srs_error_wrap(err, "init ffmpeg");
|
||||
}
|
||||
} else if (srs_config_ingest_is_stream(input_type)) {
|
||||
std::string input_url = _srs_config->get_ingest_input_url(ingest);
|
||||
std::string input_url = config_->get_ingest_input_url(ingest);
|
||||
if (input_url.empty()) {
|
||||
return srs_error_new(ERROR_ENCODER_NO_INPUT, "empty intput url, ingest=%s", ingest->arg0().c_str());
|
||||
}
|
||||
|
|
@ -446,10 +468,10 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *
|
|||
// set output format to flv for RTMP
|
||||
ffmpeg->set_oformat("flv");
|
||||
|
||||
std::string vcodec = _srs_config->get_engine_vcodec(engine);
|
||||
std::string acodec = _srs_config->get_engine_acodec(engine);
|
||||
std::string vcodec = config_->get_engine_vcodec(engine);
|
||||
std::string acodec = config_->get_engine_acodec(engine);
|
||||
// whatever the engine config, use copy as default.
|
||||
bool engine_disabled = !engine || !_srs_config->get_engine_enabled(engine);
|
||||
bool engine_disabled = !engine || !config_->get_engine_enabled(engine);
|
||||
if (engine_disabled || vcodec.empty() || acodec.empty()) {
|
||||
if ((err = ffmpeg->initialize_copy()) != srs_success) {
|
||||
return srs_error_wrap(err, "init ffmpeg");
|
||||
|
|
@ -476,7 +498,7 @@ void SrsIngester::show_ingest_log_message()
|
|||
// random choose one ingester to report.
|
||||
SrsRand rand;
|
||||
int index = rand.integer() % (int)ingesters_.size();
|
||||
SrsIngesterFFMPEG *ingester = ingesters_.at(index);
|
||||
ISrsIngesterFFMPEG *ingester = ingesters_.at(index);
|
||||
|
||||
// reportable
|
||||
if (pprint_->can_print()) {
|
||||
|
|
|
|||
|
|
@ -15,16 +15,45 @@
|
|||
#include <srs_app_st.hpp>
|
||||
|
||||
class SrsFFMPEG;
|
||||
class ISrsFFMPEG;
|
||||
class SrsConfDirective;
|
||||
class SrsPithyPrint;
|
||||
class ISrsPithyPrint;
|
||||
class ISrsAppFactory;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The ingest ffmpeg interface.
|
||||
class ISrsIngesterFFMPEG
|
||||
{
|
||||
public:
|
||||
ISrsIngesterFFMPEG();
|
||||
virtual ~ISrsIngesterFFMPEG();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsFFMPEG *ff, std::string v, std::string i) = 0;
|
||||
// The ingest uri, [vhost]/[ingest id]
|
||||
virtual std::string uri() = 0;
|
||||
// The alive in srs_utime_t.
|
||||
virtual srs_utime_t alive() = 0;
|
||||
virtual bool equals(std::string v, std::string i) = 0;
|
||||
virtual bool equals(std::string v) = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
virtual void fast_stop() = 0;
|
||||
virtual void fast_kill() = 0;
|
||||
};
|
||||
|
||||
// Ingester ffmpeg object.
|
||||
class SrsIngesterFFMPEG
|
||||
class SrsIngesterFFMPEG : public ISrsIngesterFFMPEG
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string vhost_;
|
||||
std::string id_;
|
||||
SrsFFMPEG *ffmpeg_;
|
||||
ISrsFFMPEG *ffmpeg_;
|
||||
srs_utime_t starttime_;
|
||||
|
||||
public:
|
||||
|
|
@ -32,7 +61,7 @@ public:
|
|||
virtual ~SrsIngesterFFMPEG();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFFMPEG *ff, std::string v, std::string i);
|
||||
virtual srs_error_t initialize(ISrsFFMPEG *ff, std::string v, std::string i);
|
||||
// The ingest uri, [vhost]/[ingest id]
|
||||
virtual std::string uri();
|
||||
// The alive in srs_utime_t.
|
||||
|
|
@ -44,22 +73,38 @@ public:
|
|||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual srs_error_t cycle();
|
||||
// @see SrsFFMPEG.fast_stop().
|
||||
virtual void fast_stop();
|
||||
virtual void fast_kill();
|
||||
};
|
||||
|
||||
// The ingest interface.
|
||||
class ISrsIngester
|
||||
{
|
||||
public:
|
||||
ISrsIngester();
|
||||
virtual ~ISrsIngester();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// Ingest file/stream/device,
|
||||
// encode with FFMPEG(optional),
|
||||
// push to SRS(or any RTMP server) over RTMP.
|
||||
class SrsIngester : public ISrsCoroutineHandler, public ISrsReloadHandler
|
||||
class SrsIngester : public ISrsIngester, public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
std::vector<SrsIngesterFFMPEG *> ingesters_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<ISrsIngesterFFMPEG *> ingesters_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
SrsPithyPrint *pprint_;
|
||||
ISrsPithyPrint *pprint_;
|
||||
// Whether the ingesters are expired, for example, the listen port changed,
|
||||
// all ingesters must be restart.
|
||||
bool expired_;
|
||||
|
|
@ -77,24 +122,28 @@ public:
|
|||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Notify FFMPEG to fast stop.
|
||||
virtual void fast_stop();
|
||||
virtual void
|
||||
fast_stop();
|
||||
// When SRS quit, directly kill FFMPEG after fast stop.
|
||||
virtual void fast_kill();
|
||||
// Interface ISrsReusableThreadHandler.
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void clear_engines();
|
||||
virtual srs_error_t parse();
|
||||
virtual srs_error_t parse_ingesters(SrsConfDirective *vhost);
|
||||
virtual srs_error_t parse_engines(SrsConfDirective *vhost, SrsConfDirective *ingest);
|
||||
virtual srs_error_t initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsConfDirective *vhost, SrsConfDirective *ingest, SrsConfDirective *engine);
|
||||
virtual srs_error_t initialize_ffmpeg(ISrsFFMPEG *ffmpeg, SrsConfDirective *vhost, SrsConfDirective *ingest, SrsConfDirective *engine);
|
||||
virtual void show_ingest_log_message();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <srs_app_http_conn.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
|
|
@ -176,11 +177,15 @@ void srs_build_features(stringstream &ss)
|
|||
SrsLatestVersion::SrsLatestVersion()
|
||||
{
|
||||
trd_ = new SrsSTCoroutine("signal", this);
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsLatestVersion::~SrsLatestVersion()
|
||||
{
|
||||
srs_freep(trd_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsLatestVersion::start()
|
||||
|
|
@ -255,8 +260,8 @@ srs_error_t SrsLatestVersion::query_latest_version(string &url)
|
|||
}
|
||||
|
||||
// Start HTTP request and read response.
|
||||
SrsHttpClient http;
|
||||
if ((err = http.initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
||||
SrsUniquePtr<ISrsHttpClient> http(app_factory_->create_http_client());
|
||||
if ((err = http->initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +271,7 @@ srs_error_t SrsLatestVersion::query_latest_version(string &url)
|
|||
path += uri.get_query();
|
||||
|
||||
ISrsHttpMessage *msg_raw = NULL;
|
||||
if ((err = http.get(path, "", &msg_raw)) != srs_success) {
|
||||
if ((err = http->get(path, "", &msg_raw)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,16 +15,28 @@
|
|||
|
||||
#include <srs_app_st.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
class ISrsAppFactory;
|
||||
|
||||
// Build features string for version query
|
||||
extern void srs_build_features(std::stringstream &ss);
|
||||
|
||||
class SrsLatestVersion : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
std::string server_id_;
|
||||
std::string session_id_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string match_version_;
|
||||
std::string stable_version_;
|
||||
|
||||
|
|
@ -38,7 +50,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t query_latest_version(std::string &url);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,17 +17,17 @@
|
|||
#include <unistd.h>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_server.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_kbps.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_pithy_print.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
#include <srs_kernel_kbps.hpp>
|
||||
|
||||
SrsPps *_srs_pps_rpkts = NULL;
|
||||
SrsPps *_srs_pps_addrs = NULL;
|
||||
SrsPps *_srs_pps_fast_addrs = NULL;
|
||||
|
|
@ -64,6 +64,14 @@ ISrsListener::~ISrsListener()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsIpListener::ISrsIpListener()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsIpListener::~ISrsIpListener()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTcpHandler::ISrsTcpHandler()
|
||||
{
|
||||
}
|
||||
|
|
@ -83,6 +91,8 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler *h)
|
|||
buf_ = new char[nb_buf_];
|
||||
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
|
||||
factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsUdpListener::~SrsUdpListener()
|
||||
|
|
@ -90,15 +100,17 @@ SrsUdpListener::~SrsUdpListener()
|
|||
srs_freep(trd_);
|
||||
srs_close_stfd(lfd_);
|
||||
srs_freepa(buf_);
|
||||
|
||||
factory_ = NULL;
|
||||
}
|
||||
|
||||
SrsUdpListener *SrsUdpListener::set_label(const std::string &label)
|
||||
ISrsListener *SrsUdpListener::set_label(const std::string &label)
|
||||
{
|
||||
label_ = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
SrsUdpListener *SrsUdpListener::set_endpoint(const std::string &i, int p)
|
||||
ISrsListener *SrsUdpListener::set_endpoint(const std::string &i, int p)
|
||||
{
|
||||
ip_ = i;
|
||||
port_ = p;
|
||||
|
|
@ -175,7 +187,7 @@ srs_error_t SrsUdpListener::listen()
|
|||
set_socket_buffer();
|
||||
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsSTCoroutine("udp", this, _srs_context->get_id());
|
||||
trd_ = factory_->create_coroutine("udp", this, _srs_context->get_id());
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start thread");
|
||||
}
|
||||
|
|
@ -242,28 +254,32 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler *h)
|
|||
lfd_ = NULL;
|
||||
label_ = "TCP";
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
|
||||
factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsTcpListener::~SrsTcpListener()
|
||||
{
|
||||
srs_freep(trd_);
|
||||
srs_close_stfd(lfd_);
|
||||
|
||||
factory_ = NULL;
|
||||
}
|
||||
|
||||
SrsTcpListener *SrsTcpListener::set_label(const std::string &label)
|
||||
ISrsListener *SrsTcpListener::set_label(const std::string &label)
|
||||
{
|
||||
label_ = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
SrsTcpListener *SrsTcpListener::set_endpoint(const std::string &i, int p)
|
||||
ISrsListener *SrsTcpListener::set_endpoint(const std::string &i, int p)
|
||||
{
|
||||
ip_ = i;
|
||||
port_ = p;
|
||||
return this;
|
||||
}
|
||||
|
||||
SrsTcpListener *SrsTcpListener::set_endpoint(const std::string &endpoint)
|
||||
ISrsListener *SrsTcpListener::set_endpoint(const std::string &endpoint)
|
||||
{
|
||||
std::string ip;
|
||||
int port_;
|
||||
|
|
@ -290,7 +306,7 @@ srs_error_t SrsTcpListener::listen()
|
|||
}
|
||||
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsSTCoroutine("tcp", this);
|
||||
trd_ = factory_->create_coroutine("tcp", this, _srs_context->get_id());
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "start coroutine");
|
||||
}
|
||||
|
|
@ -348,35 +364,50 @@ srs_error_t SrsTcpListener::do_cycle()
|
|||
SrsMultipleTcpListeners::SrsMultipleTcpListeners(ISrsTcpHandler *h)
|
||||
{
|
||||
handler_ = h;
|
||||
|
||||
factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsMultipleTcpListeners::~SrsMultipleTcpListeners()
|
||||
{
|
||||
for (vector<SrsTcpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
SrsTcpListener *l = *it;
|
||||
for (vector<ISrsIpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
ISrsIpListener *l = *it;
|
||||
srs_freep(l);
|
||||
}
|
||||
|
||||
factory_ = NULL;
|
||||
}
|
||||
|
||||
SrsMultipleTcpListeners *SrsMultipleTcpListeners::set_label(const std::string &label)
|
||||
ISrsListener *SrsMultipleTcpListeners::set_label(const std::string &label)
|
||||
{
|
||||
for (vector<SrsTcpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
SrsTcpListener *l = *it;
|
||||
for (vector<ISrsIpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
ISrsIpListener *l = *it;
|
||||
l->set_label(label);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
SrsMultipleTcpListeners *SrsMultipleTcpListeners::add(const std::vector<std::string> &endpoints)
|
||||
ISrsListener *SrsMultipleTcpListeners::set_endpoint(const std::string &i, int p)
|
||||
{
|
||||
for (vector<ISrsIpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
ISrsIpListener *l = *it;
|
||||
l->set_endpoint(i, p);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
ISrsIpListener *SrsMultipleTcpListeners::add(const std::vector<std::string> &endpoints)
|
||||
{
|
||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||
string ip;
|
||||
int port;
|
||||
srs_net_split_for_listener(endpoints[i], ip, port);
|
||||
|
||||
SrsTcpListener *l = new SrsTcpListener(this);
|
||||
listeners_.push_back(l->set_endpoint(ip, port));
|
||||
ISrsIpListener *l = factory_->create_tcp_listener(this);
|
||||
l->set_endpoint(ip, port);
|
||||
listeners_.push_back(l);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
@ -386,8 +417,8 @@ srs_error_t SrsMultipleTcpListeners::listen()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
for (vector<SrsTcpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
SrsTcpListener *l = *it;
|
||||
for (vector<ISrsIpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
ISrsIpListener *l = *it;
|
||||
|
||||
if ((err = l->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "listen");
|
||||
|
|
@ -399,8 +430,8 @@ srs_error_t SrsMultipleTcpListeners::listen()
|
|||
|
||||
void SrsMultipleTcpListeners::close()
|
||||
{
|
||||
for (vector<SrsTcpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
SrsTcpListener *l = *it;
|
||||
for (vector<ISrsIpListener *>::iterator it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
ISrsIpListener *l = *it;
|
||||
srs_freep(l);
|
||||
}
|
||||
listeners_.clear();
|
||||
|
|
@ -411,6 +442,14 @@ srs_error_t SrsMultipleTcpListeners::on_tcp_client(ISrsListener *listener, srs_n
|
|||
return handler_->on_tcp_client(this, stfd);
|
||||
}
|
||||
|
||||
ISrsUdpMuxSocket::ISrsUdpMuxSocket()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsUdpMuxSocket::~ISrsUdpMuxSocket()
|
||||
{
|
||||
}
|
||||
|
||||
SrsUdpMuxSocket::SrsUdpMuxSocket(srs_netfd_t fd)
|
||||
{
|
||||
nn_msgs_for_yield_ = 0;
|
||||
|
|
@ -593,7 +632,7 @@ SrsBuffer *SrsUdpMuxSocket::buffer()
|
|||
return cache_buffer_;
|
||||
}
|
||||
|
||||
SrsUdpMuxSocket *SrsUdpMuxSocket::copy_sendonly()
|
||||
ISrsUdpMuxSocket *SrsUdpMuxSocket::copy_sendonly()
|
||||
{
|
||||
SrsUdpMuxSocket *sendonly = new SrsUdpMuxSocket(lfd_);
|
||||
|
||||
|
|
@ -628,6 +667,8 @@ SrsUdpMuxListener::SrsUdpMuxListener(ISrsUdpMuxHandler *h, std::string i, int p)
|
|||
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
cid_ = _srs_context->generate_id();
|
||||
|
||||
factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsUdpMuxListener::~SrsUdpMuxListener()
|
||||
|
|
@ -635,6 +676,8 @@ SrsUdpMuxListener::~SrsUdpMuxListener()
|
|||
srs_freep(trd_);
|
||||
srs_close_stfd(lfd_);
|
||||
srs_freepa(buf_);
|
||||
|
||||
factory_ = NULL;
|
||||
}
|
||||
|
||||
int SrsUdpMuxListener::fd()
|
||||
|
|
@ -656,7 +699,7 @@ srs_error_t SrsUdpMuxListener::listen()
|
|||
}
|
||||
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsSTCoroutine("udp", this, cid_);
|
||||
trd_ = factory_->create_coroutine("udp", this, cid_);
|
||||
|
||||
// change stack size to 256K, fix crash when call some 3rd-part api.
|
||||
((SrsSTCoroutine *)trd_)->set_stack_size(1 << 18);
|
||||
|
|
@ -727,7 +770,8 @@ srs_error_t SrsUdpMuxListener::cycle()
|
|||
// Because we have to decrypt the cipher of received packet payload,
|
||||
// and the size is not determined, so we think there is at least one copy,
|
||||
// and we can reuse the plaintext h264/opus with players when got plaintext.
|
||||
SrsUdpMuxSocket skt(lfd_);
|
||||
SrsUniquePtr<SrsUdpMuxSocket> skt_ptr(new SrsUdpMuxSocket(lfd_));
|
||||
ISrsUdpMuxSocket *skt = skt_ptr.get();
|
||||
|
||||
// How many messages to run a yield.
|
||||
uint32_t nn_msgs_for_yield = 0;
|
||||
|
|
@ -739,7 +783,7 @@ srs_error_t SrsUdpMuxListener::cycle()
|
|||
|
||||
nn_loop++;
|
||||
|
||||
int nread = skt.recvfrom(SRS_UTIME_NO_TIMEOUT);
|
||||
int nread = skt->recvfrom(SRS_UTIME_NO_TIMEOUT);
|
||||
if (nread <= 0) {
|
||||
if (nread < 0) {
|
||||
srs_warn("udp recv error nn=%d", nread);
|
||||
|
|
@ -752,7 +796,7 @@ srs_error_t SrsUdpMuxListener::cycle()
|
|||
nn_msgs_stage++;
|
||||
|
||||
// Handle the UDP packet.
|
||||
err = handler_->on_udp_packet(&skt);
|
||||
err = handler_->on_udp_packet(skt);
|
||||
|
||||
// Use pithy print to show more smart information.
|
||||
if (err != srs_success) {
|
||||
|
|
@ -762,7 +806,7 @@ srs_error_t SrsUdpMuxListener::cycle()
|
|||
_srs_context->set_id(cid_);
|
||||
|
||||
// Append more information.
|
||||
err = srs_error_wrap(err, "size=%u, data=[%s]", skt.size(), srs_strings_dumps_hex(skt.data(), skt.size(), 8).c_str());
|
||||
err = srs_error_wrap(err, "size=%u, data=[%s]", skt->size(), srs_strings_dumps_hex(skt->data(), skt->size(), 8).c_str());
|
||||
srs_warn("handle udp pkt, count=%u/%u, err: %s", pp_pkt_handler_err->nn_count_, nn, srs_error_desc(err).c_str());
|
||||
}
|
||||
srs_freep(err);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ struct sockaddr;
|
|||
class SrsBuffer;
|
||||
class SrsUdpMuxSocket;
|
||||
class ISrsListener;
|
||||
class ISrsAppFactory;
|
||||
class ISrsUdpMuxSocket;
|
||||
|
||||
// The udp packet handler.
|
||||
class ISrsUdpHandler
|
||||
|
|
@ -50,7 +52,7 @@ public:
|
|||
virtual ~ISrsUdpMuxHandler();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket *skt) = 0;
|
||||
virtual srs_error_t on_udp_packet(ISrsUdpMuxSocket *skt) = 0;
|
||||
};
|
||||
|
||||
// All listener should support listen method.
|
||||
|
|
@ -64,6 +66,19 @@ public:
|
|||
virtual srs_error_t listen() = 0;
|
||||
};
|
||||
|
||||
// The IP layer TCP/UDP listener.
|
||||
class ISrsIpListener : public ISrsListener
|
||||
{
|
||||
public:
|
||||
ISrsIpListener();
|
||||
virtual ~ISrsIpListener();
|
||||
|
||||
public:
|
||||
virtual ISrsListener *set_endpoint(const std::string &i, int p) = 0;
|
||||
virtual ISrsListener *set_label(const std::string &label) = 0;
|
||||
virtual void close() = 0;
|
||||
};
|
||||
|
||||
// The tcp connection handler.
|
||||
class ISrsTcpHandler
|
||||
{
|
||||
|
|
@ -77,18 +92,25 @@ public:
|
|||
};
|
||||
|
||||
// Bind udp port, start thread to recv packet and handler it.
|
||||
class SrsUdpListener : public ISrsCoroutineHandler
|
||||
class SrsUdpListener : public ISrsCoroutineHandler, public ISrsIpListener
|
||||
{
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
std::string label_;
|
||||
srs_netfd_t lfd_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
char *buf_;
|
||||
int nb_buf_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsUdpHandler *handler_;
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
@ -98,14 +120,16 @@ public:
|
|||
virtual ~SrsUdpListener();
|
||||
|
||||
public:
|
||||
SrsUdpListener *set_label(const std::string &label);
|
||||
SrsUdpListener *set_endpoint(const std::string &i, int p);
|
||||
ISrsListener *set_label(const std::string &label);
|
||||
ISrsListener *set_endpoint(const std::string &i, int p);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual int fd();
|
||||
virtual srs_netfd_t stfd();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
void set_socket_buffer();
|
||||
|
||||
public:
|
||||
|
|
@ -115,19 +139,26 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_cycle();
|
||||
};
|
||||
|
||||
// Bind and listen tcp port, use handler to process the client.
|
||||
class SrsTcpListener : public ISrsCoroutineHandler, public ISrsListener
|
||||
class SrsTcpListener : public ISrsCoroutineHandler, public ISrsIpListener
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string label_;
|
||||
srs_netfd_t lfd_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsTcpHandler *handler_;
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
@ -137,9 +168,9 @@ public:
|
|||
virtual ~SrsTcpListener();
|
||||
|
||||
public:
|
||||
SrsTcpListener *set_label(const std::string &label);
|
||||
SrsTcpListener *set_endpoint(const std::string &i, int p);
|
||||
SrsTcpListener *set_endpoint(const std::string &endpoint);
|
||||
ISrsListener *set_label(const std::string &label);
|
||||
ISrsListener *set_endpoint(const std::string &i, int p);
|
||||
ISrsListener *set_endpoint(const std::string &endpoint);
|
||||
int port();
|
||||
|
||||
public:
|
||||
|
|
@ -149,24 +180,31 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_cycle();
|
||||
};
|
||||
|
||||
// Bind and listen tcp port, use handler to process the client.
|
||||
class SrsMultipleTcpListeners : public ISrsListener, public ISrsTcpHandler
|
||||
class SrsMultipleTcpListeners : public ISrsIpListener, public ISrsTcpHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsTcpHandler *handler_;
|
||||
std::vector<SrsTcpListener *> listeners_;
|
||||
std::vector<ISrsIpListener *> listeners_;
|
||||
|
||||
public:
|
||||
SrsMultipleTcpListeners(ISrsTcpHandler *h);
|
||||
virtual ~SrsMultipleTcpListeners();
|
||||
|
||||
public:
|
||||
SrsMultipleTcpListeners *set_label(const std::string &label);
|
||||
SrsMultipleTcpListeners *add(const std::vector<std::string> &endpoints);
|
||||
ISrsListener *set_label(const std::string &label);
|
||||
ISrsListener *set_endpoint(const std::string &i, int p);
|
||||
ISrsIpListener *add(const std::vector<std::string> &endpoints);
|
||||
|
||||
public:
|
||||
srs_error_t listen();
|
||||
|
|
@ -176,16 +214,37 @@ public:
|
|||
virtual srs_error_t on_tcp_client(ISrsListener *listener, srs_netfd_t stfd);
|
||||
};
|
||||
|
||||
// TODO: FIXME: Rename it. Refine it for performance issue.
|
||||
class SrsUdpMuxSocket
|
||||
// The UDP socket interface.
|
||||
class ISrsUdpMuxSocket
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsUdpMuxSocket();
|
||||
virtual ~ISrsUdpMuxSocket();
|
||||
|
||||
public:
|
||||
virtual srs_error_t sendto(void *data, int size, srs_utime_t timeout) = 0;
|
||||
virtual std::string get_peer_ip() const = 0;
|
||||
virtual int get_peer_port() const = 0;
|
||||
virtual std::string peer_id() = 0;
|
||||
virtual uint64_t fast_id() = 0;
|
||||
virtual ISrsUdpMuxSocket *copy_sendonly() = 0;
|
||||
virtual int recvfrom(srs_utime_t timeout) = 0;
|
||||
virtual char *data() = 0;
|
||||
virtual int size() = 0;
|
||||
};
|
||||
|
||||
// TODO: FIXME: Rename it. Refine it for performance issue.
|
||||
class SrsUdpMuxSocket : public ISrsUdpMuxSocket
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For sender yield only.
|
||||
uint32_t nn_msgs_for_yield_;
|
||||
std::map<uint32_t, std::string> cache_;
|
||||
SrsBuffer *cache_buffer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
char *buf_;
|
||||
int nb_buf_;
|
||||
int nread_;
|
||||
|
|
@ -193,11 +252,13 @@ private:
|
|||
sockaddr_storage from_;
|
||||
int fromlen_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string peer_ip_;
|
||||
int peer_port_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Cache for peer id.
|
||||
std::string peer_id_;
|
||||
// If the address changed, we should generate the peer_id.
|
||||
|
|
@ -222,21 +283,28 @@ public:
|
|||
std::string peer_id();
|
||||
uint64_t fast_id();
|
||||
SrsBuffer *buffer();
|
||||
SrsUdpMuxSocket *copy_sendonly();
|
||||
ISrsUdpMuxSocket *copy_sendonly();
|
||||
};
|
||||
|
||||
class SrsUdpMuxListener : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_netfd_t lfd_;
|
||||
ISrsCoroutine *trd_;
|
||||
SrsContextId cid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
char *buf_;
|
||||
int nb_buf_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsUdpMuxHandler *handler_;
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
@ -255,7 +323,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
void set_socket_buffer();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,13 @@
|
|||
// when you want to use different level, override this classs, set the protected _level.
|
||||
class SrsFileLog : public ISrsLog, public ISrsReloadHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Defined in SrsLogLevel.
|
||||
SrsLogLevel level_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
char *log_data_;
|
||||
// Log to file if specified srs_log_file
|
||||
int fd_;
|
||||
|
|
@ -42,7 +44,8 @@ public:
|
|||
virtual void reopen();
|
||||
virtual void log(SrsLogLevel level, const char *tag, const SrsContextId &context_id, const char *fmt, va_list args);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void write_log(int &fd, char *str_log, int size, int level);
|
||||
virtual void open_log_file();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
|
@ -35,24 +36,29 @@ SrsUdpCasterListener::SrsUdpCasterListener()
|
|||
{
|
||||
caster_ = new SrsMpegtsOverUdp();
|
||||
listener_ = new SrsUdpListener(caster_);
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsUdpCasterListener::~SrsUdpCasterListener()
|
||||
{
|
||||
srs_freep(listener_);
|
||||
srs_freep(caster_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsUdpCasterListener::initialize(SrsConfDirective *conf)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
int port = _srs_config->get_stream_caster_listen(conf);
|
||||
int port = config_->get_stream_caster_listen(conf);
|
||||
if (port <= 0) {
|
||||
return srs_error_new(ERROR_STREAM_CASTER_PORT, "invalid port=%d", port);
|
||||
}
|
||||
|
||||
listener_->set_endpoint(srs_net_address_any(), port)->set_label("MPEGTS");
|
||||
listener_->set_endpoint(srs_net_address_any(), port);
|
||||
listener_->set_label("MPEGTS");
|
||||
|
||||
if ((err = caster_->initialize(conf)) != srs_success) {
|
||||
return srs_error_wrap(err, "init caster port=%d", port);
|
||||
|
|
@ -77,6 +83,14 @@ void SrsUdpCasterListener::close()
|
|||
listener_->close();
|
||||
}
|
||||
|
||||
ISrsMpegtsQueue::ISrsMpegtsQueue()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMpegtsQueue::~ISrsMpegtsQueue()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpegtsQueue::SrsMpegtsQueue()
|
||||
{
|
||||
nb_audios_ = nb_videos_ = 0;
|
||||
|
|
@ -151,6 +165,14 @@ SrsMediaPacket *SrsMpegtsQueue::dequeue()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ISrsMpegtsOverUdp::ISrsMpegtsOverUdp()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMpegtsOverUdp::~ISrsMpegtsOverUdp()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpegtsOverUdp::SrsMpegtsOverUdp()
|
||||
{
|
||||
context_ = new SrsTsContext();
|
||||
|
|
@ -165,6 +187,9 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp()
|
|||
h264_sps_pps_sent_ = false;
|
||||
queue_ = new SrsMpegtsQueue();
|
||||
pprint_ = SrsPithyPrint::create_caster();
|
||||
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
|
||||
|
|
@ -177,11 +202,14 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
|
|||
srs_freep(aac_);
|
||||
srs_freep(queue_);
|
||||
srs_freep(pprint_);
|
||||
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsMpegtsOverUdp::initialize(SrsConfDirective *c)
|
||||
{
|
||||
output_ = _srs_config->get_stream_caster_output(c);
|
||||
output_ = config_->get_stream_caster_output(c);
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
|
|
@ -653,7 +681,7 @@ srs_error_t SrsMpegtsOverUdp::connect()
|
|||
|
||||
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
|
||||
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
|
||||
sdk_ = new SrsSimpleRtmpClient(output_, cto, sto);
|
||||
sdk_ = app_factory_->create_rtmp_client(output_, cto, sto);
|
||||
|
||||
if ((err = sdk_->connect()) != srs_success) {
|
||||
close();
|
||||
|
|
|
|||
|
|
@ -15,18 +15,27 @@ struct sockaddr;
|
|||
|
||||
class SrsBuffer;
|
||||
class SrsTsContext;
|
||||
class ISrsTsContext;
|
||||
class SrsConfDirective;
|
||||
class SrsSimpleStream;
|
||||
class SrsRtmpClient;
|
||||
class SrsStSocket;
|
||||
class ISrsRequest;
|
||||
class SrsRawH264Stream;
|
||||
class ISrsRawH264Stream;
|
||||
class SrsMediaPacket;
|
||||
class SrsRawAacStream;
|
||||
class ISrsRawAacStream;
|
||||
struct SrsRawAacStreamCodec;
|
||||
class SrsPithyPrint;
|
||||
class ISrsPithyPrint;
|
||||
class SrsSimpleRtmpClient;
|
||||
class ISrsBasicRtmpClient;
|
||||
class SrsMpegtsOverUdp;
|
||||
class ISrsIpListener;
|
||||
class ISrsMpegtsOverUdp;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
|
||||
#include <srs_app_listener.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
|
|
@ -35,9 +44,14 @@ class SrsMpegtsOverUdp;
|
|||
// A UDP listener, for udp stream caster server.
|
||||
class SrsUdpCasterListener : public ISrsListener
|
||||
{
|
||||
private:
|
||||
SrsUdpListener *listener_;
|
||||
SrsMpegtsOverUdp *caster_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsIpListener *listener_;
|
||||
ISrsMpegtsOverUdp *caster_;
|
||||
|
||||
public:
|
||||
SrsUdpCasterListener();
|
||||
|
|
@ -49,14 +63,28 @@ public:
|
|||
void close();
|
||||
};
|
||||
|
||||
// The interface for mpegts queue.
|
||||
class ISrsMpegtsQueue
|
||||
{
|
||||
public:
|
||||
ISrsMpegtsQueue();
|
||||
virtual ~ISrsMpegtsQueue();
|
||||
|
||||
public:
|
||||
virtual srs_error_t push(SrsMediaPacket *msg) = 0;
|
||||
virtual SrsMediaPacket *dequeue() = 0;
|
||||
};
|
||||
|
||||
// The queue for mpegts over udp to send packets.
|
||||
// For the aac in mpegts contains many flv packets in a pes packet,
|
||||
// we must recalc the timestamp.
|
||||
class SrsMpegtsQueue
|
||||
class SrsMpegtsQueue : public ISrsMpegtsQueue
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The key: dts, value: msg.
|
||||
std::map<int64_t, SrsMediaPacket *> msgs_;
|
||||
std::map<int64_t, SrsMediaPacket *>
|
||||
msgs_;
|
||||
int nb_audios_;
|
||||
int nb_videos_;
|
||||
|
||||
|
|
@ -69,32 +97,53 @@ public:
|
|||
virtual SrsMediaPacket *dequeue();
|
||||
};
|
||||
|
||||
// The mpegts over udp stream caster.
|
||||
class SrsMpegtsOverUdp : public ISrsTsHandler, public ISrsUdpHandler
|
||||
// The interface for mpegts over udp.
|
||||
class ISrsMpegtsOverUdp : public ISrsTsHandler, public ISrsUdpHandler
|
||||
{
|
||||
private:
|
||||
SrsTsContext *context_;
|
||||
public:
|
||||
ISrsMpegtsOverUdp();
|
||||
virtual ~ISrsMpegtsOverUdp();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsConfDirective *c) = 0;
|
||||
};
|
||||
|
||||
// The mpegts over udp stream caster.
|
||||
class SrsMpegtsOverUdp : public ISrsMpegtsOverUdp
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsTsContext *context_;
|
||||
SrsSimpleStream *buffer_;
|
||||
std::string output_;
|
||||
|
||||
private:
|
||||
SrsSimpleRtmpClient *sdk_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsBasicRtmpClient *sdk_;
|
||||
|
||||
private:
|
||||
SrsRawH264Stream *avc_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRawH264Stream *avc_;
|
||||
std::string h264_sps_;
|
||||
bool h264_sps_changed_;
|
||||
std::string h264_pps_;
|
||||
bool h264_pps_changed_;
|
||||
bool h264_sps_pps_sent_;
|
||||
|
||||
private:
|
||||
SrsRawAacStream *aac_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRawAacStream *aac_;
|
||||
std::string aac_specific_config_;
|
||||
|
||||
private:
|
||||
SrsMpegtsQueue *queue_;
|
||||
SrsPithyPrint *pprint_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsMpegtsQueue *queue_;
|
||||
ISrsPithyPrint *pprint_;
|
||||
|
||||
public:
|
||||
SrsMpegtsOverUdp();
|
||||
|
|
@ -106,25 +155,30 @@ public:
|
|||
public:
|
||||
virtual srs_error_t on_udp_packet(const sockaddr *from, const int fromlen, char *buf, int nb_buf);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_udp_bytes(std::string host, int port, char *buf, int nb_buf);
|
||||
// Interface ISrsTsHandler
|
||||
public:
|
||||
virtual srs_error_t on_ts_message(SrsTsMessage *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_ts_video(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
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 on_ts_audio(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
virtual srs_error_t write_audio_raw_frame(char *frame, int frame_size, SrsRawAacStreamCodec *codec, uint32_t dts);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t rtmp_write_packet(char type, uint32_t timestamp, char *data, int size);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Connect to RTMP server.
|
||||
virtual srs_error_t connect();
|
||||
virtual srs_error_t
|
||||
connect();
|
||||
// Close the connection to RTMP server.
|
||||
virtual void close();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ SrsNgExec::SrsNgExec()
|
|||
{
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
pprint_ = SrsPithyPrint::create_exec();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsNgExec::~SrsNgExec()
|
||||
|
|
@ -40,6 +42,8 @@ SrsNgExec::~SrsNgExec()
|
|||
|
||||
srs_freep(trd_);
|
||||
srs_freep(pprint_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsNgExec::on_publish(ISrsRequest *req)
|
||||
|
|
@ -132,7 +136,7 @@ srs_error_t SrsNgExec::parse_exec_publish(ISrsRequest *req)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_exec_enabled(req->vhost_)) {
|
||||
if (!config_->get_exec_enabled(req->vhost_)) {
|
||||
srs_trace("ignore disabled exec for vhost=%s", req->vhost_.c_str());
|
||||
return err;
|
||||
}
|
||||
|
|
@ -144,7 +148,7 @@ srs_error_t SrsNgExec::parse_exec_publish(ISrsRequest *req)
|
|||
input_stream_name_ += "/";
|
||||
input_stream_name_ += req->stream_;
|
||||
|
||||
std::vector<SrsConfDirective *> eps = _srs_config->get_exec_publishs(req->vhost_);
|
||||
std::vector<SrsConfDirective *> eps = config_->get_exec_publishs(req->vhost_);
|
||||
for (int i = 0; i < (int)eps.size(); i++) {
|
||||
SrsConfDirective *ep = eps.at(i);
|
||||
SrsProcess *process = new SrsProcess();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
class ISrsRequest;
|
||||
class SrsPithyPrint;
|
||||
class SrsProcess;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The ng-exec interface.
|
||||
class ISrsNgExec
|
||||
|
|
@ -36,7 +37,12 @@ public:
|
|||
// @see https://github.com/ossrs/srs/issues/367
|
||||
class SrsNgExec : public ISrsCoroutineHandler, public ISrsNgExec
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
SrsPithyPrint *pprint_;
|
||||
std::string input_stream_name_;
|
||||
|
|
@ -53,10 +59,12 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t parse_exec_publish(ISrsRequest *req);
|
||||
virtual void clear_exec_publish();
|
||||
virtual void show_exec_log_message();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@ using namespace std;
|
|||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
ISrsProcess::ISrsProcess()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsProcess::~ISrsProcess()
|
||||
{
|
||||
}
|
||||
|
||||
SrsProcess::SrsProcess()
|
||||
{
|
||||
is_started_ = false;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,36 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// The process interface.
|
||||
class ISrsProcess
|
||||
{
|
||||
public:
|
||||
ISrsProcess();
|
||||
virtual ~ISrsProcess();
|
||||
|
||||
public:
|
||||
// Get pid of process.
|
||||
virtual int get_pid() = 0;
|
||||
// whether process is already started.
|
||||
virtual bool started() = 0;
|
||||
// Initialize the process with binary and argv.
|
||||
virtual srs_error_t initialize(std::string binary, std::vector<std::string> argv) = 0;
|
||||
|
||||
public:
|
||||
// Start the process, ignore when already started.
|
||||
virtual srs_error_t start() = 0;
|
||||
// cycle check the process, update the state of process.
|
||||
virtual srs_error_t cycle() = 0;
|
||||
// Send SIGTERM then SIGKILL to ensure the process stopped.
|
||||
virtual void stop() = 0;
|
||||
|
||||
public:
|
||||
// The fast stop is to send a SIGTERM.
|
||||
virtual void fast_stop() = 0;
|
||||
// Directly kill process, never use it except server quiting.
|
||||
virtual void fast_kill() = 0;
|
||||
};
|
||||
|
||||
// Start and stop a process. Call cycle to restart the process when terminated.
|
||||
// The usage:
|
||||
// // the binary is the process to fork.
|
||||
|
|
@ -25,15 +55,17 @@
|
|||
// if ((ret = process->cycle()) != ERROR_SUCCESS) { return ret; }
|
||||
// process->fast_stop();
|
||||
// process->stop();
|
||||
class SrsProcess
|
||||
class SrsProcess : public ISrsProcess
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool is_started_;
|
||||
// Whether SIGTERM send but need to wait or SIGKILL.
|
||||
bool fast_stopped_;
|
||||
pid_t pid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string bin_;
|
||||
std::string stdout_file_;
|
||||
std::string stderr_file_;
|
||||
|
|
@ -57,9 +89,11 @@ public:
|
|||
// @remark the argv[0] must be the binary.
|
||||
virtual srs_error_t initialize(std::string binary, std::vector<std::string> argv);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Redirect standard I/O.
|
||||
virtual srs_error_t redirect_io();
|
||||
virtual srs_error_t
|
||||
redirect_io();
|
||||
|
||||
public:
|
||||
// Start the process, ignore when already started.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,14 @@ ISrsMessagePumper::~ISrsMessagePumper()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsRecvThread::ISrsRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRecvThread::~ISrsRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRecvThread::SrsRecvThread(ISrsMessagePumper *p, ISrsRtmpServer *r, srs_utime_t tm, SrsContextId parent_cid)
|
||||
{
|
||||
rtmp_ = r;
|
||||
|
|
@ -144,12 +152,20 @@ srs_error_t SrsRecvThread::do_cycle()
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsQueueRecvThread::SrsQueueRecvThread(SrsLiveConsumer *consumer, ISrsRtmpServer *rtmp_sdk, srs_utime_t tm, SrsContextId parent_cid)
|
||||
: trd_(this, rtmp_sdk, tm, parent_cid)
|
||||
ISrsQueueRecvThread::ISrsQueueRecvThread()
|
||||
{
|
||||
_consumer = consumer;
|
||||
}
|
||||
|
||||
ISrsQueueRecvThread::~ISrsQueueRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
SrsQueueRecvThread::SrsQueueRecvThread(SrsLiveConsumer *consumer, ISrsRtmpServer *rtmp_sdk, srs_utime_t tm, SrsContextId parent_cid)
|
||||
{
|
||||
consumer_ = consumer;
|
||||
rtmp_ = rtmp_sdk;
|
||||
recv_error_ = srs_success;
|
||||
trd_ = new SrsRecvThread(this, rtmp_sdk, tm, parent_cid);
|
||||
}
|
||||
|
||||
SrsQueueRecvThread::~SrsQueueRecvThread()
|
||||
|
|
@ -165,13 +181,14 @@ SrsQueueRecvThread::~SrsQueueRecvThread()
|
|||
queue_.clear();
|
||||
|
||||
srs_freep(recv_error_);
|
||||
srs_freep(trd_);
|
||||
}
|
||||
|
||||
srs_error_t SrsQueueRecvThread::start()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = trd_.start()) != srs_success) {
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "queue recv thread");
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +197,7 @@ srs_error_t SrsQueueRecvThread::start()
|
|||
|
||||
void SrsQueueRecvThread::stop()
|
||||
{
|
||||
trd_.stop();
|
||||
trd_->stop();
|
||||
}
|
||||
|
||||
bool SrsQueueRecvThread::empty()
|
||||
|
|
@ -215,8 +232,8 @@ srs_error_t SrsQueueRecvThread::consume(SrsRtmpCommonMessage *msg)
|
|||
// @see SrsRtmpConn::process_play_control_msg
|
||||
queue_.push_back(msg);
|
||||
#ifdef SRS_PERF_QUEUE_COND_WAIT
|
||||
if (_consumer) {
|
||||
_consumer->wakeup();
|
||||
if (consumer_) {
|
||||
consumer_->wakeup();
|
||||
}
|
||||
#endif
|
||||
return srs_success;
|
||||
|
|
@ -237,8 +254,8 @@ void SrsQueueRecvThread::interrupt(srs_error_t err)
|
|||
recv_error_ = srs_error_copy(err);
|
||||
|
||||
#ifdef SRS_PERF_QUEUE_COND_WAIT
|
||||
if (_consumer) {
|
||||
_consumer->wakeup();
|
||||
if (consumer_) {
|
||||
consumer_->wakeup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -257,40 +274,52 @@ void SrsQueueRecvThread::on_stop()
|
|||
rtmp_->set_auto_response(true);
|
||||
}
|
||||
|
||||
ISrsPublishRecvThread::ISrsPublishRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsPublishRecvThread::~ISrsPublishRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
SrsPublishRecvThread::SrsPublishRecvThread(ISrsRtmpServer *rtmp_sdk, ISrsRequest *_req,
|
||||
int mr_sock_fd, srs_utime_t tm, SrsRtmpConn *conn, SrsSharedPtr<SrsLiveSource> source, SrsContextId parent_cid)
|
||||
: trd_(this, rtmp_sdk, tm, parent_cid)
|
||||
{
|
||||
rtmp_ = rtmp_sdk;
|
||||
|
||||
_conn = conn;
|
||||
conn_ = conn;
|
||||
source_ = source;
|
||||
|
||||
nn_msgs_for_yield_ = 0;
|
||||
recv_error_ = srs_success;
|
||||
_nb_msgs = 0;
|
||||
nb_msgs_ = 0;
|
||||
video_frames_ = 0;
|
||||
error_ = srs_cond_new();
|
||||
|
||||
req_ = _req;
|
||||
mr_fd_ = mr_sock_fd;
|
||||
|
||||
// the mr settings,
|
||||
mr_ = _srs_config->get_mr_enabled(req_->vhost_);
|
||||
mr_sleep_ = _srs_config->get_mr_sleep(req_->vhost_);
|
||||
trd_ = new SrsRecvThread(this, rtmp_sdk, tm, parent_cid);
|
||||
|
||||
realtime_ = _srs_config->get_realtime_enabled(req_->vhost_, false);
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
void SrsPublishRecvThread::assemble()
|
||||
{
|
||||
mr_ = config_->get_mr_enabled(req_->vhost_);
|
||||
mr_sleep_ = config_->get_mr_sleep(req_->vhost_);
|
||||
realtime_ = config_->get_realtime_enabled(req_->vhost_, false);
|
||||
}
|
||||
|
||||
SrsPublishRecvThread::~SrsPublishRecvThread()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
trd_->stop();
|
||||
|
||||
trd_.stop();
|
||||
srs_cond_destroy(error_);
|
||||
srs_freep(recv_error_);
|
||||
srs_freep(trd_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsPublishRecvThread::wait(srs_utime_t tm)
|
||||
|
|
@ -307,7 +336,7 @@ srs_error_t SrsPublishRecvThread::wait(srs_utime_t tm)
|
|||
|
||||
int64_t SrsPublishRecvThread::nb_msgs()
|
||||
{
|
||||
return _nb_msgs;
|
||||
return nb_msgs_;
|
||||
}
|
||||
|
||||
uint64_t SrsPublishRecvThread::nb_video_frames()
|
||||
|
|
@ -334,18 +363,18 @@ srs_error_t SrsPublishRecvThread::start()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = trd_.start()) != srs_success) {
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
err = srs_error_wrap(err, "publish recv thread");
|
||||
}
|
||||
|
||||
ncid_ = cid_ = trd_.cid();
|
||||
ncid_ = cid_ = trd_->cid();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsPublishRecvThread::stop()
|
||||
{
|
||||
trd_.stop();
|
||||
trd_->stop();
|
||||
}
|
||||
|
||||
srs_error_t SrsPublishRecvThread::consume(SrsRtmpCommonMessage *msg)
|
||||
|
|
@ -358,7 +387,7 @@ srs_error_t SrsPublishRecvThread::consume(SrsRtmpCommonMessage *msg)
|
|||
cid_ = ncid_;
|
||||
}
|
||||
|
||||
_nb_msgs++;
|
||||
nb_msgs_++;
|
||||
|
||||
if (msg->header_.is_video()) {
|
||||
video_frames_++;
|
||||
|
|
@ -369,7 +398,7 @@ srs_error_t SrsPublishRecvThread::consume(SrsRtmpCommonMessage *msg)
|
|||
srs_time_now_realtime(), msg->header_.timestamp, msg->size);
|
||||
|
||||
// the rtmp connection will handle this message
|
||||
err = _conn->handle_publish_message(source_, msg);
|
||||
err = conn_->handle_publish_message(source_, msg);
|
||||
|
||||
// must always free it,
|
||||
// the source will copy it if need to use.
|
||||
|
|
@ -492,6 +521,14 @@ void SrsPublishRecvThread::set_socket_buffer(srs_utime_t sleep_v)
|
|||
rtmp_->set_recv_buffer(nb_rbuf);
|
||||
}
|
||||
|
||||
ISrsHttpRecvThread::ISrsHttpRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHttpRecvThread::~ISrsHttpRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHttpRecvThread::SrsHttpRecvThread(SrsHttpxConn *c)
|
||||
{
|
||||
conn_ = c;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ class SrsLiveConsumer;
|
|||
class SrsHttpConn;
|
||||
class SrsHttpxConn;
|
||||
class ISrsRtmpServer;
|
||||
class SrsRecvThread;
|
||||
class ISrsRecvThread;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The message consumer which consume a message.
|
||||
class ISrsMessageConsumer
|
||||
|
|
@ -61,10 +64,24 @@ public:
|
|||
virtual void on_stop() = 0;
|
||||
};
|
||||
|
||||
// The recv thread, use message handler to handle each received message.
|
||||
class SrsRecvThread : public ISrsCoroutineHandler
|
||||
// The recv thread interface.
|
||||
class ISrsRecvThread : public ISrsCoroutineHandler
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
ISrsRecvThread();
|
||||
virtual ~ISrsRecvThread();
|
||||
|
||||
public:
|
||||
virtual SrsContextId cid() = 0;
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
};
|
||||
|
||||
// The recv thread, use message handler to handle each received message.
|
||||
class SrsRecvThread : public ISrsRecvThread
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
ISrsMessagePumper *pumper_;
|
||||
ISrsRtmpServer *rtmp_;
|
||||
|
|
@ -89,23 +106,35 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
};
|
||||
|
||||
// The queue recv thread interface.
|
||||
class ISrsQueueRecvThread : public ISrsMessagePumper
|
||||
{
|
||||
public:
|
||||
ISrsQueueRecvThread();
|
||||
virtual ~ISrsQueueRecvThread();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The recv thread used to replace the timeout recv,
|
||||
// which hurt performance for the epoll_ctrl is frequently used.
|
||||
// @see: SrsRtmpConn::playing
|
||||
// @see: https://github.com/ossrs/srs/issues/217
|
||||
class SrsQueueRecvThread : public ISrsMessagePumper
|
||||
class SrsQueueRecvThread : public ISrsQueueRecvThread
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<SrsRtmpCommonMessage *> queue_;
|
||||
SrsRecvThread trd_;
|
||||
ISrsRecvThread *trd_;
|
||||
ISrsRtmpServer *rtmp_;
|
||||
// The recv thread error code.
|
||||
srs_error_t recv_error_;
|
||||
SrsLiveConsumer *_consumer;
|
||||
SrsLiveConsumer *consumer_;
|
||||
|
||||
public:
|
||||
// TODO: FIXME: Refine timeout in time unit.
|
||||
|
|
@ -130,21 +159,35 @@ public:
|
|||
virtual void on_stop();
|
||||
};
|
||||
|
||||
// The publish recv thread got message and callback the source method to process message.
|
||||
// @see: https://github.com/ossrs/srs/issues/237
|
||||
class SrsPublishRecvThread : public ISrsMessagePumper, public ISrsReloadHandler
|
||||
// The publish recv thread interface.
|
||||
class ISrsPublishRecvThread : public ISrsMessagePumper,
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
,
|
||||
public IMergeReadHandler
|
||||
public IMergeReadHandler
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsPublishRecvThread();
|
||||
virtual ~ISrsPublishRecvThread();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The publish recv thread got message and callback the source method to process message.
|
||||
// @see: https://github.com/ossrs/srs/issues/237
|
||||
class SrsPublishRecvThread : public ISrsPublishRecvThread
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint32_t nn_msgs_for_yield_;
|
||||
SrsRecvThread trd_;
|
||||
ISrsRecvThread *trd_;
|
||||
ISrsRtmpServer *rtmp_;
|
||||
ISrsRequest *req_;
|
||||
// The msgs already got.
|
||||
int64_t _nb_msgs;
|
||||
int64_t nb_msgs_;
|
||||
// The video frames we got.
|
||||
uint64_t video_frames_;
|
||||
// For mr(merged read),
|
||||
|
|
@ -156,7 +199,7 @@ private:
|
|||
bool realtime_;
|
||||
// The recv thread error code.
|
||||
srs_error_t recv_error_;
|
||||
SrsRtmpConn *_conn;
|
||||
SrsRtmpConn *conn_;
|
||||
// The params for conn callback.
|
||||
SrsSharedPtr<SrsLiveSource> source_;
|
||||
// The error timeout cond
|
||||
|
|
@ -168,6 +211,7 @@ private:
|
|||
public:
|
||||
SrsPublishRecvThread(ISrsRtmpServer *rtmp_sdk, ISrsRequest *_req,
|
||||
int mr_sock_fd, srs_utime_t tm, SrsRtmpConn *conn, SrsSharedPtr<SrsLiveSource> source, SrsContextId parent_cid);
|
||||
void assemble();
|
||||
virtual ~SrsPublishRecvThread();
|
||||
|
||||
public:
|
||||
|
|
@ -195,17 +239,29 @@ public:
|
|||
virtual void on_read(ssize_t nread);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual void set_socket_buffer(srs_utime_t sleep_v);
|
||||
};
|
||||
|
||||
// The HTTP receive thread interface.
|
||||
class ISrsHttpRecvThread : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
ISrsHttpRecvThread();
|
||||
virtual ~ISrsHttpRecvThread();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The HTTP receive thread, try to read messages util EOF.
|
||||
// For example, the HTTP FLV serving thread will use the receive thread to break
|
||||
// when client closed the request, to avoid FD leak.
|
||||
// @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427
|
||||
class SrsHttpRecvThread : public ISrsCoroutineHandler
|
||||
class SrsHttpRecvThread : public ISrsHttpRecvThread
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsHttpxConn *conn_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ public:
|
|||
// @param refer the refer in config.
|
||||
virtual srs_error_t check(std::string page_url, SrsConfDirective *refer);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t check_single_refer(std::string page_url, std::string refer);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,15 +29,27 @@ using namespace std;
|
|||
// To limit user to use too long password, to cause unknown issue.
|
||||
#define SRS_ICE_PWD_MAX 32
|
||||
|
||||
SrsGoApiRtcPlay::SrsGoApiRtcPlay(SrsServer *server)
|
||||
SrsGoApiRtcPlay::SrsGoApiRtcPlay(ISrsRtcApiServer *server)
|
||||
{
|
||||
server_ = server;
|
||||
security_ = new SrsSecurity();
|
||||
|
||||
config_ = _srs_config;
|
||||
stat_ = _srs_stat;
|
||||
rtc_sources_ = _srs_rtc_sources;
|
||||
live_sources_ = _srs_sources;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
SrsGoApiRtcPlay::~SrsGoApiRtcPlay()
|
||||
{
|
||||
srs_freep(security_);
|
||||
|
||||
config_ = NULL;
|
||||
stat_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
live_sources_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
// Request:
|
||||
|
|
@ -135,7 +147,7 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
ruc.req_->app_, ruc.req_->stream_, ruc.req_->port_, ruc.req_->param_);
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(ruc.req_->vhost_);
|
||||
SrsConfDirective *parsed_vhost = config_->get_vhost(ruc.req_->vhost_);
|
||||
if (parsed_vhost) {
|
||||
ruc.req_->vhost_ = parsed_vhost->arg0();
|
||||
}
|
||||
|
|
@ -162,7 +174,7 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
ruc.dtls_ = (dtls != "false");
|
||||
|
||||
if (srtp.empty()) {
|
||||
ruc.srtp_ = _srs_config->get_rtc_server_encrypt();
|
||||
ruc.srtp_ = config_->get_rtc_server_encrypt();
|
||||
} else {
|
||||
ruc.srtp_ = (srtp != "false");
|
||||
}
|
||||
|
|
@ -178,9 +190,9 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
}
|
||||
|
||||
res->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
res->set("server", SrsJsonAny::str(_srs_stat->server_id().c_str()));
|
||||
res->set("service", SrsJsonAny::str(_srs_stat->service_id().c_str()));
|
||||
res->set("pid", SrsJsonAny::str(_srs_stat->service_pid().c_str()));
|
||||
res->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
res->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
res->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
// TODO: add candidates in response json?
|
||||
res->set("sdp", SrsJsonAny::str(ruc.local_sdp_str_.c_str()));
|
||||
|
|
@ -200,13 +212,13 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
SrsSdp local_sdp;
|
||||
|
||||
// Config for SDP and session.
|
||||
local_sdp.session_config_.dtls_role_ = _srs_config->get_rtc_dtls_role(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_version_ = _srs_config->get_rtc_dtls_version(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_role_ = config_->get_rtc_dtls_role(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_version_ = config_->get_rtc_dtls_version(ruc->req_->vhost_);
|
||||
|
||||
// Whether enabled.
|
||||
bool server_enabled = _srs_config->get_rtc_server_enabled();
|
||||
bool rtc_enabled = _srs_config->get_rtc_enabled(ruc->req_->vhost_);
|
||||
bool edge = _srs_config->get_vhost_is_edge(ruc->req_->vhost_);
|
||||
bool server_enabled = config_->get_rtc_server_enabled();
|
||||
bool rtc_enabled = config_->get_rtc_enabled(ruc->req_->vhost_);
|
||||
bool edge = config_->get_vhost_is_edge(ruc->req_->vhost_);
|
||||
|
||||
if (rtc_enabled && edge) {
|
||||
rtc_enabled = false;
|
||||
|
|
@ -224,19 +236,19 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
// Whether RTC stream is active.
|
||||
bool is_rtc_stream_active = false;
|
||||
if (true) {
|
||||
SrsSharedPtr<SrsRtcSource> source = _srs_rtc_sources->fetch(ruc->req_);
|
||||
SrsSharedPtr<SrsRtcSource> source = rtc_sources_->fetch(ruc->req_);
|
||||
is_rtc_stream_active = (source.get() && !source->can_publish());
|
||||
}
|
||||
|
||||
// For RTMP to RTC, fail if disabled and RTMP is active, see https://github.com/ossrs/srs/issues/2728
|
||||
bool rtmp_to_rtc = _srs_config->get_rtc_from_rtmp(ruc->req_->vhost_);
|
||||
bool rtmp_to_rtc = config_->get_rtc_from_rtmp(ruc->req_->vhost_);
|
||||
if (rtmp_to_rtc && edge) {
|
||||
rtmp_to_rtc = false;
|
||||
srs_warn("disable RTMP to WebRTC for edge vhost=%s", ruc->req_->vhost_.c_str());
|
||||
}
|
||||
|
||||
if (!is_rtc_stream_active && !rtmp_to_rtc) {
|
||||
SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(ruc->req_);
|
||||
SrsSharedPtr<SrsLiveSource> live_source = live_sources_->fetch(ruc->req_);
|
||||
if (live_source.get() && !live_source->inactive()) {
|
||||
return srs_error_new(ERROR_RTC_DISABLED, "Disabled rtmp_to_rtc of %s, see #2728", ruc->req_->vhost_.c_str());
|
||||
}
|
||||
|
|
@ -251,7 +263,7 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
}
|
||||
|
||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
if ((err = server_->create_rtc_session(ruc, local_sdp, &session)) != srs_success) {
|
||||
return srs_error_wrap(err, "create session, dtls=%u, srtp=%u, eip=%s", ruc->dtls_, ruc->srtp_, ruc->eip_.c_str());
|
||||
}
|
||||
|
|
@ -310,7 +322,7 @@ srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(ISrsRequest *req)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +332,7 @@ srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(ISrsRequest *req)
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_play(req->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_play(req->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -331,7 +343,7 @@ srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(ISrsRequest *req)
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_play(url, req)) != srs_success) {
|
||||
if ((err = hooks_->on_play(url, req)) != srs_success) {
|
||||
return srs_error_wrap(err, "on_play %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -339,15 +351,23 @@ srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(ISrsRequest *req)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsGoApiRtcPublish::SrsGoApiRtcPublish(SrsServer *server)
|
||||
SrsGoApiRtcPublish::SrsGoApiRtcPublish(ISrsRtcApiServer *server)
|
||||
{
|
||||
server_ = server;
|
||||
security_ = new SrsSecurity();
|
||||
|
||||
config_ = _srs_config;
|
||||
stat_ = _srs_stat;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
SrsGoApiRtcPublish::~SrsGoApiRtcPublish()
|
||||
{
|
||||
srs_freep(security_);
|
||||
|
||||
config_ = NULL;
|
||||
stat_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
// Request:
|
||||
|
|
@ -446,7 +466,7 @@ srs_error_t SrsGoApiRtcPublish::do_serve_http(ISrsHttpResponseWriter *w, ISrsHtt
|
|||
ruc.req_->param_ = srs_strings_trim_start(ruc.req_->param_ + "&upstream=rtc", "&");
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(ruc.req_->vhost_);
|
||||
SrsConfDirective *parsed_vhost = config_->get_vhost(ruc.req_->vhost_);
|
||||
if (parsed_vhost) {
|
||||
ruc.req_->vhost_ = parsed_vhost->arg0();
|
||||
}
|
||||
|
|
@ -478,9 +498,9 @@ srs_error_t SrsGoApiRtcPublish::do_serve_http(ISrsHttpResponseWriter *w, ISrsHtt
|
|||
}
|
||||
|
||||
res->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
|
||||
res->set("server", SrsJsonAny::str(_srs_stat->server_id().c_str()));
|
||||
res->set("service", SrsJsonAny::str(_srs_stat->service_id().c_str()));
|
||||
res->set("pid", SrsJsonAny::str(_srs_stat->service_pid().c_str()));
|
||||
res->set("server", SrsJsonAny::str(stat_->server_id().c_str()));
|
||||
res->set("service", SrsJsonAny::str(stat_->service_id().c_str()));
|
||||
res->set("pid", SrsJsonAny::str(stat_->service_pid().c_str()));
|
||||
|
||||
// TODO: add candidates in response json?
|
||||
res->set("sdp", SrsJsonAny::str(ruc.local_sdp_str_.c_str()));
|
||||
|
|
@ -501,13 +521,13 @@ srs_error_t SrsGoApiRtcPublish::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
|
||||
// TODO: FIXME: move to create_session.
|
||||
// Config for SDP and session.
|
||||
local_sdp.session_config_.dtls_role_ = _srs_config->get_rtc_dtls_role(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_version_ = _srs_config->get_rtc_dtls_version(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_role_ = config_->get_rtc_dtls_role(ruc->req_->vhost_);
|
||||
local_sdp.session_config_.dtls_version_ = config_->get_rtc_dtls_version(ruc->req_->vhost_);
|
||||
|
||||
// Whether enabled.
|
||||
bool server_enabled = _srs_config->get_rtc_server_enabled();
|
||||
bool rtc_enabled = _srs_config->get_rtc_enabled(ruc->req_->vhost_);
|
||||
bool edge = _srs_config->get_vhost_is_edge(ruc->req_->vhost_);
|
||||
bool server_enabled = config_->get_rtc_server_enabled();
|
||||
bool rtc_enabled = config_->get_rtc_enabled(ruc->req_->vhost_);
|
||||
bool edge = config_->get_vhost_is_edge(ruc->req_->vhost_);
|
||||
|
||||
if (rtc_enabled && edge) {
|
||||
rtc_enabled = false;
|
||||
|
|
@ -524,7 +544,7 @@ srs_error_t SrsGoApiRtcPublish::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
|
||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
if ((err = server_->create_rtc_session(ruc, local_sdp, &session)) != srs_success) {
|
||||
return srs_error_wrap(err, "create session");
|
||||
}
|
||||
|
|
@ -592,7 +612,7 @@ srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(ISrsRequest *req)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -602,7 +622,7 @@ srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(ISrsRequest *req)
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_publish(req->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_publish(req->vhost_);
|
||||
if (!conf) {
|
||||
return err;
|
||||
}
|
||||
|
|
@ -611,7 +631,7 @@ srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(ISrsRequest *req)
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_publish(url, req)) != srs_success) {
|
||||
if ((err = hooks_->on_publish(url, req)) != srs_success) {
|
||||
return srs_error_wrap(err, "rtmp on_publish %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -619,17 +639,21 @@ srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(ISrsRequest *req)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsGoApiRtcWhip::SrsGoApiRtcWhip(SrsServer *server)
|
||||
SrsGoApiRtcWhip::SrsGoApiRtcWhip(ISrsRtcApiServer *server)
|
||||
{
|
||||
server_ = server;
|
||||
publish_ = new SrsGoApiRtcPublish(server);
|
||||
play_ = new SrsGoApiRtcPlay(server);
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsGoApiRtcWhip::~SrsGoApiRtcWhip()
|
||||
{
|
||||
srs_freep(publish_);
|
||||
srs_freep(play_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -648,7 +672,7 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
return srs_error_new(ERROR_RTC_INVALID_SESSION, "token empty");
|
||||
}
|
||||
|
||||
SrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
ISrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
if (session && token != session->token()) {
|
||||
return srs_error_new(ERROR_RTC_INVALID_SESSION, "token %s not match", token.c_str());
|
||||
}
|
||||
|
|
@ -740,7 +764,7 @@ srs_error_t SrsGoApiRtcWhip::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
}
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(ruc->req_->vhost_);
|
||||
SrsConfDirective *parsed_vhost = config_->get_vhost(ruc->req_->vhost_);
|
||||
if (parsed_vhost) {
|
||||
ruc->req_->vhost_ = parsed_vhost->arg0();
|
||||
}
|
||||
|
|
@ -761,7 +785,7 @@ srs_error_t SrsGoApiRtcWhip::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
// For client to specifies whether encrypt by SRTP.
|
||||
ruc->dtls_ = (dtls != "false");
|
||||
if (srtp.empty()) {
|
||||
ruc->srtp_ = _srs_config->get_rtc_server_encrypt();
|
||||
ruc->srtp_ = config_->get_rtc_server_encrypt();
|
||||
} else {
|
||||
ruc->srtp_ = (srtp != "false");
|
||||
}
|
||||
|
|
@ -780,7 +804,7 @@ srs_error_t SrsGoApiRtcWhip::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsGoApiRtcNACK::SrsGoApiRtcNACK(SrsServer *server)
|
||||
SrsGoApiRtcNACK::SrsGoApiRtcNACK(ISrsRtcApiServer *server)
|
||||
{
|
||||
server_ = server;
|
||||
}
|
||||
|
|
@ -823,7 +847,7 @@ srs_error_t SrsGoApiRtcNACK::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
return srs_error_new(ERROR_RTC_INVALID_PARAMS, "invalid drop=%s/%d", dropv.c_str(), drop);
|
||||
}
|
||||
|
||||
SrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
ISrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
if (!session) {
|
||||
return srs_error_new(ERROR_RTC_NO_SESSION, "no session username=%s", username.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,91 +15,128 @@ class SrsServer;
|
|||
class ISrsRequest;
|
||||
class SrsSdp;
|
||||
class SrsRtcUserConfig;
|
||||
class ISrsRtcApiServer;
|
||||
class ISrsSecurity;
|
||||
class ISrsAppConfig;
|
||||
class ISrsStatistic;
|
||||
class ISrsRtcSourceManager;
|
||||
class ISrsLiveSourceManager;
|
||||
class ISrsHttpHooks;
|
||||
|
||||
class SrsGoApiRtcPlay : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
SrsSecurity *security_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcApiServer *server_;
|
||||
ISrsSecurity *security_;
|
||||
|
||||
public:
|
||||
SrsGoApiRtcPlay(SrsServer *server);
|
||||
SrsGoApiRtcPlay(ISrsRtcApiServer *server);
|
||||
virtual ~SrsGoApiRtcPlay();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsJsonObject *res);
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsRtcUserConfig *ruc);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t check_remote_sdp(const SrsSdp &remote_sdp);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t http_hooks_on_play(ISrsRequest *req);
|
||||
};
|
||||
|
||||
class SrsGoApiRtcPublish : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
SrsSecurity *security_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcApiServer *server_;
|
||||
ISrsSecurity *security_;
|
||||
|
||||
public:
|
||||
SrsGoApiRtcPublish(SrsServer *server);
|
||||
SrsGoApiRtcPublish(ISrsRtcApiServer *server);
|
||||
virtual ~SrsGoApiRtcPublish();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsJsonObject *res);
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsRtcUserConfig *ruc);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t check_remote_sdp(const SrsSdp &remote_sdp);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t http_hooks_on_publish(ISrsRequest *req);
|
||||
};
|
||||
|
||||
// See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
|
||||
class SrsGoApiRtcWhip : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcApiServer *server_;
|
||||
SrsGoApiRtcPublish *publish_;
|
||||
SrsGoApiRtcPlay *play_;
|
||||
|
||||
public:
|
||||
SrsGoApiRtcWhip(SrsServer *server);
|
||||
SrsGoApiRtcWhip(ISrsRtcApiServer *server);
|
||||
virtual ~SrsGoApiRtcWhip();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsRtcUserConfig *ruc);
|
||||
};
|
||||
|
||||
class SrsGoApiRtcNACK : public ISrsHttpHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcApiServer *server_;
|
||||
|
||||
public:
|
||||
SrsGoApiRtcNACK(SrsServer *server);
|
||||
SrsGoApiRtcNACK(ISrsRtcApiServer *server);
|
||||
virtual ~SrsGoApiRtcNACK();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsJsonObject *res);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ public:
|
|||
// The audio transcoder, transcode audio from one codec to another.
|
||||
class SrsAudioTranscoder : public ISrsAudioTranscoder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
AVCodecContext *dec_;
|
||||
AVFrame *dec_frame_;
|
||||
AVPacket *dec_packet_;
|
||||
|
|
@ -95,7 +96,8 @@ public:
|
|||
// @remark User should never free the data, it's managed by this transcoder.
|
||||
void aac_codec_header(uint8_t **data, int *len);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t init_dec(SrsAudioCodecId from);
|
||||
srs_error_t init_enc(SrsAudioCodecId to, int channels, int samplerate, int bit_rate);
|
||||
srs_error_t init_swr(AVCodecContext *decoder);
|
||||
|
|
|
|||
|
|
@ -1816,6 +1816,14 @@ void SrsRtcPublishStream::update_send_report_time(uint32_t ssrc, const SrsNtp &n
|
|||
}
|
||||
}
|
||||
|
||||
ISrsRtcConnection::ISrsRtcConnection()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcConnection::~ISrsRtcConnection()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcConnectionNackTimerHandler::ISrsRtcConnectionNackTimerHandler()
|
||||
{
|
||||
}
|
||||
|
|
@ -2401,17 +2409,22 @@ bool SrsRtcConnection::is_alive()
|
|||
return last_stun_time_ + session_timeout_ > srs_time_now_cached();
|
||||
}
|
||||
|
||||
bool SrsRtcConnection::is_disposing()
|
||||
{
|
||||
return disposing_;
|
||||
}
|
||||
|
||||
void SrsRtcConnection::alive()
|
||||
{
|
||||
last_stun_time_ = srs_time_now_cached();
|
||||
}
|
||||
|
||||
SrsRtcUdpNetwork *SrsRtcConnection::udp()
|
||||
ISrsRtcNetwork *SrsRtcConnection::udp()
|
||||
{
|
||||
return networks_->udp();
|
||||
}
|
||||
|
||||
SrsRtcTcpNetwork *SrsRtcConnection::tcp()
|
||||
ISrsRtcNetwork *SrsRtcConnection::tcp()
|
||||
{
|
||||
return networks_->tcp();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ public:
|
|||
// The security transport, use DTLS/SRTP to protect the data.
|
||||
class SrsSecurityTransport : public ISrsRtcTransport
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcNetwork *network_;
|
||||
ISrsDtls *dtls_;
|
||||
ISrsSRTP *srtp_;
|
||||
|
|
@ -134,7 +135,8 @@ public:
|
|||
virtual srs_error_t on_dtls_application_data(const char *data, const int len);
|
||||
virtual srs_error_t write_dtls_data(void *data, int size);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t srtp_initialize();
|
||||
};
|
||||
|
||||
|
|
@ -155,7 +157,8 @@ public:
|
|||
// Plaintext transport, without DTLS or SRTP.
|
||||
class SrsPlaintextTransport : public ISrsRtcTransport
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcNetwork *network_;
|
||||
|
||||
public:
|
||||
|
|
@ -192,14 +195,17 @@ public:
|
|||
// A worker coroutine to request the PLI.
|
||||
class SrsRtcPliWorker : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
ISrsCond *wait_;
|
||||
ISrsRtcPliWorkerHandler *handler_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Key is SSRC, value is the CID of subscriber which requests PLI.
|
||||
std::map<uint32_t, SrsContextId> plis_;
|
||||
std::map<uint32_t, SrsContextId>
|
||||
plis_;
|
||||
|
||||
public:
|
||||
SrsRtcPliWorker(ISrsRtcPliWorkerHandler *h);
|
||||
|
|
@ -216,7 +222,8 @@ public:
|
|||
// the rtc on_stop async call.
|
||||
class SrsRtcAsyncCallOnStop : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
ISrsRequest *req_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
|
@ -235,22 +242,26 @@ public:
|
|||
// A RTC play stream, client pull and play stream from SRS.
|
||||
class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler, public ISrsRtcPliWorkerHandler, public ISrsRtcSourceChangeCallback
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsExecRtcAsyncTask *exec_;
|
||||
ISrsExpire *expire_;
|
||||
ISrsRtcPacketSender *sender_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
SrsFastCoroutine *trd_;
|
||||
SrsRtcPliWorker *pli_worker_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsSharedPtr<SrsRtcSource> source_;
|
||||
// key: publish_ssrc, value: send track to process rtp/rtcp
|
||||
|
|
@ -259,7 +270,8 @@ private:
|
|||
// The pithy print for special stage.
|
||||
SrsErrorPithyPrint *nack_epp_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Fast cache for tracks.
|
||||
uint32_t cache_ssrc0_;
|
||||
uint32_t cache_ssrc1_;
|
||||
|
|
@ -268,7 +280,8 @@ private:
|
|||
SrsRtcSendTrack *cache_track1_;
|
||||
SrsRtcSendTrack *cache_track2_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For merged-write messages.
|
||||
int mw_msgs_;
|
||||
bool realtime_;
|
||||
|
|
@ -276,7 +289,8 @@ private:
|
|||
bool nack_enabled_;
|
||||
bool nack_no_copy_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether player started.
|
||||
bool is_started_;
|
||||
|
||||
|
|
@ -300,7 +314,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t send_packet(SrsRtpPacket *&pkt);
|
||||
|
||||
public:
|
||||
|
|
@ -310,7 +325,8 @@ public:
|
|||
public:
|
||||
srs_error_t on_rtcp(SrsRtcpCommon *rtcp);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_rtcp_xr(SrsRtcpXr *rtcp);
|
||||
srs_error_t on_rtcp_nack(SrsRtcpNack *rtcp);
|
||||
srs_error_t on_rtcp_ps_feedback(SrsRtcpFbCommon *rtcp);
|
||||
|
|
@ -341,7 +357,8 @@ public:
|
|||
// A fast timer for publish stream, for RTCP feedback.
|
||||
class SrsRtcPublishRtcpTimer : public ISrsFastTimerHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcRtcpSender *sender_;
|
||||
srs_mutex_t lock_;
|
||||
|
||||
|
|
@ -349,17 +366,20 @@ public:
|
|||
SrsRtcPublishRtcpTimer(ISrsRtcRtcpSender *sender);
|
||||
virtual ~SrsRtcPublishRtcpTimer();
|
||||
// interface ISrsFastTimerHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
};
|
||||
|
||||
// A fast timer for publish stream, for TWCC feedback.
|
||||
class SrsRtcPublishTwccTimer : public ISrsFastTimerHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcRtcpSender *sender_;
|
||||
srs_mutex_t lock_;
|
||||
|
||||
|
|
@ -367,18 +387,21 @@ public:
|
|||
SrsRtcPublishTwccTimer(ISrsRtcRtcpSender *sender);
|
||||
virtual ~SrsRtcPublishTwccTimer();
|
||||
// interface ISrsFastTimerHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
};
|
||||
|
||||
// the rtc on_unpublish async call.
|
||||
class SrsRtcAsyncCallOnUnpublish : public ISrsAsyncCallTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsHttpHooks *hooks_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
ISrsRequest *req_;
|
||||
|
||||
|
|
@ -394,54 +417,64 @@ public:
|
|||
// A RTC publish stream, client push and publish stream to SRS.
|
||||
class SrsRtcPublishStream : public ISrsRtpPacketDecodeHandler, public ISrsRtcPublishStream, public ISrsRtcPliWorkerHandler, public ISrsRtcRtcpSender
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsExecRtcAsyncTask *exec_;
|
||||
ISrsExpire *expire_;
|
||||
ISrsRtcPacketReceiver *receiver_;
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsSrtSourceManager *srt_sources_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
friend class SrsRtcPublishRtcpTimer;
|
||||
friend class SrsRtcPublishTwccTimer;
|
||||
SrsRtcPublishRtcpTimer *timer_rtcp_;
|
||||
SrsRtcPublishTwccTimer *timer_twcc_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
uint64_t nn_audio_frames_;
|
||||
SrsRtcPliWorker *pli_worker_;
|
||||
SrsErrorPithyPrint *twcc_epp_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint16_t pt_to_drop_;
|
||||
// Whether enabled nack.
|
||||
bool nack_enabled_;
|
||||
bool nack_no_copy_;
|
||||
bool twcc_enabled_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool request_keyframe_;
|
||||
SrsErrorPithyPrint *pli_epp_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsSharedPtr<SrsRtcSource> source_;
|
||||
// Simulators.
|
||||
int nn_simulate_nack_drop_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// track vector
|
||||
std::vector<SrsRtcAudioRecvTrack *> audio_tracks_;
|
||||
std::vector<SrsRtcAudioRecvTrack *>
|
||||
audio_tracks_;
|
||||
std::vector<SrsRtcVideoRecvTrack *> video_tracks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int twcc_id_;
|
||||
uint8_t twcc_fb_count_;
|
||||
SrsRtcpTWCC rtcp_twcc_;
|
||||
|
|
@ -460,7 +493,8 @@ public:
|
|||
void set_all_tracks_status(bool status);
|
||||
virtual const SrsContextId &context_id();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool is_sender_started();
|
||||
bool is_sender_twcc_enabled();
|
||||
srs_error_t send_rtcp_rr();
|
||||
|
|
@ -470,7 +504,8 @@ public:
|
|||
srs_error_t on_rtp_cipher(char *buf, int nb_buf);
|
||||
srs_error_t on_rtp_plaintext(char *buf, int nb_buf);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_on_rtp_plaintext(SrsRtpPacket *&pkt, SrsBuffer *buf);
|
||||
|
||||
public:
|
||||
|
|
@ -479,13 +514,15 @@ public:
|
|||
public:
|
||||
virtual void on_before_decode_payload(SrsRtpPacket *pkt, SrsBuffer *buf, ISrsRtpPayloader **ppayload, SrsRtpPacketPayloadType *ppt);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t send_periodic_twcc();
|
||||
|
||||
public:
|
||||
srs_error_t on_rtcp(SrsRtcpCommon *rtcp);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_rtcp_sr(SrsRtcpSR *rtcp);
|
||||
srs_error_t on_rtcp_xr(SrsRtcpXr *rtcp);
|
||||
|
||||
|
|
@ -496,10 +533,12 @@ public:
|
|||
public:
|
||||
void simulate_nack_drop(int nn);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
void simulate_drop_packet(SrsRtpHeader *h, int nn_bytes);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_twcc(uint16_t sn);
|
||||
SrsRtcAudioRecvTrack *get_audio_track(uint32_t ssrc);
|
||||
SrsRtcVideoRecvTrack *get_video_track(uint32_t ssrc);
|
||||
|
|
@ -521,11 +560,13 @@ public:
|
|||
// A fast timer for conntion, for NACK feedback.
|
||||
class SrsRtcConnectionNackTimer : public ISrsFastTimerHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsSharedTimer *shared_timer_;
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcConnectionNackTimerHandler *handler_;
|
||||
srs_mutex_t lock_;
|
||||
|
||||
|
|
@ -537,7 +578,8 @@ public:
|
|||
virtual srs_error_t initialize();
|
||||
|
||||
// interface ISrsFastTimerHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
};
|
||||
|
||||
|
|
@ -552,21 +594,72 @@ public:
|
|||
virtual srs_error_t exec_rtc_async_work(ISrsAsyncCallTask *t) = 0;
|
||||
};
|
||||
|
||||
// The interface for RTC connection.
|
||||
class ISrsRtcConnection : public ISrsResource, // It's a resource.
|
||||
public ISrsDisposingHandler,
|
||||
public ISrsExpire,
|
||||
public ISrsRtcPacketSender,
|
||||
public ISrsRtcPacketReceiver,
|
||||
public ISrsRtcConnectionNackTimerHandler
|
||||
{
|
||||
public:
|
||||
ISrsRtcConnection();
|
||||
virtual ~ISrsRtcConnection();
|
||||
|
||||
public:
|
||||
// DTLS callbacks.
|
||||
virtual srs_error_t on_dtls_handshake_done() = 0;
|
||||
virtual srs_error_t on_dtls_alert(std::string type, std::string desc) = 0;
|
||||
// RTP/RTCP packet handling.
|
||||
virtual srs_error_t on_rtp_cipher(char *data, int nb_data) = 0;
|
||||
virtual srs_error_t on_rtp_plaintext(char *data, int nb_data) = 0;
|
||||
virtual srs_error_t on_rtcp(char *data, int nb_data) = 0;
|
||||
// STUN binding request.
|
||||
virtual srs_error_t on_binding_request(SrsStunPacket *r, std::string &ice_pwd) = 0;
|
||||
// Network access.
|
||||
virtual ISrsRtcNetwork *udp() = 0;
|
||||
virtual ISrsRtcNetwork *tcp() = 0;
|
||||
// Keep alive.
|
||||
virtual void alive() = 0;
|
||||
virtual bool is_alive() = 0;
|
||||
virtual bool is_disposing() = 0;
|
||||
// Context switching.
|
||||
virtual void switch_to_context() = 0;
|
||||
// Session management.
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp) = 0;
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp) = 0;
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status) = 0;
|
||||
// SDP management.
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp) = 0;
|
||||
virtual void set_local_sdp(const SrsSdp &sdp) = 0;
|
||||
virtual void set_state_as_waiting_stun() = 0;
|
||||
// Initialization.
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username) = 0;
|
||||
// Username and token access.
|
||||
virtual std::string username() = 0;
|
||||
virtual std::string token() = 0;
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token) = 0;
|
||||
// Simulation for testing.
|
||||
virtual void simulate_nack_drop(int nn) = 0;
|
||||
};
|
||||
|
||||
// A RTC Peer Connection, SDP level object.
|
||||
//
|
||||
// For performance, we use non-public from resource,
|
||||
// see https://stackoverflow.com/questions/3747066/c-cannot-convert-from-base-a-to-derived-type-b-via-virtual-base-a
|
||||
class SrsRtcConnection : public ISrsResource, public ISrsDisposingHandler, public ISrsExpire, public ISrsRtcPacketSender, public ISrsRtcPacketReceiver, public ISrsRtcConnectionNackTimerHandler
|
||||
class SrsRtcConnection : public ISrsRtcConnection
|
||||
{
|
||||
friend class SrsSecurityTransport;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
ISrsResourceManager *conn_manager_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcConnectionNackTimer *timer_nack_;
|
||||
ISrsExecRtcAsyncTask *exec_;
|
||||
SrsRtcPublisherNegotiator *publisher_negotiator_;
|
||||
|
|
@ -575,13 +668,16 @@ private:
|
|||
public:
|
||||
bool disposing_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
iovec *cache_iov_;
|
||||
SrsBuffer *cache_buffer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// key: stream id
|
||||
std::map<std::string, SrsRtcPlayStream *> players_;
|
||||
std::map<std::string, SrsRtcPlayStream *>
|
||||
players_;
|
||||
// key: player track's ssrc
|
||||
std::map<uint32_t, SrsRtcPlayStream *> players_ssrc_map_;
|
||||
// key: stream id
|
||||
|
|
@ -589,7 +685,8 @@ private:
|
|||
// key: publisher track's ssrc
|
||||
std::map<uint32_t, SrsRtcPublishStream *> publishers_ssrc_map_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The local:remote username, such as m5x0n128:jvOm where local name is m5x0n128.
|
||||
std::string username_;
|
||||
// The random token to verify the WHIP DELETE request etc.
|
||||
|
|
@ -597,14 +694,16 @@ private:
|
|||
// A group of networks, each has its own DTLS and SRTP context.
|
||||
SrsRtcNetworks *networks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// TODO: FIXME: Rename it.
|
||||
// The timeout of session, keep alive by STUN ping pong.
|
||||
srs_utime_t session_timeout_;
|
||||
// TODO: FIXME: Rename it.
|
||||
srs_utime_t last_stun_time_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For each RTC session, we use a specified cid for debugging logs.
|
||||
SrsContextId cid_;
|
||||
ISrsRequest *req_;
|
||||
|
|
@ -612,7 +711,8 @@ private:
|
|||
SrsSdp local_sdp_;
|
||||
SrsSharedPtr<SrsStreamPublishToken> publish_token_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// twcc handler
|
||||
int twcc_id_;
|
||||
// Simulators.
|
||||
|
|
@ -620,7 +720,8 @@ private:
|
|||
// Pithy print for PLI request.
|
||||
SrsErrorPithyPrint *pli_epp_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool nack_enabled_;
|
||||
|
||||
public:
|
||||
|
|
@ -672,14 +773,17 @@ public:
|
|||
srs_error_t on_rtp_cipher(char *data, int nb_data);
|
||||
srs_error_t on_rtp_plaintext(char *data, int nb_data);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Decode the RTP header from buf, find the publisher by SSRC.
|
||||
srs_error_t find_publisher(char *buf, int size, SrsRtcPublishStream **ppublisher);
|
||||
srs_error_t
|
||||
find_publisher(char *buf, int size, SrsRtcPublishStream **ppublisher);
|
||||
|
||||
public:
|
||||
srs_error_t on_rtcp(char *data, int nb_data);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t dispatch_rtcp(SrsRtcpCommon *rtcp);
|
||||
|
||||
public:
|
||||
|
|
@ -690,11 +794,12 @@ public:
|
|||
srs_error_t on_dtls_handshake_done();
|
||||
srs_error_t on_dtls_alert(std::string type, std::string desc);
|
||||
bool is_alive();
|
||||
bool is_disposing();
|
||||
void alive();
|
||||
|
||||
public:
|
||||
SrsRtcUdpNetwork *udp();
|
||||
SrsRtcTcpNetwork *tcp();
|
||||
ISrsRtcNetwork *udp();
|
||||
ISrsRtcNetwork *tcp();
|
||||
|
||||
public:
|
||||
// send rtcp
|
||||
|
|
@ -720,7 +825,8 @@ public:
|
|||
// Notify by specified network.
|
||||
srs_error_t on_binding_request(SrsStunPacket *r, std::string &ice_pwd);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t create_player(ISrsRequest *request, std::map<uint32_t, SrsRtcTrackDescription *> sub_relations);
|
||||
srs_error_t create_publisher(ISrsRequest *request, SrsRtcSourceDescription *stream_desc);
|
||||
};
|
||||
|
|
@ -728,7 +834,8 @@ private:
|
|||
// Negotiate via SDP exchange for WebRTC publisher.
|
||||
class SrsRtcPublisherNegotiator
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
|
|
@ -748,7 +855,8 @@ public:
|
|||
// Negotiate via SDP exchange for WebRTC player.
|
||||
class SrsRtcPlayerNegotiator
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
|
|
|
|||
|
|
@ -28,12 +28,14 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize() = 0;
|
||||
virtual std::string get_fingerprint() = 0;
|
||||
};
|
||||
|
||||
// The DTLS certificate.
|
||||
class SrsDtlsCertificate : public ISrsDtlsCertificate
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string fingerprint_;
|
||||
bool ecdsa_mode_;
|
||||
X509 *dtls_cert_;
|
||||
|
|
@ -103,7 +105,8 @@ enum SrsDtlsState {
|
|||
|
||||
class SrsDtlsImpl
|
||||
{
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
SSL_CTX *dtls_ctx_;
|
||||
SSL *dtls_;
|
||||
BIO *bio_in_;
|
||||
|
|
@ -112,7 +115,8 @@ protected:
|
|||
// @remark: dtls_version_ default value is SrsDtlsVersionAuto.
|
||||
SrsDtlsVersion version_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// Whether the handshake is done, for us only.
|
||||
// @remark For us only, means peer maybe not done, we also need to handle the DTLS packet.
|
||||
bool handshake_done_for_us_;
|
||||
|
|
@ -134,7 +138,8 @@ public:
|
|||
virtual srs_error_t start_active_handshake();
|
||||
virtual srs_error_t on_dtls(char *data, int nb_data);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
srs_error_t do_on_dtls(char *data, int nb_data);
|
||||
void state_trace(uint8_t *data, int length, bool incoming, int r0);
|
||||
|
||||
|
|
@ -142,7 +147,8 @@ public:
|
|||
srs_error_t get_srtp_key(std::string &recv_key, std::string &send_key);
|
||||
void callback_by_ssl(std::string type, std::string desc);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t on_handshake_done() = 0;
|
||||
virtual bool is_dtls_client() = 0;
|
||||
virtual srs_error_t start_arq() = 0;
|
||||
|
|
@ -150,7 +156,8 @@ protected:
|
|||
|
||||
class SrsDtlsClientImpl : public SrsDtlsImpl, public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// ARQ thread, for role active(DTLS client).
|
||||
// @note If passive(DTLS server), the ARQ is driven by DTLS client.
|
||||
ISrsCoroutine *trd_;
|
||||
|
|
@ -166,11 +173,13 @@ public:
|
|||
public:
|
||||
virtual srs_error_t initialize(std::string version, std::string role);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t on_handshake_done();
|
||||
virtual bool is_dtls_client();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
srs_error_t start_arq();
|
||||
void stop_arq();
|
||||
|
||||
|
|
@ -187,7 +196,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t initialize(std::string version, std::string role);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t on_handshake_done();
|
||||
virtual bool is_dtls_client();
|
||||
srs_error_t start_arq();
|
||||
|
|
@ -207,7 +217,8 @@ public:
|
|||
srs_error_t get_srtp_key(std::string &recv_key, std::string &send_key);
|
||||
void callback_by_ssl(std::string type, std::string desc);
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t on_handshake_done();
|
||||
virtual bool is_dtls_client();
|
||||
virtual srs_error_t start_arq();
|
||||
|
|
@ -230,7 +241,8 @@ public:
|
|||
// The DTLS transport.
|
||||
class SrsDtls : public ISrsDtls
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsDtlsImpl *impl_;
|
||||
ISrsDtlsCallback *callback_;
|
||||
|
||||
|
|
@ -270,7 +282,8 @@ public:
|
|||
// The SRTP transport.
|
||||
class SrsSRTP : public ISrsSRTP
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srtp_t recv_ctx_;
|
||||
srtp_t send_ctx_;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,15 @@ extern bool srs_is_dtls(const uint8_t *data, size_t len);
|
|||
extern bool srs_is_rtp_or_rtcp(const uint8_t *data, size_t len);
|
||||
extern bool srs_is_rtcp(const uint8_t *data, size_t len);
|
||||
|
||||
SrsRtcNetworks::SrsRtcNetworks(SrsRtcConnection *conn)
|
||||
ISrsRtcNetworks::ISrsRtcNetworks()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcNetworks::~ISrsRtcNetworks()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtcNetworks::SrsRtcNetworks(ISrsRtcConnection *conn)
|
||||
{
|
||||
conn_ = conn;
|
||||
delta_ = new SrsEphemeralDelta();
|
||||
|
|
@ -74,12 +82,12 @@ void SrsRtcNetworks::set_state(SrsRtcNetworkState state)
|
|||
tcp_->set_state(state);
|
||||
}
|
||||
|
||||
SrsRtcUdpNetwork *SrsRtcNetworks::udp()
|
||||
ISrsRtcNetwork *SrsRtcNetworks::udp()
|
||||
{
|
||||
return udp_;
|
||||
}
|
||||
|
||||
SrsRtcTcpNetwork *SrsRtcNetworks::tcp()
|
||||
ISrsRtcNetwork *SrsRtcNetworks::tcp()
|
||||
{
|
||||
return tcp_;
|
||||
}
|
||||
|
|
@ -117,6 +125,15 @@ SrsRtcDummyNetwork::~SrsRtcDummyNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::initialize(SrsSessionConfig *cfg, bool dtls, bool srtp)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void SrsRtcDummyNetwork::set_state(SrsRtcNetworkState state)
|
||||
{
|
||||
}
|
||||
|
||||
bool SrsRtcDummyNetwork::is_establelished()
|
||||
{
|
||||
return true;
|
||||
|
|
@ -132,6 +149,11 @@ srs_error_t SrsRtcDummyNetwork::on_dtls_alert(std::string type, std::string desc
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::on_dtls(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::protect_rtp(void *packet, int *nb_cipher)
|
||||
{
|
||||
return srs_success;
|
||||
|
|
@ -142,12 +164,27 @@ srs_error_t SrsRtcDummyNetwork::protect_rtcp(void *packet, int *nb_cipher)
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::on_stun(SrsStunPacket *r, char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::on_rtp(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::on_rtcp(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcDummyNetwork::write(void *buf, size_t size, ssize_t *nwrite)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
SrsRtcUdpNetwork::SrsRtcUdpNetwork(SrsRtcConnection *conn, SrsEphemeralDelta *delta)
|
||||
SrsRtcUdpNetwork::SrsRtcUdpNetwork(ISrsRtcConnection *conn, ISrsEphemeralDelta *delta)
|
||||
{
|
||||
state_ = SrsRtcNetworkStateInit;
|
||||
conn_ = conn;
|
||||
|
|
@ -155,6 +192,8 @@ SrsRtcUdpNetwork::SrsRtcUdpNetwork(SrsRtcConnection *conn, SrsEphemeralDelta *de
|
|||
sendonly_skt_ = NULL;
|
||||
pp_address_change_ = new SrsErrorPithyPrint();
|
||||
transport_ = new SrsSecurityTransport(this);
|
||||
|
||||
conn_manager_ = _srs_conn_manager;
|
||||
}
|
||||
|
||||
SrsRtcUdpNetwork::~SrsRtcUdpNetwork()
|
||||
|
|
@ -164,13 +203,15 @@ SrsRtcUdpNetwork::~SrsRtcUdpNetwork()
|
|||
|
||||
// Note that we should never delete the sendonly_skt,
|
||||
// it's just point to the object in peer_addresses_.
|
||||
map<string, SrsUdpMuxSocket *>::iterator it;
|
||||
map<string, ISrsUdpMuxSocket *>::iterator it;
|
||||
for (it = peer_addresses_.begin(); it != peer_addresses_.end(); ++it) {
|
||||
SrsUdpMuxSocket *addr = it->second;
|
||||
ISrsUdpMuxSocket *addr = it->second;
|
||||
srs_freep(addr);
|
||||
}
|
||||
|
||||
srs_freep(pp_address_change_);
|
||||
|
||||
conn_manager_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcUdpNetwork::initialize(SrsSessionConfig *cfg, bool dtls, bool srtp)
|
||||
|
|
@ -327,7 +368,7 @@ int SrsRtcUdpNetwork::get_peer_port()
|
|||
return sendonly_skt_->get_peer_port();
|
||||
}
|
||||
|
||||
void SrsRtcUdpNetwork::update_sendonly_socket(SrsUdpMuxSocket *skt)
|
||||
void SrsRtcUdpNetwork::update_sendonly_socket(ISrsUdpMuxSocket *skt)
|
||||
{
|
||||
// TODO: FIXME: Refine performance.
|
||||
string prev_peer_id, peer_id = skt->peer_id();
|
||||
|
|
@ -341,9 +382,9 @@ void SrsRtcUdpNetwork::update_sendonly_socket(SrsUdpMuxSocket *skt)
|
|||
}
|
||||
|
||||
// Find object from cache.
|
||||
SrsUdpMuxSocket *addr_cache = NULL;
|
||||
ISrsUdpMuxSocket *addr_cache = NULL;
|
||||
if (true) {
|
||||
map<string, SrsUdpMuxSocket *>::iterator it = peer_addresses_.find(peer_id);
|
||||
map<string, ISrsUdpMuxSocket *>::iterator it = peer_addresses_.find(peer_id);
|
||||
if (it != peer_addresses_.end()) {
|
||||
addr_cache = it->second;
|
||||
}
|
||||
|
|
@ -363,11 +404,11 @@ void SrsRtcUdpNetwork::update_sendonly_socket(SrsUdpMuxSocket *skt)
|
|||
// If no cache, build cache and setup the relations in connection.
|
||||
if (!addr_cache) {
|
||||
peer_addresses_[peer_id] = addr_cache = skt->copy_sendonly();
|
||||
_srs_conn_manager->add_with_id(peer_id, conn_);
|
||||
conn_manager_->add_with_id(peer_id, conn_);
|
||||
|
||||
uint64_t fast_id = skt->fast_id();
|
||||
if (fast_id) {
|
||||
_srs_conn_manager->add_with_fast_id(fast_id, conn_);
|
||||
conn_manager_->add_with_fast_id(fast_id, conn_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +492,7 @@ srs_error_t SrsRtcUdpNetwork::write(void *buf, size_t size, ssize_t *nwrite)
|
|||
return sendonly_skt_->sendto(buf, size, SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
SrsRtcTcpNetwork::SrsRtcTcpNetwork(SrsRtcConnection *conn, SrsEphemeralDelta *delta) : owner_(new SrsRtcTcpConn())
|
||||
SrsRtcTcpNetwork::SrsRtcTcpNetwork(ISrsRtcConnection *conn, ISrsEphemeralDelta *delta) : owner_(new SrsRtcTcpConn())
|
||||
{
|
||||
conn_ = conn;
|
||||
delta_ = delta;
|
||||
|
|
@ -718,6 +759,17 @@ void SrsRtcTcpConn::setup()
|
|||
pkt_ = NULL;
|
||||
delta_ = NULL;
|
||||
skt_ = NULL;
|
||||
|
||||
conn_manager_ = _srs_conn_manager;
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
ISrsRtcTcpConn::ISrsRtcTcpConn()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcTcpConn::~ISrsRtcTcpConn()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtcTcpConn::SrsRtcTcpConn()
|
||||
|
|
@ -743,9 +795,12 @@ SrsRtcTcpConn::~SrsRtcTcpConn()
|
|||
srs_freepa(pkt_);
|
||||
srs_freep(delta_);
|
||||
srs_freep(skt_);
|
||||
|
||||
conn_manager_ = NULL;
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
void SrsRtcTcpConn::setup_owner(SrsSharedResource<SrsRtcTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
void SrsRtcTcpConn::setup_owner(SrsSharedResource<ISrsRtcTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid)
|
||||
{
|
||||
wrapper_ = wrapper;
|
||||
owner_coroutine_ = owner_coroutine;
|
||||
|
|
@ -789,8 +844,8 @@ srs_error_t SrsRtcTcpConn::cycle()
|
|||
srs_error_t err = do_cycle();
|
||||
|
||||
// Only stat the HTTP streaming clients, ignore all API clients.
|
||||
_srs_stat->on_disconnect(get_id().c_str(), err);
|
||||
_srs_stat->kbps_add_delta(get_id().c_str(), delta_);
|
||||
stat_->on_disconnect(get_id().c_str(), err);
|
||||
stat_->kbps_add_delta(get_id().c_str(), delta_);
|
||||
|
||||
// Only remove session when network is established, because client might use other UDP network.
|
||||
if (session_ && session_->tcp()->is_establelished()) {
|
||||
|
|
@ -888,7 +943,7 @@ srs_error_t SrsRtcTcpConn::handshake()
|
|||
}
|
||||
|
||||
srs_assert(!session_);
|
||||
SrsRtcConnection *session = dynamic_cast<SrsRtcConnection *>(_srs_conn_manager->find_by_name(ping.get_username()));
|
||||
ISrsRtcConnection *session = dynamic_cast<ISrsRtcConnection *>(conn_manager_->find_by_name(ping.get_username()));
|
||||
// TODO: FIXME: For ICE trickle, we may get STUN packets before SDP answer, so maybe should response it.
|
||||
if (!session) {
|
||||
return srs_error_new(ERROR_RTC_TCP_STUN, "no session, stun username=%s", ping.get_username().c_str());
|
||||
|
|
@ -910,12 +965,12 @@ srs_error_t SrsRtcTcpConn::handshake()
|
|||
|
||||
// For each binding request, update the TCP socket.
|
||||
if (ping.is_binding_request()) {
|
||||
session_->tcp()->update_sendonly_socket(skt_);
|
||||
session_->tcp()->set_peer_id(ip_, port_);
|
||||
network->update_sendonly_socket(skt_);
|
||||
network->set_peer_id(ip_, port_);
|
||||
}
|
||||
|
||||
// Use the session network to handle packet.
|
||||
return session_->tcp()->on_stun(&ping, pkt_, npkt);
|
||||
return network->on_stun(&ping, pkt_, npkt);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcTcpConn::read_packet(char *pkt, int *nb_pkt)
|
||||
|
|
|
|||
|
|
@ -20,18 +20,24 @@
|
|||
class ISrsResourceManager;
|
||||
class ISrsCoroutine;
|
||||
class SrsNetworkDelta;
|
||||
class ISrsNetworkDelta;
|
||||
class SrsTcpConnection;
|
||||
class ISrsTcpConnection;
|
||||
class ISrsKbpsDelta;
|
||||
class SrsUdpMuxSocket;
|
||||
class ISrsUdpMuxSocket;
|
||||
class SrsErrorPithyPrint;
|
||||
class ISrsRtcTransport;
|
||||
class SrsEphemeralDelta;
|
||||
class ISrsEphemeralDelta;
|
||||
class ISrsKbpsDelta;
|
||||
class SrsRtcUdpNetwork;
|
||||
class ISrsRtcUdpNetwork;
|
||||
class ISrsRtcNetwork;
|
||||
class SrsRtcTcpNetwork;
|
||||
class SrsRtcDummyNetwork;
|
||||
class SrsRtcTcpConn;
|
||||
class ISrsRtcTcpConn;
|
||||
|
||||
// The network stat.
|
||||
enum SrsRtcNetworkState {
|
||||
|
|
@ -43,25 +49,37 @@ enum SrsRtcNetworkState {
|
|||
SrsRtcNetworkStateClosed = 5,
|
||||
};
|
||||
|
||||
// A group of networks, each has its own DTLS and SRTP context.
|
||||
class SrsRtcNetworks
|
||||
// The network manager interface.
|
||||
class ISrsRtcNetworks
|
||||
{
|
||||
private:
|
||||
// Network over UDP.
|
||||
SrsRtcUdpNetwork *udp_;
|
||||
// Network over TCP
|
||||
SrsRtcTcpNetwork *tcp_;
|
||||
// Network over dummy
|
||||
SrsRtcDummyNetwork *dummy_;
|
||||
|
||||
private:
|
||||
// WebRTC session object.
|
||||
SrsRtcConnection *conn_;
|
||||
// Delta object for statistics.
|
||||
SrsEphemeralDelta *delta_;
|
||||
public:
|
||||
ISrsRtcNetworks();
|
||||
virtual ~ISrsRtcNetworks();
|
||||
|
||||
public:
|
||||
SrsRtcNetworks(SrsRtcConnection *conn);
|
||||
};
|
||||
|
||||
// A group of networks, each has its own DTLS and SRTP context.
|
||||
class SrsRtcNetworks : public ISrsRtcNetworks
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Network over UDP.
|
||||
ISrsRtcNetwork *udp_;
|
||||
// Network over TCP
|
||||
ISrsRtcNetwork *tcp_;
|
||||
// Network over dummy
|
||||
ISrsRtcNetwork *dummy_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// WebRTC session object.
|
||||
ISrsRtcConnection *conn_;
|
||||
// Delta object for statistics.
|
||||
ISrsEphemeralDelta *delta_;
|
||||
|
||||
public:
|
||||
SrsRtcNetworks(ISrsRtcConnection *conn);
|
||||
virtual ~SrsRtcNetworks();
|
||||
// DTLS transport functions.
|
||||
public:
|
||||
|
|
@ -71,8 +89,8 @@ public:
|
|||
// Connection level state machine, for ARQ of UDP packets.
|
||||
void set_state(SrsRtcNetworkState state);
|
||||
// Get the UDP network object.
|
||||
SrsRtcUdpNetwork *udp();
|
||||
SrsRtcTcpNetwork *tcp();
|
||||
ISrsRtcNetwork *udp();
|
||||
ISrsRtcNetwork *tcp();
|
||||
// Get an available network.
|
||||
ISrsRtcNetwork *available();
|
||||
|
||||
|
|
@ -88,11 +106,19 @@ public:
|
|||
ISrsRtcNetwork();
|
||||
virtual ~ISrsRtcNetwork();
|
||||
|
||||
public:
|
||||
// Initialize the network with DTLS and SRTP configuration.
|
||||
virtual srs_error_t initialize(SrsSessionConfig *cfg, bool dtls, bool srtp) = 0;
|
||||
// Set the network state.
|
||||
virtual void set_state(SrsRtcNetworkState state) = 0;
|
||||
|
||||
public:
|
||||
// Callback when DTLS connected.
|
||||
virtual srs_error_t on_dtls_handshake_done() = 0;
|
||||
// Callback when DTLS disconnected.
|
||||
virtual srs_error_t on_dtls_alert(std::string type, std::string desc) = 0;
|
||||
// Handle DTLS data.
|
||||
virtual srs_error_t on_dtls(char *data, int nb_data) = 0;
|
||||
|
||||
public:
|
||||
// Protect RTP packet by SRTP context.
|
||||
|
|
@ -100,6 +126,14 @@ public:
|
|||
// Protect RTCP packet by SRTP context.
|
||||
virtual srs_error_t protect_rtcp(void *packet, int *nb_cipher) = 0;
|
||||
|
||||
public:
|
||||
// Handle STUN packet.
|
||||
virtual srs_error_t on_stun(SrsStunPacket *r, char *data, int nb_data) = 0;
|
||||
// Handle RTP packet.
|
||||
virtual srs_error_t on_rtp(char *data, int nb_data) = 0;
|
||||
// Handle RTCP packet.
|
||||
virtual srs_error_t on_rtcp(char *data, int nb_data) = 0;
|
||||
|
||||
public:
|
||||
virtual bool is_establelished() = 0;
|
||||
};
|
||||
|
|
@ -113,12 +147,22 @@ public:
|
|||
|
||||
// The interface of ISrsRtcNetwork
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsSessionConfig *cfg, bool dtls, bool srtp);
|
||||
virtual void set_state(SrsRtcNetworkState state);
|
||||
virtual srs_error_t on_dtls_handshake_done();
|
||||
virtual srs_error_t on_dtls_alert(std::string type, std::string desc);
|
||||
virtual srs_error_t on_dtls(char *data, int nb_data);
|
||||
|
||||
public:
|
||||
virtual srs_error_t protect_rtp(void *packet, int *nb_cipher);
|
||||
virtual srs_error_t protect_rtcp(void *packet, int *nb_cipher);
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_stun(SrsStunPacket *r, char *data, int nb_data);
|
||||
virtual srs_error_t on_rtp(char *data, int nb_data);
|
||||
virtual srs_error_t on_rtcp(char *data, int nb_data);
|
||||
|
||||
public:
|
||||
virtual bool is_establelished();
|
||||
// Interface ISrsStreamWriter.
|
||||
public:
|
||||
|
|
@ -128,34 +172,41 @@ public:
|
|||
// The WebRTC over UDP network.
|
||||
class SrsRtcUdpNetwork : public ISrsRtcNetwork
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *conn_manager_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// WebRTC session object.
|
||||
SrsRtcConnection *conn_;
|
||||
ISrsRtcConnection *conn_;
|
||||
// Delta object for statistics.
|
||||
SrsEphemeralDelta *delta_;
|
||||
ISrsEphemeralDelta *delta_;
|
||||
SrsRtcNetworkState state_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Pithy print for address change, use port as error code.
|
||||
SrsErrorPithyPrint *pp_address_change_;
|
||||
// The peer address, client maybe use more than one address, it's the current selected one.
|
||||
SrsUdpMuxSocket *sendonly_skt_;
|
||||
ISrsUdpMuxSocket *sendonly_skt_;
|
||||
// The address list, client may use multiple addresses.
|
||||
std::map<std::string, SrsUdpMuxSocket *> peer_addresses_;
|
||||
std::map<std::string, ISrsUdpMuxSocket *> peer_addresses_;
|
||||
// The DTLS transport over this network.
|
||||
ISrsRtcTransport *transport_;
|
||||
|
||||
public:
|
||||
SrsRtcUdpNetwork(SrsRtcConnection *conn, SrsEphemeralDelta *delta);
|
||||
SrsRtcUdpNetwork(ISrsRtcConnection *conn, ISrsEphemeralDelta *delta);
|
||||
virtual ~SrsRtcUdpNetwork();
|
||||
|
||||
public:
|
||||
// Update the UDP connection.
|
||||
void update_sendonly_socket(SrsUdpMuxSocket *skt);
|
||||
void update_sendonly_socket(ISrsUdpMuxSocket *skt);
|
||||
// When got STUN ping message. The peer address may change, we can identify that by STUN messages.
|
||||
srs_error_t on_stun(SrsStunPacket *r, char *data, int nb_data);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_binding_request(SrsStunPacket *r, std::string ice_pwd);
|
||||
// DTLS transport functions.
|
||||
public:
|
||||
|
|
@ -184,28 +235,31 @@ public:
|
|||
|
||||
class SrsRtcTcpNetwork : public ISrsRtcNetwork
|
||||
{
|
||||
private:
|
||||
SrsRtcConnection *conn_;
|
||||
SrsEphemeralDelta *delta_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtcConnection *conn_;
|
||||
ISrsEphemeralDelta *delta_;
|
||||
ISrsProtocolReadWriter *sendonly_skt_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The DTLS transport over this network.
|
||||
ISrsRtcTransport *transport_;
|
||||
SrsSharedResource<SrsRtcTcpConn> owner_;
|
||||
SrsSharedResource<ISrsRtcTcpConn> owner_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string peer_ip_;
|
||||
int peer_port_;
|
||||
SrsRtcNetworkState state_;
|
||||
|
||||
public:
|
||||
SrsRtcTcpNetwork(SrsRtcConnection *conn, SrsEphemeralDelta *delta);
|
||||
SrsRtcTcpNetwork(ISrsRtcConnection *conn, ISrsEphemeralDelta *delta);
|
||||
virtual ~SrsRtcTcpNetwork();
|
||||
|
||||
public:
|
||||
void set_owner(SrsSharedResource<SrsRtcTcpConn> v) { owner_ = v; }
|
||||
SrsSharedResource<SrsRtcTcpConn> owner() { return owner_; }
|
||||
void set_owner(SrsSharedResource<ISrsRtcTcpConn> v) { owner_ = v; }
|
||||
SrsSharedResource<ISrsRtcTcpConn> owner() { return owner_; }
|
||||
void update_sendonly_socket(ISrsProtocolReadWriter *skt);
|
||||
// ISrsRtcNetwork
|
||||
public:
|
||||
|
|
@ -221,7 +275,8 @@ public:
|
|||
// When got STUN ping message. The peer address may change, we can identify that by STUN messages.
|
||||
srs_error_t on_stun(SrsStunPacket *r, char *data, int nb_data);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_binding_request(SrsStunPacket *r, std::string ice_pwd);
|
||||
// DTLS transport functions.
|
||||
public:
|
||||
|
|
@ -248,32 +303,53 @@ public:
|
|||
void dispose();
|
||||
};
|
||||
|
||||
// For WebRTC over TCP.
|
||||
class SrsRtcTcpConn : public ISrsConnection, public ISrsCoroutineHandler, public ISrsExecutorHandler
|
||||
// The interface for TCP connection.
|
||||
class ISrsRtcTcpConn : public ISrsConnection, public ISrsCoroutineHandler, public ISrsExecutorHandler
|
||||
{
|
||||
private:
|
||||
// Because session references to this object, so we should directly use the session ptr.
|
||||
SrsRtcConnection *session_;
|
||||
public:
|
||||
ISrsRtcTcpConn();
|
||||
virtual ~ISrsRtcTcpConn();
|
||||
|
||||
private:
|
||||
public:
|
||||
// Interrupt the TCP connection.
|
||||
virtual void interrupt() = 0;
|
||||
};
|
||||
|
||||
// For WebRTC over TCP.
|
||||
class SrsRtcTcpConn : public ISrsRtcTcpConn
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *conn_manager_;
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because session references to this object, so we should directly use the session ptr.
|
||||
ISrsRtcConnection *session_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The ip and port of client.
|
||||
std::string ip_;
|
||||
int port_;
|
||||
// The delta for statistic.
|
||||
SrsNetworkDelta *delta_;
|
||||
ISrsNetworkDelta *delta_;
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
// Packet cache.
|
||||
char *pkt_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
|
||||
SrsSharedResource<SrsRtcTcpConn> *wrapper_;
|
||||
SrsSharedResource<ISrsRtcTcpConn> *wrapper_;
|
||||
// The owner coroutine, allow user to interrupt the loop.
|
||||
ISrsInterruptable *owner_coroutine_;
|
||||
ISrsContextIdSetter *owner_cid_;
|
||||
SrsContextId cid_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
void setup();
|
||||
|
||||
public:
|
||||
|
|
@ -283,7 +359,7 @@ public:
|
|||
|
||||
public:
|
||||
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
|
||||
void setup_owner(SrsSharedResource<SrsRtcTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
void setup_owner(SrsSharedResource<ISrsRtcTcpConn> *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid);
|
||||
|
||||
public:
|
||||
ISrsKbpsDelta *delta();
|
||||
|
|
@ -303,7 +379,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
srs_error_t handshake();
|
||||
srs_error_t read_packet(char *pkt, int *nb_pkt);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_api.hpp>
|
||||
#include <srs_app_rtc_api.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
|
|
@ -177,11 +178,11 @@ bool srs_is_rtcp(const uint8_t *data, size_t len)
|
|||
return (len >= 12) && (data[0] & 0x80) && (data[1] >= 192 && data[1] <= 223);
|
||||
}
|
||||
|
||||
srs_error_t api_server_as_candidates(string api, set<string> &candidate_ips)
|
||||
srs_error_t api_server_as_candidates(ISrsAppConfig *config, string api, set<string> &candidate_ips)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (api.empty() || !_srs_config->get_api_as_candidates()) {
|
||||
if (api.empty() || !config->get_api_as_candidates()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -194,12 +195,12 @@ srs_error_t api_server_as_candidates(string api, set<string> &candidate_ips)
|
|||
}
|
||||
|
||||
// Whether add domain name.
|
||||
if (!srs_net_is_ipv4(hostname) && _srs_config->get_keep_api_domain()) {
|
||||
if (!srs_net_is_ipv4(hostname) && config->get_keep_api_domain()) {
|
||||
candidate_ips.insert(hostname);
|
||||
}
|
||||
|
||||
// Try to parse the domain name if not IP.
|
||||
if (!srs_net_is_ipv4(hostname) && _srs_config->get_resolve_api_domain()) {
|
||||
if (!srs_net_is_ipv4(hostname) && config->get_resolve_api_domain()) {
|
||||
int family = 0;
|
||||
string ip = srs_dns_resolve(hostname, family);
|
||||
if (ip.empty() || ip == SRS_CONSTS_LOCALHOST || ip == SRS_CONSTS_LOOPBACK || ip == SRS_CONSTS_LOOPBACK6) {
|
||||
|
|
@ -218,7 +219,7 @@ srs_error_t api_server_as_candidates(string api, set<string> &candidate_ips)
|
|||
return err;
|
||||
}
|
||||
|
||||
set<string> discover_candidates(SrsRtcUserConfig *ruc)
|
||||
set<string> discover_candidates(SrsProtocolUtility *utility, ISrsAppConfig *config, SrsRtcUserConfig *ruc)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -229,29 +230,28 @@ set<string> discover_candidates(SrsRtcUserConfig *ruc)
|
|||
}
|
||||
|
||||
// Try to discover from api of request, if api_as_candidates enabled.
|
||||
if ((err = api_server_as_candidates(ruc->req_->host_, candidate_ips)) != srs_success) {
|
||||
if ((err = api_server_as_candidates(config, ruc->req_->host_, candidate_ips)) != srs_success) {
|
||||
srs_warn("ignore discovering ip from api %s, err %s", ruc->req_->host_.c_str(), srs_error_summary(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
// If not * or 0.0.0.0, use the candidate as exposed IP.
|
||||
string candidate = _srs_config->get_rtc_server_candidates();
|
||||
string candidate = config->get_rtc_server_candidates();
|
||||
if (candidate != "*" && candidate != "0.0.0.0") {
|
||||
candidate_ips.insert(candidate);
|
||||
return candidate_ips;
|
||||
}
|
||||
|
||||
// All automatically detected IP list.
|
||||
SrsProtocolUtility utility;
|
||||
vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||
vector<SrsIPAddress *> &ips = utility->local_ips();
|
||||
if (ips.empty()) {
|
||||
return candidate_ips;
|
||||
}
|
||||
|
||||
// Discover from local network interface addresses.
|
||||
if (_srs_config->get_use_auto_detect_network_ip()) {
|
||||
if (config->get_use_auto_detect_network_ip()) {
|
||||
// We try to find the best match candidates, no loopback.
|
||||
string family = _srs_config->get_rtc_server_ip_family();
|
||||
string family = config->get_rtc_server_ip_family();
|
||||
for (int i = 0; i < (int)ips.size(); ++i) {
|
||||
SrsIPAddress *ip = ips[i];
|
||||
if (ip->is_loopback_) {
|
||||
|
|
@ -313,12 +313,26 @@ SrsRtcUserConfig::~SrsRtcUserConfig()
|
|||
SrsRtcSessionManager::SrsRtcSessionManager()
|
||||
{
|
||||
rtc_async_ = new SrsAsyncCallWorker();
|
||||
|
||||
conn_manager_ = _srs_conn_manager;
|
||||
stream_publish_tokens_ = _srs_stream_publish_tokens;
|
||||
rtc_sources_ = _srs_rtc_sources;
|
||||
dtls_certificate_ = _srs_rtc_dtls_certificate;
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsRtcSessionManager::~SrsRtcSessionManager()
|
||||
{
|
||||
rtc_async_->stop();
|
||||
srs_freep(rtc_async_);
|
||||
|
||||
conn_manager_ = NULL;
|
||||
stream_publish_tokens_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
dtls_certificate_ = NULL;
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::initialize()
|
||||
|
|
@ -332,13 +346,13 @@ srs_error_t SrsRtcSessionManager::initialize()
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtcConnection *SrsRtcSessionManager::find_rtc_session_by_username(const std::string &username)
|
||||
ISrsRtcConnection *SrsRtcSessionManager::find_rtc_session_by_username(const std::string &username)
|
||||
{
|
||||
ISrsResource *conn = _srs_conn_manager->find_by_name(username);
|
||||
return dynamic_cast<SrsRtcConnection *>(conn);
|
||||
ISrsResource *conn = conn_manager_->find_by_name(username);
|
||||
return dynamic_cast<ISrsRtcConnection *>(conn);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -346,7 +360,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
|
||||
// Acquire stream publish token to prevent race conditions across all protocols.
|
||||
SrsStreamPublishToken *publish_token_raw = NULL;
|
||||
if (ruc->publish_ && (err = _srs_stream_publish_tokens->acquire_token(req, publish_token_raw)) != srs_success) {
|
||||
if (ruc->publish_ && (err = stream_publish_tokens_->acquire_token(req, publish_token_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "acquire stream publish token");
|
||||
}
|
||||
SrsSharedPtr<SrsStreamPublishToken> publish_token(publish_token_raw);
|
||||
|
|
@ -355,7 +369,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
}
|
||||
|
||||
SrsSharedPtr<SrsRtcSource> source;
|
||||
if ((err = _srs_rtc_sources->fetch_or_create(req, source)) != srs_success) {
|
||||
if ((err = rtc_sources_->fetch_or_create(req, source)) != srs_success) {
|
||||
return srs_error_wrap(err, "create source");
|
||||
}
|
||||
|
||||
|
|
@ -365,8 +379,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
|
||||
// TODO: FIXME: add do_create_session to error process.
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsRtcConnection *session = new SrsRtcConnection(this, cid);
|
||||
session->assemble();
|
||||
ISrsRtcConnection *session = app_factory_->create_rtc_connection(this, cid);
|
||||
|
||||
if ((err = do_create_rtc_session(ruc, local_sdp, session)) != srs_success) {
|
||||
srs_freep(session);
|
||||
|
|
@ -383,7 +396,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection *session)
|
||||
srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection *session)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -410,7 +423,7 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
std::string username = "";
|
||||
while (true) {
|
||||
username = local_ufrag + ":" + ruc->remote_sdp_.get_ice_ufrag();
|
||||
if (!_srs_conn_manager->find_by_name(username)) {
|
||||
if (!conn_manager_->find_by_name(username)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -421,7 +434,7 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
local_sdp.set_ice_ufrag(local_ufrag);
|
||||
local_sdp.set_ice_pwd(local_pwd);
|
||||
local_sdp.set_fingerprint_algo("sha-256");
|
||||
local_sdp.set_fingerprint(_srs_rtc_dtls_certificate->get_fingerprint());
|
||||
local_sdp.set_fingerprint(dtls_certificate_->get_fingerprint());
|
||||
|
||||
// We allows to mock the eip of server.
|
||||
if (true) {
|
||||
|
|
@ -429,20 +442,21 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
int udp_port = 0;
|
||||
if (true) {
|
||||
string udp_host;
|
||||
string udp_hostport = _srs_config->get_rtc_server_listens().at(0);
|
||||
string udp_hostport = config_->get_rtc_server_listens().at(0);
|
||||
srs_net_split_for_listener(udp_hostport, udp_host, udp_port);
|
||||
}
|
||||
|
||||
int tcp_port = 0;
|
||||
if (true) {
|
||||
string tcp_host;
|
||||
string tcp_hostport = _srs_config->get_rtc_server_tcp_listens().at(0);
|
||||
string tcp_hostport = config_->get_rtc_server_tcp_listens().at(0);
|
||||
srs_net_split_for_listener(tcp_hostport, tcp_host, tcp_port);
|
||||
}
|
||||
|
||||
string protocol = _srs_config->get_rtc_server_protocol();
|
||||
string protocol = config_->get_rtc_server_protocol();
|
||||
|
||||
set<string> candidates = discover_candidates(ruc);
|
||||
SrsProtocolUtility utility;
|
||||
set<string> candidates = discover_candidates(&utility, config_, ruc);
|
||||
for (set<string>::iterator it = candidates.begin(); it != candidates.end(); ++it) {
|
||||
string hostname;
|
||||
int uport = udp_port;
|
||||
|
|
@ -494,7 +508,7 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
}
|
||||
|
||||
// We allows username is optional, but it never empty here.
|
||||
_srs_conn_manager->add_with_name(username, session);
|
||||
conn_manager_->add_with_name(username, session);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -505,10 +519,10 @@ void SrsRtcSessionManager::srs_update_rtc_sessions()
|
|||
int nn_rtc_conns = 0;
|
||||
|
||||
// Check all sessions and dispose the dead sessions.
|
||||
for (int i = 0; i < (int)_srs_conn_manager->size(); i++) {
|
||||
SrsRtcConnection *session = dynamic_cast<SrsRtcConnection *>(_srs_conn_manager->at(i));
|
||||
for (int i = 0; i < (int)conn_manager_->size(); i++) {
|
||||
ISrsRtcConnection *session = dynamic_cast<ISrsRtcConnection *>(conn_manager_->at(i));
|
||||
// Ignore not session, or already disposing.
|
||||
if (!session || session->disposing_) {
|
||||
if (!session || session->is_disposing()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -525,7 +539,7 @@ void SrsRtcSessionManager::srs_update_rtc_sessions()
|
|||
srs_trace("RTC: session destroy by timeout, username=%s", username.c_str());
|
||||
|
||||
// Use manager to free session and notify other objects.
|
||||
_srs_conn_manager->remove(session);
|
||||
conn_manager_->remove(session);
|
||||
}
|
||||
|
||||
// Ignore stats if no RTC connections.
|
||||
|
|
@ -556,11 +570,11 @@ srs_error_t SrsRtcSessionManager::exec_rtc_async_work(ISrsAsyncCallTask *t)
|
|||
return rtc_async_->execute(t);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::on_udp_packet(SrsUdpMuxSocket *skt)
|
||||
srs_error_t SrsRtcSessionManager::on_udp_packet(ISrsUdpMuxSocket *skt)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
char *data = skt->data();
|
||||
int size = skt->size();
|
||||
bool is_rtp_or_rtcp = srs_is_rtp_or_rtcp((uint8_t *)data, size);
|
||||
|
|
@ -569,11 +583,11 @@ srs_error_t SrsRtcSessionManager::on_udp_packet(SrsUdpMuxSocket *skt)
|
|||
uint64_t fast_id = skt->fast_id();
|
||||
// Try fast id first, if not found, search by long peer id.
|
||||
if (fast_id) {
|
||||
session = (SrsRtcConnection *)_srs_conn_manager->find_by_fast_id(fast_id);
|
||||
session = (ISrsRtcConnection *)conn_manager_->find_by_fast_id(fast_id);
|
||||
}
|
||||
if (!session) {
|
||||
string peer_id = skt->peer_id();
|
||||
session = (SrsRtcConnection *)_srs_conn_manager->find_by_id(peer_id);
|
||||
session = (ISrsRtcConnection *)conn_manager_->find_by_id(peer_id);
|
||||
}
|
||||
|
||||
if (session) {
|
||||
|
|
@ -609,7 +623,9 @@ srs_error_t SrsRtcSessionManager::on_udp_packet(SrsUdpMuxSocket *skt)
|
|||
|
||||
// For each binding request, update the UDP socket.
|
||||
if (ping.is_binding_request()) {
|
||||
session->udp()->update_sendonly_socket(skt);
|
||||
SrsRtcUdpNetwork *udp_network = dynamic_cast<SrsRtcUdpNetwork *>(session->udp());
|
||||
srs_assert(udp_network);
|
||||
udp_network->update_sendonly_socket(skt);
|
||||
}
|
||||
|
||||
return session->udp()->on_stun(&ping, data, size);
|
||||
|
|
|
|||
|
|
@ -23,11 +23,19 @@
|
|||
class SrsRtcServer;
|
||||
class SrsHourGlass;
|
||||
class SrsRtcConnection;
|
||||
class ISrsRtcConnection;
|
||||
class ISrsRequest;
|
||||
class SrsSdp;
|
||||
class SrsRtcSource;
|
||||
class SrsResourceManager;
|
||||
class SrsAsyncCallWorker;
|
||||
class ISrsUdpMuxSocket;
|
||||
class ISrsResourceManager;
|
||||
class ISrsStreamPublishTokenManager;
|
||||
class ISrsRtcSourceManager;
|
||||
class ISrsDtlsCertificate;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The UDP black hole, for developer to use wireshark to catch plaintext packets.
|
||||
// For example, server receive UDP packets at udp://8000, and forward the plaintext packet to black hole,
|
||||
|
|
@ -37,7 +45,8 @@ class SrsRtcBlackhole
|
|||
public:
|
||||
bool blackhole_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
sockaddr_in *blackhole_addr_;
|
||||
srs_netfd_t blackhole_stfd_;
|
||||
|
||||
|
|
@ -84,7 +93,7 @@ public:
|
|||
};
|
||||
|
||||
// Discover the candidates for RTC server.
|
||||
extern std::set<std::string> discover_candidates(SrsRtcUserConfig *ruc);
|
||||
extern std::set<std::string> discover_candidates(SrsProtocolUtility *utility, ISrsAppConfig *config, SrsRtcUserConfig *ruc);
|
||||
|
||||
// The dns resolve utility, return the resolved ip address.
|
||||
extern std::string srs_dns_resolve(std::string host, int &family);
|
||||
|
|
@ -92,7 +101,17 @@ extern std::string srs_dns_resolve(std::string host, int &family);
|
|||
// RTC session manager to handle WebRTC session lifecycle and management.
|
||||
class SrsRtcSessionManager : public ISrsExecRtcAsyncTask
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *conn_manager_;
|
||||
ISrsStreamPublishTokenManager *stream_publish_tokens_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsDtlsCertificate *dtls_certificate_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// WebRTC async call worker for non-blocking operations.
|
||||
SrsAsyncCallWorker *rtc_async_;
|
||||
|
||||
|
|
@ -104,11 +123,12 @@ public:
|
|||
virtual srs_error_t initialize();
|
||||
|
||||
public:
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection *session);
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection *session);
|
||||
|
||||
public:
|
||||
virtual void srs_update_rtc_sessions();
|
||||
|
|
@ -118,7 +138,11 @@ public:
|
|||
virtual srs_error_t exec_rtc_async_work(ISrsAsyncCallTask *t);
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket *skt);
|
||||
virtual srs_error_t on_udp_packet(ISrsUdpMuxSocket *skt);
|
||||
};
|
||||
|
||||
// Helper function to discover candidate IPs from API server hostname
|
||||
// Used by WebRTC ICE candidate discovery
|
||||
extern srs_error_t api_server_as_candidates(ISrsAppConfig *config, std::string api, std::set<std::string> &candidate_ips);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -119,11 +119,13 @@ public:
|
|||
// The RTC stream consumer, consume packets from RTC stream source.
|
||||
class SrsRtcConsumer : public ISrsRtcConsumer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsRtcSourceForConsumer *source_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<SrsRtpPacket *> queue_;
|
||||
// when source id changed, notice all consumers
|
||||
bool should_update_source_id_;
|
||||
|
|
@ -132,7 +134,8 @@ private:
|
|||
bool mw_waiting_;
|
||||
int mw_min_msgs_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The callback for stream change event.
|
||||
ISrsRtcSourceChangeCallback *handler_;
|
||||
|
||||
|
|
@ -172,7 +175,8 @@ public:
|
|||
// The RTC source manager.
|
||||
class SrsRtcSourceManager : public ISrsRtcSourceManager, public ISrsHourGlassHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_mutex_t lock_;
|
||||
std::map<std::string, SrsSharedPtr<SrsRtcSource> > pool_;
|
||||
SrsHourGlass *timer_;
|
||||
|
|
@ -184,7 +188,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
||||
|
|
@ -233,11 +238,13 @@ public:
|
|||
// A Source is a stream, to publish and to play with, binding to SrsRtcPublishStream and SrsRtcPlayStream.
|
||||
class SrsRtcSource : public ISrsRtpTarget, public ISrsFastTimerHandler, public ISrsRtcSourceForConsumer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The RTP bridge, convert RTP packets to other protocols.
|
||||
ISrsRtcBridge *rtc_bridge_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Circuit breaker for protecting server resources.
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
// For publish, it's the publish client id.
|
||||
|
|
@ -252,9 +259,11 @@ private:
|
|||
// Steam description for this steam.
|
||||
SrsRtcSourceDescription *stream_desc_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// To delivery stream to clients.
|
||||
std::vector<ISrsRtcConsumer *> consumers_;
|
||||
std::vector<ISrsRtcConsumer *>
|
||||
consumers_;
|
||||
// Whether stream is created, that is, SDP is done.
|
||||
bool is_created_;
|
||||
// Whether stream is delivering data, that is, DTLS is done.
|
||||
|
|
@ -262,12 +271,14 @@ private:
|
|||
// Notify stream event to event handler
|
||||
std::vector<ISrsRtcSourceEventHandler *> event_handlers_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The PLI for RTC2RTMP.
|
||||
srs_utime_t pli_for_rtmp_;
|
||||
srs_utime_t pli_elapsed_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The last die time, while die means neither publishers nor players.
|
||||
srs_utime_t stream_die_at_;
|
||||
|
||||
|
|
@ -282,16 +293,19 @@ public:
|
|||
// Whether stream is dead, which is no publisher or player.
|
||||
virtual bool stream_is_dead();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
void init_for_play_before_publishing();
|
||||
|
||||
public:
|
||||
// Update the authentication information in request.
|
||||
virtual void update_auth(ISrsRequest *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The stream source changed.
|
||||
virtual srs_error_t on_source_changed();
|
||||
virtual srs_error_t
|
||||
on_source_changed();
|
||||
|
||||
public:
|
||||
// Get current source id.
|
||||
|
|
@ -337,7 +351,8 @@ public:
|
|||
virtual void set_stream_desc(SrsRtcSourceDescription *stream_desc);
|
||||
virtual std::vector<SrsRtcTrackDescription *> get_track_desc(std::string type, std::string media_type);
|
||||
// interface ISrsFastTimerHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_timer(srs_utime_t interval);
|
||||
};
|
||||
|
||||
|
|
@ -346,7 +361,8 @@ private:
|
|||
// Convert AV frame to RTC RTP packets.
|
||||
class SrsRtcRtpBuilder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
ISrsRtpTarget *rtp_target_;
|
||||
// The format, codec information.
|
||||
|
|
@ -356,7 +372,8 @@ private:
|
|||
// The video builder, convert frame to RTP packets.
|
||||
SrsRtpVideoBuilder *video_builder_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsAudioCodecId latest_codec_;
|
||||
ISrsAudioTranscoder *codec_;
|
||||
bool keep_bframe_;
|
||||
|
|
@ -364,11 +381,13 @@ private:
|
|||
bool merge_nalus_;
|
||||
uint16_t audio_sequence_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint32_t audio_ssrc_;
|
||||
uint8_t audio_payload_type_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsSharedPtr<SrsRtcSource> source_;
|
||||
// Lazy initialization flags
|
||||
bool audio_initialized_;
|
||||
|
|
@ -378,9 +397,11 @@ public:
|
|||
SrsRtcRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr<SrsRtcSource> source);
|
||||
virtual ~SrsRtcRtpBuilder();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Lazy initialization methods
|
||||
srs_error_t initialize_audio_track(SrsAudioCodecId codec);
|
||||
srs_error_t
|
||||
initialize_audio_track(SrsAudioCodecId codec);
|
||||
srs_error_t initialize_video_track(SrsVideoCodecId codec);
|
||||
|
||||
public:
|
||||
|
|
@ -389,18 +410,22 @@ public:
|
|||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_frame(SrsMediaPacket *frame);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t init_codec(SrsAudioCodecId codec);
|
||||
srs_error_t transcode(SrsParsedAudioPacket *audio);
|
||||
srs_error_t package_opus(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_video(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, std::vector<SrsNaluSample *> &samples);
|
||||
srs_error_t package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt);
|
||||
srs_error_t package_nalus(SrsMediaPacket *msg, const std::vector<SrsNaluSample *> &samples, std::vector<SrsRtpPacket *> &pkts);
|
||||
|
|
@ -413,7 +438,8 @@ private:
|
|||
// TODO: Maybe should use SrsRtpRingBuffer?
|
||||
class SrsRtcFrameBuilderVideoPacketCache
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
const static uint16_t cache_size_ = 512;
|
||||
struct RtcPacketCache {
|
||||
bool in_use_;
|
||||
|
|
@ -441,7 +467,8 @@ public:
|
|||
// Check if frame is complete by verifying FU-A start/end fragment counts match
|
||||
bool check_frame_complete(const uint16_t start, const uint16_t end);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool is_slot_in_use(uint16_t sequence_number);
|
||||
uint32_t get_rtp_timestamp(uint16_t sequence_number);
|
||||
inline uint16_t cache_index(uint16_t sequence_number)
|
||||
|
|
@ -453,7 +480,8 @@ private:
|
|||
// Video frame detector for managing frame boundaries and packet loss detection
|
||||
class SrsRtcFrameBuilderVideoFrameDetector
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcFrameBuilderVideoPacketCache *video_cache_;
|
||||
uint16_t header_sn_;
|
||||
uint16_t lost_sn_;
|
||||
|
|
@ -474,9 +502,11 @@ public:
|
|||
// Audio packet cache for RTP packet jitter buffer management
|
||||
class SrsRtcFrameBuilderAudioPacketCache
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Audio jitter buffer, map sequence number to packet
|
||||
std::map<uint16_t, SrsRtpPacket *> audio_buffer_;
|
||||
std::map<uint16_t, SrsRtpPacket *>
|
||||
audio_buffer_;
|
||||
// Last processed sequence number
|
||||
uint16_t last_audio_seq_num_;
|
||||
// Last time we processed the jitter buffer
|
||||
|
|
@ -503,24 +533,29 @@ public:
|
|||
// Collect and build WebRTC RTP packets to AV frames.
|
||||
class SrsRtcFrameBuilder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFrameTarget *frame_target_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool is_first_audio_;
|
||||
ISrsAudioTranscoder *audio_transcoder_;
|
||||
SrsVideoCodecId video_codec_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcFrameBuilderAudioPacketCache *audio_cache_;
|
||||
SrsRtcFrameBuilderVideoPacketCache *video_cache_;
|
||||
SrsRtcFrameBuilderVideoFrameDetector *frame_detector_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The state for timestamp sync state. -1 for init. 0 not sync. 1 sync.
|
||||
int sync_state_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For OBS WHIP, send (VPS/)SPS/PPS in dedicated RTP packet.
|
||||
SrsRtpPacket *obs_whip_vps_;
|
||||
SrsRtpPacket *obs_whip_sps_;
|
||||
|
|
@ -536,12 +571,14 @@ public:
|
|||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_rtp(SrsRtpPacket *pkt);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t packet_audio(SrsRtpPacket *pkt);
|
||||
srs_error_t transcode_audio(SrsRtpPacket *pkt);
|
||||
void packet_aac(SrsRtmpCommonMessage *audio, char *data, int len, uint32_t pts, bool is_header);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t packet_video(SrsRtpPacket *pkt);
|
||||
srs_error_t packet_video_key_frame(SrsRtpPacket *pkt);
|
||||
srs_error_t packet_sequence_header_avc(SrsRtpPacket *pkt);
|
||||
|
|
@ -549,7 +586,8 @@ private:
|
|||
srs_error_t packet_sequence_header_hevc(SrsRtpPacket *pkt);
|
||||
srs_error_t do_packet_sequence_header_hevc(SrsRtpPacket *pkt, SrsNaluSample *vps, SrsNaluSample *sps, SrsNaluSample *pps);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t packet_video_rtmp(const uint16_t start, const uint16_t end);
|
||||
int calculate_packet_payload_size(SrsRtpPacket *pkt);
|
||||
void write_packet_payload_to_buffer(SrsRtpPacket *pkt, SrsBuffer &payload, int &nalu_len);
|
||||
|
|
@ -571,7 +609,8 @@ public:
|
|||
|
||||
std::vector<std::string> rtcp_fbs_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The cached codec ID, corresponding to name_.
|
||||
// For video, you can convert it to type SrsVideoCodecId
|
||||
// For audio, you can convert it to type SrsAudioCodecId
|
||||
|
|
@ -777,19 +816,23 @@ public:
|
|||
// The RTC receive track.
|
||||
class SrsRtcRecvTrack
|
||||
{
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
SrsRtcTrackDescription *track_desc_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
ISrsRtcPacketReceiver *receiver_;
|
||||
SrsRtpRingBuffer *rtp_queue_;
|
||||
SrsRtpNackForReceiver *nack_receiver_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// By config, whether no copy.
|
||||
bool nack_no_copy_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// Latest sender report ntp and rtp time.
|
||||
SrsNtp last_sender_report_ntp_;
|
||||
int64_t last_sender_report_rtp_time_;
|
||||
|
|
@ -828,7 +871,8 @@ public:
|
|||
virtual srs_error_t on_rtp(SrsSharedPtr<SrsRtcSource> &source, SrsRtpPacket *pkt) = 0;
|
||||
virtual srs_error_t check_send_nacks() = 0;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t do_check_send_nacks(uint32_t &timeout_nacks);
|
||||
};
|
||||
|
||||
|
|
@ -864,12 +908,14 @@ public:
|
|||
template <typename T, typename ST>
|
||||
class SrsRtcJitter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ST threshold_;
|
||||
typedef ST (*PFN)(const T &, const T &);
|
||||
PFN distance_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The value about packet.
|
||||
T pkt_base_;
|
||||
T pkt_last_;
|
||||
|
|
@ -926,7 +972,8 @@ public:
|
|||
// For RTC timestamp jitter.
|
||||
class SrsRtcTsJitter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcJitter<uint32_t, int32_t> *jitter_;
|
||||
|
||||
public:
|
||||
|
|
@ -940,7 +987,8 @@ public:
|
|||
// For RTC sequence jitter.
|
||||
class SrsRtcSeqJitter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcJitter<uint16_t, int16_t> *jitter_;
|
||||
|
||||
public:
|
||||
|
|
@ -968,18 +1016,21 @@ public:
|
|||
// send track description
|
||||
SrsRtcTrackDescription *track_desc_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The owner connection for this track.
|
||||
ISrsRtcPacketSender *sender_;
|
||||
// NACK ARQ ring buffer.
|
||||
SrsRtpRingBuffer *rtp_queue_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The jitter to correct ts and sequence number.
|
||||
SrsRtcTsJitter *jitter_ts_;
|
||||
SrsRtcSeqJitter *jitter_seq_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// By config, whether no copy.
|
||||
bool nack_no_copy_;
|
||||
// The pithy print for special stage.
|
||||
|
|
@ -998,7 +1049,8 @@ public:
|
|||
bool get_track_status();
|
||||
std::string get_track_id();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
void rebuild_packet(SrsRtpPacket *pkt);
|
||||
|
||||
public:
|
||||
|
|
@ -1036,13 +1088,16 @@ public:
|
|||
|
||||
class SrsRtcSSRCGenerator
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
static SrsRtcSSRCGenerator *instance_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint32_t ssrc_num_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtcSSRCGenerator();
|
||||
virtual ~SrsRtcSSRCGenerator();
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,9 @@ void SrsRtmpConn::assemble()
|
|||
|
||||
SrsRtmpConn::~SrsRtmpConn()
|
||||
{
|
||||
config_->unsubscribe(this);
|
||||
if (config_) {
|
||||
config_->unsubscribe(this);
|
||||
}
|
||||
|
||||
trd_->interrupt();
|
||||
// wakeup the handler which need to notice.
|
||||
|
|
@ -262,6 +264,7 @@ SrsRtmpConn::~SrsRtmpConn()
|
|||
srs_freep(refer_);
|
||||
srs_freep(security_);
|
||||
|
||||
config_ = NULL;
|
||||
manager_ = NULL;
|
||||
stream_publish_tokens_ = NULL;
|
||||
live_sources_ = NULL;
|
||||
|
|
@ -890,6 +893,8 @@ srs_error_t SrsRtmpConn::publishing(SrsSharedPtr<SrsLiveSource> source)
|
|||
// use isolate thread to recv,
|
||||
// @see: https://github.com/ossrs/srs/issues/237
|
||||
SrsPublishRecvThread rtrd(rtmp_, req, srs_netfd_fileno(transport_->fd()), 0, this, source, _srs_context->get_id());
|
||||
rtrd.assemble();
|
||||
|
||||
err = do_publishing(source, &rtrd);
|
||||
rtrd.stop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,14 +56,16 @@ class ISrsSecurity;
|
|||
// The simple rtmp client for SRS.
|
||||
class SrsSimpleRtmpClient : public SrsBasicRtmpClient
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
public:
|
||||
SrsSimpleRtmpClient(std::string u, srs_utime_t ctm, srs_utime_t stm);
|
||||
virtual ~SrsSimpleRtmpClient();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t connect_app();
|
||||
};
|
||||
|
||||
|
|
@ -106,7 +108,8 @@ public:
|
|||
// The base transport layer for RTMP connections over plain TCP.
|
||||
class SrsRtmpTransport : public ISrsRtmpTransport
|
||||
{
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
srs_netfd_t stfd_;
|
||||
SrsTcpConnection *skt_;
|
||||
|
||||
|
|
@ -135,10 +138,12 @@ public:
|
|||
// The SSL/TLS transport layer for RTMPS connections.
|
||||
class SrsRtmpsTransport : public SrsRtmpTransport
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsSslConnection *ssl_;
|
||||
|
||||
public:
|
||||
|
|
@ -154,12 +159,18 @@ public:
|
|||
virtual const char *transport_type();
|
||||
};
|
||||
|
||||
class SrsRtmpConn : public ISrsConnection, public ISrsStartable, public ISrsReloadHandler, public ISrsCoroutineHandler, public ISrsExpire
|
||||
// The RTMP connection, for client to publish or play stream.
|
||||
class SrsRtmpConn : public ISrsConnection, // It's a resource.
|
||||
public ISrsStartable,
|
||||
public ISrsReloadHandler,
|
||||
public ISrsCoroutineHandler,
|
||||
public ISrsExpire
|
||||
{
|
||||
// For the thread to directly access any field of connection.
|
||||
friend class SrsPublishRecvThread;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *manager_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStreamPublishTokenManager *stream_publish_tokens_;
|
||||
|
|
@ -172,7 +183,8 @@ private:
|
|||
ISrsRtspSourceManager *rtsp_sources_;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtmpServer *rtmp_;
|
||||
SrsRefer *refer_;
|
||||
SrsBandwidth *bandwidth_;
|
||||
|
|
@ -200,7 +212,8 @@ private:
|
|||
// About the rtmp client.
|
||||
SrsClientInfo *info_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtmpTransport *transport_;
|
||||
// Each connection start a green thread,
|
||||
// when thread stop, the connection will be delete by server.
|
||||
|
|
@ -223,15 +236,18 @@ public:
|
|||
public:
|
||||
virtual std::string desc();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
public:
|
||||
virtual ISrsKbpsDelta *delta();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// When valid and connected to vhost/app, service the client.
|
||||
virtual srs_error_t service_cycle();
|
||||
virtual srs_error_t
|
||||
service_cycle();
|
||||
// The stream(play/publish) service cycle, identify client first.
|
||||
virtual srs_error_t stream_service_cycle();
|
||||
virtual srs_error_t check_vhost(bool try_default_vhost);
|
||||
|
|
@ -246,16 +262,20 @@ private:
|
|||
virtual srs_error_t process_play_control_msg(SrsLiveConsumer *consumer, SrsRtmpCommonMessage *msg);
|
||||
virtual void set_sock_options();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t check_edge_token_traverse_auth();
|
||||
virtual srs_error_t do_token_traverse_auth(SrsRtmpClient *client);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// When the connection disconnect, call this method.
|
||||
// e.g. log msg of connection and report to other system.
|
||||
virtual srs_error_t on_disconnect();
|
||||
virtual srs_error_t
|
||||
on_disconnect();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t http_hooks_on_connect();
|
||||
virtual void http_hooks_on_close();
|
||||
virtual srs_error_t http_hooks_on_publish();
|
||||
|
|
|
|||
|
|
@ -850,7 +850,10 @@ SrsOriginHub::SrsOriginHub()
|
|||
|
||||
hls_ = new SrsHls();
|
||||
dash_ = new SrsDash();
|
||||
|
||||
dvr_ = new SrsDvr();
|
||||
dvr_->assemble();
|
||||
|
||||
encoder_ = new SrsEncoder();
|
||||
#ifdef SRS_HDS
|
||||
hds_ = new SrsHds();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class ISrsHds;
|
|||
#endif
|
||||
class ISrsNgExec;
|
||||
class ISrsForwarder;
|
||||
class SrsAppFactory;
|
||||
class ISrsAppFactory;
|
||||
class ISrsLiveConsumer;
|
||||
|
||||
// The time jitter algorithm:
|
||||
|
|
@ -77,7 +77,8 @@ int srs_time_jitter_string2int(std::string time_jitter);
|
|||
// Time jitter detect and correct, to ensure the rtmp stream is monotonically.
|
||||
class SrsRtmpJitter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int64_t last_pkt_time_;
|
||||
int64_t last_pkt_correct_time_;
|
||||
|
||||
|
|
@ -97,7 +98,8 @@ public:
|
|||
// To alloc and increase fixed space, fast remove and insert for msgs sender.
|
||||
class SrsFastVector
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsMediaPacket **msgs_;
|
||||
int nb_msgs_;
|
||||
int count_;
|
||||
|
|
@ -140,12 +142,14 @@ public:
|
|||
// We limit the size in seconds, drop old messages(the whole gop) if full.
|
||||
class SrsMessageQueue : public ISrsMessageQueue
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The start and end time.
|
||||
srs_utime_t av_start_time_;
|
||||
srs_utime_t av_end_time_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether do logging when shrinking.
|
||||
bool _ignore_shrink;
|
||||
// The max queue size, shrink if exceed it.
|
||||
|
|
@ -182,10 +186,12 @@ public:
|
|||
// @remark the atc/tba/tbv/ag are same to SrsLiveConsumer.enqueue().
|
||||
virtual srs_error_t dump_packets(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Remove a gop from the front.
|
||||
// if no iframe found, clear it.
|
||||
virtual void shrink();
|
||||
virtual void
|
||||
shrink();
|
||||
|
||||
public:
|
||||
// clear all messages in queue.
|
||||
|
|
@ -224,11 +230,13 @@ public:
|
|||
// The consumer for SrsLiveSource, that is a play client.
|
||||
class SrsLiveConsumer : public ISrsWakable, public ISrsLiveConsumer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsRtmpJitter *jitter_;
|
||||
SrsMessageQueue *queue_;
|
||||
bool paused_;
|
||||
|
|
@ -285,7 +293,8 @@ public:
|
|||
// To enable it to fast startup.
|
||||
class SrsGopCache
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// if disabled the gop cache,
|
||||
// The client will wait for the next keyframe for h264,
|
||||
// and will be black-screen.
|
||||
|
|
@ -360,7 +369,8 @@ public:
|
|||
// The mix queue to correct the timestamp for mix_correct algorithm.
|
||||
class SrsMixQueue
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint32_t nb_videos_;
|
||||
uint32_t nb_audios_;
|
||||
std::multimap<int64_t, SrsMediaPacket *> msgs_;
|
||||
|
|
@ -402,6 +412,8 @@ public:
|
|||
virtual srs_error_t on_publish() = 0;
|
||||
// When stop publish stream.
|
||||
virtual void on_unpublish() = 0;
|
||||
// When DVR requests sequence header.
|
||||
virtual srs_error_t on_dvr_request_sh() = 0;
|
||||
};
|
||||
|
||||
// The hub for origin is a collection of utilities for origin only,
|
||||
|
|
@ -409,20 +421,24 @@ public:
|
|||
// they are meanless for edge server.
|
||||
class SrsOriginHub : public ISrsReloadHandler, public ISrsOriginHub
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
bool is_active_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// hls handler.
|
||||
ISrsHls *hls_;
|
||||
// The DASH encoder.
|
||||
|
|
@ -482,7 +498,8 @@ public:
|
|||
// For the SrsHls to callback to request the sequence headers.
|
||||
virtual srs_error_t on_hls_request_sh();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t create_forwarders();
|
||||
virtual srs_error_t create_backend_forwarders(bool &applied);
|
||||
virtual void destroy_forwarders();
|
||||
|
|
@ -492,7 +509,8 @@ private:
|
|||
// This class cache and update the meta.
|
||||
class SrsMetaCache
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The cached metadata, FLV script data tag.
|
||||
SrsMediaPacket *meta_;
|
||||
// The cached video sequence header, for example, sps/pps for h.264.
|
||||
|
|
@ -570,10 +588,12 @@ public:
|
|||
// The source manager to create and refresh all stream sources.
|
||||
class SrsLiveSourceManager : public ISrsHourGlassHandler, public ISrsLiveSourceManager
|
||||
{
|
||||
private:
|
||||
SrsAppFactory *app_factory_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_mutex_t lock_;
|
||||
std::map<std::string, SrsSharedPtr<SrsLiveSource> > pool_;
|
||||
ISrsHourGlass *timer_;
|
||||
|
|
@ -598,7 +618,8 @@ public:
|
|||
// dispose and cycle all sources.
|
||||
virtual void dispose();
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
||||
|
|
@ -624,18 +645,30 @@ public:
|
|||
virtual SrsContextId pre_source_id() = 0;
|
||||
virtual SrsMetaCache *meta() = 0;
|
||||
virtual SrsRtmpFormat *format() = 0;
|
||||
// The source id changed.
|
||||
virtual srs_error_t on_source_id_changed(SrsContextId id) = 0;
|
||||
// Publish stream event notify.
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
// Handle media messages.
|
||||
virtual srs_error_t on_audio(SrsRtmpCommonMessage *audio) = 0;
|
||||
virtual srs_error_t on_video(SrsRtmpCommonMessage *video) = 0;
|
||||
virtual srs_error_t on_aggregate(SrsRtmpCommonMessage *msg) = 0;
|
||||
virtual srs_error_t on_meta_data(SrsRtmpCommonMessage *msg, SrsOnMetaDataPacket *metadata) = 0;
|
||||
};
|
||||
|
||||
// The live streaming source.
|
||||
class SrsLiveSource : public ISrsReloadHandler, public ISrsFrameTarget, public ISrsLiveSource
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsLiveSourceHandler *handler_;
|
||||
SrsAppFactory *app_factory_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For publish, it's the publish client id.
|
||||
// For edge, it's the edge ingest id.
|
||||
// when source id changed, for example, the edge reconnect,
|
||||
|
|
@ -676,7 +709,8 @@ private:
|
|||
// The format, codec information.
|
||||
SrsRtmpFormat *format_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether source is avaiable for publishing.
|
||||
bool can_publish_;
|
||||
// The last die time, while die means neither publishers nor players.
|
||||
|
|
@ -726,14 +760,16 @@ public:
|
|||
virtual srs_error_t on_audio(SrsRtmpCommonMessage *audio);
|
||||
srs_error_t on_frame(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_audio_imp(SrsMediaPacket *audio);
|
||||
|
||||
public:
|
||||
// TODO: FIXME: Use SrsMediaPacket instead.
|
||||
virtual srs_error_t on_video(SrsRtmpCommonMessage *video);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_video_imp(SrsMediaPacket *video);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@ using namespace std;
|
|||
#include <sstream>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#ifdef SRS_RTSP
|
||||
#include <srs_app_rtsp_source.hpp>
|
||||
#endif
|
||||
#include <srs_app_security.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
|
@ -26,7 +29,9 @@ using namespace std;
|
|||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_pithy_print.hpp>
|
||||
#include <srs_kernel_rtc_rtp.hpp>
|
||||
#ifdef SRS_RTSP
|
||||
#include <srs_protocol_rtsp_stack.hpp>
|
||||
#endif
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
|
|
@ -41,7 +46,15 @@ extern SrsPps *_srs_pps_rnack2;
|
|||
extern SrsPps *_srs_pps_pub;
|
||||
extern SrsPps *_srs_pps_conn;
|
||||
|
||||
SrsRtspPlayStream::SrsRtspPlayStream(SrsRtspConnection *s, const SrsContextId &cid) : source_(new SrsRtspSource())
|
||||
ISrsRtspPlayStream::ISrsRtspPlayStream()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtspPlayStream::~ISrsRtspPlayStream()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtspPlayStream::SrsRtspPlayStream(ISrsRtspConnection *s, const SrsContextId &cid) : source_(new SrsRtspSource())
|
||||
{
|
||||
cid_ = cid;
|
||||
trd_ = NULL;
|
||||
|
|
@ -53,6 +66,10 @@ SrsRtspPlayStream::SrsRtspPlayStream(SrsRtspConnection *s, const SrsContextId &c
|
|||
|
||||
cache_ssrc0_ = cache_ssrc1_ = cache_ssrc2_ = 0;
|
||||
cache_track0_ = cache_track1_ = cache_track2_ = NULL;
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
stat_ = _srs_stat;
|
||||
rtsp_sources_ = _srs_rtsp_sources;
|
||||
}
|
||||
|
||||
SrsRtspPlayStream::~SrsRtspPlayStream()
|
||||
|
|
@ -61,23 +78,26 @@ SrsRtspPlayStream::~SrsRtspPlayStream()
|
|||
srs_freep(req_);
|
||||
|
||||
if (true) {
|
||||
std::map<uint32_t, SrsRtspAudioSendTrack *>::iterator it;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *>::iterator it;
|
||||
for (it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) {
|
||||
srs_freep(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (true) {
|
||||
std::map<uint32_t, SrsRtspVideoSendTrack *>::iterator it;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *>::iterator it;
|
||||
for (it = video_tracks_.begin(); it != video_tracks_.end(); ++it) {
|
||||
srs_freep(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// update the statistic when client coveried.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
// TODO: FIXME: Should finger out the err.
|
||||
stat->on_disconnect(cid_.c_str(), srs_success);
|
||||
stat_->on_disconnect(cid_.c_str(), srs_success);
|
||||
|
||||
app_factory_ = NULL;
|
||||
stat_ = NULL;
|
||||
rtsp_sources_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspPlayStream::initialize(ISrsRequest *req, std::map<uint32_t, SrsRtcTrackDescription *> sub_relations)
|
||||
|
|
@ -87,12 +107,11 @@ srs_error_t SrsRtspPlayStream::initialize(ISrsRequest *req, std::map<uint32_t, S
|
|||
req_ = req->copy();
|
||||
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
if ((err = stat->on_client(cid_.c_str(), req_, session_, SrsRtcConnPlay)) != srs_success) {
|
||||
if ((err = stat_->on_client(cid_.c_str(), req_, session_, SrsRtcConnPlay)) != srs_success) {
|
||||
return srs_error_wrap(err, "RTSP: stat client");
|
||||
}
|
||||
|
||||
if ((err = _srs_rtsp_sources->fetch_or_create(req_, source_)) != srs_success) {
|
||||
if ((err = rtsp_sources_->fetch_or_create(req_, source_)) != srs_success) {
|
||||
return srs_error_wrap(err, "RTSP: fetch source failed");
|
||||
}
|
||||
|
||||
|
|
@ -101,12 +120,12 @@ srs_error_t SrsRtspPlayStream::initialize(ISrsRequest *req, std::map<uint32_t, S
|
|||
SrsRtcTrackDescription *desc = it->second;
|
||||
|
||||
if (desc->type_ == "audio") {
|
||||
SrsRtspAudioSendTrack *track = new SrsRtspAudioSendTrack(session_, desc);
|
||||
ISrsRtspSendTrack *track = app_factory_->create_rtsp_audio_send_track(session_, desc);
|
||||
audio_tracks_.insert(make_pair(ssrc, track));
|
||||
}
|
||||
|
||||
if (desc->type_ == "video") {
|
||||
SrsRtspVideoSendTrack *track = new SrsRtspVideoSendTrack(session_, desc);
|
||||
ISrsRtspSendTrack *track = app_factory_->create_rtsp_video_send_track(session_, desc);
|
||||
video_tracks_.insert(make_pair(ssrc, track));
|
||||
}
|
||||
}
|
||||
|
|
@ -125,15 +144,15 @@ void SrsRtspPlayStream::on_stream_change(SrsRtcSourceDescription *desc)
|
|||
if (desc && desc->audio_track_desc_ && audio_tracks_.size() == 1) {
|
||||
if (!audio_tracks_.empty()) {
|
||||
uint32_t ssrc = desc->audio_track_desc_->ssrc_;
|
||||
SrsRtspAudioSendTrack *track = audio_tracks_.begin()->second;
|
||||
ISrsRtspSendTrack *track = audio_tracks_.begin()->second;
|
||||
|
||||
if (track->track_desc_->media_->pt_of_publisher_ != desc->audio_track_desc_->media_->pt_) {
|
||||
track->track_desc_->media_->pt_of_publisher_ = desc->audio_track_desc_->media_->pt_;
|
||||
if (track->track_desc()->media_->pt_of_publisher_ != desc->audio_track_desc_->media_->pt_) {
|
||||
track->track_desc()->media_->pt_of_publisher_ = desc->audio_track_desc_->media_->pt_;
|
||||
}
|
||||
|
||||
if (desc->audio_track_desc_->red_ && track->track_desc_->red_ &&
|
||||
track->track_desc_->red_->pt_of_publisher_ != desc->audio_track_desc_->red_->pt_) {
|
||||
track->track_desc_->red_->pt_of_publisher_ = desc->audio_track_desc_->red_->pt_;
|
||||
if (desc->audio_track_desc_->red_ && track->track_desc()->red_ &&
|
||||
track->track_desc()->red_->pt_of_publisher_ != desc->audio_track_desc_->red_->pt_) {
|
||||
track->track_desc()->red_->pt_of_publisher_ = desc->audio_track_desc_->red_->pt_;
|
||||
}
|
||||
|
||||
audio_tracks_.clear();
|
||||
|
|
@ -147,15 +166,15 @@ void SrsRtspPlayStream::on_stream_change(SrsRtcSourceDescription *desc)
|
|||
if (!video_tracks_.empty()) {
|
||||
SrsRtcTrackDescription *vdesc = desc->video_track_descs_.at(0);
|
||||
uint32_t ssrc = vdesc->ssrc_;
|
||||
SrsRtspVideoSendTrack *track = video_tracks_.begin()->second;
|
||||
ISrsRtspSendTrack *track = video_tracks_.begin()->second;
|
||||
|
||||
if (track->track_desc_->media_->pt_of_publisher_ != vdesc->media_->pt_) {
|
||||
track->track_desc_->media_->pt_of_publisher_ = vdesc->media_->pt_;
|
||||
if (track->track_desc()->media_->pt_of_publisher_ != vdesc->media_->pt_) {
|
||||
track->track_desc()->media_->pt_of_publisher_ = vdesc->media_->pt_;
|
||||
}
|
||||
|
||||
if (vdesc->red_ && track->track_desc_->red_ &&
|
||||
track->track_desc_->red_->pt_of_publisher_ != vdesc->red_->pt_) {
|
||||
track->track_desc_->red_->pt_of_publisher_ = vdesc->red_->pt_;
|
||||
if (vdesc->red_ && track->track_desc()->red_ &&
|
||||
track->track_desc()->red_->pt_of_publisher_ != vdesc->red_->pt_) {
|
||||
track->track_desc()->red_->pt_of_publisher_ = vdesc->red_->pt_;
|
||||
}
|
||||
|
||||
video_tracks_.clear();
|
||||
|
|
@ -267,7 +286,7 @@ srs_error_t SrsRtspPlayStream::send_packet(SrsRtpPacket *&pkt)
|
|||
uint32_t ssrc = pkt->header_.get_ssrc();
|
||||
|
||||
// Try to find track from cache.
|
||||
SrsRtspSendTrack *track = NULL;
|
||||
ISrsRtspSendTrack *track = NULL;
|
||||
if (cache_ssrc0_ == ssrc) {
|
||||
track = cache_track0_;
|
||||
} else if (cache_ssrc1_ == ssrc) {
|
||||
|
|
@ -279,12 +298,12 @@ srs_error_t SrsRtspPlayStream::send_packet(SrsRtpPacket *&pkt)
|
|||
// Find by original tracks and build fast cache.
|
||||
if (!track) {
|
||||
if (pkt->is_audio()) {
|
||||
map<uint32_t, SrsRtspAudioSendTrack *>::iterator it = audio_tracks_.find(ssrc);
|
||||
map<uint32_t, ISrsRtspSendTrack *>::iterator it = audio_tracks_.find(ssrc);
|
||||
if (it != audio_tracks_.end()) {
|
||||
track = it->second;
|
||||
}
|
||||
} else {
|
||||
map<uint32_t, SrsRtspVideoSendTrack *>::iterator it = video_tracks_.find(ssrc);
|
||||
map<uint32_t, ISrsRtspSendTrack *>::iterator it = video_tracks_.find(ssrc);
|
||||
if (it != video_tracks_.end()) {
|
||||
track = it->second;
|
||||
}
|
||||
|
|
@ -324,9 +343,9 @@ void SrsRtspPlayStream::set_all_tracks_status(bool status)
|
|||
|
||||
// set video track status
|
||||
if (true) {
|
||||
std::map<uint32_t, SrsRtspVideoSendTrack *>::iterator it;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *>::iterator it;
|
||||
for (it = video_tracks_.begin(); it != video_tracks_.end(); ++it) {
|
||||
SrsRtspVideoSendTrack *track = it->second;
|
||||
ISrsRtspSendTrack *track = it->second;
|
||||
|
||||
bool previous = track->set_track_status(status);
|
||||
merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},";
|
||||
|
|
@ -335,9 +354,9 @@ void SrsRtspPlayStream::set_all_tracks_status(bool status)
|
|||
|
||||
// set audio track status
|
||||
if (true) {
|
||||
std::map<uint32_t, SrsRtspAudioSendTrack *>::iterator it;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *>::iterator it;
|
||||
for (it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) {
|
||||
SrsRtspAudioSendTrack *track = it->second;
|
||||
ISrsRtspSendTrack *track = it->second;
|
||||
|
||||
bool previous = track->set_track_status(status);
|
||||
merged_log << "{track: " << track->get_track_id() << ", is_active: " << previous << "=>" << status << "},";
|
||||
|
|
@ -347,6 +366,14 @@ void SrsRtspPlayStream::set_all_tracks_status(bool status)
|
|||
srs_trace("RTSP: Init tracks %s ok", merged_log.str().c_str());
|
||||
}
|
||||
|
||||
ISrsRtspConnection::ISrsRtspConnection()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtspConnection::~ISrsRtspConnection()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtspConnection::SrsRtspConnection(ISrsResourceManager *cm, ISrsProtocolReadWriter *skt, std::string cip, int port)
|
||||
{
|
||||
manager_ = cm;
|
||||
|
|
@ -378,12 +405,21 @@ SrsRtspConnection::SrsRtspConnection(ISrsResourceManager *cm, ISrsProtocolReadWr
|
|||
delta_ = new SrsEphemeralDelta();
|
||||
security_ = new SrsSecurity();
|
||||
|
||||
_srs_rtsp_manager->subscribe(this);
|
||||
rtsp_manager_ = _srs_rtsp_manager;
|
||||
stat_ = _srs_stat;
|
||||
config_ = _srs_config;
|
||||
rtsp_sources_ = _srs_rtsp_sources;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
void SrsRtspConnection::assemble()
|
||||
{
|
||||
rtsp_manager_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsRtspConnection::~SrsRtspConnection()
|
||||
{
|
||||
_srs_rtsp_manager->unsubscribe(this);
|
||||
rtsp_manager_->unsubscribe(this);
|
||||
|
||||
srs_freep(request_);
|
||||
srs_freep(rtsp_);
|
||||
|
|
@ -410,6 +446,12 @@ SrsRtspConnection::~SrsRtspConnection()
|
|||
srs_freep(cache_iov_);
|
||||
}
|
||||
srs_freep(cache_buffer_);
|
||||
|
||||
rtsp_manager_ = NULL;
|
||||
stat_ = NULL;
|
||||
config_ = NULL;
|
||||
rtsp_sources_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConnection::do_send_packet(SrsRtpPacket *pkt)
|
||||
|
|
@ -487,8 +529,7 @@ srs_error_t SrsRtspConnection::cycle()
|
|||
err = do_cycle();
|
||||
|
||||
// Update statistic when done.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->kbps_add_delta(get_id().c_str(), delta());
|
||||
stat_->kbps_add_delta(get_id().c_str(), delta());
|
||||
|
||||
do_teardown();
|
||||
|
||||
|
|
@ -538,104 +579,116 @@ srs_error_t SrsRtspConnection::do_cycle()
|
|||
if ((err = rtsp_->recv_message(&req_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "recv message");
|
||||
}
|
||||
SrsUniquePtr<SrsRtspRequest> req(req_raw);
|
||||
|
||||
if (req->is_options()) {
|
||||
srs_trace("RTSP: OPTIONS cseq=%ld, url=%s, client=%s:%d", req->seq_, req->uri_.c_str(), ip_.c_str(), port_);
|
||||
SrsUniquePtr<SrsRtspOptionsResponse> res(new SrsRtspOptionsResponse((int)req->seq_));
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response option");
|
||||
}
|
||||
} else if (req->is_describe()) {
|
||||
// create session.
|
||||
if (session_id_.empty()) {
|
||||
SrsRand rand;
|
||||
session_id_ = rand.gen_str(8);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsRtspDescribeResponse> res(new SrsRtspDescribeResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
|
||||
std::string sdp;
|
||||
if ((err = do_describe(req.get(), sdp)) != srs_success) {
|
||||
res->status_ = SRS_CONSTS_RTSP_InternalServerError;
|
||||
if (srs_error_code(err) == ERROR_RTSP_NO_TRACK) {
|
||||
res->status_ = SRS_CONSTS_RTSP_NotFound;
|
||||
} else if (srs_error_code(err) == ERROR_SYSTEM_SECURITY_DENY) {
|
||||
res->status_ = SRS_CONSTS_RTSP_Forbidden;
|
||||
}
|
||||
srs_warn("RTSP: DESCRIBE failed: %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
res->sdp_ = sdp;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response describe");
|
||||
}
|
||||
|
||||
// Filter the \r\n to \\r\\n for JSON.
|
||||
std::string local_sdp_escaped = srs_strings_replace(sdp.c_str(), "\r\n", "\\r\\n");
|
||||
srs_trace("RTSP: DESCRIBE cseq=%ld, session=%s, sdp: %s", req->seq_, session_id_.c_str(), local_sdp_escaped.c_str());
|
||||
} else if (req->is_setup()) {
|
||||
srs_assert(req->transport_);
|
||||
|
||||
SrsUniquePtr<SrsRtspSetupResponse> res(new SrsRtspSetupResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
|
||||
uint32_t ssrc = 0;
|
||||
if ((err = do_setup(req.get(), &ssrc)) != srs_success) {
|
||||
if (srs_error_code(err) == ERROR_RTSP_TRANSPORT_NOT_SUPPORTED) {
|
||||
res->status_ = SRS_CONSTS_RTSP_UnsupportedTransport;
|
||||
srs_warn("RTSP: SETUP failed: %s", srs_error_summary(err).c_str());
|
||||
} else {
|
||||
res->status_ = SRS_CONSTS_RTSP_InternalServerError;
|
||||
srs_warn("RTSP: SETUP failed: %s", srs_error_desc(err).c_str());
|
||||
}
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
res->transport_->copy(req->transport_);
|
||||
res->session_ = session_id_;
|
||||
res->ssrc_ = srs_strconv_format_int(ssrc);
|
||||
res->client_port_min_ = req->transport_->client_port_min_;
|
||||
res->client_port_max_ = req->transport_->client_port_max_;
|
||||
// TODO: FIXME: listen local port
|
||||
res->local_port_min_ = 0;
|
||||
res->local_port_max_ = 0;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response setup");
|
||||
}
|
||||
srs_trace("RTSP: SETUP cseq=%ld, session=%s, transport=%s/%s/%s, ssrc=%u, client_port=%d-%d",
|
||||
req->seq_, session_id_.c_str(), req->transport_->transport_.c_str(), req->transport_->profile_.c_str(),
|
||||
req->transport_->lower_transport_.c_str(), ssrc, req->transport_->client_port_min_, req->transport_->client_port_max_);
|
||||
} else if (req->is_play()) {
|
||||
SrsUniquePtr<SrsRtspResponse> res(new SrsRtspResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response record");
|
||||
}
|
||||
|
||||
if ((err = do_play(req.get(), this)) != srs_success) {
|
||||
return srs_error_wrap(err, "prepare play");
|
||||
}
|
||||
srs_trace("RTSP: PLAY cseq=%ld, session=%s, streaming started", req->seq_, session_id_.c_str());
|
||||
} else if (req->is_teardown()) {
|
||||
SrsUniquePtr<SrsRtspResponse> res(new SrsRtspResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response teardown");
|
||||
}
|
||||
|
||||
if ((err = do_teardown()) != srs_success) {
|
||||
return srs_error_wrap(err, "teardown");
|
||||
}
|
||||
srs_trace("RTSP: TEARDOWN cseq=%ld, session=%s, streaming stopped", req->seq_, session_id_.c_str());
|
||||
if ((err = on_rtsp_request(req_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "on rtsp request");
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspConnection::on_rtsp_request(SrsRtspRequest *req_raw)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsUniquePtr<SrsRtspRequest> req(req_raw);
|
||||
|
||||
if (req->is_options()) {
|
||||
srs_trace("RTSP: OPTIONS cseq=%ld, url=%s, client=%s:%d", req->seq_, req->uri_.c_str(), ip_.c_str(), port_);
|
||||
SrsUniquePtr<SrsRtspOptionsResponse> res(new SrsRtspOptionsResponse((int)req->seq_));
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response option");
|
||||
}
|
||||
} else if (req->is_describe()) {
|
||||
// create session.
|
||||
if (session_id_.empty()) {
|
||||
SrsRand rand;
|
||||
session_id_ = rand.gen_str(8);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsRtspDescribeResponse> res(new SrsRtspDescribeResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
|
||||
std::string sdp;
|
||||
if ((err = do_describe(req.get(), sdp)) != srs_success) {
|
||||
res->status_ = SRS_CONSTS_RTSP_InternalServerError;
|
||||
if (srs_error_code(err) == ERROR_RTSP_NO_TRACK) {
|
||||
res->status_ = SRS_CONSTS_RTSP_NotFound;
|
||||
} else if (srs_error_code(err) == ERROR_SYSTEM_SECURITY_DENY) {
|
||||
res->status_ = SRS_CONSTS_RTSP_Forbidden;
|
||||
}
|
||||
srs_warn("RTSP: DESCRIBE failed: %s", srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
res->sdp_ = sdp;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response describe");
|
||||
}
|
||||
|
||||
// Filter the \r\n to \\r\\n for JSON.
|
||||
std::string local_sdp_escaped = srs_strings_replace(sdp.c_str(), "\r\n", "\\r\\n");
|
||||
srs_trace("RTSP: DESCRIBE cseq=%ld, session=%s, sdp: %s", req->seq_, session_id_.c_str(), local_sdp_escaped.c_str());
|
||||
} else if (req->is_setup()) {
|
||||
srs_assert(req->transport_);
|
||||
|
||||
SrsUniquePtr<SrsRtspSetupResponse> res(new SrsRtspSetupResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
|
||||
uint32_t ssrc = 0;
|
||||
if ((err = do_setup(req.get(), &ssrc)) != srs_success) {
|
||||
if (srs_error_code(err) == ERROR_RTSP_TRANSPORT_NOT_SUPPORTED) {
|
||||
res->status_ = SRS_CONSTS_RTSP_UnsupportedTransport;
|
||||
srs_warn("RTSP: SETUP failed: %s", srs_error_summary(err).c_str());
|
||||
} else {
|
||||
res->status_ = SRS_CONSTS_RTSP_InternalServerError;
|
||||
srs_warn("RTSP: SETUP failed: %s", srs_error_desc(err).c_str());
|
||||
}
|
||||
srs_freep(err);
|
||||
}
|
||||
|
||||
res->transport_->copy(req->transport_);
|
||||
res->session_ = session_id_;
|
||||
res->ssrc_ = srs_strconv_format_int(ssrc);
|
||||
res->client_port_min_ = req->transport_->client_port_min_;
|
||||
res->client_port_max_ = req->transport_->client_port_max_;
|
||||
// TODO: FIXME: listen local port
|
||||
res->local_port_min_ = 0;
|
||||
res->local_port_max_ = 0;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response setup");
|
||||
}
|
||||
srs_trace("RTSP: SETUP cseq=%ld, session=%s, transport=%s/%s/%s, ssrc=%u, client_port=%d-%d",
|
||||
req->seq_, session_id_.c_str(), req->transport_->transport_.c_str(), req->transport_->profile_.c_str(),
|
||||
req->transport_->lower_transport_.c_str(), ssrc, req->transport_->client_port_min_, req->transport_->client_port_max_);
|
||||
} else if (req->is_play()) {
|
||||
SrsUniquePtr<SrsRtspResponse> res(new SrsRtspResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response record");
|
||||
}
|
||||
|
||||
if ((err = do_play(req.get(), this)) != srs_success) {
|
||||
return srs_error_wrap(err, "prepare play");
|
||||
}
|
||||
srs_trace("RTSP: PLAY cseq=%ld, session=%s, streaming started", req->seq_, session_id_.c_str());
|
||||
} else if (req->is_teardown()) {
|
||||
SrsUniquePtr<SrsRtspResponse> res(new SrsRtspResponse((int)req->seq_));
|
||||
res->session_ = session_id_;
|
||||
if ((err = rtsp_->send_message(res.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "response teardown");
|
||||
}
|
||||
|
||||
if ((err = do_teardown()) != srs_success) {
|
||||
return srs_error_wrap(err, "teardown");
|
||||
}
|
||||
srs_trace("RTSP: TEARDOWN cseq=%ld, session=%s, streaming stopped", req->seq_, session_id_.c_str());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void SrsRtspConnection::on_before_dispose(ISrsResource *c)
|
||||
{
|
||||
if (disposing_) {
|
||||
|
|
@ -690,7 +743,7 @@ srs_error_t SrsRtspConnection::do_describe(SrsRtspRequest *req, std::string &sdp
|
|||
request_->app_, request_->stream_, request_->port_, request_->param_);
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(request_->vhost_);
|
||||
SrsConfDirective *parsed_vhost = config_->get_vhost(request_->vhost_);
|
||||
if (parsed_vhost) {
|
||||
request_->vhost_ = parsed_vhost->arg0();
|
||||
}
|
||||
|
|
@ -703,7 +756,7 @@ srs_error_t SrsRtspConnection::do_describe(SrsRtspRequest *req, std::string &sdp
|
|||
return srs_error_wrap(err, "RTSP: http_hooks_on_play");
|
||||
}
|
||||
|
||||
if ((err = _srs_rtsp_sources->fetch_or_create(request_, source_)) != srs_success) {
|
||||
if ((err = rtsp_sources_->fetch_or_create(request_, source_)) != srs_success) {
|
||||
return srs_error_wrap(err, "create source");
|
||||
}
|
||||
|
||||
|
|
@ -855,7 +908,7 @@ srs_error_t SrsRtspConnection::http_hooks_on_play(ISrsRequest *req)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -865,7 +918,7 @@ srs_error_t SrsRtspConnection::http_hooks_on_play(ISrsRequest *req)
|
|||
std::vector<std::string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_play(req->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_play(req->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -876,7 +929,7 @@ srs_error_t SrsRtspConnection::http_hooks_on_play(ISrsRequest *req)
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_play(url, req)) != srs_success) {
|
||||
if ((err = hooks_->on_play(url, req)) != srs_success) {
|
||||
return srs_error_wrap(err, "on_play %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,37 +31,72 @@ class SrsRtspConnection;
|
|||
class SrsSecurity;
|
||||
class SrsRtspRequest;
|
||||
class SrsRtspStack;
|
||||
class ISrsRtspConnection;
|
||||
class ISrsRtspSendTrack;
|
||||
class ISrsRtspStack;
|
||||
class ISrsAppFactory;
|
||||
class ISrsEphemeralDelta;
|
||||
class ISrsSecurity;
|
||||
class ISrsStatistic;
|
||||
class ISrsRtspSourceManager;
|
||||
class ISrsHttpHooks;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// The handler for RTSP play stream.
|
||||
class ISrsRtspPlayStream
|
||||
{
|
||||
public:
|
||||
ISrsRtspPlayStream();
|
||||
virtual ~ISrsRtspPlayStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsRequest *request, std::map<uint32_t, SrsRtcTrackDescription *> sub_relations) = 0;
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
// Directly set the status of track, generally for init to set the default value.
|
||||
virtual void set_all_tracks_status(bool status) = 0;
|
||||
};
|
||||
|
||||
// A RTSP play stream, client pull and play stream from SRS.
|
||||
class SrsRtspPlayStream : public ISrsCoroutineHandler, public ISrsRtcSourceChangeCallback
|
||||
class SrsRtspPlayStream : public ISrsRtspPlayStream, public ISrsCoroutineHandler, public ISrsRtcSourceChangeCallback
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppFactory *app_factory_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsRtspSourceManager *rtsp_sources_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
ISrsCoroutine *trd_;
|
||||
SrsRtspConnection *session_;
|
||||
ISrsRtspConnection *session_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
SrsSharedPtr<SrsRtspSource> source_;
|
||||
// key: publish_ssrc, value: send track to process rtp/rtcp
|
||||
std::map<uint32_t, SrsRtspAudioSendTrack *> audio_tracks_;
|
||||
std::map<uint32_t, SrsRtspVideoSendTrack *> video_tracks_;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *> audio_tracks_;
|
||||
std::map<uint32_t, ISrsRtspSendTrack *> video_tracks_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Fast cache for tracks.
|
||||
uint32_t cache_ssrc0_;
|
||||
uint32_t cache_ssrc1_;
|
||||
uint32_t cache_ssrc2_;
|
||||
SrsRtspSendTrack *cache_track0_;
|
||||
SrsRtspSendTrack *cache_track1_;
|
||||
SrsRtspSendTrack *cache_track2_;
|
||||
ISrsRtspSendTrack *cache_track0_;
|
||||
ISrsRtspSendTrack *cache_track1_;
|
||||
ISrsRtspSendTrack *cache_track2_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Whether player started.
|
||||
bool is_started;
|
||||
|
||||
public:
|
||||
SrsRtspPlayStream(SrsRtspConnection *s, const SrsContextId &cid);
|
||||
SrsRtspPlayStream(ISrsRtspConnection *s, const SrsContextId &cid);
|
||||
virtual ~SrsRtspPlayStream();
|
||||
|
||||
public:
|
||||
|
|
@ -80,7 +115,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t send_packet(SrsRtpPacket *&pkt);
|
||||
|
||||
public:
|
||||
|
|
@ -88,12 +124,38 @@ public:
|
|||
void set_all_tracks_status(bool status);
|
||||
};
|
||||
|
||||
class SrsRtspConnection : public ISrsResource, public ISrsDisposingHandler, public ISrsExpire, public ISrsCoroutineHandler, public ISrsStartable
|
||||
// The handler for RTSP connection send packet.
|
||||
class ISrsRtspConnection : public ISrsExpire
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ISrsRtspConnection();
|
||||
virtual ~ISrsRtspConnection();
|
||||
|
||||
public:
|
||||
virtual srs_error_t do_send_packet(SrsRtpPacket *pkt) = 0;
|
||||
};
|
||||
|
||||
// A RTSP session, client request and response with RTSP.
|
||||
class SrsRtspConnection : public ISrsResource, // It's a resource.
|
||||
public ISrsDisposingHandler,
|
||||
public ISrsCoroutineHandler,
|
||||
public ISrsStartable,
|
||||
public ISrsRtspConnection
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRtspSourceManager *rtsp_sources_;
|
||||
ISrsResourceManager *rtsp_manager_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool disposing_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// TODO: FIXME: Rename it.
|
||||
// The timeout of session, keep alive by STUN ping pong.
|
||||
srs_utime_t session_timeout;
|
||||
|
|
@ -109,22 +171,23 @@ private:
|
|||
// The ip and port of client.
|
||||
std::string ip_;
|
||||
int port_;
|
||||
SrsRtspStack *rtsp_;
|
||||
ISrsRtspStack *rtsp_;
|
||||
std::string session_id_;
|
||||
SrsSharedPtr<SrsRtspSource> source_;
|
||||
SrsEphemeralDelta *delta_;
|
||||
ISrsEphemeralDelta *delta_;
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
SrsSecurity *security_;
|
||||
ISrsSecurity *security_;
|
||||
iovec *cache_iov_;
|
||||
SrsBuffer *cache_buffer_;
|
||||
// key: ssrc
|
||||
std::map<uint32_t, SrsRtcTrackDescription *> tracks_;
|
||||
// key: ssrc
|
||||
std::map<uint32_t, ISrsStreamWriter *> networks_;
|
||||
SrsRtspPlayStream *player_;
|
||||
ISrsRtspPlayStream *player_;
|
||||
|
||||
public:
|
||||
SrsRtspConnection(ISrsResourceManager *cm, ISrsProtocolReadWriter *skt, std::string cip, int port);
|
||||
void assemble(); // Construct object, to avoid call function in constructor.
|
||||
virtual ~SrsRtspConnection();
|
||||
// interface ISrsDisposingHandler
|
||||
public:
|
||||
|
|
@ -137,7 +200,8 @@ public:
|
|||
public:
|
||||
ISrsKbpsDelta *delta();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_describe(SrsRtspRequest *req, std::string &sdp);
|
||||
virtual srs_error_t do_setup(SrsRtspRequest *req, uint32_t *ssrc);
|
||||
virtual srs_error_t do_play(SrsRtspRequest *req, SrsRtspConnection *conn);
|
||||
|
|
@ -162,6 +226,12 @@ public:
|
|||
// Interface ISrsCoroutineHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_cycle();
|
||||
srs_error_t on_rtsp_request(SrsRtspRequest *req_raw);
|
||||
|
||||
// Interface ISrsExpire.
|
||||
public:
|
||||
virtual void expire();
|
||||
|
|
@ -174,17 +244,16 @@ public:
|
|||
bool is_alive();
|
||||
void alive();
|
||||
|
||||
private:
|
||||
srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t http_hooks_on_play(ISrsRequest *req);
|
||||
srs_error_t get_ssrc_by_stream_id(uint32_t stream_id, uint32_t *ssrc);
|
||||
};
|
||||
|
||||
class SrsRtspTcpNetwork : public ISrsStreamWriter
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
int channel_;
|
||||
|
||||
|
|
|
|||
|
|
@ -250,6 +250,9 @@ SrsRtspSource::SrsRtspSource()
|
|||
req_ = NULL;
|
||||
|
||||
stream_die_at_ = 0;
|
||||
|
||||
stat_ = _srs_stat;
|
||||
circuit_breaker_ = _srs_circuit_breaker;
|
||||
}
|
||||
|
||||
SrsRtspSource::~SrsRtspSource()
|
||||
|
|
@ -266,6 +269,9 @@ SrsRtspSource::~SrsRtspSource()
|
|||
if (cid.empty())
|
||||
cid = _pre_source_id;
|
||||
srs_trace("free rtc source id=[%s]", cid.c_str());
|
||||
|
||||
stat_ = NULL;
|
||||
circuit_breaker_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -437,8 +443,7 @@ srs_error_t SrsRtspSource::on_publish()
|
|||
return srs_error_wrap(err, "source id change");
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_publish(req_, _source_id.c_str());
|
||||
stat_->on_stream_publish(req_, _source_id.c_str());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -457,8 +462,7 @@ void SrsRtspSource::on_unpublish()
|
|||
}
|
||||
_source_id = SrsContextId();
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_close(req_);
|
||||
stat_->on_stream_close(req_);
|
||||
|
||||
// Destroy and cleanup source when no publishers and consumers.
|
||||
if (consumers_.empty()) {
|
||||
|
|
@ -475,7 +479,7 @@ srs_error_t SrsRtspSource::on_rtp(SrsRtpPacket *pkt)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// If circuit-breaker is dying, drop packet.
|
||||
if (_srs_circuit_breaker->hybrid_dying_water_level()) {
|
||||
if (circuit_breaker_->hybrid_dying_water_level()) {
|
||||
_srs_pps_aloss2->sugar_ += (int64_t)consumers_.size();
|
||||
return err;
|
||||
}
|
||||
|
|
@ -531,6 +535,8 @@ SrsRtspRtpBuilder::SrsRtspRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr<SrsRtsp
|
|||
// Lazy initialization flags
|
||||
audio_initialized_ = false;
|
||||
video_initialized_ = false;
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsRtspRtpBuilder::~SrsRtspRtpBuilder()
|
||||
|
|
@ -538,6 +544,8 @@ SrsRtspRtpBuilder::~SrsRtspRtpBuilder()
|
|||
srs_freep(format_);
|
||||
srs_freep(meta_);
|
||||
srs_freep(video_builder_);
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtspRtpBuilder::initialize_audio_track(SrsAudioCodecId codec)
|
||||
|
|
@ -679,7 +687,7 @@ srs_error_t SrsRtspRtpBuilder::initialize(ISrsRequest *r)
|
|||
}
|
||||
|
||||
// Setup the SPS/PPS parsing strategy.
|
||||
format_->try_annexb_first_ = _srs_config->try_annexb_first(r->vhost_);
|
||||
format_->try_annexb_first_ = config_->try_annexb_first(r->vhost_);
|
||||
|
||||
srs_trace("RTSP bridge from RTMP, try_annexb_first=%d", format_->try_annexb_first_);
|
||||
|
||||
|
|
@ -997,7 +1005,15 @@ srs_error_t SrsRtspRtpBuilder::consume_packets(vector<SrsRtpPacket *> &pkts)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtspSendTrack::SrsRtspSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio)
|
||||
ISrsRtspSendTrack::ISrsRtspSendTrack()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtspSendTrack::~ISrsRtspSendTrack()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtspSendTrack::SrsRtspSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio)
|
||||
{
|
||||
session_ = session;
|
||||
track_desc_ = track_desc->copy();
|
||||
|
|
@ -1031,7 +1047,12 @@ std::string SrsRtspSendTrack::get_track_id()
|
|||
return track_desc_->id_;
|
||||
}
|
||||
|
||||
SrsRtspAudioSendTrack::SrsRtspAudioSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
SrsRtcTrackDescription *SrsRtspSendTrack::track_desc()
|
||||
{
|
||||
return track_desc_;
|
||||
}
|
||||
|
||||
SrsRtspAudioSendTrack::SrsRtspAudioSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
: SrsRtspSendTrack(session, track_desc, true)
|
||||
{
|
||||
}
|
||||
|
|
@ -1071,7 +1092,7 @@ srs_error_t SrsRtspAudioSendTrack::on_rtp(SrsRtpPacket *pkt)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtspVideoSendTrack::SrsRtspVideoSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
SrsRtspVideoSendTrack::SrsRtspVideoSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
: SrsRtspSendTrack(session, track_desc, false)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,15 +26,21 @@ class SrsRtcSourceDescription;
|
|||
class SrsResourceManager;
|
||||
class SrsRtspConnection;
|
||||
class SrsRtpVideoBuilder;
|
||||
class ISrsStatistic;
|
||||
class ISrsCircuitBreaker;
|
||||
class ISrsAppConfig;
|
||||
class ISrsRtspConnection;
|
||||
|
||||
// The RTSP stream consumer, consume packets from RTSP stream source.
|
||||
class SrsRtspConsumer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsRtspSource *source_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<SrsRtpPacket *> queue_;
|
||||
// when source id changed, notice all consumers
|
||||
bool should_update_source_id_;
|
||||
|
|
@ -43,7 +49,8 @@ private:
|
|||
bool mw_waiting_;
|
||||
int mw_min_msgs_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The callback for stream change event.
|
||||
ISrsRtcSourceChangeCallback *handler_;
|
||||
|
||||
|
|
@ -83,7 +90,8 @@ public:
|
|||
// The RTSP source manager.
|
||||
class SrsRtspSourceManager : public ISrsHourGlassHandler, public ISrsRtspSourceManager
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_mutex_t lock_;
|
||||
std::map<std::string, SrsSharedPtr<SrsRtspSource> > pool_;
|
||||
SrsHourGlass *timer_;
|
||||
|
|
@ -95,7 +103,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
||||
|
|
@ -118,7 +127,13 @@ extern SrsResourceManager *_srs_rtsp_manager;
|
|||
// A Source is a stream, to publish and to play with, binding to SrsRtspPlayStream.
|
||||
class SrsRtspSource : public ISrsRtpTarget
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// For publish, it's the publish client id.
|
||||
// For edge, it's the edge ingest id.
|
||||
// when source id changed, for example, the edge reconnect,
|
||||
|
|
@ -131,15 +146,18 @@ private:
|
|||
SrsRtcTrackDescription *audio_desc_;
|
||||
SrsRtcTrackDescription *video_desc_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// To delivery stream to clients.
|
||||
std::vector<SrsRtspConsumer *> consumers_;
|
||||
std::vector<SrsRtspConsumer *>
|
||||
consumers_;
|
||||
// Whether stream is created, that is, SDP is done.
|
||||
bool is_created_;
|
||||
// Whether stream is delivering data, that is, DTLS is done.
|
||||
bool is_delivering_packets_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The last die time, while die means neither publishers nor players.
|
||||
srs_utime_t stream_die_at_;
|
||||
|
||||
|
|
@ -158,9 +176,11 @@ public:
|
|||
// Update the authentication information in request.
|
||||
virtual void update_auth(ISrsRequest *r);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The stream source changed.
|
||||
virtual srs_error_t on_source_changed();
|
||||
virtual srs_error_t
|
||||
on_source_changed();
|
||||
|
||||
public:
|
||||
// Get current source id.
|
||||
|
|
@ -201,7 +221,12 @@ public:
|
|||
// Convert AV frame to RTSP RTP packets.
|
||||
class SrsRtspRtpBuilder
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
ISrsRtpTarget *rtp_target_;
|
||||
// The format, codec information.
|
||||
|
|
@ -211,13 +236,15 @@ private:
|
|||
// The video builder, convert frame to RTP packets.
|
||||
SrsRtpVideoBuilder *video_builder_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
uint16_t audio_sequence_;
|
||||
uint32_t audio_ssrc_;
|
||||
uint8_t audio_payload_type_;
|
||||
int audio_sample_rate_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsSharedPtr<SrsRtspSource> source_;
|
||||
// Lazy initialization flags
|
||||
bool audio_initialized_;
|
||||
|
|
@ -227,9 +254,11 @@ public:
|
|||
SrsRtspRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr<SrsRtspSource> source);
|
||||
virtual ~SrsRtspRtpBuilder();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Lazy initialization methods
|
||||
srs_error_t initialize_audio_track(SrsAudioCodecId codec);
|
||||
srs_error_t
|
||||
initialize_audio_track(SrsAudioCodecId codec);
|
||||
srs_error_t initialize_video_track(SrsVideoCodecId codec);
|
||||
|
||||
public:
|
||||
|
|
@ -238,16 +267,20 @@ public:
|
|||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_frame(SrsMediaPacket *frame);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t package_aac(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t on_video(SrsMediaPacket *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, std::vector<SrsNaluSample *> &samples);
|
||||
srs_error_t package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt);
|
||||
srs_error_t package_nalus(SrsMediaPacket *msg, const std::vector<SrsNaluSample *> &samples, std::vector<SrsRtpPacket *> &pkts);
|
||||
|
|
@ -256,18 +289,32 @@ private:
|
|||
srs_error_t consume_packets(std::vector<SrsRtpPacket *> &pkts);
|
||||
};
|
||||
|
||||
class SrsRtspSendTrack
|
||||
class ISrsRtspSendTrack
|
||||
{
|
||||
public:
|
||||
ISrsRtspSendTrack();
|
||||
virtual ~ISrsRtspSendTrack();
|
||||
|
||||
public:
|
||||
virtual bool set_track_status(bool active) = 0;
|
||||
virtual std::string get_track_id() = 0;
|
||||
virtual SrsRtcTrackDescription *track_desc() = 0;
|
||||
virtual srs_error_t on_rtp(SrsRtpPacket *pkt) = 0;
|
||||
};
|
||||
|
||||
class SrsRtspSendTrack : public ISrsRtspSendTrack
|
||||
{
|
||||
public:
|
||||
// send track description
|
||||
SrsRtcTrackDescription *track_desc_;
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
// The owner connection for this track.
|
||||
SrsRtspConnection *session_;
|
||||
ISrsRtspConnection *session_;
|
||||
|
||||
public:
|
||||
SrsRtspSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio);
|
||||
SrsRtspSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio);
|
||||
virtual ~SrsRtspSendTrack();
|
||||
|
||||
public:
|
||||
|
|
@ -276,15 +323,13 @@ public:
|
|||
bool set_track_status(bool active);
|
||||
bool get_track_status();
|
||||
std::string get_track_id();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_rtp(SrsRtpPacket *pkt) = 0;
|
||||
virtual SrsRtcTrackDescription *track_desc();
|
||||
};
|
||||
|
||||
class SrsRtspAudioSendTrack : public SrsRtspSendTrack
|
||||
{
|
||||
public:
|
||||
SrsRtspAudioSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
SrsRtspAudioSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
virtual ~SrsRtspAudioSendTrack();
|
||||
|
||||
public:
|
||||
|
|
@ -294,7 +339,7 @@ public:
|
|||
class SrsRtspVideoSendTrack : public SrsRtspSendTrack
|
||||
{
|
||||
public:
|
||||
SrsRtspVideoSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
SrsRtspVideoSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
virtual ~SrsRtspVideoSendTrack();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ public:
|
|||
// @param req the request object of client.
|
||||
virtual srs_error_t check(SrsRtmpConnType type, std::string ip, ISrsRequest *req);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip, ISrsRequest *req);
|
||||
virtual srs_error_t allow_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip);
|
||||
virtual srs_error_t deny_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip);
|
||||
|
|
|
|||
|
|
@ -78,15 +78,11 @@ extern std::string _srs_reload_id;
|
|||
extern SrsRtcBlackhole *_srs_blackhole;
|
||||
extern SrsDtlsCertificate *_srs_rtc_dtls_certificate;
|
||||
|
||||
bool _srs_global_initialized = false;
|
||||
srs_error_t srs_global_initialize()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Root global objects.
|
||||
_srs_log = new SrsFileLog();
|
||||
_srs_context = new SrsThreadContext();
|
||||
_srs_config = new SrsConfig();
|
||||
|
||||
// Initialize the global kbps statistics variables
|
||||
if ((err = srs_global_kbps_initialize()) != srs_success) {
|
||||
return srs_error_wrap(err, "global kbps initialize");
|
||||
|
|
@ -108,6 +104,10 @@ srs_error_t srs_global_initialize()
|
|||
_srs_stages = new SrsStageManager();
|
||||
_srs_sources = new SrsLiveSourceManager();
|
||||
_srs_circuit_breaker = new SrsCircuitBreaker();
|
||||
|
||||
// Initialize global statistic instance before _srs_hooks, as SrsHttpHooks depends on it.
|
||||
_srs_stat = new SrsStatistic();
|
||||
|
||||
_srs_hooks = new SrsHttpHooks();
|
||||
|
||||
_srs_srt_sources = new SrsSrtSourceManager();
|
||||
|
|
@ -136,12 +136,36 @@ srs_error_t srs_global_initialize()
|
|||
SrsRand rand;
|
||||
_srs_reload_id = rand.gen_str(7);
|
||||
|
||||
// Initialize global statistic instance.
|
||||
_srs_stat = new SrsStatistic();
|
||||
// Global initialization done
|
||||
_srs_global_initialized = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
ISrsSignalHandler::ISrsSignalHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsSignalHandler::~ISrsSignalHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsApiServerOwner::ISrsApiServerOwner()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsApiServerOwner::~ISrsApiServerOwner()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcApiServer::ISrsRtcApiServer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcApiServer::~ISrsRtcApiServer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsServer::SrsServer()
|
||||
{
|
||||
signal_reload_ = false;
|
||||
|
|
@ -262,7 +286,9 @@ SrsServer::~SrsServer()
|
|||
circuit_breaker_ = NULL;
|
||||
srt_sources_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
#ifdef SRS_RTSP
|
||||
rtsp_sources_ = NULL;
|
||||
#endif
|
||||
#ifdef SRS_GB28181
|
||||
gb_manager_ = NULL;
|
||||
#endif
|
||||
|
|
@ -355,7 +381,7 @@ void SrsServer::gracefully_dispose()
|
|||
srs_trace("final wait for %dms", srsu2msi(config_->get_grace_final_wait()));
|
||||
}
|
||||
|
||||
ISrsHttpServeMux *SrsServer::api_server()
|
||||
ISrsCommonHttpHandler *SrsServer::api_server()
|
||||
{
|
||||
return http_api_mux_;
|
||||
}
|
||||
|
|
@ -674,7 +700,8 @@ srs_error_t SrsServer::listen()
|
|||
|
||||
// Create exporter server listener.
|
||||
if (config_->get_exporter_enabled()) {
|
||||
exporter_listener_->set_endpoint(config_->get_exporter_listen())->set_label("Exporter-Server");
|
||||
exporter_listener_->set_endpoint(config_->get_exporter_listen());
|
||||
exporter_listener_->set_label("Exporter-Server");
|
||||
if ((err = exporter_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "exporter server listen");
|
||||
}
|
||||
|
|
@ -758,9 +785,13 @@ srs_error_t SrsServer::http_handle()
|
|||
if ((err = http_api_mux_->handle("/api/v1/clients/", new SrsGoApiClients())) != srs_success) {
|
||||
return srs_error_wrap(err, "handle clients");
|
||||
}
|
||||
if ((err = http_api_mux_->handle("/api/v1/raw", new SrsGoApiRaw(this))) != srs_success) {
|
||||
|
||||
SrsGoApiRaw *raw_api = new SrsGoApiRaw(this);
|
||||
raw_api->assemble();
|
||||
if ((err = http_api_mux_->handle("/api/v1/raw", raw_api)) != srs_success) {
|
||||
return srs_error_wrap(err, "handle raw");
|
||||
}
|
||||
|
||||
if ((err = http_api_mux_->handle("/api/v1/clusters", new SrsGoApiClusters())) != srs_success) {
|
||||
return srs_error_wrap(err, "handle clusters");
|
||||
}
|
||||
|
|
@ -805,7 +836,9 @@ srs_error_t SrsServer::http_handle()
|
|||
#endif
|
||||
|
||||
// metrics by prometheus
|
||||
if ((err = http_api_mux_->handle("/metrics", new SrsGoApiMetrics())) != srs_success) {
|
||||
SrsGoApiMetrics *metrics = new SrsGoApiMetrics();
|
||||
metrics->assemble();
|
||||
if ((err = http_api_mux_->handle("/metrics", metrics)) != srs_success) {
|
||||
return srs_error_wrap(err, "handle tests errors");
|
||||
}
|
||||
|
||||
|
|
@ -1038,6 +1071,12 @@ srs_error_t SrsServer::do_cycle()
|
|||
return srs_error_wrap(err, "cycle");
|
||||
}
|
||||
|
||||
// Break the loop when quit signals are set, otherwise we loop forever
|
||||
// printing "cleanup for quit signal" every second.
|
||||
if (signal_fast_quit_ || signal_gracefully_quit_) {
|
||||
break;
|
||||
}
|
||||
|
||||
srs_usleep(1 * SRS_UTIME_SECONDS);
|
||||
}
|
||||
|
||||
|
|
@ -1337,7 +1376,7 @@ srs_error_t SrsServer::listen_rtc_udp()
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsServer::on_udp_packet(SrsUdpMuxSocket *skt)
|
||||
srs_error_t SrsServer::on_udp_packet(ISrsUdpMuxSocket *skt)
|
||||
{
|
||||
return rtc_session_manager_->on_udp_packet(skt);
|
||||
}
|
||||
|
|
@ -1378,12 +1417,12 @@ srs_error_t SrsServer::listen_rtc_api()
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtcConnection *SrsServer::find_rtc_session_by_username(const std::string &username)
|
||||
ISrsRtcConnection *SrsServer::find_rtc_session_by_username(const std::string &username)
|
||||
{
|
||||
return rtc_session_manager_->find_rtc_session_by_username(username);
|
||||
}
|
||||
|
||||
srs_error_t SrsServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t SrsServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -1527,7 +1566,9 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stf
|
|||
resource = new SrsRtcTcpConn(new SrsTcpConnection(stfd2), ip, port);
|
||||
#ifdef SRS_RTSP
|
||||
} else if (listener == rtsp_listener_) {
|
||||
resource = new SrsRtspConnection(conn_manager_, new SrsTcpConnection(stfd2), ip, port);
|
||||
SrsRtspConnection *conn = new SrsRtspConnection(conn_manager_, new SrsTcpConnection(stfd2), ip, port);
|
||||
conn->assemble();
|
||||
resource = conn;
|
||||
#endif
|
||||
} else if (listener == exporter_listener_) {
|
||||
// TODO: FIXME: Maybe should support https metrics.
|
||||
|
|
@ -1542,7 +1583,7 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stf
|
|||
// For RTC TCP connection, use resource executor to manage the resource.
|
||||
SrsRtcTcpConn *raw_conn = dynamic_cast<SrsRtcTcpConn *>(resource);
|
||||
if (raw_conn) {
|
||||
SrsSharedResource<SrsRtcTcpConn> *conn = new SrsSharedResource<SrsRtcTcpConn>(raw_conn);
|
||||
SrsSharedResource<ISrsRtcTcpConn> *conn = new SrsSharedResource<ISrsRtcTcpConn>(raw_conn);
|
||||
SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(conn_manager_, conn, raw_conn, raw_conn);
|
||||
raw_conn->setup_owner(conn, executor, executor);
|
||||
if ((err = executor->start()) != srs_success) {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class SrsRtcConnection;
|
|||
class ISrsAsyncCallTask;
|
||||
class SrsSignalManager;
|
||||
class SrsServer;
|
||||
class ISrsHttpServeMux;
|
||||
class ISrsCommonHttpHandler;
|
||||
class SrsHttpServer;
|
||||
class SrsIngester;
|
||||
class SrsHttpHeartbeat;
|
||||
|
|
@ -68,11 +68,47 @@ class ISrsRtspSourceManager;
|
|||
class ISrsLog;
|
||||
class ISrsStatistic;
|
||||
class ISrsHourGlass;
|
||||
class SrsAppFactory;
|
||||
class ISrsAppFactory;
|
||||
class ISrsUdpMuxSocket;
|
||||
class ISrsRtcConnection;
|
||||
|
||||
// Initialize global shared variables cross all threads.
|
||||
extern srs_error_t srs_global_initialize();
|
||||
|
||||
// The signal handler interface.
|
||||
class ISrsSignalHandler
|
||||
{
|
||||
public:
|
||||
ISrsSignalHandler();
|
||||
virtual ~ISrsSignalHandler();
|
||||
|
||||
public:
|
||||
virtual void on_signal(int signo) = 0;
|
||||
};
|
||||
|
||||
// The API server owner interface.
|
||||
class ISrsApiServerOwner
|
||||
{
|
||||
public:
|
||||
ISrsApiServerOwner();
|
||||
virtual ~ISrsApiServerOwner();
|
||||
|
||||
public:
|
||||
virtual ISrsCommonHttpHandler *api_server() = 0;
|
||||
};
|
||||
|
||||
// The RTC API server owner interface.
|
||||
class ISrsRtcApiServer
|
||||
{
|
||||
public:
|
||||
ISrsRtcApiServer();
|
||||
virtual ~ISrsRtcApiServer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession) = 0;
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag) = 0;
|
||||
};
|
||||
|
||||
// SrsServer is the main server class of SRS (Simple Realtime Server) that provides comprehensive
|
||||
// streaming media server functionality. It serves as the central orchestrator for all streaming
|
||||
// protocols and services in a single-threaded, coroutine-based architecture.
|
||||
|
|
@ -81,9 +117,13 @@ class SrsServer : public ISrsReloadHandler, // Reload framework for permormance
|
|||
public ISrsTcpHandler,
|
||||
public ISrsHourGlassHandler,
|
||||
public ISrsSrtClientHandler,
|
||||
public ISrsUdpMuxHandler
|
||||
public ISrsUdpMuxHandler,
|
||||
public ISrsSignalHandler,
|
||||
public ISrsApiServerOwner,
|
||||
public ISrsRtcApiServer
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsResourceManager *conn_manager_;
|
||||
|
|
@ -92,28 +132,34 @@ private:
|
|||
ISrsCircuitBreaker *circuit_breaker_;
|
||||
ISrsSrtSourceManager *srt_sources_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
#ifdef SRS_RTSP
|
||||
ISrsRtspSourceManager *rtsp_sources_;
|
||||
#endif
|
||||
#ifdef SRS_GB28181
|
||||
ISrsResourceManager *gb_manager_;
|
||||
#endif
|
||||
ISrsLog *log_;
|
||||
ISrsStatistic *stat_;
|
||||
SrsAppFactory *app_factory_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
ISrsHttpServeMux *http_api_mux_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCommonHttpHandler *http_api_mux_;
|
||||
SrsHttpServer *http_server_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsHttpHeartbeat *http_heartbeat_;
|
||||
SrsIngester *ingester_;
|
||||
ISrsHourGlass *timer_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// PID file manager for process identification and locking.
|
||||
SrsPidFileLocker *pid_file_locker_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// If reusing, HTTP API use the same port of HTTP server.
|
||||
bool reuse_api_over_server_;
|
||||
// If reusing, WebRTC TCP use the same port of HTTP server.
|
||||
|
|
@ -150,17 +196,22 @@ private:
|
|||
SrsGbListener *stream_caster_gb28181_;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// SRT acceptors for MPEG-TS over SRT.
|
||||
std::vector<SrsSrtAcceptor *> srt_acceptors_;
|
||||
std::vector<SrsSrtAcceptor *>
|
||||
srt_acceptors_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// WebRTC UDP listeners for RTC server functionality.
|
||||
std::vector<SrsUdpMuxListener *> rtc_listeners_;
|
||||
std::vector<SrsUdpMuxListener *>
|
||||
rtc_listeners_;
|
||||
// WebRTC session manager.
|
||||
SrsRtcSessionManager *rtc_session_manager_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Signal manager which convert gignal to io message.
|
||||
SrsSignalManager *signal_manager_;
|
||||
// To query the latest available version of SRS.
|
||||
|
|
@ -178,17 +229,19 @@ public:
|
|||
SrsServer();
|
||||
virtual ~SrsServer();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// When SIGTERM, SRS should do cleanup, for example,
|
||||
// to stop all ingesters, cleanup HLS and dvr.
|
||||
virtual void dispose();
|
||||
virtual void
|
||||
dispose();
|
||||
// Close listener to stop accepting new connections,
|
||||
// then wait and quit when all connections finished.
|
||||
virtual void gracefully_dispose();
|
||||
|
||||
public:
|
||||
// Get the HTTP API server mux.
|
||||
ISrsHttpServeMux *api_server();
|
||||
ISrsCommonHttpHandler *api_server();
|
||||
|
||||
// server startup workflow, @see run_master()
|
||||
public:
|
||||
|
|
@ -199,7 +252,8 @@ public:
|
|||
public:
|
||||
srs_error_t run();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t initialize_st();
|
||||
virtual srs_error_t initialize_signal();
|
||||
virtual srs_error_t listen();
|
||||
|
|
@ -211,7 +265,8 @@ public:
|
|||
void stop();
|
||||
|
||||
// interface ISrsCoroutineHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
// server utilities.
|
||||
|
|
@ -231,21 +286,26 @@ public:
|
|||
// @remark, maybe the HTTP RAW API will trigger the on_signal() also.
|
||||
virtual void on_signal(int signo);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The server thread main cycle,
|
||||
// update the global static data, for instance, the current time,
|
||||
// the cpu/mem/network statistic.
|
||||
virtual srs_error_t do_cycle();
|
||||
virtual srs_error_t
|
||||
do_cycle();
|
||||
virtual srs_error_t do2_cycle();
|
||||
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Resample the server kbs.
|
||||
virtual void resample_kbps();
|
||||
virtual void
|
||||
resample_kbps();
|
||||
|
||||
// SRT-related methods
|
||||
virtual srs_error_t listen_srt_mpegts();
|
||||
|
|
@ -253,29 +313,34 @@ private:
|
|||
virtual srs_error_t accept_srt_client(srs_srt_t srt_fd);
|
||||
virtual srs_error_t srt_fd_to_resource(srs_srt_t srt_fd, ISrsResource **pr);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// WebRTC-related methods
|
||||
virtual srs_error_t listen_rtc_udp();
|
||||
virtual srs_error_t
|
||||
listen_rtc_udp();
|
||||
|
||||
// Interface ISrsUdpMuxHandler
|
||||
public:
|
||||
virtual srs_error_t on_udp_packet(SrsUdpMuxSocket *skt);
|
||||
virtual srs_error_t on_udp_packet(ISrsUdpMuxSocket *skt);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t listen_rtc_api();
|
||||
|
||||
public:
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t srs_update_server_statistics();
|
||||
|
||||
// Interface ISrsTcpHandler
|
||||
public:
|
||||
virtual srs_error_t on_tcp_client(ISrsListener *listener, srs_netfd_t stfd);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stfd);
|
||||
virtual srs_error_t on_before_connection(const char *label, int fd, const std::string &ip, int port);
|
||||
|
||||
|
|
@ -292,13 +357,15 @@ extern SrsServer *_srs_server;
|
|||
// @see: st-1.9/docs/notes.html
|
||||
class SrsSignalManager : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Per-process pipe which is used as a signal queue.
|
||||
// Up to PIPE_BUF/sizeof(int) signals can be queued up.
|
||||
int sig_pipe_[2];
|
||||
srs_netfd_t signal_read_stfd_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsServer *server_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
|
|
@ -313,7 +380,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Global singleton instance
|
||||
static SrsSignalManager *instance;
|
||||
// Signal catching function.
|
||||
|
|
@ -325,10 +393,12 @@ private:
|
|||
// @see https://github.com/ossrs/srs/issues/1635
|
||||
class SrsInotifyWorker : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsServer *server_;
|
||||
ISrsCoroutine *trd_;
|
||||
srs_netfd_t inotify_fd_;
|
||||
|
|
@ -347,10 +417,12 @@ public:
|
|||
// PID file manager for process identification and locking.
|
||||
class SrsPidFileLocker
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int pid_fd_;
|
||||
std::string pid_file_;
|
||||
|
||||
|
|
@ -362,9 +434,11 @@ public:
|
|||
// Acquire the PID file for the whole process.
|
||||
virtual srs_error_t acquire();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Close the PID file descriptor.
|
||||
virtual void close();
|
||||
virtual void
|
||||
close();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -92,7 +92,15 @@ srs_error_t SrsSrtConnection::writev(const iovec *iov, int iov_size, ssize_t *nw
|
|||
return srs_error_new(ERROR_SRT_CONN, "unsupport method");
|
||||
}
|
||||
|
||||
SrsSrtRecvThread::SrsSrtRecvThread(SrsSrtConnection *srt_conn)
|
||||
ISrsSrtRecvThread::ISrsSrtRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsSrtRecvThread::~ISrsSrtRecvThread()
|
||||
{
|
||||
}
|
||||
|
||||
SrsSrtRecvThread::SrsSrtRecvThread(ISrsProtocolReadWriter *srt_conn)
|
||||
{
|
||||
srt_conn_ = srt_conn;
|
||||
trd_ = new SrsSTCoroutine("srt-recv", this, _srs_context->get_id());
|
||||
|
|
@ -153,6 +161,14 @@ srs_error_t SrsSrtRecvThread::get_recv_err()
|
|||
return srs_error_copy(recv_err_);
|
||||
}
|
||||
|
||||
ISrsMpegtsSrtConnection::ISrsMpegtsSrtConnection()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMpegtsSrtConnection::~ISrsMpegtsSrtConnection()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMpegtsSrtConn::SrsMpegtsSrtConn(ISrsResourceManager *resource_manager, srs_srt_t srt_fd, std::string ip, int port) : srt_source_(new SrsSrtSource())
|
||||
{
|
||||
// Create a identify for this client.
|
||||
|
|
@ -176,6 +192,14 @@ SrsMpegtsSrtConn::SrsMpegtsSrtConn(ISrsResourceManager *resource_manager, srs_sr
|
|||
req_->ip_ = ip;
|
||||
|
||||
security_ = new SrsSecurity();
|
||||
|
||||
stat_ = _srs_stat;
|
||||
config_ = _srs_config;
|
||||
stream_publish_tokens_ = _srs_stream_publish_tokens;
|
||||
srt_sources_ = _srs_srt_sources;
|
||||
live_sources_ = _srs_sources;
|
||||
rtc_sources_ = _srs_rtc_sources;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
SrsMpegtsSrtConn::~SrsMpegtsSrtConn()
|
||||
|
|
@ -187,6 +211,14 @@ SrsMpegtsSrtConn::~SrsMpegtsSrtConn()
|
|||
srs_freep(srt_conn_);
|
||||
srs_freep(req_);
|
||||
srs_freep(security_);
|
||||
|
||||
stat_ = NULL;
|
||||
config_ = NULL;
|
||||
stream_publish_tokens_ = NULL;
|
||||
srt_sources_ = NULL;
|
||||
live_sources_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
std::string SrsMpegtsSrtConn::desc()
|
||||
|
|
@ -230,9 +262,8 @@ srs_error_t SrsMpegtsSrtConn::cycle()
|
|||
srs_error_t err = do_cycle();
|
||||
|
||||
// Update statistic when done.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->kbps_add_delta(get_id().c_str(), delta_);
|
||||
stat->on_disconnect(get_id().c_str(), err);
|
||||
stat_->kbps_add_delta(get_id().c_str(), delta_);
|
||||
stat_->on_disconnect(get_id().c_str(), err);
|
||||
|
||||
// Notify manager to remove it.
|
||||
// Note that we create this object, so we use manager to remove it.
|
||||
|
|
@ -262,7 +293,7 @@ srs_error_t SrsMpegtsSrtConn::do_cycle()
|
|||
|
||||
// If streamid empty, using default streamid instead.
|
||||
if (streamid.empty()) {
|
||||
streamid = _srs_config->get_srt_default_streamid();
|
||||
streamid = config_->get_srt_default_streamid();
|
||||
srs_warn("srt get empty streamid, using default streamid %s instead", streamid.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -273,13 +304,13 @@ srs_error_t SrsMpegtsSrtConn::do_cycle()
|
|||
}
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(req_->vhost_);
|
||||
SrsConfDirective *parsed_vhost = config_->get_vhost(req_->vhost_);
|
||||
if (parsed_vhost) {
|
||||
req_->vhost_ = parsed_vhost->arg0();
|
||||
}
|
||||
|
||||
bool srt_enabled = _srs_config->get_srt_enabled(req_->vhost_);
|
||||
bool edge = _srs_config->get_vhost_is_edge(req_->vhost_);
|
||||
bool srt_enabled = config_->get_srt_enabled(req_->vhost_);
|
||||
bool edge = config_->get_vhost_is_edge(req_->vhost_);
|
||||
|
||||
if (srt_enabled && edge) {
|
||||
srt_enabled = false;
|
||||
|
|
@ -295,7 +326,7 @@ srs_error_t SrsMpegtsSrtConn::do_cycle()
|
|||
|
||||
// Acquire stream publish token to prevent race conditions across all protocols.
|
||||
SrsStreamPublishToken *publish_token_raw = NULL;
|
||||
if (mode == SrtModePush && (err = _srs_stream_publish_tokens->acquire_token(req_, publish_token_raw)) != srs_success) {
|
||||
if (mode == SrtModePush && (err = stream_publish_tokens_->acquire_token(req_, publish_token_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "acquire stream publish token");
|
||||
}
|
||||
SrsUniquePtr<SrsStreamPublishToken> publish_token(publish_token_raw);
|
||||
|
|
@ -303,7 +334,7 @@ srs_error_t SrsMpegtsSrtConn::do_cycle()
|
|||
srs_trace("stream publish token acquired, type=srt, url=%s", req_->get_stream_url().c_str());
|
||||
}
|
||||
|
||||
if ((err = _srs_srt_sources->fetch_or_create(req_, srt_source_)) != srs_success) {
|
||||
if ((err = srt_sources_->fetch_or_create(req_, srt_source_)) != srs_success) {
|
||||
return srs_error_wrap(err, "fetch srt source");
|
||||
}
|
||||
|
||||
|
|
@ -327,8 +358,7 @@ srs_error_t SrsMpegtsSrtConn::publishing()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPublish)) != srs_success) {
|
||||
if ((err = stat_->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPublish)) != srs_success) {
|
||||
return srs_error_wrap(err, "srt: stat client");
|
||||
}
|
||||
|
||||
|
|
@ -356,8 +386,7 @@ srs_error_t SrsMpegtsSrtConn::playing()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPlay)) != srs_success) {
|
||||
if ((err = stat_->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPlay)) != srs_success) {
|
||||
return srs_error_wrap(err, "srt: stat client");
|
||||
}
|
||||
|
||||
|
|
@ -387,19 +416,19 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
|
|||
}
|
||||
|
||||
// Check rtmp stream is busy.
|
||||
SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req_);
|
||||
SrsSharedPtr<SrsLiveSource> live_source = live_sources_->fetch(req_);
|
||||
if (live_source.get() && !live_source->can_publish(false)) {
|
||||
return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "live_source stream %s busy", req_->get_stream_url().c_str());
|
||||
}
|
||||
|
||||
if ((err = _srs_sources->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
if ((err = live_sources_->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
return srs_error_wrap(err, "create source");
|
||||
}
|
||||
|
||||
srs_assert(live_source.get() != NULL);
|
||||
|
||||
bool enabled_cache = _srs_config->get_gop_cache(req_->vhost_);
|
||||
int gcmf = _srs_config->get_gop_cache_max_frames(req_->vhost_);
|
||||
bool enabled_cache = config_->get_gop_cache(req_->vhost_);
|
||||
int gcmf = config_->get_gop_cache_max_frames(req_->vhost_);
|
||||
live_source->set_cache(enabled_cache);
|
||||
live_source->set_gop_cache_max_frames(gcmf);
|
||||
|
||||
|
|
@ -408,9 +437,9 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
|
|||
|
||||
// Check whether RTC stream is busy.
|
||||
SrsSharedPtr<SrsRtcSource> rtc;
|
||||
bool rtc_server_enabled = _srs_config->get_rtc_server_enabled();
|
||||
bool rtc_enabled = _srs_config->get_rtc_enabled(req_->vhost_);
|
||||
bool edge = _srs_config->get_vhost_is_edge(req_->vhost_);
|
||||
bool rtc_server_enabled = config_->get_rtc_server_enabled();
|
||||
bool rtc_enabled = config_->get_rtc_enabled(req_->vhost_);
|
||||
bool edge = config_->get_vhost_is_edge(req_->vhost_);
|
||||
|
||||
if (rtc_enabled && edge) {
|
||||
rtc_enabled = false;
|
||||
|
|
@ -418,7 +447,7 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
|
|||
}
|
||||
|
||||
if (rtc_server_enabled && rtc_enabled) {
|
||||
if ((err = _srs_rtc_sources->fetch_or_create(req_, rtc)) != srs_success) {
|
||||
if ((err = rtc_sources_->fetch_or_create(req_, rtc)) != srs_success) {
|
||||
return srs_error_wrap(err, "create source");
|
||||
}
|
||||
|
||||
|
|
@ -430,7 +459,7 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
|
|||
// Bridge to RTMP and RTC streaming.
|
||||
SrsSrtBridge *bridge = new SrsSrtBridge();
|
||||
|
||||
bool srt_to_rtmp = _srs_config->get_srt_to_rtmp(req_->vhost_);
|
||||
bool srt_to_rtmp = config_->get_srt_to_rtmp(req_->vhost_);
|
||||
if (srt_to_rtmp && edge) {
|
||||
srt_to_rtmp = false;
|
||||
srs_warn("disable SRT to RTMP for edge vhost=%s", req_->vhost_.c_str());
|
||||
|
|
@ -440,7 +469,7 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
|
|||
bridge->enable_srt2rtmp(live_source);
|
||||
}
|
||||
|
||||
bool rtmp_to_rtc = _srs_config->get_rtc_from_rtmp(req_->vhost_);
|
||||
bool rtmp_to_rtc = config_->get_rtc_from_rtmp(req_->vhost_);
|
||||
if (rtmp_to_rtc && edge) {
|
||||
rtmp_to_rtc = false;
|
||||
srs_warn("disable RTMP to WebRTC for edge vhost=%s", req_->vhost_.c_str());
|
||||
|
|
@ -524,13 +553,13 @@ srs_error_t SrsMpegtsSrtConn::do_playing()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsSrtConsumer *consumer_raw = NULL;
|
||||
ISrsSrtConsumer *consumer_raw = NULL;
|
||||
if ((err = srt_source_->create_consumer(consumer_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "create consumer, ts source=%s", req_->get_stream_url().c_str());
|
||||
}
|
||||
|
||||
srs_assert(consumer_raw);
|
||||
SrsUniquePtr<SrsSrtConsumer> consumer(consumer_raw);
|
||||
SrsUniquePtr<ISrsSrtConsumer> consumer(consumer_raw);
|
||||
|
||||
// TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames.
|
||||
if ((err = srt_source_->consumer_dumps(consumer.get())) != srs_success) {
|
||||
|
|
@ -632,7 +661,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_connect()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -642,7 +671,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_connect()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_connect(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_connect(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -653,7 +682,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_connect()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_connect(url, req_)) != srs_success) {
|
||||
if ((err = hooks_->on_connect(url, req_)) != srs_success) {
|
||||
return srs_error_wrap(err, "srt on_connect %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -663,7 +692,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_connect()
|
|||
|
||||
void SrsMpegtsSrtConn::http_hooks_on_close()
|
||||
{
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -673,7 +702,7 @@ void SrsMpegtsSrtConn::http_hooks_on_close()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_close(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_close(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return;
|
||||
|
|
@ -684,7 +713,7 @@ void SrsMpegtsSrtConn::http_hooks_on_close()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
_srs_hooks->on_close(url, req_, srt_conn_->get_send_bytes(), srt_conn_->get_recv_bytes());
|
||||
hooks_->on_close(url, req_, srt_conn_->get_send_bytes(), srt_conn_->get_recv_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +721,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_publish()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -702,7 +731,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_publish()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_publish(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_publish(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -713,7 +742,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_publish()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_publish(url, req_)) != srs_success) {
|
||||
if ((err = hooks_->on_publish(url, req_)) != srs_success) {
|
||||
return srs_error_wrap(err, "srt on_publish %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -723,7 +752,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_publish()
|
|||
|
||||
void SrsMpegtsSrtConn::http_hooks_on_unpublish()
|
||||
{
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -733,7 +762,7 @@ void SrsMpegtsSrtConn::http_hooks_on_unpublish()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_unpublish(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_unpublish(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return;
|
||||
|
|
@ -744,7 +773,7 @@ void SrsMpegtsSrtConn::http_hooks_on_unpublish()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
_srs_hooks->on_unpublish(url, req_);
|
||||
hooks_->on_unpublish(url, req_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -752,7 +781,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_play()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -762,7 +791,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_play()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_play(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_play(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -773,7 +802,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_play()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_play(url, req_)) != srs_success) {
|
||||
if ((err = hooks_->on_play(url, req_)) != srs_success) {
|
||||
return srs_error_wrap(err, "srt on_play %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -783,7 +812,7 @@ srs_error_t SrsMpegtsSrtConn::http_hooks_on_play()
|
|||
|
||||
void SrsMpegtsSrtConn::http_hooks_on_stop()
|
||||
{
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -793,7 +822,7 @@ void SrsMpegtsSrtConn::http_hooks_on_stop()
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_stop(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_stop(req_->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return;
|
||||
|
|
@ -804,7 +833,7 @@ void SrsMpegtsSrtConn::http_hooks_on_stop()
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
_srs_hooks->on_stop(url, req_);
|
||||
hooks_->on_stop(url, req_);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@ class SrsLiveSource;
|
|||
class SrsSrtSource;
|
||||
class SrsSrtServer;
|
||||
class SrsNetworkDelta;
|
||||
class ISrsNetworkDelta;
|
||||
class ISrsSrtSocket;
|
||||
class SrsNetworkKbps;
|
||||
class ISrsSecurity;
|
||||
class ISrsStatistic;
|
||||
class ISrsAppConfig;
|
||||
class ISrsStreamPublishTokenManager;
|
||||
class ISrsSrtSourceManager;
|
||||
class ISrsLiveSourceManager;
|
||||
class ISrsRtcSourceManager;
|
||||
class ISrsHttpHooks;
|
||||
|
||||
// The basic connection of SRS, for SRT based protocols,
|
||||
// all srt connections accept from srt listener must extends from this base class,
|
||||
|
|
@ -48,37 +59,75 @@ public:
|
|||
virtual srs_error_t write(void *buf, size_t size, ssize_t *nwrite);
|
||||
virtual srs_error_t writev(const iovec *iov, int iov_size, ssize_t *nwrite);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// The underlayer srt fd handler.
|
||||
srs_srt_t srt_fd_;
|
||||
// The underlayer srt socket.
|
||||
SrsSrtSocket *srt_skt_;
|
||||
ISrsSrtSocket *srt_skt_;
|
||||
};
|
||||
|
||||
class SrsSrtRecvThread : public ISrsCoroutineHandler
|
||||
// The recv thread for SRT connection.
|
||||
class ISrsSrtRecvThread : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
SrsSrtRecvThread(SrsSrtConnection *srt_conn);
|
||||
ISrsSrtRecvThread();
|
||||
virtual ~ISrsSrtRecvThread();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The recv thread for SRT connection.
|
||||
class SrsSrtRecvThread : public ISrsSrtRecvThread
|
||||
{
|
||||
public:
|
||||
SrsSrtRecvThread(ISrsProtocolReadWriter *srt_conn);
|
||||
~SrsSrtRecvThread();
|
||||
// Interface ISrsCoroutineHandler
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t do_cycle();
|
||||
|
||||
public:
|
||||
srs_error_t start();
|
||||
srs_error_t get_recv_err();
|
||||
|
||||
private:
|
||||
SrsSrtConnection *srt_conn_;
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsProtocolReadWriter *srt_conn_;
|
||||
ISrsCoroutine *trd_;
|
||||
srs_error_t recv_err_;
|
||||
};
|
||||
|
||||
class SrsMpegtsSrtConn : public ISrsConnection, public ISrsStartable, public ISrsCoroutineHandler, public ISrsExpire
|
||||
// The SRT connection, for client to publish or play stream.
|
||||
class ISrsMpegtsSrtConnection : public ISrsConnection, // It's a resource.
|
||||
public ISrsStartable,
|
||||
public ISrsCoroutineHandler,
|
||||
public ISrsExpire
|
||||
{
|
||||
public:
|
||||
ISrsMpegtsSrtConnection();
|
||||
virtual ~ISrsMpegtsSrtConnection();
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// The SRT connection, for client to publish or play stream.
|
||||
class SrsMpegtsSrtConn : public ISrsMpegtsSrtConnection
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStreamPublishTokenManager *stream_publish_tokens_;
|
||||
ISrsSrtSourceManager *srt_sources_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
public:
|
||||
SrsMpegtsSrtConn(ISrsResourceManager *resource_manager, srs_srt_t srt_fd, std::string ip, int port);
|
||||
virtual ~SrsMpegtsSrtConn();
|
||||
|
|
@ -102,10 +151,12 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
protected:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PROTECTED: // clang-format on
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t publishing();
|
||||
srs_error_t playing();
|
||||
srs_error_t acquire_publish();
|
||||
|
|
@ -113,10 +164,12 @@ private:
|
|||
srs_error_t do_publishing();
|
||||
srs_error_t do_playing();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_srt_packet(char *buf, int nb_buf);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t http_hooks_on_connect();
|
||||
void http_hooks_on_close();
|
||||
srs_error_t http_hooks_on_publish();
|
||||
|
|
@ -124,11 +177,12 @@ private:
|
|||
srs_error_t http_hooks_on_play();
|
||||
void http_hooks_on_stop();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *resource_manager_;
|
||||
srs_srt_t srt_fd_;
|
||||
SrsSrtConnection *srt_conn_;
|
||||
SrsNetworkDelta *delta_;
|
||||
ISrsProtocolReadWriter *srt_conn_;
|
||||
ISrsNetworkDelta *delta_;
|
||||
SrsNetworkKbps *kbps_;
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
@ -136,7 +190,7 @@ private:
|
|||
|
||||
ISrsRequest *req_;
|
||||
SrsSharedPtr<SrsSrtSource> srt_source_;
|
||||
SrsSecurity *security_;
|
||||
ISrsSecurity *security_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,12 +28,14 @@ public:
|
|||
// Bind and listen SRT(udp) port, use handler to process the client.
|
||||
class SrsSrtListener : public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_srt_t lfd_;
|
||||
SrsSrtSocket *srt_skt_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsSrtHandler *handler_;
|
||||
std::string ip_;
|
||||
int port_;
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@ public:
|
|||
// A common srt acceptor, for SRT server.
|
||||
class SrsSrtAcceptor : public ISrsSrtHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string ip_;
|
||||
int port_;
|
||||
ISrsSrtClientHandler *srt_handler_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsSrtListener *listener_;
|
||||
|
||||
public:
|
||||
|
|
@ -45,7 +47,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t listen(std::string ip, int port);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t set_srt_opt();
|
||||
// Interface ISrsSrtHandler
|
||||
public:
|
||||
|
|
@ -69,7 +72,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsSrtPoller *srt_poller_;
|
||||
ISrsCoroutine *trd_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -220,7 +220,15 @@ SrsSharedPtr<SrsSrtSource> SrsSrtSourceManager::fetch(ISrsRequest *r)
|
|||
|
||||
SrsSrtSourceManager *_srs_srt_sources = NULL;
|
||||
|
||||
SrsSrtConsumer::SrsSrtConsumer(SrsSrtSource *s)
|
||||
ISrsSrtConsumer::ISrsSrtConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsSrtConsumer::~ISrsSrtConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsSrtConsumer::SrsSrtConsumer(ISrsSrtSource *s)
|
||||
{
|
||||
source_ = s;
|
||||
should_update_source_id_ = false;
|
||||
|
|
@ -916,12 +924,22 @@ srs_error_t SrsSrtFrameBuilder::on_aac_frame(SrsTsMessage *msg, uint32_t pts, ch
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsSrtSource::ISrsSrtSource()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsSrtSource::~ISrsSrtSource()
|
||||
{
|
||||
}
|
||||
|
||||
SrsSrtSource::SrsSrtSource()
|
||||
{
|
||||
req_ = NULL;
|
||||
can_publish_ = true;
|
||||
srt_bridge_ = NULL;
|
||||
stream_die_at_ = 0;
|
||||
|
||||
stat_ = _srs_stat;
|
||||
}
|
||||
|
||||
SrsSrtSource::~SrsSrtSource()
|
||||
|
|
@ -937,6 +955,8 @@ SrsSrtSource::~SrsSrtSource()
|
|||
if (cid.empty())
|
||||
cid = _pre_source_id;
|
||||
srs_trace("free srt source id=[%s]", cid.c_str());
|
||||
|
||||
stat_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -995,10 +1015,13 @@ srs_error_t SrsSrtSource::on_source_id_changed(SrsContextId id)
|
|||
_source_id = id;
|
||||
|
||||
// notice all consumer
|
||||
std::vector<SrsSrtConsumer *>::iterator it;
|
||||
std::vector<ISrsSrtConsumer *>::iterator it;
|
||||
for (it = consumers_.begin(); it != consumers_.end(); ++it) {
|
||||
SrsSrtConsumer *consumer = *it;
|
||||
consumer->update_source_id();
|
||||
ISrsSrtConsumer *consumer = *it;
|
||||
SrsSrtConsumer *consumer_impl = dynamic_cast<SrsSrtConsumer *>(consumer);
|
||||
if (consumer_impl) {
|
||||
consumer_impl->update_source_id();
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
@ -1025,7 +1048,7 @@ void SrsSrtSource::set_bridge(ISrsSrtBridge *bridge)
|
|||
srt_bridge_ = bridge;
|
||||
}
|
||||
|
||||
srs_error_t SrsSrtSource::create_consumer(SrsSrtConsumer *&consumer)
|
||||
srs_error_t SrsSrtSource::create_consumer(ISrsSrtConsumer *&consumer)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -1037,7 +1060,7 @@ srs_error_t SrsSrtSource::create_consumer(SrsSrtConsumer *&consumer)
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsSrtSource::consumer_dumps(SrsSrtConsumer *consumer)
|
||||
srs_error_t SrsSrtSource::consumer_dumps(ISrsSrtConsumer *consumer)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -1047,9 +1070,9 @@ srs_error_t SrsSrtSource::consumer_dumps(SrsSrtConsumer *consumer)
|
|||
return err;
|
||||
}
|
||||
|
||||
void SrsSrtSource::on_consumer_destroy(SrsSrtConsumer *consumer)
|
||||
void SrsSrtSource::on_consumer_destroy(ISrsSrtConsumer *consumer)
|
||||
{
|
||||
std::vector<SrsSrtConsumer *>::iterator it;
|
||||
std::vector<ISrsSrtConsumer *>::iterator it;
|
||||
it = std::find(consumers_.begin(), consumers_.end(), consumer);
|
||||
if (it != consumers_.end()) {
|
||||
it = consumers_.erase(it);
|
||||
|
|
@ -1080,8 +1103,7 @@ srs_error_t SrsSrtSource::on_publish()
|
|||
return srs_error_wrap(err, "bridge on publish");
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_publish(req_, _source_id.c_str());
|
||||
stat_->on_stream_publish(req_, _source_id.c_str());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1093,8 +1115,7 @@ void SrsSrtSource::on_unpublish()
|
|||
return;
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_close(req_);
|
||||
stat_->on_stream_close(req_);
|
||||
|
||||
if (srt_bridge_) {
|
||||
srt_bridge_->on_unpublish();
|
||||
|
|
@ -1115,7 +1136,7 @@ srs_error_t SrsSrtSource::on_packet(SrsSrtPacket *packet)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
for (int i = 0; i < (int)consumers_.size(); i++) {
|
||||
SrsSrtConsumer *consumer = consumers_.at(i);
|
||||
ISrsSrtConsumer *consumer = consumers_.at(i);
|
||||
if ((err = consumer->enqueue(packet->copy())) != srs_success) {
|
||||
return srs_error_wrap(err, "consume ts packet");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ class SrsLiveSource;
|
|||
class SrsSrtSource;
|
||||
class SrsAlonePithyPrint;
|
||||
class SrsSrtFrameBuilder;
|
||||
class ISrsStatistic;
|
||||
class ISrsSrtConsumer;
|
||||
class ISrsSrtSource;
|
||||
|
||||
// The SRT packet with shared message.
|
||||
class SrsSrtPacket
|
||||
|
|
@ -45,7 +48,8 @@ public:
|
|||
char *data();
|
||||
int size();
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsMediaPacket *shared_buffer_;
|
||||
// The size of SRT packet or SRT payload.
|
||||
int actual_buffer_size_;
|
||||
|
|
@ -67,7 +71,8 @@ public:
|
|||
// The SRT source manager.
|
||||
class SrsSrtSourceManager : public ISrsHourGlassHandler, public ISrsSrtSourceManager
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_mutex_t lock_;
|
||||
std::map<std::string, SrsSharedPtr<SrsSrtSource> > pool_;
|
||||
SrsHourGlass *timer_;
|
||||
|
|
@ -79,7 +84,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
||||
|
|
@ -97,17 +103,33 @@ public:
|
|||
// Global singleton instance.
|
||||
extern SrsSrtSourceManager *_srs_srt_sources;
|
||||
|
||||
class SrsSrtConsumer
|
||||
// The SRT consumer interface.
|
||||
class ISrsSrtConsumer
|
||||
{
|
||||
public:
|
||||
SrsSrtConsumer(SrsSrtSource *source);
|
||||
ISrsSrtConsumer();
|
||||
virtual ~ISrsSrtConsumer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t enqueue(SrsSrtPacket *packet) = 0;
|
||||
virtual srs_error_t dump_packet(SrsSrtPacket **ppkt) = 0;
|
||||
virtual void wait(int nb_msgs, srs_utime_t timeout) = 0;
|
||||
};
|
||||
|
||||
// The SRT consumer, consume packets from SRT stream source.
|
||||
class SrsSrtConsumer : public ISrsSrtConsumer
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
ISrsSrtSource *source_;
|
||||
|
||||
public:
|
||||
SrsSrtConsumer(ISrsSrtSource *source);
|
||||
virtual ~SrsSrtConsumer();
|
||||
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsSrtSource *source_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::vector<SrsSrtPacket *> queue_;
|
||||
// when source id changed, notice all consumers
|
||||
bool should_update_source_id_;
|
||||
|
|
@ -145,7 +167,8 @@ public:
|
|||
public:
|
||||
virtual srs_error_t on_ts_message(SrsTsMessage *msg);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t on_ts_video_avc(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
srs_error_t on_ts_audio(SrsTsMessage *msg, SrsBuffer *avs);
|
||||
srs_error_t check_sps_pps_change(SrsTsMessage *msg);
|
||||
|
|
@ -156,10 +179,12 @@ private:
|
|||
srs_error_t check_vps_sps_pps_change(SrsTsMessage *msg);
|
||||
srs_error_t on_hevc_frame(SrsTsMessage *msg, std::vector<std::pair<char *, int> > &ipb_frames);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsFrameTarget *frame_target_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsTsContext *ts_ctx_;
|
||||
// Record sps/pps had changed, if change, need to generate new video sh frame.
|
||||
bool sps_pps_change_;
|
||||
|
|
@ -173,10 +198,12 @@ private:
|
|||
bool audio_sh_change_;
|
||||
std::string audio_sh_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsRequest *req_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// SRT to rtmp, video stream id.
|
||||
int video_streamid_;
|
||||
// SRT to rtmp, audio stream id.
|
||||
|
|
@ -185,9 +212,26 @@ private:
|
|||
SrsAlonePithyPrint *pp_audio_duration_;
|
||||
};
|
||||
|
||||
// A SRT source is a stream, to publish and to play with.
|
||||
class SrsSrtSource : public ISrsSrtTarget
|
||||
// The SRT source interface.
|
||||
class ISrsSrtSource : public ISrsSrtTarget
|
||||
{
|
||||
public:
|
||||
ISrsSrtSource();
|
||||
virtual ~ISrsSrtSource();
|
||||
|
||||
public:
|
||||
virtual SrsContextId source_id() = 0;
|
||||
virtual SrsContextId pre_source_id() = 0;
|
||||
virtual void on_consumer_destroy(ISrsSrtConsumer *consumer) = 0;
|
||||
};
|
||||
|
||||
// A SRT source is a stream, to publish and to play with.
|
||||
class SrsSrtSource : public ISrsSrtSource
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsStatistic *stat_;
|
||||
|
||||
public:
|
||||
SrsSrtSource();
|
||||
virtual ~SrsSrtSource();
|
||||
|
|
@ -214,10 +258,10 @@ public:
|
|||
public:
|
||||
// Create consumer
|
||||
// @param consumer, output the create consumer.
|
||||
virtual srs_error_t create_consumer(SrsSrtConsumer *&consumer);
|
||||
virtual srs_error_t create_consumer(ISrsSrtConsumer *&consumer);
|
||||
// Dumps packets in cache to consumer.
|
||||
virtual srs_error_t consumer_dumps(SrsSrtConsumer *consumer);
|
||||
virtual void on_consumer_destroy(SrsSrtConsumer *consumer);
|
||||
virtual srs_error_t consumer_dumps(ISrsSrtConsumer *consumer);
|
||||
virtual void on_consumer_destroy(ISrsSrtConsumer *consumer);
|
||||
// Whether we can publish stream to the source, return false if it exists.
|
||||
virtual bool can_publish();
|
||||
// When start publish stream.
|
||||
|
|
@ -228,19 +272,21 @@ public:
|
|||
public:
|
||||
srs_error_t on_packet(SrsSrtPacket *packet);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Source id.
|
||||
SrsContextId _source_id;
|
||||
// previous source id.
|
||||
SrsContextId _pre_source_id;
|
||||
ISrsRequest *req_;
|
||||
// To delivery packets to clients.
|
||||
std::vector<SrsSrtConsumer *> consumers_;
|
||||
std::vector<ISrsSrtConsumer *> consumers_;
|
||||
bool can_publish_;
|
||||
// The last die time, while die means neither publishers nor players.
|
||||
srs_utime_t stream_die_at_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsSrtBridge *srt_bridge_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ class SrsExecutorCoroutine;
|
|||
// @see https://github.com/ossrs/srs/pull/908
|
||||
class SrsDummyCoroutine : public ISrsCoroutine
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
|
||||
public:
|
||||
|
|
@ -55,7 +56,8 @@ public:
|
|||
// Please read https://github.com/ossrs/srs/issues/78
|
||||
class SrsSTCoroutine : public ISrsCoroutine
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsFastCoroutine *impl_;
|
||||
|
||||
public:
|
||||
|
|
@ -96,24 +98,28 @@ public:
|
|||
// High performance coroutine.
|
||||
class SrsFastCoroutine : public ISrsCoroutine
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
std::string name_;
|
||||
int stack_size_;
|
||||
ISrsCoroutineHandler *handler_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_thread_t trd_;
|
||||
SrsContextId cid_;
|
||||
srs_error_t trd_err_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
bool started_;
|
||||
bool interrupted_;
|
||||
bool disposed_;
|
||||
// Cycle done, no need to interrupt it.
|
||||
bool cycle_done_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
// Sub state in disposed, we need to wait for thread to quit.
|
||||
bool stopping_;
|
||||
SrsContextId stopping_cid_;
|
||||
|
|
@ -140,7 +146,8 @@ public:
|
|||
const SrsContextId &cid();
|
||||
virtual void set_cid(const SrsContextId &cid);
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
srs_error_t cycle();
|
||||
static void *pfn(void *arg);
|
||||
};
|
||||
|
|
@ -148,7 +155,8 @@ private:
|
|||
// Like goroutine sync.WaitGroup.
|
||||
class SrsWaitGroup
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
int nn_;
|
||||
srs_cond_t done_;
|
||||
|
||||
|
|
@ -196,15 +204,22 @@ public:
|
|||
// srs_freep(executor);
|
||||
// return err;
|
||||
// }
|
||||
class SrsExecutorCoroutine : public ISrsResource, public ISrsStartable, public ISrsInterruptable, public ISrsContextIdSetter, public ISrsContextIdGetter, public ISrsCoroutineHandler
|
||||
class SrsExecutorCoroutine : public ISrsResource, // It's a resource.
|
||||
public ISrsStartable,
|
||||
public ISrsInterruptable,
|
||||
public ISrsContextIdSetter,
|
||||
public ISrsContextIdGetter,
|
||||
public ISrsCoroutineHandler
|
||||
{
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsResourceManager *manager_;
|
||||
ISrsResource *resource_;
|
||||
ISrsCoroutineHandler *handler_;
|
||||
ISrsExecutorHandler *callback_;
|
||||
|
||||
private:
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
public:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user