mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-10-06 12:13:49 +08:00
rtsp player add query param for content-base (#2637)
rtsp以content-base为基准,增加url的query参数(根据抓包分析,vlc是这样处理的),以兼容海康rtsp录像流与 直播流,主要是为了兼容这两个issue: #2624 #2501
This commit is contained in:
parent
8ee91d705b
commit
4e33f5b477
|
@ -320,7 +320,6 @@ void splitUrl(const std::string &url, std::string &host, uint16_t &port) {
|
||||||
host = url.substr(0, pos);
|
host = url.substr(0, pos);
|
||||||
checkHost(host);
|
checkHost(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//测试代码
|
//测试代码
|
||||||
static onceToken token([](){
|
static onceToken token([](){
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cinttypes>
|
|
||||||
#include "Rtsp.h"
|
#include "Rtsp.h"
|
||||||
#include "Common/Parser.h"
|
#include "Common/Parser.h"
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
#include "Network/Socket.h"
|
#include "Network/Socket.h"
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
@ -22,7 +22,8 @@ namespace mediakit {
|
||||||
|
|
||||||
int RtpPayload::getClockRate(int pt) {
|
int RtpPayload::getClockRate(int pt) {
|
||||||
switch (pt) {
|
switch (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;
|
||||||
|
@ -31,7 +32,8 @@ int RtpPayload::getClockRate(int pt) {
|
||||||
|
|
||||||
TrackType RtpPayload::getTrackType(int pt) {
|
TrackType RtpPayload::getTrackType(int pt) {
|
||||||
switch (pt) {
|
switch (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;
|
||||||
|
@ -40,7 +42,8 @@ TrackType RtpPayload::getTrackType(int pt) {
|
||||||
|
|
||||||
int RtpPayload::getAudioChannel(int pt) {
|
int RtpPayload::getAudioChannel(int pt) {
|
||||||
switch (pt) {
|
switch (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;
|
||||||
|
@ -49,7 +52,8 @@ int RtpPayload::getAudioChannel(int pt) {
|
||||||
|
|
||||||
const char *RtpPayload::getName(int pt) {
|
const char *RtpPayload::getName(int pt) {
|
||||||
switch (pt) {
|
switch (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";
|
||||||
|
@ -58,7 +62,8 @@ const char *RtpPayload::getName(int pt) {
|
||||||
|
|
||||||
CodecId RtpPayload::getCodecId(int pt) {
|
CodecId RtpPayload::getCodecId(int pt) {
|
||||||
switch (pt) {
|
switch (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;
|
||||||
|
@ -85,7 +90,8 @@ static void getAttrSdp(const multimap<string, string> &attr, _StrPrinter &printe
|
||||||
|
|
||||||
string SdpTrack::getName() const {
|
string SdpTrack::getName() const {
|
||||||
switch (_pt) {
|
switch (_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 _codec;
|
default: return _codec;
|
||||||
|
@ -143,6 +149,7 @@ static TrackType toTrackType(const string &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdpParser::load(const string &sdp) {
|
void SdpParser::load(const string &sdp) {
|
||||||
|
std::multimap<char, std::string> global_infos;
|
||||||
{
|
{
|
||||||
_track_vec.clear();
|
_track_vec.clear();
|
||||||
SdpTrack::Ptr track = std::make_shared<SdpTrack>();
|
SdpTrack::Ptr track = std::make_shared<SdpTrack>();
|
||||||
|
@ -159,17 +166,23 @@ void SdpParser::load(const string &sdp) {
|
||||||
string opt_val = line.substr(2);
|
string opt_val = line.substr(2);
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
|
if (_track_vec.empty())
|
||||||
|
global_infos.emplace(opt, opt_val);
|
||||||
|
else
|
||||||
track->_t = opt_val;
|
track->_t = opt_val;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
|
if (_track_vec.empty())
|
||||||
|
global_infos.emplace(opt, opt_val);
|
||||||
|
else
|
||||||
track->_b = opt_val;
|
track->_b = opt_val;
|
||||||
break;
|
break;
|
||||||
case 'm': {
|
case 'm': {
|
||||||
track = std::make_shared<SdpTrack>();
|
track = std::make_shared<SdpTrack>();
|
||||||
int pt, port, port_count;
|
int pt, port, port_count;
|
||||||
char rtp[16] = { 0 }, type[16];
|
char rtp[16] = { 0 }, type[16];
|
||||||
if (4 == sscanf(opt_val.data(), " %15[^ ] %d %15[^ ] %d", type, &port, rtp, &pt) ||
|
if (4 == sscanf(opt_val.data(), " %15[^ ] %d %15[^ ] %d", type, &port, rtp, &pt)
|
||||||
5 == sscanf(opt_val.data(), " %15[^ ] %d/%d %15[^ ] %d", type, &port, &port_count, rtp, &pt)) {
|
|| 5 == sscanf(opt_val.data(), " %15[^ ] %d/%d %15[^ ] %d", type, &port, &port_count, rtp, &pt)) {
|
||||||
track->_pt = pt;
|
track->_pt = pt;
|
||||||
track->_samplerate = RtpPayload::getClockRate(pt);
|
track->_samplerate = RtpPayload::getClockRate(pt);
|
||||||
track->_channel = RtpPayload::getAudioChannel(pt);
|
track->_channel = RtpPayload::getAudioChannel(pt);
|
||||||
|
@ -182,17 +195,43 @@ void SdpParser::load(const string &sdp) {
|
||||||
case 'a': {
|
case 'a': {
|
||||||
string attr = findSubString(opt_val.data(), nullptr, ":");
|
string attr = findSubString(opt_val.data(), nullptr, ":");
|
||||||
if (attr.empty()) {
|
if (attr.empty()) {
|
||||||
|
if (_track_vec.empty())
|
||||||
|
global_infos.emplace(opt, opt_val);
|
||||||
|
else
|
||||||
track->_attr.emplace(opt_val, "");
|
track->_attr.emplace(opt_val, "");
|
||||||
} else {
|
} else {
|
||||||
|
if (_track_vec.empty())
|
||||||
|
global_infos.emplace(opt, opt_val);
|
||||||
|
else
|
||||||
track->_attr.emplace(attr, findSubString(opt_val.data(), ":", nullptr));
|
track->_attr.emplace(attr, findSubString(opt_val.data(), ":", nullptr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: track->_other[opt] = opt_val; break;
|
default: {
|
||||||
|
if (_track_vec.empty()) {
|
||||||
|
global_infos.emplace(opt, opt_val);
|
||||||
|
} else {
|
||||||
|
track->_other[opt] = opt_val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &info : global_infos) {
|
||||||
|
std::string attr;
|
||||||
|
switch (info.first) {
|
||||||
|
case 'a':
|
||||||
|
attr = findSubString(info.second.data(), nullptr, ":");
|
||||||
|
if (attr == "control") {
|
||||||
|
_control_url = findSubString(info.second.data(), ":", nullptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto &track_ptr : _track_vec) {
|
for (auto &track_ptr : _track_vec) {
|
||||||
auto &track = *track_ptr;
|
auto &track = *track_ptr;
|
||||||
auto it = track._attr.find("range");
|
auto it = track._attr.find("range");
|
||||||
|
@ -315,6 +354,14 @@ string SdpParser::toString() const {
|
||||||
return title + video + audio;
|
return title + video + audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SdpParser::getControlUrl(const std::string &url) const {
|
||||||
|
if (_control_url.find("://") != string::npos) {
|
||||||
|
// 以rtsp://开头
|
||||||
|
return _control_url;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
template <int type>
|
template <int type>
|
||||||
class PortManager : public std::enable_shared_from_this<PortManager<type>> {
|
class PortManager : public std::enable_shared_from_this<PortManager<type>> {
|
||||||
public:
|
public:
|
||||||
|
@ -470,9 +517,7 @@ Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved) {
|
||||||
return rtp_tcp;
|
return rtp_tcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AV_RB16(x) \
|
#define AV_RB16(x) ((((const uint8_t *)(x))[0] << 8) | ((const uint8_t *)(x))[1])
|
||||||
((((const uint8_t*)(x))[0] << 8) | \
|
|
||||||
((const uint8_t*)(x))[1])
|
|
||||||
|
|
||||||
size_t RtpHeader::getCsrcSize() const {
|
size_t RtpHeader::getCsrcSize() const {
|
||||||
// 每个csrc占用4字节
|
// 每个csrc占用4字节
|
||||||
|
@ -608,7 +653,6 @@ RtpPacket::Ptr RtpPacket::create() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造title类型sdp
|
* 构造title类型sdp
|
||||||
* @param dur_sec rtsp点播时长,0代表直播,单位秒
|
* @param dur_sec rtsp点播时长,0代表直播,单位秒
|
||||||
|
@ -616,15 +660,15 @@ RtpPacket::Ptr RtpPacket::create() {
|
||||||
* @param version sdp版本
|
* @param version sdp版本
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TitleSdp::TitleSdp(float dur_sec, const std::map<std::string, std::string>& header, int version) : Sdp(0, 0) {
|
TitleSdp::TitleSdp(float dur_sec, const std::map<std::string, std::string> &header, int version)
|
||||||
|
: Sdp(0, 0) {
|
||||||
_printer << "v=" << version << "\r\n";
|
_printer << "v=" << version << "\r\n";
|
||||||
|
|
||||||
if (!header.empty()) {
|
if (!header.empty()) {
|
||||||
for (auto &pr : header) {
|
for (auto &pr : header) {
|
||||||
_printer << pr.first << "=" << pr.second << "\r\n";
|
_printer << pr.first << "=" << pr.second << "\r\n";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
_printer << "o=- 0 0 IN IP4 0.0.0.0\r\n";
|
_printer << "o=- 0 0 IN IP4 0.0.0.0\r\n";
|
||||||
_printer << "s=Streamed by " << kServerName << "\r\n";
|
_printer << "s=Streamed by " << kServerName << "\r\n";
|
||||||
_printer << "c=IN IP4 0.0.0.0\r\n";
|
_printer << "c=IN IP4 0.0.0.0\r\n";
|
||||||
|
@ -634,8 +678,7 @@ TitleSdp::TitleSdp(float dur_sec, const std::map<std::string, std::string>& head
|
||||||
if (dur_sec <= 0) {
|
if (dur_sec <= 0) {
|
||||||
// 直播
|
// 直播
|
||||||
_printer << "a=range:npt=now-\r\n";
|
_printer << "a=range:npt=now-\r\n";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 点播
|
// 点播
|
||||||
_dur_sec = dur_sec;
|
_dur_sec = dur_sec;
|
||||||
_printer << "a=range:npt=0-" << dur_sec << "\r\n";
|
_printer << "a=range:npt=0-" << dur_sec << "\r\n";
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
#ifndef RTSP_RTSP_H_
|
#ifndef RTSP_RTSP_H_
|
||||||
#define RTSP_RTSP_H_
|
#define RTSP_RTSP_H_
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Common/macros.h"
|
#include "Common/macros.h"
|
||||||
#include "Extension/Frame.h"
|
#include "Extension/Frame.h"
|
||||||
#include "Network/Socket.h"
|
#include "Network/Socket.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
|
@ -53,16 +53,17 @@ typedef enum {
|
||||||
XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \
|
XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \
|
||||||
XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \
|
XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \
|
||||||
XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \
|
XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \
|
||||||
XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid) \
|
XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define ENUM_DEF(name, type, value, clock_rate, channel, codec_id) PT_##name = value,
|
#define ENUM_DEF(name, type, value, clock_rate, channel, codec_id) PT_##name = value,
|
||||||
RTP_PT_MAP(ENUM_DEF)
|
RTP_PT_MAP(ENUM_DEF)
|
||||||
#undef ENUM_DEF
|
#undef ENUM_DEF
|
||||||
PT_MAX = 128
|
PT_MAX
|
||||||
|
= 128
|
||||||
} PayloadType;
|
} PayloadType;
|
||||||
|
|
||||||
};
|
}; // namespace Rtsp
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -141,11 +142,7 @@ private:
|
||||||
class RtpPacket : public toolkit::BufferRaw {
|
class RtpPacket : public toolkit::BufferRaw {
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<RtpPacket>;
|
using Ptr = std::shared_ptr<RtpPacket>;
|
||||||
enum {
|
enum { kRtpVersion = 2, kRtpHeaderSize = 12, kRtpTcpHeaderSize = 4 };
|
||||||
kRtpVersion = 2,
|
|
||||||
kRtpHeaderSize = 12,
|
|
||||||
kRtpTcpHeaderSize = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取rtp头
|
// 获取rtp头
|
||||||
RtpHeader *getHeader();
|
RtpHeader *getHeader();
|
||||||
|
@ -246,9 +243,11 @@ public:
|
||||||
SdpTrack::Ptr getTrack(TrackType type) const;
|
SdpTrack::Ptr getTrack(TrackType type) const;
|
||||||
std::vector<SdpTrack::Ptr> getAvailableTrack() const;
|
std::vector<SdpTrack::Ptr> getAvailableTrack() const;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
std::string getControlUrl(const std::string &url) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<SdpTrack::Ptr> _track_vec;
|
std::vector<SdpTrack::Ptr> _track_vec;
|
||||||
|
std::string _control_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -280,17 +279,13 @@ public:
|
||||||
* 获取pt
|
* 获取pt
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
uint8_t getPayloadType() const{
|
uint8_t getPayloadType() const { return _payload_type; }
|
||||||
return _payload_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取采样率
|
* 获取采样率
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
uint32_t getSampleRate() const{
|
uint32_t getSampleRate() const { return _sample_rate; }
|
||||||
return _sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _payload_type;
|
uint8_t _payload_type;
|
||||||
|
@ -309,21 +304,13 @@ public:
|
||||||
* @param header 自定义sdp描述
|
* @param header 自定义sdp描述
|
||||||
* @param version sdp版本
|
* @param version sdp版本
|
||||||
*/
|
*/
|
||||||
TitleSdp(float dur_sec = 0,
|
TitleSdp(float dur_sec = 0, const std::map<std::string, std::string> &header = std::map<std::string, std::string>(), int version = 0);
|
||||||
const std::map<std::string, std::string> &header = std::map<std::string, std::string>(),
|
|
||||||
int version = 0);
|
|
||||||
|
|
||||||
std::string getSdp() const override {
|
std::string getSdp() const override { return _printer; }
|
||||||
return _printer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecId getCodecId() const override {
|
CodecId getCodecId() const override { return CodecInvalid; }
|
||||||
return CodecInvalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getDuration() const {
|
float getDuration() const { return _dur_sec; }
|
||||||
return _dur_sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _dur_sec = 0;
|
float _dur_sec = 0;
|
||||||
|
|
|
@ -38,8 +38,8 @@ RtspPlayer::~RtspPlayer(void) {
|
||||||
|
|
||||||
void RtspPlayer::sendTeardown() {
|
void RtspPlayer::sendTeardown() {
|
||||||
if (alive()) {
|
if (alive()) {
|
||||||
if (!_content_base.empty()) {
|
if (!_control_url.empty()) {
|
||||||
sendRtspRequest("TEARDOWN", _content_base);
|
sendRtspRequest("TEARDOWN", _control_url);
|
||||||
}
|
}
|
||||||
shutdown(SockException(Err_shutdown, "teardown"));
|
shutdown(SockException(Err_shutdown, "teardown"));
|
||||||
}
|
}
|
||||||
|
@ -203,6 +203,8 @@ void RtspPlayer::handleResDESCRIBE(const Parser &parser) {
|
||||||
// 解析sdp
|
// 解析sdp
|
||||||
SdpParser sdpParser(parser.content());
|
SdpParser sdpParser(parser.content());
|
||||||
|
|
||||||
|
_control_url = sdpParser.getControlUrl(_content_base);
|
||||||
|
|
||||||
string sdp;
|
string sdp;
|
||||||
auto play_track = (TrackType)((int)(*this)[Client::kPlayTrack] - 1);
|
auto play_track = (TrackType)((int)(*this)[Client::kPlayTrack] - 1);
|
||||||
if (play_track != TrackInvalid) {
|
if (play_track != TrackInvalid) {
|
||||||
|
@ -412,7 +414,7 @@ void RtspPlayer::sendKeepAlive() {
|
||||||
_on_response = [](const Parser &parser) {};
|
_on_response = [](const Parser &parser) {};
|
||||||
if (_supported_cmd.find("GET_PARAMETER") != _supported_cmd.end()) {
|
if (_supported_cmd.find("GET_PARAMETER") != _supported_cmd.end()) {
|
||||||
// 支持GET_PARAMETER,用此命令保活
|
// 支持GET_PARAMETER,用此命令保活
|
||||||
sendRtspRequest("GET_PARAMETER", _content_base);
|
sendRtspRequest("GET_PARAMETER", _control_url);
|
||||||
} else {
|
} else {
|
||||||
// 不支持GET_PARAMETER,用OPTIONS命令保活
|
// 不支持GET_PARAMETER,用OPTIONS命令保活
|
||||||
sendRtspRequest("OPTIONS", _play_url);
|
sendRtspRequest("OPTIONS", _play_url);
|
||||||
|
@ -423,12 +425,12 @@ void RtspPlayer::sendPause(int type, uint32_t seekMS) {
|
||||||
_on_response = std::bind(&RtspPlayer::handleResPAUSE, this, placeholders::_1, type);
|
_on_response = std::bind(&RtspPlayer::handleResPAUSE, this, placeholders::_1, type);
|
||||||
// 开启或暂停rtsp
|
// 开启或暂停rtsp
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case type_pause: sendRtspRequest("PAUSE", _content_base); break;
|
case type_pause: sendRtspRequest("PAUSE", _control_url, {}); break;
|
||||||
case type_play:
|
case type_play:
|
||||||
// sendRtspRequest("PLAY", _content_base);
|
// sendRtspRequest("PLAY", _content_base);
|
||||||
// break;
|
// break;
|
||||||
case type_seek:
|
case type_seek:
|
||||||
sendRtspRequest("PLAY", _content_base, { "Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-" });
|
sendRtspRequest("PLAY", _control_url, { "Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-" });
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WarnL << "unknown type : " << type;
|
WarnL << "unknown type : " << type;
|
||||||
|
@ -442,7 +444,7 @@ void RtspPlayer::pause(bool bPause) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspPlayer::speed(float speed) {
|
void RtspPlayer::speed(float speed) {
|
||||||
sendRtspRequest("PLAY", _content_base, { "Scale", StrPrinter << speed });
|
sendRtspRequest("PLAY", _control_url, { "Scale", StrPrinter << speed });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspPlayer::handleResPAUSE(const Parser &parser, int type) {
|
void RtspPlayer::handleResPAUSE(const Parser &parser, int type) {
|
||||||
|
@ -451,7 +453,7 @@ void RtspPlayer::handleResPAUSE(const Parser &parser, int type) {
|
||||||
case type_pause: WarnL << "Pause failed:" << parser.status() << " " << parser.statusStr(); break;
|
case type_pause: WarnL << "Pause failed:" << parser.status() << " " << parser.statusStr(); break;
|
||||||
case type_play:
|
case type_play:
|
||||||
WarnL << "Play failed:" << parser.status() << " " << parser.statusStr();
|
WarnL << "Play failed:" << parser.status() << " " << parser.statusStr();
|
||||||
onPlayResult_l(SockException(Err_shutdown, StrPrinter << "rtsp play failed:" << parser.status() << " " << parser.statusStr()), !_play_check_timer);
|
onPlayResult_l(SockException(Err_other, StrPrinter << "rtsp play failed:" << parser.status() << " " << parser.statusStr()), !_play_check_timer);
|
||||||
break;
|
break;
|
||||||
case type_seek: WarnL << "Seek failed:" << parser.status() << " " << parser.statusStr(); break;
|
case type_seek: WarnL << "Seek failed:" << parser.status() << " " << parser.statusStr(); break;
|
||||||
}
|
}
|
||||||
|
@ -571,6 +573,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const std
|
||||||
key = val;
|
key = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRtspRequest(cmd, url, header_map);
|
sendRtspRequest(cmd, url, header_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,12 +618,9 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const Str
|
||||||
}
|
}
|
||||||
|
|
||||||
_StrPrinter printer;
|
_StrPrinter printer;
|
||||||
if (cmd == "PLAY") {
|
|
||||||
printer << cmd << " " << _play_url << " RTSP/1.0\r\n";
|
|
||||||
} else {
|
|
||||||
printer << cmd << " " << url << " RTSP/1.0\r\n";
|
printer << cmd << " " << url << " RTSP/1.0\r\n";
|
||||||
}
|
|
||||||
|
|
||||||
|
TraceL << cmd << " "<< url;
|
||||||
for (auto &pr : header) {
|
for (auto &pr : header) {
|
||||||
printer << pr.first << ": " << pr.second << "\r\n";
|
printer << pr.first << ": " << pr.second << "\r\n";
|
||||||
}
|
}
|
||||||
|
@ -743,7 +743,7 @@ int RtspPlayer::getTrackIndexByTrackType(TrackType track_type) const {
|
||||||
if (_sdp_track.size() == 1) {
|
if (_sdp_track.size() == 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
throw SockException(Err_shutdown, StrPrinter << "no such track with type:" << getTrackString(track_type));
|
throw SockException(Err_other, StrPrinter << "no such track with type:" << getTrackString(track_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
|
|
|
@ -129,6 +129,7 @@ private:
|
||||||
std::string _session_id;
|
std::string _session_id;
|
||||||
uint32_t _cseq_send = 1;
|
uint32_t _cseq_send = 1;
|
||||||
std::string _content_base;
|
std::string _content_base;
|
||||||
|
std::string _control_url;
|
||||||
Rtsp::eRtpType _rtp_type = Rtsp::RTP_TCP;
|
Rtsp::eRtpType _rtp_type = Rtsp::RTP_TCP;
|
||||||
|
|
||||||
//当前rtp时间戳
|
//当前rtp时间戳
|
||||||
|
|
Loading…
Reference in New Issue
Block a user