mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-03 17:21:48 +08:00
Support multi audio/video track
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user