mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
优化hls生成
This commit is contained in:
parent
7f203ce9b7
commit
c4aaaa11c7
@ -35,16 +35,6 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
|
||||
//克隆Track,只拷贝其数据,不拷贝其数据转发关系
|
||||
auto track = track_in->clone();
|
||||
|
||||
weak_ptr<MediaSink> weakSelf = shared_from_this();
|
||||
track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([weakSelf](const Frame::Ptr &frame){
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
if(!strongSelf->_anyTrackUnReady){
|
||||
strongSelf->onTrackFrame(frame);
|
||||
}
|
||||
}));
|
||||
auto codec_id = track->getCodecId();
|
||||
_track_map[codec_id] = track;
|
||||
auto lam = [this,track](){
|
||||
@ -58,6 +48,17 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
|
||||
_trackReadyCallback[codec_id] = lam;
|
||||
_ticker.resetTime();
|
||||
}
|
||||
|
||||
weak_ptr<MediaSink> weakSelf = shared_from_this();
|
||||
track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([weakSelf](const Frame::Ptr &frame){
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
if(!strongSelf->_anyTrackUnReady){
|
||||
strongSelf->onTrackFrame(frame);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void MediaSink::resetTracks() {
|
||||
|
@ -43,11 +43,6 @@ void HlsMaker::makeIndexFile(bool eof) {
|
||||
char file_content[1024];
|
||||
int maxSegmentDuration = 0;
|
||||
|
||||
//停止写之后将最后的片段也写进m3u8文件中
|
||||
if (eof && _stampInc > 0) {
|
||||
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
|
||||
}
|
||||
|
||||
for (auto &tp : _seg_dur_list) {
|
||||
int dur = std::get<0>(tp);
|
||||
if (dur > maxSegmentDuration) {
|
||||
@ -83,18 +78,16 @@ void HlsMaker::makeIndexFile(bool eof) {
|
||||
void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) {
|
||||
//分片数据中断结束
|
||||
if (data && len) {
|
||||
addNewFile(timestamp);
|
||||
onWriteFile((char *) data, len);
|
||||
addNewSegment(timestamp);
|
||||
onWriteSegment((char *) data, len);
|
||||
//记录上次写入数据时间
|
||||
_ticker_last_data.resetTime();
|
||||
} else {
|
||||
_noData = true;
|
||||
_stampInc = _ticker.elapsedTime();
|
||||
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
|
||||
delOldFile();
|
||||
makeIndexFile();
|
||||
flushLastSegment(true);
|
||||
}
|
||||
}
|
||||
|
||||
void HlsMaker::delOldFile() {
|
||||
void HlsMaker::delOldSegment() {
|
||||
if(_seg_number == 0){
|
||||
//如果设置为保留0个切片,则认为是保存为点播
|
||||
return;
|
||||
@ -106,28 +99,38 @@ void HlsMaker::delOldFile() {
|
||||
|
||||
//但是实际保存的切片个数比m3u8所述多两个,这样做的目的是防止播放器在切片删除前能下载完毕
|
||||
if (_file_index >= _seg_number + 4) {
|
||||
onDelFile(_file_index - _seg_number - 4);
|
||||
onDelSegment(_file_index - _seg_number - 4);
|
||||
}
|
||||
}
|
||||
|
||||
void HlsMaker::addNewFile(uint32_t) {
|
||||
//上次分片数据中断结束,重置时间避免中途的等待
|
||||
if (_noData) {
|
||||
_ticker.resetTime();
|
||||
_last_file_name = onOpenFile(_file_index++);
|
||||
_noData = false;
|
||||
void HlsMaker::addNewSegment(uint32_t) {
|
||||
if(!_last_file_name.empty() && _ticker.elapsedTime() < _seg_duration * 1000){
|
||||
//存在上个切片,并且未到分片时间
|
||||
return;
|
||||
}
|
||||
_stampInc = _ticker.elapsedTime();
|
||||
if (_file_index == 0 || _stampInc >= _seg_duration * 1000) {
|
||||
_ticker.resetTime();
|
||||
auto file_name = onOpenFile(_file_index);
|
||||
if (_file_index++ > 0) {
|
||||
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
|
||||
delOldFile();
|
||||
makeIndexFile();
|
||||
}
|
||||
_last_file_name = file_name;
|
||||
|
||||
//关闭并保存上一个切片
|
||||
flushLastSegment();
|
||||
//新增切片
|
||||
_last_file_name = onOpenSegment(_file_index++);
|
||||
//重置切片计时器
|
||||
_ticker.resetTime();
|
||||
}
|
||||
|
||||
void HlsMaker::flushLastSegment(bool eof){
|
||||
if(_last_file_name.empty()){
|
||||
//不存在上个切片
|
||||
return;
|
||||
}
|
||||
//文件创建到最后一次数据写入的时间即为切片长度
|
||||
auto seg_dur = _ticker.elapsedTime() - _ticker_last_data.elapsedTime();
|
||||
if(seg_dur <= 0){
|
||||
seg_dur = 100;
|
||||
}
|
||||
_seg_dur_list.push_back(std::make_tuple(seg_dur, _last_file_name));
|
||||
delOldSegment();
|
||||
makeIndexFile(eof);
|
||||
_last_file_name.clear();
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
@ -60,20 +60,20 @@ protected:
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
virtual string onOpenFile(int index) = 0;
|
||||
virtual string onOpenSegment(int index) = 0;
|
||||
|
||||
/**
|
||||
* 删除ts切片文件回调
|
||||
* @param index
|
||||
*/
|
||||
virtual void onDelFile(int index) = 0;
|
||||
virtual void onDelSegment(int index) = 0;
|
||||
|
||||
/**
|
||||
* 写ts切片文件回调
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
virtual void onWriteFile(const char *data, int len) = 0;
|
||||
virtual void onWriteSegment(const char *data, int len) = 0;
|
||||
|
||||
/**
|
||||
* 写m3u8文件回调
|
||||
@ -82,21 +82,34 @@ protected:
|
||||
*/
|
||||
virtual void onWriteHls(const char *data, int len) = 0;
|
||||
|
||||
/**
|
||||
* 关闭上个ts切片并且写入m3u8索引
|
||||
* @param eof
|
||||
*/
|
||||
void flushLastSegment(bool eof = false);
|
||||
private:
|
||||
/**
|
||||
* 生成m3u8文件
|
||||
* @param eof true代表点播
|
||||
*/
|
||||
void makeIndexFile(bool eof = false);
|
||||
void delOldFile();
|
||||
void addNewFile(uint32_t timestamp);
|
||||
protected:
|
||||
uint32_t _seg_number = 0;
|
||||
|
||||
/**
|
||||
* 删除旧的ts切片
|
||||
*/
|
||||
void delOldSegment();
|
||||
|
||||
/**
|
||||
* 添加新的ts切片
|
||||
* @param timestamp
|
||||
*/
|
||||
void addNewSegment(uint32_t timestamp);
|
||||
private:
|
||||
bool _noData = false;
|
||||
int _stampInc = 0;
|
||||
uint32_t _seg_number = 0;
|
||||
float _seg_duration = 0;
|
||||
uint64_t _file_index = 0;
|
||||
Ticker _ticker;
|
||||
Ticker _ticker_last_data;
|
||||
string _last_file_name;
|
||||
std::deque<tuple<int,string> > _seg_dur_list;
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
|
||||
_path_hls = m3u8_file;
|
||||
_params = params;
|
||||
_buf_size = bufSize;
|
||||
_is_vod = seg_number == 0;
|
||||
_file_buf.reset(new char[bufSize],[](char *ptr){
|
||||
delete[] ptr;
|
||||
});
|
||||
@ -47,14 +48,14 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
|
||||
|
||||
HlsMakerImp::~HlsMakerImp() {
|
||||
//录制完了
|
||||
makeIndexFile(true);
|
||||
if(_seg_number){
|
||||
flushLastSegment(true);
|
||||
if(!_is_vod){
|
||||
//hls直播才删除文件
|
||||
File::delete_file(_path_prefix.data());
|
||||
}
|
||||
}
|
||||
|
||||
string HlsMakerImp::onOpenFile(int index) {
|
||||
string HlsMakerImp::onOpenSegment(int index) {
|
||||
auto full_path = fullPath(index);
|
||||
_file = makeFile(full_path, true);
|
||||
if(!_file){
|
||||
@ -67,12 +68,12 @@ string HlsMakerImp::onOpenFile(int index) {
|
||||
return StrPrinter << index << ".ts" << "?" << _params;
|
||||
}
|
||||
|
||||
void HlsMakerImp::onDelFile(int index) {
|
||||
void HlsMakerImp::onDelSegment(int index) {
|
||||
//WarnL << index;
|
||||
File::delete_file(fullPath(index).data());
|
||||
}
|
||||
|
||||
void HlsMakerImp::onWriteFile(const char *data, int len) {
|
||||
void HlsMakerImp::onWriteSegment(const char *data, int len) {
|
||||
if (_file) {
|
||||
fwrite(data, len, 1, _file.get());
|
||||
}
|
||||
|
@ -44,9 +44,9 @@ public:
|
||||
uint32_t seg_number = 3);
|
||||
virtual ~HlsMakerImp();
|
||||
protected:
|
||||
string onOpenFile(int index) override ;
|
||||
void onDelFile(int index) override;
|
||||
void onWriteFile(const char *data, int len) override;
|
||||
string onOpenSegment(int index) override ;
|
||||
void onDelSegment(int index) override;
|
||||
void onWriteSegment(const char *data, int len) override;
|
||||
void onWriteHls(const char *data, int len) override;
|
||||
private:
|
||||
string fullPath(int index);
|
||||
@ -58,6 +58,8 @@ private:
|
||||
string _path_hls;
|
||||
string _params;
|
||||
int _buf_size;
|
||||
//是否为点播
|
||||
bool _is_vod;
|
||||
};
|
||||
|
||||
}//namespace mediakit
|
||||
|
Loading…
Reference in New Issue
Block a user