ZLMediaKit/src/Rtp/GB28181Process.cpp

176 lines
6.2 KiB
C++
Raw Normal View History

2020-10-24 23:37:43 +08:00
/*
2020-10-24 23:33:13 +08:00
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
2020-10-24 23:33:13 +08:00
*
* 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 "GB28181Process.h"
#include "Extension/CommonRtp.h"
#include "Extension/Factory.h"
#include "Extension/G711.h"
2022-06-15 00:20:53 +08:00
#include "Extension/H264Rtp.h"
#include "Extension/H265.h"
2022-06-15 00:20:53 +08:00
#include "Extension/Opus.h"
#include "Http/HttpTSPlayer.h"
#include "Util/File.h"
2020-10-24 23:33:13 +08:00
using namespace std;
using namespace toolkit;
namespace mediakit {
2020-10-24 23:33:13 +08:00
2022-06-15 00:20:53 +08:00
// 判断是否为ts负载
static inline bool checkTS(const uint8_t *packet, size_t bytes) {
2020-10-24 23:33:13 +08:00
return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE;
}
2021-06-25 16:24:44 +08:00
class RtpReceiverImp : public RtpTrackImp {
public:
using Ptr = std::shared_ptr<RtpReceiverImp>;
RtpReceiverImp(int sample_rate, RtpTrackImp::OnSorted cb, RtpTrackImp::BeforeSorted cb_before = nullptr) {
2021-06-21 20:32:13 +08:00
_sample_rate = sample_rate;
2021-06-25 16:24:44 +08:00
setOnSorted(std::move(cb));
setBeforeSorted(std::move(cb_before));
2022-06-15 00:20:53 +08:00
// GB28181推流不支持ntp时间戳
2021-09-02 21:17:59 +08:00
setNtpStamp(0, 0);
}
~RtpReceiverImp() override = default;
2022-06-15 00:20:53 +08:00
bool inputRtp(TrackType type, uint8_t *ptr, size_t len) {
return RtpTrack::inputRtp(type, _sample_rate, ptr, len).operator bool();
}
private:
2021-06-21 20:32:13 +08:00
int _sample_rate;
};
///////////////////////////////////////////////////////////////////////////////////////////
2022-01-11 14:09:57 +08:00
GB28181Process::GB28181Process(const MediaInfo &media_info, MediaSinkInterface *sink) {
assert(sink);
2020-10-24 23:33:13 +08:00
_media_info = media_info;
2022-01-11 14:09:57 +08:00
_interface = sink;
2020-10-24 23:33:13 +08:00
}
GB28181Process::~GB28181Process() {}
2021-06-21 20:32:13 +08:00
void GB28181Process::onRtpSorted(RtpPacket::Ptr rtp) {
_rtp_decoder[rtp->getHeader()->pt]->inputRtp(rtp, false);
2020-10-24 23:33:13 +08:00
}
2021-06-21 20:32:13 +08:00
bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
2022-06-15 00:20:53 +08:00
GET_CONFIG(uint32_t, h264_pt, RtpProxy::KH264PT);
GET_CONFIG(uint32_t, h265_pt, RtpProxy::KH265PT);
GET_CONFIG(uint32_t, ps_pt, RtpProxy::KPSPT);
GET_CONFIG(uint32_t, ts_pt, RtpProxy::KTSPT);
GET_CONFIG(uint32_t, opus_pt, RtpProxy::KOpusPT);
GET_CONFIG(uint32_t, g711u_pt, RtpProxy::KG711UPT);
GET_CONFIG(uint32_t, g711a_pt, RtpProxy::KG711APT);
RtpHeader *header = (RtpHeader *)data;
2021-06-21 20:32:13 +08:00
auto pt = header->pt;
auto &ref = _rtp_receiver[pt];
if (!ref) {
2021-06-21 20:32:13 +08:00
if (_rtp_receiver.size() > 2) {
2022-06-15 00:20:53 +08:00
// 防止pt类型太多导致内存溢出
2021-06-21 20:32:13 +08:00
throw std::invalid_argument("rtp pt类型不得超过2种!");
}
2022-06-15 00:20:53 +08:00
if (pt == opus_pt) {
// opus负载
ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<OpusTrack>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else if (pt == h265_pt) {
// H265负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<H265Track>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else if (pt == h264_pt) {
// H264负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<H264Track>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else if (pt == g711u_pt || pt == g711a_pt) {
// CodecG711U
// CodecG711A
ref = std::make_shared<RtpReceiverImp>(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<G711Track>(pt == 0 ? CodecG711U : CodecG711A, 8000, 1, 16);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else {
if (pt != ts_pt && pt != ps_pt) {
WarnL << "rtp payload type未识别(" << (int)pt << "),已按ts或ps负载处理";
}
2022-06-15 00:20:53 +08:00
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
// ts或ps负载
_rtp_decoder[pt] = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
// 设置dump目录
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
if (!dump_dir.empty()) {
auto save_path = File::absolutePath(_media_info._streamid + ".mp2", dump_dir);
_save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
if (fp) {
fclose(fp);
}
2021-06-21 20:32:13 +08:00
});
2020-10-24 23:33:13 +08:00
}
}
2022-06-15 00:20:53 +08:00
// 设置frame回调
2021-06-21 20:32:13 +08:00
_rtp_decoder[pt]->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
2020-10-24 23:33:13 +08:00
onRtpDecode(frame);
return true;
2020-10-24 23:33:13 +08:00
}));
}
2022-06-15 00:20:53 +08:00
return ref->inputRtp(TrackVideo, (unsigned char *)data, data_len);
2020-10-24 23:33:13 +08:00
}
void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
if (frame->getCodecId() != CodecInvalid) {
2022-06-15 00:20:53 +08:00
// 这里不是ps或ts
2020-11-01 22:27:44 +08:00
_interface->inputFrame(frame);
return;
}
2022-06-15 00:20:53 +08:00
// 这是TS或PS
2020-10-24 23:33:13 +08:00
if (_save_file_ps) {
fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
}
if (!_decoder) {
2022-06-15 00:20:53 +08:00
// 创建解码器
if (checkTS((uint8_t *)frame->data(), frame->size())) {
// 猜测是ts负载
2020-10-24 23:33:13 +08:00
InfoL << _media_info._streamid << " judged to be TS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
} else {
2022-06-15 00:20:53 +08:00
// 猜测是ps负载
2020-10-24 23:33:13 +08:00
InfoL << _media_info._streamid << " judged to be PS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
}
}
if (_decoder) {
_decoder->input(reinterpret_cast<const uint8_t *>(frame->data()), frame->size());
2020-10-24 23:33:13 +08:00
}
}
2022-06-15 00:20:53 +08:00
} // namespace mediakit
#endif // defined(ENABLE_RTPPROXY)