Commit 08789454 by custompal Committed by GitHub

rtsp支持指定播放单一track (#1937)

parent d04a6d43
ZLToolKit @ 9300828f
Subproject commit 82f82e723eda127777aaf91ad0e4615e8d56e8d5 Subproject commit 9300828fd9df9f581d1422171a5f13bdc2a4e6ab
...@@ -53,7 +53,7 @@ int main(int argc, char *argv[]) { ...@@ -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[]) { ...@@ -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"; ...@@ -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; ...@@ -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) { ...@@ -197,13 +197,24 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
_content_base.pop_back(); _content_base.pop_back();
} }
SdpParser sdpParser(parser.Content());
//解析sdp //解析sdp
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_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) { ...@@ -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) { ...@@ -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,14 +963,18 @@ void RtspSession::onRcvPeerUdpData(int interleaved, const Buffer::Ptr &buf, cons ...@@ -956,14 +963,18 @@ 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);
if (_rtp_socks[interleaved / 2]) {
_rtp_socks[interleaved / 2]->bindPeerAddr((struct sockaddr *)&addr); _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);
if (_rtcp_socks[(interleaved - 1) / 2]) {
_rtcp_socks[(interleaved - 1) / 2]->bindPeerAddr((struct sockaddr *)&addr); _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){ ...@@ -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) {
if (_target_play_track == TrackInvalid || _target_play_track == rtp->type) {
updateRtcpContext(rtp); updateRtcpContext(rtp);
if (++i == size) {
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) {
if (_target_play_track == TrackInvalid || _target_play_track == rtp->type) {
updateRtcpContext(rtp); updateRtcpContext(rtp);
int track_index = getTrackIndexByTrackType(rtp->type); auto &sock = rtp_socks[rtp->type];
auto &pSock = _rtp_socks[track_index]; if (!sock) {
if (!pSock) {
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; _bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize;
pSock->send(std::make_shared<BufferRtp>(rtp, RtpPacket::kRtpTcpHeaderSize), nullptr, 0, ++i == size); sock->send(std::make_shared<BufferRtp>(rtp, RtpPacket::kRtpTcpHeaderSize), nullptr, 0, false);
}
}); });
for (auto &sock : rtp_socks) {
if (sock) {
sock->flushAll();
}
}
} }
break; break;
default: default:
......
...@@ -195,6 +195,8 @@ private: ...@@ -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 为数组下标
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论