-
Notifications
You must be signed in to change notification settings - Fork 203
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
Multiple encoder support #588
Multiple encoder support #588
Conversation
cb28f84
to
4cc32ea
Compare
@@ -873,8 +873,6 @@ def configure_(self, camera_config="preview") -> None: | |||
""" | |||
if self.started: | |||
raise RuntimeError("Camera must be stopped before configuring") | |||
if self.encoder is not None and self.encoder.running: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this check, to allow starting multiple encoders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels to me as though we still want something like this. It would need to complain if any encoder in the set is still running. Does that sound correct?
@@ -937,9 +935,6 @@ def configure_(self, camera_config="preview") -> None: | |||
self.encode_stream_name = camera_config['encode'] | |||
if self.encode_stream_name is not None and self.encode_stream_name not in camera_config: | |||
raise RuntimeError(f"Encode stream {self.encode_stream_name} was not defined") | |||
elif self.encode_stream_name is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this check as encoders don't need to always encode from encode_stream_name
Hi Chris, what's the status on this one, should I be trying this PR out now? |
Hi David, yeah if you could try it out, that'd be great. |
Hi Chris, I noticed a couple of things and also there are just a couple of things I want to think about a bit more. Firstly, I noticed that when I ran the example, the resolution of the MJPEG was the same as the h.264 file! The problem is this line where Fixing this actually breaks the example because the s/w JpegEncoder can't accept YUV420, but it does work if you use the MJPEGEncoder instead which is fine (at least, it's how things are). The next thing I tried was a modified version of the example that went like this:
The point of the example being to start and stop one encoder while another is running continuously. The first little issue I had was when starting This brings me to the final question - do we think that |
Thanks a lot for the feedback. I hadn't noticed that about Could |
Yes, maybe
That feels OK, I think. As regards One other thing I wondered, whether we should remove an encoder from the list (or set) when we stop it (seeing as we insert it when we start, so it would satisfy my need for symmetry). There is actually a race condition between removing it from the set and whether |
4cc32ea
to
f547815
Compare
Realised need to work on case when |
No prob, give me a shout when you want me to try it again! |
f547815
to
63236ff
Compare
@davidplowman Just wondering if you'd be able to take another look. Thanks! I modified the I found it was necessary when modifying the set to take ownership of the lock, so that there wasn't an exception thrown in process_requests. I've also modified / tested some of the examples which aren't in the test list such as |
Yes, seems to be working really nicely now. Let me just do the usual look over code changes and then we'll hopefully be all good! |
picamera2/picamera2.py
Outdated
@@ -270,7 +270,7 @@ def _reset_flags(self) -> None: | |||
self.frames = 0 | |||
self._job_list = [] | |||
self.options = {} | |||
self._encoder = None | |||
self._encoder = set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder about renaming _encoder
to _encoders
, and the encoder
property to encoders
. It might feel a bit more natural, both for users and anyone reading the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, will change that. Just wondering with the encoders property, should that let you assign a set of encoders, that overwrites the previous set of encoders now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure! Currently you have to use start_encoder
, but that also sets up a whole load of stuff like the size etc. What would you do with an encoder that hadn't been set up "properly"? Perhaps it should only be for checking what encoders it thinks are running?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just made it so that you can assign a single encoder, or a set of additional encoders via the property, as a couple of examples used that method.
encoder2 = MJPEGEncoder(10000000) | ||
|
||
picam2.start_recording(encoder1, 'test1.h264') | ||
picam2.start_recording(encoder2, 'test2.mjpeg', name="lores") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this was why you made it OK to start the Picamera2 object twice! :)
@@ -40,7 +40,7 @@ def server(): | |||
stream = conn.makefile("wb") | |||
filestream = FileOutput(stream) | |||
filestream.start() | |||
picam2.encoder.output = [circ, filestream] | |||
encoder.output = [circ, filestream] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose if we rename picam2.encoder
to picam2.encoders
then we could redefine picam2.encoder
to give you the encoder object if there's exactly one, and otherwise complain. But maybe that's bending over backwards too much for backwards compatibility, it certainly feels like it's starting to get a bit fussy!
Signed-off-by: Chris Richardson <christopher.richardson@raspberrypi.org>
Signed-off-by: Chris Richardson <christopher.richardson@raspberrypi.org>
Signed-off-by: Chris Richardson <christopher.richardson@raspberrypi.org>
Because '.encoder' of a Picamera2 object now returns a set, some examples needed to be updated. Signed-off-by: Chris Richardson <christopher.richardson@raspberrypi.org>
63236ff
to
e6baf98
Compare
I noticed that it seemed to be setting .framerate of the encoder, which wasn't used anywhere, so I just changed it to set _framerate, which does seem to be used. |
Hi Chris, actually I have started getting an error as follows
(Not quite sure why the tests haven't picked that up.) Anyway, I'm thinking that I'd quite like to leave Other than that, this is looking pretty good and I'd like to get it merged. Thanks! |
Hi David, Do you mind pasting your /home/pi/test.py file? I think the reason I made it use _framerate, was it's present as that in here - I could rename that to framerate? |
Sure, here it is:
I guess we just need to review our use of |
It looks like we had a mix of framerate and _framerate, changed to former Signed-off-by: Chris Richardson <christopher.richardson@raspberrypi.org>
e6baf98
to
b94dc7c
Compare
Thanks for that test case, I've got that to pass now. I renamed |
Are you happy to merge this one now? |
Sure, am happy for this to be merged now |
No description provided.