From 341459fbf5e65a2350470a28b12d22fcca9b0967 Mon Sep 17 00:00:00 2001 From: xgj Date: Mon, 24 Jan 2022 11:57:24 +0800 Subject: [PATCH] fix non rtc push rtc play g711 audio loss --- src/Extension/Factory.cpp | 9 +++++-- src/Extension/G711Rtp.cpp | 46 +++++++++++++++++++++++++++++++++++ src/Extension/G711Rtp.h | 51 +++++++++++++++++++++++++++++++++++++++ webrtc/WebRtcPlayer.cpp | 2 +- 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 src/Extension/G711Rtp.cpp create mode 100644 src/Extension/G711Rtp.h diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 6d047940..b1614bf9 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -18,6 +18,7 @@ #include "AACRtp.h" #include "H265Rtp.h" #include "CommonRtp.h" +#include "G711Rtp.h" #include "Opus.h" #include "G711.h" #include "L16.h" @@ -119,9 +120,13 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) { case CodecH265 : return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); case CodecAAC : return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); case CodecL16 : - case CodecOpus : + case CodecOpus : return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); case CodecG711A : - case CodecG711U : return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); + case CodecG711U : + if(pt == Rtsp::PT_PCMA || pt == Rtsp::PT_PCMU){ + return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved,1); + } + return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); default : WarnL << "暂不支持该CodecId:" << codec_id; return nullptr; } } diff --git a/src/Extension/G711Rtp.cpp b/src/Extension/G711Rtp.cpp new file mode 100644 index 00000000..14b256b6 --- /dev/null +++ b/src/Extension/G711Rtp.cpp @@ -0,0 +1,46 @@ +#include "G711Rtp.h" + +G711RtpEncoder::G711RtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, + uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved,uint32_t channels) + : CommonRtpDecoder(codec), RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) { + _cache_frame = FrameImp::create(); + _cache_frame->_codec_id = codec; + _channels = channels; +} + +bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame){ + auto dur = (_cache_frame->size()-_cache_frame->prefixSize())/(8*_channels); + auto next_pts = _cache_frame->pts()+dur; + if(next_pts == 0){ + _cache_frame->_pts = frame->pts(); + }else{ + if((next_pts+20) < frame->pts()){// 有丢包超过20ms + _cache_frame->_pts = frame->pts() - dur; + } + } + _cache_frame->_buffer.append(frame->data() + frame->prefixSize(),frame->size() - frame->prefixSize()); + + auto stamp = _cache_frame->pts(); + auto ptr = _cache_frame->data() + _cache_frame->prefixSize(); + auto len = _cache_frame->size() - _cache_frame->prefixSize(); + auto remain_size = len; + auto max_size = 160*_channels; //20 ms per rtp + int n = 0; + bool mark = false; + while (remain_size >= max_size) { + size_t rtp_size; + if (remain_size >= max_size) { + rtp_size = max_size; + } else { + break; + } + n++; + stamp += 20; + RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), false); + ptr += rtp_size; + remain_size -= rtp_size; + } + _cache_frame->_buffer.erase(0,n*max_size); + _cache_frame->_pts += 20*n; + return len > 0; +} \ No newline at end of file diff --git a/src/Extension/G711Rtp.h b/src/Extension/G711Rtp.h new file mode 100644 index 00000000..3b66bdd8 --- /dev/null +++ b/src/Extension/G711Rtp.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * + * 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. + */ + +#ifndef ZLMEDIAKIT_G711RTP_H +#define ZLMEDIAKIT_G711RTP_H + +#include "Frame.h" +#include "CommonRtp.h" +#include "Rtsp/RtpCodec.h" + +namespace mediakit{ + + +/** + * G711 rtp编码类 + */ +class G711RtpEncoder : public CommonRtpDecoder, public RtpInfo { +public: + typedef std::shared_ptr Ptr; + + ~G711RtpEncoder() override {} + + /** + * 构造函数 + * @param codec 编码类型 + * @param ssrc ssrc + * @param mtu_size mtu 大小 + * @param sample_rate 采样率 + * @param payload_type pt类型 + * @param interleaved rtsp interleaved 值 + */ + G711RtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved,uint32_t channels); + + /** + * 输入帧数据并编码成rtp + */ + bool inputFrame(const Frame::Ptr &frame) override; +private: + FrameImp::Ptr _cache_frame; + uint32_t _channels = 1; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_G711RTP_H diff --git a/webrtc/WebRtcPlayer.cpp b/webrtc/WebRtcPlayer.cpp index 1bd8b513..4447ab8e 100644 --- a/webrtc/WebRtcPlayer.cpp +++ b/webrtc/WebRtcPlayer.cpp @@ -43,6 +43,7 @@ void WebRtcPlayer::onStartWebRTC() { } size_t i = 0; pkt->for_each([&](const RtpPacket::Ptr &rtp) { + //TraceL<<"send track type:"<type<<" ts:"<getStamp()<<" ntp:"<ntp_stamp<<" size:"<getPayloadSize()<<" i:"<onSendRtp(rtp, ++i == pkt->size()); }); }); @@ -57,7 +58,6 @@ void WebRtcPlayer::onStartWebRTC() { //使用完毕后,释放强引用,这样确保推流器断开后能及时注销媒体 _play_src = nullptr; } - void WebRtcPlayer::onDestory() { WebRtcTransportImp::onDestory();