TS: hls/http-ts 改为绝对时间戳

This commit is contained in:
ziyue 2021-12-28 17:09:20 +08:00
parent 878ce87329
commit b749cfb8a3
2 changed files with 21 additions and 49 deletions

View File

@ -9,6 +9,7 @@
*/ */
#if defined(ENABLE_HLS) #if defined(ENABLE_HLS)
#include "TsMuxer.h" #include "TsMuxer.h"
#include "mpeg-ts-proto.h" #include "mpeg-ts-proto.h"
#include "mpeg-ts.h" #include "mpeg-ts.h"
@ -24,65 +25,43 @@ TsMuxer::~TsMuxer() {
uninit(); uninit();
} }
void TsMuxer::stampSync(){
if (_codec_to_trackid.size() < 2) {
return;
}
Stamp *audio = nullptr, *video = nullptr;
for (auto &pr : _codec_to_trackid) {
switch (getTrackType((CodecId) pr.first)) {
case TrackAudio : audio = &pr.second.stamp; break;
case TrackVideo : video = &pr.second.stamp; break;
default : break;
}
}
if (audio && video) {
//音频时间戳同步于视频,因为音频时间戳被修改后不影响播放
audio->syncTo(*video);
}
}
bool TsMuxer::addTrack(const Track::Ptr &track) { bool TsMuxer::addTrack(const Track::Ptr &track) {
switch (track->getCodecId()) { switch (track->getCodecId()) {
case CodecH264: { case CodecH264: {
_have_video = true; _have_video = true;
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H264, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_H264, nullptr, 0);
break; break;
} }
case CodecH265: { case CodecH265: {
_have_video = true; _have_video = true;
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_H265, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_H265, nullptr, 0);
break; break;
} }
case CodecAAC: { case CodecAAC: {
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_AAC, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_AAC, nullptr, 0);
break; break;
} }
case CodecG711A: { case CodecG711A: {
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_G711A, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_G711A,nullptr, 0);
break; break;
} }
case CodecG711U: { case CodecG711U: {
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_G711U, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_G711U,nullptr, 0);
break; break;
} }
case CodecOpus: { case CodecOpus: {
_codec_to_trackid[track->getCodecId()].track_id = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_OPUS, nullptr, 0); _codec_to_trackid[track->getCodecId()] = mpeg_ts_add_stream(_context, PSI_STREAM_AUDIO_OPUS,nullptr, 0);
break; break;
} }
default: WarnL << "mpeg-ts 不支持该编码格式,已忽略:" << track->getCodecName(); return false; default: WarnL << "mpeg-ts 不支持该编码格式,已忽略:" << track->getCodecName(); return false;
} }
//尝试音视频同步
stampSync();
return true; return true;
} }
@ -91,20 +70,17 @@ bool TsMuxer::inputFrame(const Frame::Ptr &frame) {
if (it == _codec_to_trackid.end()) { if (it == _codec_to_trackid.end()) {
return false; return false;
} }
auto &track_info = it->second; auto track_id = it->second;
int64_t dts_out, pts_out;
_is_idr_fast_packet = !_have_video; _is_idr_fast_packet = !_have_video;
switch (frame->getCodecId()){ switch (frame->getCodecId()) {
case CodecH264: case CodecH264:
case CodecH265: { case CodecH265: {
//这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理 //这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理
return _frame_merger.inputFrame(frame, [&](uint32_t dts, uint32_t pts, const Buffer::Ptr &buffer, bool have_idr){ return _frame_merger.inputFrame(frame,[&](uint32_t dts, uint32_t pts, const Buffer::Ptr &buffer, bool have_idr) {
track_info.stamp.revise(dts, pts, dts_out, pts_out);
//取视频时间戳为TS的时间戳 //取视频时间戳为TS的时间戳
_timestamp = (uint32_t) dts_out; _timestamp = (uint32_t) dts;
_is_idr_fast_packet = have_idr; _is_idr_fast_packet = have_idr;
mpeg_ts_write(_context, track_info.track_id, have_idr ? 0x0001 : 0, mpeg_ts_write(_context, track_id, have_idr ? 0x0001 : 0, pts * 90LL,dts * 90LL, buffer->data(), buffer->size());
pts_out * 90LL, dts_out * 90LL, buffer->data(), buffer->size());
flushCache(); flushCache();
}); });
} }
@ -117,13 +93,11 @@ bool TsMuxer::inputFrame(const Frame::Ptr &frame) {
} }
default: { default: {
track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out);
if (!_have_video) { if (!_have_video) {
//没有视频时才以音频时间戳为TS的时间戳 //没有视频时才以音频时间戳为TS的时间戳
_timestamp = (uint32_t) dts_out; _timestamp = (uint32_t) frame->dts();
} }
mpeg_ts_write(_context, track_info.track_id, frame->keyFrame() ? 0x0001 : 0, mpeg_ts_write(_context, track_id, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size());
pts_out * 90LL, dts_out * 90LL, frame->data(), frame->size());
flushCache(); flushCache();
return true; return true;
} }
@ -181,4 +155,5 @@ void TsMuxer::uninit() {
} }
}//namespace mediakit }//namespace mediakit
#endif// defined(ENABLE_HLS) #endif// defined(ENABLE_HLS)

View File

@ -12,13 +12,16 @@
#define TSMUXER_H #define TSMUXER_H
#if defined(ENABLE_HLS) #if defined(ENABLE_HLS)
#include <unordered_map> #include <unordered_map>
#include "Extension/Frame.h" #include "Extension/Frame.h"
#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 "Common/Stamp.h" #include "Common/Stamp.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
//该类用于产生MPEG-TS //该类用于产生MPEG-TS
@ -49,15 +52,13 @@ protected:
* @param timestamp * @param timestamp
* @param is_idr_fast_packet TS包ts切片第一帧为关键帧 * @param is_idr_fast_packet TS包ts切片第一帧为关键帧
*/ */
virtual void onTs(std::shared_ptr<Buffer> buffer, uint32_t timestamp,bool is_idr_fast_packet) = 0; virtual void onTs(std::shared_ptr<Buffer> buffer, uint32_t timestamp, bool is_idr_fast_packet) = 0;
private: private:
void init(); void init();
void uninit(); void uninit();
//音视频时间戳同步用
void stampSync();
void onTs_l(const void *packet, size_t bytes);
void flushCache(); void flushCache();
void onTs_l(const void *packet, size_t bytes);
private: private:
bool _have_video = false; bool _have_video = false;
@ -65,11 +66,7 @@ private:
void *_context = nullptr; void *_context = nullptr;
char _tsbuf[188]; char _tsbuf[188];
uint32_t _timestamp = 0; uint32_t _timestamp = 0;
struct track_info { unordered_map<int, int/*track_id*/> _codec_to_trackid;
int track_id = -1;
Stamp stamp;
};
unordered_map<int, track_info> _codec_to_trackid;
FrameMerger _frame_merger{FrameMerger::h264_prefix}; FrameMerger _frame_merger{FrameMerger::h264_prefix};
std::shared_ptr<BufferLikeString> _cache; std::shared_ptr<BufferLikeString> _cache;
}; };