2022-06-11 12:56:03 +08:00
/*
2020-04-04 20:30:09 +08:00
* Copyright ( c ) 2016 The ZLMediaKit project authors . All Rights Reserved .
2018-02-02 18:19:35 +08:00
*
2021-01-17 18:31:50 +08:00
* This file is part of ZLMediaKit ( https : //github.com/xia-chu/ZLMediaKit).
2018-02-02 18:19:35 +08:00
*
2020-04-04 20:30:09 +08:00
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree . All contributing project authors
* may be found in the AUTHORS file in the root of the source tree .
2018-02-02 18:19:35 +08:00
*/
# ifndef ZLMEDIAKIT_MEDIASOURCE_H
# define ZLMEDIAKIT_MEDIASOURCE_H
# include <mutex>
# include <string>
2022-01-10 16:37:50 +08:00
# include <atomic>
2018-02-02 18:19:35 +08:00
# include <memory>
# include <functional>
# include <unordered_map>
# include "Common/config.h"
2019-06-28 16:48:02 +08:00
# include "Common/Parser.h"
2020-04-09 16:19:03 +08:00
# include "Util/List.h"
2020-09-27 11:32:49 +08:00
# include "Network/Socket.h"
2019-06-28 16:48:02 +08:00
# include "Extension/Track.h"
2020-04-05 09:26:29 +08:00
# include "Record/Recorder.h"
2018-02-02 18:19:35 +08:00
2022-10-31 17:53:20 +08:00
namespace toolkit {
class Session ;
} // namespace toolkit
2019-05-27 22:32:07 +08:00
2018-10-24 17:17:55 +08:00
namespace mediakit {
2018-02-02 18:19:35 +08:00
2020-09-27 11:32:49 +08:00
enum class MediaOriginType : uint8_t {
unknown = 0 ,
rtmp_push ,
rtsp_push ,
rtp_push ,
pull ,
ffmpeg_pull ,
mp4_vod ,
2021-04-07 18:17:49 +08:00
device_chn ,
rtc_push ,
2022-06-03 15:02:07 +08:00
srt_push
2020-09-27 11:32:49 +08:00
} ;
2022-02-02 20:34:50 +08:00
std : : string getOriginTypeString ( MediaOriginType type ) ;
2020-09-27 11:32:49 +08:00
2019-05-27 18:39:43 +08:00
class MediaSource ;
2022-04-03 18:25:36 +08:00
class MediaSourceEvent {
2018-02-02 18:19:35 +08:00
public :
2020-03-23 10:21:17 +08:00
friend class MediaSource ;
2022-08-28 17:25:56 +08:00
class NotImplemented : public std : : runtime_error {
public :
template < typename . . . T >
NotImplemented ( T & & . . . args ) : std : : runtime_error ( std : : forward < T > ( args ) . . . ) { }
~ NotImplemented ( ) override = default ;
} ;
2022-10-31 17:53:20 +08:00
MediaSourceEvent ( ) { } ;
virtual ~ MediaSourceEvent ( ) { } ;
2019-12-03 16:10:02 +08:00
2020-09-27 11:32:49 +08:00
// 获取媒体源类型
virtual MediaOriginType getOriginType ( MediaSource & sender ) const { return MediaOriginType : : unknown ; }
// 获取媒体源url或者文件路径
2022-02-02 20:34:50 +08:00
virtual std : : string getOriginUrl ( MediaSource & sender ) const ;
2020-09-27 11:32:49 +08:00
// 获取媒体源客户端相关信息
2022-02-02 20:34:50 +08:00
virtual std : : shared_ptr < toolkit : : SockInfo > getOriginSock ( MediaSource & sender ) const { return nullptr ; }
2020-09-27 11:32:49 +08:00
2019-12-03 16:10:02 +08:00
// 通知拖动进度条
2020-09-06 17:52:07 +08:00
virtual bool seekTo ( MediaSource & sender , uint32_t stamp ) { return false ; }
2021-08-12 16:07:31 +08:00
// 通知暂停或恢复
virtual bool pause ( MediaSource & sender , bool pause ) { return false ; }
2021-08-09 18:28:43 +08:00
// 通知倍数
2021-08-12 16:07:31 +08:00
virtual bool speed ( MediaSource & sender , float speed ) { return false ; }
2020-09-06 17:52:07 +08:00
// 通知其停止产生流
2022-09-18 20:36:47 +08:00
virtual bool close ( MediaSource & sender ) { return false ; }
2022-08-28 17:25:56 +08:00
// 获取观看总人数,此函数一般强制重载
virtual int totalReaderCount ( MediaSource & sender ) { throw NotImplemented ( toolkit : : demangle ( typeid ( * this ) . name ( ) ) + " ::totalReaderCount not implemented " ) ; }
2020-09-12 19:09:56 +08:00
// 通知观看人数变化
virtual void onReaderChanged ( MediaSource & sender , int size ) ;
2020-07-02 18:14:39 +08:00
//流注册或注销事件
2022-09-07 11:06:39 +08:00
virtual void onRegist ( MediaSource & sender , bool regist ) { }
2022-06-11 12:56:03 +08:00
// 获取丢包率
2022-09-03 15:53:01 +08:00
virtual float getLossRate ( MediaSource & sender , TrackType type ) { return - 1 ; }
2022-08-28 17:25:56 +08:00
// 获取所在线程, 此函数一般强制重载
virtual toolkit : : EventPoller : : Ptr getOwnerPoller ( MediaSource & sender ) { throw NotImplemented ( toolkit : : demangle ( typeid ( * this ) . name ( ) ) + " ::getOwnerPoller not implemented " ) ; }
2022-06-11 12:31:06 +08:00
2020-09-06 17:52:07 +08:00
////////////////////////仅供MultiMediaSourceMuxer对象继承////////////////////////
// 开启或关闭录制
2022-02-02 20:34:50 +08:00
virtual bool setupRecord ( MediaSource & sender , Recorder : : type type , bool start , const std : : string & custom_path , size_t max_second ) { return false ; } ;
2020-09-06 17:52:07 +08:00
// 获取录制状态
2022-09-07 11:06:39 +08:00
virtual bool isRecording ( MediaSource & sender , Recorder : : type type ) { return false ; }
2020-09-06 17:54:52 +08:00
// 获取所有track相关信息
2022-02-02 20:34:50 +08:00
virtual std : : vector < Track : : Ptr > getMediaTracks ( MediaSource & sender , bool trackReady = true ) const { return std : : vector < Track : : Ptr > ( ) ; } ;
2022-04-03 18:25:36 +08:00
class SendRtpArgs {
public :
// 是否采用udp方式发送rtp
bool is_udp = true ;
// rtp采用ps还是es方式
bool use_ps = true ;
//发送es流时指定是否只发送纯音频流
bool only_audio = true ;
2022-05-14 23:25:22 +08:00
//tcp被动方式
bool passive = false ;
2022-04-03 18:25:36 +08:00
// rtp payload type
uint8_t pt = 96 ;
// 指定rtp ssrc
std : : string ssrc ;
// 指定本地发送端口
uint16_t src_port = 0 ;
// 发送目标端口
uint16_t dst_port ;
// 发送目标主机地址, 可以是ip或域名
std : : string dst_url ;
2022-08-20 12:48:27 +08:00
//udp发送时, 是否开启rr rtcp接收超时判断
bool udp_rtcp_timeout = false ;
//tcp被动发送服务器延时关闭事件, 单位毫秒
uint32_t tcp_passive_close_delay_ms = 5 * 1000 ;
//udp 发送时, rr rtcp包接收超时时间, 单位毫秒
uint32_t rtcp_timeout_ms = 30 * 1000 ;
//udp 发送时, 发送sr rtcp包间隔, 单位毫秒
uint32_t rtcp_send_interval_ms = 5 * 1000 ;
2022-04-03 18:25:36 +08:00
} ;
2020-09-06 17:56:05 +08:00
// 开始发送ps-rtp
2022-04-03 18:25:36 +08:00
virtual void startSendRtp ( MediaSource & sender , const SendRtpArgs & args , const std : : function < void ( uint16_t , const toolkit : : SockException & ) > cb ) { cb ( 0 , toolkit : : SockException ( toolkit : : Err_other , " not implemented " ) ) ; } ;
2020-09-06 17:56:05 +08:00
// 停止发送ps-rtp
2022-02-02 20:34:50 +08:00
virtual bool stopSendRtp ( MediaSource & sender , const std : : string & ssrc ) { return false ; }
2020-09-06 17:52:07 +08:00
2020-03-23 10:21:17 +08:00
private :
2022-02-02 20:34:50 +08:00
toolkit : : Timer : : Ptr _async_close_timer ;
2018-02-02 18:19:35 +08:00
} ;
2019-05-27 18:39:43 +08:00
2020-09-06 17:52:07 +08:00
//该对象用于拦截感兴趣的MediaSourceEvent事件
2022-10-31 17:53:20 +08:00
class MediaSourceEventInterceptor : public MediaSourceEvent {
2020-09-06 17:52:07 +08:00
public :
2022-10-31 17:53:20 +08:00
MediaSourceEventInterceptor ( ) = default ;
~ MediaSourceEventInterceptor ( ) override = default ;
2020-09-06 17:52:07 +08:00
2020-10-24 23:31:58 +08:00
void setDelegate ( const std : : weak_ptr < MediaSourceEvent > & listener ) ;
std : : shared_ptr < MediaSourceEvent > getDelegate ( ) const ;
2020-09-27 11:32:49 +08:00
MediaOriginType getOriginType ( MediaSource & sender ) const override ;
2022-02-02 20:34:50 +08:00
std : : string getOriginUrl ( MediaSource & sender ) const override ;
std : : shared_ptr < toolkit : : SockInfo > getOriginSock ( MediaSource & sender ) const override ;
2020-09-27 11:32:49 +08:00
2020-09-06 17:52:07 +08:00
bool seekTo ( MediaSource & sender , uint32_t stamp ) override ;
2021-08-12 16:07:31 +08:00
bool pause ( MediaSource & sender , bool pause ) override ;
bool speed ( MediaSource & sender , float speed ) override ;
2022-09-18 20:36:47 +08:00
bool close ( MediaSource & sender ) override ;
2020-09-06 17:52:07 +08:00
int totalReaderCount ( MediaSource & sender ) override ;
2020-09-12 19:09:56 +08:00
void onReaderChanged ( MediaSource & sender , int size ) override ;
2020-09-06 17:54:52 +08:00
void onRegist ( MediaSource & sender , bool regist ) override ;
2022-02-02 20:34:50 +08:00
bool setupRecord ( MediaSource & sender , Recorder : : type type , bool start , const std : : string & custom_path , size_t max_second ) override ;
2020-09-06 17:52:07 +08:00
bool isRecording ( MediaSource & sender , Recorder : : type type ) override ;
2022-02-02 20:34:50 +08:00
std : : vector < Track : : Ptr > getMediaTracks ( MediaSource & sender , bool trackReady = true ) const override ;
2022-04-03 18:25:36 +08:00
void startSendRtp ( MediaSource & sender , const SendRtpArgs & args , const std : : function < void ( uint16_t , const toolkit : : SockException & ) > cb ) override ;
2022-02-02 20:34:50 +08:00
bool stopSendRtp ( MediaSource & sender , const std : : string & ssrc ) override ;
2022-09-03 15:53:01 +08:00
float getLossRate ( MediaSource & sender , TrackType type ) override ;
2022-06-11 12:56:03 +08:00
toolkit : : EventPoller : : Ptr getOwnerPoller ( MediaSource & sender ) override ;
2020-10-24 23:31:58 +08:00
private :
2020-09-06 17:52:07 +08:00
std : : weak_ptr < MediaSourceEvent > _listener ;
} ;
2019-12-29 10:49:04 +08:00
/**
* 解 析 url获取媒体相关信息
*/
2022-10-31 17:53:20 +08:00
class MediaInfo {
2018-02-02 18:19:35 +08:00
public :
2022-10-31 17:53:20 +08:00
~ MediaInfo ( ) = default ;
MediaInfo ( ) = default ;
2022-02-02 20:34:50 +08:00
MediaInfo ( const std : : string & url ) { parse ( url ) ; }
void parse ( const std : : string & url ) ;
2022-10-31 17:53:20 +08:00
std : : string shortUrl ( ) const { return _vhost + " / " + _app + " / " + _streamid ; }
std : : string getUrl ( ) const { return _schema + " :// " + shortUrl ( ) ; }
2018-02-02 18:19:35 +08:00
public :
2022-10-31 17:53:20 +08:00
uint16_t _port = 0 ;
2022-02-02 20:34:50 +08:00
std : : string _full_url ;
std : : string _schema ;
std : : string _host ;
std : : string _vhost ;
std : : string _app ;
std : : string _streamid ;
std : : string _param_strs ;
2018-02-02 18:19:35 +08:00
} ;
2019-12-03 16:10:02 +08:00
/**
* 媒 体 源 , 任 何 rtsp / rtmp的直播流都源自该对象
*/
2022-02-02 20:34:50 +08:00
class MediaSource : public TrackSource , public std : : enable_shared_from_this < MediaSource > {
2018-02-02 18:19:35 +08:00
public :
2022-08-23 14:11:32 +08:00
static MediaSource & NullMediaSource ( ) ;
2021-06-16 10:14:24 +08:00
using Ptr = std : : shared_ptr < MediaSource > ;
2018-02-02 18:19:35 +08:00
2022-10-31 17:53:20 +08:00
MediaSource ( const std : : string & schema , const std : : string & vhost , const std : : string & app , const std : : string & stream_id ) ;
2021-07-20 13:15:57 +08:00
virtual ~ MediaSource ( ) ;
2019-12-03 16:10:02 +08:00
2020-09-06 17:54:52 +08:00
////////////////获取MediaSource相关信息////////////////
2019-12-03 16:10:02 +08:00
// 获取协议类型
2022-02-02 20:34:50 +08:00
const std : : string & getSchema ( ) const ;
2019-12-03 16:10:02 +08:00
// 虚拟主机
2022-02-02 20:34:50 +08:00
const std : : string & getVhost ( ) const ;
2019-12-03 16:10:02 +08:00
// 应用名
2022-02-02 20:34:50 +08:00
const std : : string & getApp ( ) const ;
2019-12-03 16:10:02 +08:00
// 流id
2022-02-02 20:34:50 +08:00
const std : : string & getId ( ) const ;
2019-12-03 16:10:02 +08:00
2022-10-31 17:53:20 +08:00
std : : string shortUrl ( ) const { return _vhost + " / " + _app + " / " + _stream_id ; }
std : : string getUrl ( ) const { return _schema + " :// " + shortUrl ( ) ; }
2022-01-10 16:37:50 +08:00
//获取对象所有权
std : : shared_ptr < void > getOwnership ( ) ;
2019-12-29 10:49:04 +08:00
// 获取所有Track
2022-02-02 20:34:50 +08:00
std : : vector < Track : : Ptr > getTracks ( bool ready = true ) const override ;
2019-12-29 10:49:04 +08:00
2020-09-06 17:54:52 +08:00
// 获取流当前时间戳
virtual uint32_t getTimeStamp ( TrackType type ) { return 0 ; } ;
// 设置时间戳
virtual void setTimeStamp ( uint32_t stamp ) { } ;
2020-10-01 11:02:00 +08:00
// 获取数据速率, 单位bytes/s
2020-12-05 12:22:17 +08:00
int getBytesSpeed ( TrackType type = TrackInvalid ) ;
2020-10-01 18:57:15 +08:00
// 获取流创建GMT unix时间戳, 单位秒
2022-10-31 17:53:20 +08:00
uint64_t getCreateStamp ( ) const { return _create_stamp ; }
2020-10-01 18:57:15 +08:00
// 获取流上线时间,单位秒
uint64_t getAliveSecond ( ) const ;
2020-10-01 11:02:00 +08:00
2020-09-06 17:54:52 +08:00
////////////////MediaSourceEvent相关接口实现////////////////
2019-12-03 16:10:02 +08:00
// 设置监听者
2020-10-24 23:31:58 +08:00
virtual void setListener ( const std : : weak_ptr < MediaSourceEvent > & listener ) ;
2019-12-29 10:49:04 +08:00
// 获取监听者
2020-10-24 23:31:58 +08:00
std : : weak_ptr < MediaSourceEvent > getListener ( bool next = false ) const ;
2019-12-29 10:49:04 +08:00
2019-12-28 16:48:11 +08:00
// 本协议获取观看者个数,可能返回本协议的观看人数,也可能返回总人数
2019-12-03 16:10:02 +08:00
virtual int readerCount ( ) = 0 ;
2019-12-28 16:48:11 +08:00
// 观看者个数,包括(hls/rtsp/rtmp)
virtual int totalReaderCount ( ) ;
2022-08-30 21:05:19 +08:00
// 获取播放器列表
virtual void getPlayerList ( const std : : function < void ( const std : : list < std : : shared_ptr < void > > & info_list ) > & cb ,
const std : : function < std : : shared_ptr < void > ( std : : shared_ptr < void > & & info ) > & on_change ) {
assert ( cb ) ;
cb ( std : : list < std : : shared_ptr < void > > ( ) ) ;
}
2019-12-29 10:49:04 +08:00
2020-09-27 11:32:49 +08:00
// 获取媒体源类型
MediaOriginType getOriginType ( ) const ;
// 获取媒体源url或者文件路径
2022-02-02 20:34:50 +08:00
std : : string getOriginUrl ( ) const ;
2020-09-27 11:32:49 +08:00
// 获取媒体源客户端相关信息
2022-02-02 20:34:50 +08:00
std : : shared_ptr < toolkit : : SockInfo > getOriginSock ( ) const ;
2020-09-27 11:32:49 +08:00
2019-12-03 16:10:02 +08:00
// 拖动进度条
2020-09-06 17:52:07 +08:00
bool seekTo ( uint32_t stamp ) ;
2022-10-31 17:53:20 +08:00
// 暂停
2021-08-12 16:07:31 +08:00
bool pause ( bool pause ) ;
2022-10-31 17:53:20 +08:00
// 倍数播放
2021-08-09 18:28:43 +08:00
bool speed ( float speed ) ;
2019-12-03 16:10:02 +08:00
// 关闭该流
bool close ( bool force ) ;
2020-09-12 19:09:56 +08:00
// 该流观看人数变化
void onReaderChanged ( int size ) ;
2020-04-05 09:26:29 +08:00
// 开启或关闭录制
2022-02-02 20:34:50 +08:00
bool setupRecord ( Recorder : : type type , bool start , const std : : string & custom_path , size_t max_second ) ;
2020-04-05 09:26:29 +08:00
// 获取录制状态
2020-09-06 17:52:33 +08:00
bool isRecording ( Recorder : : type type ) ;
2020-09-06 17:56:05 +08:00
// 开始发送ps-rtp
2022-04-03 18:25:36 +08:00
void startSendRtp ( const MediaSourceEvent : : SendRtpArgs & args , const std : : function < void ( uint16_t , const toolkit : : SockException & ) > cb ) ;
2020-09-06 17:56:05 +08:00
// 停止发送ps-rtp
2022-02-02 20:34:50 +08:00
bool stopSendRtp ( const std : : string & ssrc ) ;
2022-06-11 12:56:03 +08:00
// 获取丢包率
2022-09-03 15:53:01 +08:00
float getLossRate ( mediakit : : TrackType type ) ;
2022-06-11 12:56:03 +08:00
// 获取所在线程
toolkit : : EventPoller : : Ptr getOwnerPoller ( ) ;
2019-11-18 12:07:11 +08:00
2020-09-06 17:54:52 +08:00
////////////////static方法, 查找或生成MediaSource////////////////
2019-12-03 16:10:02 +08:00
// 同步查找流
2022-02-02 20:34:50 +08:00
static Ptr find ( const std : : string & schema , const std : : string & vhost , const std : : string & app , const std : : string & id , bool from_mp4 = false ) ;
2022-09-07 11:06:39 +08:00
static Ptr find ( const MediaInfo & info , bool from_mp4 = false ) {
return find ( info . _schema , info . _vhost , info . _app , info . _streamid , from_mp4 ) ;
}
2020-09-06 18:19:54 +08:00
2022-09-07 11:06:39 +08:00
// 忽略schema, 同步查找流, 可能返回rtmp/rtsp/hls类型
2022-02-02 20:34:50 +08:00
static Ptr find ( const std : : string & vhost , const std : : string & app , const std : : string & stream_id , bool from_mp4 = false ) ;
2020-09-06 18:19:54 +08:00
2019-12-03 16:10:02 +08:00
// 异步查找流
2022-02-02 20:34:50 +08:00
static void findAsync ( const MediaInfo & info , const std : : shared_ptr < toolkit : : Session > & session , const std : : function < void ( const Ptr & src ) > & cb ) ;
2019-12-03 16:10:02 +08:00
// 遍历所有流
2022-02-02 20:34:50 +08:00
static void for_each_media ( const std : : function < void ( const Ptr & src ) > & cb , const std : : string & schema = " " , const std : : string & vhost = " " , const std : : string & app = " " , const std : : string & stream = " " ) ;
2020-04-03 23:27:16 +08:00
// 从mp4文件生成MediaSource
2022-02-02 20:34:50 +08:00
static MediaSource : : Ptr createFromMP4 ( const std : : string & schema , const std : : string & vhost , const std : : string & app , const std : : string & stream , const std : : string & file_path = " " , bool check_app = true ) ;
2020-05-26 10:11:58 +08:00
2018-08-31 14:13:00 +08:00
protected :
2020-09-06 17:52:07 +08:00
//媒体注册
void regist ( ) ;
2020-05-26 10:11:58 +08:00
private :
2022-10-31 17:53:20 +08:00
// 媒体注销
2020-09-06 17:52:07 +08:00
bool unregist ( ) ;
2022-10-31 17:53:20 +08:00
// 触发媒体事件
2020-09-06 17:52:07 +08:00
void emitEvent ( bool regist ) ;
2020-10-01 11:02:00 +08:00
protected :
2022-08-30 21:05:19 +08:00
toolkit : : BytesSpeed _speed [ TrackMax ] ;
2020-10-01 11:02:00 +08:00
2018-02-02 18:19:35 +08:00
private :
2022-02-02 20:34:50 +08:00
std : : atomic_flag _owned { false } ;
2020-10-01 18:57:15 +08:00
time_t _create_stamp ;
2022-02-02 20:34:50 +08:00
toolkit : : Ticker _ticker ;
std : : string _schema ;
std : : string _vhost ;
std : : string _app ;
std : : string _stream_id ;
2020-09-06 17:52:07 +08:00
std : : weak_ptr < MediaSourceEvent > _listener ;
2022-11-12 09:57:47 +08:00
toolkit : : EventPoller : : Ptr _default_poller ;
2022-10-31 17:53:20 +08:00
// 对象个数统计
2022-02-02 20:34:50 +08:00
toolkit : : ObjectStatistic < MediaSource > _statistic ;
2018-02-02 18:19:35 +08:00
} ;
2022-10-31 17:53:20 +08:00
/// 缓存刷新策略类
2020-04-09 16:19:03 +08:00
class FlushPolicy {
public :
2020-05-27 11:09:02 +08:00
FlushPolicy ( ) = default ;
2020-04-09 16:19:03 +08:00
~ FlushPolicy ( ) = default ;
2021-01-17 18:31:50 +08:00
bool isFlushAble ( bool is_video , bool is_key , uint64_t new_stamp , size_t cache_size ) ;
2020-05-27 11:09:02 +08:00
2020-04-09 16:19:03 +08:00
private :
2022-09-07 11:06:39 +08:00
// 音视频的最后时间戳
2022-10-31 17:53:20 +08:00
uint64_t _last_stamp [ 2 ] = { 0 , 0 } ;
2020-04-09 16:19:03 +08:00
} ;
2020-05-27 11:09:02 +08:00
/// 合并写缓存模板
2020-04-09 16:19:03 +08:00
/// \tparam packet 包类型
/// \tparam policy 刷新缓存策略
/// \tparam packet_list 包缓存类型
2022-02-02 20:34:50 +08:00
template < typename packet , typename policy = FlushPolicy , typename packet_list = toolkit : : List < std : : shared_ptr < packet > > >
2020-05-27 11:09:02 +08:00
class PacketCache {
2020-04-09 16:19:03 +08:00
public :
2022-10-31 17:53:20 +08:00
PacketCache ( ) { _cache = std : : make_shared < packet_list > ( ) ; }
2020-04-09 16:19:03 +08:00
2020-05-27 11:09:02 +08:00
virtual ~ PacketCache ( ) = default ;
2020-04-09 16:19:03 +08:00
2020-10-24 23:28:25 +08:00
void inputPacket ( uint64_t stamp , bool is_video , std : : shared_ptr < packet > pkt , bool key_pos ) {
2022-10-16 19:49:56 +08:00
bool flag = flushImmediatelyWhenCloseMerge ( ) ;
if ( ! flag & & _policy . isFlushAble ( is_video , key_pos , stamp , _cache - > size ( ) ) ) {
flush ( ) ;
2020-04-09 16:19:03 +08:00
}
//追加数据到最后
2020-10-10 18:23:25 +08:00
_cache - > emplace_back ( std : : move ( pkt ) ) ;
2020-04-09 16:19:03 +08:00
if ( key_pos ) {
_key_pos = key_pos ;
}
2021-08-30 18:05:21 +08:00
2022-10-16 19:49:56 +08:00
if ( flag ) {
flush ( ) ;
2021-08-30 18:05:21 +08:00
}
2020-04-09 16:19:03 +08:00
}
2022-10-16 19:49:56 +08:00
void flush ( ) {
2020-04-09 16:19:03 +08:00
if ( _cache - > empty ( ) ) {
return ;
}
2020-10-10 18:23:25 +08:00
onFlush ( std : : move ( _cache ) , _key_pos ) ;
2020-04-09 16:19:03 +08:00
_cache = std : : make_shared < packet_list > ( ) ;
_key_pos = false ;
}
2022-10-16 19:49:56 +08:00
virtual void clearCache ( ) {
_cache - > clear ( ) ;
}
virtual void onFlush ( std : : shared_ptr < packet_list > , bool key_pos ) = 0 ;
private :
2021-08-30 18:05:21 +08:00
bool flushImmediatelyWhenCloseMerge ( ) {
2022-10-31 17:53:20 +08:00
// 一般的协议关闭合并写时, 立即刷新缓存, 这样可以减少一帧的延时, 但是rtp例外
// 因为rtp的包很小, 一个RtpPacket包中也不是完整的一帧图像, 所以在关闭合并写时,
// 还是有必要缓冲一帧的rtp(也就是时间戳相同的rtp)再输出,这样虽然会增加一帧的延时
// 但是却对性能提升很大,这样做还是比较划算的
2022-01-11 14:09:57 +08:00
2021-08-30 18:05:21 +08:00
GET_CONFIG ( int , mergeWriteMS , General : : kMergeWriteMS ) ;
2022-10-19 14:20:53 +08:00
2022-10-19 14:55:39 +08:00
GET_CONFIG ( int , rtspLowLatency , Rtsp : : kLowLatency ) ;
2022-10-31 17:53:20 +08:00
if ( std : : is_same < packet , RtpPacket > : : value & & rtspLowLatency ) {
2022-10-19 14:20:53 +08:00
return true ;
}
2022-01-11 14:09:57 +08:00
return std : : is_same < packet , RtpPacket > : : value ? false : ( mergeWriteMS < = 0 ) ;
2021-08-30 18:05:21 +08:00
}
2020-04-09 16:19:03 +08:00
private :
2020-09-06 17:52:07 +08:00
bool _key_pos = false ;
2020-04-09 16:19:03 +08:00
policy _policy ;
std : : shared_ptr < packet_list > _cache ;
} ;
2018-10-24 17:17:55 +08:00
} /* namespace mediakit */
2022-07-28 16:43:03 +08:00
# endif //ZLMEDIAKIT_MEDIASOURCE_H