mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-24 03:30:52 +08:00
Compare commits
7 Commits
0f408ccdaf
...
95905154ec
Author | SHA1 | Date | |
---|---|---|---|
|
95905154ec | ||
|
4c90a1a95b | ||
|
6fcf7f81a4 | ||
|
fdbf77d46d | ||
|
90bd28249e | ||
|
c3106d514a | ||
|
f03d414e82 |
@ -1 +1 @@
|
|||||||
Subproject commit 46231014e2a7ec1903d4a37e96222481ecc779d8
|
Subproject commit 08c094ea14f259ecf0c356e6243cb47ee96ce292
|
@ -12,6 +12,7 @@
|
|||||||
#define MK_RECORDER_API_H_
|
#define MK_RECORDER_API_H_
|
||||||
|
|
||||||
#include "mk_common.h"
|
#include "mk_common.h"
|
||||||
|
#include "mk_util.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -124,6 +125,18 @@ API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const cha
|
|||||||
*/
|
*/
|
||||||
API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream);
|
API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载mp4列表
|
||||||
|
* @param vhost 虚拟主机
|
||||||
|
* @param app app
|
||||||
|
* @param stream 流id
|
||||||
|
* @param file_path 文件路径
|
||||||
|
* @param file_repeat 循环解复用
|
||||||
|
* @param ini 配置
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_load_mp4_file(const char *vhost, const char *app, const char *stream, const char *file_path, int file_repeat);
|
||||||
|
API_EXPORT void API_CALL mk_load_mp4_file2(const char *vhost, const char *app, const char *stream, const char *file_path, int file_repeat, mk_ini ini);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "mk_recorder.h"
|
#include "mk_recorder.h"
|
||||||
#include "Rtmp/FlvMuxer.h"
|
#include "Rtmp/FlvMuxer.h"
|
||||||
#include "Record/Recorder.h"
|
#include "Record/Recorder.h"
|
||||||
|
#include "Record/MP4Reader.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
@ -83,3 +84,36 @@ API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char
|
|||||||
assert(vhost && app && stream);
|
assert(vhost && app && stream);
|
||||||
return stopRecord((Recorder::type)type,vhost,app,stream);
|
return stopRecord((Recorder::type)type,vhost,app,stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_load_mp4_file(const char *vhost, const char *app, const char *stream, const char *file_path, int file_repeat) {
|
||||||
|
mINI ini;
|
||||||
|
mk_load_mp4_file2(vhost, app, stream, file_path, file_repeat, (mk_ini)&ini);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_load_mp4_file2(const char *vhost, const char *app, const char *stream, const char *file_path, int file_repeat, mk_ini ini) {
|
||||||
|
#if ENABLE_MP4
|
||||||
|
assert(vhost && app && stream && file_path && ini);
|
||||||
|
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);
|
||||||
|
#else
|
||||||
|
WarnL << "MP4-related features are disabled. Please enable the ENABLE_MP4 macro and recompile.";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -25,13 +25,8 @@ RUN apt-get update && \
|
|||||||
ca-certificates \
|
ca-certificates \
|
||||||
tzdata \
|
tzdata \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libmysqlclient-dev \
|
|
||||||
libx264-dev \
|
|
||||||
libfaac-dev \
|
|
||||||
gcc \
|
gcc \
|
||||||
g++ \
|
g++ \
|
||||||
libavcodec-dev libavutil-dev libswscale-dev libresample-dev \
|
|
||||||
libsdl-dev libusrsctp-dev \
|
|
||||||
gdb && \
|
gdb && \
|
||||||
apt-get autoremove -y && \
|
apt-get autoremove -y && \
|
||||||
apt-get clean -y && \
|
apt-get clean -y && \
|
||||||
@ -69,13 +64,9 @@ RUN apt-get update && \
|
|||||||
tzdata \
|
tzdata \
|
||||||
curl \
|
curl \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libx264-dev \
|
|
||||||
libfaac-dev \
|
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
gcc \
|
gcc \
|
||||||
g++ \
|
g++ \
|
||||||
libavcodec-dev libavutil-dev libswscale-dev libresample-dev \
|
|
||||||
libsdl-dev libusrsctp-dev \
|
|
||||||
gdb && \
|
gdb && \
|
||||||
apt-get autoremove -y && \
|
apt-get autoremove -y && \
|
||||||
apt-get clean -y && \
|
apt-get clean -y && \
|
||||||
|
@ -114,12 +114,14 @@ void MediaSink::checkTrackIfReady() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待音频超时时间
|
// 等待音频超时时间 [AUTO-TRANSLATED:5ec16b26]
|
||||||
|
// Wait for audio timeout time
|
||||||
GET_CONFIG(uint32_t, kWaitAudioTrackDataMS, General::kWaitAudioTrackDataMS);
|
GET_CONFIG(uint32_t, kWaitAudioTrackDataMS, General::kWaitAudioTrackDataMS);
|
||||||
if (_max_track_size > 1) {
|
if (_max_track_size > 1) {
|
||||||
for (auto it = _track_map.begin(); it != _track_map.end();) {
|
for (auto it = _track_map.begin(); it != _track_map.end();) {
|
||||||
if (it->second.first->getTrackType() == TrackAudio && _ticker.elapsedTime() > kWaitAudioTrackDataMS && !it->second.second) {
|
if (it->second.first->getTrackType() == TrackAudio && _ticker.elapsedTime() > kWaitAudioTrackDataMS && !it->second.second) {
|
||||||
// 音频超时且完全没收到音频数据,忽略音频
|
// 音频超时且完全没收到音频数据,忽略音频 [AUTO-TRANSLATED:0d0fbb13]
|
||||||
|
// Audio timeout and did not receive any audio data, ignore audio
|
||||||
auto index = it->second.first->getIndex();
|
auto index = it->second.first->getIndex();
|
||||||
WarnL << "Audio track index " << index << " codec " << it->second.first->getCodecName() << " receive no data for long "
|
WarnL << "Audio track index " << index << " codec " << it->second.first->getCodecName() << " receive no data for long "
|
||||||
<< _ticker.elapsedTime() << "ms. Ignore it!";
|
<< _ticker.elapsedTime() << "ms. Ignore it!";
|
||||||
|
@ -122,12 +122,17 @@ private:
|
|||||||
std::list<std::pair<uint64_t, Frame::Ptr>> _cache;
|
std::list<std::pair<uint64_t, Frame::Ptr>> _cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, const vector<Track::Ptr> &tracks, Recorder::type type, const ProtocolOption &option){
|
std::shared_ptr<MediaSinkInterface> MultiMediaSourceMuxer::makeRecorder(MediaSource &sender, Recorder::type type) {
|
||||||
auto recorder = Recorder::createRecorder(type, sender.getMediaTuple(), option);
|
auto recorder = Recorder::createRecorder(type, sender.getMediaTuple(), _option);
|
||||||
for (auto &track : tracks) {
|
for (auto &track : getTracks()) {
|
||||||
recorder->addTrack(track);
|
recorder->addTrack(track);
|
||||||
}
|
}
|
||||||
recorder->addTrackCompleted();
|
recorder->addTrackCompleted();
|
||||||
|
if (_ring) {
|
||||||
|
_ring->flushGop([&](const Frame::Ptr &frame) {
|
||||||
|
recorder->inputFrame(frame);
|
||||||
|
});
|
||||||
|
}
|
||||||
return recorder;
|
return recorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +310,7 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
|||||||
// 开始录制 [AUTO-TRANSLATED:36d99250]
|
// 开始录制 [AUTO-TRANSLATED:36d99250]
|
||||||
// Start recording
|
// Start recording
|
||||||
_option.hls_save_path = custom_path;
|
_option.hls_save_path = custom_path;
|
||||||
auto hls = dynamic_pointer_cast<HlsRecorder>(makeRecorder(sender, getTracks(), type, _option));
|
auto hls = dynamic_pointer_cast<HlsRecorder>(makeRecorder(sender, type));
|
||||||
if (hls) {
|
if (hls) {
|
||||||
// 设置HlsMediaSource的事件监听器 [AUTO-TRANSLATED:69990c92]
|
// 设置HlsMediaSource的事件监听器 [AUTO-TRANSLATED:69990c92]
|
||||||
// Set the event listener for HlsMediaSource
|
// Set the event listener for HlsMediaSource
|
||||||
@ -325,7 +330,7 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
|||||||
// Start recording
|
// Start recording
|
||||||
_option.mp4_save_path = custom_path;
|
_option.mp4_save_path = custom_path;
|
||||||
_option.mp4_max_second = max_second;
|
_option.mp4_max_second = max_second;
|
||||||
_mp4 = makeRecorder(sender, getTracks(), type, _option);
|
_mp4 = makeRecorder(sender, type);
|
||||||
} else if (!start && _mp4) {
|
} else if (!start && _mp4) {
|
||||||
// 停止录制 [AUTO-TRANSLATED:3dee9292]
|
// 停止录制 [AUTO-TRANSLATED:3dee9292]
|
||||||
// Stop recording
|
// Stop recording
|
||||||
@ -338,7 +343,7 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
|||||||
// 开始录制 [AUTO-TRANSLATED:36d99250]
|
// 开始录制 [AUTO-TRANSLATED:36d99250]
|
||||||
// Start recording
|
// Start recording
|
||||||
_option.hls_save_path = custom_path;
|
_option.hls_save_path = custom_path;
|
||||||
auto hls = dynamic_pointer_cast<HlsFMP4Recorder>(makeRecorder(sender, getTracks(), type, _option));
|
auto hls = dynamic_pointer_cast<HlsFMP4Recorder>(makeRecorder(sender, type));
|
||||||
if (hls) {
|
if (hls) {
|
||||||
// 设置HlsMediaSource的事件监听器 [AUTO-TRANSLATED:69990c92]
|
// 设置HlsMediaSource的事件监听器 [AUTO-TRANSLATED:69990c92]
|
||||||
// Set the event listener for HlsMediaSource
|
// Set the event listener for HlsMediaSource
|
||||||
@ -354,7 +359,7 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
|||||||
}
|
}
|
||||||
case Recorder::type_fmp4: {
|
case Recorder::type_fmp4: {
|
||||||
if (start && !_fmp4) {
|
if (start && !_fmp4) {
|
||||||
auto fmp4 = dynamic_pointer_cast<FMP4MediaSourceMuxer>(makeRecorder(sender, getTracks(), type, _option));
|
auto fmp4 = dynamic_pointer_cast<FMP4MediaSourceMuxer>(makeRecorder(sender, type));
|
||||||
if (fmp4) {
|
if (fmp4) {
|
||||||
fmp4->setListener(shared_from_this());
|
fmp4->setListener(shared_from_this());
|
||||||
}
|
}
|
||||||
@ -366,7 +371,7 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
|||||||
}
|
}
|
||||||
case Recorder::type_ts: {
|
case Recorder::type_ts: {
|
||||||
if (start && !_ts) {
|
if (start && !_ts) {
|
||||||
auto ts = dynamic_pointer_cast<TSMediaSourceMuxer>(makeRecorder(sender, getTracks(), type, _option));
|
auto ts = dynamic_pointer_cast<TSMediaSourceMuxer>(makeRecorder(sender, type));
|
||||||
if (ts) {
|
if (ts) {
|
||||||
ts->setListener(shared_from_this());
|
ts->setListener(shared_from_this());
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void createGopCacheIfNeed();
|
void createGopCacheIfNeed();
|
||||||
|
std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, Recorder::type type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_enable = false;
|
bool _is_enable = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user