mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
尝试修复时间戳回环或乱序导致的问题
This commit is contained in:
parent
6a9eb8d54b
commit
f9426c2cfb
@ -104,41 +104,15 @@ void MP4Muxer::onTrackFrame(const Frame::Ptr &frame) {
|
||||
|
||||
//mp4文件时间戳需要从0开始
|
||||
auto &track_info = it->second;
|
||||
if(!track_info.start_dts){
|
||||
track_info.start_dts = frame->dts();
|
||||
}
|
||||
|
||||
//相对时间戳
|
||||
int64_t dts_inc = frame->dts() - track_info.start_dts;
|
||||
//pts和dts的差值
|
||||
int pts_dts_diff = frame->pts() - frame->dts();
|
||||
if(pts_dts_diff > 200 || pts_dts_diff < -200){
|
||||
//如果差值大于200毫秒,则认为由于回环导致时间戳错乱了
|
||||
pts_dts_diff = 0;
|
||||
}
|
||||
|
||||
if(dts_inc < track_info.dts_inc){
|
||||
//本次相对时间戳竟然小于上次?
|
||||
if(dts_inc < 0){
|
||||
//时间戳回环,保证下次相对时间戳与本次相对合理增长
|
||||
track_info.start_dts = frame->dts() - track_info.dts_inc;
|
||||
//本次时间戳强制等于上次时间戳+10
|
||||
dts_inc = track_info.dts_inc + 10;
|
||||
}else{
|
||||
//时间戳变小了?,那么取上次时间戳+10
|
||||
dts_inc = track_info.dts_inc + 10;
|
||||
}
|
||||
}
|
||||
|
||||
//保留上次相对时间戳
|
||||
track_info.dts_inc = dts_inc;
|
||||
int64_t dts_out, pts_out;
|
||||
track_info.stamp.revise(frame->dts(),frame->pts(),dts_out,pts_out);
|
||||
|
||||
mov_writer_write_l(_mov_writter.get(),
|
||||
track_info.track_id,
|
||||
frame->data() + frame->prefixSize(),
|
||||
frame->size() - frame->prefixSize(),
|
||||
pts_dts_diff + dts_inc,
|
||||
dts_inc,
|
||||
pts_out,
|
||||
dts_out,
|
||||
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
||||
with_nalu_size);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "Extension/AAC.h"
|
||||
#include "Extension/H264.h"
|
||||
#include "Extension/H265.h"
|
||||
#include "Stamp.h"
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
@ -76,10 +77,9 @@ protected:
|
||||
private:
|
||||
struct track_info{
|
||||
int track_id = -1;
|
||||
int64_t start_dts = 0;
|
||||
int64_t dts_inc = 0;
|
||||
Stamp stamp;
|
||||
};
|
||||
map<CodecId,track_info> _codec_to_trackid;
|
||||
unordered_map<int,track_info> _codec_to_trackid;
|
||||
bool _started = false;
|
||||
};
|
||||
|
||||
|
74
src/MediaFile/Stamp.cpp
Normal file
74
src/MediaFile/Stamp.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 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.
|
||||
*/
|
||||
|
||||
#include "Stamp.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
void Stamp::revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out) {
|
||||
if(_first){
|
||||
//记录第一次时间戳,后面好计算时间戳增量
|
||||
_start_dts = dts;
|
||||
_first = false;
|
||||
}
|
||||
|
||||
//相对时间戳
|
||||
dts_out = dts - _start_dts;
|
||||
if(dts_out < _dts_inc){
|
||||
//本次相对时间戳竟然小于上次?
|
||||
if(dts_out < 0 || _dts_inc - dts_out > 0xFFFF){
|
||||
//时间戳回环,保证下次相对时间戳与本次相对合理增长
|
||||
_start_dts = dts - _dts_inc;
|
||||
//本次时间戳强制等于上次时间戳
|
||||
dts_out = _dts_inc;
|
||||
}else{
|
||||
//时间戳变小了?,那么取上次时间戳
|
||||
dts_out = _dts_inc;
|
||||
}
|
||||
}
|
||||
|
||||
//保留这次相对时间戳,以便下次对比是否回环或乱序
|
||||
_dts_inc = dts_out;
|
||||
|
||||
//////////////以下是播放时间戳的计算//////////////////
|
||||
if(!pts){
|
||||
//没有播放时间戳
|
||||
pts = dts;
|
||||
}
|
||||
//pts和dts的差值
|
||||
int pts_dts_diff = pts - dts;
|
||||
if(pts_dts_diff > 200 || pts_dts_diff < -200){
|
||||
//如果差值大于200毫秒,则认为由于回环导致时间戳错乱了
|
||||
pts_dts_diff = 0;
|
||||
}
|
||||
pts_out = dts_out + pts_dts_diff;
|
||||
if(pts_out < 0){
|
||||
//时间戳不能小于0
|
||||
pts_out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
48
src/MediaFile/Stamp.h
Normal file
48
src/MediaFile/Stamp.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 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_STAMP_H
|
||||
#define ZLMEDIAKIT_STAMP_H
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class Stamp {
|
||||
public:
|
||||
Stamp() = default;
|
||||
~Stamp() = default;
|
||||
void revise(uint32_t dts, uint32_t pts, int64_t &dts_out, int64_t &pts_out);
|
||||
private:
|
||||
int64_t _start_dts = 0;
|
||||
int64_t _dts_inc = 0;
|
||||
bool _first = true;
|
||||
};
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_STAMP_H
|
@ -41,25 +41,35 @@ TsMuxer::~TsMuxer() {
|
||||
|
||||
void TsMuxer::addTrack(const Track::Ptr &track) {
|
||||
switch (track->getCodecId()){
|
||||
case CodecH264:
|
||||
_codecid_to_stream_id[CodecH264] = mpeg_ts_add_stream(_context,PSI_STREAM_H264, nullptr,0);
|
||||
break;
|
||||
case CodecH265:
|
||||
_codecid_to_stream_id[CodecH265] = mpeg_ts_add_stream(_context,PSI_STREAM_H265, nullptr,0);
|
||||
break;
|
||||
case CodecAAC:
|
||||
_codecid_to_stream_id[CodecAAC] = mpeg_ts_add_stream(_context,PSI_STREAM_AAC, nullptr,0);
|
||||
break;
|
||||
case CodecH264: {
|
||||
track_info info;
|
||||
info.track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H264, nullptr, 0);
|
||||
_codec_to_trackid[track->getCodecId()] = info;
|
||||
} break;
|
||||
case CodecH265: {
|
||||
track_info info;
|
||||
info.track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H265, nullptr, 0);
|
||||
_codec_to_trackid[track->getCodecId()] = info;
|
||||
}break;
|
||||
case CodecAAC: {
|
||||
track_info info;
|
||||
info.track_id = mpeg_ts_add_stream(_context, PSI_STREAM_AAC, nullptr, 0);
|
||||
_codec_to_trackid[track->getCodecId()] = info;
|
||||
}break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TsMuxer::inputFrame(const Frame::Ptr &frame) {
|
||||
auto it = _codecid_to_stream_id.find(frame->getCodecId());
|
||||
if(it == _codecid_to_stream_id.end()){
|
||||
auto it = _codec_to_trackid.find(frame->getCodecId());
|
||||
if(it == _codec_to_trackid.end()){
|
||||
return;
|
||||
}
|
||||
//mp4文件时间戳需要从0开始
|
||||
auto &track_info = it->second;
|
||||
int64_t dts_out, pts_out;
|
||||
|
||||
switch (frame->getCodecId()){
|
||||
case CodecH265:
|
||||
case CodecH264: {
|
||||
@ -79,16 +89,18 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) {
|
||||
});
|
||||
merged_frame = std::make_shared<BufferString>(std::move(merged));
|
||||
}
|
||||
_timestamp = back->dts();
|
||||
mpeg_ts_write(_context, it->second, back->keyFrame() ? 0x0001 : 0, back->pts() * 90LL, back->dts() * 90LL, merged_frame->data(), merged_frame->size());
|
||||
track_info.stamp.revise(back->dts(),back->pts(),dts_out,pts_out);
|
||||
_timestamp = dts_out;
|
||||
mpeg_ts_write(_context, track_info.track_id, back->keyFrame() ? 0x0001 : 0, pts_out * 90LL, dts_out * 90LL, merged_frame->data(), merged_frame->size());
|
||||
_frameCached.clear();
|
||||
}
|
||||
_frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
_timestamp = frame->dts();
|
||||
mpeg_ts_write(_context, it->second, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size());
|
||||
track_info.stamp.revise(frame->dts(),frame->pts(),dts_out,pts_out);
|
||||
_timestamp = dts_out;
|
||||
mpeg_ts_write(_context, track_info.track_id, frame->keyFrame() ? 0x0001 : 0, pts_out * 90LL, dts_out * 90LL, frame->data(), frame->size());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -124,7 +136,7 @@ void TsMuxer::uninit() {
|
||||
mpeg_ts_destroy(_context);
|
||||
_context = nullptr;
|
||||
}
|
||||
_codecid_to_stream_id.clear();
|
||||
_codec_to_trackid.clear();
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "Extension/Track.h"
|
||||
#include "Util/File.h"
|
||||
#include "Common/MediaSink.h"
|
||||
#include "Stamp.h"
|
||||
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
@ -52,7 +54,12 @@ private:
|
||||
void *_context = nullptr;
|
||||
char *_tsbuf[188];
|
||||
uint32_t _timestamp = 0;
|
||||
unordered_map<int,int > _codecid_to_stream_id;
|
||||
|
||||
struct track_info{
|
||||
int track_id = -1;
|
||||
Stamp stamp;
|
||||
};
|
||||
unordered_map<int,track_info> _codec_to_trackid;
|
||||
List<Frame::Ptr> _frameCached;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user