ZLMediaKit/src/Extension/CommonRtp.cpp
夏楚 6aa4b741a3
修复通用rtp解码器输入小时间戳增量流在丢包时不再输出帧数据的bug (#2589)
如果rtp时间戳增量很小,在rtp时间戳在转换单位为毫秒时无变化,
从而被认为是上一帧数据,由于处于丢包状态,此rtp数据将被一直丢弃。
2023-06-28 14:56:24 +08:00

96 lines
3.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
#include "CommonRtp.h"
using namespace mediakit;
CommonRtpDecoder::CommonRtpDecoder(CodecId codec, size_t max_frame_size ){
_codec = codec;
_max_frame_size = max_frame_size;
obtainFrame();
}
CodecId CommonRtpDecoder::getCodecId() const {
return _codec;
}
void CommonRtpDecoder::obtainFrame() {
_frame = FrameImp::create();
_frame->_codec_id = _codec;
}
bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){
auto payload_size = rtp->getPayloadSize();
if (payload_size <= 0) {
//无实际负载
return false;
}
auto payload = rtp->getPayload();
auto stamp = rtp->getStamp();
auto seq = rtp->getSeq();
if (_last_stamp != stamp || _frame->_buffer.size() > _max_frame_size) {
//时间戳发生变化或者缓存超过MAX_FRAME_SIZE则清空上帧数据
if (!_frame->_buffer.empty()) {
//有有效帧,则输出
RtpCodec::inputFrame(_frame);
}
//新的一帧数据
obtainFrame();
_frame->_dts = rtp->getStampMS();
_last_stamp = stamp;
_drop_flag = false;
} else if (_last_seq != 0 && (uint16_t)(_last_seq + 1) != seq) {
//时间戳未发生变化但是seq却不连续说明中间rtp丢包了那么整帧应该废弃
WarnL << "rtp丢包:" << _last_seq << " -> " << seq;
_drop_flag = true;
_frame->_buffer.clear();
}
if (!_drop_flag) {
_frame->_buffer.append((char *)payload, payload_size);
}
_last_seq = seq;
return false;
}
////////////////////////////////////////////////////////////////
CommonRtpEncoder::CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size,
uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved)
: CommonRtpDecoder(codec), RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) {
}
bool CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){
auto stamp = frame->pts();
auto ptr = frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto remain_size = len;
auto max_size = getMaxSize();
bool is_key = frame->keyFrame();
bool mark = false;
while (remain_size > 0) {
size_t rtp_size;
if (remain_size > max_size) {
rtp_size = max_size;
} else {
rtp_size = remain_size;
mark = true;
}
RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), is_key);
ptr += rtp_size;
remain_size -= rtp_size;
is_key = false;
}
return len > 0;
}