mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
rtsp支持指定播放单一track (#1937)
This commit is contained in:
parent
d04a6d4355
commit
08789454c3
@ -1 +1 @@
|
|||||||
Subproject commit 82f82e723eda127777aaf91ad0e4615e8d56e8d5
|
Subproject commit 9300828fd9df9f581d1422171a5f13bdc2a4e6ab
|
@ -53,7 +53,7 @@ int main(int argc, char *argv[]) {
|
|||||||
Logger::Instance().add(std::make_shared<ConsoleChannel>());
|
Logger::Instance().add(std::make_shared<ConsoleChannel>());
|
||||||
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
|
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc < 3) {
|
||||||
ErrorL << "\r\n测试方法:./test_player rtxp_url rtp_type\r\n"
|
ErrorL << "\r\n测试方法:./test_player rtxp_url rtp_type\r\n"
|
||||||
<< "例如:./test_player rtsp://admin:123456@127.0.0.1/live/0 0\r\n"
|
<< "例如:./test_player rtsp://admin:123456@127.0.0.1/live/0 0\r\n"
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -119,6 +119,9 @@ int main(int argc, char *argv[]) {
|
|||||||
(*player)[Client::kRtpType] = atoi(argv[2]);
|
(*player)[Client::kRtpType] = atoi(argv[2]);
|
||||||
//不等待track ready再回调播放成功事件,这样可以加快秒开速度
|
//不等待track ready再回调播放成功事件,这样可以加快秒开速度
|
||||||
(*player)[Client::kWaitTrackReady] = false;
|
(*player)[Client::kWaitTrackReady] = false;
|
||||||
|
if (argc > 3) {
|
||||||
|
(*player)[Client::kPlayTrack] = atoi(argv[3]);
|
||||||
|
}
|
||||||
player->play(argv[1]);
|
player->play(argv[1]);
|
||||||
SDLDisplayerHelper::Instance().runLoop();
|
SDLDisplayerHelper::Instance().runLoop();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -317,6 +317,7 @@ const string kMediaTimeoutMS = "media_timeout_ms";
|
|||||||
const string kBeatIntervalMS = "beat_interval_ms";
|
const string kBeatIntervalMS = "beat_interval_ms";
|
||||||
const string kBenchmarkMode = "benchmark_mode";
|
const string kBenchmarkMode = "benchmark_mode";
|
||||||
const string kWaitTrackReady = "wait_track_ready";
|
const string kWaitTrackReady = "wait_track_ready";
|
||||||
|
const string kPlayTrack = "play_track";
|
||||||
} // namespace Client
|
} // namespace Client
|
||||||
|
|
||||||
} // namespace mediakit
|
} // namespace mediakit
|
||||||
|
@ -375,6 +375,9 @@ extern const std::string kBeatIntervalMS;
|
|||||||
extern const std::string kBenchmarkMode;
|
extern const std::string kBenchmarkMode;
|
||||||
// 播放器在触发播放成功事件时,是否等待所有track ready时再回调
|
// 播放器在触发播放成功事件时,是否等待所有track ready时再回调
|
||||||
extern const std::string kWaitTrackReady;
|
extern const std::string kWaitTrackReady;
|
||||||
|
// rtsp播放指定track,可选项有0(不指定,默认)、1(视频)、2(音频)
|
||||||
|
// 设置方法:player[Client::kPlayTrack] = 0/1/2;
|
||||||
|
extern const std::string kPlayTrack;
|
||||||
} // namespace Client
|
} // namespace Client
|
||||||
} // namespace mediakit
|
} // namespace mediakit
|
||||||
|
|
||||||
|
@ -197,13 +197,24 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
|
|||||||
_content_base.pop_back();
|
_content_base.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
SdpParser sdpParser(parser.Content());
|
|
||||||
//解析sdp
|
//解析sdp
|
||||||
_sdp_track = sdpParser.getAvailableTrack();
|
SdpParser sdpParser(parser.Content());
|
||||||
|
|
||||||
|
string sdp;
|
||||||
|
auto play_track = (TrackType)((int)(*this)[Client::kPlayTrack] - 1);
|
||||||
|
if (play_track != TrackInvalid) {
|
||||||
|
auto track = sdpParser.getTrack(play_track);
|
||||||
|
_sdp_track.emplace_back(track);
|
||||||
|
sdp = track->toString();
|
||||||
|
} else {
|
||||||
|
_sdp_track = sdpParser.getAvailableTrack();
|
||||||
|
sdp = sdpParser.toString();
|
||||||
|
}
|
||||||
|
|
||||||
if (_sdp_track.empty()) {
|
if (_sdp_track.empty()) {
|
||||||
throw std::runtime_error("无有效的Sdp Track");
|
throw std::runtime_error("无有效的Sdp Track");
|
||||||
}
|
}
|
||||||
if (!onCheckSDP(sdpParser.toString())) {
|
if (!onCheckSDP(sdp)) {
|
||||||
throw std::runtime_error("onCheckSDP faied");
|
throw std::runtime_error("onCheckSDP faied");
|
||||||
}
|
}
|
||||||
_rtcp_context.clear();
|
_rtcp_context.clear();
|
||||||
|
@ -801,13 +801,14 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
InfoP(this) << "rtsp seekTo(ms):" << iStartTime;
|
InfoP(this) << "rtsp seekTo(ms):" << iStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<TrackType> inited_tracks;
|
||||||
_StrPrinter rtp_info;
|
_StrPrinter rtp_info;
|
||||||
for (auto &track : _sdp_track) {
|
for (auto &track : _sdp_track) {
|
||||||
if (track->_inited == false) {
|
if (track->_inited == false) {
|
||||||
//还有track没有setup
|
//为支持播放器播放单一track, 不校验没有发setup的track
|
||||||
shutdown(SockException(Err_shutdown, "track not setuped"));
|
continue;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
inited_tracks.emplace_back(track->_type);
|
||||||
track->_ssrc = play_src->getSsrc(track->_type);
|
track->_ssrc = play_src->getSsrc(track->_type);
|
||||||
track->_seq = play_src->getSeqence(track->_type);
|
track->_seq = play_src->getSeqence(track->_type);
|
||||||
track->_time_stamp = play_src->getTimeStamp(track->_type);
|
track->_time_stamp = play_src->getTimeStamp(track->_type);
|
||||||
@ -824,6 +825,12 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
res_header.emplace("Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << play_src->getTimeStamp(TrackInvalid) / 1000.0);
|
res_header.emplace("Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << play_src->getTimeStamp(TrackInvalid) / 1000.0);
|
||||||
sendRtspResponse("200 OK", res_header);
|
sendRtspResponse("200 OK", res_header);
|
||||||
|
|
||||||
|
//设置播放track
|
||||||
|
if (inited_tracks.size() == 1) {
|
||||||
|
_target_play_track = inited_tracks[0];
|
||||||
|
InfoP(this) << "指定播放track:" << _target_play_track;
|
||||||
|
}
|
||||||
|
|
||||||
//在回复rtsp信令后再恢复播放
|
//在回复rtsp信令后再恢复播放
|
||||||
play_src->pause(false);
|
play_src->pause(false);
|
||||||
|
|
||||||
@ -956,13 +963,17 @@ void RtspSession::onRcvPeerUdpData(int interleaved, const Buffer::Ptr &buf, cons
|
|||||||
} else if (!_udp_connected_flags.count(interleaved)) {
|
} else if (!_udp_connected_flags.count(interleaved)) {
|
||||||
//这是rtsp播放器的rtp打洞包
|
//这是rtsp播放器的rtp打洞包
|
||||||
_udp_connected_flags.emplace(interleaved);
|
_udp_connected_flags.emplace(interleaved);
|
||||||
_rtp_socks[interleaved / 2]->bindPeerAddr((struct sockaddr *)&addr);
|
if (_rtp_socks[interleaved / 2]) {
|
||||||
|
_rtp_socks[interleaved / 2]->bindPeerAddr((struct sockaddr *)&addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//rtcp包
|
//rtcp包
|
||||||
if (!_udp_connected_flags.count(interleaved)) {
|
if (!_udp_connected_flags.count(interleaved)) {
|
||||||
_udp_connected_flags.emplace(interleaved);
|
_udp_connected_flags.emplace(interleaved);
|
||||||
_rtcp_socks[(interleaved - 1) / 2]->bindPeerAddr((struct sockaddr *)&addr);
|
if (_rtcp_socks[(interleaved - 1) / 2]) {
|
||||||
|
_rtcp_socks[(interleaved - 1) / 2]->bindPeerAddr((struct sockaddr *)&addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onRtcpPacket((interleaved - 1) / 2, _sdp_track[(interleaved - 1) / 2], buf->data(), buf->size());
|
onRtcpPacket((interleaved - 1) / 2, _sdp_track[(interleaved - 1) / 2], buf->data(), buf->size());
|
||||||
}
|
}
|
||||||
@ -1190,32 +1201,39 @@ void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
|||||||
void RtspSession::sendRtpPacket(const RtspMediaSource::RingDataType &pkt) {
|
void RtspSession::sendRtpPacket(const RtspMediaSource::RingDataType &pkt) {
|
||||||
switch (_rtp_type) {
|
switch (_rtp_type) {
|
||||||
case Rtsp::RTP_TCP: {
|
case Rtsp::RTP_TCP: {
|
||||||
size_t i = 0;
|
|
||||||
auto size = pkt->size();
|
|
||||||
setSendFlushFlag(false);
|
setSendFlushFlag(false);
|
||||||
pkt->for_each([&](const RtpPacket::Ptr &rtp) {
|
pkt->for_each([&](const RtpPacket::Ptr &rtp) {
|
||||||
updateRtcpContext(rtp);
|
if (_target_play_track == TrackInvalid || _target_play_track == rtp->type) {
|
||||||
if (++i == size) {
|
updateRtcpContext(rtp);
|
||||||
setSendFlushFlag(true);
|
send(rtp);
|
||||||
}
|
}
|
||||||
send(rtp);
|
|
||||||
});
|
});
|
||||||
|
flushAll();
|
||||||
|
setSendFlushFlag(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Rtsp::RTP_UDP: {
|
case Rtsp::RTP_UDP: {
|
||||||
size_t i = 0;
|
//下标0表示视频,1表示音频
|
||||||
auto size = pkt->size();
|
Socket::Ptr rtp_socks[2];
|
||||||
|
rtp_socks[TrackVideo] = _rtp_socks[getTrackIndexByTrackType(TrackVideo)];
|
||||||
|
rtp_socks[TrackAudio] = _rtp_socks[getTrackIndexByTrackType(TrackAudio)];
|
||||||
pkt->for_each([&](const RtpPacket::Ptr &rtp) {
|
pkt->for_each([&](const RtpPacket::Ptr &rtp) {
|
||||||
updateRtcpContext(rtp);
|
if (_target_play_track == TrackInvalid || _target_play_track == rtp->type) {
|
||||||
int track_index = getTrackIndexByTrackType(rtp->type);
|
updateRtcpContext(rtp);
|
||||||
auto &pSock = _rtp_socks[track_index];
|
auto &sock = rtp_socks[rtp->type];
|
||||||
if (!pSock) {
|
if (!sock) {
|
||||||
shutdown(SockException(Err_shutdown, "udp sock not opened yet"));
|
shutdown(SockException(Err_shutdown, "udp sock not opened yet"));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
_bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize;
|
||||||
|
sock->send(std::make_shared<BufferRtp>(rtp, RtpPacket::kRtpTcpHeaderSize), nullptr, 0, false);
|
||||||
}
|
}
|
||||||
_bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize;
|
|
||||||
pSock->send(std::make_shared<BufferRtp>(rtp, RtpPacket::kRtpTcpHeaderSize), nullptr, 0, ++i == size);
|
|
||||||
});
|
});
|
||||||
|
for (auto &sock : rtp_socks) {
|
||||||
|
if (sock) {
|
||||||
|
sock->flushAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -195,6 +195,8 @@ private:
|
|||||||
RtspMediaSource::RingType::RingReader::Ptr _play_reader;
|
RtspMediaSource::RingType::RingReader::Ptr _play_reader;
|
||||||
//sdp里面有效的track,包含音频或视频
|
//sdp里面有效的track,包含音频或视频
|
||||||
std::vector<SdpTrack::Ptr> _sdp_track;
|
std::vector<SdpTrack::Ptr> _sdp_track;
|
||||||
|
//播放器setup指定的播放track,默认为TrackInvalid表示不指定即音视频都推
|
||||||
|
TrackType _target_play_track = TrackInvalid;
|
||||||
|
|
||||||
////////RTP over udp////////
|
////////RTP over udp////////
|
||||||
//RTP端口,trackid idx 为数组下标
|
//RTP端口,trackid idx 为数组下标
|
||||||
|
Loading…
Reference in New Issue
Block a user