优化rtmp时间戳修正

This commit is contained in:
xiongziliang 2019-08-22 14:56:58 +08:00
parent 7f0fa0ead1
commit fc0544512b
4 changed files with 37 additions and 41 deletions

View File

@ -29,15 +29,21 @@
namespace mediakit { namespace mediakit {
void Stamp::revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out) { void Stamp::revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out) {
if(!pts){
//没有播放时间戳,使其赋值为解码时间戳
pts = dts;
}
//pts和dts的差值
int pts_dts_diff = pts - dts;
if(_first){ if(_first){
//记录第一次时间戳,后面好计算时间戳增量 //记录第一次时间戳,后面好计算时间戳增量
_start_dts = dts; _start_dts = dts;
_first = false; _first = false;
_ticker = std::make_shared<SmoothTicker>(); _ticker = std::make_shared<SmoothTicker>();
} }
//pts和dts的差值 if (!dts) {
int pts_dts_diff = pts - dts; //没有解码时间戳,我们生成解码时间戳
if(_modifyStamp){
dts = _ticker->elapsedTime(); dts = _ticker->elapsedTime();
} }
@ -60,11 +66,6 @@ void Stamp::revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_ou
_dts_inc = dts_out; _dts_inc = dts_out;
//////////////以下是播放时间戳的计算////////////////// //////////////以下是播放时间戳的计算//////////////////
if(!pts){
//没有播放时间戳
pts = dts;
}
if(pts_dts_diff > 200 || pts_dts_diff < -200){ if(pts_dts_diff > 200 || pts_dts_diff < -200){
//如果差值大于200毫秒则认为由于回环导致时间戳错乱了 //如果差值大于200毫秒则认为由于回环导致时间戳错乱了
pts_dts_diff = 0; pts_dts_diff = 0;

View File

@ -33,16 +33,17 @@ using namespace toolkit;
namespace mediakit { namespace mediakit {
//该类解决时间戳回环、回退问题
//计算相对时间戳或者产生平滑时间戳
class Stamp { class Stamp {
public: public:
Stamp(bool modifyStamp = false) {_modifyStamp = modifyStamp;}; Stamp() = default;
~Stamp() = default; ~Stamp() = default;
void revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out); void revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out);
private: private:
int64_t _start_dts = 0; int64_t _start_dts = 0;
int64_t _dts_inc = 0; int64_t _dts_inc = 0;
bool _first = true; bool _first = true;
bool _modifyStamp;
std::shared_ptr<SmoothTicker> _ticker; std::shared_ptr<SmoothTicker> _ticker;
}; };

View File

@ -397,20 +397,20 @@ void RtmpSession::setMetaData(AMFDecoder &dec) {
void RtmpSession::onProcessCmd(AMFDecoder &dec) { void RtmpSession::onProcessCmd(AMFDecoder &dec) {
typedef void (RtmpSession::*rtmpCMDHandle)(AMFDecoder &dec); typedef void (RtmpSession::*rtmpCMDHandle)(AMFDecoder &dec);
static unordered_map<string, rtmpCMDHandle> g_mapCmd; static unordered_map<string, rtmpCMDHandle> s_cmd_functions;
static onceToken token([]() { static onceToken token([]() {
g_mapCmd.emplace("connect",&RtmpSession::onCmd_connect); s_cmd_functions.emplace("connect",&RtmpSession::onCmd_connect);
g_mapCmd.emplace("createStream",&RtmpSession::onCmd_createStream); s_cmd_functions.emplace("createStream",&RtmpSession::onCmd_createStream);
g_mapCmd.emplace("publish",&RtmpSession::onCmd_publish); s_cmd_functions.emplace("publish",&RtmpSession::onCmd_publish);
g_mapCmd.emplace("deleteStream",&RtmpSession::onCmd_deleteStream); s_cmd_functions.emplace("deleteStream",&RtmpSession::onCmd_deleteStream);
g_mapCmd.emplace("play",&RtmpSession::onCmd_play); s_cmd_functions.emplace("play",&RtmpSession::onCmd_play);
g_mapCmd.emplace("play2",&RtmpSession::onCmd_play2); s_cmd_functions.emplace("play2",&RtmpSession::onCmd_play2);
g_mapCmd.emplace("seek",&RtmpSession::onCmd_seek); s_cmd_functions.emplace("seek",&RtmpSession::onCmd_seek);
g_mapCmd.emplace("pause",&RtmpSession::onCmd_pause);}, []() {}); s_cmd_functions.emplace("pause",&RtmpSession::onCmd_pause);}, []() {});
std::string method = dec.load<std::string>(); std::string method = dec.load<std::string>();
auto it = g_mapCmd.find(method); auto it = s_cmd_functions.find(method);
if (it == g_mapCmd.end()) { if (it == s_cmd_functions.end()) {
TraceP(this) << "can not support cmd:" << method; TraceP(this) << "can not support cmd:" << method;
return; return;
} }
@ -444,10 +444,12 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
throw std::runtime_error("Not a rtmp publisher!"); throw std::runtime_error("Not a rtmp publisher!");
} }
GET_CONFIG(bool,rtmp_modify_stamp,Rtmp::kModifyStamp); GET_CONFIG(bool,rtmp_modify_stamp,Rtmp::kModifyStamp);
if(rtmp_modify_stamp){ if(rtmp_modify_stamp){
chunkData.timeStamp = _stampTicker[chunkData.typeId % 2].elapsedTime(); int64_t dts_out;
} _stamp[chunkData.typeId % 2].revise(0, 0, dts_out, dts_out);
_pPublisherSrc->onWrite(std::make_shared<RtmpPacket>(std::move(chunkData))); chunkData.timeStamp = dts_out;
}
_pPublisherSrc->onWrite(std::make_shared<RtmpPacket>(std::move(chunkData)));
} }
break; break;
default: default:
@ -473,20 +475,10 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
} }
void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) { void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
auto modifiedStamp = pkt->timeStamp; //rtmp播放器时间戳从零开始
auto &firstStamp = _aui32FirstStamp[pkt->typeId % 2]; int64_t dts_out;
if(!firstStamp){ _stamp[pkt->typeId % 2].revise(pkt->timeStamp, 0, dts_out, dts_out);
firstStamp = modifiedStamp; sendRtmp(pkt->typeId, pkt->streamId, pkt, dts_out, pkt->chunkId);
}
if(modifiedStamp >= firstStamp){
//计算时间戳增量
modifiedStamp -= firstStamp;
}else{
//发生回环,重新计算时间戳增量
CLEAR_ARR(_aui32FirstStamp);
modifiedStamp = 0;
}
sendRtmp(pkt->typeId, pkt->streamId, pkt, modifiedStamp, pkt->chunkId);
} }

View File

@ -37,6 +37,8 @@
#include "Util/util.h" #include "Util/util.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "Network/TcpSession.h" #include "Network/TcpSession.h"
#include "MediaFile/Stamp.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
@ -88,11 +90,11 @@ private:
MediaInfo _mediaInfo; MediaInfo _mediaInfo;
double _dNowReqID = 0; double _dNowReqID = 0;
Ticker _ticker;//数据接收时间 Ticker _ticker;//数据接收时间
SmoothTicker _stampTicker[2];//时间戳生产器
RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr _pRingReader; RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr _pRingReader;
std::shared_ptr<RtmpMediaSource> _pPublisherSrc; std::shared_ptr<RtmpMediaSource> _pPublisherSrc;
std::weak_ptr<RtmpMediaSource> _pPlayerSrc; std::weak_ptr<RtmpMediaSource> _pPlayerSrc;
uint32_t _aui32FirstStamp[2] = {0}; //时间戳修整器
Stamp _stamp[2];
//消耗的总流量 //消耗的总流量
uint64_t _ui64TotalBytes = 0; uint64_t _ui64TotalBytes = 0;