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)
#include "TsMuxer.h"
#include "mpeg-ts-proto.h"
#include "mpeg-ts.h"
@ -24,65 +25,43 @@ TsMuxer::~TsMuxer() {
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) {
switch (track->getCodecId()) {
case CodecH264: {
_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;
}
case CodecH265: {
_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;
}
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;
}
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;
}
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;
}
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;
}
default: WarnL << "mpeg-ts 不支持该编码格式,已忽略:" << track->getCodecName(); return false;
}
//尝试音视频同步
stampSync();
return true;
}
@ -91,20 +70,17 @@ bool TsMuxer::inputFrame(const Frame::Ptr &frame) {
if (it == _codec_to_trackid.end()) {
return false;
}
auto &track_info = it->second;
int64_t dts_out, pts_out;
auto track_id = it->second;
_is_idr_fast_packet = !_have_video;
switch (frame->getCodecId()){
switch (frame->getCodecId()) {
case CodecH264:
case CodecH265: {
//这里的代码逻辑是让SPS、PPS、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);
return _frame_merger.inputFrame(frame,[&](uint32_t dts, uint32_t pts, const Buffer::Ptr &buffer, bool have_idr) {
//取视频时间戳为TS的时间戳
_timestamp = (uint32_t) dts_out;
_timestamp = (uint32_t) dts;
_is_idr_fast_packet = have_idr;
mpeg_ts_write(_context, track_info.track_id, have_idr ? 0x0001 : 0,
pts_out * 90LL, dts_out * 90LL, buffer->data(), buffer->size());
mpeg_ts_write(_context, track_id, have_idr ? 0x0001 : 0, pts * 90LL,dts * 90LL, buffer->data(), buffer->size());
flushCache();
});
}
@ -117,13 +93,11 @@ bool TsMuxer::inputFrame(const Frame::Ptr &frame) {
}
default: {
track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out);
if (!_have_video) {
//没有视频时才以音频时间戳为TS的时间戳
_timestamp = (uint32_t) dts_out;
_timestamp = (uint32_t) frame->dts();
}
mpeg_ts_write(_context, track_info.track_id, frame->keyFrame() ? 0x0001 : 0,
pts_out * 90LL, dts_out * 90LL, frame->data(), frame->size());
mpeg_ts_write(_context, track_id, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size());
flushCache();
return true;
}
@ -181,4 +155,5 @@ void TsMuxer::uninit() {
}
}//namespace mediakit
#endif// defined(ENABLE_HLS)

View File

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