Merge branch 'feature/rawrtpsend' of github.com:ZLMediaKit/ZLMediaKit

This commit is contained in:
xiongziliang 2022-04-03 17:34:51 +08:00
commit de0738b1d1
11 changed files with 205 additions and 18 deletions

View File

@ -1104,7 +1104,10 @@ void installWebApi() {
if (!src) { if (!src) {
throw ApiRetException("该媒体流不存在", API::OtherFailed); throw ApiRetException("该媒体流不存在", API::OtherFailed);
} }
uint8_t pt = allArgs["pt"].empty() ? 96 : allArgs["pt"].as<int>();
bool use_ps = allArgs["use_ps"].empty() ? true : allArgs["use_ps"].as<bool>();
bool only_audio = allArgs["only_audio"].empty() ? true : allArgs["only_audio"].as<bool>();
TraceL << "pt "<<int(pt)<<" ps "<<use_ps<<" audio "<<only_audio;
//src_port为空时则随机本地端口 //src_port为空时则随机本地端口
src->startSendRtp(allArgs["dst_url"], allArgs["dst_port"], allArgs["ssrc"], allArgs["is_udp"], allArgs["src_port"], [val, headerOut, invoker](uint16_t local_port, const SockException &ex) mutable{ src->startSendRtp(allArgs["dst_url"], allArgs["dst_port"], allArgs["ssrc"], allArgs["is_udp"], allArgs["src_port"], [val, headerOut, invoker](uint16_t local_port, const SockException &ex) mutable{
if (ex) { if (ex) {
@ -1113,7 +1116,7 @@ void installWebApi() {
} }
val["local_port"] = local_port; val["local_port"] = local_port;
invoker(200, headerOut, val.toStyledString()); invoker(200, headerOut, val.toStyledString());
}); },pt,use_ps,only_audio);
}); });
api_regist("/index/api/stopSendRtp",[](API_ARGS_MAP){ api_regist("/index/api/stopSendRtp",[](API_ARGS_MAP){

View File

@ -237,13 +237,13 @@ bool MediaSource::isRecording(Recorder::type type){
return listener->isRecording(*this, type); return listener->isRecording(*this, type);
} }
void MediaSource::startSendRtp(const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb){ void MediaSource::startSendRtp(const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb,uint8_t pt, bool use_ps,bool only_audio){
auto listener = _listener.lock(); auto listener = _listener.lock();
if (!listener) { if (!listener) {
cb(0, SockException(Err_other, "尚未设置事件监听器")); cb(0, SockException(Err_other, "尚未设置事件监听器"));
return; return;
} }
return listener->startSendRtp(*this, dst_url, dst_port, ssrc, is_udp, src_port, cb); return listener->startSendRtp(*this, dst_url, dst_port, ssrc, is_udp, src_port, cb, pt, use_ps, only_audio);
} }
bool MediaSource::stopSendRtp(const string &ssrc) { bool MediaSource::stopSendRtp(const string &ssrc) {
@ -720,12 +720,12 @@ vector<Track::Ptr> MediaSourceEventInterceptor::getMediaTracks(MediaSource &send
return listener->getMediaTracks(sender, trackReady); return listener->getMediaTracks(sender, trackReady);
} }
void MediaSourceEventInterceptor::startSendRtp(MediaSource &sender, const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb){ void MediaSourceEventInterceptor::startSendRtp(MediaSource &sender, const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb, uint8_t pt, bool use_ps,bool only_audio ){
auto listener = _listener.lock(); auto listener = _listener.lock();
if (listener) { if (listener) {
listener->startSendRtp(sender, dst_url, dst_port, ssrc, is_udp, src_port, cb); listener->startSendRtp(sender, dst_url, dst_port, ssrc, is_udp, src_port, cb, pt, use_ps, only_audio);
} else { } else {
MediaSourceEvent::startSendRtp(sender, dst_url, dst_port, ssrc, is_udp, src_port, cb); MediaSourceEvent::startSendRtp(sender, dst_url, dst_port, ssrc, is_udp, src_port, cb, pt, use_ps, only_audio);
} }
} }

View File

@ -86,7 +86,7 @@ public:
// 获取所有track相关信息 // 获取所有track相关信息
virtual std::vector<Track::Ptr> getMediaTracks(MediaSource &sender, bool trackReady = true) const { return std::vector<Track::Ptr>(); }; virtual std::vector<Track::Ptr> getMediaTracks(MediaSource &sender, bool trackReady = true) const { return std::vector<Track::Ptr>(); };
// 开始发送ps-rtp // 开始发送ps-rtp
virtual void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb) { cb(0, toolkit::SockException(toolkit::Err_other, "not implemented"));}; virtual void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb, uint8_t pt=96, bool use_ps = true,bool only_audio = true) { cb(0, toolkit::SockException(toolkit::Err_other, "not implemented"));};
// 停止发送ps-rtp // 停止发送ps-rtp
virtual bool stopSendRtp(MediaSource &sender, const std::string &ssrc) {return false; } virtual bool stopSendRtp(MediaSource &sender, const std::string &ssrc) {return false; }
@ -117,7 +117,7 @@ public:
bool setupRecord(MediaSource &sender, Recorder::type type, bool start, const std::string &custom_path, size_t max_second) override; bool setupRecord(MediaSource &sender, Recorder::type type, bool start, const std::string &custom_path, size_t max_second) override;
bool isRecording(MediaSource &sender, Recorder::type type) override; bool isRecording(MediaSource &sender, Recorder::type type) override;
std::vector<Track::Ptr> getMediaTracks(MediaSource &sender, bool trackReady = true) const override; std::vector<Track::Ptr> getMediaTracks(MediaSource &sender, bool trackReady = true) const override;
void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb) override; void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb, uint8_t pt=96, bool use_ps = true,bool only_audio = true) override;
bool stopSendRtp(MediaSource &sender, const std::string &ssrc) override; bool stopSendRtp(MediaSource &sender, const std::string &ssrc) override;
private: private:
@ -269,7 +269,7 @@ public:
// 获取录制状态 // 获取录制状态
bool isRecording(Recorder::type type); bool isRecording(Recorder::type type);
// 开始发送ps-rtp // 开始发送ps-rtp
void startSendRtp(const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb); void startSendRtp(const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb , uint8_t pt = 96, bool use_ps = true,bool only_audio = true);
// 停止发送ps-rtp // 停止发送ps-rtp
bool stopSendRtp(const std::string &ssrc); bool stopSendRtp(const std::string &ssrc);

View File

@ -213,9 +213,9 @@ bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type
} }
} }
void MultiMediaSourceMuxer::startSendRtp(MediaSource &, const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb){ void MultiMediaSourceMuxer::startSendRtp(MediaSource &, const string &dst_url, uint16_t dst_port, const string &ssrc, bool is_udp, uint16_t src_port, const function<void(uint16_t local_port, const SockException &ex)> &cb ,uint8_t pt, bool use_ps,bool only_audio){
#if defined(ENABLE_RTPPROXY) #if defined(ENABLE_RTPPROXY)
RtpSender::Ptr rtp_sender = std::make_shared<RtpSender>(atoi(ssrc.data())); RtpSender::Ptr rtp_sender = std::make_shared<RtpSender>(atoi(ssrc.data()),pt,use_ps,only_audio);
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this(); weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
rtp_sender->startSend(dst_url, dst_port, is_udp, src_port, [weak_self, rtp_sender, cb, ssrc](uint16_t local_port, const SockException &ex) { rtp_sender->startSend(dst_url, dst_port, is_udp, src_port, [weak_self, rtp_sender, cb, ssrc](uint16_t local_port, const SockException &ex) {
cb(local_port, ex); cb(local_port, ex);

View File

@ -134,7 +134,7 @@ public:
* @param is_udp udp * @param is_udp udp
* @param cb * @param cb
*/ */
void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb) override; void startSendRtp(MediaSource &sender, const std::string &dst_url, uint16_t dst_port, const std::string &ssrc, bool is_udp, uint16_t src_port, const std::function<void(uint16_t local_port, const toolkit::SockException &ex)> &cb ,uint8_t pt = 96, bool use_ps = true,bool only_audio = true) override;
/** /**
* ps-rtp发送 * ps-rtp发送

102
src/Rtp/RawEncoder.cpp Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#if defined(ENABLE_RTPPROXY)
#include "RawEncoder.h"
#include "Extension/H264Rtp.h"
#include "Extension/AACRtp.h"
#include "Extension/H265Rtp.h"
#include "Extension/CommonRtp.h"
#include "Extension/G711Rtp.h"
#include "Rtsp/RtspMuxer.h"
using namespace toolkit;
namespace mediakit{
RawEncoderImp::RawEncoderImp(uint32_t ssrc, uint8_t payload_type,bool sendAudio):_ssrc(ssrc),_payload_type(payload_type),_sendAudio(sendAudio) {
}
RawEncoderImp::~RawEncoderImp() {
InfoL << this << " " << printSSRC(_ssrc);
}
bool RawEncoderImp::addTrack(const Track::Ptr &track){
if(_sendAudio && track->getTrackType() == TrackType::TrackAudio && !_rtp_encoder){// audio
_rtp_encoder = createRtpEncoder(track);
_rtp_encoder->setRtpRing(std::make_shared<RtpRing::RingType>());
_rtp_encoder->getRtpRing()->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr rtp, bool is_key){
onRTP(std::move(rtp));
}));
return true;
}
if(!_sendAudio && track->getTrackType()==TrackType::TrackVideo && !_rtp_encoder){
_rtp_encoder = createRtpEncoder(track);
_rtp_encoder->setRtpRing(std::make_shared<RtpRing::RingType>());
_rtp_encoder->getRtpRing()->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr rtp, bool is_key){
onRTP(std::move(rtp));
}));
return true;
}
return true;
}
void RawEncoderImp::resetTracks(){
return;
}
bool RawEncoderImp::inputFrame(const Frame::Ptr &frame){
if(frame->getTrackType() == TrackType::TrackAudio && _sendAudio && _rtp_encoder){
_rtp_encoder->inputFrame(frame);
}
if(frame->getTrackType() == TrackType::TrackVideo && !_sendAudio && _rtp_encoder){
_rtp_encoder->inputFrame(frame);
}
return true;
}
RtpCodec::Ptr RawEncoderImp::createRtpEncoder(const Track::Ptr &track){
GET_CONFIG(uint32_t,audio_mtu,Rtp::kAudioMtuSize);
GET_CONFIG(uint32_t,video_mtu,Rtp::kVideoMtuSize);
auto codec_id = track->getCodecId();
uint32_t sample_rate = 90000;
int channels = 1;
auto mtu = (track->getTrackType() == TrackVideo ? video_mtu : audio_mtu);
if(track->getTrackType() == TrackType::TrackAudio){
AudioTrack::Ptr audioTrack = std::dynamic_pointer_cast<AudioTrack>(track);
sample_rate = audioTrack->getAudioSampleRate();
channels = audioTrack->getAudioChannel();
}
switch (codec_id){
case CodecH264 : return std::make_shared<H264RtpEncoder>(_ssrc, mtu, sample_rate, _payload_type, 0);
case CodecH265 : return std::make_shared<H265RtpEncoder>(_ssrc, mtu, sample_rate, _payload_type, 0);
case CodecAAC : return std::make_shared<AACRtpEncoder>(_ssrc, mtu, sample_rate, _payload_type, 0);
case CodecL16 :
case CodecOpus : return std::make_shared<CommonRtpEncoder>(codec_id, _ssrc, mtu, sample_rate, _payload_type, 0);
case CodecG711A :
case CodecG711U : {
if (_payload_type == Rtsp::PT_PCMA || _payload_type == Rtsp::PT_PCMU) {
return std::make_shared<G711RtpEncoder>(codec_id, _ssrc, mtu, sample_rate, _payload_type, 0, channels);
}
return std::make_shared<CommonRtpEncoder>(codec_id, _ssrc, mtu, sample_rate, _payload_type, 0);
}
default : WarnL << "暂不支持该CodecId:" << codec_id; return nullptr;
}
}
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)

59
src/Rtp/RawEncoder.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_RAWENCODER_H
#define ZLMEDIAKIT_RAWENCODER_H
#if defined(ENABLE_RTPPROXY)
#include "Common/MediaSink.h"
#include "Common/Stamp.h"
#include "Extension/CommonRtp.h"
namespace mediakit{
class RawEncoderImp : public MediaSinkInterface{
public:
RawEncoderImp(uint32_t ssrc, uint8_t payload_type = 96, bool sendAudio = true);
~RawEncoderImp() override;
/**
*
*/
bool addTrack(const Track::Ptr &track) override;
/**
*
*/
void resetTracks() override;
/**
*
*/
bool inputFrame(const Frame::Ptr &frame) override;
protected:
//rtp打包后回调
virtual void onRTP(toolkit::Buffer::Ptr rtp) = 0;
private:
RtpCodec::Ptr createRtpEncoder(const Track::Ptr &track);
uint32_t _ssrc;
uint8_t _payload_type;
bool _sendAudio;
RtpCodec::Ptr _rtp_encoder;
};
}//namespace mediakit
#endif //ENABLE_RTPPROXY
#endif //ZLMEDIAKIT_RAWENCODER_H

View File

@ -34,6 +34,12 @@ void RtpCachePS::onRTP(Buffer::Ptr buffer) {
input(stamp, std::move(buffer)); input(stamp, std::move(buffer));
} }
void RtpCacheRaw::onRTP(Buffer::Ptr buffer) {
auto rtp = std::static_pointer_cast<RtpPacket>(buffer);
auto stamp = rtp->getStampMS();
input(stamp, std::move(buffer));
}
}//namespace mediakit }//namespace mediakit
#endif//#if defined(ENABLE_RTPPROXY) #endif//#if defined(ENABLE_RTPPROXY)

View File

@ -14,6 +14,7 @@
#if defined(ENABLE_RTPPROXY) #if defined(ENABLE_RTPPROXY)
#include "PSEncoder.h" #include "PSEncoder.h"
#include "RawEncoder.h"
#include "Extension/CommonRtp.h" #include "Extension/CommonRtp.h"
namespace mediakit{ namespace mediakit{
@ -47,6 +48,16 @@ protected:
void onRTP(toolkit::Buffer::Ptr rtp) override; void onRTP(toolkit::Buffer::Ptr rtp) override;
}; };
class RtpCacheRaw : public RtpCache, public RawEncoderImp{
public:
RtpCacheRaw(onFlushed cb, uint32_t ssrc, uint8_t payload_type = 96,bool sendAudio = true) : RtpCache(std::move(cb)), RawEncoderImp(ssrc, payload_type,sendAudio) {};
~RtpCacheRaw() override = default;
protected:
void onRTP(toolkit::Buffer::Ptr rtp) override;
};
}//namespace mediakit }//namespace mediakit
#endif//ENABLE_RTPPROXY #endif//ENABLE_RTPPROXY
#endif //ZLMEDIAKIT_RTPCACHE_H #endif //ZLMEDIAKIT_RTPCACHE_H

View File

@ -19,11 +19,15 @@ using namespace toolkit;
namespace mediakit{ namespace mediakit{
RtpSender::RtpSender(uint32_t ssrc, uint8_t payload_type) { RtpSender::RtpSender(uint32_t ssrc, uint8_t payload_type,bool use_ps, bool only_audio) {
_poller = EventPollerPool::Instance().getPoller(); _poller = EventPollerPool::Instance().getPoller();
_interface = std::make_shared<RtpCachePS>([this](std::shared_ptr<List<Buffer::Ptr> > list) { if (use_ps) {
onFlushRtpList(std::move(list)); _interface = std::make_shared<RtpCachePS>(
}, ssrc, payload_type); [this](std::shared_ptr<List<Buffer::Ptr>> list) { onFlushRtpList(std::move(list)); }, ssrc, payload_type);
}else{
_interface = std::make_shared<RtpCacheRaw>(
[this](std::shared_ptr<List<Buffer::Ptr>> list) { onFlushRtpList(std::move(list)); }, ssrc, payload_type,only_audio);
}
} }
RtpSender::~RtpSender() {} RtpSender::~RtpSender() {}

View File

@ -27,8 +27,10 @@ public:
* GB28181 RTP发送客户端 * GB28181 RTP发送客户端
* @param ssrc rtp的ssrc * @param ssrc rtp的ssrc
* @param payload_type ps-rtp的pt一般为96 * @param payload_type ps-rtp的pt一般为96
* @param use_ps PS然后发送
* @param only_audio use_ps false
*/ */
RtpSender(uint32_t ssrc, uint8_t payload_type = 96); RtpSender(uint32_t ssrc, uint8_t payload_type = 96,bool use_ps = true,bool only_audio = true);
/** /**
* ps-rtp包 * ps-rtp包