Use cmap for infos

This commit is contained in:
Zoe Roux 2024-02-19 00:47:25 +01:00
parent 2afed432f7
commit f54a876636
5 changed files with 53 additions and 26 deletions

View File

@ -176,19 +176,20 @@ func (h *Handler) GetInfo(c echo.Context) error {
return err
}
route := GetRoute(c)
sha, err := src.GetHash(path)
if err != nil {
return err
}
ret, err := src.GetInfo(path)
ret, err := src.GetInfo(path, sha, route)
if err != nil {
return err
}
// Run extractors to have them in cache
src.Extract(ret.Path, sha)
src.Extract(ret.Path, sha, route)
go h.thumbnails.ExtractThumbnail(
ret.Path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
fmt.Sprintf("%s/thumbnails.png", route),
)
return c.JSON(http.StatusOK, ret)
}
@ -208,11 +209,12 @@ func (h *Handler) GetAttachment(c echo.Context) error {
return err
}
route := GetRoute(c)
sha, err := src.GetHash(path)
if err != nil {
return err
}
wait, err := src.Extract(path, sha)
wait, err := src.Extract(path, sha, route)
if err != nil {
return err
}
@ -237,11 +239,12 @@ func (h *Handler) GetSubtitle(c echo.Context) error {
return err
}
route := GetRoute(c)
sha, err := src.GetHash(path)
if err != nil {
return err
}
wait, err := src.Extract(path, sha)
wait, err := src.Extract(path, sha, route)
if err != nil {
return err
}
@ -264,7 +267,7 @@ func (h *Handler) GetThumbnails(c echo.Context) error {
out, err := h.thumbnails.ExtractThumbnail(
path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
fmt.Sprintf("%s/thumbnails.png", GetRoute(c)),
)
if err != nil {
return err
@ -287,7 +290,7 @@ func (h *Handler) GetThumbnailsVtt(c echo.Context) error {
out, err := h.thumbnails.ExtractThumbnail(
path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
fmt.Sprintf("%s/thumbnails.png", GetRoute(c)),
)
if err != nil {
return err

View File

@ -48,6 +48,13 @@ func (m *CMap[K, V]) GetOrSet(key K, val V) (V, bool) {
return m.GetOrCreate(key, func() V { return val })
}
func (m *CMap[K, V]) Set(key K, val V) {
m.lock.Lock()
defer m.lock.Unlock()
m.data[key] = val
}
func (m *CMap[K, V]) Remove(key K) {
m.lock.Lock()
defer m.lock.Unlock()

View File

@ -8,7 +8,7 @@ import (
var extracted = NewCMap[string, <-chan struct{}]()
func Extract(path string, sha string) (<-chan struct{}, error) {
func Extract(path string, sha string, route string) (<-chan struct{}, error) {
ret := make(chan struct{})
existing, created := extracted.GetOrSet(sha, ret)
if !created {
@ -16,7 +16,7 @@ func Extract(path string, sha string) (<-chan struct{}, error) {
}
go func() {
info, err := GetInfo(path)
info, err := GetInfo(path, sha, route)
if err != nil {
extracted.Remove(sha)
close(ret)

View File

@ -1,8 +1,6 @@
package src
import (
"crypto/sha1"
"encoding/hex"
"fmt"
"path/filepath"
"strconv"
@ -12,6 +10,8 @@ import (
)
type MediaInfo struct {
// closed if the mediainfo is ready for read. open otherwise
ready <-chan struct{}
// The sha1 of the video file.
Sha string `json:"sha"`
/// The internal path of the video file.
@ -173,7 +173,32 @@ var SubtitleExtensions = map[string]string{
"vtt": "vtt",
}
func GetInfo(path string) (*MediaInfo, error) {
var infos = NewCMap[string, *MediaInfo]()
func GetInfo(path string, sha string, route string) (*MediaInfo, error) {
var err error
ret, _ := infos.GetOrCreate(sha, func() *MediaInfo {
readyChan := make(chan struct{})
mi := &MediaInfo{
Sha: sha,
ready: readyChan,
}
go func() {
var val *MediaInfo
val, err = getInfo(path, route)
*mi = *val
mi.ready = readyChan
mi.Sha = sha
close(readyChan)
}()
return mi
})
<-ret.ready
return ret, err
}
func getInfo(path string, route string) (*MediaInfo, error) {
defer printExecTime("mediainfo for %s", path)()
mi, err := mediainfo.Open(path)
@ -182,17 +207,6 @@ func GetInfo(path string) (*MediaInfo, error) {
}
defer mi.Close()
sha := mi.Parameter(mediainfo.StreamGeneral, 0, "UniqueID")
// Remove dummy values that some tools use.
if len(sha) <= 5 {
date := mi.Parameter(mediainfo.StreamGeneral, 0, "File_Modified_Date")
h := sha1.New()
h.Write([]byte(path))
h.Write([]byte(date))
sha = hex.EncodeToString(h.Sum(nil))
}
chapters_begin := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_Begin"))
chapters_end := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_End"))
@ -204,7 +218,6 @@ func GetInfo(path string) (*MediaInfo, error) {
// fmt.Printf("%s", mi.Option("info_parameters", ""))
ret := MediaInfo{
Sha: sha,
Path: path,
// Remove leading .
Extension: filepath.Ext(path)[1:],
@ -248,7 +261,7 @@ func GetInfo(path string) (*MediaInfo, error) {
extension := OrNull(SubtitleExtensions[format])
var link *string
if extension != nil {
x := fmt.Sprintf("/video/%s/subtitle/%d.%s", sha, i, *extension)
x := fmt.Sprintf("%s/subtitle/%d.%s", route, i, *extension)
link = &x
}
return Subtitle{
@ -273,7 +286,7 @@ func GetInfo(path string) (*MediaInfo, error) {
Fonts: Map(
attachments,
func(font string, _ int) string {
return fmt.Sprintf("/video/%s/attachment/%s", sha, font)
return fmt.Sprintf("%s/attachment/%s", route, font)
}),
}
if len(ret.Videos) > 0 {

View File

@ -23,6 +23,10 @@ func GetPath(c echo.Context) (string, error) {
return key, nil
}
func GetRoute(c echo.Context) string {
return c.Request().Header.Get("X-Route")
}
func SanitizePath(path string) error {
if strings.Contains(path, "/") || strings.Contains(path, "..") {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid parameter. Can't contains path delimiters or ..")