mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
尝试修复时间戳回环或乱序导致的问题
This commit is contained in:
parent
6a9eb8d54b
commit
f9426c2cfb
@ -104,41 +104,15 @@ void MP4Muxer::onTrackFrame(const Frame::Ptr &frame) {
|
|||||||
|
|
||||||
//mp4文件时间戳需要从0开始
|
//mp4文件时间戳需要从0开始
|
||||||
auto &track_info = it->second;
|
auto &track_info = it->second;
|
||||||
if(!track_info.start_dts){
|
int64_t dts_out, pts_out;
|
||||||
track_info.start_dts = frame->dts();
|
track_info.stamp.revise(frame->dts(),frame->pts(),dts_out,pts_out);
|
||||||
}
|
|
||||||
|
|
||||||
//相对时间戳
|
|
||||||
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;
|
|
||||||
|
|
||||||
mov_writer_write_l(_mov_writter.get(),
|
mov_writer_write_l(_mov_writter.get(),
|
||||||
track_info.track_id,
|
track_info.track_id,
|
||||||
frame->data() + frame->prefixSize(),
|
frame->data() + frame->prefixSize(),
|
||||||
frame->size() - frame->prefixSize(),
|
frame->size() - frame->prefixSize(),
|
||||||
pts_dts_diff + dts_inc,
|
pts_out,
|
||||||
dts_inc,
|
dts_out,
|
||||||
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
||||||
with_nalu_size);
|
with_nalu_size);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "Extension/AAC.h"
|
#include "Extension/AAC.h"
|
||||||
#include "Extension/H264.h"
|
#include "Extension/H264.h"
|
||||||
#include "Extension/H265.h"
|
#include "Extension/H265.h"
|
||||||
|
#include "Stamp.h"
|
||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
@ -76,10 +77,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
struct track_info{
|
struct track_info{
|
||||||
int track_id = -1;
|
int track_id = -1;
|
||||||
int64_t start_dts = 0;
|
Stamp stamp;
|
||||||
int64_t dts_inc = 0;
|
|
||||||
};
|
};
|
||||||
map<CodecId,track_info> _codec_to_trackid;
|
unordered_map<int,track_info> _codec_to_trackid;
|
||||||
bool _started = false;
|
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) {
|
void TsMuxer::addTrack(const Track::Ptr &track) {
|
||||||
switch (track->getCodecId()){
|
switch (track->getCodecId()){
|
||||||
case CodecH264:
|
case CodecH264: {
|
||||||
_codecid_to_stream_id[CodecH264] = mpeg_ts_add_stream(_context,PSI_STREAM_H264, nullptr,0);
|
track_info info;
|
||||||
break;
|
info.track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H264, nullptr, 0);
|
||||||
case CodecH265:
|
_codec_to_trackid[track->getCodecId()] = info;
|
||||||
_codecid_to_stream_id[CodecH265] = mpeg_ts_add_stream(_context,PSI_STREAM_H265, nullptr,0);
|
} break;
|
||||||
break;
|
case CodecH265: {
|
||||||
case CodecAAC:
|
track_info info;
|
||||||
_codecid_to_stream_id[CodecAAC] = mpeg_ts_add_stream(_context,PSI_STREAM_AAC, nullptr,0);
|
info.track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H265, nullptr, 0);
|
||||||
break;
|
_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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TsMuxer::inputFrame(const Frame::Ptr &frame) {
|
void TsMuxer::inputFrame(const Frame::Ptr &frame) {
|
||||||
auto it = _codecid_to_stream_id.find(frame->getCodecId());
|
auto it = _codec_to_trackid.find(frame->getCodecId());
|
||||||
if(it == _codecid_to_stream_id.end()){
|
if(it == _codec_to_trackid.end()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//mp4文件时间戳需要从0开始
|
||||||
|
auto &track_info = it->second;
|
||||||
|
int64_t dts_out, pts_out;
|
||||||
|
|
||||||
switch (frame->getCodecId()){
|
switch (frame->getCodecId()){
|
||||||
case CodecH265:
|
case CodecH265:
|
||||||
case CodecH264: {
|
case CodecH264: {
|
||||||
@ -79,16 +89,18 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) {
|
|||||||
});
|
});
|
||||||
merged_frame = std::make_shared<BufferString>(std::move(merged));
|
merged_frame = std::make_shared<BufferString>(std::move(merged));
|
||||||
}
|
}
|
||||||
_timestamp = back->dts();
|
track_info.stamp.revise(back->dts(),back->pts(),dts_out,pts_out);
|
||||||
mpeg_ts_write(_context, it->second, back->keyFrame() ? 0x0001 : 0, back->pts() * 90LL, back->dts() * 90LL, merged_frame->data(), merged_frame->size());
|
_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.clear();
|
||||||
}
|
}
|
||||||
_frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
|
_frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
_timestamp = frame->dts();
|
track_info.stamp.revise(frame->dts(),frame->pts(),dts_out,pts_out);
|
||||||
mpeg_ts_write(_context, it->second, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size());
|
_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;
|
break;
|
||||||
}
|
}
|
||||||
@ -124,7 +136,7 @@ void TsMuxer::uninit() {
|
|||||||
mpeg_ts_destroy(_context);
|
mpeg_ts_destroy(_context);
|
||||||
_context = nullptr;
|
_context = nullptr;
|
||||||
}
|
}
|
||||||
_codecid_to_stream_id.clear();
|
_codec_to_trackid.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include "Extension/Track.h"
|
#include "Extension/Track.h"
|
||||||
#include "Util/File.h"
|
#include "Util/File.h"
|
||||||
#include "Common/MediaSink.h"
|
#include "Common/MediaSink.h"
|
||||||
|
#include "Stamp.h"
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
@ -52,7 +54,12 @@ private:
|
|||||||
void *_context = nullptr;
|
void *_context = nullptr;
|
||||||
char *_tsbuf[188];
|
char *_tsbuf[188];
|
||||||
uint32_t _timestamp = 0;
|
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;
|
List<Frame::Ptr> _frameCached;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user