mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
RTC: Fix rtmp to rtc bug
This commit is contained in:
parent
7ad1dfbbb8
commit
6dd77923ca
3 changed files with 119 additions and 22 deletions
|
@ -1554,8 +1554,6 @@ void SrsRtcPublishStream::update_send_report_time(uint32_t ssrc, const SrsNtp& n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SrsRtcConnection::ssrc_num = 0;
|
|
||||||
|
|
||||||
SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s)
|
SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s)
|
||||||
{
|
{
|
||||||
req = NULL;
|
req = NULL;
|
||||||
|
@ -2516,11 +2514,6 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S
|
||||||
return srs_error_wrap(err, "fetch rtc source");
|
return srs_error_wrap(err, "fetch rtc source");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: Avoid SSRC collision.
|
|
||||||
if (!ssrc_num) {
|
|
||||||
ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < remote_sdp.media_descs_.size(); ++i) {
|
for (size_t i = 0; i < remote_sdp.media_descs_.size(); ++i) {
|
||||||
const SrsMediaDesc& remote_media_desc = remote_sdp.media_descs_[i];
|
const SrsMediaDesc& remote_media_desc = remote_sdp.media_descs_[i];
|
||||||
// Whether feature enabled in remote extmap.
|
// Whether feature enabled in remote extmap.
|
||||||
|
@ -2536,12 +2529,17 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SrsRtcTrackDescription*> track_descs;
|
std::vector<SrsRtcTrackDescription*> track_descs;
|
||||||
|
std::vector<std::string> remote_rtcp_fb;
|
||||||
if (remote_media_desc.is_audio()) {
|
if (remote_media_desc.is_audio()) {
|
||||||
// TODO: check opus format specific param
|
// TODO: check opus format specific param
|
||||||
std::vector<SrsMediaPayloadType> payloads = remote_media_desc.find_media_with_encoding_name("opus");
|
std::vector<SrsMediaPayloadType> payloads = remote_media_desc.find_media_with_encoding_name("opus");
|
||||||
if (payloads.empty()) {
|
if (payloads.empty()) {
|
||||||
return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type");
|
return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsMediaPayloadType payload = payloads.at(0);
|
||||||
|
remote_rtcp_fb = payload.rtcp_fb_;
|
||||||
|
|
||||||
track_descs = source->get_track_desc("audio", "opus");
|
track_descs = source->get_track_desc("audio", "opus");
|
||||||
} else if (remote_media_desc.is_video()) {
|
} else if (remote_media_desc.is_video()) {
|
||||||
// TODO: check opus format specific param
|
// TODO: check opus format specific param
|
||||||
|
@ -2549,25 +2547,34 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S
|
||||||
if (payloads.empty()) {
|
if (payloads.empty()) {
|
||||||
return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type");
|
return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsMediaPayloadType payload = payloads.at(0);
|
||||||
|
remote_rtcp_fb = payload.rtcp_fb_;
|
||||||
|
|
||||||
track_descs = source->get_track_desc("video", "H264");
|
track_descs = source->get_track_desc("video", "H264");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < track_descs.size(); ++i) {
|
for (int i = 0; i < track_descs.size(); ++i) {
|
||||||
SrsRtcTrackDescription* track = track_descs[i]->copy();
|
SrsRtcTrackDescription* track = track_descs[i]->copy();
|
||||||
|
track->mid_ = remote_media_desc.mid_;
|
||||||
uint32_t publish_ssrc = track->ssrc_;
|
uint32_t publish_ssrc = track->ssrc_;
|
||||||
|
|
||||||
track->media_->rtcp_fbs_.clear();
|
track->media_->rtcp_fbs_.clear();
|
||||||
|
track->extmaps_.clear();
|
||||||
|
|
||||||
|
for (int j = 0; j < (int)remote_rtcp_fb.size(); j++) {
|
||||||
if (nack_enabled) {
|
if (nack_enabled) {
|
||||||
track->media_->rtcp_fbs_.push_back("nack");
|
if (remote_rtcp_fb.at(j) == "nack" || remote_rtcp_fb.at(j) == "nack pli" || remote_rtcp_fb.at(j) == "transport-cc") {
|
||||||
track->media_->rtcp_fbs_.push_back("nack pli");
|
track->media_->rtcp_fbs_.push_back(remote_rtcp_fb.at(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track->extmaps_.clear();
|
|
||||||
if (twcc_enabled && remote_twcc_id) {
|
if (twcc_enabled && remote_twcc_id) {
|
||||||
track->add_rtp_extension_desc(remote_twcc_id, kTWCCExt);
|
track->add_rtp_extension_desc(remote_twcc_id, kTWCCExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
track->ssrc_ = ++ssrc_num;
|
track->ssrc_ = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||||
// TODO: FIXME: set audio_payload rtcp_fbs_,
|
// TODO: FIXME: set audio_payload rtcp_fbs_,
|
||||||
// according by whether downlink is support transport algorithms.
|
// according by whether downlink is support transport algorithms.
|
||||||
// TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt
|
// TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt
|
||||||
|
@ -2603,11 +2610,6 @@ srs_error_t SrsRtcConnection::fetch_source_capability(SrsRequest* req, std::map<
|
||||||
return srs_error_wrap(err, "fetch rtc source");
|
return srs_error_wrap(err, "fetch rtc source");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: Avoid SSRC collision.
|
|
||||||
if (!ssrc_num) {
|
|
||||||
ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SrsRtcTrackDescription*> track_descs = source->get_track_desc("audio", "opus");
|
std::vector<SrsRtcTrackDescription*> track_descs = source->get_track_desc("audio", "opus");
|
||||||
std::vector<SrsRtcTrackDescription*> video_track_desc = source->get_track_desc("video", "H264");
|
std::vector<SrsRtcTrackDescription*> video_track_desc = source->get_track_desc("video", "H264");
|
||||||
|
|
||||||
|
@ -2629,7 +2631,7 @@ srs_error_t SrsRtcConnection::fetch_source_capability(SrsRequest* req, std::map<
|
||||||
track->add_rtp_extension_desc(local_twcc_id, kTWCCExt);
|
track->add_rtp_extension_desc(local_twcc_id, kTWCCExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
track->ssrc_ = ++ssrc_num;
|
track->ssrc_ = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||||
// TODO: FIXME: set audio_payload rtcp_fbs_,
|
// TODO: FIXME: set audio_payload rtcp_fbs_,
|
||||||
// according by whether downlink is support transport algorithms.
|
// according by whether downlink is support transport algorithms.
|
||||||
// TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt
|
// TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include <srs_app_rtc_source.hpp>
|
#include <srs_app_rtc_source.hpp>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <srs_app_conn.hpp>
|
#include <srs_app_conn.hpp>
|
||||||
#include <srs_rtmp_stack.hpp>
|
#include <srs_rtmp_stack.hpp>
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_app_config.hpp>
|
||||||
|
@ -37,13 +39,18 @@
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
#include <srs_app_rtc_queue.hpp>
|
#include <srs_app_rtc_queue.hpp>
|
||||||
#include <srs_app_rtc_conn.hpp>
|
#include <srs_app_rtc_conn.hpp>
|
||||||
|
#include <srs_protocol_utility.hpp>
|
||||||
|
|
||||||
#ifdef SRS_FFMPEG_FIT
|
#ifdef SRS_FFMPEG_FIT
|
||||||
#include <srs_app_rtc_codec.hpp>
|
#include <srs_app_rtc_codec.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const int kChannel = 2;
|
const int kAudioPayloadType = 111;
|
||||||
const int kSamplerate = 48000;
|
const int kAudioChannel = 2;
|
||||||
|
const int kAudioSamplerate = 48000;
|
||||||
|
|
||||||
|
const int kVideoPayloadType = 102;
|
||||||
|
const int kVideoSamplerate = 90000;
|
||||||
|
|
||||||
// An AAC packet may be transcoded to many OPUS packets.
|
// An AAC packet may be transcoded to many OPUS packets.
|
||||||
const int kMaxOpusPackets = 8;
|
const int kMaxOpusPackets = 8;
|
||||||
|
@ -284,6 +291,7 @@ SrsRtcStream::SrsRtcStream()
|
||||||
{
|
{
|
||||||
_can_publish = true;
|
_can_publish = true;
|
||||||
publish_stream_ = NULL;
|
publish_stream_ = NULL;
|
||||||
|
stream_desc_ = NULL;
|
||||||
|
|
||||||
req = NULL;
|
req = NULL;
|
||||||
#ifdef SRS_FFMPEG_FIT
|
#ifdef SRS_FFMPEG_FIT
|
||||||
|
@ -291,7 +299,6 @@ SrsRtcStream::SrsRtcStream()
|
||||||
#else
|
#else
|
||||||
bridger_ = new SrsRtcDummyBridger();
|
bridger_ = new SrsRtcDummyBridger();
|
||||||
#endif
|
#endif
|
||||||
stream_desc_ = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtcStream::~SrsRtcStream()
|
SrsRtcStream::~SrsRtcStream()
|
||||||
|
@ -498,7 +505,7 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcStream* source)
|
||||||
req = NULL;
|
req = NULL;
|
||||||
source_ = source;
|
source_ = source;
|
||||||
format = new SrsRtmpFormat();
|
format = new SrsRtmpFormat();
|
||||||
codec = new SrsAudioRecode(kChannel, kSamplerate);
|
codec = new SrsAudioRecode(kAudioChannel, kAudioSamplerate);
|
||||||
discard_aac = false;
|
discard_aac = false;
|
||||||
discard_bframe = false;
|
discard_bframe = false;
|
||||||
merge_nalus = false;
|
merge_nalus = false;
|
||||||
|
@ -506,6 +513,39 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcStream* source)
|
||||||
audio_timestamp = 0;
|
audio_timestamp = 0;
|
||||||
audio_sequence = 0;
|
audio_sequence = 0;
|
||||||
video_sequence = 0;
|
video_sequence = 0;
|
||||||
|
|
||||||
|
SrsRtcStreamDescription* stream_desc = new SrsRtcStreamDescription();
|
||||||
|
SrsAutoFree(SrsRtcStreamDescription, stream_desc);
|
||||||
|
|
||||||
|
// audio track description
|
||||||
|
if (true) {
|
||||||
|
SrsRtcTrackDescription* audio_track_desc = new SrsRtcTrackDescription();
|
||||||
|
audio_track_desc->type_ = "audio";
|
||||||
|
audio_track_desc->id_ = "audio-" + srs_random_str(8);
|
||||||
|
|
||||||
|
audio_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||||
|
audio_track_desc->ssrc_ = audio_ssrc;
|
||||||
|
audio_track_desc->direction_ = "recvonly";
|
||||||
|
|
||||||
|
audio_track_desc->media_ = new SrsAudioPayload(kAudioPayloadType, "opus", kAudioSamplerate, kAudioChannel);
|
||||||
|
stream_desc->audio_track_desc_ = audio_track_desc->copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// video track description
|
||||||
|
if (true) {
|
||||||
|
SrsRtcTrackDescription* video_track_desc = new SrsRtcTrackDescription();
|
||||||
|
video_track_desc->type_ = "video";
|
||||||
|
video_track_desc->id_ = "video-" + srs_random_str(8);
|
||||||
|
|
||||||
|
video_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||||
|
video_track_desc->ssrc_ = video_ssrc;
|
||||||
|
video_track_desc->direction_ = "recvonly";
|
||||||
|
|
||||||
|
video_track_desc->media_ = new SrsVideoPayload(kVideoPayloadType, "H264", kVideoSamplerate);
|
||||||
|
stream_desc->video_track_descs_.push_back(video_track_desc->copy());
|
||||||
|
}
|
||||||
|
|
||||||
|
source_->set_stream_desc(stream_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger()
|
SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger()
|
||||||
|
@ -672,6 +712,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kAudioPayloadType);
|
||||||
|
pkt->header.set_ssrc(audio_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeAudio;
|
pkt->frame_type = SrsFrameTypeAudio;
|
||||||
pkt->header.set_marker(true);
|
pkt->header.set_marker(true);
|
||||||
pkt->header.set_sequence(audio_sequence++);
|
pkt->header.set_sequence(audio_sequence++);
|
||||||
|
@ -813,6 +855,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kVideoPayloadType);
|
||||||
|
pkt->header.set_ssrc(video_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeVideo;
|
pkt->frame_type = SrsFrameTypeVideo;
|
||||||
pkt->header.set_marker(false);
|
pkt->header.set_marker(false);
|
||||||
pkt->header.set_sequence(video_sequence++);
|
pkt->header.set_sequence(video_sequence++);
|
||||||
|
@ -884,6 +928,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const
|
||||||
if (nn_bytes < kRtpMaxPayloadSize) {
|
if (nn_bytes < kRtpMaxPayloadSize) {
|
||||||
// Package NALUs in a single RTP packet.
|
// Package NALUs in a single RTP packet.
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kVideoPayloadType);
|
||||||
|
pkt->header.set_ssrc(video_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeVideo;
|
pkt->frame_type = SrsFrameTypeVideo;
|
||||||
pkt->header.set_sequence(video_sequence++);
|
pkt->header.set_sequence(video_sequence++);
|
||||||
pkt->header.set_timestamp(msg->timestamp * 90);
|
pkt->header.set_timestamp(msg->timestamp * 90);
|
||||||
|
@ -914,6 +960,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kVideoPayloadType);
|
||||||
|
pkt->header.set_ssrc(video_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeVideo;
|
pkt->frame_type = SrsFrameTypeVideo;
|
||||||
pkt->header.set_sequence(video_sequence++);
|
pkt->header.set_sequence(video_sequence++);
|
||||||
pkt->header.set_timestamp(msg->timestamp * 90);
|
pkt->header.set_timestamp(msg->timestamp * 90);
|
||||||
|
@ -940,6 +988,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg,
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kVideoPayloadType);
|
||||||
|
pkt->header.set_ssrc(video_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeVideo;
|
pkt->frame_type = SrsFrameTypeVideo;
|
||||||
pkt->header.set_sequence(video_sequence++);
|
pkt->header.set_sequence(video_sequence++);
|
||||||
pkt->header.set_timestamp(msg->timestamp * 90);
|
pkt->header.set_timestamp(msg->timestamp * 90);
|
||||||
|
@ -970,6 +1020,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam
|
||||||
int packet_size = srs_min(nb_left, fu_payload_size);
|
int packet_size = srs_min(nb_left, fu_payload_size);
|
||||||
|
|
||||||
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
SrsRtpPacket2* pkt = new SrsRtpPacket2();
|
||||||
|
pkt->header.set_payload_type(kVideoPayloadType);
|
||||||
|
pkt->header.set_ssrc(video_ssrc);
|
||||||
pkt->frame_type = SrsFrameTypeVideo;
|
pkt->frame_type = SrsFrameTypeVideo;
|
||||||
pkt->header.set_sequence(video_sequence++);
|
pkt->header.set_sequence(video_sequence++);
|
||||||
pkt->header.set_timestamp(msg->timestamp * 90);
|
pkt->header.set_timestamp(msg->timestamp * 90);
|
||||||
|
@ -1700,3 +1752,30 @@ srs_error_t SrsRtcVideoSendTrack::on_rtcp(SrsRtpPacket2* pkt)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsRtcSSRCGenerator* SrsRtcSSRCGenerator::_instance = NULL;
|
||||||
|
|
||||||
|
SrsRtcSSRCGenerator::SrsRtcSSRCGenerator()
|
||||||
|
{
|
||||||
|
ssrc_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRtcSSRCGenerator::~SrsRtcSSRCGenerator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRtcSSRCGenerator* SrsRtcSSRCGenerator::instance()
|
||||||
|
{
|
||||||
|
if (!_instance) {
|
||||||
|
_instance = new SrsRtcSSRCGenerator();
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SrsRtcSSRCGenerator::generate_ssrc()
|
||||||
|
{
|
||||||
|
if (!ssrc_num) {
|
||||||
|
ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ++ssrc_num;
|
||||||
|
}
|
||||||
|
|
|
@ -211,6 +211,8 @@ private:
|
||||||
uint32_t audio_timestamp;
|
uint32_t audio_timestamp;
|
||||||
uint16_t audio_sequence;
|
uint16_t audio_sequence;
|
||||||
uint16_t video_sequence;
|
uint16_t video_sequence;
|
||||||
|
uint32_t audio_ssrc;
|
||||||
|
uint32_t video_ssrc;
|
||||||
public:
|
public:
|
||||||
SrsRtcFromRtmpBridger(SrsRtcStream* source);
|
SrsRtcFromRtmpBridger(SrsRtcStream* source);
|
||||||
virtual ~SrsRtcFromRtmpBridger();
|
virtual ~SrsRtcFromRtmpBridger();
|
||||||
|
@ -473,5 +475,19 @@ public:
|
||||||
virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt);
|
virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SrsRtcSSRCGenerator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static SrsRtcSSRCGenerator* _instance;
|
||||||
|
private:
|
||||||
|
uint32_t ssrc_num;
|
||||||
|
private:
|
||||||
|
SrsRtcSSRCGenerator();
|
||||||
|
virtual ~SrsRtcSSRCGenerator();
|
||||||
|
public:
|
||||||
|
static SrsRtcSSRCGenerator* instance();
|
||||||
|
uint32_t generate_ssrc();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue