ZLMediaKit/src/Rtp/RtpProcess.cpp

243 lines
8.0 KiB
C++
Raw Normal View History

2019-12-05 19:20:12 +08:00
/*
2019-12-06 11:54:10 +08:00
* MIT License
*
* Copyright (c) 2019 Gemfield <gemfield@civilnet.cn>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
2019-12-05 19:20:12 +08:00
2019-12-06 11:54:10 +08:00
#if defined(ENABLE_RTPPROXY)
#include "mpeg-ps.h"
2019-12-05 19:20:12 +08:00
#include "RtpProcess.h"
#include "Util/File.h"
#include "Extension/H265.h"
#include "Extension/AAC.h"
2019-12-06 11:54:10 +08:00
namespace mediakit{
2019-12-05 19:20:12 +08:00
string printSSRC(uint32_t ui32Ssrc) {
char tmp[9] = { 0 };
ui32Ssrc = htonl(ui32Ssrc);
uint8_t *pSsrc = (uint8_t *) &ui32Ssrc;
for (int i = 0; i < 4; i++) {
sprintf(tmp + 2 * i, "%02X", pSsrc[i]);
}
return tmp;
}
static string printAddress(const struct sockaddr *addr){
return StrPrinter << inet_ntoa(((struct sockaddr_in *) addr)->sin_addr) << ":" << ntohs(((struct sockaddr_in *) addr)->sin_port);
}
RtpProcess::RtpProcess(uint32_t ssrc) {
_ssrc = ssrc;
_track = std::make_shared<SdpTrack>();
_track = std::make_shared<SdpTrack>();
_track->_interleaved = 0;
_track->_samplerate = 90000;
_track->_type = TrackVideo;
_track->_ssrc = _ssrc;
DebugL << printSSRC(_ssrc);
GET_CONFIG(bool,toRtxp,General::kPublishToRtxp);
GET_CONFIG(bool,toHls,General::kPublishToHls);
GET_CONFIG(bool,toMP4,General::kPublishToMP4);
_muxer = std::make_shared<MultiMediaSourceMuxer>(DEFAULT_VHOST,"rtp",printSSRC(_ssrc),0,toRtxp,toRtxp,toHls,toMP4);
2019-12-05 19:20:12 +08:00
2019-12-06 11:54:10 +08:00
GET_CONFIG(string,dump_dir,RtpProxy::kDumpDir);
2019-12-05 19:20:12 +08:00
{
2019-12-06 11:54:10 +08:00
FILE *fp = !dump_dir.empty() ? File::createfile_file(File::absolutePath(printSSRC(_ssrc) + ".rtp",dump_dir).data(),"wb") : nullptr;
2019-12-05 19:20:12 +08:00
if(fp){
_save_file_rtp.reset(fp,[](FILE *fp){
fclose(fp);
});
}
}
{
2019-12-06 11:54:10 +08:00
FILE *fp = !dump_dir.empty() ? File::createfile_file(File::absolutePath(printSSRC(_ssrc) + ".mp2",dump_dir).data(),"wb") : nullptr;
2019-12-05 19:20:12 +08:00
if(fp){
_save_file_ps.reset(fp,[](FILE *fp){
fclose(fp);
});
}
}
{
2019-12-06 11:54:10 +08:00
FILE *fp = !dump_dir.empty() ? File::createfile_file(File::absolutePath(printSSRC(_ssrc) + ".video",dump_dir).data(),"wb") : nullptr;
2019-12-05 19:20:12 +08:00
if(fp){
_save_file_video.reset(fp,[](FILE *fp){
fclose(fp);
});
}
}
}
RtpProcess::~RtpProcess() {
if(_addr){
DebugL << printSSRC(_ssrc) << " " << printAddress(_addr);
delete _addr;
}else{
DebugL << printSSRC(_ssrc);
}
}
bool RtpProcess::inputRtp(const char *data, int data_len,const struct sockaddr *addr) {
2019-12-06 11:54:10 +08:00
GET_CONFIG(bool,check_source,RtpProxy::kCheckSource);
2019-12-05 19:20:12 +08:00
//检查源是否合法
if(!_addr){
_addr = new struct sockaddr;
memcpy(_addr,addr, sizeof(struct sockaddr));
DebugL << "RtpProcess(" << printSSRC(_ssrc) << ") bind to address:" << printAddress(_addr);
}
if(check_source && memcmp(_addr,addr,sizeof(struct sockaddr)) != 0){
DebugL << "RtpProcess(" << printSSRC(_ssrc) << ") address dismatch:" << printAddress(addr) << " != " << printAddress(_addr);
return false;
}
_last_rtp_time.resetTime();
return handleOneRtp(0,_track,(unsigned char *)data,data_len);
}
void RtpProcess::onRtpSorted(const RtpPacket::Ptr &rtp, int) {
if(rtp->sequence != _sequence + 1){
WarnL << rtp->sequence << " != " << _sequence << "+1";
}
_sequence = rtp->sequence;
if(_save_file_rtp){
uint16_t size = rtp->size() - 4;
size = htons(size);
fwrite((uint8_t *) &size, 2, 1, _save_file_rtp.get());
fwrite((uint8_t *) rtp->data() + 4, rtp->size() - 4, 1, _save_file_rtp.get());
}
2019-12-06 11:54:10 +08:00
GET_CONFIG(string,rtp_type,::RtpProxy::kRtpType);
2019-12-05 19:20:12 +08:00
decodeRtp(rtp->data() + 4 ,rtp->size() - 4,rtp_type.data());
}
void RtpProcess::onRtpDecode(const void *packet, int bytes, uint32_t, int flags) {
if(_save_file_ps){
fwrite((uint8_t *)packet,bytes, 1, _save_file_ps.get());
}
auto ret = decodePS((uint8_t *)packet,bytes);
if(ret != bytes){
WarnL << ret << " != " << bytes << " " << flags;
}
}
void RtpProcess::onPSDecode(int stream,
int codecid,
int flags,
int64_t pts,
int64_t dts,
const void *data,
2019-12-06 11:54:10 +08:00
int bytes) {
2019-12-13 15:42:12 +08:00
pts /= 90;
dts /= 90;
_stamps[codecid].revise(dts,pts,dts,pts,false);
2019-12-05 19:20:12 +08:00
switch (codecid) {
case STREAM_VIDEO_H264: {
if (!_codecid_video) {
//获取到视频
_codecid_video = codecid;
InfoL << "got video track: H264";
auto track = std::make_shared<H264Track>();
_muxer->addTrack(track);
}
if (codecid != _codecid_video) {
WarnL << "video track change to H264 from codecid:" << _codecid_video;
return;
}
if(_save_file_video){
fwrite((uint8_t *)data,bytes, 1, _save_file_video.get());
}
2019-12-13 15:49:57 +08:00
auto frame = std::make_shared<H264FrameNoCacheAble>((char *) data, bytes, dts, pts,4);
_muxer->inputFrame(frame);
2019-12-05 19:20:12 +08:00
break;
}
case STREAM_VIDEO_H265: {
if (!_codecid_video) {
//获取到视频
_codecid_video = codecid;
InfoL << "got video track: H265";
auto track = std::make_shared<H265Track>();
_muxer->addTrack(track);
}
if (codecid != _codecid_video) {
WarnL << "video track change to H265 from codecid:" << _codecid_video;
return;
}
if(_save_file_video){
fwrite((uint8_t *)data,bytes, 1, _save_file_video.get());
}
2019-12-13 15:49:57 +08:00
auto frame = std::make_shared<H265FrameNoCacheAble>((char *) data, bytes, dts, pts, 4);
_muxer->inputFrame(frame);
2019-12-05 19:20:12 +08:00
break;
}
case STREAM_AUDIO_AAC: {
if (!_codecid_audio) {
//获取到音频
_codecid_audio = codecid;
InfoL << "got audio track: AAC";
auto track = std::make_shared<AACTrack>();
_muxer->addTrack(track);
}
if (codecid != _codecid_audio) {
WarnL << "audio track change to AAC from codecid:" << _codecid_audio;
return;
}
2019-12-13 15:42:12 +08:00
_muxer->inputFrame(std::make_shared<AACFrameNoCacheAble>((char *) data, bytes, dts, 7));
2019-12-05 19:20:12 +08:00
break;
}
default:
WarnL << "unsupported codec type:" << codecid;
return;
}
}
bool RtpProcess::alive() {
2019-12-06 11:54:10 +08:00
GET_CONFIG(int,timeoutSec,RtpProxy::kTimeoutSec)
2019-12-05 19:20:12 +08:00
if(_last_rtp_time.elapsedTime() / 1000 < timeoutSec){
return true;
}
return false;
}
string RtpProcess::get_peer_ip() {
return inet_ntoa(((struct sockaddr_in *) _addr)->sin_addr);
}
uint16_t RtpProcess::get_peer_port() {
return ntohs(((struct sockaddr_in *) _addr)->sin_port);
}
2019-12-06 11:54:10 +08:00
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)