Skip to content

Commit

Permalink
Track支持转码
Browse files Browse the repository at this point in the history
  • Loading branch information
cqm committed Dec 29, 2023
1 parent dde42bf commit 8645c5e
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 13 deletions.
4 changes: 2 additions & 2 deletions api/source/mk_track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ using namespace std;
using namespace toolkit;
using namespace mediakit;

class VideoTrackForC : public VideoTrack, public std::enable_shared_from_this<VideoTrackForC> {
class VideoTrackForC : public VideoTrack {
public:
VideoTrackForC(int codec_id, codec_args *args) {
_codec_id = (CodecId) codec_id;
Expand Down Expand Up @@ -61,7 +61,7 @@ class VideoTrackForC : public VideoTrack, public std::enable_shared_from_this<Vi
codec_args _args;
};

class AudioTrackForC : public AudioTrackImp, public std::enable_shared_from_this<AudioTrackForC> {
class AudioTrackForC : public AudioTrackImp {
public:
AudioTrackForC(int codec_id, codec_args *args) :
AudioTrackImp((CodecId) codec_id, args->audio.sample_rate, args->audio.channels, 16) {}
Expand Down
9 changes: 6 additions & 3 deletions src/Extension/Frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ class FrameDispatcher : public FrameWriterInterface {
*/
FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
std::lock_guard<std::recursive_mutex> 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<bool(const Frame::Ptr &frame)> cb);
Expand All @@ -554,9 +556,10 @@ class FrameDispatcher : public FrameWriterInterface {
*/
void delDelegate(FrameWriterInterface *ptr) {
std::lock_guard<std::recursive_mutex> lck(_mtx);
_delegates.erase(ptr);
if (_delegates.erase(ptr))
onSizeChange(_delegates.size());
}

virtual void onSizeChange(int size) {}
/**
* 写入帧并派发
*/
Expand Down
88 changes: 88 additions & 0 deletions src/Extension/Track.cpp
Original file line number Diff line number Diff line change
@@ -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<FFmpegDecoder>(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<FFmpegFrame> &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<FFmpegEncoder>(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<FFmpegEncoder>(cfg);
_encoder->setOnEncode([this](const Frame::Ptr &frame) { inputFrame(frame); });
_trans_tracks[key] = ret;
}
}
return ret;
}
#endif

} // namespace mediakit
49 changes: 41 additions & 8 deletions src/Extension/Track.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Track> {
public:
using Ptr = std::shared_ptr<Track>;

Expand Down Expand Up @@ -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生成
*/
Expand All @@ -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<FFmpegFrame>& frame);
Ptr getTransodeTrack(CodecId code, int arg1, int arg2);
protected:
virtual void onSizeChange(int size);
void upateTransSize();
protected:
// _trans_tracks 的 size 之和
std::atomic<int> _trans_size = { 0 };
// 转码Map getInfo -> Ptr
std::map<std::string, Ptr> _trans_tracks;
// 指向转码的父Track
Track* _parent = nullptr;
// 父Track负责解码
std::shared_ptr<FFmpegDecoder> _decoder;
// 每个子Tracker负责编码
std::shared_ptr<FFmpegEncoder> _encoder;
#endif
private:
int _bit_rate = 0;
};
Expand All @@ -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 {
Expand Down Expand Up @@ -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<AudioTrackImp>;

Expand Down

0 comments on commit 8645c5e

Please sign in to comment.