We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'float' object cannot be interpreted as an integer when calling `read_frame` on a `CameraAndroid`
**Software Versions**
* Python: 3.11
* OS: Android 14
* Kivy: 2.3.0
* Kivy installation method: pip (through Poetry)

**Describe the bug**
Calling `camera.read_frame()` from `on_tex`'s `camera` argument in a subclass of `kivy.uix.camera.Camera` throws with:

```
'float' object cannot be interpreted as an integer
```

**Expected behavior**
`camera.read_frame()` returns a numpy array to use with OpenCV

**To Reproduce**
A short, *runnable* example that reproduces the issue with *latest kivy master*.

Note: I did not try reproducing with master because building the wheel from master (3eadfd9fdeb4f0fb1f1a8e786e88952e0a8c42ec) fails

```python
# coding:utf-8
from android.permissions import Permission, request_permissions
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.camera import Camera

Builder.load_string("""
#:kivy 2.3.0
<RootLayout>
    orientation: 'vertical'
    size: root.width, root.height

    Cam:
        index: 0
        # resolution: self.camera_resolution
        allow_stretch: True
        play: True
""")

class Cam(Camera):
    def on_tex(self, camera):
        frame = camera.read_frame()
        return super().on_tex(camera)


class RootLayout(BoxLayout):
    pass


class MyApp(App):
    def build(self):
        return RootLayout()

if __name__ == "__main__":
    request_permissions([Permission.CAMERA])
    MyApp().run()
```

**Code and Logs and screenshots**
```python
# coding:utf-8
from android.permissions import Permission, request_permissions
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.camera import Camera
from rich import print

Builder.load_string("""
#:kivy 2.3.0
<RootLayout>
    orientation: 'vertical'
    size: root.width, root.height

    Cam:
        # index: 0
        # resolution: self.camera_resolution
        # allow_stretch: True
        # play: True
""")

class Cam(Camera):
    def on_tex(self, camera):
        print(f"on_texture: {camera}")
        try:
            frame = camera.read_frame()
            print(f"frame @ {frame.shape}")
        except Exception as e:
            print(e)
            pass
        return super().on_tex(camera)


class RootLayout(BoxLayout):
    pass


class AudioseekApp(App):
    def build(self):
        return RootLayout()


if __name__ == "__main__":
    request_permissions([Permission.CAMERA])
    AudioseekApp().run()
```


Logcat:
```logcat
06-10 17:10:03.910 20603 20730 I python  : 'float' object cannot be interpreted as an integer
06-10 17:10:03.941 20603 20730 I python  : on_texture: <kivy.core.camera.camera_android.CameraAndroid object at 
06-10 17:10:03.941 20603 20730 I python  : 0x76e27f3000>
```

**Additional context**

The stacktrace points to `decode_frame`, see https://github.com/kivy/kivy/blob/3eadfd9fdeb4f0fb1f1a8e786e88952e0a8c42ec/kivy/core/camera/camera_android.py#L191


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kivy/core/camera/camera_android.py`
Content:
```
1 from jnius import autoclass, PythonJavaClass, java_method
2 from kivy.clock import Clock
3 from kivy.graphics.texture import Texture
4 from kivy.graphics import Fbo, Callback, Rectangle
5 from kivy.core.camera import CameraBase
6 import threading
7 
8 
9 Camera = autoclass('android.hardware.Camera')
10 SurfaceTexture = autoclass('android.graphics.SurfaceTexture')
11 GL_TEXTURE_EXTERNAL_OES = autoclass(
12     'android.opengl.GLES11Ext').GL_TEXTURE_EXTERNAL_OES
13 ImageFormat = autoclass('android.graphics.ImageFormat')
14 
15 
16 class PreviewCallback(PythonJavaClass):
17     """
18     Interface used to get back the preview frame of the Android Camera
19     """
20     __javainterfaces__ = ('android.hardware.Camera$PreviewCallback', )
21 
22     def __init__(self, callback):
23         super(PreviewCallback, self).__init__()
24         self._callback = callback
25 
26     @java_method('([BLandroid/hardware/Camera;)V')
27     def onPreviewFrame(self, data, camera):
28         self._callback(data, camera)
29 
30 
31 class CameraAndroid(CameraBase):
32     """
33     Implementation of CameraBase using Android API
34     """
35 
36     _update_ev = None
37 
38     def __init__(self, **kwargs):
39         self._android_camera = None
40         self._preview_cb = PreviewCallback(self._on_preview_frame)
41         self._buflock = threading.Lock()
42         super(CameraAndroid, self).__init__(**kwargs)
43 
44     def __del__(self):
45         self._release_camera()
46 
47     def init_camera(self):
48         self._release_camera()
49         self._android_camera = Camera.open(self._index)
50         params = self._android_camera.getParameters()
51         width, height = self._resolution
52         params.setPreviewSize(width, height)
53         supported_focus_modes = self._android_camera.getParameters() \
54             .getSupportedFocusModes()
55         if supported_focus_modes.contains('continuous-picture'):
56             params.setFocusMode('continuous-picture')
57         self._android_camera.setParameters(params)
58         # self._android_camera.setDisplayOrientation()
59         self.fps = 30.
60 
61         pf = params.getPreviewFormat()
62         assert pf == ImageFormat.NV21  # default format is NV21
63         self._bufsize = int(ImageFormat.getBitsPerPixel(pf) / 8. *
64                             width * height)
65 
66         self._camera_texture = Texture(width=width, height=height,
67                                        target=GL_TEXTURE_EXTERNAL_OES,
68                                        colorfmt='rgba')
69         self._surface_texture = SurfaceTexture(int(self._camera_texture.id))
70         self._android_camera.setPreviewTexture(self._surface_texture)
71 
72         self._fbo = Fbo(size=self._resolution)
73         self._fbo['resolution'] = (float(width), float(height))
74         self._fbo.shader.fs = '''
75             #extension GL_OES_EGL_image_external : require
76             #ifdef GL_ES
77                 precision highp float;
78             #endif
79 
80             /* Outputs from the vertex shader */
81             varying vec4 frag_color;
82             varying vec2 tex_coord0;
83 
84             /* uniform texture samplers */
85             uniform sampler2D texture0;
86             uniform samplerExternalOES texture1;
87             uniform vec2 resolution;
88 
89             void main()
90             {
91                 vec2 coord = vec2(tex_coord0.y * (
92                     resolution.y / resolution.x), 1. -tex_coord0.x);
93                 gl_FragColor = texture2D(texture1, tex_coord0);
94             }
95         '''
96         with self._fbo:
97             self._texture_cb = Callback(lambda instr:
98                                         self._camera_texture.bind)
99             Rectangle(size=self._resolution)
100 
101     def _release_camera(self):
102         if self._android_camera is None:
103             return
104 
105         self.stop()
106         self._android_camera.release()
107         self._android_camera = None
108 
109         # clear texture and it'll be reset in `_update` pointing to new FBO
110         self._texture = None
111         del self._fbo, self._surface_texture, self._camera_texture
112 
113     def _on_preview_frame(self, data, camera):
114         with self._buflock:
115             if self._buffer is not None:
116                 # add buffer back for reuse
117                 self._android_camera.addCallbackBuffer(self._buffer)
118             self._buffer = data
119         # check if frame grabbing works
120         # print self._buffer, len(self.frame_data)
121 
122     def _refresh_fbo(self):
123         self._texture_cb.ask_update()
124         self._fbo.draw()
125 
126     def start(self):
127         super(CameraAndroid, self).start()
128 
129         with self._buflock:
130             self._buffer = None
131         for k in range(2):  # double buffer
132             buf = b'\x00' * self._bufsize
133             self._android_camera.addCallbackBuffer(buf)
134         self._android_camera.setPreviewCallbackWithBuffer(self._preview_cb)
135 
136         self._android_camera.startPreview()
137         if self._update_ev is not None:
138             self._update_ev.cancel()
139         self._update_ev = Clock.schedule_interval(self._update, 1 / self.fps)
140 
141     def stop(self):
142         super(CameraAndroid, self).stop()
143         if self._update_ev is not None:
144             self._update_ev.cancel()
145             self._update_ev = None
146         self._android_camera.stopPreview()
147 
148         self._android_camera.setPreviewCallbackWithBuffer(None)
149         # buffer queue cleared as well, to be recreated on next start
150         with self._buflock:
151             self._buffer = None
152 
153     def _update(self, dt):
154         self._surface_texture.updateTexImage()
155         self._refresh_fbo()
156         if self._texture is None:
157             self._texture = self._fbo.texture
158             self.dispatch('on_load')
159         self._copy_to_gpu()
160 
161     def _copy_to_gpu(self):
162         """
163         A dummy placeholder (the image is already in GPU) to be consistent
164         with other providers.
165         """
166         self.dispatch('on_texture')
167 
168     def grab_frame(self):
169         """
170         Grab current frame (thread-safe, minimal overhead)
171         """
172         with self._buflock:
173             if self._buffer is None:
174                 return None
175             buf = self._buffer.tostring()
176             return buf
177 
178     def decode_frame(self, buf):
179         """
180         Decode image data from grabbed frame.
181 
182         This method depends on OpenCV and NumPy - however it is only used for
183         fetching the current frame as a NumPy array, and not required when
184         this :class:`CameraAndroid` provider is simply used by a
185         :class:`~kivy.uix.camera.Camera` widget.
186         """
187         import numpy as np
188         from cv2 import cvtColor
189 
190         w, h = self._resolution
191         arr = np.fromstring(buf, 'uint8').reshape((h + h / 2, w))
192         arr = cvtColor(arr, 93)  # NV21 -> BGR
193         return arr
194 
195     def read_frame(self):
196         """
197         Grab and decode frame in one call
198         """
199         return self.decode_frame(self.grab_frame())
200 
201     @staticmethod
202     def get_camera_count():
203         """
204         Get the number of available cameras.
205         """
206         return Camera.getNumberOfCameras()
207
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kivy/core/camera/camera_android.py b/kivy/core/camera/camera_android.py
--- a/kivy/core/camera/camera_android.py
+++ b/kivy/core/camera/camera_android.py
@@ -188,7 +188,7 @@
         from cv2 import cvtColor
 
         w, h = self._resolution
-        arr = np.fromstring(buf, 'uint8').reshape((h + h / 2, w))
+        arr = np.fromstring(buf, 'uint8').reshape((h + h // 2, w))
         arr = cvtColor(arr, 93)  # NV21 -> BGR
         return arr

{"golden_diff": "diff --git a/kivy/core/camera/camera_android.py b/kivy/core/camera/camera_android.py\n--- a/kivy/core/camera/camera_android.py\n+++ b/kivy/core/camera/camera_android.py\n@@ -188,7 +188,7 @@\n         from cv2 import cvtColor\n \n         w, h = self._resolution\n-        arr = np.fromstring(buf, 'uint8').reshape((h + h / 2, w))\n+        arr = np.fromstring(buf, 'uint8').reshape((h + h // 2, w))\n         arr = cvtColor(arr, 93)  # NV21 -> BGR\n         return arr\n", "issue": "'float' object cannot be interpreted as an integer when calling `read_frame` on a `CameraAndroid`\n**Software Versions**\r\n* Python: 3.11\r\n* OS: Android 14\r\n* Kivy: 2.3.0\r\n* Kivy installation method: pip (through Poetry)\r\n\r\n**Describe the bug**\r\nCalling `camera.read_frame()` from `on_tex`'s `camera` argument in a subclass of `kivy.uix.camera.Camera` throws with:\r\n\r\n```\r\n'float' object cannot be interpreted as an integer\r\n```\r\n\r\n**Expected behavior**\r\n`camera.read_frame()` returns a numpy array to use with OpenCV\r\n\r\n**To Reproduce**\r\nA short, *runnable* example that reproduces the issue with *latest kivy master*.\r\n\r\nNote: I did not try reproducing with master because building the wheel from master (3eadfd9fdeb4f0fb1f1a8e786e88952e0a8c42ec) fails\r\n\r\n```python\r\n# coding:utf-8\r\nfrom android.permissions import Permission, request_permissions\r\nfrom kivy.app import App\r\nfrom kivy.lang import Builder\r\nfrom kivy.uix.boxlayout import BoxLayout\r\nfrom kivy.uix.camera import Camera\r\n\r\nBuilder.load_string(\"\"\"\r\n#:kivy 2.3.0\r\n<RootLayout>\r\n    orientation: 'vertical'\r\n    size: root.width, root.height\r\n\r\n    Cam:\r\n        index: 0\r\n        # resolution: self.camera_resolution\r\n        allow_stretch: True\r\n        play: True\r\n\"\"\")\r\n\r\nclass Cam(Camera):\r\n    def on_tex(self, camera):\r\n        frame = camera.read_frame()\r\n        return super().on_tex(camera)\r\n\r\n\r\nclass RootLayout(BoxLayout):\r\n    pass\r\n\r\n\r\nclass MyApp(App):\r\n    def build(self):\r\n        return RootLayout()\r\n\r\nif __name__ == \"__main__\":\r\n    request_permissions([Permission.CAMERA])\r\n    MyApp().run()\r\n```\r\n\r\n**Code and Logs and screenshots**\r\n```python\r\n# coding:utf-8\r\nfrom android.permissions import Permission, request_permissions\r\nfrom kivy.app import App\r\nfrom kivy.lang import Builder\r\nfrom kivy.uix.boxlayout import BoxLayout\r\nfrom kivy.uix.camera import Camera\r\nfrom rich import print\r\n\r\nBuilder.load_string(\"\"\"\r\n#:kivy 2.3.0\r\n<RootLayout>\r\n    orientation: 'vertical'\r\n    size: root.width, root.height\r\n\r\n    Cam:\r\n        # index: 0\r\n        # resolution: self.camera_resolution\r\n        # allow_stretch: True\r\n        # play: True\r\n\"\"\")\r\n\r\nclass Cam(Camera):\r\n    def on_tex(self, camera):\r\n        print(f\"on_texture: {camera}\")\r\n        try:\r\n            frame = camera.read_frame()\r\n            print(f\"frame @ {frame.shape}\")\r\n        except Exception as e:\r\n            print(e)\r\n            pass\r\n        return super().on_tex(camera)\r\n\r\n\r\nclass RootLayout(BoxLayout):\r\n    pass\r\n\r\n\r\nclass AudioseekApp(App):\r\n    def build(self):\r\n        return RootLayout()\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    request_permissions([Permission.CAMERA])\r\n    AudioseekApp().run()\r\n```\r\n\r\n\r\nLogcat:\r\n```logcat\r\n06-10 17:10:03.910 20603 20730 I python  : 'float' object cannot be interpreted as an integer\r\n06-10 17:10:03.941 20603 20730 I python  : on_texture: <kivy.core.camera.camera_android.CameraAndroid object at \r\n06-10 17:10:03.941 20603 20730 I python  : 0x76e27f3000>\r\n```\r\n\r\n**Additional context**\r\n\r\nThe stacktrace points to `decode_frame`, see https://github.com/kivy/kivy/blob/3eadfd9fdeb4f0fb1f1a8e786e88952e0a8c42ec/kivy/core/camera/camera_android.py#L191\r\n\n", "before_files": [{"content": "from jnius import autoclass, PythonJavaClass, java_method\nfrom kivy.clock import Clock\nfrom kivy.graphics.texture import Texture\nfrom kivy.graphics import Fbo, Callback, Rectangle\nfrom kivy.core.camera import CameraBase\nimport threading\n\n\nCamera = autoclass('android.hardware.Camera')\nSurfaceTexture = autoclass('android.graphics.SurfaceTexture')\nGL_TEXTURE_EXTERNAL_OES = autoclass(\n    'android.opengl.GLES11Ext').GL_TEXTURE_EXTERNAL_OES\nImageFormat = autoclass('android.graphics.ImageFormat')\n\n\nclass PreviewCallback(PythonJavaClass):\n    \"\"\"\n    Interface used to get back the preview frame of the Android Camera\n    \"\"\"\n    __javainterfaces__ = ('android.hardware.Camera$PreviewCallback', )\n\n    def __init__(self, callback):\n        super(PreviewCallback, self).__init__()\n        self._callback = callback\n\n    @java_method('([BLandroid/hardware/Camera;)V')\n    def onPreviewFrame(self, data, camera):\n        self._callback(data, camera)\n\n\nclass CameraAndroid(CameraBase):\n    \"\"\"\n    Implementation of CameraBase using Android API\n    \"\"\"\n\n    _update_ev = None\n\n    def __init__(self, **kwargs):\n        self._android_camera = None\n        self._preview_cb = PreviewCallback(self._on_preview_frame)\n        self._buflock = threading.Lock()\n        super(CameraAndroid, self).__init__(**kwargs)\n\n    def __del__(self):\n        self._release_camera()\n\n    def init_camera(self):\n        self._release_camera()\n        self._android_camera = Camera.open(self._index)\n        params = self._android_camera.getParameters()\n        width, height = self._resolution\n        params.setPreviewSize(width, height)\n        supported_focus_modes = self._android_camera.getParameters() \\\n            .getSupportedFocusModes()\n        if supported_focus_modes.contains('continuous-picture'):\n            params.setFocusMode('continuous-picture')\n        self._android_camera.setParameters(params)\n        # self._android_camera.setDisplayOrientation()\n        self.fps = 30.\n\n        pf = params.getPreviewFormat()\n        assert pf == ImageFormat.NV21  # default format is NV21\n        self._bufsize = int(ImageFormat.getBitsPerPixel(pf) / 8. *\n                            width * height)\n\n        self._camera_texture = Texture(width=width, height=height,\n                                       target=GL_TEXTURE_EXTERNAL_OES,\n                                       colorfmt='rgba')\n        self._surface_texture = SurfaceTexture(int(self._camera_texture.id))\n        self._android_camera.setPreviewTexture(self._surface_texture)\n\n        self._fbo = Fbo(size=self._resolution)\n        self._fbo['resolution'] = (float(width), float(height))\n        self._fbo.shader.fs = '''\n            #extension GL_OES_EGL_image_external : require\n            #ifdef GL_ES\n                precision highp float;\n            #endif\n\n            /* Outputs from the vertex shader */\n            varying vec4 frag_color;\n            varying vec2 tex_coord0;\n\n            /* uniform texture samplers */\n            uniform sampler2D texture0;\n            uniform samplerExternalOES texture1;\n            uniform vec2 resolution;\n\n            void main()\n            {\n                vec2 coord = vec2(tex_coord0.y * (\n                    resolution.y / resolution.x), 1. -tex_coord0.x);\n                gl_FragColor = texture2D(texture1, tex_coord0);\n            }\n        '''\n        with self._fbo:\n            self._texture_cb = Callback(lambda instr:\n                                        self._camera_texture.bind)\n            Rectangle(size=self._resolution)\n\n    def _release_camera(self):\n        if self._android_camera is None:\n            return\n\n        self.stop()\n        self._android_camera.release()\n        self._android_camera = None\n\n        # clear texture and it'll be reset in `_update` pointing to new FBO\n        self._texture = None\n        del self._fbo, self._surface_texture, self._camera_texture\n\n    def _on_preview_frame(self, data, camera):\n        with self._buflock:\n            if self._buffer is not None:\n                # add buffer back for reuse\n                self._android_camera.addCallbackBuffer(self._buffer)\n            self._buffer = data\n        # check if frame grabbing works\n        # print self._buffer, len(self.frame_data)\n\n    def _refresh_fbo(self):\n        self._texture_cb.ask_update()\n        self._fbo.draw()\n\n    def start(self):\n        super(CameraAndroid, self).start()\n\n        with self._buflock:\n            self._buffer = None\n        for k in range(2):  # double buffer\n            buf = b'\\x00' * self._bufsize\n            self._android_camera.addCallbackBuffer(buf)\n        self._android_camera.setPreviewCallbackWithBuffer(self._preview_cb)\n\n        self._android_camera.startPreview()\n        if self._update_ev is not None:\n            self._update_ev.cancel()\n        self._update_ev = Clock.schedule_interval(self._update, 1 / self.fps)\n\n    def stop(self):\n        super(CameraAndroid, self).stop()\n        if self._update_ev is not None:\n            self._update_ev.cancel()\n            self._update_ev = None\n        self._android_camera.stopPreview()\n\n        self._android_camera.setPreviewCallbackWithBuffer(None)\n        # buffer queue cleared as well, to be recreated on next start\n        with self._buflock:\n            self._buffer = None\n\n    def _update(self, dt):\n        self._surface_texture.updateTexImage()\n        self._refresh_fbo()\n        if self._texture is None:\n            self._texture = self._fbo.texture\n            self.dispatch('on_load')\n        self._copy_to_gpu()\n\n    def _copy_to_gpu(self):\n        \"\"\"\n        A dummy placeholder (the image is already in GPU) to be consistent\n        with other providers.\n        \"\"\"\n        self.dispatch('on_texture')\n\n    def grab_frame(self):\n        \"\"\"\n        Grab current frame (thread-safe, minimal overhead)\n        \"\"\"\n        with self._buflock:\n            if self._buffer is None:\n                return None\n            buf = self._buffer.tostring()\n            return buf\n\n    def decode_frame(self, buf):\n        \"\"\"\n        Decode image data from grabbed frame.\n\n        This method depends on OpenCV and NumPy - however it is only used for\n        fetching the current frame as a NumPy array, and not required when\n        this :class:`CameraAndroid` provider is simply used by a\n        :class:`~kivy.uix.camera.Camera` widget.\n        \"\"\"\n        import numpy as np\n        from cv2 import cvtColor\n\n        w, h = self._resolution\n        arr = np.fromstring(buf, 'uint8').reshape((h + h / 2, w))\n        arr = cvtColor(arr, 93)  # NV21 -> BGR\n        return arr\n\n    def read_frame(self):\n        \"\"\"\n        Grab and decode frame in one call\n        \"\"\"\n        return self.decode_frame(self.grab_frame())\n\n    @staticmethod\n    def get_camera_count():\n        \"\"\"\n        Get the number of available cameras.\n        \"\"\"\n        return Camera.getNumberOfCameras()\n", "path": "kivy/core/camera/camera_android.py"}], "after_files": [{"content": "from jnius import autoclass, PythonJavaClass, java_method\nfrom kivy.clock import Clock\nfrom kivy.graphics.texture import Texture\nfrom kivy.graphics import Fbo, Callback, Rectangle\nfrom kivy.core.camera import CameraBase\nimport threading\n\n\nCamera = autoclass('android.hardware.Camera')\nSurfaceTexture = autoclass('android.graphics.SurfaceTexture')\nGL_TEXTURE_EXTERNAL_OES = autoclass(\n    'android.opengl.GLES11Ext').GL_TEXTURE_EXTERNAL_OES\nImageFormat = autoclass('android.graphics.ImageFormat')\n\n\nclass PreviewCallback(PythonJavaClass):\n    \"\"\"\n    Interface used to get back the preview frame of the Android Camera\n    \"\"\"\n    __javainterfaces__ = ('android.hardware.Camera$PreviewCallback', )\n\n    def __init__(self, callback):\n        super(PreviewCallback, self).__init__()\n        self._callback = callback\n\n    @java_method('([BLandroid/hardware/Camera;)V')\n    def onPreviewFrame(self, data, camera):\n        self._callback(data, camera)\n\n\nclass CameraAndroid(CameraBase):\n    \"\"\"\n    Implementation of CameraBase using Android API\n    \"\"\"\n\n    _update_ev = None\n\n    def __init__(self, **kwargs):\n        self._android_camera = None\n        self._preview_cb = PreviewCallback(self._on_preview_frame)\n        self._buflock = threading.Lock()\n        super(CameraAndroid, self).__init__(**kwargs)\n\n    def __del__(self):\n        self._release_camera()\n\n    def init_camera(self):\n        self._release_camera()\n        self._android_camera = Camera.open(self._index)\n        params = self._android_camera.getParameters()\n        width, height = self._resolution\n        params.setPreviewSize(width, height)\n        supported_focus_modes = self._android_camera.getParameters() \\\n            .getSupportedFocusModes()\n        if supported_focus_modes.contains('continuous-picture'):\n            params.setFocusMode('continuous-picture')\n        self._android_camera.setParameters(params)\n        # self._android_camera.setDisplayOrientation()\n        self.fps = 30.\n\n        pf = params.getPreviewFormat()\n        assert pf == ImageFormat.NV21  # default format is NV21\n        self._bufsize = int(ImageFormat.getBitsPerPixel(pf) / 8. *\n                            width * height)\n\n        self._camera_texture = Texture(width=width, height=height,\n                                       target=GL_TEXTURE_EXTERNAL_OES,\n                                       colorfmt='rgba')\n        self._surface_texture = SurfaceTexture(int(self._camera_texture.id))\n        self._android_camera.setPreviewTexture(self._surface_texture)\n\n        self._fbo = Fbo(size=self._resolution)\n        self._fbo['resolution'] = (float(width), float(height))\n        self._fbo.shader.fs = '''\n            #extension GL_OES_EGL_image_external : require\n            #ifdef GL_ES\n                precision highp float;\n            #endif\n\n            /* Outputs from the vertex shader */\n            varying vec4 frag_color;\n            varying vec2 tex_coord0;\n\n            /* uniform texture samplers */\n            uniform sampler2D texture0;\n            uniform samplerExternalOES texture1;\n            uniform vec2 resolution;\n\n            void main()\n            {\n                vec2 coord = vec2(tex_coord0.y * (\n                    resolution.y / resolution.x), 1. -tex_coord0.x);\n                gl_FragColor = texture2D(texture1, tex_coord0);\n            }\n        '''\n        with self._fbo:\n            self._texture_cb = Callback(lambda instr:\n                                        self._camera_texture.bind)\n            Rectangle(size=self._resolution)\n\n    def _release_camera(self):\n        if self._android_camera is None:\n            return\n\n        self.stop()\n        self._android_camera.release()\n        self._android_camera = None\n\n        # clear texture and it'll be reset in `_update` pointing to new FBO\n        self._texture = None\n        del self._fbo, self._surface_texture, self._camera_texture\n\n    def _on_preview_frame(self, data, camera):\n        with self._buflock:\n            if self._buffer is not None:\n                # add buffer back for reuse\n                self._android_camera.addCallbackBuffer(self._buffer)\n            self._buffer = data\n        # check if frame grabbing works\n        # print self._buffer, len(self.frame_data)\n\n    def _refresh_fbo(self):\n        self._texture_cb.ask_update()\n        self._fbo.draw()\n\n    def start(self):\n        super(CameraAndroid, self).start()\n\n        with self._buflock:\n            self._buffer = None\n        for k in range(2):  # double buffer\n            buf = b'\\x00' * self._bufsize\n            self._android_camera.addCallbackBuffer(buf)\n        self._android_camera.setPreviewCallbackWithBuffer(self._preview_cb)\n\n        self._android_camera.startPreview()\n        if self._update_ev is not None:\n            self._update_ev.cancel()\n        self._update_ev = Clock.schedule_interval(self._update, 1 / self.fps)\n\n    def stop(self):\n        super(CameraAndroid, self).stop()\n        if self._update_ev is not None:\n            self._update_ev.cancel()\n            self._update_ev = None\n        self._android_camera.stopPreview()\n\n        self._android_camera.setPreviewCallbackWithBuffer(None)\n        # buffer queue cleared as well, to be recreated on next start\n        with self._buflock:\n            self._buffer = None\n\n    def _update(self, dt):\n        self._surface_texture.updateTexImage()\n        self._refresh_fbo()\n        if self._texture is None:\n            self._texture = self._fbo.texture\n            self.dispatch('on_load')\n        self._copy_to_gpu()\n\n    def _copy_to_gpu(self):\n        \"\"\"\n        A dummy placeholder (the image is already in GPU) to be consistent\n        with other providers.\n        \"\"\"\n        self.dispatch('on_texture')\n\n    def grab_frame(self):\n        \"\"\"\n        Grab current frame (thread-safe, minimal overhead)\n        \"\"\"\n        with self._buflock:\n            if self._buffer is None:\n                return None\n            buf = self._buffer.tostring()\n            return buf\n\n    def decode_frame(self, buf):\n        \"\"\"\n        Decode image data from grabbed frame.\n\n        This method depends on OpenCV and NumPy - however it is only used for\n        fetching the current frame as a NumPy array, and not required when\n        this :class:`CameraAndroid` provider is simply used by a\n        :class:`~kivy.uix.camera.Camera` widget.\n        \"\"\"\n        import numpy as np\n        from cv2 import cvtColor\n\n        w, h = self._resolution\n        arr = np.fromstring(buf, 'uint8').reshape((h + h // 2, w))\n        arr = cvtColor(arr, 93)  # NV21 -> BGR\n        return arr\n\n    def read_frame(self):\n        \"\"\"\n        Grab and decode frame in one call\n        \"\"\"\n        return self.decode_frame(self.grab_frame())\n\n    @staticmethod\n    def get_camera_count():\n        \"\"\"\n        Get the number of available cameras.\n        \"\"\"\n        return Camera.getNumberOfCameras()\n", "path": "kivy/core/camera/camera_android.py"}]}