Kyoo/transcoder/src/codec.go
2024-06-19 12:40:43 +00:00

123 lines
2.4 KiB
Go

package src
import (
"fmt"
"log"
"strings"
"gopkg.in/vansante/go-ffprobe.v2"
)
// 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
// and https://git.ffmpeg.org/gitweb/ffmpeg.git/blob/HEAD%3a/libavformat/hlsenc.c#l344
func GetMimeCodec(stream *ffprobe.Stream) *string {
switch stream.CodecName {
case "h264":
ret := "avc1"
switch strings.ToLower(stream.Profile) {
case "high":
ret += ".6400"
case "main":
ret += ".4D40"
case "baseline":
ret += ".42E0"
default:
// Default to constrained baseline if profile is invalid
ret += ".4240"
}
ret += fmt.Sprintf("%02x", stream.Level)
return &ret
case "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"
if stream.Profile == "main 10" {
ret += ".2.4"
} else {
ret += ".1.4"
}
ret += fmt.Sprintf(".L%02X.BO", stream.Level)
return &ret
case "av1":
// https://aomedia.org/av1/specification/annex-a/
// FORMAT: [codecTag].[profile].[level][tier].[bitDepth]
ret := "av01"
switch strings.ToLower(stream.Profile) {
case "main":
ret += ".0"
case "high":
ret += ".1"
case "professional":
ret += ".2"
default:
}
// not sure about this field, we want pixel bit depth
bitdepth := ParseUint(stream.BitsPerRawSample)
if bitdepth != 8 && bitdepth != 10 && bitdepth != 12 {
// Default to 8 bits
bitdepth = 8
}
tierflag := 'M'
ret += fmt.Sprintf(".%02X%c.%02d", stream.Level, tierflag, bitdepth)
return &ret
case "aac":
ret := "mp4a"
switch strings.ToLower(stream.Profile) {
case "he":
ret += ".40.5"
case "lc":
ret += ".40.2"
default:
ret += ".40.2"
}
return &ret
case "mp3":
ret := "mp4a.40.34"
return &ret
case "opus":
ret := "Opus"
return &ret
case "ac3":
ret := "mp4a.a5"
return &ret
case "eac3":
ret := "mp4a.a6"
return &ret
case "flac":
ret := "fLaC"
return &ret
case "alac":
ret := "alac"
return &ret
default:
log.Printf("No known mime format for: %s", stream.CodecName)
return nil
}
}