mirror of https://github.com/gwuhaolin/livego.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
1.7 KiB
84 lines
1.7 KiB
package hls |
|
|
|
import ( |
|
"bytes" |
|
"container/list" |
|
"fmt" |
|
"sync" |
|
) |
|
|
|
const ( |
|
maxTSCacheNum = 3 |
|
) |
|
|
|
var ( |
|
ErrNoKey = fmt.Errorf("No key for cache") |
|
) |
|
|
|
type TSCacheItem struct { |
|
id string |
|
num int |
|
lock sync.RWMutex |
|
ll *list.List |
|
lm map[string]TSItem |
|
} |
|
|
|
func NewTSCacheItem(id string) *TSCacheItem { |
|
return &TSCacheItem{ |
|
id: id, |
|
ll: list.New(), |
|
num: maxTSCacheNum, |
|
lm: make(map[string]TSItem), |
|
} |
|
} |
|
|
|
func (tcCacheItem *TSCacheItem) ID() string { |
|
return tcCacheItem.id |
|
} |
|
|
|
// TODO: found data race, fix it |
|
func (tcCacheItem *TSCacheItem) GenM3U8PlayList() ([]byte, error) { |
|
var seq int |
|
var getSeq bool |
|
var maxDuration int |
|
m3u8body := bytes.NewBuffer(nil) |
|
for e := tcCacheItem.ll.Front(); e != nil; e = e.Next() { |
|
key := e.Value.(string) |
|
v, ok := tcCacheItem.lm[key] |
|
if ok { |
|
if v.Duration > maxDuration { |
|
maxDuration = v.Duration |
|
} |
|
if !getSeq { |
|
getSeq = true |
|
seq = v.SeqNum |
|
} |
|
fmt.Fprintf(m3u8body, "#EXTINF:%.3f,\n%s\n", float64(v.Duration)/float64(1000), v.Name) |
|
} |
|
} |
|
w := bytes.NewBuffer(nil) |
|
fmt.Fprintf(w, |
|
"#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-ALLOW-CACHE:NO\n#EXT-X-TARGETDURATION:%d\n#EXT-X-MEDIA-SEQUENCE:%d\n\n", |
|
maxDuration/1000+1, seq) |
|
w.Write(m3u8body.Bytes()) |
|
return w.Bytes(), nil |
|
} |
|
|
|
func (tcCacheItem *TSCacheItem) SetItem(key string, item TSItem) { |
|
if tcCacheItem.ll.Len() == tcCacheItem.num { |
|
e := tcCacheItem.ll.Front() |
|
tcCacheItem.ll.Remove(e) |
|
k := e.Value.(string) |
|
delete(tcCacheItem.lm, k) |
|
} |
|
tcCacheItem.lm[key] = item |
|
tcCacheItem.ll.PushBack(key) |
|
} |
|
|
|
func (tcCacheItem *TSCacheItem) GetItem(key string) (TSItem, error) { |
|
item, ok := tcCacheItem.lm[key] |
|
if !ok { |
|
return item, ErrNoKey |
|
} |
|
return item, nil |
|
}
|
|
|