[libcamera-devel,v2,06/19] py: Add CameraManager.read_event()
diff mbox series

Message ID 20220524114610.41848-7-tomi.valkeinen@ideasonboard.com
State Accepted
Headers show
Series
  • More misc Python patches
Related show

Commit Message

Tomi Valkeinen May 24, 2022, 11:45 a.m. UTC
Add CameraManager.read_event() so that the user does not need to call
os.read().

We use eventfd, and we must always read 8 bytes. Hiding that inside
read_event() makes sense.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 src/py/cam/cam.py            | 3 +--
 src/py/libcamera/py_main.cpp | 8 ++++++++
 test/py/unittests.py         | 3 +--
 3 files changed, 10 insertions(+), 4 deletions(-)

Comments

Laurent Pinchart May 26, 2022, 3:27 p.m. UTC | #1
Hi Tomi,

Thank you for the patch.

On Tue, May 24, 2022 at 02:45:57PM +0300, Tomi Valkeinen wrote:
> Add CameraManager.read_event() so that the user does not need to call
> os.read().
> 
> We use eventfd, and we must always read 8 bytes. Hiding that inside
> read_event() makes sense.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
>  src/py/cam/cam.py            | 3 +--
>  src/py/libcamera/py_main.cpp | 8 ++++++++
>  test/py/unittests.py         | 3 +--
>  3 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
> index e2bc78da..66df18bf 100755
> --- a/src/py/cam/cam.py
> +++ b/src/py/cam/cam.py
> @@ -9,7 +9,6 @@
>  import argparse
>  import binascii
>  import libcamera as libcam
> -import os
>  import sys
>  import traceback
>  
> @@ -294,7 +293,7 @@ def event_handler(state):
>          cm = state['cm']
>          contexts = state['contexts']
>  
> -        os.read(cm.efd, 8)
> +        cm.read_event()
>  
>          reqs = cm.get_ready_requests()

Would it make sense to read the event within get_ready_requests() ?

>  
> diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp
> index e7066841..5d389942 100644
> --- a/src/py/libcamera/py_main.cpp
> +++ b/src/py/libcamera/py_main.cpp
> @@ -212,6 +212,14 @@ PYBIND11_MODULE(_libcamera, m)
>  			return gEventfd;
>  		})
>  
> +		.def("read_event", [](CameraManager &) {
> +			uint8_t buf[8];
> +
> +			int ret = read(gEventfd, buf, 8);
> +			if (ret != 8)
> +				throw std::system_error(errno, std::generic_category());
> +		})
> +
>  		.def("get_ready_requests", [](CameraManager &) {
>  			std::vector<Request *> v;
>  
> diff --git a/test/py/unittests.py b/test/py/unittests.py
> index 7dede33b..8c445bc9 100755
> --- a/test/py/unittests.py
> +++ b/test/py/unittests.py
> @@ -7,7 +7,6 @@ from collections import defaultdict
>  import errno
>  import gc
>  import libcamera as libcam
> -import os
>  import selectors
>  import time
>  import typing
> @@ -278,7 +277,7 @@ class SimpleCaptureMethods(CameraTesterBase):
>          while running:
>              events = sel.select()
>              for key, _ in events:
> -                os.read(key.fd, 8)
> +                cm.read_event()
>  
>                  ready_reqs = cm.get_ready_requests()
>
Tomi Valkeinen May 27, 2022, 6 a.m. UTC | #2
On 26/05/2022 18:27, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Tue, May 24, 2022 at 02:45:57PM +0300, Tomi Valkeinen wrote:
>> Add CameraManager.read_event() so that the user does not need to call
>> os.read().
>>
>> We use eventfd, and we must always read 8 bytes. Hiding that inside
>> read_event() makes sense.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>>   src/py/cam/cam.py            | 3 +--
>>   src/py/libcamera/py_main.cpp | 8 ++++++++
>>   test/py/unittests.py         | 3 +--
>>   3 files changed, 10 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
>> index e2bc78da..66df18bf 100755
>> --- a/src/py/cam/cam.py
>> +++ b/src/py/cam/cam.py
>> @@ -9,7 +9,6 @@
>>   import argparse
>>   import binascii
>>   import libcamera as libcam
>> -import os
>>   import sys
>>   import traceback
>>   
>> @@ -294,7 +293,7 @@ def event_handler(state):
>>           cm = state['cm']
>>           contexts = state['contexts']
>>   
>> -        os.read(cm.efd, 8)
>> +        cm.read_event()
>>   
>>           reqs = cm.get_ready_requests()
> 
> Would it make sense to read the event within get_ready_requests() ?

I thought about these two functions, but this seemed the safest to me. 
If get_ready_requests() would do read_event(), then you could not call 
get_ready_requests() unless you knew there is an event waiting, or it 
would block. Or we could make the fd non-blocking, but I think that's 
usually the choice of the user, not the library.

  Tomi
Laurent Pinchart May 27, 2022, 11:04 a.m. UTC | #3
Hi Tomi,

On Fri, May 27, 2022 at 09:00:44AM +0300, Tomi Valkeinen wrote:
> On 26/05/2022 18:27, Laurent Pinchart wrote:
> > On Tue, May 24, 2022 at 02:45:57PM +0300, Tomi Valkeinen wrote:
> >> Add CameraManager.read_event() so that the user does not need to call
> >> os.read().
> >>
> >> We use eventfd, and we must always read 8 bytes. Hiding that inside
> >> read_event() makes sense.
> >>
> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >> ---
> >>   src/py/cam/cam.py            | 3 +--
> >>   src/py/libcamera/py_main.cpp | 8 ++++++++
> >>   test/py/unittests.py         | 3 +--
> >>   3 files changed, 10 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
> >> index e2bc78da..66df18bf 100755
> >> --- a/src/py/cam/cam.py
> >> +++ b/src/py/cam/cam.py
> >> @@ -9,7 +9,6 @@
> >>   import argparse
> >>   import binascii
> >>   import libcamera as libcam
> >> -import os
> >>   import sys
> >>   import traceback
> >>   
> >> @@ -294,7 +293,7 @@ def event_handler(state):
> >>           cm = state['cm']
> >>           contexts = state['contexts']
> >>   
> >> -        os.read(cm.efd, 8)
> >> +        cm.read_event()
> >>   
> >>           reqs = cm.get_ready_requests()
> > 
> > Would it make sense to read the event within get_ready_requests() ?
> 
> I thought about these two functions, but this seemed the safest to me. 
> If get_ready_requests() would do read_event(), then you could not call 
> get_ready_requests() unless you knew there is an event waiting, or it 
> would block. Or we could make the fd non-blocking, but I think that's 
> usually the choice of the user, not the library.

Hmmm... I have a feeling we can do better, but I don't know what yet :-)
It doesn't have to be done now.

Patch
diff mbox series

diff --git a/src/py/cam/cam.py b/src/py/cam/cam.py
index e2bc78da..66df18bf 100755
--- a/src/py/cam/cam.py
+++ b/src/py/cam/cam.py
@@ -9,7 +9,6 @@ 
 import argparse
 import binascii
 import libcamera as libcam
-import os
 import sys
 import traceback
 
@@ -294,7 +293,7 @@  def event_handler(state):
         cm = state['cm']
         contexts = state['contexts']
 
-        os.read(cm.efd, 8)
+        cm.read_event()
 
         reqs = cm.get_ready_requests()
 
diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp
index e7066841..5d389942 100644
--- a/src/py/libcamera/py_main.cpp
+++ b/src/py/libcamera/py_main.cpp
@@ -212,6 +212,14 @@  PYBIND11_MODULE(_libcamera, m)
 			return gEventfd;
 		})
 
+		.def("read_event", [](CameraManager &) {
+			uint8_t buf[8];
+
+			int ret = read(gEventfd, buf, 8);
+			if (ret != 8)
+				throw std::system_error(errno, std::generic_category());
+		})
+
 		.def("get_ready_requests", [](CameraManager &) {
 			std::vector<Request *> v;
 
diff --git a/test/py/unittests.py b/test/py/unittests.py
index 7dede33b..8c445bc9 100755
--- a/test/py/unittests.py
+++ b/test/py/unittests.py
@@ -7,7 +7,6 @@  from collections import defaultdict
 import errno
 import gc
 import libcamera as libcam
-import os
 import selectors
 import time
 import typing
@@ -278,7 +277,7 @@  class SimpleCaptureMethods(CameraTesterBase):
         while running:
             events = sel.select()
             for key, _ in events:
-                os.read(key.fd, 8)
+                cm.read_event()
 
                 ready_reqs = cm.get_ready_requests()