Commit Graph

8690 Commits (develop)
 

Author SHA1 Message Date
ChenGH 13597d1b7f
update copyright to 2025. v5.0.218 v6.0.159 v7.0.21 (#4271)
update copyright to 2025

---------

Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2 weeks ago
Jacob Su 7416134262
fix compile error in srs_protocol_rtmp_stack.cpp (#4247)
Fix a compiling error.

## How to reproduce?


7951bf3bd6/trunk/src/core/srs_core_performance.hpp (L146)

Delete this line to write `iovs` one by one (or 2 by 2).
Then `./configure && make`, the compiling error appears.
2 months ago
Jacob Su 7951bf3bd6
Test: Fix utest fail for StUtimeInMicroseconds. v7.0.20 (#4218)
```
../../../src/utest/srs_utest_st.cpp:27: Failure
Expected: (st_time_2 - st_time_1) <= (100), actual: 119 vs 100
[  FAILED  ] StTest.StUtimeInMicroseconds (0 ms)
```

Maybe github's vm, running the action jobs, is slower. I notice this
error happens frequently, so let the UT pass by increase the number.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: winlin <winlinvip@gmail.com>
3 months ago
Haibo Chen 58e775ce8d
HLS: Fix error when stream has extension. #4215 v5.0.217 v6.0.158 v7.0.19 (#4216)
---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
3 months ago
Jacob Su 101382afd0
RTC2RTMP: Fix screen sharing stutter caused by packet loss. v5.0.216 v6.0.157 v7.0.18 (#4160)
## How to reproduce?

1. Refer this commit, which contains the web demo to capture screen as
video stream through RTC.
2. Copy the `trunk/research/players/whip.html` and
`trunk/research/players/js/srs.sdk.js` to replace the `develop` branch
source code.
3. `./configure && make`
4. `./objs/srs -c conf/rtc2rtmp.conf`
5. open `http://localhost:8080/players/whip.html?schema=http`
6. check `Screen` radio option.
7. click `publish`, then check the screen to share.
8. play the rtmp live stream: `rtmp://localhost/live/livestream`
9. check the video stuttering.

## Cause
When capture screen by the chrome web browser, which send RTP packet
with empty payload frequently, then all the cached RTP packets are
dropped before next key frame arrive in this case.

The OBS screen stream and camera stream do not have such problem.

## Add screen stream to WHIP demo

><img width="581" alt="Screenshot 2024-08-28 at 2 49 46 PM"
src="https://github.com/user-attachments/assets/9557dbd2-c799-4dfd-b336-5bbf2e4f8fb8">

---------

Co-authored-by: winlin <winlinvip@gmail.com>
4 months ago
Jacob Su e7d78462fe
ST: Use clock_gettime to prevent time jumping backwards. v7.0.17 (#3979)
try to fix #3978 

**Background**
check #3978 

**Research**

I referred the Android platform's solution, because I have android
background, and there is a loop to handle message inside android.


ff007a03c0/core/java/android/os/Handler.java (L701-L706C6)

```
    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
```


59d9dc1f50/libutils/SystemClock.cpp (L37-L51)

```
/*
 * native public static long uptimeMillis();
 */
int64_t uptimeMillis()
{
    return nanoseconds_to_milliseconds(uptimeNanos());
}


/*
 * public static native long uptimeNanos();
 */
int64_t uptimeNanos()
{
    return systemTime(SYSTEM_TIME_MONOTONIC);
}
```


59d9dc1f50/libutils/Timers.cpp (L32-L55)
```
#if defined(__linux__)
nsecs_t systemTime(int clock) {
    checkClockId(clock);
    static constexpr clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC,
                                           CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID,
                                           CLOCK_BOOTTIME};
    static_assert(clock_id_max == arraysize(clocks));
    timespec t = {};
    clock_gettime(clocks[clock], &t);
    return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
#else
nsecs_t systemTime(int clock) {
    // TODO: is this ever called with anything but REALTIME on mac/windows?
    checkClockId(clock);


    // Clock support varies widely across hosts. Mac OS doesn't support
    // CLOCK_BOOTTIME (and doesn't even have clock_gettime until 10.12).
    // Windows is windows.
    timeval t = {};
    gettimeofday(&t, nullptr);
    return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL;
}
#endif
```
For Linux system, we can use `clock_gettime` api, but it's first
appeared in Mac OSX 10.12.

`man clock_gettime`

The requirement is to find an alternative way to get the timestamp in
microsecond unit, but the `clock_gettime` get nanoseconds, the math
formula is the nanoseconds / 1000 = microsecond. Then I check the
performance of this api + math division.

I used those code to check the `clock_gettime` performance.

```
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>

int main() {
	struct timeval tv;
	struct timespec ts;
	clock_t start;
	clock_t end;
	long t;

	while (1) {
		start = clock();
		gettimeofday(&tv, NULL);
		end = clock();
		printf("gettimeofday clock is %lu\n", end - start);
		printf("gettimeofday is %lld\n", (tv.tv_sec * 1000000LL + tv.tv_usec));

		start = clock();
		clock_gettime(CLOCK_MONOTONIC, &ts);
		t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L;
		end = clock();
		printf("clock_monotonic clock is %lu\n", end - start);
		printf("clock_monotonic: seconds is %ld, nanoseconds is %ld, sum is %ld\n", ts.tv_sec, ts.tv_nsec, t);

		start = clock();
		clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
		t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L;
		end = clock();
		printf("clock_monotonic_raw clock is %lu\n", end - start);
		printf("clock_monotonic_raw: nanoseconds is %ld, sum is %ld\n", ts.tv_nsec, t);

		sleep(3);
	}
	
	return 0;
}

```

Here is output:

env: Mac OS M2 chip.

```
gettimeofday clock is 11
gettimeofday is 1709775727153949
clock_monotonic clock is 2
clock_monotonic: seconds is 1525204, nanoseconds is 409453000, sum is 1525204409453
clock_monotonic_raw clock is 2
clock_monotonic_raw: nanoseconds is 770493000, sum is 1525222770493
```
We can see the `clock_gettime` is faster than `gettimeofday`, so there
are no performance risks.

**MacOS solution**

`clock_gettime` api only available until mac os 10.12, for the mac os
older than 10.12, just keep the `gettimeofday`.
check osx version in `auto/options.sh`, then add MACRO in
`auto/depends.sh`, the MACRO is `MD_OSX_HAS_NO_CLOCK_GETTIME`.


**CYGWIN**
According to google search, it seems the
`clock_gettime(CLOCK_MONOTONIC)` is not support well at least 10 years
ago, but I didn't own an windows machine, so can't verify it. so keep
win's solution.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
4 months ago
Winlin 0de887d374
Update bug_report.md 4 months ago
Winlin 2068aa4659
Update FUNDING.yml 4 months ago
winlin 40e8ed4586 VSCode: Support IDE vscode to run and debug. 5 months ago
winlin e674f8266a Proxy: Remove dependency of godotenv. #4158 5 months ago
Winlin 2e4014ae1c
Proxy: Support proxy server for SRS. v7.0.16 (#4158)
Please note that the proxy server is a new architecture or the next
version of the Origin Cluster, which allows the publication of multiple
streams. The SRS origin cluster consists of a group of origin servers
designed to handle a large number of streams.

```text
                         +-----------------------+
                     +---+ SRS Proxy(Deployment) +------+---------------------+
+-----------------+  |   +-----------+-----------+      +                     +
| LB(K8s Service) +--+               +(Redis/MESH)      + SRS Origin Servers  +
+-----------------+  |   +-----------+-----------+      +    (Deployment)     +
                     +---+ SRS Proxy(Deployment) +------+---------------------+
                         +-----------------------+
```

The new origin cluster is designed as a collection of proxy servers. For
more information, see [Discussion
#3634](https://github.com/ossrs/srs/discussions/3634). If you prefer to
use the old origin cluster, please switch to a version before SRS 6.0.

A proxy server can be used for a set of origin servers, which are
isolated and dedicated origin servers. The main improvement in the new
architecture is to store the state for origin servers in the proxy
server, rather than using MESH to communicate between origin servers.
With a proxy server, you can deploy origin servers as stateless servers,
such as in a Kubernetes (K8s) deployment.

Now that the proxy server is a stateful server, it uses Redis to store
the states. For faster development, we use Go to develop the proxy
server, instead of C/C++. Therefore, the proxy server itself is also
stateless, with all states stored in the Redis server or cluster. This
makes the new origin cluster architecture very powerful and robust.

The proxy server is also an architecture designed to solve multiple
process bottlenecks. You can run hundreds of SRS origin servers with one
proxy server on the same machine. This solution can utilize multi-core
machines, such as servers with 128 CPUs. Thus, we can keep SRS
single-threaded and very simple. See
https://github.com/ossrs/srs/discussions/3665#discussioncomment-6474441
for details.

```text
                                       +--------------------+
                               +-------+ SRS Origin Server  +
                               +       +--------------------+
                               +
+-----------------------+      +       +--------------------+
+ SRS Proxy(Deployment) +------+-------+ SRS Origin Server  +
+-----------------------+      +       +--------------------+
                               +
                               +       +--------------------+
                               +-------+ SRS Origin Server  +
                                       +--------------------+
```

Keep in mind that the proxy server for the Origin Cluster is designed to
handle many streams. To address the issue of many viewers, we will
enhance the Edge Cluster to support more protocols.

```text
+------------------+                                               +--------------------+
+ SRS Edge Server  +--+                                    +-------+ SRS Origin Server  +
+------------------+  +                                    +       +--------------------+
                      +                                    +
+------------------+  +     +-----------------------+      +       +--------------------+
+ SRS Edge Server  +--+-----+ SRS Proxy(Deployment) +------+-------+ SRS Origin Server  +
+------------------+  +     +-----------------------+      +       +--------------------+
                      +                                    +
+------------------+  +                                    +       +--------------------+
+ SRS Edge Server  +--+                                    +-------+ SRS Origin Server  +
+------------------+                                               +--------------------+
```

With the new Origin Cluster and Edge Cluster, you have a media system
capable of supporting a large number of streams and viewers. For
example, you can publish 10,000 streams, each with 100,000 viewers.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin b475d552aa
Heartbeat: Report ports for proxy server. v5.0.215 v6.0.156 v7.0.15 (#4171)
The heartbeat of SRS is a timer that requests an HTTP URL. We can use
this heartbeat to report the necessary information for registering the
backend server with the proxy server.

```text
SRS(backend) --heartbeat---> Proxy server
```

A proxy server is a specialized load balancer for media servers. It
operates at the application level rather than the TCP level. For more
information about the proxy server, see issue #4158.

Note that we will merge this PR into SRS 5.0+, allowing the use of SRS
5.0+ as the backend server, not limited to SRS 7.0. However, the proxy
server is introduced in SRS 7.0.

It's also possible to implement a registration service, allowing you to
use other media servers as backend servers. For example, if you gather
information about an nginx-rtmp server and register it with the proxy
server, the proxy will forward RTMP streams to nginx-rtmp. The backend
server is not limited to SRS.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
winlin d70e7357cf Release v6.0-a1, 6.0 alpha1, v6.0.155, 169636 lines. 5 months ago
Winlin 15fbe45a9a
FLV: Refine source and http handler. v6.0.155 v7.0.14 (#4165)
1. Do not create a source when mounting FLV because it may not unmount
FLV when freeing the source. If you access the FLV stream without any
publisher, then wait for source cleanup and review the FLV stream again,
there is an annoying warning message.

```bash
# View HTTP FLV stream by curl, wait for stream to be ready.
# curl http://localhost:8080/live/livestream.flv -v >/dev/null
HTTP #0 127.0.0.1:58026 GET http://localhost:8080/live/livestream.flv, content-length=-1
new live source, stream_url=/live/livestream
http: mount flv stream for sid=/live/livestream, mount=/live/livestream.flv

# Cancel the curl and trigger source cleanup without http unmount.
client disconnect peer. ret=1007
Live: cleanup die source, id=[], total=1

# View the stream again, it fails.
# curl http://localhost:8080/live/livestream.flv -v >/dev/null
HTTP #0 127.0.0.1:58040 GET http://localhost:8080/live/livestream.flv, content-length=-1
serve error code=1097(NoSource)(No source found) : process request=0 : cors serve : serve http : no source for /live/livestream
serve_http() [srs_app_http_stream.cpp:641]
```

> Note: There is an inconsistency. The first time, you can access the
FLV stream and wait for the publisher, but the next time, you cannot.

2. Create a source when starting to serve the FLV client. We do not need
to create the source when creating the HTTP handler. Instead, we should
try to create the source in the cache or stream. Because the source
cleanup does not unmount the HTTP handler, the handler remains after the
source is destroyed. The next time you access the FLV stream, the source
is not found.

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(r.get(), server, live_source)) != srs_success) { }
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }
```

> Note: We should not create the source in hijack, instead, we create it
in cache or stream:

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }
```

> Note: This fixes the failure and annoying warning message, and
maintains consistency by always waiting for the stream to be ready if
there is no publisher.

3. Fail the http request if the HTTP handler is disposing, and also keep
the handler entry when disposing the stream, because we should dispose
the handler entry and stream at the same time.

```cpp
srs_error_t SrsHttpStreamServer::http_mount(SrsRequest* r) {
        entry = streamHandlers[sid];
        if (entry->disposing) {
            return srs_error_new(ERROR_STREAM_DISPOSING, "stream is disposing");
        }

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    std::map<std::string, SrsLiveEntry*>::iterator it = streamHandlers.find(sid);
    SrsUniquePtr<SrsLiveEntry> entry(it->second);
    entry->disposing = true;
```

> Note: If the disposal process takes a long time, this will prevent
unexpected behavior or access to the resource that is being disposed of.

4. In edge mode, the edge ingester will unpublish the source when the
last consumer quits, which is actually triggered by the HTTP stream.
While it also waits for the stream to quit when the HTTP unmounts, there
is a self-destruction risk: the HTTP live stream object destroys itself.

```cpp
srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw); // Trigger destroy.

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    for (;;) { if (!cache->alive() && !stream->alive()) { break; } // A circle reference.
    mux.unhandle(entry->mount, stream.get()); // Free the SrsLiveStream itself.
```

> Note: It also introduces a circular reference in the object
relationships, the stream reference to itself when unmount:

```text
SrsLiveStream::serve_http 
    -> SrsLiveConsumer::~SrsLiveConsumer -> SrsEdgeIngester::stop 
    -> SrsLiveSource::on_unpublish -> SrsHttpStreamServer::http_unmount 
        -> SrsLiveStream::alive
```

> Note: We should use an asynchronous worker to perform the cleanup to
avoid the stream destroying itself and to prevent self-referencing.

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    entry->disposing = true;
    if ((err = async_->execute(new SrsHttpStreamDestroy(&mux, &streamHandlers, sid))) != srs_success) { }
```

> Note: This also ensures there are no circular references and no
self-destruction.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin 740f0d38ec
Edge: Fix flv edge crash when http unmount. v6.0.154 v7.0.13 (#4166)
Edge FLV is not working because it is stuck in an infinite loop waiting.
Previously, there was no need to wait for exit since resources were not
being cleaned up. Now, since resources need to be cleaned up, it must
wait for all active connections to exit, which causes this issue.

To reproduce the issue, start SRS edge, run the bellow command and press
`CTRL+C` to stop the request:

```bash
curl http://localhost:8080/live/livestream.flv -v >/dev/null
```

It will cause edge to fetch stream from origin, and free the consumer
when client quit. When `SrsLiveStream::do_serve_http` return, it will
free the consumer:

```cpp
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
```

Keep in mind that in this moment, the stream is alive, because only set
to not alive after this function return:

```cpp
    alive_viewers_++;
    err = do_serve_http(w, r); // Free 'this' alive stream.
    alive_viewers_--; // Crash here, because 'this' is freed.
```

When freeing the consumer, it will cause the source to unpublish and
attempt to free the HTTP handler, which ultimately waits for the stream
not to be alive:

```cpp
SrsLiveConsumer::~SrsLiveConsumer() {
    source_->on_consumer_destroy(this);

void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) {
    if (consumers.empty()) {
        play_edge->on_all_client_stop();

void SrsLiveSource::on_unpublish() {
    handler->on_unpublish(req);

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    if (stream->entry) stream->entry->enabled = false;

    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }
```

After 120 seconds, it will free the stream and cause SRS to crash
because the stream is still active. In order to track this potential
issue, also add an important warning log:

```cpp
srs_warn("http: try to free a alive stream, cache=%d, stream=%d", cache->alive(), stream->alive());
```

SRS may crash if got this log.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin a7aa2eaf76
Fix #3767: RTMP: Do not response empty data packet. v6.0.153 v7.0.12 (#4162)
If SRS responds with this empty data packet, FFmpeg will receive an
empty stream, like `Stream #0:0: Data: none` in following logs:

```bash
ffmpeg -i rtmp://localhost:11935/live/livestream
#  Stream #0:0: Data: none
#  Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 30 kb/s
#  Stream #0:2: Video: h264 (High), yuv420p(progressive), 768x320 [SAR 1:1 DAR 12:5], 212 kb/s, 25 fps, 25 tbr, 1k tbn
```

This won't cause the player to fail, but it will inconvenience the user
significantly. It may also cause FFmpeg slower to analysis the stream,
see #3767

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin 05c3a422a5
HTTP-FLV: Notify connection to expire when unpublishing. v6.0.152 v7.0.11 (#4164)
When stopping the stream, it will wait for the HTTP Streaming to exit.
If the HTTP Streaming goroutine hangs, it will not exit automatically.

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
{
    SrsUniquePtr<SrsLiveStream> stream(entry->stream);
    if (stream->entry) stream->entry->enabled = false;
    srs_usleep(...); // Wait for about 120s.
    mux.unhandle(entry->mount, stream.get()); // Free stream.
}

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
    err = do_serve_http(w, r); // If stuck in here for 120s+
    alive_viewers_--; // Crash at here, because stream has been deleted.
```

We should notify http stream connection to interrupt(expire):

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
{
    SrsUniquePtr<SrsLiveStream> stream(entry->stream);
    if (stream->entry) stream->entry->enabled = false;
    stream->expire(); // Notify http stream to interrupt.
```

Note that we should notify all viewers pulling stream from this http
stream.

Note that we have tried to fix this issue, but only try to wait for all
viewers to quit, without interrupting the viewers, see
https://github.com/ossrs/srs/pull/4144


---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin f8319d6b6d
Fix crash when quiting. v6.0.151 v7.0.10 (#4157)
1. Remove the srs_global_dispose, which causes the crash when still
publishing when quit.
2. Always call _srs_thread_pool->initialize for single thread.
3. Support `--signal-api` to send signal by HTTP API, because CLion
eliminate the signals.

---

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Jacob Su cc6db250fb
Build: Fix srs_mp4_parser compiling error. v6.0.150 v7.0.9 (#4156)
`SrsAutoFree` moved to `srs_core_deprecated.hpp`.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
5 months ago
winlin 47f8fe4395 Fix utest fail. 5 months ago
Winlin d4248503e7
ASAN: Disable memory leak detection by default. v7.0.8 (#4154)
By setting the env `ASAN_OPTIONS=halt_on_error=0`, we can ignore memory
leaks, see
https://github.com/google/sanitizers/wiki/AddressSanitizerFlags

By setting env `ASAN_OPTIONS=detect_leaks=0`, we can disable memory
leaking detection in parent process when forking for daemon.
5 months ago
Winlin 8f48a0e2d1
ASAN: Support coroutine context switching and stack tracing (#4153)
For coroutine, we should use `__sanitizer_start_switch_fiber` which
similar to`VALGRIND_STACK_REGISTER`, see
https://github.com/google/sanitizers/issues/189#issuecomment-1346243598
for details. If not fix this, asan will output warning:

```
==72269==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x00016f638000; bottom 0x000106bec000; size: 0x000068a4c000 (1755627520)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
```

It will cause asan failed to get the stack, see
`research/st/asan-switch.cpp` for example:

```
==71611==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x000103600733 at pc 0x0001009d3d7c bp 0x000100b4bd40 sp 0x000100b4bd38
WRITE of size 1 at 0x000103600733 thread T0
    #0 0x1009d3d78 in foo(void*) asan-switch.cpp:13
```

After fix this issue, it should provide the full stack when crashing:

```
==73437==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x000103300733 at pc 0x000100693d7c bp 0x00016f76f550 sp 0x00016f76f548
WRITE of size 1 at 0x000103300733 thread T0
    #0 0x100693d78 in foo(void*) asan-switch.cpp:13
    #1 0x100693df4 in main asan-switch.cpp:23
    #2 0x195aa20dc  (<unknown module>)
```

For primordial coroutine, if not set the stack by
`st_set_primordial_stack`, then the stack is NULL and asan can't get the
stack tracing. Note that it's optional and only make it fail to display
the stack information, no other errors.

---

Co-authored-by: john <hondaxiao@tencent.com>
5 months ago
winlin 55610cf689 ST: Refine switch context. 5 months ago
Winlin ff6a608099
ST: Replace macros with explicit code for better understanding. v7.0.7 (#4149)
Improvements for ST(State Threads):

1. ST: Use g++ for CXX compiler.
2. ST: Remove macros for clist.
3. ST: Remove macros for global thread and vp.
4. ST: Remove macros for vp queue operations.
5. ST: Remove macros for context switch.
6. ST: Remove macros for setjmp/longjmp.
7. ST: Remove macro for stack pad.
8. ST: Refine macro for valgrind.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Winlin 0d76081430
API: Support new HTTP API for VALGRIND. v6.0.149 v7.0.6 (#4150)
New features for valgrind:

1. ST: Support /api/v1/valgrind for leaking check.
2. ST: Support /api/v1/valgrind?check=full|added|changed|new|quick

To use Valgrind to detect memory leaks in SRS, even though Valgrind
hooks are supported in ST, there are still many false positives. A more
reasonable approach is to have Valgrind report incremental memory leaks.
This way, global and static variables can be avoided, and detection can
be achieved without exiting the program. Follow these steps:

1. Compile SRS with Valgrind support: `./configure --valgrind=on &&
make`
2. Start SRS with memory leak detection enabled: `valgrind
--leak-check=full ./objs/srs -c conf/console.conf`
3. Trigger memory detection by using curl to access the API and generate
calibration data. There will still be many false positives, but these
can be ignored: `curl http://127.0.0.1:1985/api/v1/valgrind?check=added`
4. Perform load testing or test the suspected leaking functionality,
such as RTMP streaming: `ffmpeg -re -i doc/source.flv -c copy -f flv
rtmp://127.0.0.1/live/livestream`
5. Stop streaming and wait for SRS to clean up the Source memory,
approximately 30 seconds.
6. Perform incremental memory leak detection. The reported leaks will be
very accurate at this point: `curl
http://127.0.0.1:1985/api/v1/valgrind?check=added`

> Note: To avoid interference from the HTTP request itself on Valgrind,
SRS uses a separate coroutine to perform periodic checks. Therefore,
after accessing the API, you may need to wait a few seconds for the
detection to be triggered.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
5 months ago
Bahamut 3e811ba34a HTTP-FLV: Crash when multiple viewers. v6.0.148 v7.0.5 (#4144)
I did some preliminary code inspection. The two playback endpoints share
the same `SrsLiveStream` instance. After the first one disconnects,
`alive_` is set to false.
```
  alive_ = true;
  err = do_serve_http(w, r);
  alive_ = false;
```

In the `SrsHttpStreamServer::http_unmount(SrsRequest* r)` function,
`stream->alive()` is already false, so `mux.unhandle` will free the
`SrsLiveStream`. This causes the other connection coroutine to return to
its execution environment after the `SrsLiveStream` instance has already
been freed.
```
    // Wait for cache and stream to stop.
    int i = 0;
    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }

    // Unmount the HTTP handler, which will free the entry. Note that we must free it after cache and
    // stream stopped for it uses it.
    mux.unhandle(entry->mount, stream.get());
```

`alive_` was changed from a `bool` to an `int` to ensure that
`mux.unhandle` is only executed after each connection's `serve_http` has
exited.

---------

Co-authored-by: liumengte <liumengte@visionular.com>
Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Jacob Su e323215478
Config: Add more utest for env config. v6.0.147 v7.0.4 (#4142)
1. don't use static variable to store the result;
2. add more UT to handle the multi value and values with whitespaces;

related to #4092 


16e569d823/trunk/src/app/srs_app_config.cpp (L71-L82)

`static SrsConfDirective* dir` removed, this static var here is to avoid
the memory leak, I add the `SrsConfDirective` instance to the `env_dirs`
directive container, which will destroy itself inside `SrsConfig`
destructor.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Bahamut 38417d9ccc
Live: Crash for invalid live stream state when unmount HTTP. v6.0.146 v7.0.3 (#4141)
When unpublishing, the handler callback that will stop the coroutine:

```cpp
_can_publish = true;
handler->on_unpublish(req);
```

In this handler, the `http_unmount` will be called:

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
    cache->stop();
```

In this `http_unmount` function, there could be context switching. In
such a situation, a new connection might publish the stream while the
unpublish process is freeing the stream, leading to a crash.

To prevent a new publisher, we should change the state only after all
handlers and hooks are completed.

---------

Co-authored-by: liumengte <liumengte@visionular.com>
Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Jacob Su 16e569d823
Config: Improve env config to support multi values. v7.0.2 (#4092)
1. add on_connect & on_close directives to conf/full.conf;
2. let http_hooks env overwrite support multi values; e.g.
SRS_VHOST_HTTP_HOOKS_ON_CONNECT="http://127.0.0.1/api/connect
http://localhost/api/connect"

related to
https://github.com/ossrs/srs/issues/1222#issuecomment-2170424703
Above comments said `http_hook` env may not works as expected, as I
found there are still has some issue in `http_hooks` env configuration,
but this PR may not target above problem.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
jb-alvarado 2e211f6abe Transcode: More generic h264/h265 codec support. v7.0.1 (#4131)
Sorry this is another pull request with same intention. But there is
more variants of h264 und h265 codecs and I think it is good to support
them all.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
winlin 7478311547 Start the SRS 7.0.0 6 months ago
winlin 384ccbac0d Release v6.0-a0, 6.0 alpha0, v6.0.145, 169259 lines. 6 months ago
jb-alvarado 331ef9ffae
Transcode: Support video codec such as h264_qsv and libx265. v6.0.145 (#4127)
Currently only libx264 ffmpeg encoder is supported. This pull request
add also h264_qsv. But maybe a more generic solution with oder encoders
would be useful to.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Haibo Chen 65ad907fe4
GB28181: Support external SIP server. v6.0.144 (#4101)
For #3369 to support an external powerful SIP server, do not use the
embedded SIP server of SRS.
For more information, detailed steps, system architecture, and
background explanation, please see
https://ossrs.net/lts/zh-cn/docs/v6/doc/gb28181#external-sip

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Marc Olzheim f76be5fe9b
HLS: Add missing newline to end of session manifest. v6.0.143 (#4115)
The session HLS manifest file lacks a terminating newline in the final
line.
This may cause strict players to reject it.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Jacob Su 3e1a4e4439
Player: Fix empty img tag occupy 20px size in safari. v6.0.142 (#4029)
the html img tag occupy 20px size in safari. 

427104f1da/trunk/research/players/rtc_player.html (L19)

> <img width="1011" alt="Screenshot 2024-04-17 at 9 17 07 AM"
src="https://github.com/ossrs/srs/assets/2757043/79a4edf8-5bbf-4300-8817-039088f13283">


(ignore the img css warning: `auto\9;` it's another problem, I will file
another PR.)

but, the empty img tag just occupy 1px size in chrome. So I guess it's a
html compatible problem.

> <img width="608" alt="Screenshot 2024-04-17 at 9 46 33 AM"
src="https://github.com/ossrs/srs/assets/2757043/40cb2eb6-3a6d-4bb7-9b17-51c5fd6d2272">

---------

`TRANS_BY_GPT4`

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Jacob Su eb788a62ad
HTTP-TS: Support guess_has_av for audio only stream. v6.0.141 (#4063)
## Describe ##
http_remux feature support config `has_audio`, `has_video` &
`guess_has_av` prop.


282d94d7bb/trunk/src/app/srs_app_http_stream.cpp (L630-L632)

Take `http_flv` as example, `srs` can accept both RTMP streams with only
audio, only video or both audio and video streams. It is controlled by
above three properties.

But `guess_has_av` is not implemented by `http_ts`. The problem is that
if I want publish a RTMP stream with audio or video track, the
`has_audio` and `has_video`, which are default true/on, must to be
config to match the RTMP stream, otherwise the `mpegts.js` player can't
play the `http-ts` stream.

## How to reproduce  ##

1. `export SRS_VHOST_HTTP_REMUX_HAS_AUDIO=on; export
SRS_VHOST_HTTP_REMUX_HAS_VIDEO=on; export
SRS_VHOST_HTTP_REMUX_GUESS_HAS_AV=on; ./objs/srs -c
conf/http.ts.live.conf`
2. publish rtmp stream without video: `ffmpeg -re -stream_loop -1 -i
srs/trunk/doc/source.200kbps.768x320.flv -vn -acodec copy -f flv
rtmp://localhost/live/livestream`
3. open chrome browser, open
`http://localhost:8080/players/srs_player.html?schema=http`, go to
`LivePlayer`, input URL: `http://localhost:8080/live/livestream.ts`,
click play.
4. the `http://localhost:8080/live/livestream.ts` can not play.

## Solution ##

Let `http-ts` support `guess_has_av`, `http-flv` already supported. The
`guess_has_av` default value is ture/on, so the `http-ts|flv` can play
any streams with audio, video or both.

---------

Co-authored-by: Winlin <winlinvip@gmail.com>
6 months ago
Marc Olzheim d50fb1563a
Dockerfile: Consistently use proper ENV syntax using equal sign. v6.0.140 (#4116)
This not only silences a deprecation warning by docker build, but also
makes it consistent as the other ENV statement already uses the new
syntax.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
6 months ago
Winlin f04e9392fa
Edge: Improve stability for state and fd closing. v5.0.214 v6.0.139 (#4126)
1. Should always stop coroutine before close fd, see #511, #1784
2. When edge forwarder coroutine quit, always set the error code.
3. Do not unpublish if invalid state.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
6 months ago
winlin 8c034e5a13 Always use single thread by default. 6 months ago
Jacob Su d220bf280e
DASH: Fix time unit error for disposing. v6.0.138 (#4111)
## Cause
dash auto dispose is configured by seconds, but the code compare by
usecond, 1 second = 1,000,000 useconds.

releated to #4097
Bug introduced after #4097 supported Dash auto dispose after a timeout
without media data.

## How to reproduce

1. `./objs/srs -c conf/dash.conf`
2. publish a rtmp stream.
3. play dash stream. -> no dash stream, always 404 error.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
7 months ago
Jacob Su f1d98b9830
HTTPS: Support config key/cert for HTTPS API. v6.0.137 (#4028)
Co-authored-by: winlin <winlinvip@gmail.com>
7 months ago
Winlin 23d2602c34
UniquePtr: Support SrsUniquePtr to replace SrsAutoFree. v6.0.136 (#4109)
To manage an object:

```cpp
// Before
MyClass* ptr = new MyClass();
SrsAutoFree(MyClass, ptr);
ptr->do_something();

// Now
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
```

To manage an array of objects:

```cpp
// Before
char* ptr = new char[10];
SrsAutoFreeA(char, ptr);
ptr[0] = 0xf;

// Now
SrsUniquePtr<char[]> ptr(new char[10]);
ptr[0] = 0xf;
```

In fact, SrsUniquePtr is a limited subset of SrsAutoFree, mainly
managing pointers and arrays. SrsUniquePtr is better than SrsAutoFree
because it has the same API to standard unique ptr.

```cpp
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
MyClass* p = ptr.get();
```

SrsAutoFree actually uses a pointer to a pointer, so it can be set to
NULL, allowing the pointer's value to be changed later (this usage is
different from SrsUniquePtr).

```cpp
// OK to free ptr correctly.
MyClass* ptr;
SrsAutoFree(MyClass, ptr);
ptr = new MyClass();

// Crash because ptr is an invalid pointer.
MyClass* ptr;
SrsUniquePtr<MyClass> ptr(ptr);
ptr = new MyClass();
```

Additionally, SrsAutoFreeH can use specific release functions, which
SrsUniquePtr does not support.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
7 months ago
Jacob Su baf22d01c1
Refine config directive token parsing. v6.0.135 (#4042)
make sure one directive token don't span more than two lines.

try to fix #2228

---------

Co-authored-by: winlin <winlinvip@gmail.com>
7 months ago
winlin 6bbd461ec9 Release v6.0-d6, 6.0 dev6, v6.0.134, 168904 lines. 7 months ago
Winlin 20c8e6423b
SmartPtr: Fix SRT source memory leaking. v6.0.134 (#4106)
---------

Co-authored-by: john <hondaxiao@tencent.com>
7 months ago
Jacob Su 75ddd8f5b6
Fix misspelling error in app config. v6.0.133 (#4077)
1. misspelling fix;
2. remove finished TODO;

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
7 months ago
Winlin 7ab012c60f
SmartPtr: Support detect memory leak by valgrind. v6.0.132 (#4102)
1. Support detect memory leak by valgrind.
2. Free the http handler entry.
3. Free the stack of ST.

---

Co-authored-by: Jacob Su <suzp1984@gmail.com>
7 months ago
Jacob Su ea7e2c2849
Fix security scan problems. v6.0.131 (#4100)
1. fix redundant null check, there is no potential risks by the way,
just redundant null check.
2. Potential use pointer after free, that's not true. So we can ignore
this one, or find a way to make stupid security tool happy.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
7 months ago
Winlin 1f9309ae25
SmartPtr: Support load test for source by srs-bench. v6.0.130 (#4097)
1. Add live benchmark support in srs-bench, which only connects and
disconnects without any media transport, to test source creation and
disposal and verify source memory leaks.
2. SmartPtr: Support cleanup of HTTP-FLV stream. Unregister the HTTP-FLV
handler for the pattern and clean up the objects and resources.
3. Support benchmarking RTMP/SRT with srs-bench by integrating the gosrt
and oryx RTMP libraries.
4. Refine SRT and RTC sources by using a timer to clean up the sources,
following the same strategy as the Live source.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: Jacob Su <suzp1984@gmail.com>
7 months ago