mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
WHIP: Support DELETE resource for Larix Broadcaster. v5.0.148 v6.0.36 (#3427)
* WHIP: Support DELETE resource. * Support push by Larix. * FLV: Disable stash buffer for realtime. * WHEP: Fix muted issue. ------- Co-authored-by: chundonglinlin <chundonglinlin@163.com> Co-authored-by: panda <542638787@qq.com>
This commit is contained in:
parent
c001acaae9
commit
363e0c2a6e
9 changed files with 67 additions and 34 deletions
|
@ -8,6 +8,7 @@ The changelog for SRS.
|
|||
|
||||
## SRS 6.0 Changelog
|
||||
|
||||
* v6.0, 2023-03-22, Merge [#3427](https://github.com/ossrs/srs/pull/3427): WHIP: Support DELETE resource for Larix Broadcaster. v6.0.36 (#3427)
|
||||
* v6.0, 2023-03-20, Merge [#3460](https://github.com/ossrs/srs/pull/3460): WebRTC: Support WHIP/WHEP players. v6.0.35 (#3460)
|
||||
* v6.0, 2023-03-07, Merge [#3441](https://github.com/ossrs/srs/pull/3441): HEVC: webrtc support hevc on safari. v6.0.34 (#3441)
|
||||
* v6.0, 2023-03-07, Merge [#3446](https://github.com/ossrs/srs/pull/3446): WebRTC: Warning if no ideal profile. v6.0.33 (#3446)
|
||||
|
@ -49,6 +50,7 @@ The changelog for SRS.
|
|||
|
||||
## SRS 5.0 Changelog
|
||||
|
||||
* v5.0, 2023-03-22, Merge [#3427](https://github.com/ossrs/srs/pull/3427): WHIP: Support DELETE resource for Larix Broadcaster. v5.0.148 (#3427)
|
||||
* v5.0, 2023-03-20, Merge [#3460](https://github.com/ossrs/srs/pull/3460): WebRTC: Support WHIP/WHEP players. v5.0.147 (#3460)
|
||||
* v5.0, 2023-03-07, Merge [#3446](https://github.com/ossrs/srs/pull/3446): WebRTC: Warning if no ideal profile. v5.0.146 (#3446)
|
||||
* v5.0, 2023-03-06, Merge [#3445](https://github.com/ossrs/srs/pull/3445): Support configure for generic linux. v5.0.145 (#3445)
|
||||
|
|
|
@ -61,6 +61,7 @@ The features of SRS.
|
|||
- [x] RTC: [Experimental] Support transmux RTC to RTMP, [#2093](https://github.com/ossrs/srs/issues/2093). v4.0.95
|
||||
- [x] RTC: [Experimental] Support WebRTC over TCP directly, [#2852](https://github.com/ossrs/srs/issues/2852). v5.0.60+
|
||||
- [x] RTC: [Experimental] Support WHIP(WebRTC-HTTP ingestion protocol), [#3170](https://github.com/ossrs/srs/issues/3170). v5.0.61+
|
||||
- [x] RTC: [Experimental] Support [Larix Broadcaster](https://softvelum.com/larix/), [#3476](https://github.com/ossrs/srs/issues/3476). v5.0.148+
|
||||
- [x] Other: Support ingesting([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/ingest), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/ingest)) other protocols to SRS by FFMPEG. v1.0.0+
|
||||
- [x] Other: Support forwarding([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/forward), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/forward)) to other RTMP servers. v1.0.0+
|
||||
- [x] Other: Support transcoding([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/ffmpeg), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/ffmpeg)) by FFMPEG. v1.0.0+
|
||||
|
|
|
@ -83,7 +83,7 @@ function SrsRtcPublisherAsync() {
|
|||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
|
||||
const data = JSON.parse(xhr.responseText);
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
|
@ -318,7 +318,7 @@ function SrsRtcPlayerAsync() {
|
|||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
|
||||
const data = JSON.parse(xhr.responseText);
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
|
@ -553,7 +553,7 @@ function SrsRtcWhipWhepAsync() {
|
|||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
|
||||
const data = xhr.responseText;
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
|
@ -586,7 +586,7 @@ function SrsRtcWhipWhepAsync() {
|
|||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
|
||||
const data = xhr.responseText;
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
|
||||
show_for_video_ok();
|
||||
|
||||
tsPlayer = mpegts.createPlayer({type: 'mpegts', url: r.url, isLive: true});
|
||||
tsPlayer = mpegts.createPlayer({type: 'mpegts', url: r.url, isLive: true, enableStashBuffer: false});
|
||||
tsPlayer.attachMediaElement(document.getElementById('video_player'));
|
||||
tsPlayer.load();
|
||||
tsPlayer.play();
|
||||
|
@ -264,7 +264,7 @@
|
|||
|
||||
show_for_video_ok();
|
||||
|
||||
flvPlayer = mpegts.createPlayer({type: 'flv', url: r.url, isLive: true});
|
||||
flvPlayer = mpegts.createPlayer({type: 'flv', url: r.url, isLive: true, enableStashBuffer: false});
|
||||
flvPlayer.attachMediaElement(document.getElementById('video_player'));
|
||||
flvPlayer.load();
|
||||
flvPlayer.play();
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</div>
|
||||
|
||||
<label></label>
|
||||
<video id="rtc_media_player" width="320" autoplay muted></video>
|
||||
<video id="rtc_media_player" controls autoplay></video>
|
||||
|
||||
<label></label>
|
||||
SessionID: <span id='sessionid'></span>
|
||||
|
|
|
@ -600,6 +600,41 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
|||
// For each RTC session, we use short-term HTTP connection.
|
||||
w->header()->set("Connection", "Close");
|
||||
|
||||
// Client stop publish.
|
||||
// TODO: FIXME: Stop and cleanup the RTC session.
|
||||
if (r->method() == SRS_CONSTS_HTTP_DELETE) {
|
||||
srs_trace("WHIP: Delete stream %s", r->url().c_str());
|
||||
w->write_header(SRS_CONSTS_HTTP_OK);
|
||||
return w->write(NULL, 0);
|
||||
}
|
||||
|
||||
SrsRtcUserConfig ruc;
|
||||
if ((err = do_serve_http(w, r, &ruc)) != srs_success) {
|
||||
return srs_error_wrap(err, "serve");
|
||||
}
|
||||
if (ruc.local_sdp_str_.empty()) {
|
||||
return srs_go_http_error(w, SRS_CONSTS_HTTP_InternalServerError);
|
||||
}
|
||||
|
||||
// The SDP to response.
|
||||
string sdp = ruc.local_sdp_str_;
|
||||
|
||||
// Setup the content type to SDP.
|
||||
w->header()->set("Content-Type", "application/sdp");
|
||||
// The location for DELETE resource, not required by SRS, but required by WHIP.
|
||||
w->header()->set("Location", srs_fmt("/rtc/v1/whip/?app=%s&stream=%s", ruc.req_->app.c_str(), ruc.req_->stream.c_str()));
|
||||
w->header()->set_content_length((int64_t)sdp.length());
|
||||
// Must be 201, see https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
|
||||
w->write_header(201);
|
||||
|
||||
// Response the SDP content.
|
||||
return w->write((char*)sdp.data(), (int)sdp.length());
|
||||
}
|
||||
|
||||
srs_error_t SrsGoApiRtcWhip::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, SrsRtcUserConfig* ruc)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
string remote_sdp_str;
|
||||
if ((err = r->body_read_all(remote_sdp_str)) != srs_success) {
|
||||
return srs_error_wrap(err, "read sdp");
|
||||
|
@ -632,48 +667,41 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
|||
}
|
||||
|
||||
// The RTC user config object.
|
||||
SrsRtcUserConfig ruc;
|
||||
ruc.req_->ip = clientip;
|
||||
ruc.req_->host = r->host();
|
||||
ruc.req_->vhost = ruc.req_->host;
|
||||
ruc.req_->app = app.empty() ? "live" : app;
|
||||
ruc.req_->stream = stream.empty() ? "livestream" : stream;
|
||||
ruc.req_->param = r->query();
|
||||
ruc->req_->ip = clientip;
|
||||
ruc->req_->host = r->host();
|
||||
ruc->req_->vhost = ruc->req_->host;
|
||||
ruc->req_->app = app.empty() ? "live" : app;
|
||||
ruc->req_->stream = stream.empty() ? "livestream" : stream;
|
||||
ruc->req_->param = r->query();
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective* parsed_vhost = _srs_config->get_vhost(ruc.req_->vhost);
|
||||
SrsConfDirective* parsed_vhost = _srs_config->get_vhost(ruc->req_->vhost);
|
||||
if (parsed_vhost) {
|
||||
ruc.req_->vhost = parsed_vhost->arg0();
|
||||
ruc->req_->vhost = parsed_vhost->arg0();
|
||||
}
|
||||
|
||||
srs_trace("RTC whip %s %s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, codec=%s, param=%s",
|
||||
action.c_str(), ruc.req_->get_stream_url().c_str(), clientip.c_str(), ruc.req_->app.c_str(), ruc.req_->stream.c_str(),
|
||||
remote_sdp_str.length(), eip.c_str(), codec.c_str(), ruc.req_->param.c_str()
|
||||
action.c_str(), ruc->req_->get_stream_url().c_str(), clientip.c_str(), ruc->req_->app.c_str(), ruc->req_->stream.c_str(),
|
||||
remote_sdp_str.length(), eip.c_str(), codec.c_str(), ruc->req_->param.c_str()
|
||||
);
|
||||
|
||||
ruc.eip_ = eip;
|
||||
ruc.codec_ = codec;
|
||||
ruc.publish_ = (action == "publish");
|
||||
ruc.dtls_ = ruc.srtp_ = true;
|
||||
ruc->eip_ = eip;
|
||||
ruc->codec_ = codec;
|
||||
ruc->publish_ = (action == "publish");
|
||||
ruc->dtls_ = ruc->srtp_ = true;
|
||||
|
||||
// TODO: FIXME: It seems remote_sdp doesn't represents the full SDP information.
|
||||
ruc.remote_sdp_str_ = remote_sdp_str;
|
||||
if ((err = ruc.remote_sdp_.parse(remote_sdp_str)) != srs_success) {
|
||||
ruc->remote_sdp_str_ = remote_sdp_str;
|
||||
if ((err = ruc->remote_sdp_.parse(remote_sdp_str)) != srs_success) {
|
||||
return srs_error_wrap(err, "parse sdp failed: %s", remote_sdp_str.c_str());
|
||||
}
|
||||
|
||||
err = action == "publish" ? publish_->serve_http(w, r, &ruc) : play_->serve_http(w, r, &ruc);
|
||||
err = action == "publish" ? publish_->serve_http(w, r, ruc) : play_->serve_http(w, r, ruc);
|
||||
if (err != srs_success) {
|
||||
return srs_error_wrap(err, "serve");
|
||||
}
|
||||
|
||||
if (ruc.local_sdp_str_.empty()) {
|
||||
return srs_go_http_error(w, SRS_CONSTS_HTTP_InternalServerError);
|
||||
}
|
||||
|
||||
string sdp = ruc.local_sdp_str_;
|
||||
w->header()->set("Content-Type", "application/sdp");
|
||||
return w->write((char*)sdp.data(), (int)sdp.length());
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsGoApiRtcNACK::SrsGoApiRtcNACK(SrsRtcServer* server)
|
||||
|
|
|
@ -65,6 +65,8 @@ public:
|
|||
virtual ~SrsGoApiRtcWhip();
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
|
||||
private:
|
||||
virtual srs_error_t do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, SrsRtcUserConfig* ruc);
|
||||
};
|
||||
|
||||
class SrsGoApiRtcNACK : public ISrsHttpHandler
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 147
|
||||
#define VERSION_REVISION 148
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 6
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 35
|
||||
#define VERSION_REVISION 36
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue