ZLMediaKit/server/VideoStack.h

190 lines
4.0 KiB
C++
Raw Normal View History

2024-03-16 22:56:32 +08:00
#pragma once
#if defined(ENABLE_VIDEOSTACK) && defined(ENABLE_X264) && defined(ENABLE_FFMPEG)
2024-03-16 22:56:32 +08:00
#include "Codec/Transcode.h"
#include "Common/Device.h"
#include "Player/MediaPlayer.h"
#include "json/json.h"
#include <mutex>
2024-06-18 17:20:52 +08:00
template<typename T> class RefWrapper {
public:
using Ptr = std::shared_ptr<RefWrapper<T>>;
template<typename... Args>
explicit RefWrapper(Args&&... args) : _rc(0), _entity(std::forward<Args>(args)...) {}
T acquire() {
++_rc;
return _entity;
}
bool dispose() { return --_rc <= 0; }
private:
std::atomic<int> _rc;
T _entity;
2024-03-16 22:56:32 +08:00
};
class Channel;
struct Param {
2024-06-18 17:20:52 +08:00
using Ptr = std::shared_ptr<Param>;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
int posX = 0;
int posY = 0;
int width = 0;
int height = 0;
AVPixelFormat pixfmt = AV_PIX_FMT_YUV420P;
std::string id{};
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
// runtime
std::weak_ptr<Channel> weak_chn;
std::weak_ptr<mediakit::FFmpegFrame> weak_buf;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
~Param();
2024-03-16 22:56:32 +08:00
};
using Params = std::shared_ptr<std::vector<Param::Ptr>>;
class Channel : public std::enable_shared_from_this<Channel> {
2024-06-18 17:20:52 +08:00
public:
using Ptr = std::shared_ptr<Channel>;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
Channel(const std::string& id, int width, int height, AVPixelFormat pixfmt);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void addParam(const std::weak_ptr<Param>& p);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void onFrame(const mediakit::FFmpegFrame::Ptr& frame);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void fillBuffer(const Param::Ptr& p);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
protected:
void forEachParam(const std::function<void(const Param::Ptr&)>& func);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void copyData(const mediakit::FFmpegFrame::Ptr& buf, const Param::Ptr& p);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
private:
std::string _id;
int _width;
int _height;
AVPixelFormat _pixfmt;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
mediakit::FFmpegFrame::Ptr _tmp;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::recursive_mutex _mx;
std::vector<std::weak_ptr<Param>> _params;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
mediakit::FFmpegSws::Ptr _sws;
toolkit::EventPoller::Ptr _poller;
2024-03-16 22:56:32 +08:00
};
class StackPlayer : public std::enable_shared_from_this<StackPlayer> {
2024-06-18 17:20:52 +08:00
public:
using Ptr = std::shared_ptr<StackPlayer>;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
StackPlayer(const std::string& url) : _url(url) {}
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void addChannel(const std::weak_ptr<Channel>& chn);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void play();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void onFrame(const mediakit::FFmpegFrame::Ptr& frame);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void onDisconnect();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
protected:
void rePlay(const std::string& url);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
private:
std::string _url;
mediakit::MediaPlayer::Ptr _player;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
//用于断线重连
toolkit::Timer::Ptr _timer;
int _failedCount = 0;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::recursive_mutex _mx;
std::vector<std::weak_ptr<Channel>> _channels;
2024-03-16 22:56:32 +08:00
};
class VideoStack {
2024-06-18 17:20:52 +08:00
public:
using Ptr = std::shared_ptr<VideoStack>;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
VideoStack(const std::string& url, int width = 1920, int height = 1080,
AVPixelFormat pixfmt = AV_PIX_FMT_YUV420P, float fps = 25.0,
int bitRate = 2 * 1024 * 1024);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
~VideoStack();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void setParam(const Params& params);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void start();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
protected:
void initBgColor();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
public:
Params _params;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
mediakit::FFmpegFrame::Ptr _buffer;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
private:
std::string _id;
int _width;
int _height;
AVPixelFormat _pixfmt;
float _fps;
int _bitRate;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
mediakit::DevChannel::Ptr _dev;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
bool _isExit;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::thread _thread;
2024-03-16 22:56:32 +08:00
};
class VideoStackManager {
2024-06-18 17:20:52 +08:00
public:
//创建拼接流
int startVideoStack(const Json::Value& json);
//停止拼接流
int stopVideoStack(const std::string& id);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
//可以在不断流的情况下,修改拼接流的配置(实现切换拼接屏内容)
int resetVideoStack(const Json::Value& json);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
public:
static VideoStackManager& Instance();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
Channel::Ptr getChannel(const std::string& id, int width, int height, AVPixelFormat pixfmt);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void unrefChannel(const std::string& id, int width, int height, AVPixelFormat pixfmt);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
bool loadBgImg(const std::string& path);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
void clear();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
mediakit::FFmpegFrame::Ptr getBgImg();
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
protected:
Params parseParams(const Json::Value& json, std::string& id, int& width, int& height);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
protected:
Channel::Ptr createChannel(const std::string& id, int width, int height, AVPixelFormat pixfmt);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
StackPlayer::Ptr createPlayer(const std::string& id);
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
private:
mediakit::FFmpegFrame::Ptr _bgImg;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
private:
std::recursive_mutex _mx;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::unordered_map<std::string, VideoStack::Ptr> _stackMap;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::unordered_map<std::string, RefWrapper<Channel::Ptr>::Ptr> _channelMap;
2024-03-16 22:56:32 +08:00
2024-06-18 17:20:52 +08:00
std::unordered_map<std::string, RefWrapper<StackPlayer::Ptr>::Ptr> _playerMap;
2024-03-16 22:56:32 +08:00
};
#endif