mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
Fix no resize transcode of 10bits items with hwaccel (#793)
This commit is contained in:
parent
401f1b5bc4
commit
f522a42560
@ -12,7 +12,7 @@ func DetectHardwareAccel() HwAccelT {
|
|||||||
}
|
}
|
||||||
log.Printf("Using hardware acceleration: %s", name)
|
log.Printf("Using hardware acceleration: %s", name)
|
||||||
|
|
||||||
// superfast or ultrafast would produce a file extremly big so we prever to ignore them. Fast is available on all hw accel modes
|
// superfast or ultrafast would produce a file extremely big so we prefer to ignore them. Fast is available on all hwaccel modes
|
||||||
// so we use that by default.
|
// so we use that by default.
|
||||||
// vaapi does not have any presets so this flag is unused for vaapi hwaccel.
|
// vaapi does not have any presets so this flag is unused for vaapi hwaccel.
|
||||||
preset := GetEnvOr("GOCODER_PRESET", "fast")
|
preset := GetEnvOr("GOCODER_PRESET", "fast")
|
||||||
@ -25,9 +25,9 @@ func DetectHardwareAccel() HwAccelT {
|
|||||||
EncodeFlags: []string{
|
EncodeFlags: []string{
|
||||||
"-c:v", "libx264",
|
"-c:v", "libx264",
|
||||||
"-preset", preset,
|
"-preset", preset,
|
||||||
// sc_threshold is a scene detection mechanisum used to create a keyframe when the scene changes
|
// sc_threshold is a scene detection mechanism used to create a keyframe when the scene changes
|
||||||
// this is on by default and inserts keyframes where we don't want to (it also breaks force_key_frames)
|
// this is on by default and inserts keyframes where we don't want to (it also breaks force_key_frames)
|
||||||
// we disable it to prevents whole scenes from behing removed due to the -f segment failing to find the corresonding keyframe
|
// we disable it to prevents whole scenes from being removed due to the -f segment failing to find the corresponding keyframe
|
||||||
"-sc_threshold", "0",
|
"-sc_threshold", "0",
|
||||||
// force 8bits output (by default it keeps the same as the source but 10bits is not playable on some devices)
|
// force 8bits output (by default it keeps the same as the source but 10bits is not playable on some devices)
|
||||||
"-pix_fmt", "yuv420p",
|
"-pix_fmt", "yuv420p",
|
||||||
@ -53,16 +53,23 @@ func DetectHardwareAccel() HwAccelT {
|
|||||||
// see https://trac.ffmpeg.org/wiki/Hardware/VAAPI#Encoding for more info
|
// see https://trac.ffmpeg.org/wiki/Hardware/VAAPI#Encoding for more info
|
||||||
// we also need to force the format to be nv12 since 10bits is not supported via hwaccel.
|
// we also need to force the format to be nv12 since 10bits is not supported via hwaccel.
|
||||||
// this filter is equivalent to this pseudocode:
|
// this filter is equivalent to this pseudocode:
|
||||||
// if (vaapi) {
|
//
|
||||||
// hwupload, passthrough, keep vaapi as is
|
// if (format != nv12 && format != vaapi) {
|
||||||
// convert whatever to nv12 on GPU
|
// convert_to_nv12() (in cpu space, the format is invalid only if hw-decode failed)
|
||||||
|
// hwupload (send to gpu space)
|
||||||
|
// scale_to(width, height, output_format="nv12") (output format doesn't change since we are already in nv12)
|
||||||
// } else {
|
// } else {
|
||||||
// convert whatever to nv12 on CPU
|
// _format_has_nothing_to_do (do nothing since the format is already valid)
|
||||||
// hwupload to vaapi(nv12)
|
// _hwupload (the format is already a gpu space format so this is also a no-op)
|
||||||
// convert whatever to nv12 on GPU // scale_vaapi doesn't support passthrough option, so it has to make a copy
|
// scale_to(width, height, output_format="nv12") (if we are already in nv12 it's only a scale, otherwise it converts to it)
|
||||||
|
// note: nv12 is 8bit format while vaapi can be 10bits or anything else
|
||||||
// }
|
// }
|
||||||
// See https://www.reddit.com/r/ffmpeg/comments/1bqn60w/hardware_accelerated_decoding_without_hwdownload/ for more info
|
// See https://www.reddit.com/r/ffmpeg/comments/1bqn60w/hardware_accelerated_decoding_without_hwdownload/ for more info
|
||||||
ScaleFilter: "format=nv12|vaapi,hwupload,scale_vaapi=%d:%d:format=nv12",
|
ScaleFilter: "format=nv12|vaapi,hwupload,scale_vaapi=%d:%d:format=nv12",
|
||||||
|
// Exactly the same as above but without the scaling.
|
||||||
|
// Yes scale_vaapi is used to convert the format (the `format` filter will pick a format for
|
||||||
|
// the next filter so it doesn't work if there is no next filter).
|
||||||
|
NoResizeFilter: "format=nv12|vaapi,hwupload,scale_vaapi=format=nv12",
|
||||||
}
|
}
|
||||||
case "qsv", "intel":
|
case "qsv", "intel":
|
||||||
return HwAccelT{
|
return HwAccelT{
|
||||||
@ -77,7 +84,8 @@ func DetectHardwareAccel() HwAccelT {
|
|||||||
"-preset", preset,
|
"-preset", preset,
|
||||||
},
|
},
|
||||||
// see note on ScaleFilter of the vaapi HwAccel, this is the same filter but adapted to qsv
|
// see note on ScaleFilter of the vaapi HwAccel, this is the same filter but adapted to qsv
|
||||||
ScaleFilter: "format=nv12|qsv,hwupload,scale_qsv=%d:%d:format=nv12",
|
ScaleFilter: "format=nv12|qsv,hwupload,scale_qsv=%d:%d:format=nv12",
|
||||||
|
NoResizeFilter: "format=nv12|qsv,hwupload,scale_qsv=format=nv12",
|
||||||
}
|
}
|
||||||
case "nvidia":
|
case "nvidia":
|
||||||
return HwAccelT{
|
return HwAccelT{
|
||||||
@ -91,11 +99,12 @@ func DetectHardwareAccel() HwAccelT {
|
|||||||
EncodeFlags: []string{
|
EncodeFlags: []string{
|
||||||
"-c:v", "h264_nvenc",
|
"-c:v", "h264_nvenc",
|
||||||
"-preset", preset,
|
"-preset", preset,
|
||||||
// the exivalent of -sc_threshold on nvidia.
|
// the equivalent of -sc_threshold on nvidia.
|
||||||
"-no-scenecut", "1",
|
"-no-scenecut", "1",
|
||||||
},
|
},
|
||||||
// see note on ScaleFilter of the vaapi HwAccel, this is the same filter but adapted to cuda
|
// see note on ScaleFilter of the vaapi HwAccel, this is the same filter but adapted to cuda
|
||||||
ScaleFilter: "format=nv12|cuda,hwupload,scale_cuda=%d:%d:format=nv12",
|
ScaleFilter: "format=nv12|cuda,hwupload,scale_cuda=%d:%d:format=nv12",
|
||||||
|
NoResizeFilter: "format=nv12|cuda,hwupload,scale_cuda=format=nv12",
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Printf("No hardware accelerator named: %s", name)
|
log.Printf("No hardware accelerator named: %s", name)
|
||||||
|
@ -22,10 +22,11 @@ type SettingsT struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HwAccelT struct {
|
type HwAccelT struct {
|
||||||
Name string
|
Name string
|
||||||
DecodeFlags []string
|
DecodeFlags []string
|
||||||
EncodeFlags []string
|
EncodeFlags []string
|
||||||
ScaleFilter string
|
NoResizeFilter string
|
||||||
|
ScaleFilter string
|
||||||
}
|
}
|
||||||
|
|
||||||
var Settings = SettingsT{
|
var Settings = SettingsT{
|
||||||
|
@ -81,6 +81,8 @@ func (vs *VideoStream) getTranscodeArgs(segments string) []string {
|
|||||||
"-vf", fmt.Sprintf(Settings.HwAccel.ScaleFilter, width, vs.quality.Height()),
|
"-vf", fmt.Sprintf(Settings.HwAccel.ScaleFilter, width, vs.quality.Height()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
args = append(args, "-vf", Settings.HwAccel.NoResizeFilter)
|
||||||
|
|
||||||
// NoResize doesn't have bitrate info, fallback to a know quality higher or equal.
|
// NoResize doesn't have bitrate info, fallback to a know quality higher or equal.
|
||||||
for _, q := range Qualities {
|
for _, q := range Qualities {
|
||||||
if q.Height() >= vs.video.Height {
|
if q.Height() >= vs.video.Height {
|
||||||
@ -90,7 +92,7 @@ func (vs *VideoStream) getTranscodeArgs(segments string) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
args = append(args,
|
args = append(args,
|
||||||
// Even less sure but bufsize are 5x the avergae bitrate since the average bitrate is only
|
// Even less sure but bufsize are 5x the average bitrate since the average bitrate is only
|
||||||
// useful for hls segments.
|
// useful for hls segments.
|
||||||
"-bufsize", fmt.Sprint(quality.MaxBitrate()*5),
|
"-bufsize", fmt.Sprint(quality.MaxBitrate()*5),
|
||||||
"-b:v", fmt.Sprint(quality.AverageBitrate()),
|
"-b:v", fmt.Sprint(quality.AverageBitrate()),
|
||||||
@ -100,7 +102,7 @@ func (vs *VideoStream) getTranscodeArgs(segments string) []string {
|
|||||||
// without this option, some hardware encoders uses others i-frames and the -f segment can't cut at them.
|
// without this option, some hardware encoders uses others i-frames and the -f segment can't cut at them.
|
||||||
"-forced-idr", "1",
|
"-forced-idr", "1",
|
||||||
"-force_key_frames", segments,
|
"-force_key_frames", segments,
|
||||||
// make ffmpeg globaly less buggy
|
// make ffmpeg globally less buggy
|
||||||
"-strict", "-2",
|
"-strict", "-2",
|
||||||
)
|
)
|
||||||
return args
|
return args
|
||||||
|
Loading…
x
Reference in New Issue
Block a user