From 8645c5e938b65276b00d0c8a9385ab2aca8305cc Mon Sep 17 00:00:00 2001 From: cqm Date: Fri, 22 Dec 2023 14:31:21 +0800 Subject: [PATCH] =?UTF-8?q?Track=E6=94=AF=E6=8C=81=E8=BD=AC=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/source/mk_track.cpp | 4 +- src/Extension/Frame.h | 9 +++-- src/Extension/Track.cpp | 88 +++++++++++++++++++++++++++++++++++++++++ src/Extension/Track.h | 49 +++++++++++++++++++---- 4 files changed, 137 insertions(+), 13 deletions(-) create mode 100644 src/Extension/Track.cpp diff --git a/api/source/mk_track.cpp b/api/source/mk_track.cpp index c409ef22e1..296c72bea3 100644 --- a/api/source/mk_track.cpp +++ b/api/source/mk_track.cpp @@ -16,7 +16,7 @@ using namespace std; using namespace toolkit; using namespace mediakit; -class VideoTrackForC : public VideoTrack, public std::enable_shared_from_this { +class VideoTrackForC : public VideoTrack { public: VideoTrackForC(int codec_id, codec_args *args) { _codec_id = (CodecId) codec_id; @@ -61,7 +61,7 @@ class VideoTrackForC : public VideoTrack, public std::enable_shared_from_this { +class AudioTrackForC : public AudioTrackImp { public: AudioTrackForC(int codec_id, codec_args *args) : AudioTrackImp((CodecId) codec_id, args->audio.sample_rate, args->audio.channels, 16) {} diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index da55e8fee3..e9b0ff2d17 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -544,7 +544,9 @@ class FrameDispatcher : public FrameWriterInterface { */ FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) { std::lock_guard lck(_mtx); - return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get(); + auto ret = _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get(); + onSizeChange(_delegates.size()); + return ret; } FrameWriterInterface* addDelegate(std::function cb); @@ -554,9 +556,10 @@ class FrameDispatcher : public FrameWriterInterface { */ void delDelegate(FrameWriterInterface *ptr) { std::lock_guard lck(_mtx); - _delegates.erase(ptr); + if (_delegates.erase(ptr)) + onSizeChange(_delegates.size()); } - + virtual void onSizeChange(int size) {} /** * 写入帧并派发 */ diff --git a/src/Extension/Track.cpp b/src/Extension/Track.cpp new file mode 100644 index 0000000000..48cd52cea8 --- /dev/null +++ b/src/Extension/Track.cpp @@ -0,0 +1,88 @@ +#include "Track.h" +#include "Codec/Transcode.h" +#include "Extension/Factory.h" +#include "Poller/EventPoller.h" +#include "Util/logger.h" + +namespace mediakit { + +#ifdef ENABLE_FFMPEG + +bool Track::inputFrame(const Frame::Ptr &frame) { + bool ret = FrameDispatcher::inputFrame(frame); + // ˶ȡRawݣ + if (_trans_size) { + if (!_decoder) { + _decoder = std::make_shared(shared_from_this()); + InfoL << " open decoder " << getInfo(); + _decoder->setOnDecode([this](const FFmpegFrame::Ptr &frame) { inputRawFrame(frame); }); + } + _decoder->inputFrame(frame, true, true); + } else if (_decoder) { + InfoL << " close decoder " << getInfo(); + _decoder = nullptr; + } + return ret; +} + +bool Track::inputRawFrame(const std::shared_ptr &frame) { + bool ret = false; + for (auto it : _trans_tracks) { + auto track = it.second; + if (track->_encoder && (track->size() || !track->ready())) { + ret |= track->_encoder->inputFrame(frame, true); + } + } + return ret; +} + +void Track::onSizeChange(int size) { + if (_parent) { + _parent->upateTransSize(); + } + return; + if (size == 0) { + _encoder = nullptr; + } else if (_parent) { + // transcode from + _encoder = std::make_shared(shared_from_this()); + _encoder->setOnEncode([this](const Frame::Ptr &frame) { inputFrame(frame); }); + } +} + +void Track::upateTransSize() { + int ret = 0; + for (auto it : _trans_tracks) { + ret += it.second->size(); + } + _trans_size = ret; +} + +Track::Ptr Track::getTransodeTrack(CodecId id, int arg1, int arg2) { + char key[256]; + int arg3 = (mediakit::getTrackType(id) == TrackVideo) ? 30 : 16; + snprintf(key, sizeof(key), "%s[%dx%dx%d]", mediakit::getCodecName(id), arg1, arg2, arg3); + if (key == getInfo()) { + return shared_from_this(); + } + Ptr ret = _trans_tracks[key]; + if (!ret) { + ret = Factory::getTrackByCodecId(id, arg1, arg2, arg3); + if (ret) { + ret->_parent = this; + // Factory::getTrackByCodecIdĿ߲δسʼϣ Encode + Track::Ptr cfg; + if (mediakit::getTrackType(id) == TrackVideo) + cfg.reset(new VideoTrackImp(id, arg1, arg2, arg3)); + else + cfg.reset(new AudioTrackImp(id, arg1, arg2, arg3)); + ret->_encoder = std::make_shared(cfg); + _encoder->setOnEncode([this](const Frame::Ptr &frame) { inputFrame(frame); }); + _trans_tracks[key] = ret; + } + } + return ret; +} +#endif + +} // namespace mediakit diff --git a/src/Extension/Track.h b/src/Extension/Track.h index 8264b3a83b..ad77942e69 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -17,11 +17,14 @@ #include "Rtsp/Rtsp.h" namespace mediakit{ - +class FFmpegDecoder; +class FFmpegEncoder; +class FFmpegFrame; /** * 媒体通道描述类,也支持帧输入输出 */ -class Track : public FrameDispatcher, public CodecInfo { +class Track : public FrameDispatcher, public CodecInfo + , public std::enable_shared_from_this { public: using Ptr = std::shared_ptr; @@ -61,7 +64,7 @@ class Track : public FrameDispatcher, public CodecInfo { * @return sdp对象 */ virtual Sdp::Ptr getSdp(uint8_t payload_type) const = 0; - + virtual std::string getInfo() const = 0; /** * 获取extra data, 一般用于rtmp/mp4生成 */ @@ -83,7 +86,25 @@ class Track : public FrameDispatcher, public CodecInfo { * @param bit_rate 比特率 */ virtual void setBitRate(int bit_rate) { _bit_rate = bit_rate; } - +#ifdef ENABLE_FFMPEG + bool inputFrame(const Frame::Ptr &frame) override; + bool inputRawFrame(const std::shared_ptr& frame); + Ptr getTransodeTrack(CodecId code, int arg1, int arg2); +protected: + virtual void onSizeChange(int size); + void upateTransSize(); +protected: + // _trans_tracks 的 size 之和 + std::atomic _trans_size = { 0 }; + // 转码Map getInfo -> Ptr + std::map _trans_tracks; + // 指向转码的父Track + Track* _parent = nullptr; + // 父Track负责解码 + std::shared_ptr _decoder; + // 每个子Tracker负责编码 + std::shared_ptr _encoder; +#endif private: int _bit_rate = 0; }; @@ -109,6 +130,12 @@ class VideoTrack : public Track { * 返回视频fps */ virtual float getVideoFps() const { return 0; } + + std::string getInfo() const override { + char buff[256]; + snprintf(buff, sizeof(buff), "%s[%dx%d@%f]", getCodecName(), getVideoWidth(), getVideoHeight(), getVideoFps()); + return buff; + } }; class VideoTrackImp : public VideoTrack { @@ -155,20 +182,26 @@ class AudioTrack : public Track { /** * 返回音频采样率 */ - virtual int getAudioSampleRate() const {return 0;}; + virtual int getAudioSampleRate() const {return 0;} /** * 返回音频采样位数,一般为16或8 */ - virtual int getAudioSampleBit() const {return 0;}; + virtual int getAudioSampleBit() const {return 0;} /** * 返回音频通道数 */ - virtual int getAudioChannel() const {return 0;}; + virtual int getAudioChannel() const {return 0;} + + std::string getInfo() const override { + char buff[256]; + snprintf(buff, sizeof(buff), "%s[%dx%d@%d]", getCodecName(), getAudioSampleRate(), getAudioChannel(), getAudioSampleBit()); + return buff; + } }; -class AudioTrackImp : public AudioTrack{ +class AudioTrackImp : public AudioTrack { public: using Ptr = std::shared_ptr;