Skip to content

Commit

Permalink
Track支持转码
Browse files Browse the repository at this point in the history
  • Loading branch information
cqm committed Jan 4, 2024
1 parent 51efa13 commit 19ee45f
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 11 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
91 changes: 91 additions & 0 deletions src/Extension/Track.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "Track.h"
#include "Codec/Transcode.h"
#include "Extension/Factory.h"
#include "Poller/EventPoller.h"
#include "Util/logger.h"

namespace mediakit {

#ifdef ENABLE_FFMPEG

void Track::setRawFrameCB(RawFrameCB cb) {
std::unique_lock<decltype(_trans_mutex)> l(_trans_mutex);
_raw_cb = cb;
}

int Track::trans_size() {
std::unique_lock<decltype(_trans_mutex)> l(_trans_mutex);
return _trans_tracks.size();
}

bool Track::needDecode() {
std::unique_lock<decltype(_trans_mutex)> l(_trans_mutex);
return _raw_cb != nullptr || _trans_tracks.size() > 0;
}

bool Track::inputFrame(const Frame::Ptr &frame) {
bool ret = FrameDispatcher::inputFrame(frame);
// 有人读取Raw数据,则解码
if (needDecode()) {
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;
}

void Track::inputRawFrame(const std::shared_ptr<FFmpegFrame> &frame) {
std::list<Ptr> tracks;
{
std::unique_lock<decltype(_trans_mutex)> l(_trans_mutex);
for (auto it : _trans_tracks) {
tracks.push_back(it.second);
}
if (_raw_cb)
_raw_cb(frame);
}
for (auto it : tracks) {
auto track = it;
if (track->_encoder && (track->size() || !track->ready())) {
track->_encoder->inputFrame(frame, true);
}
}
}

Track::Ptr Track::getTransodeTrack(CodecId id, int arg1, int arg2) {
if (_parent)
return _parent->getTransodeTrack(id, arg1, 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();
}
std::unique_lock<decltype(_trans_mutex)> l(_trans_mutex);
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
52 changes: 43 additions & 9 deletions src/Extension/Track.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
#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 +63,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 +85,27 @@ class Track : public FrameDispatcher, public CodecInfo {
* @param bit_rate 比特率
*/
virtual void setBitRate(int bit_rate) { _bit_rate = bit_rate; }

#ifdef ENABLE_FFMPEG
using RawFrameCB = std::function<void(const std::shared_ptr<FFmpegFrame> &frame)>;
RawFrameCB _raw_cb;
void setRawFrameCB(RawFrameCB cb);
bool inputFrame(const Frame::Ptr &frame) override;
void inputRawFrame(const std::shared_ptr<FFmpegFrame>& frame);
Ptr getTransodeTrack(CodecId code, int arg1, int arg2);
int trans_size();
bool needDecode();

protected:
std::recursive_mutex _trans_mutex;
// 转码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 +131,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 +183,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 19ee45f

Please sign in to comment.