Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature/option to rotate cameras #5653

Closed
wants to merge 14 commits into from
Closed

Add feature/option to rotate cameras #5653

wants to merge 14 commits into from

Conversation

horttorrell32
Copy link

Added field in the configuration file to rotate camera: 0 (default), 90, 180 or 270 (-90º) degrees.
Enable this feature to detect and record output.
Update the documentation.
Add new test to test_ffmpeg_presets.

@netlify
Copy link

netlify bot commented Mar 6, 2023

Deploy Preview for frigate-docs ready!

Name Link
🔨 Latest commit 21c4135
🔍 Latest deploy log https://app.netlify.com/sites/frigate-docs/deploys/640c858411941700070c0628
😎 Deploy Preview https://deploy-preview-5653--frigate-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@@ -52,6 +52,17 @@ def get_selected_gpu(self) -> str:
f"FFmpeg Frigate/{VERSION}",
]

PRESETS_FFMPEG_HW_ACCEL = {
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for breaking this out? The encoding still has different set of args for each preset anyway

scale = PRESETS_HW_ACCEL_SCALE.get(arg, "")

if scale:
scale = scale.format(fps, width, height).split(" ")
scale = scale.format(fps, width, height, transpose).split(" ")
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this is going to lead to multiple -vf args, I think this logic needs to be refactored.

We're also going to need more logic for the vf formatting as many of these are going to need hwupload/hwdownload args

Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still an issue I think, the scale and rotation both have -vf which will cause issues

roles:
- detect
- record
rotate: 90
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be better as a field of the ffmpeg config and not the camera

@@ -156,6 +291,142 @@ def test_ffmpeg_output_record_not_preset(self):
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
)

def test_ffmpeg_output_record_rotate_90_preset(self):
Copy link
Sponsor Collaborator

@NickM-27 NickM-27 Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have these all been tested? (If not, which ones?)

At least some of these I believe wouldn't actually work in ffmpeg because they're missing the hwupload/hwdownload and formatting args.

I've spent a lot of time getting these to manually work with rotation with my nvidia and vaapi setups so definitely need to have the ffmpeg commands for the test confirmed working.

else : # Rotation not need or not supported
return ""

return PRESETS_HW_ACCEL_SCALE_ROTATION.get(arg, "").get(mode).format(transpose)
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work with the second .get call? This would fail if calling .get on an empty string (which is the default value for no preset)

@NickM-27
Copy link
Sponsor Collaborator

NickM-27 commented Mar 6, 2023

I'm also curious about the utility of this. I think it would be much preferred (and recommended) to use go2rtc to rotate the stream as a restream so the rotation is only done once instead of twice (detect and record)

@NickM-27
Copy link
Sponsor Collaborator

NickM-27 commented Mar 6, 2023

For example, here is a working ffmpeg command to do rotation for nvidia GPU

ffmpeg -hide_banner -threads 1 -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 2 -fflags nobuffer -flags low_delay -timeout 5000000 -user_agent go2rtc/ffmpeg -noautorotate -rtsp_transport tcp -i {input} -r 10 -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll -vf hwdownload,format=nv12,transpose=1,hwupload -c:a copy -threads 1 -user_agent ffmpeg/go2rtc -rtsp_transport tcp -f rtsp {output}

@horttorrell32
Copy link
Author

I am totally agree with you that more efficient way would be to use go2rtc to rotate the stream, but I read that go2rtc doesn't work with cameras with some errors in the input.
The idea is leave to 'configurator' the option to use the rotation in the frigate or go2rtc.
Another question that I have is that go2rtc seems to do the rotation using SW and not HW accelerator.

@horttorrell32
Copy link
Author

I am not an expert with ffmpeg, but the ffmpeg command to do rotation for nvidia GPU seems to be executed by CPU and not by GPU.
doesn't NVIDIA offer the GPU rotation?
I have read that exist the 'transpose_npp' HW filter, but like I don't have NVIDIA GPU, I can't test.

@NickM-27
Copy link
Sponsor Collaborator

NickM-27 commented Mar 7, 2023

I am not an expert with ffmpeg, but the ffmpeg command to do rotation for nvidia GPU seems to be executed by CPU and not by GPU.
doesn't NVIDIA offer the GPU rotation?
I have read that exist the 'transpose_npp' HW filter, but like I don't have NVIDIA GPU, I can't test.

Right, but scale_cuda is done on the GPU meaning that filters need to be used to move between GPU and CPU

and npp support can't be built into a distributable ffmpeg build so it's not feasible for us to use it

@NickM-27
Copy link
Sponsor Collaborator

NickM-27 commented Mar 7, 2023

I am totally agree with you that more efficient way would be to use go2rtc to rotate the stream, but I read that go2rtc doesn't work with cameras with some errors in the input.

That's if using a camera directly. Go2rtc recommends using ffmpeg for cameras with bad data which solves that issue

The idea is leave to 'configurator' the option to use the rotation in the frigate or go2rtc.

Makes sense, but the docs should definitely recommend users to use go2rtc

Another question that I have is that go2rtc seems to do the rotation using SW and not HW accelerator.

Right, hardware support is early for go2rtc.

@horttorrell32
Copy link
Author

  • Documentation updated to recommend the usage of go2rtc.
  • Rotate field moved to camera/ffmpeg configuration.
  • Add ffmpeg flags to allow rotation with cuda (sw ratation)

@NickM-27 NickM-27 enabled auto-merge (squash) March 7, 2023 15:23
auto-merge was automatically disabled March 8, 2023 08:12

Head branch was pushed to by a user without write access

@horttorrell32
Copy link
Author

Hello NickM-27, I don't have clear if I need to correct something more.
Could you guide me ?

@blakeblackshear
Copy link
Owner

@NickM-27 is unavailable, so this will have to wait until he is back a week from now.

@horttorrell32
Copy link
Author

Ok, thanks Blakeblackshear

scale = PRESETS_HW_ACCEL_SCALE.get(arg, "")

if scale:
scale = scale.format(fps, width, height).split(" ")
scale = scale.format(fps, width, height, transpose).split(" ")
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still an issue I think, the scale and rotation both have -vf which will cause issues

"default": "-r {0}{3} -s {1}x{2}",
}

PRESETS_HW_ACCEL_SCALE_ROTATION = {
Copy link
Sponsor Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't doing any scaling just rotation so the name should reflect that

Copy link
Sponsor Collaborator

@NickM-27 NickM-27 Mar 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think this way of doing it is a bit confusing (to me at least). I think I would rather see a separate dict for DECODE_SCALE and DECODE_SCALE_ROTATE so they are not dependent on each other. Similarly we can have another ENCODE_ROTATE or something so we don't need to worry about splitting a multi layer dict with multiple modes

@github-actions github-actions bot added the stale label Apr 18, 2023
@github-actions github-actions bot closed this Apr 21, 2023
@KenwoodFox
Copy link

Did this get merged? Is there a way to rotate the camera views? I don't see anything in the docs...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants