github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/media/storageStreamHLS.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package media 20 21 import ( 22 "sort" 23 "strconv" 24 "time" 25 26 "github.com/deepch/vdk/av" 27 ) 28 29 // StreamHLSAdd add hls seq to buffer 30 func (obj *StorageST) StreamHLSAdd(uuid string, channelID string, val []*av.Packet, dur time.Duration) { 31 obj.mutex.Lock() 32 defer obj.mutex.Unlock() 33 if tmp, ok := obj.Streams[uuid]; ok { 34 if channelTmp, ok := tmp.Channels[channelID]; ok { 35 channelTmp.hlsSegmentNumber++ 36 channelTmp.hlsSegmentBuffer[channelTmp.hlsSegmentNumber] = SegmentOld{data: val, dur: dur} 37 if len(channelTmp.hlsSegmentBuffer) >= 6 { 38 delete(channelTmp.hlsSegmentBuffer, channelTmp.hlsSegmentNumber-6-1) 39 } 40 tmp.Channels[channelID] = channelTmp 41 obj.Streams[uuid] = tmp 42 } 43 } 44 } 45 46 // StreamHLSm3u8 get hls m3u8 list 47 func (obj *StorageST) StreamHLSm3u8(uuid string, channelID string) (string, int, error) { 48 obj.mutex.RLock() 49 defer obj.mutex.RUnlock() 50 if tmp, ok := obj.Streams[uuid]; ok { 51 if channelTmp, ok := tmp.Channels[channelID]; ok { 52 var out string 53 //TODO fix it 54 out += "#EXTM3U\r\n#EXT-X-TARGETDURATION:4\r\n#EXT-X-VERSION:4\r\n#EXT-X-MEDIA-SEQUENCE:" + strconv.Itoa(channelTmp.hlsSegmentNumber) + "\r\n" 55 var keys []int 56 for k := range channelTmp.hlsSegmentBuffer { 57 keys = append(keys, k) 58 } 59 sort.Ints(keys) 60 var count int 61 for _, i := range keys { 62 count++ 63 out += "#EXTINF:" + strconv.FormatFloat(channelTmp.hlsSegmentBuffer[i].dur.Seconds(), 'f', 1, 64) + ",\r\nsegment/" + strconv.Itoa(i) + "/file.ts\r\n" 64 65 } 66 return out, count, nil 67 } 68 } 69 return "", 0, ErrorStreamNotFound 70 } 71 72 // StreamHLSTS send hls segment buffer to clients 73 func (obj *StorageST) StreamHLSTS(uuid string, channelID string, seq int) ([]*av.Packet, error) { 74 obj.mutex.RLock() 75 defer obj.mutex.RUnlock() 76 if tmp, ok := obj.Streams[uuid]; ok { 77 if channelTmp, ok := tmp.Channels[channelID]; ok { 78 if tmp, ok := channelTmp.hlsSegmentBuffer[seq]; ok { 79 return tmp.data, nil 80 } 81 } 82 } 83 return nil, ErrorStreamNotFound 84 } 85 86 // StreamHLSFlush delete hls cache 87 func (obj *StorageST) StreamHLSFlush(uuid string, channelID string) { 88 obj.mutex.Lock() 89 defer obj.mutex.Unlock() 90 if tmp, ok := obj.Streams[uuid]; ok { 91 if channelTmp, ok := tmp.Channels[channelID]; ok { 92 channelTmp.hlsSegmentBuffer = make(map[int]SegmentOld) 93 channelTmp.hlsSegmentNumber = 0 94 tmp.Channels[channelID] = channelTmp 95 obj.Streams[uuid] = tmp 96 } 97 } 98 }