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  }