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.
|
|
|
|
|
*
|
2021-01-17 18:31:50 +08:00
|
|
|
|
* 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 "Util/File.h"
|
|
|
|
|
#include "Http/HttpTSPlayer.h"
|
|
|
|
|
#include "Extension/CommonRtp.h"
|
2020-11-01 22:27:44 +08:00
|
|
|
|
#include "Extension/H264Rtp.h"
|
2021-06-21 19:58:59 +08:00
|
|
|
|
#include "Extension/Factory.h"
|
2021-06-21 20:32:13 +08:00
|
|
|
|
#include "Extension/Opus.h"
|
2020-10-24 23:33:13 +08:00
|
|
|
|
|
|
|
|
|
namespace mediakit{
|
|
|
|
|
|
|
|
|
|
//判断是否为ts负载
|
2021-01-17 18:31:50 +08:00
|
|
|
|
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 {
|
2021-06-21 19:58:59 +08:00
|
|
|
|
public:
|
|
|
|
|
using Ptr = std::shared_ptr<RtpReceiverImp>;
|
2021-06-25 16:24:44 +08:00
|
|
|
|
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));
|
2021-06-21 19:58:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~RtpReceiverImp() override = default;
|
|
|
|
|
|
2021-06-21 20:32:13 +08:00
|
|
|
|
bool inputRtp(TrackType type, uint8_t *ptr, size_t len){
|
2021-06-25 16:24:44 +08:00
|
|
|
|
return RtpTrack::inputRtp(type, _sample_rate, ptr, len);
|
2021-06-21 19:58:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2021-06-21 20:32:13 +08:00
|
|
|
|
int _sample_rate;
|
2021-06-21 19:58:59 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2020-10-24 23:33:13 +08:00
|
|
|
|
GB28181Process::GB28181Process(const MediaInfo &media_info, MediaSinkInterface *interface) {
|
|
|
|
|
assert(interface);
|
|
|
|
|
_media_info = media_info;
|
|
|
|
|
_interface = interface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
RtpHeader *header = (RtpHeader *) data;
|
|
|
|
|
auto pt = header->pt;
|
|
|
|
|
auto &ref = _rtp_receiver[pt];
|
2021-06-21 19:58:59 +08:00
|
|
|
|
if (!ref) {
|
2021-06-21 20:32:13 +08:00
|
|
|
|
if (_rtp_receiver.size() > 2) {
|
|
|
|
|
//防止pt类型太多导致内存溢出
|
|
|
|
|
throw std::invalid_argument("rtp pt类型不得超过2种!");
|
|
|
|
|
}
|
2021-01-31 19:19:24 +08:00
|
|
|
|
switch (pt) {
|
2021-06-21 20:32:13 +08:00
|
|
|
|
case 100: {
|
|
|
|
|
//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);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 19:58:59 +08:00
|
|
|
|
case 99: {
|
|
|
|
|
//H265负载
|
2021-06-21 20:32:13 +08:00
|
|
|
|
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
|
|
|
|
onRtpSorted(std::move(rtp));
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-21 19:58:59 +08:00
|
|
|
|
auto track = std::make_shared<H265Track>();
|
|
|
|
|
_interface->addTrack(track);
|
2021-06-21 20:32:13 +08:00
|
|
|
|
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
2021-06-21 19:58:59 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-01-02 20:02:38 +08:00
|
|
|
|
case 98: {
|
|
|
|
|
//H264负载
|
2021-06-21 20:32:13 +08:00
|
|
|
|
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
|
|
|
|
onRtpSorted(std::move(rtp));
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-21 19:58:59 +08:00
|
|
|
|
auto track = std::make_shared<H264Track>();
|
|
|
|
|
_interface->addTrack(track);
|
2021-06-21 20:32:13 +08:00
|
|
|
|
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
2021-01-02 20:02:38 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-21 19:58:59 +08:00
|
|
|
|
|
2021-06-21 20:32:13 +08:00
|
|
|
|
case 0:
|
|
|
|
|
//CodecG711U
|
2021-06-21 19:58:59 +08:00
|
|
|
|
case 8: {
|
|
|
|
|
//CodecG711A
|
2021-06-21 20:32:13 +08:00
|
|
|
|
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);
|
2021-06-21 19:58:59 +08:00
|
|
|
|
_interface->addTrack(track);
|
2021-06-21 20:32:13 +08:00
|
|
|
|
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
2021-06-21 19:58:59 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-02 20:02:38 +08:00
|
|
|
|
default: {
|
2021-01-31 19:19:24 +08:00
|
|
|
|
if (pt != 33 && pt != 96) {
|
|
|
|
|
WarnL << "rtp payload type未识别(" << (int) pt << "),已按ts或ps负载处理";
|
2021-01-02 20:02:38 +08:00
|
|
|
|
}
|
2021-06-21 20:32:13 +08:00
|
|
|
|
|
|
|
|
|
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
|
|
|
|
onRtpSorted(std::move(rtp));
|
|
|
|
|
});
|
|
|
|
|
|
2020-10-24 23:33:13 +08:00
|
|
|
|
//ts或ps负载
|
2021-06-21 20:32:13 +08:00
|
|
|
|
_rtp_decoder[pt] = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
|
2020-10-24 23:33:13 +08:00
|
|
|
|
//设置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);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//设置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);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 20:32:13 +08:00
|
|
|
|
return ref->inputRtp(TrackVideo, (unsigned char *) data, data_len);
|
2020-10-24 23:33:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-17 18:31:50 +08:00
|
|
|
|
const char *GB28181Process::onSearchPacketTail(const char *packet,size_t bytes){
|
2020-10-24 23:33:13 +08:00
|
|
|
|
try {
|
|
|
|
|
auto ret = _decoder->input((uint8_t *) packet, bytes);
|
2021-02-09 14:19:07 +08:00
|
|
|
|
if (ret >= 0) {
|
|
|
|
|
//解析成功全部或部分
|
2020-10-24 23:33:13 +08:00
|
|
|
|
return packet + ret;
|
|
|
|
|
}
|
2021-02-09 14:19:07 +08:00
|
|
|
|
//解析失败,丢弃所有数据
|
|
|
|
|
return packet + bytes;
|
2020-10-24 23:33:13 +08:00
|
|
|
|
} catch (std::exception &ex) {
|
|
|
|
|
InfoL << "解析ps或ts异常: bytes=" << bytes
|
|
|
|
|
<< " ,exception=" << ex.what()
|
2021-02-21 21:26:45 +08:00
|
|
|
|
<< " ,hex=" << hexdump((uint8_t *) packet, MIN(bytes,32));
|
2020-10-24 23:33:13 +08:00
|
|
|
|
if (remainDataSize() > 256 * 1024) {
|
|
|
|
|
//缓存太多数据无法处理则上抛异常
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
|
2021-06-21 19:58:59 +08:00
|
|
|
|
if (frame->getCodecId() != CodecInvalid) {
|
|
|
|
|
//这里不是ps或ts
|
2020-11-01 22:27:44 +08:00
|
|
|
|
_interface->inputFrame(frame);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-24 23:33:13 +08:00
|
|
|
|
//这是TS或PS
|
|
|
|
|
if (_save_file_ps) {
|
|
|
|
|
fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_decoder) {
|
|
|
|
|
//创建解码器
|
|
|
|
|
if (checkTS((uint8_t *) frame->data(), frame->size())) {
|
|
|
|
|
//猜测是ts负载
|
|
|
|
|
InfoL << _media_info._streamid << " judged to be TS";
|
|
|
|
|
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
|
|
|
|
|
} else {
|
|
|
|
|
//猜测是ps负载
|
|
|
|
|
InfoL << _media_info._streamid << " judged to be PS";
|
|
|
|
|
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_decoder) {
|
|
|
|
|
HttpRequestSplitter::input(frame->data(), frame->size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}//namespace mediakit
|
2021-01-09 17:53:21 +08:00
|
|
|
|
#endif//defined(ENABLE_RTPPROXY)
|