mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
兼容一些奇怪的rtsp流:#1031
This commit is contained in:
parent
8b1d1d6e24
commit
07c5341fb0
@ -26,7 +26,18 @@
|
|||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
||||||
if (strcasecmp(track->_codec.data(), "mpeg4-generic") == 0) {
|
auto codec = getCodecId(track->_codec);
|
||||||
|
if (codec == CodecInvalid) {
|
||||||
|
//根据传统的payload type 获取编码类型以及采样率等信息
|
||||||
|
codec = RtpPayload::getCodecId(track->_pt);
|
||||||
|
}
|
||||||
|
switch (codec) {
|
||||||
|
case CodecG711A:
|
||||||
|
case CodecG711U: return std::make_shared<G711Track>(codec, track->_samplerate, track->_channel, 16);
|
||||||
|
case CodecL16: return std::make_shared<L16Track>(track->_samplerate, track->_channel);
|
||||||
|
case CodecOpus : return std::make_shared<OpusTrack>();
|
||||||
|
|
||||||
|
case CodecAAC : {
|
||||||
string aac_cfg_str = FindField(track->_fmtp.data(), "config=", ";");
|
string aac_cfg_str = FindField(track->_fmtp.data(), "config=", ";");
|
||||||
if (aac_cfg_str.empty()) {
|
if (aac_cfg_str.empty()) {
|
||||||
aac_cfg_str = FindField(track->_fmtp.data(), "config=", nullptr);
|
aac_cfg_str = FindField(track->_fmtp.data(), "config=", nullptr);
|
||||||
@ -45,25 +56,9 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
return std::make_shared<AACTrack>(aac_cfg);
|
return std::make_shared<AACTrack>(aac_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "opus") == 0) {
|
case CodecH264 : {
|
||||||
return std::make_shared<OpusTrack>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "PCMA") == 0) {
|
|
||||||
return std::make_shared<G711Track>(CodecG711A, track->_samplerate, track->_channel, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "PCMU") == 0) {
|
|
||||||
return std::make_shared<G711Track>(CodecG711U, track->_samplerate, track->_channel, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "L16") == 0) {
|
|
||||||
return std::make_shared<L16Track>(track->_samplerate, track->_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "h264") == 0) {
|
|
||||||
//a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
|
//a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
|
||||||
auto map = Parser::parseArgs(FindField(track->_fmtp.data()," ", nullptr),";","=");
|
auto map = Parser::parseArgs(track->_fmtp, ";", "=");
|
||||||
auto sps_pps = map["sprop-parameter-sets"];
|
auto sps_pps = map["sprop-parameter-sets"];
|
||||||
string base64_SPS = FindField(sps_pps.data(), NULL, ",");
|
string base64_SPS = FindField(sps_pps.data(), NULL, ",");
|
||||||
string base64_PPS = FindField(sps_pps.data(), ",", NULL);
|
string base64_PPS = FindField(sps_pps.data(), ",", NULL);
|
||||||
@ -73,13 +68,12 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
//如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps
|
//如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps
|
||||||
return std::make_shared<H264Track>();
|
return std::make_shared<H264Track>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<H264Track>(sps, pps, 0, 0);
|
return std::make_shared<H264Track>(sps, pps, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "h265") == 0) {
|
case CodecH265: {
|
||||||
//a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA=
|
//a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA=
|
||||||
auto map = Parser::parseArgs(FindField(track->_fmtp.data()," ", nullptr),";","=");
|
auto map = Parser::parseArgs(track->_fmtp, ";", "=");
|
||||||
auto vps = decodeBase64(map["sprop-vps"]);
|
auto vps = decodeBase64(map["sprop-vps"]);
|
||||||
auto sps = decodeBase64(map["sprop-sps"]);
|
auto sps = decodeBase64(map["sprop-sps"]);
|
||||||
auto pps = decodeBase64(map["sprop-pps"]);
|
auto pps = decodeBase64(map["sprop-pps"]);
|
||||||
@ -90,17 +84,13 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
return std::make_shared<H265Track>(vps, sps, pps, 0, 0, 0);
|
return std::make_shared<H265Track>(vps, sps, pps, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//可以根据传统的payload type 获取编码类型以及采样率等信息
|
default: {
|
||||||
CodecId codec_id = RtpPayload::getCodecId(track->_pt);
|
//其他codec不支持
|
||||||
switch (codec_id){
|
WarnL << "暂不支持该rtsp编码类型:" << track->getName();
|
||||||
case CodecG711A :
|
|
||||||
case CodecG711U : return std::make_shared<G711Track>(codec_id, track->_samplerate, track->_channel, 16);
|
|
||||||
default : break;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnL << "暂不支持该sdp:" << track->getName();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
|
RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
|
||||||
GET_CONFIG(uint32_t,audio_mtu,Rtp::kAudioMtuSize);
|
GET_CONFIG(uint32_t,audio_mtu,Rtp::kAudioMtuSize);
|
||||||
|
@ -19,7 +19,8 @@ int RtpPayload::getClockRate(int pt){
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return clock_rate;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return clock_rate;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default: return 90000;
|
default:
|
||||||
|
return 90000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +29,8 @@ TrackType RtpPayload::getTrackType(int pt){
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return type;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return type;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default: return TrackInvalid;
|
default:
|
||||||
|
return TrackInvalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +39,8 @@ int RtpPayload::getAudioChannel(int pt){
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return channel;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return channel;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default: return 1;
|
default:
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +49,8 @@ const char * RtpPayload::getName(int pt){
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default: return "unknown payload type";
|
default:
|
||||||
|
return "unknown payload type";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,11 +59,12 @@ CodecId RtpPayload::getCodecId(int pt) {
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return codec_id;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return codec_id;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default : return CodecInvalid;
|
default :
|
||||||
|
return CodecInvalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getAttrSdp(const map<string, string> &attr, _StrPrinter &printer){
|
static void getAttrSdp(const multimap<string, string> &attr, _StrPrinter &printer) {
|
||||||
const map<string, string>::value_type *ptr = nullptr;
|
const map<string, string>::value_type *ptr = nullptr;
|
||||||
for (auto &pr : attr) {
|
for (auto &pr : attr) {
|
||||||
if (pr.first == "control") {
|
if (pr.first == "control") {
|
||||||
@ -82,7 +87,8 @@ string SdpTrack::getName() const{
|
|||||||
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name;
|
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name;
|
||||||
RTP_PT_MAP(SWITCH_CASE)
|
RTP_PT_MAP(SWITCH_CASE)
|
||||||
#undef SWITCH_CASE
|
#undef SWITCH_CASE
|
||||||
default: return _codec;
|
default:
|
||||||
|
return _codec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,9 +206,9 @@ void SdpParser::load(const string &sdp) {
|
|||||||
case 'a': {
|
case 'a': {
|
||||||
string attr = FindField(opt_val.data(), nullptr, ":");
|
string attr = FindField(opt_val.data(), nullptr, ":");
|
||||||
if (attr.empty()) {
|
if (attr.empty()) {
|
||||||
track->_attr[opt_val] = "";
|
track->_attr.emplace(opt_val, "");
|
||||||
} else {
|
} else {
|
||||||
track->_attr[attr] = FindField(opt_val.data(), ":", nullptr);
|
track->_attr.emplace(attr, FindField(opt_val.data(), ":", nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -229,13 +235,18 @@ void SdpParser::load(const string &sdp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it = track._attr.find("rtpmap");
|
for (it = track._attr.find("rtpmap"); it != track._attr.end();) {
|
||||||
if (it != track._attr.end()) {
|
auto &rtpmap = it->second;
|
||||||
auto rtpmap = it->second;
|
|
||||||
int pt, samplerate, channel;
|
int pt, samplerate, channel;
|
||||||
char codec[16] = {0};
|
char codec[16] = {0};
|
||||||
|
|
||||||
|
sscanf(rtpmap.data(), "%d", &pt);
|
||||||
|
if (track._pt != pt) {
|
||||||
|
//pt不匹配
|
||||||
|
it = track._attr.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (4 == sscanf(rtpmap.data(), "%d %15[^/]/%d/%d", &pt, codec, &samplerate, &channel)) {
|
if (4 == sscanf(rtpmap.data(), "%d %15[^/]/%d/%d", &pt, codec, &samplerate, &channel)) {
|
||||||
track._pt = pt;
|
|
||||||
track._codec = codec;
|
track._codec = codec;
|
||||||
track._samplerate = samplerate;
|
track._samplerate = samplerate;
|
||||||
track._channel = channel;
|
track._channel = channel;
|
||||||
@ -248,11 +259,20 @@ void SdpParser::load(const string &sdp) {
|
|||||||
//未设置视频采样率时,赋值为90000
|
//未设置视频采样率时,赋值为90000
|
||||||
track._samplerate = 90000;
|
track._samplerate = 90000;
|
||||||
}
|
}
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = track._attr.find("fmtp");
|
for (it = track._attr.find("fmtp"); it != track._attr.end(); ) {
|
||||||
if (it != track._attr.end()) {
|
auto &fmtp = it->second;
|
||||||
track._fmtp = it->second;
|
int pt;
|
||||||
|
sscanf(fmtp.data(), "%d", &pt);
|
||||||
|
if (track._pt != pt) {
|
||||||
|
//pt不匹配
|
||||||
|
it = track._attr.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
track._fmtp = FindField(fmtp.data(), " ", nullptr);
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = track._attr.find("control");
|
it = track._attr.find("control");
|
||||||
|
@ -220,7 +220,7 @@ public:
|
|||||||
float _end = 0;
|
float _end = 0;
|
||||||
|
|
||||||
map<char, string> _other;
|
map<char, string> _other;
|
||||||
map<string, string> _attr;
|
multimap<string, string> _attr;
|
||||||
|
|
||||||
string toString() const;
|
string toString() const;
|
||||||
string getName() const;
|
string getName() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user