mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 00:13:46 +01:00
Add hardware codec support for rkmpp (#6182)
This commit is contained in:
parent
b4d148bdb0
commit
289b698598
1 changed files with 41 additions and 2 deletions
|
|
@ -29,6 +29,7 @@ var (
|
|||
VideoCodecIVP9 = makeVideoCodec("VP9 Intel Quick Sync Video (QSV)", "vp9_qsv")
|
||||
VideoCodecVVP9 = makeVideoCodec("VP9 VAAPI", "vp9_vaapi")
|
||||
VideoCodecVVPX = makeVideoCodec("VP8 VAAPI", "vp8_vaapi")
|
||||
VideoCodecRK264 = makeVideoCodec("H264 Rockchip MPP (rkmpp)", "h264_rkmpp")
|
||||
)
|
||||
|
||||
const minHeight int = 480
|
||||
|
|
@ -45,6 +46,7 @@ func (f *FFMpeg) InitHWSupport(ctx context.Context) {
|
|||
VideoCodecI264C,
|
||||
VideoCodecV264,
|
||||
VideoCodecR264,
|
||||
VideoCodecRK264,
|
||||
VideoCodecIVP9,
|
||||
VideoCodecVVP9,
|
||||
VideoCodecM264,
|
||||
|
|
@ -201,6 +203,19 @@ func (f *FFMpeg) hwDeviceInit(args Args, toCodec VideoCodec, fullhw bool) Args {
|
|||
args = append(args, "-init_hw_device")
|
||||
args = append(args, "videotoolbox=vt")
|
||||
}
|
||||
case VideoCodecRK264:
|
||||
// Rockchip: always create rkmpp device and make it the filter device, so
|
||||
// scale_rkrga and subsequent hwupload/hwmap operate in the right context.
|
||||
args = append(args, "-init_hw_device")
|
||||
args = append(args, "rkmpp=rk")
|
||||
args = append(args, "-filter_hw_device")
|
||||
args = append(args, "rk")
|
||||
if fullhw {
|
||||
args = append(args, "-hwaccel")
|
||||
args = append(args, "rkmpp")
|
||||
args = append(args, "-hwaccel_output_format")
|
||||
args = append(args, "drm_prime")
|
||||
}
|
||||
}
|
||||
|
||||
return args
|
||||
|
|
@ -233,6 +248,14 @@ func (f *FFMpeg) hwFilterInit(toCodec VideoCodec, fullhw bool) VideoFilter {
|
|||
videoFilter = videoFilter.Append("format=nv12")
|
||||
videoFilter = videoFilter.Append("hwupload")
|
||||
}
|
||||
case VideoCodecRK264:
|
||||
// For Rockchip full-hw, do NOT pre-map to rkrga here. scale_rkrga can
|
||||
// consume DRM_PRIME frames directly when filter_hw_device is set.
|
||||
// For non-fullhw, keep a sane software format.
|
||||
if !fullhw {
|
||||
videoFilter = videoFilter.Append("format=nv12")
|
||||
videoFilter = videoFilter.Append("hwupload")
|
||||
}
|
||||
}
|
||||
|
||||
return videoFilter
|
||||
|
|
@ -310,6 +333,9 @@ func (f *FFMpeg) hwApplyFullHWFilter(args VideoFilter, codec VideoCodec, fullhw
|
|||
if fullhw && f.version.Gteq(Version{major: 3, minor: 3}) { // Added in FFMpeg 3.3
|
||||
args = args.Append("scale_qsv=format=nv12")
|
||||
}
|
||||
case VideoCodecRK264:
|
||||
// For Rockchip, no extra mapping here. If there is no scale filter,
|
||||
// leave frames in DRM_PRIME for the encoder.
|
||||
}
|
||||
|
||||
return args
|
||||
|
|
@ -337,6 +363,14 @@ func (f *FFMpeg) hwApplyScaleTemplate(sargs string, codec VideoCodec, match []in
|
|||
}
|
||||
case VideoCodecM264:
|
||||
template = "scale_vt=$value"
|
||||
case VideoCodecRK264:
|
||||
// The original filter chain is a fallback for maximum compatibility:
|
||||
// "scale_rkrga=$value:format=nv12,hwdownload,format=nv12,hwupload"
|
||||
// It avoids hwmap(rkrga→rkmpp) failures (-38/-12) seen on some builds
|
||||
// by downloading the scaled frame to system RAM and re-uploading it.
|
||||
// The filter chain below uses a zero-copy approach, passing the hardware-scaled
|
||||
// frame directly to the encoder. This is more efficient but may be less stable.
|
||||
template = "scale_rkrga=$value"
|
||||
default:
|
||||
return VideoFilter(sargs)
|
||||
}
|
||||
|
|
@ -345,12 +379,15 @@ func (f *FFMpeg) hwApplyScaleTemplate(sargs string, codec VideoCodec, match []in
|
|||
isIntel := codec == VideoCodecI264 || codec == VideoCodecI264C || codec == VideoCodecIVP9
|
||||
// BUG: scale_vt doesn't call ff_scale_adjust_dimensions, thus cant accept negative size values
|
||||
isApple := codec == VideoCodecM264
|
||||
// Rockchip's scale_rkrga supports -1/-2; don't apply minus-one hack here.
|
||||
return VideoFilter(templateReplaceScale(sargs, template, match, vf, isIntel || isApple))
|
||||
}
|
||||
|
||||
// Returns the max resolution for a given codec, or a default
|
||||
func (f *FFMpeg) hwCodecMaxRes(codec VideoCodec) (int, int) {
|
||||
switch codec {
|
||||
case VideoCodecRK264:
|
||||
return 8192, 8192
|
||||
case VideoCodecN264,
|
||||
VideoCodecN264H,
|
||||
VideoCodecI264,
|
||||
|
|
@ -382,7 +419,8 @@ func (f *FFMpeg) hwCodecHLSCompatible() *VideoCodec {
|
|||
VideoCodecI264C,
|
||||
VideoCodecV264,
|
||||
VideoCodecR264,
|
||||
VideoCodecM264: // Note that the Apple encoder sucks at startup, thus HLS quality is crap
|
||||
VideoCodecM264, // Note that the Apple encoder sucks at startup, thus HLS quality is crap
|
||||
VideoCodecRK264:
|
||||
return &element
|
||||
}
|
||||
}
|
||||
|
|
@ -397,7 +435,8 @@ func (f *FFMpeg) hwCodecMP4Compatible() *VideoCodec {
|
|||
VideoCodecN264H,
|
||||
VideoCodecI264,
|
||||
VideoCodecI264C,
|
||||
VideoCodecM264:
|
||||
VideoCodecM264,
|
||||
VideoCodecRK264:
|
||||
return &element
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue