支持ts rtp流

This commit is contained in:
xiongziliang 2020-03-06 13:00:06 +08:00
parent d35f1d0bfe
commit 069bde09c1
11 changed files with 302 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* /*
* MIT License * MIT License
* *
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com> * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>

41
src/Rtp/Decoder.cpp Normal file
View File

@ -0,0 +1,41 @@
/*
* MIT License
*
* Copyright (c) 2020 xiongziliang <771730766@qq.com>
*
* 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.
*/
#if defined(ENABLE_RTPPROXY)
#include "Decoder.h"
#include "PSDecoder.h"
#include "TSDecoder.h"
namespace mediakit {
Decoder::Ptr Decoder::createDecoder(Decoder::Type type) {
switch (type){
case decoder_ps : return std::make_shared<PSDecoder>();
case decoder_ts : return std::make_shared<TSDecoder>();
default : return nullptr;
}
}
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)

57
src/Rtp/Decoder.h Normal file
View File

@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2020 xiongziliang <771730766@qq.com>
*
* 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.
*/
#ifndef ZLMEDIAKIT_DECODER_H
#define ZLMEDIAKIT_DECODER_H
#if defined(ENABLE_RTPPROXY)
#include <stdint.h>
#include <memory>
#include <functional>
#include "Decoder.h"
using namespace std;
namespace mediakit {
class Decoder {
public:
typedef std::shared_ptr<Decoder> Ptr;
typedef enum {
decoder_ts = 0,
decoder_ps
}Type;
typedef std::function<void(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes)> onDecode;
virtual int input(const uint8_t *data, int bytes) = 0;
virtual void setOnDecode(const onDecode &decode) = 0;
static Ptr createDecoder(Type type);
protected:
Decoder() = default;
virtual ~Decoder() = default;
};
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)
#endif //ZLMEDIAKIT_DECODER_H

View File

@ -27,7 +27,6 @@
#if defined(ENABLE_RTPPROXY) #if defined(ENABLE_RTPPROXY)
#include "PSDecoder.h" #include "PSDecoder.h"
#include "mpeg-ps.h" #include "mpeg-ps.h"
namespace mediakit{ namespace mediakit{
PSDecoder::PSDecoder() { PSDecoder::PSDecoder() {
@ -40,7 +39,9 @@ PSDecoder::PSDecoder() {
const void* data, const void* data,
size_t bytes){ size_t bytes){
PSDecoder *thiz = (PSDecoder *)param; PSDecoder *thiz = (PSDecoder *)param;
thiz->onPSDecode(stream, codecid, flags, pts, dts, data, bytes); if(thiz->_on_decode){
thiz->_on_decode(stream, codecid, flags, pts, dts, data, bytes);
}
},this); },this);
} }
@ -48,10 +49,13 @@ PSDecoder::~PSDecoder() {
ps_demuxer_destroy((struct ps_demuxer_t*)_ps_demuxer); ps_demuxer_destroy((struct ps_demuxer_t*)_ps_demuxer);
} }
int PSDecoder::decodePS(const uint8_t *data, int bytes) { int PSDecoder::input(const uint8_t *data, int bytes) {
return ps_demuxer_input((struct ps_demuxer_t*)_ps_demuxer,data,bytes); return ps_demuxer_input((struct ps_demuxer_t*)_ps_demuxer,data,bytes);
} }
}//namespace mediakit void PSDecoder::setOnDecode(const Decoder::onDecode &decode) {
_on_decode = decode;
}
}//namespace mediakit
#endif//#if defined(ENABLE_RTPPROXY) #endif//#if defined(ENABLE_RTPPROXY)

View File

@ -29,27 +29,21 @@
#if defined(ENABLE_RTPPROXY) #if defined(ENABLE_RTPPROXY)
#include <stdint.h> #include <stdint.h>
#include "Decoder.h"
namespace mediakit{ namespace mediakit{
class PSDecoder { //ps解析器
class PSDecoder : public Decoder {
public: public:
PSDecoder(); PSDecoder();
virtual ~PSDecoder(); ~PSDecoder();
int decodePS(const uint8_t *data, int bytes); int input(const uint8_t* data, int bytes) override;
protected: void setOnDecode(const onDecode &decode) override;
virtual void onPSDecode(int stream,
int codecid,
int flags,
int64_t pts,
int64_t dts,
const void *data,
int bytes) = 0;
private: private:
void *_ps_demuxer = nullptr; void *_ps_demuxer = nullptr;
onDecode _on_decode;
}; };
}//namespace mediakit }//namespace mediakit
#endif//defined(ENABLE_RTPPROXY) #endif//defined(ENABLE_RTPPROXY)
#endif //ZLMEDIAKIT_PSDECODER_H #endif //ZLMEDIAKIT_PSDECODER_H

View File

@ -63,7 +63,7 @@ void RtpDecoder::decodeRtp(const void *data, int bytes,const string &type_name)
}, },
[](void* param, const void *packet, int bytes, uint32_t timestamp, int flags){ [](void* param, const void *packet, int bytes, uint32_t timestamp, int flags){
RtpDecoder *obj = (RtpDecoder *)param; RtpDecoder *obj = (RtpDecoder *)param;
obj->onRtpDecode(packet, bytes, timestamp, flags); obj->onRtpDecode((uint8_t *)packet, bytes, timestamp, flags);
} }
}; };

View File

@ -39,7 +39,7 @@ public:
virtual ~RtpDecoder(); virtual ~RtpDecoder();
protected: protected:
void decodeRtp(const void *data, int bytes,const string &type_name); void decodeRtp(const void *data, int bytes,const string &type_name);
virtual void onRtpDecode(const void *packet, int bytes, uint32_t timestamp, int flags) = 0; virtual void onRtpDecode(const uint8_t *packet, int bytes, uint32_t timestamp, int flags) = 0;
private: private:
void *_rtp_decoder = nullptr; void *_rtp_decoder = nullptr;
BufferRaw::Ptr _buffer; BufferRaw::Ptr _buffer;

View File

@ -179,12 +179,26 @@ void RtpProcess::onRtpSorted(const RtpPacket::Ptr &rtp, int) {
decodeRtp(rtp->data() + 4 ,rtp->size() - 4,_rtp_type); decodeRtp(rtp->data() + 4 ,rtp->size() - 4,_rtp_type);
} }
void RtpProcess::onRtpDecode(const void *packet, int bytes, uint32_t, int flags) { void RtpProcess::onRtpDecode(const uint8_t *packet, int bytes, uint32_t, int flags) {
if(_save_file_ps){ if(_save_file_ps){
fwrite((uint8_t *)packet,bytes, 1, _save_file_ps.get()); fwrite((uint8_t *)packet,bytes, 1, _save_file_ps.get());
} }
auto ret = decodePS((uint8_t *)packet,bytes); if(!_decoder){
//创建解码器
if(bytes % 188 == 0 || packet[0] == 0x47){
//猜测是ts负载
_decoder = Decoder::createDecoder(Decoder::decoder_ts);
}else{
//猜测是ps负载
_decoder = Decoder::createDecoder(Decoder::decoder_ps);
}
_decoder->setOnDecode([this](int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes){
onDecode(stream,codecid,flags,pts,dts,data,bytes);
});
}
auto ret = _decoder->input((uint8_t *)packet,bytes);
if(ret != bytes){ if(ret != bytes){
WarnL << ret << " != " << bytes << " " << flags; WarnL << ret << " != " << bytes << " " << flags;
if(++_rtp_dec_failed_cnt == 10){ if(++_rtp_dec_failed_cnt == 10){
@ -215,13 +229,7 @@ static const char *getCodecName(int codec_id) {
} }
} }
void RtpProcess::onPSDecode(int stream, void RtpProcess::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes) {
int codecid,
int flags,
int64_t pts,
int64_t dts,
const void *data,
int bytes) {
pts /= 90; pts /= 90;
dts /= 90; dts /= 90;
_stamps[codecid].revise(dts,pts,dts,pts,false); _stamps[codecid].revise(dts,pts,dts,pts,false);

View File

@ -31,7 +31,7 @@
#include "Rtsp/RtpReceiver.h" #include "Rtsp/RtpReceiver.h"
#include "RtpDecoder.h" #include "RtpDecoder.h"
#include "PSDecoder.h" #include "Decoder.h"
#include "Common/Device.h" #include "Common/Device.h"
#include "Common/Stamp.h" #include "Common/Stamp.h"
using namespace mediakit; using namespace mediakit;
@ -40,7 +40,7 @@ namespace mediakit{
string printSSRC(uint32_t ui32Ssrc); string printSSRC(uint32_t ui32Ssrc);
class FrameMerger; class FrameMerger;
class RtpProcess : public RtpReceiver , public RtpDecoder , public PSDecoder { class RtpProcess : public RtpReceiver , public RtpDecoder{
public: public:
typedef std::shared_ptr<RtpProcess> Ptr; typedef std::shared_ptr<RtpProcess> Ptr;
RtpProcess(uint32_t ssrc); RtpProcess(uint32_t ssrc);
@ -54,14 +54,8 @@ public:
void setListener(const std::weak_ptr<MediaSourceEvent> &listener); void setListener(const std::weak_ptr<MediaSourceEvent> &listener);
protected: protected:
void onRtpSorted(const RtpPacket::Ptr &rtp, int track_index) override ; void onRtpSorted(const RtpPacket::Ptr &rtp, int track_index) override ;
void onRtpDecode(const void *packet, int bytes, uint32_t timestamp, int flags) override; void onRtpDecode(const uint8_t *packet, int bytes, uint32_t timestamp, int flags) override;
void onPSDecode(int stream, void onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts, const void *data,int bytes);
int codecid,
int flags,
int64_t pts,
int64_t dts,
const void *data,
int bytes) override ;
private: private:
void getNextRtpType(); void getNextRtpType();
private: private:
@ -82,6 +76,7 @@ private:
int _rtp_type_idx = 0; int _rtp_type_idx = 0;
string _rtp_type; string _rtp_type;
int _rtp_dec_failed_cnt = 0; int _rtp_dec_failed_cnt = 0;
Decoder::Ptr _decoder;
}; };
}//namespace mediakit }//namespace mediakit

96
src/Rtp/TSDecoder.cpp Normal file
View File

@ -0,0 +1,96 @@
/*
* MIT License
*
* Copyright (c) 2020 xiongziliang <771730766@qq.com>
*
* 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.
*/
#if defined(ENABLE_RTPPROXY)
#include "mpeg-ts.h"
#include "TSDecoder.h"
#define TS_PACKET_SIZE 188
namespace mediakit {
void TSSegment::setOnSegment(const TSSegment::onSegment &cb) {
_onSegment = cb;
}
int64_t TSSegment::onRecvHeader(const char *data, uint64_t len) {
_onSegment(data, len);
return 0;
}
const char *TSSegment::onSearchPacketTail(const char *data, int len) {
if (len < _size + 1) {
if (len == _size && ((uint8_t *) data)[0] == 0x47) {
return data + _size;
}
return nullptr;
}
//下一个包头
if (((uint8_t *) data)[_size] == 0x47) {
return data + _size;
}
auto pos = memchr(data + _size, 0x47, len - _size);
if (pos) {
return (char *) pos;
}
return nullptr;
}
////////////////////////////////////////////////////////////////
TSDecoder::TSDecoder() : _ts_segment(TS_PACKET_SIZE) {
_ts_segment.setOnSegment([this](const char *data,uint64_t len){
if(((uint8_t*)data)[0] != 0x47 || len != TS_PACKET_SIZE ){
WarnL << "不是ts包:" << (int)(data[0]) << " " << len;
return;
}
ts_demuxer_input(_demuxer_ctx,(uint8_t*)data,len);
});
_demuxer_ctx = ts_demuxer_create([](void* param, int program, int stream, int codecid, int flags, int64_t pts, int64_t dts, const void* data, size_t bytes){
TSDecoder *thiz = (TSDecoder*)param;
if(thiz->_on_decode){
thiz->_on_decode(stream,codecid,flags,pts,dts,data,bytes);
}
return 0;
},this);
}
TSDecoder::~TSDecoder() {
ts_demuxer_destroy(_demuxer_ctx);
}
int TSDecoder::input(const uint8_t *data, int bytes) {
if(bytes == TS_PACKET_SIZE && ((uint8_t*)data)[0] == 0x47){
return ts_demuxer_input(_demuxer_ctx,(uint8_t*)data,bytes);
}
_ts_segment.input((char*)data,bytes);
return bytes;
}
void TSDecoder::setOnDecode(const Decoder::onDecode &decode) {
_on_decode = decode;
}
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)

68
src/Rtp/TSDecoder.h Normal file
View File

@ -0,0 +1,68 @@
/*
* MIT License
*
* Copyright (c) 2020 xiongziliang <771730766@qq.com>
*
* 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.
*/
#ifndef ZLMEDIAKIT_TSDECODER_H
#define ZLMEDIAKIT_TSDECODER_H
#if defined(ENABLE_RTPPROXY)
#include "Util/logger.h"
#include "Http/HttpRequestSplitter.h"
#include "Decoder.h"
using namespace toolkit;
namespace mediakit {
//ts包拆分器
class TSSegment : public HttpRequestSplitter {
public:
typedef std::function<void(const char *data,uint64_t len)> onSegment;
TSSegment(int size = 188) : _size(size){}
~TSSegment(){}
void setOnSegment(const onSegment &cb);
protected:
int64_t onRecvHeader(const char *data, uint64_t len) override ;
const char *onSearchPacketTail(const char *data, int len) override ;
private:
int _size;
onSegment _onSegment;
};
//ts解析器
class TSDecoder : public Decoder {
public:
TSDecoder();
~TSDecoder();
int input(const uint8_t* data, int bytes) override ;
void setOnDecode(const onDecode &decode) override;
private:
TSSegment _ts_segment;
struct ts_demuxer_t* _demuxer_ctx = nullptr;
onDecode _on_decode;
};
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)
#endif //ZLMEDIAKIT_TSDECODER_H