mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 12:11:36 +08:00
完善线程安全设计
This commit is contained in:
parent
8b0bd2d224
commit
c2ab45f78d
@ -15,6 +15,7 @@
|
|||||||
#include "mk_track.h"
|
#include "mk_track.h"
|
||||||
#include "mk_frame.h"
|
#include "mk_frame.h"
|
||||||
#include "mk_events_objects.h"
|
#include "mk_events_objects.h"
|
||||||
|
#include "mk_thread.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -246,7 +247,7 @@ API_EXPORT void API_CALL mk_media_set_on_regist(mk_media ctx, on_mk_media_source
|
|||||||
typedef on_mk_media_source_send_rtp_result on_mk_media_send_rtp_result;
|
typedef on_mk_media_source_send_rtp_result on_mk_media_send_rtp_result;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始发送一路ps-rtp流(通过ssrc区分多路)
|
* 开始发送一路ps-rtp流(通过ssrc区分多路),此api线程安全
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param dst_url 目标ip或域名
|
* @param dst_url 目标ip或域名
|
||||||
* @param dst_port 目标端口
|
* @param dst_port 目标端口
|
||||||
@ -258,12 +259,18 @@ typedef on_mk_media_source_send_rtp_result on_mk_media_send_rtp_result;
|
|||||||
API_EXPORT void API_CALL mk_media_start_send_rtp(mk_media ctx, const char *dst_url, uint16_t dst_port, const char *ssrc, int is_udp, on_mk_media_send_rtp_result cb, void *user_data);
|
API_EXPORT void API_CALL mk_media_start_send_rtp(mk_media ctx, const char *dst_url, uint16_t dst_port, const char *ssrc, int is_udp, on_mk_media_send_rtp_result cb, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止某路或全部ps-rtp发送
|
* 停止某路或全部ps-rtp发送,此api线程安全
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param ssrc rtp的ssrc,10进制的字符串打印,如果为null或空字符串,则停止所有rtp推流
|
* @param ssrc rtp的ssrc,10进制的字符串打印,如果为null或空字符串,则停止所有rtp推流
|
||||||
* @return 1成功,0失败
|
|
||||||
*/
|
*/
|
||||||
API_EXPORT int API_CALL mk_media_stop_send_rtp(mk_media ctx, const char *ssrc);
|
API_EXPORT void API_CALL mk_media_stop_send_rtp(mk_media ctx, const char *ssrc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所属线程
|
||||||
|
* @param ctx 对象指针
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_thread API_CALL mk_media_get_owner_thread(mk_media ctx);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
template<typename ...ArgsType>
|
template<typename ...ArgsType>
|
||||||
MediaHelper(ArgsType &&...args){
|
MediaHelper(ArgsType &&...args){
|
||||||
_channel = std::make_shared<DevChannel>(std::forward<ArgsType>(args)...);
|
_channel = std::make_shared<DevChannel>(std::forward<ArgsType>(args)...);
|
||||||
|
_poller = EventPollerPool::Instance().getPoller();
|
||||||
}
|
}
|
||||||
~MediaHelper(){}
|
~MediaHelper(){}
|
||||||
|
|
||||||
@ -58,6 +59,11 @@ public:
|
|||||||
_on_regist_data = user_data;
|
_on_regist_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所属线程
|
||||||
|
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override {
|
||||||
|
return _poller;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 通知其停止推流
|
// 通知其停止推流
|
||||||
bool close(MediaSource &sender,bool force) override{
|
bool close(MediaSource &sender,bool force) override{
|
||||||
@ -111,6 +117,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
EventPoller::Ptr _poller;
|
||||||
DevChannel::Ptr _channel;
|
DevChannel::Ptr _channel;
|
||||||
on_mk_media_close _on_close = nullptr;
|
on_mk_media_close _on_close = nullptr;
|
||||||
on_mk_media_seek _on_seek = nullptr;
|
on_mk_media_seek _on_seek = nullptr;
|
||||||
@ -266,16 +273,28 @@ API_EXPORT void API_CALL mk_media_start_send_rtp(mk_media ctx, const char *dst_u
|
|||||||
args.is_udp = is_udp;
|
args.is_udp = is_udp;
|
||||||
|
|
||||||
// sender参数无用
|
// sender参数无用
|
||||||
(*obj)->getChannel()->startSendRtp(MediaSource::NullMediaSource(), args, [cb, user_data](uint16_t local_port, const SockException &ex){
|
auto ref = *obj;
|
||||||
|
(*obj)->getOwnerPoller(MediaSource::NullMediaSource())->async([args, ref, cb, user_data]() {
|
||||||
|
ref->getChannel()->startSendRtp(MediaSource::NullMediaSource(), args, [cb, user_data](uint16_t local_port, const SockException &ex) {
|
||||||
if (cb) {
|
if (cb) {
|
||||||
cb(user_data, local_port, ex.getErrCode(), ex.what());
|
cb(user_data, local_port, ex.getErrCode(), ex.what());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_media_stop_send_rtp(mk_media ctx, const char *ssrc){
|
API_EXPORT void API_CALL mk_media_stop_send_rtp(mk_media ctx, const char *ssrc){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *)ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *)ctx;
|
||||||
// sender参数无用
|
// sender参数无用
|
||||||
return (*obj)->getChannel()->stopSendRtp(MediaSource::NullMediaSource(), ssrc ? ssrc : "");
|
auto ref = *obj;
|
||||||
|
string ssrc_str = ssrc ? ssrc : "";
|
||||||
|
(*obj)->getOwnerPoller(MediaSource::NullMediaSource())->async([ref, ssrc_str]() {
|
||||||
|
ref->getChannel()->stopSendRtp(MediaSource::NullMediaSource(), ssrc_str);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_thread API_CALL mk_media_get_owner_thread(mk_media ctx) {
|
||||||
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *)ctx;
|
||||||
|
return (*obj)->getOwnerPoller(MediaSource::NullMediaSource()).get();
|
||||||
}
|
}
|
@ -576,8 +576,8 @@ MediaSource::Ptr MediaSource::createFromMP4(const string &schema, const string &
|
|||||||
}
|
}
|
||||||
#ifdef ENABLE_MP4
|
#ifdef ENABLE_MP4
|
||||||
try {
|
try {
|
||||||
MP4Reader::Ptr pReader(new MP4Reader(vhost, app, stream, file_path));
|
auto reader = std::make_shared<MP4Reader>(vhost, app, stream, file_path);
|
||||||
pReader->startReadMP4();
|
reader->startReadMP4();
|
||||||
return MediaSource::find(schema, vhost, app, stream);
|
return MediaSource::find(schema, vhost, app, stream);
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
WarnL << ex.what();
|
WarnL << ex.what();
|
||||||
@ -733,7 +733,7 @@ toolkit::EventPoller::Ptr MediaSourceEventInterceptor::getOwnerPoller(MediaSourc
|
|||||||
if (listener) {
|
if (listener) {
|
||||||
return listener->getOwnerPoller(sender);
|
return listener->getOwnerPoller(sender);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return EventPollerPool::Instance().getPoller();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public:
|
|||||||
// 获取丢包率
|
// 获取丢包率
|
||||||
virtual int getLossRate(MediaSource &sender, TrackType type) { return -1; }
|
virtual int getLossRate(MediaSource &sender, TrackType type) { return -1; }
|
||||||
// 获取所在线程
|
// 获取所在线程
|
||||||
virtual toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) { return nullptr; }
|
virtual toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) = 0;
|
||||||
|
|
||||||
////////////////////////仅供MultiMediaSourceMuxer对象继承////////////////////////
|
////////////////////////仅供MultiMediaSourceMuxer对象继承////////////////////////
|
||||||
// 开启或关闭录制
|
// 开启或关闭录制
|
||||||
|
@ -219,9 +219,9 @@ bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiMediaSourceMuxer::startSendRtp(MediaSource &, const MediaSourceEvent::SendRtpArgs &args, const std::function<void(uint16_t, const toolkit::SockException &)> cb) {
|
void MultiMediaSourceMuxer::startSendRtp(MediaSource &sender, const MediaSourceEvent::SendRtpArgs &args, const std::function<void(uint16_t, const toolkit::SockException &)> cb) {
|
||||||
#if defined(ENABLE_RTPPROXY)
|
#if defined(ENABLE_RTPPROXY)
|
||||||
auto rtp_sender = std::make_shared<RtpSender>();
|
auto rtp_sender = std::make_shared<RtpSender>(getOwnerPoller(sender));
|
||||||
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
|
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
|
||||||
rtp_sender->startSend(args, [args, weak_self, rtp_sender, cb](uint16_t local_port, const SockException &ex) mutable {
|
rtp_sender->startSend(args, [args, weak_self, rtp_sender, cb](uint16_t local_port, const SockException &ex) mutable {
|
||||||
cb(local_port, ex);
|
cb(local_port, ex);
|
||||||
|
@ -20,6 +20,8 @@ using namespace toolkit;
|
|||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
MP4Reader::MP4Reader(const string &vhost, const string &app, const string &stream_id, const string &file_path) {
|
MP4Reader::MP4Reader(const string &vhost, const string &app, const string &stream_id, const string &file_path) {
|
||||||
|
//读写文件建议放在后台线程
|
||||||
|
_poller = WorkThreadPool::Instance().getPoller();
|
||||||
_file_path = file_path;
|
_file_path = file_path;
|
||||||
if (_file_path.empty()) {
|
if (_file_path.empty()) {
|
||||||
GET_CONFIG(string, recordPath, Record::kFilePath);
|
GET_CONFIG(string, recordPath, Record::kFilePath);
|
||||||
@ -105,7 +107,7 @@ void MP4Reader::stopReadMP4() {
|
|||||||
_timer = nullptr;
|
_timer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4Reader::startReadMP4(const EventPoller::Ptr &poller_in, uint64_t sample_ms, bool ref_self, bool file_repeat) {
|
void MP4Reader::startReadMP4(uint64_t sample_ms, bool ref_self, bool file_repeat) {
|
||||||
GET_CONFIG(uint32_t, sampleMS, Record::kSampleMS);
|
GET_CONFIG(uint32_t, sampleMS, Record::kSampleMS);
|
||||||
auto strong_self = shared_from_this();
|
auto strong_self = shared_from_this();
|
||||||
if (_muxer) {
|
if (_muxer) {
|
||||||
@ -114,8 +116,6 @@ void MP4Reader::startReadMP4(const EventPoller::Ptr &poller_in, uint64_t sample_
|
|||||||
while (!_muxer->isAllTrackReady() && readNextSample()) {}
|
while (!_muxer->isAllTrackReady() && readNextSample()) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//未指定线程,那么使用后台线程(读写文件采用后台线程)
|
|
||||||
auto poller = poller_in ? poller_in : WorkThreadPool::Instance().getPoller();
|
|
||||||
auto timer_sec = (sample_ms ? sample_ms : sampleMS) / 1000.0f;
|
auto timer_sec = (sample_ms ? sample_ms : sampleMS) / 1000.0f;
|
||||||
|
|
||||||
//启动定时器
|
//启动定时器
|
||||||
@ -123,7 +123,7 @@ void MP4Reader::startReadMP4(const EventPoller::Ptr &poller_in, uint64_t sample_
|
|||||||
_timer = std::make_shared<Timer>(timer_sec, [strong_self]() {
|
_timer = std::make_shared<Timer>(timer_sec, [strong_self]() {
|
||||||
lock_guard<recursive_mutex> lck(strong_self->_mtx);
|
lock_guard<recursive_mutex> lck(strong_self->_mtx);
|
||||||
return strong_self->readSample();
|
return strong_self->readSample();
|
||||||
}, poller);
|
}, _poller);
|
||||||
} else {
|
} else {
|
||||||
weak_ptr<MP4Reader> weak_self = strong_self;
|
weak_ptr<MP4Reader> weak_self = strong_self;
|
||||||
_timer = std::make_shared<Timer>(timer_sec, [weak_self]() {
|
_timer = std::make_shared<Timer>(timer_sec, [weak_self]() {
|
||||||
@ -133,7 +133,7 @@ void MP4Reader::startReadMP4(const EventPoller::Ptr &poller_in, uint64_t sample_
|
|||||||
}
|
}
|
||||||
lock_guard<recursive_mutex> lck(strong_self->_mtx);
|
lock_guard<recursive_mutex> lck(strong_self->_mtx);
|
||||||
return strong_self->readSample();
|
return strong_self->readSample();
|
||||||
}, poller);
|
}, _poller);
|
||||||
}
|
}
|
||||||
|
|
||||||
_file_repeat = file_repeat;
|
_file_repeat = file_repeat;
|
||||||
@ -251,5 +251,9 @@ string MP4Reader::getOriginUrl(MediaSource &sender) const {
|
|||||||
return _file_path;
|
return _file_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolkit::EventPoller::Ptr MP4Reader::getOwnerPoller(MediaSource &sender) {
|
||||||
|
return _poller;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
#endif //ENABLE_MP4
|
#endif //ENABLE_MP4
|
@ -33,12 +33,11 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始解复用MP4文件
|
* 开始解复用MP4文件
|
||||||
* @param poller 解复用mp4定时器所绑定线程,置空则随机采用一条后台线程
|
|
||||||
* @param sample_ms 每次读取文件数据量,单位毫秒,置0时采用配置文件配置
|
* @param sample_ms 每次读取文件数据量,单位毫秒,置0时采用配置文件配置
|
||||||
* @param ref_self 是否让定时器引用此对象本身,如果无其他对象引用本身,在不循环读文件时,读取文件结束后本对象将自动销毁
|
* @param ref_self 是否让定时器引用此对象本身,如果无其他对象引用本身,在不循环读文件时,读取文件结束后本对象将自动销毁
|
||||||
* @param file_repeat 是否循环读取文件,如果配置文件设置为循环读文件,此参数无效
|
* @param file_repeat 是否循环读取文件,如果配置文件设置为循环读文件,此参数无效
|
||||||
*/
|
*/
|
||||||
void startReadMP4(const toolkit::EventPoller::Ptr &poller = nullptr, uint64_t sample_ms = 0, bool ref_self = true, bool file_repeat = false);
|
void startReadMP4(uint64_t sample_ms = 0, bool ref_self = true, bool file_repeat = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止解复用MP4定时器
|
* 停止解复用MP4定时器
|
||||||
@ -60,6 +59,7 @@ private:
|
|||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
MediaOriginType getOriginType(MediaSource &sender) const override;
|
MediaOriginType getOriginType(MediaSource &sender) const override;
|
||||||
std::string getOriginUrl(MediaSource &sender) const override;
|
std::string getOriginUrl(MediaSource &sender) const override;
|
||||||
|
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override;
|
||||||
|
|
||||||
bool readSample();
|
bool readSample();
|
||||||
bool readNextSample();
|
bool readNextSample();
|
||||||
@ -80,6 +80,7 @@ private:
|
|||||||
toolkit::Timer::Ptr _timer;
|
toolkit::Timer::Ptr _timer;
|
||||||
MP4Demuxer::Ptr _demuxer;
|
MP4Demuxer::Ptr _demuxer;
|
||||||
MultiMediaSourceMuxer::Ptr _muxer;
|
MultiMediaSourceMuxer::Ptr _muxer;
|
||||||
|
toolkit::EventPoller::Ptr _poller;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
@ -285,7 +285,7 @@ std::shared_ptr<SockInfo> RtpProcess::getOriginSock(MediaSource &sender) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toolkit::EventPoller::Ptr RtpProcess::getOwnerPoller(MediaSource &sender) {
|
toolkit::EventPoller::Ptr RtpProcess::getOwnerPoller(MediaSource &sender) {
|
||||||
return _sock ? _sock->getPoller() : nullptr;
|
return _sock ? _sock->getPoller() : EventPollerPool::Instance().getPoller();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpProcess::setHelper(std::weak_ptr<RtcpContext> help) {
|
void RtpProcess::setHelper(std::weak_ptr<RtcpContext> help) {
|
||||||
|
@ -120,12 +120,6 @@ void RtpSelector::onManager() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpSelector::RtpSelector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
RtpSelector::~RtpSelector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
RtpProcessHelper::RtpProcessHelper(const string &stream_id, const weak_ptr<RtpSelector> &parent) {
|
RtpProcessHelper::RtpProcessHelper(const string &stream_id, const weak_ptr<RtpSelector> &parent) {
|
||||||
_stream_id = stream_id;
|
_stream_id = stream_id;
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
@ -136,6 +130,7 @@ RtpProcessHelper::~RtpProcessHelper() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpProcessHelper::attachEvent() {
|
void RtpProcessHelper::attachEvent() {
|
||||||
|
//主要目的是close回调触发时能把对象从RtpSelector中删除
|
||||||
_process->setListener(shared_from_this());
|
_process->setListener(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +152,10 @@ int RtpProcessHelper::totalReaderCount(MediaSource &sender) {
|
|||||||
return _process ? _process->getTotalReaderCount() : sender.totalReaderCount();
|
return _process ? _process->getTotalReaderCount() : sender.totalReaderCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolkit::EventPoller::Ptr RtpProcessHelper::getOwnerPoller(MediaSource &sender) {
|
||||||
|
return toolkit::EventPollerPool::Instance().getPoller();
|
||||||
|
}
|
||||||
|
|
||||||
RtpProcess::Ptr &RtpProcessHelper::getProcess() {
|
RtpProcess::Ptr &RtpProcessHelper::getProcess() {
|
||||||
return _process;
|
return _process;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ protected:
|
|||||||
bool close(MediaSource &sender,bool force) override;
|
bool close(MediaSource &sender,bool force) override;
|
||||||
// 观看总人数
|
// 观看总人数
|
||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
|
// 获取所属线程
|
||||||
|
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::weak_ptr<RtpSelector > _parent;
|
std::weak_ptr<RtpSelector > _parent;
|
||||||
@ -43,8 +45,8 @@ private:
|
|||||||
|
|
||||||
class RtpSelector : public std::enable_shared_from_this<RtpSelector>{
|
class RtpSelector : public std::enable_shared_from_this<RtpSelector>{
|
||||||
public:
|
public:
|
||||||
RtpSelector();
|
RtpSelector() = default;
|
||||||
~RtpSelector();
|
~RtpSelector() = default;
|
||||||
|
|
||||||
static bool getSSRC(const char *data,size_t data_len, uint32_t &ssrc);
|
static bool getSSRC(const char *data,size_t data_len, uint32_t &ssrc);
|
||||||
static RtpSelector &Instance();
|
static RtpSelector &Instance();
|
||||||
|
@ -20,8 +20,8 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
RtpSender::RtpSender() {
|
RtpSender::RtpSender(EventPoller::Ptr poller) {
|
||||||
_poller = EventPollerPool::Instance().getPoller();
|
_poller = poller ? std::move(poller) : EventPollerPool::Instance().getPoller();
|
||||||
_socket_rtp = Socket::createSocket(_poller, false);
|
_socket_rtp = Socket::createSocket(_poller, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,9 +253,8 @@ void RtpSender::onSendRtpUdp(const toolkit::Buffer::Ptr &buf, bool check) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpSender::onClose() {
|
void RtpSender::onClose() {
|
||||||
auto cb = _on_close;
|
if (_on_close) {
|
||||||
if (cb) {
|
_on_close();
|
||||||
_poller->async([cb]() { cb(); }, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,25 +265,18 @@ void RtpSender::onFlushRtpList(shared_ptr<List<Buffer::Ptr> > rtp_list) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_ptr<RtpSender> weak_self = shared_from_this();
|
|
||||||
_poller->async([rtp_list, weak_self]() {
|
|
||||||
auto strong_self = weak_self.lock();
|
|
||||||
if (!strong_self) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
auto size = rtp_list->size();
|
auto size = rtp_list->size();
|
||||||
rtp_list->for_each([&](Buffer::Ptr &packet) {
|
rtp_list->for_each([&](Buffer::Ptr &packet) {
|
||||||
if (strong_self->_args.is_udp) {
|
if (_args.is_udp) {
|
||||||
strong_self->onSendRtpUdp(packet, i == 0);
|
onSendRtpUdp(packet, i == 0);
|
||||||
// udp模式,rtp over tcp前4个字节可以忽略
|
// udp模式,rtp over tcp前4个字节可以忽略
|
||||||
strong_self->_socket_rtp->send(std::make_shared<BufferRtp>(std::move(packet), RtpPacket::kRtpTcpHeaderSize), nullptr, 0, ++i == size);
|
_socket_rtp->send(std::make_shared<BufferRtp>(std::move(packet), RtpPacket::kRtpTcpHeaderSize), nullptr, 0, ++i == size);
|
||||||
} else {
|
} else {
|
||||||
// tcp模式, rtp over tcp前2个字节可以忽略,只保留后续rtp长度的2个字节
|
// tcp模式, rtp over tcp前2个字节可以忽略,只保留后续rtp长度的2个字节
|
||||||
strong_self->_socket_rtp->send(std::make_shared<BufferRtp>(std::move(packet), 2), nullptr, 0, ++i == size);
|
_socket_rtp->send(std::make_shared<BufferRtp>(std::move(packet), 2), nullptr, 0, ++i == size);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpSender::onErr(const SockException &ex, bool is_connect) {
|
void RtpSender::onErr(const SockException &ex, bool is_connect) {
|
||||||
|
@ -22,7 +22,7 @@ class RtpSender : public MediaSinkInterface, public std::enable_shared_from_this
|
|||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<RtpSender> Ptr;
|
typedef std::shared_ptr<RtpSender> Ptr;
|
||||||
|
|
||||||
RtpSender();
|
RtpSender(toolkit::EventPoller::Ptr poller = nullptr);
|
||||||
~RtpSender() override = default;
|
~RtpSender() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,6 +139,10 @@ int RtpSession::totalReaderCount(MediaSource &sender) {
|
|||||||
return _process ? _process->getTotalReaderCount() : sender.totalReaderCount();
|
return _process ? _process->getTotalReaderCount() : sender.totalReaderCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolkit::EventPoller::Ptr RtpSession::getOwnerPoller(MediaSource &sender) {
|
||||||
|
return getPoller();
|
||||||
|
}
|
||||||
|
|
||||||
static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) {
|
static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) {
|
||||||
//rtp前面必须预留两个字节的长度字段
|
//rtp前面必须预留两个字节的长度字段
|
||||||
for (ssize_t i = 2; i <= len - 4; ++i) {
|
for (ssize_t i = 2; i <= len - 4; ++i) {
|
||||||
|
@ -38,6 +38,8 @@ protected:
|
|||||||
bool close(MediaSource &sender,bool force) override;
|
bool close(MediaSource &sender,bool force) override;
|
||||||
// 观看总人数
|
// 观看总人数
|
||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
|
// 获取所属线程
|
||||||
|
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override;
|
||||||
// 收到rtp回调
|
// 收到rtp回调
|
||||||
void onRtpPacket(const char *data, size_t len) override;
|
void onRtpPacket(const char *data, size_t len) override;
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ std::shared_ptr<SockInfo> SrtTransportImp::getOriginSock(mediakit::MediaSource &
|
|||||||
|
|
||||||
toolkit::EventPoller::Ptr SrtTransportImp::getOwnerPoller(MediaSource &sender){
|
toolkit::EventPoller::Ptr SrtTransportImp::getOwnerPoller(MediaSource &sender){
|
||||||
auto session = getSession();
|
auto session = getSession();
|
||||||
return session ? session->getPoller() : nullptr;
|
return session ? session->getPoller() : EventPollerPool::Instance().getPoller();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrtTransportImp::emitOnPublish() {
|
void SrtTransportImp::emitOnPublish() {
|
||||||
|
Loading…
Reference in New Issue
Block a user