2019-12-18 11:47:49 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
2019-12-17 18:45:31 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
2019-12-17 18:45:31 +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 .
2019-12-17 18:45:31 +08:00
*/
2019-12-27 10:10:31 +08:00
# include "mk_recorder.h"
2019-12-17 18:45:31 +08:00
# include "Rtmp/FlvMuxer.h"
2019-12-24 16:19:33 +08:00
# include "Record/Recorder.h"
2024-10-18 15:22:29 +08:00
# include "Record/MP4Reader.h"
2022-06-11 14:18:55 +08:00
using namespace std ;
2019-12-17 18:45:31 +08:00
using namespace toolkit ;
using namespace mediakit ;
API_EXPORT mk_flv_recorder API_CALL mk_flv_recorder_create ( ) {
FlvRecorder : : Ptr * ret = new FlvRecorder : : Ptr ( new FlvRecorder ) ;
2023-02-26 21:45:14 +08:00
return ( mk_flv_recorder ) ret ;
2019-12-17 18:45:31 +08:00
}
API_EXPORT void API_CALL mk_flv_recorder_release ( mk_flv_recorder ctx ) {
2019-12-18 14:43:32 +08:00
assert ( ctx ) ;
2019-12-17 18:45:31 +08:00
FlvRecorder : : Ptr * record = ( FlvRecorder : : Ptr * ) ( ctx ) ;
delete record ;
}
2019-12-27 13:56:02 +08:00
API_EXPORT int API_CALL mk_flv_recorder_start ( mk_flv_recorder ctx , const char * vhost , const char * app , const char * stream , const char * file_path ) {
assert ( ctx & & vhost & & app & & stream & & file_path ) ;
2019-12-17 18:45:31 +08:00
try {
2019-12-18 14:43:32 +08:00
FlvRecorder : : Ptr * record = ( FlvRecorder : : Ptr * ) ( ctx ) ;
2019-12-27 13:56:02 +08:00
( * record ) - > startRecord ( EventPollerPool : : Instance ( ) . getPoller ( ) , vhost , app , stream , file_path ) ;
2019-12-17 18:45:31 +08:00
return 0 ;
} catch ( std : : exception & ex ) {
WarnL < < ex . what ( ) ;
return - 1 ;
}
2020-04-05 09:26:29 +08:00
}
2024-09-19 14:53:50 +08:00
// /////////////////////////////////////////hls/mp4录制///////////////////////////////////////////// [AUTO-TRANSLATED:99c61c68]
// /////////////////////////////////////////hls/mp4 recording/////////////////////////////////////////////
2022-06-11 14:18:55 +08:00
static inline bool isRecording ( Recorder : : type type , const string & vhost , const string & app , const string & stream_id ) {
auto src = MediaSource : : find ( vhost , app , stream_id ) ;
if ( ! src ) {
return false ;
}
return src - > isRecording ( type ) ;
}
2023-07-08 22:12:56 +08:00
static inline bool startRecord ( Recorder : : type type , const string & vhost , const string & app , const string & stream_id , const string & customized_path , size_t max_second ) {
2022-06-11 14:18:55 +08:00
auto src = MediaSource : : find ( vhost , app , stream_id ) ;
if ( ! src ) {
WarnL < < " 未找到相关的MediaSource,startRecord失败: " < < vhost < < " / " < < app < < " / " < < stream_id ;
return false ;
}
2023-07-08 22:12:56 +08:00
bool ret ;
src - > getOwnerPoller ( ) - > sync ( [ & ] ( ) { ret = src - > setupRecord ( type , true , customized_path , max_second ) ; } ) ;
return ret ;
2022-06-11 14:18:55 +08:00
}
2023-07-08 22:12:56 +08:00
static inline bool stopRecord ( Recorder : : type type , const string & vhost , const string & app , const string & stream_id ) {
2022-06-11 14:18:55 +08:00
auto src = MediaSource : : find ( vhost , app , stream_id ) ;
2023-07-08 22:12:56 +08:00
if ( ! src ) {
2022-06-11 14:18:55 +08:00
return false ;
}
2023-07-08 22:12:56 +08:00
bool ret ;
src - > getOwnerPoller ( ) - > sync ( [ & ] ( ) { ret = src - > setupRecord ( type , false , " " , 0 ) ; } ) ;
return ret ;
2022-06-11 14:18:55 +08:00
}
2020-04-05 09:26:29 +08:00
API_EXPORT int API_CALL mk_recorder_is_recording ( int type , const char * vhost , const char * app , const char * stream ) {
assert ( vhost & & app & & stream ) ;
2022-06-11 14:18:55 +08:00
return isRecording ( ( Recorder : : type ) type , vhost , app , stream ) ;
2020-04-05 09:26:29 +08:00
}
2021-03-07 10:41:57 +08:00
API_EXPORT int API_CALL mk_recorder_start ( int type , const char * vhost , const char * app , const char * stream , const char * customized_path , size_t max_second ) {
2020-04-05 09:26:29 +08:00
assert ( vhost & & app & & stream ) ;
2022-06-11 14:18:55 +08:00
return startRecord ( ( Recorder : : type ) type , vhost , app , stream , customized_path ? customized_path : " " , max_second ) ;
2020-04-05 09:26:29 +08:00
}
API_EXPORT int API_CALL mk_recorder_stop ( int type , const char * vhost , const char * app , const char * stream ) {
assert ( vhost & & app & & stream ) ;
2022-06-11 14:18:55 +08:00
return stopRecord ( ( Recorder : : type ) type , vhost , app , stream ) ;
2020-04-05 09:26:29 +08:00
}
2024-10-18 15:22:29 +08:00
# if ENABLE_MP4
API_EXPORT void API_CALL mk_player_load_mp4_file ( const char * vhost , const char * app , const char * stream , const char * file_path , int file_repeat ) {
assert ( vhost & & app & & stream & & file_path ) ;
ProtocolOption option ;
// mp4支持多track [AUTO-TRANSLATED:b9688762]
// mp4 supports multiple tracks
option . max_track = 16 ;
// 默认解复用mp4不生成mp4 [AUTO-TRANSLATED:11f2dcee]
// By default, demultiplexing mp4 does not generate mp4
option . enable_mp4 = false ;
// 但是如果参数明确指定开启mp4, 那么也允许之 [AUTO-TRANSLATED:b143a9e3]
// But if the parameter explicitly specifies to enable mp4, then it is also allowed
// 强制无人观看时自动关闭 [AUTO-TRANSLATED:f7c85948]
// Force automatic shutdown when no one is watching
option . auto_close = true ;
MediaTuple tuple = { vhost , app , stream , " " } ;
auto reader = std : : make_shared < MP4Reader > ( tuple , file_path , option ) ;
// sample_ms设置为0, 从配置文件加载; file_repeat可以指定, 如果配置文件也指定循环解复用, 那么强制开启 [AUTO-TRANSLATED:23e826b4]
// sample_ms is set to 0, loaded from the configuration file; file_repeat can be specified, if the configuration file also specifies loop demultiplexing,
// then force it to be enabled
reader - > startReadMP4 ( 0 , true , file_repeat ) ;
}
API_EXPORT void API_CALL mk_player_load_mp4_file2 ( const char * vhost , const char * app , const char * stream , const char * file_path , int file_repeat , mk_ini ini ) {
assert ( vhost & & app & & stream & & file_path ) ;
ProtocolOption option ( * ( ( mINI * ) ini ) ) ;
// mp4支持多track [AUTO-TRANSLATED:b9688762]
// mp4 supports multiple tracks
option . max_track = 16 ;
// 默认解复用mp4不生成mp4 [AUTO-TRANSLATED:11f2dcee]
// By default, demultiplexing mp4 does not generate mp4
option . enable_mp4 = false ;
// 但是如果参数明确指定开启mp4, 那么也允许之 [AUTO-TRANSLATED:b143a9e3]
// But if the parameter explicitly specifies to enable mp4, then it is also allowed
// 强制无人观看时自动关闭 [AUTO-TRANSLATED:f7c85948]
// Force automatic shutdown when no one is watching
option . auto_close = true ;
MediaTuple tuple = { vhost , app , stream , " " } ;
auto reader = std : : make_shared < MP4Reader > ( tuple , file_path , option ) ;
// sample_ms设置为0, 从配置文件加载; file_repeat可以指定, 如果配置文件也指定循环解复用, 那么强制开启 [AUTO-TRANSLATED:23e826b4]
// sample_ms is set to 0, loaded from the configuration file; file_repeat can be specified, if the configuration file also specifies loop demultiplexing,
// then force it to be enabled
reader - > startReadMP4 ( 0 , true , file_repeat ) ;
}
# endif