Support multi audio/video track

This commit is contained in:
夏楚
2023-12-09 22:34:22 +08:00
committed by GitHub
parent bbe8f4a018
commit 64f15202de
36 changed files with 366 additions and 278 deletions

View File

@@ -62,7 +62,9 @@ DecoderImp::Ptr DecoderImp::createDecoder(Type type, MediaSinkInterface *sink){
}
void DecoderImp::flush() {
_merger.flush();
for (auto &pr : _tracks) {
pr.second.second.flush();
}
}
ssize_t DecoderImp::input(const uint8_t *data, size_t bytes){
@@ -88,9 +90,9 @@ void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t byt
if (!track) {
return;
}
onTrack(std::move(track));
onTrack(stream, std::move(track));
// 防止未获取视频track提前complete导致忽略后续视频的问题用于兼容一些不太规范的ps流
if (finish && _tracks[TrackVideo]) {
if (finish && _have_video) {
_sink->addTrackCompleted();
InfoL << "Add track finished";
}
@@ -104,37 +106,43 @@ void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64
if (codec == CodecInvalid) {
return;
}
if (!_tracks[getTrackType(codec)]) {
onTrack(Factory::getTrackByCodecId(codec, 8000, 1, 16));
auto &ref = _tracks[stream];
if (!ref.first) {
onTrack(stream, Factory::getTrackByCodecId(codec, 8000, 1, 16));
}
// TODO 支持多track
auto frame = Factory::getFrameFromPtr(codec, (char *) data, bytes, dts, pts);
if (getTrackType(codec) == TrackVideo) {
_merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) {
onFrame(Factory::getFrameFromBuffer(codec, buffer, dts, pts));
});
} else {
onFrame(frame);
auto frame = Factory::getFrameFromPtr(codec, (char *)data, bytes, dts, pts);
if (getTrackType(codec) != TrackVideo) {
onFrame(stream, frame);
return;
}
ref.second.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) {
onFrame(stream, Factory::getFrameFromBuffer(codec, buffer, dts, pts));
});
}
#else
void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,size_t bytes) {}
void DecoderImp::onStream(int stream,int codecid,const void *extra,size_t bytes,int finish) {}
#endif
void DecoderImp::onTrack(const Track::Ptr &track) {
void DecoderImp::onTrack(int index, const Track::Ptr &track) {
if (!track) {
return;
}
if (!_tracks[track->getTrackType()]) {
_tracks[track->getTrackType()] = track;
_sink->addTrack(track);
InfoL << "got track: " << track->getCodecName();
track->setIndex(index);
auto &ref = _tracks[index];
if (ref.first) {
WarnL << "Already existed a same track: " << index << ", codec: " << track->getCodecName();
return;
}
ref.first = track;
_sink->addTrack(track);
InfoL << "Got track: " << track->getCodecName();
_have_video = track->getTrackType() == TrackVideo ? true : _have_video;
}
void DecoderImp::onFrame(const Frame::Ptr &frame) {
void DecoderImp::onFrame(int index, const Frame::Ptr &frame) {
if (frame) {
frame->setIndex(index);
_sink->inputFrame(frame);
}
}

View File

@@ -48,8 +48,8 @@ public:
void flush();
protected:
void onTrack(const Track::Ptr &track);
void onFrame(const Frame::Ptr &frame);
void onTrack(int index, const Track::Ptr &track);
void onFrame(int index, const Frame::Ptr &frame);
private:
DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink);
@@ -57,10 +57,15 @@ private:
void onStream(int stream, int codecid, const void *extra, size_t bytes, int finish);
private:
bool _have_video = false;
Decoder::Ptr _decoder;
MediaSinkInterface *_sink;
FrameMerger _merger{FrameMerger::none};
Track::Ptr _tracks[TrackMax];
class FrameMergerImp : public FrameMerger {
public:
FrameMergerImp() : FrameMerger(FrameMerger::none) {}
};
std::unordered_map<int, std::pair<Track::Ptr, FrameMergerImp> > _tracks;
};
}//namespace mediakit

View File

@@ -78,7 +78,7 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
if (!ref) {
if (_rtp_receiver.size() > 2) {
// 防止pt类型太多导致内存溢出
throw std::invalid_argument("rtp pt类型不得超过2种!");
WarnL << "Rtp payload type more than 2 types: " << _rtp_receiver.size();
}
switch (pt) {
case Rtsp::PT_PCMA:
@@ -87,6 +87,7 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
ref = std::make_shared<RtpReceiverImp>(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = Factory::getTrackByCodecId(pt == Rtsp::PT_PCMU ? CodecG711U : CodecG711A, 8000, 1, 16);
CHECK(track);
track->setIndex(pt);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
@@ -96,6 +97,7 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = Factory::getTrackByCodecId(CodecJPEG);
CHECK(track);
track->setIndex(pt);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
@@ -106,23 +108,28 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = Factory::getTrackByCodecId(CodecOpus);
CHECK(track);
track->setIndex(pt);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else if (pt == h265_pt) {
// H265负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = Factory::getTrackByCodecId(CodecH265);
CHECK(track);
track->setIndex(pt);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else if (pt == h264_pt) {
// H264负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = Factory::getTrackByCodecId(CodecH264);
CHECK(track);
track->setIndex(pt);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
} else {
if (pt != Rtsp::PT_MP2T && pt != ps_pt) {
WarnL << "rtp payload type未识别(" << (int)pt << "),已按ts或ps负载处理";
WarnL << "Unknown rtp payload type(" << (int)pt << "), decode it as mpeg-ps or mpeg-ts";
}
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
// ts或ps负载
@@ -142,7 +149,8 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
}
}
// 设置frame回调
_rtp_decoder[pt]->addDelegate([this](const Frame::Ptr &frame) {
_rtp_decoder[pt]->addDelegate([this, pt](const Frame::Ptr &frame) {
frame->setIndex(pt);
onRtpDecode(frame);
return true;
});

View File

@@ -22,7 +22,7 @@ namespace mediakit{
PSEncoderImp::PSEncoderImp(uint32_t ssrc, uint8_t payload_type) : MpegMuxer(true) {
GET_CONFIG(uint32_t,video_mtu,Rtp::kVideoMtuSize);
_rtp_encoder = std::make_shared<CommonRtpEncoder>();
_rtp_encoder->setRtpInfo(ssrc, video_mtu, 90000, payload_type, 0);
_rtp_encoder->setRtpInfo(ssrc, video_mtu, 90000, payload_type);
auto ring = std::make_shared<RtpRing::RingType>();
ring->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); }));
_rtp_encoder->setRtpRing(std::move(ring));

View File

@@ -72,7 +72,7 @@ RtpCodec::Ptr RawEncoderImp::createRtpEncoder(const Track::Ptr &track) {
sample_rate = std::static_pointer_cast<AudioTrack>(track)->getAudioSampleRate();
}
auto ret = Factory::getRtpEncoderByCodecId(track->getCodecId(), _payload_type);
ret->setRtpInfo(_ssrc, mtu, sample_rate, _payload_type, 2 * track->getTrackType());
ret->setRtpInfo(_ssrc, mtu, sample_rate, _payload_type);
return ret;
}

View File

@@ -254,8 +254,7 @@ void RtpProcess::emitOnPublish() {
return;
}
if (err.empty()) {
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info, 0.0f,
option);
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info, 0.0f, option);
if (strong_self->_only_audio) {
strong_self->_muxer->setOnlyAudio();
}