mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 02:34:26 +08:00
Add xr targetbitrate process and update js demo sdk (#4031)
Some checks are pending
Android / build (push) Waiting to run
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Docker / build (push) Waiting to run
Linux / build (push) Waiting to run
macOS / build (push) Waiting to run
Windows / build (push) Waiting to run
Some checks are pending
Android / build (push) Waiting to run
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Docker / build (push) Waiting to run
Linux / build (push) Waiting to run
macOS / build (push) Waiting to run
Windows / build (push) Waiting to run
rtc 增加对于rtcp xr target bitrate 的解析,参照 https://webrtc.googlesource.com/src/+/refs/heads/main/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.cc zlmrtcclient.js 更新,修复推屏幕流失败的问题
This commit is contained in:
parent
226b87a633
commit
8868320301
@ -209,8 +209,13 @@ void RtcpHeader::net2Host(size_t len) {
|
|||||||
RtcpXRDLRR *dlrr = (RtcpXRDLRR *)this;
|
RtcpXRDLRR *dlrr = (RtcpXRDLRR *)this;
|
||||||
dlrr->net2Host(len);
|
dlrr->net2Host(len);
|
||||||
TraceL << dlrr->dumpString();
|
TraceL << dlrr->dumpString();
|
||||||
|
} else if (xr->bt == 42){
|
||||||
|
//当有浏览器将屏幕推流到服务器时会发生这个, 暂时没发现什么作用,先解析出来,不做处理
|
||||||
|
RtcpXRTargetBitrate* tb = (RtcpXRTargetBitrate *)this;
|
||||||
|
tb->net2Host(len);
|
||||||
|
//TraceL << tb->dumpString();
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error(StrPrinter << "rtcp xr bt " << xr->bt << " not support");
|
throw std::runtime_error(StrPrinter << "rtcp xr bt " << (int)xr->bt << " not support");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -796,6 +801,71 @@ std::shared_ptr<RtcpXRDLRR> RtcpXRDLRR::create(size_t item_count) {
|
|||||||
return std::shared_ptr<RtcpXRDLRR>(ptr, [](RtcpXRDLRR *ptr) { delete[](char *) ptr; });
|
return std::shared_ptr<RtcpXRDLRR>(ptr, [](RtcpXRDLRR *ptr) { delete[](char *) ptr; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
string RtcpXRTargetBitrateItem::dumpString() const {
|
||||||
|
_StrPrinter printer;
|
||||||
|
|
||||||
|
printer << "Spatial Layer :" << spatial_layer << "\r\n";
|
||||||
|
printer << "Temporal Layer :" << temporal_layer << "\r\n";
|
||||||
|
printer << "Target Bitrate: " << target_bitrate << "\r\n";
|
||||||
|
|
||||||
|
return std::move(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtcpXRTargetBitrateItem::net2Host() {
|
||||||
|
|
||||||
|
target_bitrate = ntohl(target_bitrate) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<RtcpXRTargetBitrateItem *> RtcpXRTargetBitrate::getItemList() {
|
||||||
|
auto count = block_length;
|
||||||
|
RtcpXRTargetBitrateItem *ptr = &items;
|
||||||
|
vector<RtcpXRTargetBitrateItem *> ret;
|
||||||
|
for (int i = 0; i < (int)count; ++i) {
|
||||||
|
ret.emplace_back(ptr);
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
string RtcpXRTargetBitrate::dumpString() const {
|
||||||
|
_StrPrinter printer;
|
||||||
|
printer << RtcpHeader::dumpHeader();
|
||||||
|
printer << "ssrc :" << ssrc << "\r\n";
|
||||||
|
printer << "bt :" << (int)bt << "\r\n";
|
||||||
|
printer << "block_length : " << block_length << "\r\n";
|
||||||
|
auto items_list = ((RtcpXRTargetBitrate *)this)->getItemList();
|
||||||
|
auto i = 0;
|
||||||
|
for (auto &item : items_list) {
|
||||||
|
printer << "---- item:" << i++ << " ----\r\n";
|
||||||
|
printer << item->dumpString();
|
||||||
|
}
|
||||||
|
return std::move(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtcpXRTargetBitrate::net2Host(size_t size) {
|
||||||
|
static const size_t kMinSize = sizeof(RtcpHeader);
|
||||||
|
CHECK_MIN_SIZE(size, kMinSize);
|
||||||
|
|
||||||
|
ssrc = ntohl(ssrc);
|
||||||
|
block_length = ntohs(block_length);
|
||||||
|
|
||||||
|
auto count = block_length;
|
||||||
|
for (int i = 0; i < (int)count; ++i) {
|
||||||
|
RtcpXRTargetBitrateItem *ptr = &items;
|
||||||
|
ptr->net2Host();
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RtcpXRTargetBitrate> RtcpXRTargetBitrate::create(size_t item_count) {
|
||||||
|
auto real_size = sizeof(RtcpXRTargetBitrate) - sizeof(RtcpXRTargetBitrateItem) + item_count * sizeof(RtcpXRTargetBitrateItem);
|
||||||
|
auto bytes = alignSize(real_size);
|
||||||
|
auto ptr = (RtcpXRTargetBitrate *)new char[bytes];
|
||||||
|
setupHeader(ptr, RtcpType::RTCP_XR, 0, bytes);
|
||||||
|
setupPadding(ptr, bytes - real_size);
|
||||||
|
return std::shared_ptr<RtcpXRTargetBitrate>(ptr, [](RtcpXRTargetBitrate *ptr) { delete[](char *) ptr; });
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#include "Util/onceToken.h"
|
#include "Util/onceToken.h"
|
||||||
|
|
||||||
|
100
src/Rtcp/Rtcp.h
100
src/Rtcp/Rtcp.h
@ -772,7 +772,6 @@ private:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 网络字节序转换为主机字节序
|
* 网络字节序转换为主机字节序
|
||||||
* @param size 字节长度,防止内存越界
|
|
||||||
*/
|
*/
|
||||||
void net2Host();
|
void net2Host();
|
||||||
};
|
};
|
||||||
@ -814,6 +813,105 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// RFC 4585: Feedback format.
|
||||||
|
//
|
||||||
|
// Common packet format:
|
||||||
|
//
|
||||||
|
// 0 1 2 3
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | BT=42 | reserved | block length |
|
||||||
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||||
|
//
|
||||||
|
// Target bitrate item (repeat as many times as necessary).
|
||||||
|
//
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | S | T | Target Bitrate |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// : ... :
|
||||||
|
//
|
||||||
|
// Spatial Layer (S): 4 bits
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
//
|
||||||
|
// Temporal Layer (T): 4 bits
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
//
|
||||||
|
// Target Bitrate: 24 bits
|
||||||
|
// The encoder target bitrate for this layer, in kbps.
|
||||||
|
//
|
||||||
|
// As an example of how S and T are intended to be used, VP8 simulcast will
|
||||||
|
// use a separate TargetBitrate message per stream, since they are transmitted
|
||||||
|
// on separate SSRCs, with temporal layers grouped by stream.
|
||||||
|
// If VP9 SVC is used, there will be only one SSRC, so each spatial and
|
||||||
|
// temporal layer combo used shall be specified in the TargetBitrate packet.
|
||||||
|
class RtcpXRTargetBitrateItem {
|
||||||
|
public:
|
||||||
|
friend class RtcpXRTargetBitrate;
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
uint32_t spatial_layer : 4;
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
uint32_t temporal_layer : 4;
|
||||||
|
#else
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
uint32_t temporal_layer : 4;
|
||||||
|
// Indicates which temporal layer this bitrate concerns.
|
||||||
|
uint32_t spatial_layer : 4;
|
||||||
|
#endif
|
||||||
|
//The encoder target bitrate for this layer, in kbps.
|
||||||
|
uint32_t target_bitrate : 24;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 打印字段详情
|
||||||
|
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||||
|
*/
|
||||||
|
std::string dumpString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络字节序转换为主机字节序
|
||||||
|
*/
|
||||||
|
void net2Host();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RtcpXRTargetBitrate : public RtcpHeader {
|
||||||
|
public:
|
||||||
|
friend class RtcpHeader;
|
||||||
|
uint32_t ssrc;
|
||||||
|
uint8_t bt;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint16_t block_length;
|
||||||
|
RtcpXRTargetBitrateItem items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建RtcpXRTargetBitrate包,只赋值了RtcpHeader部分(网络字节序)
|
||||||
|
* @param item_count RtcpXRTargetBitrateItem对象个数
|
||||||
|
* @return RtcpXRTargetBitrate包
|
||||||
|
*/
|
||||||
|
static std::shared_ptr<RtcpXRTargetBitrate> create(size_t item_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取RtcpXRTargetBitrateItem对象指针列表
|
||||||
|
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||||
|
*/
|
||||||
|
std::vector<RtcpXRTargetBitrateItem *> getItemList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 打印字段详情
|
||||||
|
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||||
|
*/
|
||||||
|
std::string dumpString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络字节序转换为主机字节序
|
||||||
|
* @param size 字节长度,防止内存越界
|
||||||
|
*/
|
||||||
|
void net2Host(size_t size);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
} // namespace mediakit
|
} // namespace mediakit
|
||||||
|
@ -15,8 +15,8 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED'
|
CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED'
|
||||||
};
|
};
|
||||||
|
|
||||||
const VERSION$1 = '1.1.0';
|
const VERSION$1 = '1.1.1';
|
||||||
const BUILD_DATE = 'Thu Jun 20 2024 16:15:41 GMT+0800 (China Standard Time)';
|
const BUILD_DATE = 'Tue Nov 19 2024 20:10:15 GMT+0800 (China Standard Time)';
|
||||||
|
|
||||||
// Copyright (C) <2018> Intel Corporation
|
// Copyright (C) <2018> Intel Corporation
|
||||||
//
|
//
|
||||||
@ -9090,6 +9090,12 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
if (this.options.useCamera) {
|
if (this.options.useCamera) {
|
||||||
if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
|
if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
|
||||||
if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
|
if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
|
||||||
|
if (typeof videoConstraints == 'object' && this.options.videoId != '') {
|
||||||
|
videoConstraints.deviceId = this.options.videoId;
|
||||||
|
}
|
||||||
|
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
||||||
|
audioConstraints.deviceId = this.options.audioId;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.options.videoEnable) {
|
if (this.options.videoEnable) {
|
||||||
videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
|
videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
|
||||||
@ -9099,17 +9105,14 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
// error shared display media not only audio
|
// error shared display media not only audio
|
||||||
error(this.TAG, 'error paramter');
|
error(this.TAG, 'error paramter');
|
||||||
}
|
}
|
||||||
|
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
||||||
|
audioConstraints.deviceId = this.options.audioId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') {
|
if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') {
|
||||||
videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h);
|
videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h);
|
||||||
}
|
}
|
||||||
if (typeof videoConstraints == 'object' && this.options.videoId != '') {
|
|
||||||
videoConstraints.deviceId = this.options.videoId;
|
|
||||||
}
|
|
||||||
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
|
||||||
audioConstraints.deviceId = this.options.audioId;
|
|
||||||
}
|
|
||||||
MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => {
|
MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => {
|
||||||
this._localStream = stream;
|
this._localStream = stream;
|
||||||
this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream);
|
this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream);
|
||||||
|
File diff suppressed because one or more lines are too long
@ -15,8 +15,8 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED'
|
CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED'
|
||||||
};
|
};
|
||||||
|
|
||||||
const VERSION$1 = '1.1.0';
|
const VERSION$1 = '1.1.1';
|
||||||
const BUILD_DATE = 'Thu Jun 20 2024 16:15:41 GMT+0800 (China Standard Time)';
|
const BUILD_DATE = 'Tue Nov 19 2024 20:10:15 GMT+0800 (China Standard Time)';
|
||||||
|
|
||||||
// Copyright (C) <2018> Intel Corporation
|
// Copyright (C) <2018> Intel Corporation
|
||||||
//
|
//
|
||||||
@ -9090,6 +9090,12 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
if (this.options.useCamera) {
|
if (this.options.useCamera) {
|
||||||
if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
|
if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
|
||||||
if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
|
if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
|
||||||
|
if (typeof videoConstraints == 'object' && this.options.videoId != '') {
|
||||||
|
videoConstraints.deviceId = this.options.videoId;
|
||||||
|
}
|
||||||
|
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
||||||
|
audioConstraints.deviceId = this.options.audioId;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.options.videoEnable) {
|
if (this.options.videoEnable) {
|
||||||
videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
|
videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
|
||||||
@ -9099,17 +9105,14 @@ var ZLMRTCClient = (function (exports) {
|
|||||||
// error shared display media not only audio
|
// error shared display media not only audio
|
||||||
error(this.TAG, 'error paramter');
|
error(this.TAG, 'error paramter');
|
||||||
}
|
}
|
||||||
|
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
||||||
|
audioConstraints.deviceId = this.options.audioId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') {
|
if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') {
|
||||||
videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h);
|
videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h);
|
||||||
}
|
}
|
||||||
if (typeof videoConstraints == 'object' && this.options.videoId != '') {
|
|
||||||
videoConstraints.deviceId = this.options.videoId;
|
|
||||||
}
|
|
||||||
if (typeof audioConstraints == 'object' && this.options.audioId != '') {
|
|
||||||
audioConstraints.deviceId = this.options.audioId;
|
|
||||||
}
|
|
||||||
MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => {
|
MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => {
|
||||||
this._localStream = stream;
|
this._localStream = stream;
|
||||||
this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream);
|
this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream);
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user