mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-04 01:37:33 +08:00
合并pr:#1025
This commit is contained in:
@@ -157,17 +157,15 @@ bool MediaSource::seekTo(uint32_t stamp) {
|
||||
return listener->seekTo(*this, stamp);
|
||||
}
|
||||
|
||||
bool MediaSource::pause()
|
||||
{
|
||||
bool MediaSource::pause(bool pause) {
|
||||
auto listener = _listener.lock();
|
||||
if (!listener) {
|
||||
return false;
|
||||
}
|
||||
return listener->pause(*this);
|
||||
return listener->pause(*this, pause);
|
||||
}
|
||||
|
||||
bool MediaSource::speed(float speed)
|
||||
{
|
||||
bool MediaSource::speed(float speed) {
|
||||
auto listener = _listener.lock();
|
||||
if (!listener) {
|
||||
return false;
|
||||
@@ -601,17 +599,15 @@ bool MediaSourceEventInterceptor::seekTo(MediaSource &sender, uint32_t stamp) {
|
||||
return listener->seekTo(sender, stamp);
|
||||
}
|
||||
|
||||
bool MediaSourceEventInterceptor::pause(MediaSource& sender)
|
||||
{
|
||||
bool MediaSourceEventInterceptor::pause(MediaSource &sender, bool pause) {
|
||||
auto listener = _listener.lock();
|
||||
if (!listener) {
|
||||
return false;
|
||||
}
|
||||
return listener->pause(sender);
|
||||
return listener->pause(sender, pause);
|
||||
}
|
||||
|
||||
bool MediaSourceEventInterceptor::speed(MediaSource& sender, float speed)
|
||||
{
|
||||
bool MediaSourceEventInterceptor::speed(MediaSource &sender, float speed) {
|
||||
auto listener = _listener.lock();
|
||||
if (!listener) {
|
||||
return false;
|
||||
|
||||
@@ -67,10 +67,10 @@ public:
|
||||
|
||||
// 通知拖动进度条
|
||||
virtual bool seekTo(MediaSource &sender, uint32_t stamp) { return false; }
|
||||
// 通知暂停
|
||||
virtual bool pause(MediaSource& sender) { return false; }
|
||||
// 通知暂停或恢复
|
||||
virtual bool pause(MediaSource &sender, bool pause) { return false; }
|
||||
// 通知倍数
|
||||
virtual bool speed(MediaSource& sender, float speed) { return false; }
|
||||
virtual bool speed(MediaSource &sender, float speed) { return false; }
|
||||
// 通知其停止产生流
|
||||
virtual bool close(MediaSource &sender, bool force) { return false; }
|
||||
// 获取观看总人数
|
||||
@@ -110,8 +110,8 @@ public:
|
||||
std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override;
|
||||
|
||||
bool seekTo(MediaSource &sender, uint32_t stamp) override;
|
||||
bool pause(MediaSource& sender) override;
|
||||
bool speed(MediaSource& sender, float speed) override;
|
||||
bool pause(MediaSource &sender, bool pause) override;
|
||||
bool speed(MediaSource &sender, float speed) override;
|
||||
bool close(MediaSource &sender, bool force) override;
|
||||
int totalReaderCount(MediaSource &sender) override;
|
||||
void onReaderChanged(MediaSource &sender, int size) override;
|
||||
@@ -256,8 +256,7 @@ public:
|
||||
// 拖动进度条
|
||||
bool seekTo(uint32_t stamp);
|
||||
//暂停
|
||||
bool pause();
|
||||
|
||||
bool pause(bool pause);
|
||||
//倍数播放
|
||||
bool speed(float speed);
|
||||
// 关闭该流
|
||||
|
||||
@@ -33,11 +33,11 @@ public:
|
||||
|
||||
protected:
|
||||
void onResponseBody(const char *buf, size_t size, size_t recvedSize, size_t totalSize) override;
|
||||
|
||||
private:
|
||||
ssize_t onResponseHeader(const string &status, const HttpHeader &headers) override;
|
||||
void onResponseCompleted() override;
|
||||
void onDisconnect(const SockException &ex) override;
|
||||
|
||||
private:
|
||||
void closeFile();
|
||||
|
||||
private:
|
||||
|
||||
@@ -130,7 +130,7 @@ void HttpSession::onManager() {
|
||||
|
||||
if(_ticker.elapsedTime() > keepAliveSec * 1000){
|
||||
//1分钟超时
|
||||
shutdown(SockException(Err_timeout,"session timeouted"));
|
||||
shutdown(SockException(Err_timeout,"session timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,7 @@ void MediaPlayer::pause(bool pause) {
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::speed(float speed)
|
||||
{
|
||||
void MediaPlayer::speed(float speed) {
|
||||
if (_delegate) {
|
||||
_delegate->speed(speed);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
virtual ~MediaPlayer();
|
||||
void play(const string &url) override;
|
||||
void pause(bool pause) override;
|
||||
void speed(float speed)override;
|
||||
void speed(float speed) override;
|
||||
void teardown() override;
|
||||
EventPoller::Ptr getPoller();
|
||||
void setOnCreateSocket(Socket::onCreateSocket cb);
|
||||
|
||||
@@ -102,7 +102,6 @@ public:
|
||||
|
||||
/**
|
||||
* 获取播放进度pos,取值 相对开始时间增量 单位秒
|
||||
* @return
|
||||
*/
|
||||
virtual uint32_t getProgressPos() const { return 0; }
|
||||
|
||||
@@ -152,15 +151,16 @@ public:
|
||||
typedef std::shared_ptr<PlayerImp> Ptr;
|
||||
|
||||
template<typename ...ArgsType>
|
||||
PlayerImp(ArgsType &&...args):Parent(std::forward<ArgsType>(args)...){}
|
||||
PlayerImp(ArgsType &&...args):Parent(std::forward<ArgsType>(args)...) {}
|
||||
virtual ~PlayerImp() {}
|
||||
|
||||
virtual ~PlayerImp(){}
|
||||
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
||||
if (_delegate) {
|
||||
_delegate->setOnShutdown(cb);
|
||||
}
|
||||
_shutdownCB = cb;
|
||||
}
|
||||
|
||||
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
||||
if (_delegate) {
|
||||
_delegate->setOnPlayResult(cb);
|
||||
@@ -175,31 +175,35 @@ public:
|
||||
_resumeCB = cb;
|
||||
}
|
||||
|
||||
bool isInited(int analysisMs) override{
|
||||
bool isInited(int analysisMs) override {
|
||||
if (_delegate) {
|
||||
return _delegate->isInited(analysisMs);
|
||||
}
|
||||
return Parent::isInited(analysisMs);
|
||||
}
|
||||
|
||||
float getDuration() const override {
|
||||
if (_delegate) {
|
||||
return _delegate->getDuration();
|
||||
}
|
||||
return Parent::getDuration();
|
||||
}
|
||||
float getProgress() const override{
|
||||
|
||||
float getProgress() const override {
|
||||
if (_delegate) {
|
||||
return _delegate->getProgress();
|
||||
}
|
||||
return Parent::getProgress();
|
||||
}
|
||||
|
||||
uint32_t getProgressPos() const override {
|
||||
if (_delegate) {
|
||||
return _delegate->getProgressPos();
|
||||
}
|
||||
return Parent::getProgressPos();
|
||||
}
|
||||
void seekTo(float fProgress) override{
|
||||
|
||||
void seekTo(float fProgress) override {
|
||||
if (_delegate) {
|
||||
return _delegate->seekTo(fProgress);
|
||||
}
|
||||
@@ -213,21 +217,21 @@ public:
|
||||
return Parent::seekTo(seekPos);
|
||||
}
|
||||
|
||||
void setMediaSource(const MediaSource::Ptr & src) override {
|
||||
void setMediaSource(const MediaSource::Ptr &src) override {
|
||||
if (_delegate) {
|
||||
_delegate->setMediaSource(src);
|
||||
}
|
||||
_pMediaSrc = src;
|
||||
}
|
||||
|
||||
vector<Track::Ptr> getTracks(bool trackReady = true) const override{
|
||||
vector<Track::Ptr> getTracks(bool trackReady = true) const override {
|
||||
if (_delegate) {
|
||||
return _delegate->getTracks(trackReady);
|
||||
}
|
||||
return Parent::getTracks(trackReady);
|
||||
}
|
||||
|
||||
std::shared_ptr<SockInfo> getSockInfo() const{
|
||||
std::shared_ptr<SockInfo> getSockInfo() const {
|
||||
return dynamic_pointer_cast<SockInfo>(_delegate);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ void MP4Recorder::createFile() {
|
||||
}
|
||||
_strFileTmp = strFileTmp;
|
||||
_strFile = strFile;
|
||||
_createFileTicker.resetTime();
|
||||
} catch (std::exception &ex) {
|
||||
WarnL << ex.what();
|
||||
}
|
||||
@@ -107,21 +106,21 @@ void MP4Recorder::closeFile() {
|
||||
}
|
||||
|
||||
void MP4Recorder::inputFrame(const Frame::Ptr &frame) {
|
||||
if (_baseSec == 0)
|
||||
_baseSec = frame->dts();
|
||||
auto dis = frame->dts() - _baseSec;
|
||||
if(!_muxer || ((dis > _max_second * 1000) &&
|
||||
(!_haveVideo || (_haveVideo && frame->keyFrame()))) ){
|
||||
if (_baseSec == 0) {
|
||||
_baseSec = frame->dts();
|
||||
}
|
||||
|
||||
auto duration = frame->dts() - _baseSec;
|
||||
if (!_muxer || ((duration > _max_second * 1000) && (!_haveVideo || (_haveVideo && frame->keyFrame())))) {
|
||||
//成立条件
|
||||
//1、_muxer为空
|
||||
//2、到了切片时间,并且只有音频
|
||||
//3、到了切片时间,有视频并且遇到视频的关键帧
|
||||
DebugL << "create file dts:" << frame->dts() << " baseSec:" << _baseSec;
|
||||
_baseSec = 0;
|
||||
createFile();
|
||||
}
|
||||
|
||||
if(_muxer){
|
||||
if (_muxer) {
|
||||
//生成mp4文件
|
||||
_muxer->inputFrame(frame);
|
||||
}
|
||||
@@ -139,7 +138,6 @@ void MP4Recorder::resetTracks() {
|
||||
closeFile();
|
||||
_tracks.clear();
|
||||
_haveVideo = false;
|
||||
_createFileTicker.resetTime();
|
||||
}
|
||||
|
||||
} /* namespace mediakit */
|
||||
|
||||
@@ -61,11 +61,9 @@ private:
|
||||
string _strPath;
|
||||
string _strFile;
|
||||
string _strFileTmp;
|
||||
Ticker _createFileTicker;
|
||||
RecordInfo _info;
|
||||
MP4Muxer::Ptr _muxer;
|
||||
list<Track::Ptr> _tracks;
|
||||
|
||||
uint64_t _baseSec = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -171,8 +171,7 @@ void RtmpPlayer::pause(bool bPause) {
|
||||
send_pause(bPause);
|
||||
}
|
||||
|
||||
void RtmpPlayer::speed(float speed)
|
||||
{
|
||||
void RtmpPlayer::speed(float speed) {
|
||||
//todo
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
void play(const string &strUrl) override;
|
||||
void pause(bool bPause) override;
|
||||
void speed(float speed)override;
|
||||
void speed(float speed) override;
|
||||
void teardown() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
}
|
||||
|
||||
void seekTo(uint32_t seekPos) override {
|
||||
uint32_t pos = MAX(float(0), MIN(seekPos, getDuration()))*1000;
|
||||
uint32_t pos = MAX(float(0), MIN(seekPos, getDuration())) * 1000;
|
||||
seekToMilliSecond(pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -413,23 +413,18 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
|
||||
sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN, STREAM_MEDIA);
|
||||
_paused = paused;
|
||||
|
||||
auto stongSrc = _player_src.lock();
|
||||
if (stongSrc) {
|
||||
if (_paused)
|
||||
stongSrc->pause();
|
||||
else
|
||||
stongSrc->seekTo(-1);
|
||||
auto strongSrc = _player_src.lock();
|
||||
if (strongSrc) {
|
||||
strongSrc->pause(paused);
|
||||
}
|
||||
}
|
||||
|
||||
void RtmpSession::onCmd_playCtrl(AMFDecoder& dec)
|
||||
{
|
||||
void RtmpSession::onCmd_playCtrl(AMFDecoder &dec) {
|
||||
dec.load<AMFValue>();
|
||||
auto ctrlObj = dec.load<AMFValue>();
|
||||
int ctrlType = ctrlObj["ctrlType"].as_integer();
|
||||
float speed = ctrlObj["speed"].as_number();
|
||||
|
||||
|
||||
AMFValue status(AMF_OBJECT);
|
||||
status.set("level", "status");
|
||||
status.set("code", "NetStream.Speed.Notify");
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
|
||||
void onCmd_seek(AMFDecoder &dec);
|
||||
void onCmd_pause(AMFDecoder &dec);
|
||||
void onCmd_playCtrl(AMFDecoder& dec);
|
||||
void onCmd_playCtrl(AMFDecoder &dec);
|
||||
void setMetaData(AMFDecoder &dec);
|
||||
|
||||
void onSendMedia(const RtmpPacket::Ptr &pkt);
|
||||
|
||||
@@ -419,9 +419,8 @@ void RtspPlayer::pause(bool bPause) {
|
||||
sendPause(bPause ? type_pause : type_seek, getProgressMilliSecond());
|
||||
}
|
||||
|
||||
void RtspPlayer::speed(float speed)
|
||||
{
|
||||
sendRtspRequest("PLAY", _content_base, { "Scale",StrPrinter << speed });
|
||||
void RtspPlayer::speed(float speed) {
|
||||
sendRtspRequest("PLAY", _content_base, {"Scale", StrPrinter << speed});
|
||||
}
|
||||
|
||||
void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
|
||||
|
||||
@@ -41,8 +41,8 @@ public:
|
||||
~RtspPlayer() override;
|
||||
|
||||
void play(const string &strUrl) override;
|
||||
void pause(bool bPause) override;
|
||||
void speed(float speed)override;
|
||||
void pause(bool pause) override;
|
||||
void speed(float speed) override;
|
||||
void teardown() override;
|
||||
float getPacketLossRate(TrackType type) const override;
|
||||
|
||||
|
||||
@@ -47,12 +47,11 @@ public:
|
||||
return getProgressMilliSecond();
|
||||
}
|
||||
return PlayerBase::getProgressPos();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void seekTo(float fProgress) override{
|
||||
fProgress = MAX(float(0),MIN(fProgress,float(1.0)));
|
||||
seekToMilliSecond((uint32_t)(fProgress * getDuration() * 1000));
|
||||
void seekTo(float fProgress) override {
|
||||
fProgress = MAX(float(0), MIN(fProgress, float(1.0)));
|
||||
seekToMilliSecond((uint32_t) (fProgress * getDuration() * 1000));
|
||||
}
|
||||
|
||||
void seekTo(uint32_t seekPos) override {
|
||||
|
||||
@@ -101,13 +101,13 @@ void RtspSession::onManager() {
|
||||
|
||||
if (_push_src && _alive_ticker.elapsedTime() > keep_alive_sec * 1000) {
|
||||
//推流超时
|
||||
shutdown(SockException(Err_timeout, "pusher session timeouted"));
|
||||
shutdown(SockException(Err_timeout, "pusher session timeout"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_push_src && _rtp_type == Rtsp::RTP_UDP && _enable_send_rtp && _alive_ticker.elapsedTime() > keep_alive_sec * 4000) {
|
||||
//rtp over udp播放器超时
|
||||
shutdown(SockException(Err_timeout, "rtp over udp player timeouted"));
|
||||
shutdown(SockException(Err_timeout, "rtp over udp player timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,36 +774,27 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
||||
}
|
||||
|
||||
bool useGOP = true;
|
||||
//_enable_send_rtp = false;
|
||||
float iStartTime = 0;
|
||||
auto strRange = parser["Range"];
|
||||
auto strScale = parser["Scale"];
|
||||
if (strScale.size() == 0)
|
||||
{
|
||||
auto &strRange = parser["Range"];
|
||||
auto &strScale = parser["Scale"];
|
||||
|
||||
if (strRange.size()) {
|
||||
//这个是seek操作
|
||||
auto strStart = FindField(strRange.data(), "npt=", "-");
|
||||
if (strStart == "now") {
|
||||
strStart = "0";
|
||||
}
|
||||
iStartTime = 1000 * (float)atof(strStart.data());
|
||||
InfoP(this) << "rtsp seekTo(ms):" << iStartTime;
|
||||
useGOP = !play_src->seekTo((uint32_t)iStartTime);
|
||||
}
|
||||
else if (play_src->totalReaderCount() == 0) {
|
||||
//第一个消费者
|
||||
play_src->seekTo(0);
|
||||
}
|
||||
else if (play_src->totalReaderCount() > 0)
|
||||
{
|
||||
_enable_send_rtp = true;
|
||||
play_src->seekTo(-1);
|
||||
}
|
||||
if (!strScale.empty()) {
|
||||
//这是设置播放速度
|
||||
auto speed = atof(strScale.data());
|
||||
play_src->speed(speed);
|
||||
InfoP(this) << "rtp set play speed:" << speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
play_src->speed(atof(strScale.data()));
|
||||
|
||||
if (!strRange.empty()) {
|
||||
//这是seek操作
|
||||
_enable_send_rtp = false;
|
||||
auto strStart = FindField(strRange.data(), "npt=", "-");
|
||||
if (strStart == "now") {
|
||||
strStart = "0";
|
||||
}
|
||||
iStartTime = 1000 * (float) atof(strStart.data());
|
||||
useGOP = !play_src->seekTo((uint32_t) iStartTime);
|
||||
InfoP(this) << "rtsp seekTo(ms):" << iStartTime;
|
||||
}
|
||||
|
||||
_StrPrinter rtp_info;
|
||||
@@ -828,7 +819,10 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
||||
"RTP-Info",rtp_info
|
||||
});
|
||||
|
||||
//在回复rtsp信令后再恢复播放
|
||||
_enable_send_rtp = true;
|
||||
play_src->pause(false);
|
||||
|
||||
setSocketFlags();
|
||||
|
||||
if (!_play_reader && _rtp_type != Rtsp::RTP_MULTICAST) {
|
||||
@@ -856,26 +850,21 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
||||
void RtspSession::handleReq_Pause(const Parser &parser) {
|
||||
if (parser["Session"] != _sessionid) {
|
||||
send_SessionNotFound();
|
||||
throw SockException(Err_shutdown,"session not found when pause");
|
||||
throw SockException(Err_shutdown, "session not found when pause");
|
||||
}
|
||||
|
||||
sendRtspResponse("200 OK");
|
||||
|
||||
_enable_send_rtp = false;
|
||||
|
||||
auto play_src = _play_src.lock();
|
||||
if (!play_src) {
|
||||
send_StreamNotFound();
|
||||
shutdown(SockException(Err_shutdown, "rtsp stream released"));
|
||||
return;
|
||||
if (play_src) {
|
||||
play_src->pause(true);
|
||||
}
|
||||
|
||||
play_src->pause();
|
||||
//_enable_send_rtp = false;
|
||||
}
|
||||
|
||||
void RtspSession::handleReq_Teardown(const Parser &parser) {
|
||||
sendRtspResponse("200 OK");
|
||||
throw SockException(Err_shutdown,"rtsp player send teardown request");
|
||||
throw SockException(Err_shutdown,"recv teardown request");
|
||||
}
|
||||
|
||||
void RtspSession::handleReq_Get(const Parser &parser) {
|
||||
|
||||
Reference in New Issue
Block a user