优化hls生成

This commit is contained in:
xiongziliang 2019-10-12 10:29:40 +08:00
parent 7f203ce9b7
commit c4aaaa11c7
5 changed files with 77 additions and 57 deletions

View File

@ -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() {

View File

@ -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

View File

@ -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;
};

View File

@ -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());
}

View File

@ -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