2022-06-11 12:56:03 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
2018-02-02 18:19:35 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
2018-02-02 18:19:35 +08:00
*
2023-12-09 16:23:51 +08:00
* Use of this source code is governed by MIT - like license that can be found in the
2020-04-04 20:30:09 +08:00
* 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
*/
2022-11-29 11:07:13 +08:00
# include <mutex>
2018-02-02 18:19:35 +08:00
# include "Util/util.h"
2022-11-12 23:54:35 +08:00
# include "Util/NoticeCenter.h"
2018-03-05 10:41:15 +08:00
# include "Network/sockutil.h"
2022-11-19 09:33:10 +08:00
# include "Network/Session.h"
2022-11-12 23:54:35 +08:00
# include "MediaSource.h"
# include "Common/config.h"
2022-11-29 11:07:13 +08:00
# include "Common/Parser.h"
2023-08-08 16:01:01 +08:00
# include "Common/MultiMediaSourceMuxer.h"
2022-11-12 23:54:35 +08:00
# include "Record/MP4Reader.h"
2022-11-29 11:07:13 +08:00
# include "PacketCache.h"
2023-08-08 16:01:01 +08:00
2022-02-02 20:34:50 +08:00
using namespace std ;
2018-10-24 17:17:55 +08:00
using namespace toolkit ;
2021-01-23 09:44:37 +08:00
namespace toolkit {
StatisticImp ( mediakit : : MediaSource ) ;
}
2018-10-24 17:17:55 +08:00
namespace mediakit {
2018-02-02 18:19:35 +08:00
2021-09-28 22:42:13 +08:00
static recursive_mutex s_media_source_mtx ;
2022-09-07 11:06:39 +08:00
using StreamMap = unordered_map < string /*strema_id*/ , weak_ptr < MediaSource > > ;
using AppStreamMap = unordered_map < string /*app*/ , StreamMap > ;
using VhostAppStreamMap = unordered_map < string /*vhost*/ , AppStreamMap > ;
using SchemaVhostAppStreamMap = unordered_map < string /*schema*/ , VhostAppStreamMap > ;
static SchemaVhostAppStreamMap s_media_source_map ;
2018-02-02 18:19:35 +08:00
2020-09-27 11:32:49 +08:00
string getOriginTypeString ( MediaOriginType type ) {
2020-10-24 23:31:22 +08:00
# define SWITCH_CASE(type) case MediaOriginType::type : return #type
2020-09-27 11:32:49 +08:00
switch ( type ) {
2020-10-24 23:31:22 +08:00
SWITCH_CASE ( unknown ) ;
SWITCH_CASE ( rtmp_push ) ;
SWITCH_CASE ( rtsp_push ) ;
SWITCH_CASE ( rtp_push ) ;
SWITCH_CASE ( pull ) ;
SWITCH_CASE ( ffmpeg_pull ) ;
SWITCH_CASE ( mp4_vod ) ;
SWITCH_CASE ( device_chn ) ;
2021-04-07 18:17:49 +08:00
SWITCH_CASE ( rtc_push ) ;
2022-06-03 20:38:35 +08:00
SWITCH_CASE ( srt_push ) ;
2020-11-29 09:34:02 +08:00
default : return " unknown " ;
2020-09-27 11:32:49 +08:00
}
}
2021-08-16 17:31:13 +08:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-11-12 23:54:35 +08:00
ProtocolOption : : ProtocolOption ( ) {
2024-06-28 19:35:03 +08:00
mINI ini ;
auto & config = mINI : : Instance ( ) ;
static auto sz = strlen ( Protocol : : kFieldName ) ;
for ( auto it = config . lower_bound ( Protocol : : kFieldName ) ; it ! = config . end ( ) & & start_with ( it - > first , Protocol : : kFieldName ) ; + + it ) {
ini . emplace ( it - > first . substr ( sz ) , it - > second ) ;
}
load ( ini ) ;
2022-11-12 23:54:35 +08:00
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-08-20 13:16:25 +08:00
struct MediaSourceNull : public MediaSource {
2024-03-30 14:59:28 +08:00
MediaSourceNull ( ) : MediaSource ( " schema " , MediaTuple { " vhost " , " app " , " stream " , " " } ) { } ;
2022-08-20 13:16:25 +08:00
int readerCount ( ) override { return 0 ; }
} ;
2021-08-16 17:31:13 +08:00
2022-08-23 14:11:32 +08:00
MediaSource & MediaSource : : NullMediaSource ( ) {
static std : : shared_ptr < MediaSource > s_null = std : : make_shared < MediaSourceNull > ( ) ;
return * s_null ;
}
2021-08-16 17:31:13 +08:00
2023-05-25 16:23:24 +08:00
MediaSource : : MediaSource ( const string & schema , const MediaTuple & tuple ) : _tuple ( tuple ) {
2020-09-06 17:52:07 +08:00
GET_CONFIG ( bool , enableVhost , General : : kEnableVhost ) ;
2023-05-25 16:23:24 +08:00
if ( ! enableVhost | | _tuple . vhost . empty ( ) ) {
_tuple . vhost = DEFAULT_VHOST ;
2019-12-03 16:10:02 +08:00
}
2020-09-06 17:52:07 +08:00
_schema = schema ;
2020-10-01 18:57:15 +08:00
_create_stamp = time ( NULL ) ;
2019-12-03 16:10:02 +08:00
}
MediaSource : : ~ MediaSource ( ) {
2023-06-11 22:07:15 +08:00
try {
unregist ( ) ;
} catch ( std : : exception & ex ) {
WarnL < < " Exception occurred: " < < ex . what ( ) ;
}
2019-12-03 16:10:02 +08:00
}
2022-01-10 16:37:50 +08:00
std : : shared_ptr < void > MediaSource : : getOwnership ( ) {
if ( _owned . test_and_set ( ) ) {
2024-09-19 14:53:50 +08:00
// 已经被所有 [AUTO-TRANSLATED:bab937dc]
// Already owned by all
2022-01-10 16:37:50 +08:00
return nullptr ;
}
weak_ptr < MediaSource > weak_self = shared_from_this ( ) ;
2024-09-19 14:53:50 +08:00
// 确保返回的Ownership智能指针不为空, 0x01无实际意义 [AUTO-TRANSLATED:9a4cca08]
// Ensure that the returned Ownership smart pointer is not empty, 0x01 has no practical meaning
2022-01-26 00:36:57 +08:00
return std : : shared_ptr < void > ( ( void * ) 0x01 , [ weak_self ] ( void * ptr ) {
2022-01-10 16:37:50 +08:00
auto strong_self = weak_self . lock ( ) ;
if ( strong_self ) {
strong_self - > _owned . clear ( ) ;
}
} ) ;
}
2020-12-05 12:22:17 +08:00
int MediaSource : : getBytesSpeed ( TrackType type ) {
2022-09-07 11:06:39 +08:00
if ( type = = TrackInvalid | | type = = TrackMax ) {
2020-12-05 12:22:17 +08:00
return _speed [ TrackVideo ] . getSpeed ( ) + _speed [ TrackAudio ] . getSpeed ( ) ;
}
return _speed [ type ] . getSpeed ( ) ;
2020-10-01 11:02:00 +08:00
}
2020-10-01 18:57:15 +08:00
uint64_t MediaSource : : getAliveSecond ( ) const {
2024-09-19 14:53:50 +08:00
// 使用Ticker对象获取存活时间的目的是防止修改系统时间导致回退 [AUTO-TRANSLATED:68474061]
// The purpose of using the Ticker object to obtain the survival time is to prevent the modification of the system time from causing a rollback
2020-10-01 18:57:15 +08:00
return _ticker . createdTime ( ) / 1000 ;
}
2020-09-06 17:52:07 +08:00
vector < Track : : Ptr > MediaSource : : getTracks ( bool ready ) const {
2020-09-06 17:54:52 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return vector < Track : : Ptr > ( ) ;
2019-12-03 16:10:02 +08:00
}
2021-07-20 13:15:57 +08:00
return listener - > getMediaTracks ( const_cast < MediaSource & > ( * this ) , ready ) ;
2019-12-03 16:10:02 +08:00
}
void MediaSource : : setListener ( const std : : weak_ptr < MediaSourceEvent > & listener ) {
_listener = listener ;
}
2023-07-08 21:35:09 +08:00
std : : weak_ptr < MediaSourceEvent > MediaSource : : getListener ( ) const {
return _listener ;
2019-12-03 16:10:02 +08:00
}
2019-12-28 16:48:11 +08:00
int MediaSource : : totalReaderCount ( ) {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return readerCount ( ) ;
}
return listener - > totalReaderCount ( * this ) ;
}
2020-09-06 17:52:07 +08:00
2020-09-27 11:32:49 +08:00
MediaOriginType MediaSource : : getOriginType ( ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return MediaOriginType : : unknown ;
}
return listener - > getOriginType ( const_cast < MediaSource & > ( * this ) ) ;
}
string MediaSource : : getOriginUrl ( ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2022-09-07 11:06:39 +08:00
return getUrl ( ) ;
2021-08-16 17:31:13 +08:00
}
auto ret = listener - > getOriginUrl ( const_cast < MediaSource & > ( * this ) ) ;
if ( ! ret . empty ( ) ) {
return ret ;
2020-09-27 11:32:49 +08:00
}
2022-09-07 11:06:39 +08:00
return getUrl ( ) ;
2020-09-27 11:32:49 +08:00
}
std : : shared_ptr < SockInfo > MediaSource : : getOriginSock ( ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return nullptr ;
}
return listener - > getOriginSock ( const_cast < MediaSource & > ( * this ) ) ;
}
2020-09-06 17:52:07 +08:00
bool MediaSource : : seekTo ( uint32_t stamp ) {
2019-12-03 16:10:02 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return false ;
}
2020-09-06 17:52:07 +08:00
return listener - > seekTo ( * this , stamp ) ;
2019-12-03 16:10:02 +08:00
}
2021-08-12 16:07:31 +08:00
bool MediaSource : : pause ( bool pause ) {
2021-08-09 18:28:43 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return false ;
}
2021-08-12 16:07:31 +08:00
return listener - > pause ( * this , pause ) ;
2021-08-09 18:28:43 +08:00
}
2021-08-12 16:07:31 +08:00
bool MediaSource : : speed ( float speed ) {
2021-08-09 18:28:43 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return false ;
}
return listener - > speed ( * this , speed ) ;
}
2019-12-03 16:10:02 +08:00
bool MediaSource : : close ( bool force ) {
auto listener = _listener . lock ( ) ;
2022-09-18 20:36:47 +08:00
if ( ! listener ) {
return false ;
}
if ( ! force & & totalReaderCount ( ) ) {
2024-09-19 14:53:50 +08:00
// 有人观看,不强制关闭 [AUTO-TRANSLATED:44b7e24d]
// Someone is watching, do not force close
2019-12-03 16:10:02 +08:00
return false ;
}
2022-09-18 20:36:47 +08:00
return listener - > close ( * this ) ;
2019-12-03 16:10:02 +08:00
}
2022-09-03 15:53:01 +08:00
float MediaSource : : getLossRate ( mediakit : : TrackType type ) {
2022-06-11 04:31:06 +00:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return - 1 ;
}
return listener - > getLossRate ( * this , type ) ;
}
2022-06-11 12:56:03 +08:00
toolkit : : EventPoller : : Ptr MediaSource : : getOwnerPoller ( ) {
2022-06-11 13:08:58 +08:00
toolkit : : EventPoller : : Ptr ret ;
2022-06-11 12:56:03 +08:00
auto listener = _listener . lock ( ) ;
2022-06-11 13:08:58 +08:00
if ( listener ) {
2022-10-31 17:53:20 +08:00
return listener - > getOwnerPoller ( * this ) ;
2022-06-11 12:56:03 +08:00
}
2022-11-26 10:14:37 +08:00
throw std : : runtime_error ( toolkit : : demangle ( typeid ( * this ) . name ( ) ) + " ::getOwnerPoller failed: " + getUrl ( ) ) ;
2022-06-11 12:56:03 +08:00
}
2024-06-09 10:52:10 +08:00
std : : shared_ptr < MultiMediaSourceMuxer > MediaSource : : getMuxer ( ) const {
2023-07-08 21:35:09 +08:00
auto listener = _listener . lock ( ) ;
2024-06-09 10:52:10 +08:00
return listener ? listener - > getMuxer ( const_cast < MediaSource & > ( * this ) ) : nullptr ;
}
std : : shared_ptr < RtpProcess > MediaSource : : getRtpProcess ( ) const {
auto listener = _listener . lock ( ) ;
return listener ? listener - > getRtpProcess ( const_cast < MediaSource & > ( * this ) ) : nullptr ;
2023-07-08 21:35:09 +08:00
}
2020-09-12 19:09:56 +08:00
void MediaSource : : onReaderChanged ( int size ) {
2022-11-26 10:14:37 +08:00
try {
weak_ptr < MediaSource > weak_self = shared_from_this ( ) ;
getOwnerPoller ( ) - > async ( [ weak_self , size ] ( ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
return ;
}
auto listener = strong_self - > _listener . lock ( ) ;
if ( listener ) {
listener - > onReaderChanged ( * strong_self , size ) ;
}
} ) ;
} catch ( MediaSourceEvent : : NotImplemented & ex ) {
2024-09-19 14:53:50 +08:00
// 未实现接口,应该打印异常 [AUTO-TRANSLATED:84f28c9d]
// The interface is not implemented, an exception should be printed
2022-11-26 10:14:37 +08:00
WarnL < < ex . what ( ) ;
} catch ( . . . ) {
2024-09-19 14:53:50 +08:00
// getOwnerPoller()接口抛异常机制应该只对外不对内 [AUTO-TRANSLATED:ee2e2923]
// The getOwnerPoller() interface should only throw exceptions externally, not internally
// 所以listener已经销毁导致获取归属线程失败的异常直接忽略 [AUTO-TRANSLATED:26cb5521]
// Therefore, the exception that the listener has been destroyed and the ownership thread cannot be obtained is directly ignored
2022-10-31 17:53:20 +08:00
}
2019-12-03 16:10:02 +08:00
}
2021-03-07 10:41:57 +08:00
bool MediaSource : : setupRecord ( Recorder : : type type , bool start , const string & custom_path , size_t max_second ) {
2020-04-05 09:26:29 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2022-09-07 11:06:39 +08:00
WarnL < < " 未设置MediaSource的事件监听者, setupRecord失败: " < < getUrl ( ) ;
2020-04-05 09:26:29 +08:00
return false ;
}
2021-03-07 10:41:57 +08:00
return listener - > setupRecord ( * this , type , start , custom_path , max_second ) ;
2020-04-05 09:26:29 +08:00
}
bool MediaSource : : isRecording ( Recorder : : type type ) {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return false ;
}
return listener - > isRecording ( * this , type ) ;
}
2022-04-03 18:25:36 +08:00
void MediaSource : : startSendRtp ( const MediaSourceEvent : : SendRtpArgs & args , const std : : function < void ( uint16_t , const toolkit : : SockException & ) > cb ) {
2020-09-06 17:56:05 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2021-01-02 20:43:02 +08:00
cb ( 0 , SockException ( Err_other , " 尚未设置事件监听器 " ) ) ;
2020-09-06 17:56:05 +08:00
return ;
}
2022-04-03 18:25:36 +08:00
return listener - > startSendRtp ( * this , args , cb ) ;
2020-09-06 17:56:05 +08:00
}
2020-12-27 18:41:53 +08:00
bool MediaSource : : stopSendRtp ( const string & ssrc ) {
2020-09-06 17:56:05 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
return false ;
}
2020-12-27 18:41:53 +08:00
return listener - > stopSendRtp ( * this , ssrc ) ;
2020-09-06 17:56:05 +08:00
}
2021-06-30 23:03:27 +08:00
template < typename MAP , typename LIST , typename First , typename . . . KeyTypes >
static void for_each_media_l ( const MAP & map , LIST & list , const First & first , const KeyTypes & . . . keys ) {
if ( first . empty ( ) ) {
for ( auto & pr : map ) {
for_each_media_l ( pr . second , list , keys . . . ) ;
}
return ;
}
auto it = map . find ( first ) ;
if ( it ! = map . end ( ) ) {
for_each_media_l ( it - > second , list , keys . . . ) ;
}
}
template < typename LIST , typename Ptr >
static void emplace_back ( LIST & list , const Ptr & ptr ) {
2021-06-30 21:06:29 +08:00
auto src = ptr . lock ( ) ;
if ( src ) {
2021-06-30 23:03:27 +08:00
list . emplace_back ( std : : move ( src ) ) ;
2021-06-30 21:06:29 +08:00
}
}
2021-06-30 23:03:27 +08:00
template < typename MAP , typename LIST , typename First >
static void for_each_media_l ( const MAP & map , LIST & list , const First & first ) {
if ( first . empty ( ) ) {
for ( auto & pr : map ) {
emplace_back ( list , pr . second ) ;
}
return ;
}
auto it = map . find ( first ) ;
if ( it ! = map . end ( ) ) {
emplace_back ( list , it - > second ) ;
}
}
void MediaSource : : for_each_media ( const function < void ( const Ptr & src ) > & cb ,
2021-06-30 21:06:29 +08:00
const string & schema ,
const string & vhost ,
const string & app ,
const string & stream ) {
2021-06-30 23:03:27 +08:00
deque < Ptr > src_list ;
2020-04-06 21:23:35 +08:00
{
2020-09-06 17:52:07 +08:00
lock_guard < recursive_mutex > lock ( s_media_source_mtx ) ;
2021-06-30 23:03:27 +08:00
for_each_media_l ( s_media_source_map , src_list , schema , vhost , app , stream ) ;
2020-04-06 21:23:35 +08:00
}
2021-06-30 23:03:27 +08:00
for ( auto & src : src_list ) {
cb ( src ) ;
2019-12-03 16:10:02 +08:00
}
}
2021-10-21 10:21:52 +08:00
static MediaSource : : Ptr find_l ( const string & schema , const string & vhost_in , const string & app , const string & id , bool from_mp4 ) {
2020-09-06 17:52:07 +08:00
string vhost = vhost_in ;
2022-09-07 11:06:39 +08:00
GET_CONFIG ( bool , enableVhost , General : : kEnableVhost ) ;
2020-09-06 17:52:07 +08:00
if ( vhost . empty ( ) | | ! enableVhost ) {
vhost = DEFAULT_VHOST ;
}
2021-07-01 10:56:59 +08:00
if ( app . empty ( ) | | id . empty ( ) ) {
2024-09-19 14:53:50 +08:00
// 如果未指定app与stream id, 那么就是遍历而非查找, 所以应该返回查找失败 [AUTO-TRANSLATED:84976471]
// If no app and stream id are specified, then it is traversal instead of searching, so it should return search failure
2021-07-01 10:56:59 +08:00
return nullptr ;
}
2020-09-06 17:52:07 +08:00
MediaSource : : Ptr ret ;
2021-06-30 23:35:19 +08:00
MediaSource : : for_each_media ( [ & ] ( const MediaSource : : Ptr & src ) { ret = std : : move ( const_cast < MediaSource : : Ptr & > ( src ) ) ; } , schema , vhost , app , id ) ;
2020-09-06 17:52:07 +08:00
2021-10-21 10:21:52 +08:00
if ( ! ret & & from_mp4 & & schema ! = HLS_SCHEMA ) {
2024-09-19 14:53:50 +08:00
// 未找到媒体源, 则读取mp4创建一个 [AUTO-TRANSLATED:e2e03a82]
// If the media source is not found, read mp4 to create one
// 播放hls不触发mp4点播(因为HLS也可以用于录像, 不是纯粹的直播) [AUTO-TRANSLATED:30b18b6d]
// Playing hls does not trigger mp4 on-demand (because HLS can also be used for recording, not purely live)
2020-09-06 17:52:07 +08:00
ret = MediaSource : : createFromMP4 ( schema , vhost , app , id ) ;
}
return ret ;
}
2021-07-15 11:25:06 +08:00
static void findAsync_l ( const MediaInfo & info , const std : : shared_ptr < Session > & session , bool retry ,
2020-09-06 17:52:07 +08:00
const function < void ( const MediaSource : : Ptr & src ) > & cb ) {
2023-05-25 16:23:24 +08:00
auto src = find_l ( info . schema , info . vhost , info . app , info . stream , true ) ;
2020-07-16 16:00:31 +08:00
if ( src | | ! retry ) {
2019-05-27 22:32:07 +08:00
cb ( src ) ;
return ;
}
2021-02-28 20:58:25 +08:00
GET_CONFIG ( int , maxWaitMS , General : : kMaxStreamWaitTimeMS ) ;
2019-05-27 22:32:07 +08:00
void * listener_tag = session . get ( ) ;
2021-02-28 20:58:25 +08:00
auto poller = session - > getPoller ( ) ;
std : : shared_ptr < atomic_flag > invoked ( new atomic_flag { false } ) ;
auto cb_once = [ cb , invoked ] ( const MediaSource : : Ptr & src ) {
if ( invoked - > test_and_set ( ) ) {
2024-09-19 14:53:50 +08:00
// 回调已经执行过了 [AUTO-TRANSLATED:f034e2eb]
// The callback has already been executed
2021-02-28 20:58:25 +08:00
return ;
}
cb ( src ) ;
} ;
2019-05-28 09:25:41 +08:00
2021-02-28 20:58:25 +08:00
auto on_timeout = poller - > doDelayTask ( maxWaitMS , [ cb_once , listener_tag ] ( ) {
2024-09-19 14:53:50 +08:00
// 最多等待一定时间,如在这个时间内,流还未注册上,则返回空 [AUTO-TRANSLATED:e8851208]
// Wait for a certain amount of time at most, if the stream is not registered within this time, return empty
2020-07-16 16:00:31 +08:00
NoticeCenter : : Instance ( ) . delListener ( listener_tag , Broadcast : : kBroadcastMediaChanged ) ;
2021-02-28 20:58:25 +08:00
cb_once ( nullptr ) ;
2019-05-27 22:32:07 +08:00
return 0 ;
} ) ;
2020-09-06 17:52:07 +08:00
auto cancel_all = [ on_timeout , listener_tag ] ( ) {
2024-09-19 14:53:50 +08:00
// 取消延时任务,防止多次回调 [AUTO-TRANSLATED:42988b9c]
// Cancel the delayed task to prevent multiple callbacks
2020-09-06 17:52:07 +08:00
on_timeout - > cancel ( ) ;
2024-09-19 14:53:50 +08:00
// 取消媒体注册事件监听 [AUTO-TRANSLATED:efb9aacb]
// Cancel the media registration event listener
2020-07-16 16:00:31 +08:00
NoticeCenter : : Instance ( ) . delListener ( listener_tag , Broadcast : : kBroadcastMediaChanged ) ;
} ;
2021-07-15 11:25:06 +08:00
weak_ptr < Session > weak_session = session ;
2021-02-28 20:58:25 +08:00
auto on_register = [ weak_session , info , cb_once , cancel_all , poller ] ( BroadcastMediaChangedArgs ) {
2019-12-24 14:08:16 +08:00
if ( ! bRegist | |
2023-05-25 16:23:24 +08:00
sender . getSchema ( ) ! = info . schema | |
2023-06-17 10:28:01 +08:00
! equalMediaTuple ( sender . getMediaTuple ( ) , info ) ) {
2024-09-19 14:53:50 +08:00
// 不是自己感兴趣的事件,忽略之 [AUTO-TRANSLATED:b4e102d4]
// Not an event of interest, ignore it
2019-05-27 22:32:07 +08:00
return ;
}
2022-09-07 11:06:39 +08:00
2021-02-28 20:58:25 +08:00
poller - > async ( [ weak_session , cancel_all , info , cb_once ] ( ) {
cancel_all ( ) ;
2022-09-07 11:06:39 +08:00
if ( auto strong_session = weak_session . lock ( ) ) {
2024-09-19 14:53:50 +08:00
// 播发器请求的流终于注册上了,切换到自己的线程再回复 [AUTO-TRANSLATED:7b79ad9b]
// The stream requested by the player is finally registered, switch to its own thread and reply
2022-09-07 11:06:39 +08:00
DebugL < < " 收到媒体注册事件,回复播放器: " < < info . getUrl ( ) ;
2024-09-19 14:53:50 +08:00
// 再找一遍媒体源,一般能找到 [AUTO-TRANSLATED:069de7f6]
// Find the media source again, usually it can be found
2022-09-07 11:06:39 +08:00
findAsync_l ( info , strong_session , false , cb_once ) ;
2019-05-27 22:32:07 +08:00
}
} , false ) ;
} ;
2020-07-16 16:00:31 +08:00
2024-09-19 14:53:50 +08:00
// 监听媒体注册事件 [AUTO-TRANSLATED:9cf13779]
// Listen for media registration events
2021-02-28 20:58:25 +08:00
NoticeCenter : : Instance ( ) . addListener ( listener_tag , Broadcast : : kBroadcastMediaChanged , on_register ) ;
function < void ( ) > close_player = [ cb_once , cancel_all , poller ] ( ) {
poller - > async ( [ cancel_all , cb_once ] ( ) {
cancel_all ( ) ;
2024-09-19 14:53:50 +08:00
// 告诉播放器,流不存在,这样会立即断开播放器 [AUTO-TRANSLATED:b5b4eead]
// Tell the player that the stream does not exist, so it will immediately disconnect the player
2021-02-28 20:58:25 +08:00
cb_once ( nullptr ) ;
} ) ;
} ;
2024-09-19 14:53:50 +08:00
// 广播未找到流,此时可以立即去拉流,这样还来得及 [AUTO-TRANSLATED:794014f1]
// Broadcast that the stream is not found, at this time you can immediately pull the stream, so it is still in time
2023-09-02 10:52:07 +08:00
NOTICE_EMIT ( BroadcastNotFoundStreamArgs , Broadcast : : kBroadcastNotFoundStream , info , * session , close_player ) ;
2019-05-27 22:32:07 +08:00
}
2019-12-03 16:10:02 +08:00
2021-07-15 11:25:06 +08:00
void MediaSource : : findAsync ( const MediaInfo & info , const std : : shared_ptr < Session > & session , const function < void ( const Ptr & ) > & cb ) {
2019-12-03 16:10:02 +08:00
return findAsync_l ( info , session , true , cb ) ;
}
2021-10-21 10:21:52 +08:00
MediaSource : : Ptr MediaSource : : find ( const string & schema , const string & vhost , const string & app , const string & id , bool from_mp4 ) {
return find_l ( schema , vhost , app , id , from_mp4 ) ;
2020-05-26 10:11:58 +08:00
}
2021-10-21 10:21:52 +08:00
MediaSource : : Ptr MediaSource : : find ( const string & vhost , const string & app , const string & stream_id , bool from_mp4 ) {
auto src = MediaSource : : find ( RTMP_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
2020-09-06 18:19:54 +08:00
if ( src ) {
return src ;
}
2021-10-21 10:21:52 +08:00
src = MediaSource : : find ( RTSP_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
2020-09-06 18:19:54 +08:00
if ( src ) {
return src ;
}
2023-12-02 16:31:40 +08:00
src = MediaSource : : find ( TS_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
if ( src ) {
return src ;
}
src = MediaSource : : find ( FMP4_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
if ( src ) {
return src ;
}
src = MediaSource : : find ( HLS_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
if ( src ) {
return src ;
}
return MediaSource : : find ( HLS_FMP4_SCHEMA , vhost , app , stream_id , from_mp4 ) ;
2020-09-06 18:19:54 +08:00
}
2020-09-06 17:52:07 +08:00
void MediaSource : : emitEvent ( bool regist ) {
2020-07-02 18:14:39 +08:00
auto listener = _listener . lock ( ) ;
if ( listener ) {
2024-09-19 14:53:50 +08:00
// 触发回调 [AUTO-TRANSLATED:08ea452d]
// Trigger callback
2020-09-06 17:52:07 +08:00
listener - > onRegist ( * this , regist ) ;
}
2024-09-19 14:53:50 +08:00
// 触发广播 [AUTO-TRANSLATED:a5b415a4]
// Trigger broadcast
2023-09-02 10:52:07 +08:00
NOTICE_EMIT ( BroadcastMediaChangedArgs , Broadcast : : kBroadcastMediaChanged , regist , * this ) ;
2022-09-07 11:06:39 +08:00
InfoL < < ( regist ? " 媒体注册: " : " 媒体注销: " ) < < getUrl ( ) ;
2020-09-06 17:52:07 +08:00
}
void MediaSource : : regist ( ) {
{
2024-09-19 14:53:50 +08:00
// 减小互斥锁临界区 [AUTO-TRANSLATED:1309d309]
// Reduce mutex lock critical area
2020-09-06 17:52:07 +08:00
lock_guard < recursive_mutex > lock ( s_media_source_mtx ) ;
2023-05-25 16:23:24 +08:00
auto & ref = s_media_source_map [ _schema ] [ _tuple . vhost ] [ _tuple . app ] [ _tuple . stream ] ;
2022-01-10 16:37:50 +08:00
auto src = ref . lock ( ) ;
if ( src ) {
if ( src . get ( ) = = this ) {
return ;
}
2024-09-19 14:53:50 +08:00
// 增加判断, 防止当前流已注册时再次注册 [AUTO-TRANSLATED:ccc5dcb1]
// Add judgment to prevent re-registration when the current stream is already registered
2022-09-07 11:06:39 +08:00
throw std : : invalid_argument ( " media source already existed: " + getUrl ( ) ) ;
2021-11-19 15:33:16 +08:00
}
ref = shared_from_this ( ) ;
2020-07-02 18:14:39 +08:00
}
2020-09-06 17:52:07 +08:00
emitEvent ( true ) ;
2018-02-02 18:19:35 +08:00
}
2020-03-04 21:57:31 +08:00
2021-06-30 23:35:19 +08:00
template < typename MAP , typename First , typename . . . KeyTypes >
static bool erase_media_source ( bool & hit , const MediaSource * thiz , MAP & map , const First & first , const KeyTypes & . . . keys ) {
auto it = map . find ( first ) ;
if ( it ! = map . end ( ) & & erase_media_source ( hit , thiz , it - > second , keys . . . ) ) {
map . erase ( it ) ;
}
return map . empty ( ) ;
}
template < typename MAP , typename First >
static bool erase_media_source ( bool & hit , const MediaSource * thiz , MAP & map , const First & first ) {
auto it = map . find ( first ) ;
if ( it ! = map . end ( ) ) {
auto src = it - > second . lock ( ) ;
if ( ! src | | src . get ( ) = = thiz ) {
2024-09-19 14:53:50 +08:00
// 对象已经销毁或者对象就是自己,那么移除之 [AUTO-TRANSLATED:1b9a11d1]
// If the object has been destroyed or the object is itself, then remove it
2021-06-30 23:35:19 +08:00
map . erase ( it ) ;
hit = true ;
}
}
return map . empty ( ) ;
}
2024-09-19 14:53:50 +08:00
// 反注册该源 [AUTO-TRANSLATED:682c27ab]
// Unregister the source
2018-02-02 18:19:35 +08:00
bool MediaSource : : unregist ( ) {
2021-06-30 23:35:19 +08:00
bool ret = false ;
2020-03-04 21:57:31 +08:00
{
2024-09-19 14:53:50 +08:00
// 减小互斥锁临界区 [AUTO-TRANSLATED:1309d309]
// Reduce mutex lock critical area
2020-09-06 17:52:07 +08:00
lock_guard < recursive_mutex > lock ( s_media_source_mtx ) ;
2023-05-25 16:23:24 +08:00
erase_media_source ( ret , this , s_media_source_map , _schema , _tuple . vhost , _tuple . app , _tuple . stream ) ;
2020-09-06 17:52:07 +08:00
}
if ( ret ) {
emitEvent ( false ) ;
2020-03-04 21:57:31 +08:00
}
return ret ;
}
2019-12-03 16:10:02 +08:00
2023-06-17 10:28:01 +08:00
bool equalMediaTuple ( const MediaTuple & a , const MediaTuple & b ) {
return a . vhost = = b . vhost & & a . app = = b . app & & a . stream = = b . stream ;
}
2019-12-03 16:10:02 +08:00
/////////////////////////////////////MediaInfo//////////////////////////////////////
2022-09-07 11:06:39 +08:00
void MediaInfo : : parse ( const std : : string & url_in ) {
2023-05-25 16:23:24 +08:00
full_url = url_in ;
2022-09-07 11:06:39 +08:00
auto url = url_in ;
2020-09-20 20:15:39 +08:00
auto pos = url . find ( " ? " ) ;
if ( pos ! = string : : npos ) {
2024-03-30 14:41:20 +08:00
params = url . substr ( pos + 1 ) ;
2020-09-20 20:15:39 +08:00
url . erase ( pos ) ;
}
2018-02-02 18:19:35 +08:00
auto schema_pos = url . find ( " :// " ) ;
2020-09-06 17:52:07 +08:00
if ( schema_pos ! = string : : npos ) {
2023-05-25 16:23:24 +08:00
schema = url . substr ( 0 , schema_pos ) ;
2020-09-06 17:52:07 +08:00
} else {
2018-02-02 18:19:35 +08:00
schema_pos = - 3 ;
}
2020-09-06 17:52:07 +08:00
auto split_vec = split ( url . substr ( schema_pos + 3 ) , " / " ) ;
if ( split_vec . size ( ) > 0 ) {
2023-05-25 16:23:24 +08:00
splitUrl ( split_vec [ 0 ] , host , port ) ;
vhost = host ;
if ( vhost = = " localhost " | | isIP ( vhost . data ( ) ) ) {
2024-09-19 14:53:50 +08:00
// 如果访问的是localhost或ip, 那么则为默认虚拟主机 [AUTO-TRANSLATED:67291b7a]
// If the access is to localhost or ip, then it is the default virtual host
2023-05-25 16:23:24 +08:00
vhost = DEFAULT_VHOST ;
2020-03-12 12:47:15 +08:00
}
2018-02-02 18:19:35 +08:00
}
2020-09-06 17:52:07 +08:00
if ( split_vec . size ( ) > 1 ) {
2023-05-25 16:23:24 +08:00
app = split_vec [ 1 ] ;
2018-02-02 18:19:35 +08:00
}
2020-09-06 17:52:07 +08:00
if ( split_vec . size ( ) > 2 ) {
string stream_id ;
2021-01-19 16:05:38 +08:00
for ( size_t i = 2 ; i < split_vec . size ( ) ; + + i ) {
2020-09-06 17:52:07 +08:00
stream_id . append ( split_vec [ i ] + " / " ) ;
2018-02-02 18:19:35 +08:00
}
2020-09-06 17:52:07 +08:00
if ( stream_id . back ( ) = = ' / ' ) {
stream_id . pop_back ( ) ;
2018-02-02 18:19:35 +08:00
}
2023-05-25 16:23:24 +08:00
stream = stream_id ;
2020-09-20 20:15:39 +08:00
}
2024-03-30 14:41:20 +08:00
auto kv = Parser : : parseArgs ( params ) ;
auto it = kv . find ( VHOST_KEY ) ;
if ( it ! = kv . end ( ) ) {
vhost = it - > second ;
2018-02-02 18:19:35 +08:00
}
2019-05-29 09:26:16 +08:00
2020-09-06 17:52:07 +08:00
GET_CONFIG ( bool , enableVhost , General : : kEnableVhost ) ;
2023-05-25 16:23:24 +08:00
if ( ! enableVhost | | vhost . empty ( ) ) {
2024-09-19 14:53:50 +08:00
// 如果关闭虚拟主机或者虚拟主机为空,则设置虚拟主机为默认 [AUTO-TRANSLATED:9f76a112]
// If the virtual host is closed or the virtual host is empty, set the virtual host to the default
2023-05-25 16:23:24 +08:00
vhost = DEFAULT_VHOST ;
2018-02-02 18:19:35 +08:00
}
}
2020-09-06 17:52:07 +08:00
MediaSource : : Ptr MediaSource : : createFromMP4 ( const string & schema , const string & vhost , const string & app , const string & stream , const string & file_path , bool check_app ) {
GET_CONFIG ( string , appName , Record : : kAppName ) ;
if ( check_app & & app ! = appName ) {
return nullptr ;
}
# ifdef ENABLE_MP4
try {
2024-07-14 09:32:41 +08:00
MediaTuple tuple = { vhost , app , stream , " " } ;
auto reader = std : : make_shared < MP4Reader > ( tuple , file_path ) ;
2022-08-27 10:17:06 +08:00
reader - > startReadMP4 ( ) ;
2020-09-06 17:52:07 +08:00
return MediaSource : : find ( schema , vhost , app , stream ) ;
} catch ( std : : exception & ex ) {
WarnL < < ex . what ( ) ;
return nullptr ;
}
# else
WarnL < < " 创建MP4点播失败, 请编译时打开 \" ENABLE_MP4 \" 选项 " ;
return nullptr ;
# endif //ENABLE_MP4
}
2019-12-03 16:10:02 +08:00
/////////////////////////////////////MediaSourceEvent//////////////////////////////////////
2020-09-12 19:09:56 +08:00
void MediaSourceEvent : : onReaderChanged ( MediaSource & sender , int size ) {
2024-05-23 10:30:11 +08:00
GET_CONFIG ( bool , enable , General : : kBroadcastPlayerCountChanged ) ;
if ( enable ) {
NOTICE_EMIT ( BroadcastPlayerCountChangedArgs , Broadcast : : kBroadcastPlayerCountChanged , sender . getMediaTuple ( ) , sender . totalReaderCount ( ) ) ;
}
2022-08-28 17:25:56 +08:00
if ( size | | sender . totalReaderCount ( ) ) {
2024-09-19 14:53:50 +08:00
// 还有人观看该视频,不触发关闭事件 [AUTO-TRANSLATED:7f2f6ed3]
// Someone is still watching this video, do not trigger the close event
2021-04-18 21:27:44 +08:00
_async_close_timer = nullptr ;
2020-09-12 19:09:56 +08:00
return ;
}
2024-09-19 14:53:50 +08:00
// 没有任何人观看该视频源,表明该源可以关闭了 [AUTO-TRANSLATED:ea64bb8f]
// No one is watching this video source, indicating that the source can be closed.
2020-09-06 17:52:07 +08:00
GET_CONFIG ( string , record_app , Record : : kAppName ) ;
2020-03-23 10:21:17 +08:00
GET_CONFIG ( int , stream_none_reader_delay , General : : kStreamNoneReaderDelayMS ) ;
2024-09-19 14:53:50 +08:00
// 如果mp4点播, 无人观看时我们强制关闭点播 [AUTO-TRANSLATED:9576e4b0]
// If it's an mp4 on-demand, we force close the on-demand when no one is watching.
2023-06-17 10:28:01 +08:00
bool is_mp4_vod = sender . getMediaTuple ( ) . app = = record_app ;
2020-09-12 19:09:56 +08:00
weak_ptr < MediaSource > weak_sender = sender . shared_from_this ( ) ;
2020-04-03 22:39:44 +08:00
2021-01-17 18:31:50 +08:00
_async_close_timer = std : : make_shared < Timer > ( stream_none_reader_delay / 1000.0f , [ weak_sender , is_mp4_vod ] ( ) {
2020-09-12 19:09:56 +08:00
auto strong_sender = weak_sender . lock ( ) ;
if ( ! strong_sender ) {
2024-09-19 14:53:50 +08:00
// 对象已经销毁 [AUTO-TRANSLATED:130328af]
// The object has been destroyed.
2020-03-23 10:21:17 +08:00
return false ;
}
2020-09-12 19:09:56 +08:00
if ( strong_sender - > totalReaderCount ( ) ) {
2024-09-19 14:53:50 +08:00
// 还有人观看该视频,不触发关闭事件 [AUTO-TRANSLATED:7f2f6ed3]
// Someone is still watching this video, so the close event is not triggered.
2020-03-23 10:21:17 +08:00
return false ;
2019-07-11 14:38:54 +08:00
}
2020-03-23 10:21:17 +08:00
2020-09-12 19:09:56 +08:00
if ( ! is_mp4_vod ) {
2023-07-08 21:36:34 +08:00
auto muxer = strong_sender - > getMuxer ( ) ;
if ( muxer & & muxer - > getOption ( ) . auto_close ) {
2024-09-19 14:53:50 +08:00
// 此流被标记为无人观看自动关闭流 [AUTO-TRANSLATED:64a0dac3]
// This stream is marked as an automatically closed stream with no viewers.
2023-07-08 21:36:34 +08:00
WarnL < < " Auto cloe stream when none reader: " < < strong_sender - > getUrl ( ) ;
strong_sender - > close ( false ) ;
} else {
2024-09-19 14:53:50 +08:00
// 直播时触发无人观看事件,让开发者自行选择是否关闭 [AUTO-TRANSLATED:c6c75eaa]
// When live streaming, trigger the no-viewer event, allowing developers to choose whether to close it.
2023-09-02 10:52:07 +08:00
NOTICE_EMIT ( BroadcastStreamNoneReaderArgs , Broadcast : : kBroadcastStreamNoneReader , * strong_sender ) ;
2023-07-08 21:36:34 +08:00
}
2020-09-12 19:09:56 +08:00
} else {
2024-09-19 14:53:50 +08:00
// 这个是mp4点播, 我们自动关闭 [AUTO-TRANSLATED:8a7b9a90]
// This is an mp4 on-demand, we automatically close it.
2022-09-07 11:06:39 +08:00
WarnL < < " MP4点播无人观看,自动关闭: " < < strong_sender - > getUrl ( ) ;
2020-09-12 19:09:56 +08:00
strong_sender - > close ( false ) ;
2020-04-03 22:39:44 +08:00
}
2020-03-23 10:21:17 +08:00
return false ;
} , nullptr ) ;
2019-05-29 18:08:50 +08:00
}
2021-08-16 17:31:13 +08:00
string MediaSourceEvent : : getOriginUrl ( MediaSource & sender ) const {
2022-09-07 11:06:39 +08:00
return sender . getUrl ( ) ;
2021-08-16 17:31:13 +08:00
}
2020-09-27 11:32:49 +08:00
MediaOriginType MediaSourceEventInterceptor : : getOriginType ( MediaSource & sender ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : getOriginType ( sender ) ;
2020-09-27 11:32:49 +08:00
}
return listener - > getOriginType ( sender ) ;
}
string MediaSourceEventInterceptor : : getOriginUrl ( MediaSource & sender ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2021-08-16 17:31:13 +08:00
return MediaSourceEvent : : getOriginUrl ( sender ) ;
}
auto ret = listener - > getOriginUrl ( sender ) ;
if ( ! ret . empty ( ) ) {
return ret ;
2020-09-27 11:32:49 +08:00
}
2021-08-16 17:31:13 +08:00
return MediaSourceEvent : : getOriginUrl ( sender ) ;
2020-09-27 11:32:49 +08:00
}
std : : shared_ptr < SockInfo > MediaSourceEventInterceptor : : getOriginSock ( MediaSource & sender ) const {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : getOriginSock ( sender ) ;
2020-09-27 11:32:49 +08:00
}
return listener - > getOriginSock ( sender ) ;
}
2020-09-06 17:52:07 +08:00
bool MediaSourceEventInterceptor : : seekTo ( MediaSource & sender , uint32_t stamp ) {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : seekTo ( sender , stamp ) ;
2020-04-03 23:27:16 +08:00
}
2020-09-06 17:52:07 +08:00
return listener - > seekTo ( sender , stamp ) ;
}
2021-08-12 16:07:31 +08:00
bool MediaSourceEventInterceptor : : pause ( MediaSource & sender , bool pause ) {
2021-08-09 18:28:43 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : pause ( sender , pause ) ;
2021-08-09 18:28:43 +08:00
}
2021-08-12 16:07:31 +08:00
return listener - > pause ( sender , pause ) ;
2021-08-09 18:28:43 +08:00
}
2021-08-12 16:07:31 +08:00
bool MediaSourceEventInterceptor : : speed ( MediaSource & sender , float speed ) {
2021-08-09 18:28:43 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : speed ( sender , speed ) ;
2021-08-09 18:28:43 +08:00
}
return listener - > speed ( sender , speed ) ;
}
2022-09-18 20:36:47 +08:00
bool MediaSourceEventInterceptor : : close ( MediaSource & sender ) {
2020-09-06 17:52:07 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : close ( sender ) ;
2020-04-03 23:27:16 +08:00
}
2022-09-18 20:36:47 +08:00
return listener - > close ( sender ) ;
2020-09-06 17:52:07 +08:00
}
int MediaSourceEventInterceptor : : totalReaderCount ( MediaSource & sender ) {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : totalReaderCount ( sender ) ;
2020-09-06 17:52:07 +08:00
}
return listener - > totalReaderCount ( sender ) ;
}
2020-09-12 19:09:56 +08:00
void MediaSourceEventInterceptor : : onReaderChanged ( MediaSource & sender , int size ) {
2020-09-06 17:52:07 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : onReaderChanged ( sender , size ) ;
2020-09-06 17:52:07 +08:00
}
2024-06-14 12:59:02 +08:00
listener - > onReaderChanged ( sender , size ) ;
2020-09-06 17:52:07 +08:00
}
void MediaSourceEventInterceptor : : onRegist ( MediaSource & sender , bool regist ) {
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : onRegist ( sender , regist ) ;
2020-09-06 17:52:07 +08:00
}
2024-06-14 12:59:02 +08:00
listener - > onRegist ( sender , regist ) ;
2020-09-06 17:52:07 +08:00
}
2024-06-14 12:59:02 +08:00
float MediaSourceEventInterceptor : : getLossRate ( MediaSource & sender , TrackType type ) {
2022-06-11 04:31:06 +00:00
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : getLossRate ( sender , type ) ;
2022-06-11 04:31:06 +00:00
}
2024-06-14 12:59:02 +08:00
return listener - > getLossRate ( sender , type ) ;
2022-06-11 04:31:06 +00:00
}
2022-06-11 12:56:03 +08:00
toolkit : : EventPoller : : Ptr MediaSourceEventInterceptor : : getOwnerPoller ( MediaSource & sender ) {
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : getOwnerPoller ( sender ) ;
2022-06-11 12:56:03 +08:00
}
2024-06-14 12:59:02 +08:00
return listener - > getOwnerPoller ( sender ) ;
2022-06-11 12:56:03 +08:00
}
2024-06-09 10:52:10 +08:00
std : : shared_ptr < MultiMediaSourceMuxer > MediaSourceEventInterceptor : : getMuxer ( MediaSource & sender ) const {
2023-07-08 21:35:09 +08:00
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : getMuxer ( sender ) ;
}
return listener - > getMuxer ( sender ) ;
2023-07-08 21:35:09 +08:00
}
2024-06-09 10:52:10 +08:00
std : : shared_ptr < RtpProcess > MediaSourceEventInterceptor : : getRtpProcess ( MediaSource & sender ) const {
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : getRtpProcess ( sender ) ;
}
return listener - > getRtpProcess ( sender ) ;
2024-06-09 10:52:10 +08:00
}
2021-03-07 10:41:57 +08:00
bool MediaSourceEventInterceptor : : setupRecord ( MediaSource & sender , Recorder : : type type , bool start , const string & custom_path , size_t max_second ) {
2020-09-06 17:52:07 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : setupRecord ( sender , type , start , custom_path , max_second ) ;
2020-09-06 17:52:07 +08:00
}
2021-03-07 10:41:57 +08:00
return listener - > setupRecord ( sender , type , start , custom_path , max_second ) ;
2020-09-06 17:52:07 +08:00
}
bool MediaSourceEventInterceptor : : isRecording ( MediaSource & sender , Recorder : : type type ) {
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : isRecording ( sender , type ) ;
2020-09-06 17:52:07 +08:00
}
return listener - > isRecording ( sender , type ) ;
2020-04-03 23:27:16 +08:00
}
2018-02-02 18:19:35 +08:00
2021-07-20 13:15:57 +08:00
vector < Track : : Ptr > MediaSourceEventInterceptor : : getMediaTracks ( MediaSource & sender , bool trackReady ) const {
2020-09-06 17:54:52 +08:00
auto listener = _listener . lock ( ) ;
if ( ! listener ) {
2024-06-14 12:59:02 +08:00
return MediaSourceEvent : : getMediaTracks ( sender , trackReady ) ;
2020-09-06 17:54:52 +08:00
}
2021-07-20 13:15:57 +08:00
return listener - > getMediaTracks ( sender , trackReady ) ;
2020-09-06 17:54:52 +08:00
}
2022-04-03 18:25:36 +08:00
void MediaSourceEventInterceptor : : startSendRtp ( MediaSource & sender , const MediaSourceEvent : : SendRtpArgs & args , const std : : function < void ( uint16_t , const toolkit : : SockException & ) > cb ) {
2020-09-06 17:56:05 +08:00
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : startSendRtp ( sender , args , cb ) ;
2020-09-06 17:56:05 +08:00
}
2024-06-14 12:59:02 +08:00
listener - > startSendRtp ( sender , args , cb ) ;
2020-09-06 17:56:05 +08:00
}
2024-06-14 12:59:02 +08:00
bool MediaSourceEventInterceptor : : stopSendRtp ( MediaSource & sender , const string & ssrc ) {
2020-09-06 17:56:05 +08:00
auto listener = _listener . lock ( ) ;
2024-06-14 12:59:02 +08:00
if ( ! listener ) {
return MediaSourceEvent : : stopSendRtp ( sender , ssrc ) ;
2020-09-06 17:56:05 +08:00
}
2024-06-14 12:59:02 +08:00
return listener - > stopSendRtp ( sender , ssrc ) ;
2020-09-06 17:56:05 +08:00
}
2020-10-24 23:31:58 +08:00
void MediaSourceEventInterceptor : : setDelegate ( const std : : weak_ptr < MediaSourceEvent > & listener ) {
if ( listener . lock ( ) . get ( ) = = this ) {
throw std : : invalid_argument ( " can not set self as a delegate " ) ;
}
_listener = listener ;
}
2024-06-14 12:59:02 +08:00
std : : shared_ptr < MediaSourceEvent > MediaSourceEventInterceptor : : getDelegate ( ) const {
2020-10-24 23:31:58 +08:00
return _listener . lock ( ) ;
}
2020-09-06 17:52:07 +08:00
/////////////////////////////////////FlushPolicy//////////////////////////////////////
2021-01-17 18:31:50 +08:00
static bool isFlushAble_default ( bool is_video , uint64_t last_stamp , uint64_t new_stamp , size_t cache_size ) {
2020-05-27 11:25:56 +08:00
if ( new_stamp + 500 < last_stamp ) {
2024-09-19 14:53:50 +08:00
// 时间戳回退比较大(可能seek中), 由于rtp中时间戳是pts, 是可能存在一定程度的回退的 [AUTO-TRANSLATED:67158987]
// The timestamp rollback is relatively large (possibly during seek), because the timestamp in RTP is PTS, which may have a certain degree of rollback.
2020-04-09 16:19:03 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 时间戳发送变化或者缓存超过1024个,sendmsg接口一般最多只能发送1024个数据包 [AUTO-TRANSLATED:f87d1da0]
// The timestamp sends changes or the cache exceeds 1024, the sendmsg interface generally can only send a maximum of 1024 data packets.
2020-05-27 11:09:02 +08:00
return last_stamp ! = new_stamp | | cache_size > = 1024 ;
2020-04-09 16:19:03 +08:00
}
2021-01-17 18:31:50 +08:00
static bool isFlushAble_merge ( bool is_video , uint64_t last_stamp , uint64_t new_stamp , size_t cache_size , int merge_ms ) {
2020-05-27 11:25:56 +08:00
if ( new_stamp + 500 < last_stamp ) {
2024-09-19 14:53:50 +08:00
// 时间戳回退比较大(可能seek中), 由于rtp中时间戳是pts, 是可能存在一定程度的回退的 [AUTO-TRANSLATED:67158987]
// The timestamp rollback is relatively large (possibly during seek), because the timestamp in RTP is PTS, which may have a certain degree of rollback.
2020-04-09 16:19:03 +08:00
return true ;
}
2020-05-27 11:09:02 +08:00
if ( new_stamp > last_stamp + merge_ms ) {
2024-09-19 14:53:50 +08:00
// 时间戳增量超过合并写阈值 [AUTO-TRANSLATED:cbcf3ab0]
// The timestamp increment exceeds the merge write threshold.
2020-04-09 16:19:03 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 缓存数超过1024个,这个逻辑用于避免时间戳异常的流导致的内存暴增问题 [AUTO-TRANSLATED:f27e11f8]
// The number of caches exceeds 1024, this logic is used to avoid memory explosion caused by streams with abnormal timestamps.
// 而且sendmsg接口一般最多只能发送1024个数据包 [AUTO-TRANSLATED:872436e2]
// Moreover, the sendmsg interface generally can only send a maximum of 1024 data packets.
2020-05-27 11:09:02 +08:00
return cache_size > = 1024 ;
2020-04-09 16:19:03 +08:00
}
2021-01-17 18:31:50 +08:00
bool FlushPolicy : : isFlushAble ( bool is_video , bool is_key , uint64_t new_stamp , size_t cache_size ) {
2020-05-27 11:09:02 +08:00
bool flush_flag = false ;
if ( is_key & & is_video ) {
2024-09-19 14:53:50 +08:00
// 遇到关键帧flush掉前面的数据, 确保关键帧为该组数据的第一帧, 确保GOP缓存有效 [AUTO-TRANSLATED:e2ebbf9b]
// Encounter a key frame, flush the previous data, ensure that the key frame is the first frame of this group of data, and ensure the GOP cache is valid.
2020-05-27 11:09:02 +08:00
flush_flag = true ;
2020-04-24 13:51:04 +08:00
} else {
2020-05-27 11:09:02 +08:00
GET_CONFIG ( int , mergeWriteMS , General : : kMergeWriteMS ) ;
if ( mergeWriteMS < = 0 ) {
2024-09-19 14:53:50 +08:00
// 关闭了合并写或者合并写阈值小于等于0 [AUTO-TRANSLATED:2397b647]
// Merge writing is closed or the merge writing threshold is less than or equal to 0.
2020-05-27 11:09:02 +08:00
flush_flag = isFlushAble_default ( is_video , _last_stamp [ is_video ] , new_stamp , cache_size ) ;
} else {
flush_flag = isFlushAble_merge ( is_video , _last_stamp [ is_video ] , new_stamp , cache_size , mergeWriteMS ) ;
}
2020-04-24 13:51:04 +08:00
}
2020-05-27 11:09:02 +08:00
if ( flush_flag ) {
_last_stamp [ is_video ] = new_stamp ;
2020-04-09 16:19:03 +08:00
}
2020-05-27 11:09:02 +08:00
return flush_flag ;
2020-04-09 16:19:03 +08:00
}
2018-10-24 17:17:55 +08:00
} /* namespace mediakit */