mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-24 11:40:37 +08:00
Compare commits
1 Commits
546476ddfe
...
74445de679
Author | SHA1 | Date | |
---|---|---|---|
|
74445de679 |
@ -1 +1 @@
|
|||||||
Subproject commit 9e319b70557f3ece0372a0d05f31a6560292556a
|
Subproject commit 08c094ea14f259ecf0c356e6243cb47ee96ce292
|
@ -139,8 +139,8 @@ listen_ip=::
|
|||||||
fileBufSize=65536
|
fileBufSize=65536
|
||||||
#hls最大切片时间
|
#hls最大切片时间
|
||||||
segDur=2
|
segDur=2
|
||||||
#m3u8索引中,hls保留切片个数(实际保留切片个数+segRetain个)
|
#m3u8索引中,hls保留切片个数(实际保留切片个数大2~3个)
|
||||||
#如果设置为0,则不删除切片且m3u8文件全量记录切片列表
|
#如果设置为0,则不删除切片,而是保存为点播
|
||||||
segNum=3
|
segNum=3
|
||||||
#HLS切片延迟个数,大于0将生成hls_delay.m3u8文件,0则不生成
|
#HLS切片延迟个数,大于0将生成hls_delay.m3u8文件,0则不生成
|
||||||
segDelay=0
|
segDelay=0
|
||||||
@ -150,8 +150,10 @@ segRetain=5
|
|||||||
broadcastRecordTs=0
|
broadcastRecordTs=0
|
||||||
#直播hls文件删除延时,单位秒,issue: #913
|
#直播hls文件删除延时,单位秒,issue: #913
|
||||||
deleteDelaySec=10
|
deleteDelaySec=10
|
||||||
#此选项开启后m3u8文件还是表现为直播,但是切片文件会被全部保留为点播用
|
#是否保留hls文件,此功能部分等效于segNum=0的情况
|
||||||
#segDur设置为0或segKeep设置为1的情况下,每个切片文件夹下会生成一个vod.m3u8文件用于点播该时间段的录像
|
#不同的是这个保留不会在m3u8文件中体现
|
||||||
|
#0为不保留,不起作用
|
||||||
|
#1为保留,则不删除hls文件,如果开启此功能,注意磁盘大小,或者定期手动清理hls文件
|
||||||
segKeep=0
|
segKeep=0
|
||||||
#如果设置为1,则第一个切片长度强制设置为1个GOP。当GOP小于segDur,可以提高首屏速度
|
#如果设置为1,则第一个切片长度强制设置为1个GOP。当GOP小于segDur,可以提高首屏速度
|
||||||
fastRegister=0
|
fastRegister=0
|
||||||
|
@ -23,11 +23,7 @@
|
|||||||
|
|
||||||
INSTANCE_IMP(VideoStackManager)
|
INSTANCE_IMP(VideoStackManager)
|
||||||
|
|
||||||
Param::~Param() {
|
Param::~Param() { VideoStackManager::Instance().unrefChannel(id, width, height, pixfmt); }
|
||||||
auto strongChn= weak_chn.lock();
|
|
||||||
if (!strongChn) { return; }
|
|
||||||
VideoStackManager::Instance().unrefChannel(id, width, height, pixfmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
Channel::Channel(const std::string& id, int width, int height, AVPixelFormat pixfmt)
|
Channel::Channel(const std::string& id, int width, int height, AVPixelFormat pixfmt)
|
||||||
: _id(id), _width(width), _height(height), _pixfmt(pixfmt) {
|
: _id(id), _width(width), _height(height), _pixfmt(pixfmt) {
|
||||||
@ -282,8 +278,6 @@ void VideoStack::start() {
|
|||||||
|
|
||||||
_dev->inputYUV((char**)_buffer->get()->data, _buffer->get()->linesize, pts);
|
_dev->inputYUV((char**)_buffer->get()->data, _buffer->get()->linesize, pts);
|
||||||
pts += frameInterval;
|
pts += frameInterval;
|
||||||
} else {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -122,9 +122,9 @@ void HlsMaker::inputData(const char *data, size_t len, uint64_t timestamp, bool
|
|||||||
|
|
||||||
void HlsMaker::delOldSegment() {
|
void HlsMaker::delOldSegment() {
|
||||||
GET_CONFIG(uint32_t, segDelay, Hls::kSegmentDelay);
|
GET_CONFIG(uint32_t, segDelay, Hls::kSegmentDelay);
|
||||||
if (_seg_number == 0 || _seg_keep) {
|
if (_seg_number == 0) {
|
||||||
// 如果设置为保留0个切片,则认为是保存为点播;或者设置为一直保存,就不删除 [AUTO-TRANSLATED:5bf20108]
|
// 如果设置为保留0个切片,则认为是保存为点播 [AUTO-TRANSLATED:5bf20108]
|
||||||
// If set to keep 0 or all slices, it is considered to be saved as on-demand
|
// If set to keep 0 slices, it is considered to be saved as on-demand
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 在hls m3u8索引文件中,我们保存的切片个数跟_seg_number相关设置一致 [AUTO-TRANSLATED:b14b5b98]
|
// 在hls m3u8索引文件中,我们保存的切片个数跟_seg_number相关设置一致 [AUTO-TRANSLATED:b14b5b98]
|
||||||
@ -132,6 +132,11 @@ void HlsMaker::delOldSegment() {
|
|||||||
if (_file_index > _seg_number + segDelay) {
|
if (_file_index > _seg_number + segDelay) {
|
||||||
_seg_dur_list.pop_front();
|
_seg_dur_list.pop_front();
|
||||||
}
|
}
|
||||||
|
// 如果设置为一直保存,就不删除 [AUTO-TRANSLATED:7c622e24]
|
||||||
|
// If set to always save, it will not be deleted
|
||||||
|
if (_seg_keep) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
GET_CONFIG(uint32_t, segRetain, Hls::kSegmentRetain);
|
GET_CONFIG(uint32_t, segRetain, Hls::kSegmentRetain);
|
||||||
// 但是实际保存的切片个数比m3u8所述多若干个,这样做的目的是防止播放器在切片删除前能下载完毕 [AUTO-TRANSLATED:1688f857]
|
// 但是实际保存的切片个数比m3u8所述多若干个,这样做的目的是防止播放器在切片删除前能下载完毕 [AUTO-TRANSLATED:1688f857]
|
||||||
// However, the actual number of slices saved is a few more than what is stated in the m3u8, this is done to prevent the player from downloading the slices before they are deleted
|
// However, the actual number of slices saved is a few more than what is stated in the m3u8, this is done to prevent the player from downloading the slices before they are deleted
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iomanip>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "HlsMakerImp.h"
|
#include "HlsMakerImp.h"
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
@ -50,10 +49,6 @@ HlsMakerImp::~HlsMakerImp() {
|
|||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
WarnL << ex.what();
|
WarnL << ex.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLive() || isKeep()) {
|
|
||||||
saveCurrentDir();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlsMakerImp::clearCache() {
|
void HlsMakerImp::clearCache() {
|
||||||
@ -104,66 +99,17 @@ void HlsMakerImp::clearCache(bool immediately, bool eof) {
|
|||||||
_segment_file_paths.clear();
|
_segment_file_paths.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 写入该目录的init.mp4文件以及m3u8文件 **/
|
|
||||||
void HlsMakerImp::saveCurrentDir() {
|
|
||||||
if (_current_dir.empty() || _current_dir_seg_list.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isFmp4()) {
|
|
||||||
// 写入init.mp4文件
|
|
||||||
File::saveFile(_current_dir_init_file, _path_prefix + "/" + _current_dir + "init.mp4");
|
|
||||||
}
|
|
||||||
|
|
||||||
int maxSegmentDuration = 0;
|
|
||||||
for (auto &tp : _current_dir_seg_list) {
|
|
||||||
int dur = std::get<0>(tp);
|
|
||||||
if (dur > maxSegmentDuration) {
|
|
||||||
maxSegmentDuration = dur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string index_str;
|
|
||||||
index_str.reserve(2048);
|
|
||||||
index_str += "#EXTM3U\n";
|
|
||||||
index_str += (isFmp4() ? "#EXT-X-VERSION:7\n" : "#EXT-X-VERSION:4\n");
|
|
||||||
index_str += "#EXT-X-ALLOW-CACHE:YES\n";
|
|
||||||
index_str += "#EXT-X-TARGETDURATION:" + std::to_string((maxSegmentDuration + 999) / 1000) + "\n";
|
|
||||||
index_str += "#EXT-X-MEDIA-SEQUENCE:0\n";
|
|
||||||
if (isFmp4()) {
|
|
||||||
index_str += "#EXT-X-MAP:URI=\"init.mp4\"\n";
|
|
||||||
}
|
|
||||||
stringstream ss;
|
|
||||||
for (auto &t : _current_dir_seg_list) {
|
|
||||||
ss << "#EXTINF:" << std::setprecision(3) << std::get<0>(t) / 1000.0 << ",\n" << std::get<1>(t) << "\n";
|
|
||||||
}
|
|
||||||
_current_dir_seg_list.clear();
|
|
||||||
index_str += ss.str();
|
|
||||||
index_str += "#EXT-X-ENDLIST\n";
|
|
||||||
|
|
||||||
/** 写入该目录的m3u8文件 **/
|
|
||||||
File::saveFile(index_str, _path_prefix + "/" + _current_dir + (isFmp4() ? "vod.fmp4.m3u8" : "vod.m3u8"));
|
|
||||||
}
|
|
||||||
|
|
||||||
string HlsMakerImp::onOpenSegment(uint64_t index) {
|
string HlsMakerImp::onOpenSegment(uint64_t index) {
|
||||||
string segment_name, segment_path;
|
string segment_name, segment_path;
|
||||||
{
|
{
|
||||||
auto strDate = getTimeStr("%Y-%m-%d");
|
auto strDate = getTimeStr("%Y-%m-%d");
|
||||||
auto strHour = getTimeStr("%H");
|
auto strHour = getTimeStr("%H");
|
||||||
auto strTime = getTimeStr("%M-%S");
|
auto strTime = getTimeStr("%M-%S");
|
||||||
auto current_dir = strDate + "/" + strHour + "/";
|
segment_name = StrPrinter << strDate + "/" + strHour + "/" + strTime << "_" << index << (isFmp4() ? ".mp4" : ".ts");
|
||||||
segment_name = current_dir + strTime + "_" + std::to_string(index) + (isFmp4() ? ".mp4" : ".ts");
|
|
||||||
segment_path = _path_prefix + "/" + segment_name;
|
segment_path = _path_prefix + "/" + segment_name;
|
||||||
if (isLive()) {
|
if (isLive()) {
|
||||||
// 直播
|
|
||||||
_segment_file_paths.emplace(index, segment_path);
|
_segment_file_paths.emplace(index, segment_path);
|
||||||
}
|
}
|
||||||
if (!isLive() || isKeep()) {
|
|
||||||
// 目录将发生变更,保留ts切片时,每个目录都生成一个m3u8文件
|
|
||||||
if (!_current_dir.empty() && current_dir != _current_dir) {
|
|
||||||
saveCurrentDir();
|
|
||||||
}
|
|
||||||
_current_dir = std::move(current_dir);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_file = makeFile(segment_path, true);
|
_file = makeFile(segment_path, true);
|
||||||
|
|
||||||
@ -193,14 +139,13 @@ void HlsMakerImp::onDelSegment(uint64_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HlsMakerImp::onWriteInitSegment(const char *data, size_t len) {
|
void HlsMakerImp::onWriteInitSegment(const char *data, size_t len) {
|
||||||
if (!isLive() || isKeep()) {
|
|
||||||
_current_dir_init_file.assign(data, len);
|
|
||||||
}
|
|
||||||
string init_seg_path = _path_prefix + "/init.mp4";
|
string init_seg_path = _path_prefix + "/init.mp4";
|
||||||
auto file = makeFile(init_seg_path);
|
_file = makeFile(init_seg_path);
|
||||||
if (file) {
|
|
||||||
fwrite(data, len, 1, file.get());
|
if (_file) {
|
||||||
|
fwrite(data, len, 1, _file.get());
|
||||||
_path_init = std::move(init_seg_path);
|
_path_init = std::move(init_seg_path);
|
||||||
|
_file = nullptr;
|
||||||
} else {
|
} else {
|
||||||
WarnL << "Create file failed," << init_seg_path << " " << get_uv_errmsg();
|
WarnL << "Create file failed," << init_seg_path << " " << get_uv_errmsg();
|
||||||
}
|
}
|
||||||
@ -233,9 +178,7 @@ void HlsMakerImp::onFlushLastSegment(uint64_t duration_ms) {
|
|||||||
// 关闭并flush文件到磁盘 [AUTO-TRANSLATED:9798ec4d]
|
// 关闭并flush文件到磁盘 [AUTO-TRANSLATED:9798ec4d]
|
||||||
// Close and flush file to disk
|
// Close and flush file to disk
|
||||||
_file = nullptr;
|
_file = nullptr;
|
||||||
if (!isLive() || isKeep()) {
|
|
||||||
_current_dir_seg_list.emplace_back(duration_ms, _info.file_name.erase(0, _current_dir.size()));
|
|
||||||
}
|
|
||||||
GET_CONFIG(bool, broadcastRecordTs, Hls::kBroadcastRecordTs);
|
GET_CONFIG(bool, broadcastRecordTs, Hls::kBroadcastRecordTs);
|
||||||
if (broadcastRecordTs) {
|
if (broadcastRecordTs) {
|
||||||
_info.time_len = duration_ms / 1000.0f;
|
_info.time_len = duration_ms / 1000.0f;
|
||||||
|
@ -63,7 +63,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
std::shared_ptr<FILE> makeFile(const std::string &file,bool setbuf = false);
|
std::shared_ptr<FILE> makeFile(const std::string &file,bool setbuf = false);
|
||||||
void clearCache(bool immediately, bool eof);
|
void clearCache(bool immediately, bool eof);
|
||||||
void saveCurrentDir();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _buf_size;
|
int _buf_size;
|
||||||
@ -72,15 +71,12 @@ private:
|
|||||||
std::string _path_hls_delay;
|
std::string _path_hls_delay;
|
||||||
std::string _path_init;
|
std::string _path_init;
|
||||||
std::string _path_prefix;
|
std::string _path_prefix;
|
||||||
std::string _current_dir;
|
|
||||||
std::string _current_dir_init_file;
|
|
||||||
RecordInfo _info;
|
RecordInfo _info;
|
||||||
std::shared_ptr<FILE> _file;
|
std::shared_ptr<FILE> _file;
|
||||||
std::shared_ptr<char> _file_buf;
|
std::shared_ptr<char> _file_buf;
|
||||||
HlsMediaSource::Ptr _media_src;
|
HlsMediaSource::Ptr _media_src;
|
||||||
toolkit::EventPoller::Ptr _poller;
|
toolkit::EventPoller::Ptr _poller;
|
||||||
std::map<uint64_t/*index*/,std::string/*file_path*/> _segment_file_paths;
|
std::map<uint64_t/*index*/,std::string/*file_path*/> _segment_file_paths;
|
||||||
std::deque<std::tuple<int,std::string> > _current_dir_seg_list;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
Loading…
Reference in New Issue
Block a user