mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Perform hardware codec checks on separate go routine (#6414)
Warn if tests are taking a long time Add WaitDelay to try to kill process if hanging
This commit is contained in:
@@ -313,6 +313,7 @@ func (s *Manager) RefreshFFMpeg(ctx context.Context) {
|
|||||||
s.FFMpeg = ffmpeg.NewEncoder(ffmpegPath)
|
s.FFMpeg = ffmpeg.NewEncoder(ffmpegPath)
|
||||||
s.FFProbe = ffmpeg.NewFFProbe(ffprobePath)
|
s.FFProbe = ffmpeg.NewFFProbe(ffprobePath)
|
||||||
|
|
||||||
s.FFMpeg.InitHWSupport(ctx)
|
// initialise hardware support with background context
|
||||||
|
s.FFMpeg.InitHWSupport(context.Background())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,32 @@ const minHeight int = 480
|
|||||||
|
|
||||||
// Tests all (given) hardware codec's
|
// Tests all (given) hardware codec's
|
||||||
func (f *FFMpeg) InitHWSupport(ctx context.Context) {
|
func (f *FFMpeg) InitHWSupport(ctx context.Context) {
|
||||||
|
// do the hardware codec tests in a separate goroutine to avoid blocking
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
f.initHWSupport(ctx)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// log if the initialization takes too long
|
||||||
|
const hwInitLogTimeoutSecondsDefault = 5
|
||||||
|
hwInitLogTimeoutSeconds := hwInitLogTimeoutSecondsDefault * time.Second
|
||||||
|
timer := time.NewTimer(hwInitLogTimeoutSeconds)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
logger.Warnf("[InitHWSupport] Hardware codec initialization is taking longer than %s...", hwInitLogTimeoutSeconds)
|
||||||
|
logger.Info("[InitHWSupport] Hardware encoding will not be available until initialization is complete.")
|
||||||
|
case <-done:
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FFMpeg) initHWSupport(ctx context.Context) {
|
||||||
var hwCodecSupport []VideoCodec
|
var hwCodecSupport []VideoCodec
|
||||||
|
|
||||||
// Note that the first compatible codec is returned, so order is important
|
// Note that the first compatible codec is returned, so order is important
|
||||||
@@ -83,6 +109,7 @@ func (f *FFMpeg) InitHWSupport(ctx context.Context) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
cmd := f.Command(testCtx, args)
|
cmd := f.Command(testCtx, args)
|
||||||
|
cmd.WaitDelay = time.Second
|
||||||
logger.Tracef("[InitHWSupport] Testing codec %s: %v", codec, cmd.Args)
|
logger.Tracef("[InitHWSupport] Testing codec %s: %v", codec, cmd.Args)
|
||||||
|
|
||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
@@ -112,6 +139,8 @@ func (f *FFMpeg) InitHWSupport(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
logger.Info(outstr)
|
logger.Info(outstr)
|
||||||
|
|
||||||
|
f.hwCodecSupportMutex.Lock()
|
||||||
|
defer f.hwCodecSupportMutex.Unlock()
|
||||||
f.hwCodecSupport = hwCodecSupport
|
f.hwCodecSupport = hwCodecSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +440,7 @@ func (f *FFMpeg) hwMaxResFilter(toCodec VideoCodec, vf *models.VideoFile, reqHei
|
|||||||
|
|
||||||
// Return if a hardware accelerated for HLS is available
|
// Return if a hardware accelerated for HLS is available
|
||||||
func (f *FFMpeg) hwCodecHLSCompatible() *VideoCodec {
|
func (f *FFMpeg) hwCodecHLSCompatible() *VideoCodec {
|
||||||
for _, element := range f.hwCodecSupport {
|
for _, element := range f.getHWCodecSupport() {
|
||||||
switch element {
|
switch element {
|
||||||
case VideoCodecN264,
|
case VideoCodecN264,
|
||||||
VideoCodecN264H,
|
VideoCodecN264H,
|
||||||
@@ -429,7 +458,7 @@ func (f *FFMpeg) hwCodecHLSCompatible() *VideoCodec {
|
|||||||
|
|
||||||
// Return if a hardware accelerated codec for MP4 is available
|
// Return if a hardware accelerated codec for MP4 is available
|
||||||
func (f *FFMpeg) hwCodecMP4Compatible() *VideoCodec {
|
func (f *FFMpeg) hwCodecMP4Compatible() *VideoCodec {
|
||||||
for _, element := range f.hwCodecSupport {
|
for _, element := range f.getHWCodecSupport() {
|
||||||
switch element {
|
switch element {
|
||||||
case VideoCodecN264,
|
case VideoCodecN264,
|
||||||
VideoCodecN264H,
|
VideoCodecN264H,
|
||||||
@@ -445,7 +474,7 @@ func (f *FFMpeg) hwCodecMP4Compatible() *VideoCodec {
|
|||||||
|
|
||||||
// Return if a hardware accelerated codec for WebM is available
|
// Return if a hardware accelerated codec for WebM is available
|
||||||
func (f *FFMpeg) hwCodecWEBMCompatible() *VideoCodec {
|
func (f *FFMpeg) hwCodecWEBMCompatible() *VideoCodec {
|
||||||
for _, element := range f.hwCodecSupport {
|
for _, element := range f.getHWCodecSupport() {
|
||||||
switch element {
|
switch element {
|
||||||
case VideoCodecIVP9,
|
case VideoCodecIVP9,
|
||||||
VideoCodecVVP9:
|
VideoCodecVVP9:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
stashExec "github.com/stashapp/stash/pkg/exec"
|
stashExec "github.com/stashapp/stash/pkg/exec"
|
||||||
"github.com/stashapp/stash/pkg/fsutil"
|
"github.com/stashapp/stash/pkg/fsutil"
|
||||||
@@ -216,9 +217,10 @@ func (v Version) String() string {
|
|||||||
|
|
||||||
// FFMpeg provides an interface to ffmpeg.
|
// FFMpeg provides an interface to ffmpeg.
|
||||||
type FFMpeg struct {
|
type FFMpeg struct {
|
||||||
ffmpeg string
|
ffmpeg string
|
||||||
version Version
|
version Version
|
||||||
hwCodecSupport []VideoCodec
|
hwCodecSupport []VideoCodec
|
||||||
|
hwCodecSupportMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new FFMpeg encoder
|
// Creates a new FFMpeg encoder
|
||||||
@@ -241,3 +243,9 @@ func (f *FFMpeg) Command(ctx context.Context, args []string) *exec.Cmd {
|
|||||||
func (f *FFMpeg) Path() string {
|
func (f *FFMpeg) Path() string {
|
||||||
return f.ffmpeg
|
return f.ffmpeg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FFMpeg) getHWCodecSupport() []VideoCodec {
|
||||||
|
f.hwCodecSupportMutex.RLock()
|
||||||
|
defer f.hwCodecSupportMutex.RUnlock()
|
||||||
|
return f.hwCodecSupport
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user