summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/camera/vita
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/camera/vita')
-rw-r--r--contrib/SDL-3.2.8/src/camera/vita/SDL_camera_vita.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/camera/vita/SDL_camera_vita.c b/contrib/SDL-3.2.8/src/camera/vita/SDL_camera_vita.c
new file mode 100644
index 0000000..42a5a89
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/camera/vita/SDL_camera_vita.c
@@ -0,0 +1,258 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_CAMERA_DRIVER_VITA
24
25#include "../SDL_syscamera.h"
26#include <psp2/camera.h>
27#include <psp2/kernel/sysmem.h>
28
29static struct {
30 Sint32 w;
31 Sint32 h;
32 Sint32 res;
33} resolutions[] = {
34 {640, 480, SCE_CAMERA_RESOLUTION_640_480},
35 {320, 240, SCE_CAMERA_RESOLUTION_320_240},
36 {160, 120, SCE_CAMERA_RESOLUTION_160_120},
37 {352, 288, SCE_CAMERA_RESOLUTION_352_288},
38 {176, 144, SCE_CAMERA_RESOLUTION_176_144},
39 {480, 272, SCE_CAMERA_RESOLUTION_480_272},
40 {640, 360, SCE_CAMERA_RESOLUTION_640_360},
41 {0, 0, 0}
42};
43
44static Sint32 fps[] = {5, 10, 15, 20, 24, 25, 30, 60, 0};
45
46static void GatherCameraSpecs(Sint32 devid, CameraFormatAddData *add_data, char **fullname, SDL_CameraPosition *position)
47{
48 SDL_zerop(add_data);
49
50 if (devid == SCE_CAMERA_DEVICE_FRONT) {
51 *position = SDL_CAMERA_POSITION_FRONT_FACING;
52 *fullname = SDL_strdup("Front-facing camera");
53 } else if (devid == SCE_CAMERA_DEVICE_BACK) {
54 *position = SDL_CAMERA_POSITION_BACK_FACING;
55 *fullname = SDL_strdup("Back-facing camera");
56 }
57
58 if (!*fullname) {
59 *fullname = SDL_strdup("Generic camera");
60 }
61
62 // Note: there are actually more fps and pixelformats. Planar YUV is fastest. Support only YUV and integer fps for now
63 Sint32 idx = 0;
64 while (resolutions[idx].res > 0) {
65 Sint32 fps_idx = 0;
66 while (fps[fps_idx] > 0) {
67 SDL_AddCameraFormat(add_data, SDL_PIXELFORMAT_IYUV, SDL_COLORSPACE_BT601_LIMITED, resolutions[idx].w, resolutions[idx].h, fps[fps_idx], 1); /* SCE_CAMERA_FORMAT_ARGB */
68 fps_idx++;
69 }
70 idx++;
71 }
72}
73
74static bool FindVitaCameraByID(SDL_Camera *device, void *userdata)
75{
76 Sint32 devid = (Sint32) userdata;
77 return (devid == (Sint32)device->handle);
78}
79
80static void MaybeAddDevice(Sint32 devid)
81{
82 #if DEBUG_CAMERA
83 SDL_Log("CAMERA: MaybeAddDevice('%d')", devid);
84 #endif
85
86 if (SDL_FindPhysicalCameraByCallback(FindVitaCameraByID, (void *) devid)) {
87 return; // already have this one.
88 }
89
90 SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN;
91 char *fullname = NULL;
92 CameraFormatAddData add_data;
93 GatherCameraSpecs(devid, &add_data, &fullname, &position);
94
95 if (add_data.num_specs > 0) {
96 SDL_AddCamera(fullname, position, add_data.num_specs, add_data.specs, (void*)devid);
97 }
98
99 SDL_free(fullname);
100 SDL_free(add_data.specs);
101}
102
103static SceUID imbUid = -1;
104
105static void freeBuffers(SceCameraInfo* info)
106{
107 if (imbUid != -1) {
108 sceKernelFreeMemBlock(imbUid);
109 info->pIBase = NULL;
110 imbUid = -1;
111 }
112}
113
114static bool VITACAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
115{
116 // we can't open more than one camera, so error-out early
117 if (imbUid != -1) {
118 return SDL_SetError("Only one camera can be active");
119 }
120
121 SceCameraInfo* info = (SceCameraInfo*)SDL_calloc(1, sizeof(SceCameraInfo));
122
123 info->size = sizeof(SceCameraInfo);
124 info->priority = SCE_CAMERA_PRIORITY_SHARE;
125 info->buffer = 0; // target buffer set by sceCameraOpen
126
127 info->framerate = spec->framerate_numerator / spec->framerate_denominator;
128
129 Sint32 idx = 0;
130 while (resolutions[idx].res > 0) {
131 if (spec->width == resolutions[idx].w && spec->height == resolutions[idx].h) {
132 info->resolution = resolutions[idx].res;
133 break;
134 }
135 idx++;
136 }
137
138 info->range = 1;
139 info->format = SCE_CAMERA_FORMAT_YUV420_PLANE;
140 info->pitch = 0; // same size surface
141
142 info->sizeIBase = spec->width*spec->height;;
143 info->sizeUBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
144 info->sizeVBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
145
146 // PHYCONT memory size *must* be a multiple of 1MB, we can just always spend 2MB, since we don't use PHYCONT anywhere else
147 imbUid = sceKernelAllocMemBlock("CameraI", SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW, 2*1024*1024 , NULL);
148 if (imbUid < 0)
149 {
150 return SDL_SetError("sceKernelAllocMemBlock error: 0x%08X", imbUid);
151 }
152 sceKernelGetMemBlockBase(imbUid, &(info->pIBase));
153
154 info->pUBase = info->pIBase + info->sizeIBase;
155 info->pVBase = info->pIBase + (info->sizeIBase + info->sizeUBase);
156
157 device->hidden = (struct SDL_PrivateCameraData *)info;
158
159 int ret = sceCameraOpen((int)device->handle, info);
160 if (ret == 0) {
161 ret = sceCameraStart((int)device->handle);
162 if (ret == 0) {
163 SDL_CameraPermissionOutcome(device, true);
164 return true;
165 } else {
166 SDL_SetError("sceCameraStart error: 0x%08X", imbUid);
167 }
168 } else {
169 SDL_SetError("sceCameraOpen error: 0x%08X", imbUid);
170 }
171
172 freeBuffers(info);
173
174 return false;
175}
176
177static void VITACAMERA_CloseDevice(SDL_Camera *device)
178{
179 if (device->hidden) {
180 sceCameraStop((int)device->handle);
181 sceCameraClose((int)device->handle);
182 freeBuffers((SceCameraInfo*)device->hidden);
183 SDL_free(device->hidden);
184 }
185}
186
187static bool VITACAMERA_WaitDevice(SDL_Camera *device)
188{
189 while(!sceCameraIsActive((int)device->handle)) {}
190 return true;
191}
192
193static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
194{
195 SceCameraRead read = {0};
196 read.size = sizeof(SceCameraRead);
197 read.mode = 1; // don't wait next frame
198
199 int ret = sceCameraRead((int)device->handle, &read);
200
201 if (ret < 0) {
202 SDL_SetError("sceCameraRead error: 0x%08X", ret);
203 return SDL_CAMERA_FRAME_ERROR;
204 }
205
206 *timestampNS = read.timestamp;
207
208 SceCameraInfo* info = (SceCameraInfo*)(device->hidden);
209
210 frame->pitch = info->width;
211 frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), info->sizeIBase + info->sizeUBase + info->sizeVBase);
212
213 if (frame->pixels) {
214 SDL_memcpy(frame->pixels, info->pIBase, info->sizeIBase + info->sizeUBase + info->sizeVBase);
215 return SDL_CAMERA_FRAME_READY;
216 }
217
218 return SDL_CAMERA_FRAME_ERROR;
219}
220
221static void VITACAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame)
222{
223 SDL_aligned_free(frame->pixels);
224}
225
226static void VITACAMERA_DetectDevices(void)
227{
228 MaybeAddDevice(SCE_CAMERA_DEVICE_FRONT);
229 MaybeAddDevice(SCE_CAMERA_DEVICE_BACK);
230}
231
232static void VITACAMERA_FreeDeviceHandle(SDL_Camera *device)
233{
234}
235
236static void VITACAMERA_Deinitialize(void)
237{
238}
239
240static bool VITACAMERA_Init(SDL_CameraDriverImpl *impl)
241{
242 impl->DetectDevices = VITACAMERA_DetectDevices;
243 impl->OpenDevice = VITACAMERA_OpenDevice;
244 impl->CloseDevice = VITACAMERA_CloseDevice;
245 impl->WaitDevice = VITACAMERA_WaitDevice;
246 impl->AcquireFrame = VITACAMERA_AcquireFrame;
247 impl->ReleaseFrame = VITACAMERA_ReleaseFrame;
248 impl->FreeDeviceHandle = VITACAMERA_FreeDeviceHandle;
249 impl->Deinitialize = VITACAMERA_Deinitialize;
250
251 return true;
252}
253
254CameraBootStrap VITACAMERA_bootstrap = {
255 "vita", "SDL PSVita camera driver", VITACAMERA_Init, false
256};
257
258#endif // SDL_CAMERA_DRIVER_VITA