From 069bde09c1fefbb22218fc466c4813e95382ee75 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Fri, 6 Mar 2020 13:00:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81ts=20rtp=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Record/HlsMediaSource.h | 2 +- src/Rtp/Decoder.cpp | 41 ++++++++++++++++ src/Rtp/Decoder.h | 57 ++++++++++++++++++++++ src/Rtp/PSDecoder.cpp | 12 +++-- src/Rtp/PSDecoder.h | 20 +++----- src/Rtp/RtpDecoder.cpp | 2 +- src/Rtp/RtpDecoder.h | 2 +- src/Rtp/RtpProcess.cpp | 26 ++++++---- src/Rtp/RtpProcess.h | 15 ++---- src/Rtp/TSDecoder.cpp | 96 +++++++++++++++++++++++++++++++++++++ src/Rtp/TSDecoder.h | 68 ++++++++++++++++++++++++++ 11 files changed, 302 insertions(+), 39 deletions(-) create mode 100644 src/Rtp/Decoder.cpp create mode 100644 src/Rtp/Decoder.h create mode 100644 src/Rtp/TSDecoder.cpp create mode 100644 src/Rtp/TSDecoder.h diff --git a/src/Record/HlsMediaSource.h b/src/Record/HlsMediaSource.h index 8da52e2c..38a192b7 100644 --- a/src/Record/HlsMediaSource.h +++ b/src/Record/HlsMediaSource.h @@ -1,4 +1,4 @@ -/* +/* * MIT License * * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com> diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp new file mode 100644 index 00000000..ca6e8a6b --- /dev/null +++ b/src/Rtp/Decoder.cpp @@ -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(); + case decoder_ts : return std::make_shared(); + default : return nullptr; + } +} + +}//namespace mediakit +#endif//defined(ENABLE_RTPPROXY) diff --git a/src/Rtp/Decoder.h b/src/Rtp/Decoder.h new file mode 100644 index 00000000..406508d2 --- /dev/null +++ b/src/Rtp/Decoder.h @@ -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 +#include +#include +#include "Decoder.h" +using namespace std; +namespace mediakit { + +class Decoder { +public: + typedef std::shared_ptr Ptr; + typedef enum { + decoder_ts = 0, + decoder_ps + }Type; + + typedef std::function 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 diff --git a/src/Rtp/PSDecoder.cpp b/src/Rtp/PSDecoder.cpp index 47abb768..77733d2b 100644 --- a/src/Rtp/PSDecoder.cpp +++ b/src/Rtp/PSDecoder.cpp @@ -27,7 +27,6 @@ #if defined(ENABLE_RTPPROXY) #include "PSDecoder.h" #include "mpeg-ps.h" - namespace mediakit{ PSDecoder::PSDecoder() { @@ -40,7 +39,9 @@ PSDecoder::PSDecoder() { const void* data, size_t bytes){ 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); } @@ -48,10 +49,13 @@ PSDecoder::~PSDecoder() { 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); } -}//namespace mediakit +void PSDecoder::setOnDecode(const Decoder::onDecode &decode) { + _on_decode = decode; +} +}//namespace mediakit #endif//#if defined(ENABLE_RTPPROXY) \ No newline at end of file diff --git a/src/Rtp/PSDecoder.h b/src/Rtp/PSDecoder.h index c8a73872..967a4ed4 100644 --- a/src/Rtp/PSDecoder.h +++ b/src/Rtp/PSDecoder.h @@ -29,27 +29,21 @@ #if defined(ENABLE_RTPPROXY) #include - +#include "Decoder.h" namespace mediakit{ -class PSDecoder { +//ps解析器 +class PSDecoder : public Decoder { public: PSDecoder(); - virtual ~PSDecoder(); - int decodePS(const uint8_t *data, int bytes); -protected: - virtual void onPSDecode(int stream, - int codecid, - int flags, - int64_t pts, - int64_t dts, - const void *data, - int bytes) = 0; + ~PSDecoder(); + int input(const uint8_t* data, int bytes) override; + void setOnDecode(const onDecode &decode) override; private: void *_ps_demuxer = nullptr; + onDecode _on_decode; }; }//namespace mediakit - #endif//defined(ENABLE_RTPPROXY) #endif //ZLMEDIAKIT_PSDECODER_H diff --git a/src/Rtp/RtpDecoder.cpp b/src/Rtp/RtpDecoder.cpp index e7b63fb9..af64f0d5 100644 --- a/src/Rtp/RtpDecoder.cpp +++ b/src/Rtp/RtpDecoder.cpp @@ -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){ RtpDecoder *obj = (RtpDecoder *)param; - obj->onRtpDecode(packet, bytes, timestamp, flags); + obj->onRtpDecode((uint8_t *)packet, bytes, timestamp, flags); } }; diff --git a/src/Rtp/RtpDecoder.h b/src/Rtp/RtpDecoder.h index c89aebe3..a6d78a65 100644 --- a/src/Rtp/RtpDecoder.h +++ b/src/Rtp/RtpDecoder.h @@ -39,7 +39,7 @@ public: virtual ~RtpDecoder(); protected: 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: void *_rtp_decoder = nullptr; BufferRaw::Ptr _buffer; diff --git a/src/Rtp/RtpProcess.cpp b/src/Rtp/RtpProcess.cpp index 83ceb843..32986f98 100644 --- a/src/Rtp/RtpProcess.cpp +++ b/src/Rtp/RtpProcess.cpp @@ -179,12 +179,26 @@ void RtpProcess::onRtpSorted(const RtpPacket::Ptr &rtp, int) { 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){ 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){ WarnL << ret << " != " << bytes << " " << flags; if(++_rtp_dec_failed_cnt == 10){ @@ -215,13 +229,7 @@ static const char *getCodecName(int codec_id) { } } -void RtpProcess::onPSDecode(int stream, - int codecid, - int flags, - int64_t pts, - int64_t dts, - const void *data, - int bytes) { +void RtpProcess::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes) { pts /= 90; dts /= 90; _stamps[codecid].revise(dts,pts,dts,pts,false); diff --git a/src/Rtp/RtpProcess.h b/src/Rtp/RtpProcess.h index bf0b979a..e8295969 100644 --- a/src/Rtp/RtpProcess.h +++ b/src/Rtp/RtpProcess.h @@ -31,7 +31,7 @@ #include "Rtsp/RtpReceiver.h" #include "RtpDecoder.h" -#include "PSDecoder.h" +#include "Decoder.h" #include "Common/Device.h" #include "Common/Stamp.h" using namespace mediakit; @@ -40,7 +40,7 @@ namespace mediakit{ string printSSRC(uint32_t ui32Ssrc); class FrameMerger; -class RtpProcess : public RtpReceiver , public RtpDecoder , public PSDecoder { +class RtpProcess : public RtpReceiver , public RtpDecoder{ public: typedef std::shared_ptr Ptr; RtpProcess(uint32_t ssrc); @@ -54,14 +54,8 @@ public: void setListener(const std::weak_ptr &listener); protected: void onRtpSorted(const RtpPacket::Ptr &rtp, int track_index) override ; - void onRtpDecode(const void *packet, int bytes, uint32_t timestamp, int flags) override; - void onPSDecode(int stream, - int codecid, - int flags, - int64_t pts, - int64_t dts, - const void *data, - int bytes) override ; + void onRtpDecode(const uint8_t *packet, int bytes, uint32_t timestamp, int flags) override; + void onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts, const void *data,int bytes); private: void getNextRtpType(); private: @@ -82,6 +76,7 @@ private: int _rtp_type_idx = 0; string _rtp_type; int _rtp_dec_failed_cnt = 0; + Decoder::Ptr _decoder; }; }//namespace mediakit diff --git a/src/Rtp/TSDecoder.cpp b/src/Rtp/TSDecoder.cpp new file mode 100644 index 00000000..9f1bee8c --- /dev/null +++ b/src/Rtp/TSDecoder.cpp @@ -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) \ No newline at end of file diff --git a/src/Rtp/TSDecoder.h b/src/Rtp/TSDecoder.h new file mode 100644 index 00000000..dc442726 --- /dev/null +++ b/src/Rtp/TSDecoder.h @@ -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 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