mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-02 05:04:15 -04:00
135 lines
2.9 KiB
Go
135 lines
2.9 KiB
Go
package src
|
|
|
|
import (
|
|
"cmp"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"github.com/zoriya/go-mediainfo"
|
|
)
|
|
|
|
// convert mediainfo to RFC 6381, waiting for either of those tickets to be resolved:
|
|
//
|
|
// https://sourceforge.net/p/mediainfo/feature-requests/499
|
|
// https://trac.ffmpeg.org/ticket/6617
|
|
//
|
|
// this code is addapted from https://github.com/jellyfin/jellyfin/blob/master/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
|
|
func GetMimeCodec(mi *mediainfo.File, kind mediainfo.StreamKind, i int) *string {
|
|
codec := cmp.Or(
|
|
mi.Parameter(kind, i, "InternetMediaType"),
|
|
mi.Parameter(kind, i, "Format"),
|
|
)
|
|
|
|
switch codec {
|
|
case "video/H264", "AVC":
|
|
ret := "avc1"
|
|
info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")
|
|
|
|
format := info[0]
|
|
switch format {
|
|
case "high":
|
|
ret += ".6400"
|
|
case "main":
|
|
ret += ".4D40"
|
|
case "baseline":
|
|
ret += ".42E0"
|
|
default:
|
|
// Default to constrained baseline if profile is invalid
|
|
ret += ".4240"
|
|
}
|
|
|
|
// level format is l3.1 for level 31
|
|
level := ParseFloat(info[1][1:])
|
|
ret += fmt.Sprintf("%02x", int(level*10))
|
|
return &ret
|
|
|
|
case "video/H265", "HEVC":
|
|
// The h265 syntax is a bit of a mystery at the time this comment was written.
|
|
// This is what I've found through various sources:
|
|
// FORMAT: [codecTag].[profile].[constraint?].L[level * 30].[UNKNOWN]
|
|
ret := "hvc1"
|
|
info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")
|
|
|
|
profile := info[0]
|
|
if profile == "main 10" {
|
|
ret += ".2.4"
|
|
} else {
|
|
ret += ".1.4"
|
|
}
|
|
|
|
level := ParseFloat(info[1][:1])
|
|
ret += fmt.Sprintf(".L%02X.BO", int(level*30))
|
|
return &ret
|
|
|
|
case "AV1":
|
|
// https://aomedia.org/av1/specification/annex-a/
|
|
// FORMAT: [codecTag].[profile].[level][tier].[bitDepth]
|
|
ret := "av01"
|
|
info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")
|
|
|
|
profile := info[0]
|
|
switch profile {
|
|
case "main":
|
|
ret += ".0"
|
|
case "high":
|
|
ret += ".1"
|
|
case "professional":
|
|
ret += ".2"
|
|
default:
|
|
// Default to Main
|
|
ret += ".0"
|
|
}
|
|
|
|
// level is not defined in mediainfo. using a default
|
|
// Default to the maximum defined level 6.3
|
|
level := 19
|
|
|
|
bitdepth := ParseUint(mi.Parameter(kind, i, "BitDepth"))
|
|
if bitdepth != 8 && bitdepth != 10 && bitdepth != 12 {
|
|
// Default to 8 bits
|
|
bitdepth = 8
|
|
}
|
|
|
|
tierflag := 'M'
|
|
ret += fmt.Sprintf(".%02X%c.%02d", level, tierflag, bitdepth)
|
|
|
|
return &ret
|
|
|
|
case "AAC":
|
|
ret := "mp4a"
|
|
|
|
profile := strings.ToLower(mi.Parameter(kind, i, "Format_AdditionalFeatures"))
|
|
switch profile {
|
|
case "he":
|
|
ret += ".40.5"
|
|
case "lc":
|
|
ret += ".40.2"
|
|
default:
|
|
ret += ".40.2"
|
|
}
|
|
|
|
return &ret
|
|
|
|
case "audio/opus", "Opus":
|
|
ret := "Opus"
|
|
return &ret
|
|
|
|
case "AC-3":
|
|
ret := "mp4a.a5"
|
|
return &ret
|
|
|
|
case "audio/eac3", "E-AC-3":
|
|
ret := "mp4a.a6"
|
|
return &ret
|
|
|
|
case "audio/x-flac", "FLAC":
|
|
ret := "fLaC"
|
|
return &ret
|
|
|
|
default:
|
|
log.Printf("No known mime format for: %s", codec)
|
|
return nil
|
|
}
|
|
}
|