mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
TS: hls/http-ts 改为绝对时间戳
This commit is contained in:
parent
878ce87329
commit
b749cfb8a3
@ -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)
|
@ -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
|
||||||
@ -54,10 +57,8 @@ protected:
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user