From 6309d323dcbe4d11d7769b5ba7d13deeb24e1b5c Mon Sep 17 00:00:00 2001 From: Alex X Date: Sat, 22 Mar 2025 10:32:12 +0300 Subject: [PATCH] Update hardware support for Rockchip --- internal/ffmpeg/ffmpeg.go | 5 ++-- internal/ffmpeg/ffmpeg_test.go | 36 +++++++++++++++++------ internal/ffmpeg/hardware/hardware.go | 29 +++++++++++++++--- internal/ffmpeg/hardware/hardware_unix.go | 13 ++++++-- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/internal/ffmpeg/ffmpeg.go b/internal/ffmpeg/ffmpeg.go index ccbd826c..e0c2aa8b 100644 --- a/internal/ffmpeg/ffmpeg.go +++ b/internal/ffmpeg/ffmpeg.go @@ -130,8 +130,9 @@ var defaults = map[string]string{ // hardware Rockchip // important to use custom ffmpeg https://github.com/AlexxIT/go2rtc/issues/768 // hevc - doesn't have a profile setting - "h264/rkmpp": "-c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1", - "h265/rkmpp": "-c:v hevc_rkmpp -g 50 -bf 0 -profile:v main -level:v 5.1", + "h264/rkmpp": "-c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1", + "h265/rkmpp": "-c:v hevc_rkmpp -g 50 -bf 0 -profile:v main -level:v 5.1", + "mjpeg/rkmpp": "-c:v mjpeg_rkmpp", // hardware NVidia on Linux and Windows // preset=p2 - faster, tune=ll - low latency diff --git a/internal/ffmpeg/ffmpeg_test.go b/internal/ffmpeg/ffmpeg_test.go index 5ad9d6e3..0efddbb9 100644 --- a/internal/ffmpeg/ffmpeg_test.go +++ b/internal/ffmpeg/ffmpeg_test.go @@ -193,15 +193,33 @@ func _TestParseArgsHwV4l2m2m(t *testing.T) { } func TestParseArgsHwRKMPP(t *testing.T) { - // [HTTP-MJPEG] video will be transcoded to H264 - args := parseArgs("http://example.com#video=h264#hardware=rkmpp") - require.Equal(t, `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -fflags nobuffer -flags low_delay -i http://example.com -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, args.String()) - - args = parseArgs("http://example.com#video=h264#rotate=180#hardware=rkmpp") - require.Equal(t, `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -fflags nobuffer -flags low_delay -i http://example.com -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -vf "transpose=1,transpose=1" -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, args.String()) - - args = parseArgs("http://example.com#video=h264#height=320#hardware=rkmpp") - require.Equal(t, `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -fflags nobuffer -flags low_delay -i http://example.com -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -vf "scale_rkrga=-1:320:force_original_aspect_ratio=0" -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, args.String()) + tests := []struct { + name string + source string + expect string + }{ + { + name: "[FILE] transcoding to H264", + source: "bbb.mp4#video=h264#hardware=rkmpp", + expect: `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -re -i bbb.mp4 -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, + }, + { + name: "[FILE] transcoding with rotation", + source: "bbb.mp4#video=h264#rotate=180#hardware=rkmpp", + expect: `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -re -i bbb.mp4 -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -vf "format=drm_prime|nv12,hwupload,vpp_rkrga=transpose=4" -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, + }, + { + name: "[FILE] transcoding with scaling", + source: "bbb.mp4#video=h264#height=320#hardware=rkmpp", + expect: `ffmpeg -hide_banner -hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga -re -i bbb.mp4 -c:v h264_rkmpp -g 50 -bf 0 -profile:v high -level:v 4.1 -an -vf "format=drm_prime|nv12,hwupload,scale_rkrga=-1:320:force_original_aspect_ratio=0" -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}`, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + args := parseArgs(test.source) + require.Equal(t, test.expect, args.String()) + }) + } } func _TestParseArgsHwCuda(t *testing.T) { diff --git a/internal/ffmpeg/hardware/hardware.go b/internal/ffmpeg/hardware/hardware.go index 34b21085..80166890 100644 --- a/internal/ffmpeg/hardware/hardware.go +++ b/internal/ffmpeg/hardware/hardware.go @@ -127,12 +127,33 @@ func MakeHardware(args *ffmpeg.Args, engine string, defaults map[string]string) case EngineRKMPP: args.Codecs[i] = defaults[name+"/"+engine] - args.Input = "-hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga " + args.Input - for j, filter := range args.Filters { - if strings.HasPrefix(filter, "scale=") { - args.Filters[j] = "scale_rkrga=" + filter[6:] + ":force_original_aspect_ratio=0" + if !args.HasFilters("drawtext=") { + args.Input = "-hwaccel rkmpp -hwaccel_output_format drm_prime -afbc rga " + args.Input + + for i, filter := range args.Filters { + if strings.HasPrefix(filter, "scale=") { + args.Filters[i] = "scale_rkrga=" + filter[6:] + ":force_original_aspect_ratio=0" + } + if strings.HasPrefix(filter, "transpose=") { + if filter == "transpose=1,transpose=1" { // 180 degrees half-turn + args.Filters[i] = "vpp_rkrga=transpose=4" // reversal + } else { + args.Filters[i] = "vpp_rkrga=transpose=" + filter[10:] + } + } } + + if len(args.Filters) > 0 { + // fix if input doesn't support hwaccel, do nothing when support + // insert as first filter before hardware scale and transpose + args.InsertFilter("format=drm_prime|nv12,hwupload") + } + } else { + // enable software pixel for drawtext, scale and transpose + args.Input = "-hwaccel rkmpp -hwaccel_output_format nv12 -afbc rga " + args.Input + + args.AddFilter("hwupload") } } } diff --git a/internal/ffmpeg/hardware/hardware_unix.go b/internal/ffmpeg/hardware/hardware_unix.go index 4f688ce4..e8000e17 100644 --- a/internal/ffmpeg/hardware/hardware_unix.go +++ b/internal/ffmpeg/hardware/hardware_unix.go @@ -11,8 +11,9 @@ import ( const ( ProbeV4L2M2MH264 = "-f lavfi -i testsrc2 -t 1 -c h264_v4l2m2m -f null -" ProbeV4L2M2MH265 = "-f lavfi -i testsrc2 -t 1 -c hevc_v4l2m2m -f null -" - ProbeRKMPPH264 = "-f lavfi -i testsrc2 -t 1 -c h264_rkmpp_encoder -f null -" - ProbeRKMPPH265 = "-f lavfi -i testsrc2 -t 1 -c hevc_rkmpp_encoder -f null -" + ProbeRKMPPH264 = "-f lavfi -i testsrc2 -t 1 -c h264_rkmpp -f null -" + ProbeRKMPPH265 = "-f lavfi -i testsrc2 -t 1 -c hevc_rkmpp -f null -" + ProbeRKMPPJPEG = "-f lavfi -i testsrc2 -t 1 -c mjpeg_rkmpp -f null -" ProbeVAAPIH264 = "-init_hw_device vaapi -f lavfi -i testsrc2 -t 1 -vf format=nv12,hwupload -c h264_vaapi -f null -" ProbeVAAPIH265 = "-init_hw_device vaapi -f lavfi -i testsrc2 -t 1 -vf format=nv12,hwupload -c hevc_vaapi -f null -" ProbeVAAPIJPEG = "-init_hw_device vaapi -f lavfi -i testsrc2 -t 1 -vf format=nv12,hwupload -c mjpeg_vaapi -f null -" @@ -39,6 +40,10 @@ func ProbeAll(bin string) []*api.Source { Name: runToString(bin, ProbeRKMPPH265), URL: "ffmpeg:...#video=h265#hardware=" + EngineRKMPP, }, + { + Name: runToString(bin, ProbeRKMPPJPEG), + URL: "ffmpeg:...#video=mjpeg#hardware=" + EngineRKMPP, + }, } } @@ -83,6 +88,10 @@ func ProbeHardware(bin, name string) string { if run(bin, ProbeRKMPPH265) { return EngineRKMPP } + case "mjpeg": + if run(bin, ProbeRKMPPJPEG) { + return EngineRKMPP + } } return EngineSoftware