From f9426c2cfb0027603328b4f2aae377a60b3d8def Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Fri, 2 Aug 2019 18:06:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E5=9B=9E=E7=8E=AF=E6=88=96=E4=B9=B1=E5=BA=8F?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MediaFile/MP4Muxer.cpp | 34 +++--------------- src/MediaFile/MP4Muxer.h | 6 ++-- src/MediaFile/Stamp.cpp | 74 ++++++++++++++++++++++++++++++++++++++ src/MediaFile/Stamp.h | 48 +++++++++++++++++++++++++ src/MediaFile/TsMuxer.cpp | 44 ++++++++++++++--------- src/MediaFile/TsMuxer.h | 9 ++++- 6 files changed, 165 insertions(+), 50 deletions(-) create mode 100644 src/MediaFile/Stamp.cpp create mode 100644 src/MediaFile/Stamp.h diff --git a/src/MediaFile/MP4Muxer.cpp b/src/MediaFile/MP4Muxer.cpp index 3e279d15..3f575e83 100644 --- a/src/MediaFile/MP4Muxer.cpp +++ b/src/MediaFile/MP4Muxer.cpp @@ -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); } diff --git a/src/MediaFile/MP4Muxer.h b/src/MediaFile/MP4Muxer.h index 79793323..a1191b79 100644 --- a/src/MediaFile/MP4Muxer.h +++ b/src/MediaFile/MP4Muxer.h @@ -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 _codec_to_trackid; + unordered_map _codec_to_trackid; bool _started = false; }; diff --git a/src/MediaFile/Stamp.cpp b/src/MediaFile/Stamp.cpp new file mode 100644 index 00000000..d90679b5 --- /dev/null +++ b/src/MediaFile/Stamp.cpp @@ -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 \ No newline at end of file diff --git a/src/MediaFile/Stamp.h b/src/MediaFile/Stamp.h new file mode 100644 index 00000000..d111c947 --- /dev/null +++ b/src/MediaFile/Stamp.h @@ -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 + +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 diff --git a/src/MediaFile/TsMuxer.cpp b/src/MediaFile/TsMuxer.cpp index 2eabd145..d1eeee1b 100644 --- a/src/MediaFile/TsMuxer.cpp +++ b/src/MediaFile/TsMuxer.cpp @@ -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(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 diff --git a/src/MediaFile/TsMuxer.h b/src/MediaFile/TsMuxer.h index 8185307f..06230bb5 100644 --- a/src/MediaFile/TsMuxer.h +++ b/src/MediaFile/TsMuxer.h @@ -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 _codecid_to_stream_id; + + struct track_info{ + int track_id = -1; + Stamp stamp; + }; + unordered_map _codec_to_trackid; List _frameCached; };