1 /* 2 * Copyright (C) 2013-2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_SERVERS_CAMERA_CAMERADEVICEBASE_H 18 #define ANDROID_SERVERS_CAMERA_CAMERADEVICEBASE_H 19 20 #include <list> 21 22 #include <utils/RefBase.h> 23 #include <utils/String16.h> 24 #include <utils/Vector.h> 25 #include <utils/KeyedVector.h> 26 #include <utils/Timers.h> 27 #include <utils/List.h> 28 #include <gui/Flags.h> 29 30 #include "hardware/camera2.h" 31 #include "camera/CameraMetadata.h" 32 #include "camera/CaptureResult.h" 33 #if not WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES 34 #include "gui/IGraphicBufferProducer.h" 35 #endif 36 #include "device3/Camera3StreamInterface.h" 37 #include "device3/StatusTracker.h" 38 #include "binder/Status.h" 39 #include "FrameProcessorBase.h" 40 #include "FrameProducer.h" 41 #include "utils/IPCTransport.h" 42 #include "utils/SessionConfigurationUtils.h" 43 44 #include "CameraOfflineSessionBase.h" 45 46 namespace android { 47 48 namespace camera3 { 49 50 typedef enum camera_stream_configuration_mode { 51 CAMERA_STREAM_CONFIGURATION_NORMAL_MODE = 0, 52 CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1, 53 CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START = 0x8000 54 } camera_stream_configuration_mode_t; 55 56 // Matches definition of camera3_jpeg_blob in camera3.h and HIDL definition 57 // device@3.2:types.hal, needs to stay around till HIDL support is removed (for 58 // HIDL -> AIDL cameraBlob translation) 59 typedef struct camera_jpeg_blob { 60 uint16_t jpeg_blob_id; 61 uint32_t jpeg_size; 62 } camera_jpeg_blob_t; 63 64 enum { 65 CAMERA_JPEG_BLOB_ID = 0x00FF, 66 CAMERA_JPEG_APP_SEGMENTS_BLOB_ID = 0x0100, 67 }; 68 69 } // namespace camera3 70 71 using camera3::camera_request_template_t;; 72 using camera3::camera_stream_configuration_mode_t; 73 using camera3::camera_stream_rotation_t; 74 using camera3::SurfaceHolder; 75 76 class CameraProviderManager; 77 78 // Mapping of output stream index to surface ids 79 typedef std::unordered_map<int, std::vector<size_t> > SurfaceMap; 80 81 /** 82 * Base interface for version >= 2 camera device classes, which interface to 83 * camera HAL device versions >= 2. 84 */ 85 class CameraDeviceBase : public virtual FrameProducer { 86 public: 87 virtual ~CameraDeviceBase(); 88 89 virtual IPCTransport getTransportType() const = 0; 90 91 /** 92 * The device vendor tag ID 93 */ 94 virtual metadata_vendor_id_t getVendorTagId() const = 0; 95 96 virtual status_t initialize(sp<CameraProviderManager> manager, 97 const std::string& monitorTags) = 0; 98 virtual status_t disconnect() = 0; disconnectClient(int)99 virtual status_t disconnectClient(int) {return OK;}; 100 101 virtual status_t dump(int fd, const Vector<String16> &args) = 0; 102 virtual status_t startWatchingTags(const std::string &tags) = 0; 103 virtual status_t stopWatchingTags() = 0; 104 virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out) = 0; 105 106 /** 107 * The physical camera device's static characteristics metadata buffer, or 108 * the logical camera's static characteristics if physical id is empty. 109 */ 110 virtual const CameraMetadata& infoPhysical(const std::string& physicalId) const = 0; 111 isCompositeJpegRDisabled()112 virtual bool isCompositeJpegRDisabled() const { return false; }; isCompositeHeicDisabled()113 virtual bool isCompositeHeicDisabled() const { return false; } isCompositeHeicUltraHDRDisabled()114 virtual bool isCompositeHeicUltraHDRDisabled() const { return false; } 115 116 struct PhysicalCameraSettings { 117 std::string cameraId; 118 CameraMetadata metadata; 119 120 // Whether the physical camera supports testPatternMode/testPatternData 121 bool mHasTestPatternModeTag = true; 122 bool mHasTestPatternDataTag = true; 123 124 // Original value of TEST_PATTERN_MODE and DATA so that they can be 125 // restored when sensor muting is turned off 126 int32_t mOriginalTestPatternMode = 0; 127 int32_t mOriginalTestPatternData[4] = {}; 128 129 // Original value of SETTINGS_OVERRIDE so that they can be restored if 130 // camera service isn't overwriting the app value. 131 int32_t mOriginalSettingsOverride = ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF; 132 }; 133 typedef List<PhysicalCameraSettings> PhysicalCameraSettingsList; 134 135 /** 136 * Submit request for capture. The CameraDevice takes ownership of the 137 * passed-in buffer. 138 * Output lastFrameNumber is the expected frame number of this request. 139 */ 140 virtual status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL) = 0; 141 142 /** 143 * Submit a list of requests. 144 * Output lastFrameNumber is the expected last frame number of the list of requests. 145 */ 146 virtual status_t captureList(const List<const PhysicalCameraSettingsList> &requests, 147 const std::list<SurfaceMap> &surfaceMaps, 148 int64_t *lastFrameNumber = NULL) = 0; 149 150 /** 151 * Submit request for streaming. The CameraDevice makes a copy of the 152 * passed-in buffer and the caller retains ownership. 153 * Output lastFrameNumber is the last frame number of the previous streaming request. 154 */ 155 virtual status_t setStreamingRequest(const CameraMetadata &request, 156 int64_t *lastFrameNumber = NULL) = 0; 157 158 /** 159 * Submit a list of requests for streaming. 160 * Output lastFrameNumber is the last frame number of the previous streaming request. 161 */ 162 virtual status_t setStreamingRequestList(const List<const PhysicalCameraSettingsList> &requests, 163 const std::list<SurfaceMap> &surfaceMaps, 164 int64_t *lastFrameNumber = NULL) = 0; 165 166 /** 167 * Clear the streaming request slot. 168 * Output lastFrameNumber is the last frame number of the previous streaming request. 169 */ 170 virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL) = 0; 171 172 /** 173 * Wait until a request with the given ID has been dequeued by the 174 * HAL. Returns TIMED_OUT if the timeout duration is reached. Returns 175 * immediately if the latest request received by the HAL has this id. 176 */ 177 virtual status_t waitUntilRequestReceived(int32_t requestId, 178 nsecs_t timeout) = 0; 179 180 /** 181 * Create an output stream of the requested size, format, rotation and dataspace 182 * 183 * For HAL_PIXEL_FORMAT_BLOB formats, the width and height should be the 184 * logical dimensions of the buffer, not the number of bytes. 185 */ 186 virtual status_t createStream(sp<Surface> consumer, 187 uint32_t width, uint32_t height, int format, 188 android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id, 189 const std::string& physicalCameraId, 190 const std::unordered_set<int32_t> &sensorPixelModesUsed, 191 std::vector<int> *surfaceIds = nullptr, 192 int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID, 193 bool isShared = false, bool isMultiResolution = false, 194 uint64_t consumerUsage = 0, 195 int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, 196 int64_t streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, 197 int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT, 198 int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO, 199 int32_t colorSpace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED, 200 bool useReadoutTimestamp = false) 201 = 0; 202 203 /** 204 * Create an output stream of the requested size, format, rotation and 205 * dataspace with a number of consumers. 206 * 207 * For HAL_PIXEL_FORMAT_BLOB formats, the width and height should be the 208 * logical dimensions of the buffer, not the number of bytes. 209 */ 210 virtual status_t createStream(const std::vector<SurfaceHolder>& consumers, 211 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format, 212 android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id, 213 const std::string& physicalCameraId, 214 const std::unordered_set<int32_t> &sensorPixelModesUsed, 215 std::vector<int> *surfaceIds = nullptr, 216 int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID, 217 bool isShared = false, bool isMultiResolution = false, 218 uint64_t consumerUsage = 0, 219 int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD, 220 int64_t streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT, 221 int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT, 222 int32_t colorSpace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED, 223 bool useReadoutTimestamp = false) 224 = 0; 225 226 /** 227 * Create an input stream of width, height, and format. 228 * 229 * Return value is the stream ID if non-negative and an error if negative. 230 */ 231 virtual status_t createInputStream(uint32_t width, uint32_t height, 232 int32_t format, bool multiResolution, /*out*/ int32_t *id) = 0; 233 234 struct StreamInfo { 235 uint32_t width; 236 uint32_t height; 237 238 uint32_t format; 239 bool formatOverridden; 240 uint32_t originalFormat; 241 242 android_dataspace dataSpace; 243 bool dataSpaceOverridden; 244 android_dataspace originalDataSpace; 245 int64_t dynamicRangeProfile; 246 int32_t colorSpace; 247 StreamInfoStreamInfo248 StreamInfo() : width(0), height(0), format(0), formatOverridden(false), originalFormat(0), 249 dataSpace(HAL_DATASPACE_UNKNOWN), dataSpaceOverridden(false), 250 originalDataSpace(HAL_DATASPACE_UNKNOWN), 251 dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD), 252 colorSpace(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED) {} 253 /** 254 * Check whether the format matches the current or the original one in case 255 * it got overridden. 256 */ matchFormatStreamInfo257 bool matchFormat(uint32_t clientFormat) const { 258 if ((formatOverridden && (originalFormat == clientFormat)) || 259 (format == clientFormat)) { 260 return true; 261 } 262 return false; 263 } 264 265 /** 266 * Check whether the dataspace matches the current or the original one in case 267 * it got overridden. 268 */ matchDataSpaceStreamInfo269 bool matchDataSpace(android_dataspace clientDataSpace) const { 270 if ((dataSpaceOverridden && (originalDataSpace == clientDataSpace)) || 271 (dataSpace == clientDataSpace)) { 272 return true; 273 } 274 return false; 275 } 276 277 }; 278 279 /** 280 * Get information about a given stream. 281 */ 282 virtual status_t getStreamInfo(int id, StreamInfo *streamInfo) = 0; 283 284 /** 285 * Set stream gralloc buffer transform 286 */ 287 virtual status_t setStreamTransform(int id, int transform) = 0; 288 289 /** 290 * Delete stream. Must not be called if there are requests in flight which 291 * reference that stream. 292 */ 293 virtual status_t deleteStream(int id) = 0; 294 295 296 /** 297 * This function is responsible for configuring camera streams at the start of a session. 298 * In shared session mode, where multiple clients may access the camera, camera service 299 * applies a predetermined shared session configuration. If the camera is opened in non-shared 300 * mode, this function is a no-op. 301 */ 302 virtual status_t beginConfigure() = 0; 303 304 /** 305 * In shared session mode, this function retrieves the stream ID associated with a specific 306 * output configuration. 307 */ 308 virtual status_t getSharedStreamId(const android::camera3::OutputStreamInfo &config, 309 int *streamId) = 0; 310 311 /** 312 * In shared session mode, this function add surfaces to an existing shared stream ID. 313 */ 314 virtual status_t addSharedSurfaces(int streamId, 315 const std::vector<android::camera3::OutputStreamInfo> &outputInfo, 316 const std::vector<SurfaceHolder>& surfaces, std::vector<int> *surfaceIds = nullptr) = 0; 317 318 /** 319 * In shared session mode, this function remove surfaces from an existing shared stream ID. 320 */ 321 virtual status_t removeSharedSurfaces(int streamId, const std::vector<size_t> &surfaceIds) = 0; 322 323 /** 324 * In shared session mode, this function retrieves the frame processor. 325 */ 326 virtual sp<camera2::FrameProcessorBase> getSharedFrameProcessor() = 0; 327 328 /** 329 * Submit a shared streaming request for streaming. 330 * Output lastFrameNumber is the last frame number of the previous streaming request. 331 */ 332 virtual status_t setSharedStreamingRequest( 333 const PhysicalCameraSettingsList &request, 334 const SurfaceMap &surfaceMap, int32_t *sharedReqID, 335 int64_t *lastFrameNumber = NULL) = 0; 336 337 /** 338 * Clear the shared streaming request slot. 339 * Output lastFrameNumber is the last frame number of the previous streaming request. 340 */ 341 virtual status_t clearSharedStreamingRequest(int64_t *lastFrameNumber = NULL) = 0; 342 343 /** 344 * In shared session mode, only primary clients can change the capture 345 * parameters through capture request or repeating request. When the primary 346 * client sends the capture request to the camera device, the request ID is 347 * overridden by the camera device to maintain unique ID. This API is 348 * similar to captureList API, with only difference that the request ID is 349 * changed by the device before submitting the request to HAL. 350 * Output sharedReqID is the request ID actually used. 351 * Output lastFrameNumber is the expected last frame number of the list of requests. 352 */ 353 virtual status_t setSharedCaptureRequest(const PhysicalCameraSettingsList &request, 354 const SurfaceMap &surfaceMap, int32_t *sharedReqID, 355 int64_t *lastFrameNumber = NULL) = 0; 356 357 /** 358 * Submit a start streaming request. 359 * Output lastFrameNumber is the last frame number of the previous streaming request. 360 */ 361 virtual status_t startStreaming(const int32_t reqId, const SurfaceMap &surfaceMap, 362 int32_t *sharedReqID, int64_t *lastFrameNumber = NULL) = 0; 363 364 virtual int32_t getCaptureResultFMQSize() = 0; 365 366 /** 367 * Take the currently-defined set of streams and configure the HAL to use 368 * them. This is a long-running operation (may be several hundered ms). 369 * 370 * The device must be idle (see waitUntilDrained) before calling this. 371 * 372 * Returns OK on success; otherwise on error: 373 * - BAD_VALUE if the set of streams was invalid (e.g. fmts or sizes) 374 * - INVALID_OPERATION if the device was in the wrong state 375 */ 376 virtual status_t configureStreams(const CameraMetadata& sessionParams, 377 int operatingMode = 378 camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) = 0; 379 380 /** 381 * Retrieve a list of all stream ids that were advertised as capable of 382 * supporting offline processing mode by Hal after the last stream configuration. 383 */ 384 virtual void getOfflineStreamIds(std::vector<int> *offlineStreamIds) = 0; 385 386 #if WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES 387 // get the surface of the input stream 388 virtual status_t getInputSurface(sp<Surface> *surface) = 0; 389 #else 390 // get the buffer producer of the input stream 391 virtual status_t getInputBufferProducer( 392 sp<IGraphicBufferProducer> *producer) = 0; 393 #endif 394 395 /** 396 * Create a metadata buffer with fields that the HAL device believes are 397 * best for the given use case 398 */ 399 virtual status_t createDefaultRequest(camera_request_template_t templateId, 400 CameraMetadata *request) = 0; 401 402 /** 403 * Wait until all requests have been processed. Returns INVALID_OPERATION if 404 * the streaming slot is not empty, or TIMED_OUT if the requests haven't 405 * finished processing in 10 seconds. 406 */ 407 virtual status_t waitUntilDrained() = 0; 408 409 /** 410 * Get Jpeg buffer size for a given jpeg resolution. 411 * Negative values are error codes. 412 */ 413 virtual ssize_t getJpegBufferSize(const CameraMetadata &info, uint32_t width, 414 uint32_t height) const = 0; 415 416 /** 417 * Connect HAL notifications to a listener. Overwrites previous 418 * listener. Set to NULL to stop receiving notifications. 419 */ 420 virtual status_t setNotifyCallback(wp<NotificationListener> listener) = 0; 421 422 /** 423 * Whether the device supports calling notifyAutofocus, notifyAutoExposure, 424 * and notifyAutoWhitebalance; if this returns false, the client must 425 * synthesize these notifications from received frame metadata. 426 */ 427 virtual bool willNotify3A() = 0; 428 429 /** 430 * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel 431 * autofocus call will be returned by the HAL in all subsequent AF 432 * notifications. 433 */ 434 virtual status_t triggerAutofocus(uint32_t id) = 0; 435 436 /** 437 * Cancel auto-focus. The latest ID used in a trigger autofocus/cancel 438 * autofocus call will be returned by the HAL in all subsequent AF 439 * notifications. 440 */ 441 virtual status_t triggerCancelAutofocus(uint32_t id) = 0; 442 443 /** 444 * Trigger pre-capture metering. The latest ID used in a trigger pre-capture 445 * call will be returned by the HAL in all subsequent AE and AWB 446 * notifications. 447 */ 448 virtual status_t triggerPrecaptureMetering(uint32_t id) = 0; 449 450 /** 451 * Flush all pending and in-flight requests. Blocks until flush is 452 * complete. 453 * Output lastFrameNumber is the last frame number of the previous streaming request. 454 */ 455 virtual status_t flush(int64_t *lastFrameNumber = NULL) = 0; 456 457 /** 458 * Prepare stream by preallocating buffers for it asynchronously. 459 * Calls notifyPrepared() once allocation is complete. 460 */ 461 virtual status_t prepare(int streamId) = 0; 462 463 /** 464 * Free stream resources by dumping its unused gralloc buffers. 465 */ 466 virtual status_t tearDown(int streamId) = 0; 467 468 /** 469 * Add buffer listener for a particular stream in the device. 470 */ 471 virtual status_t addBufferListenerForStream(int streamId, 472 wp<camera3::Camera3StreamBufferListener> listener) = 0; 473 474 /** 475 * Prepare stream by preallocating up to maxCount buffers for it asynchronously. 476 * Calls notifyPrepared() once allocation is complete. 477 */ 478 virtual status_t prepare(int maxCount, int streamId) = 0; 479 480 /** 481 * Set the deferred consumer surface and finish the rest of the stream configuration. 482 */ 483 virtual status_t setConsumerSurfaces(int streamId, 484 const std::vector<SurfaceHolder>& consumers, std::vector<int> *surfaceIds /*out*/) = 0; 485 486 /** 487 * Update a given stream. 488 */ 489 virtual status_t updateStream(int streamId, const std::vector<SurfaceHolder> &newSurfaces, 490 const std::vector<android::camera3::OutputStreamInfo> &outputInfo, 491 const std::vector<size_t> &removedSurfaceIds, 492 KeyedVector<sp<Surface>, size_t> *outputMap/*out*/) = 0; 493 494 /** 495 * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not 496 * drop buffers for stream of streamId. 497 */ 498 virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0; 499 500 /** 501 * Returns the maximum expected time it'll take for all currently in-flight 502 * requests to complete, based on their settings 503 */ 504 virtual nsecs_t getExpectedInFlightDuration() = 0; 505 506 /** 507 * switch to offline session 508 */ 509 virtual status_t switchToOffline( 510 const std::vector<int32_t>& streamsToKeep, 511 /*out*/ sp<CameraOfflineSessionBase>* session) = 0; 512 513 /** 514 * Set the current behavior for the ROTATE_AND_CROP control when in AUTO. 515 * 516 * The value must be one of the ROTATE_AND_CROP_* values besides AUTO, 517 * and defaults to NONE. 518 */ 519 virtual status_t setRotateAndCropAutoBehavior( 520 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue, 521 bool fromHal = false) = 0; 522 523 /** 524 * Set the current behavior for the AUTOFRAMING control when in AUTO. 525 * 526 * The value must be one of the AUTOFRAMING_* values besides AUTO. 527 */ 528 virtual status_t setAutoframingAutoBehavior( 529 camera_metadata_enum_android_control_autoframing_t autoframingValue) = 0; 530 531 /** 532 * Whether camera muting (producing black-only output) is supported. 533 * 534 * Calling setCameraMute(true) when this returns false will return an 535 * INVALID_OPERATION error. 536 */ 537 virtual bool supportsCameraMute() = 0; 538 539 /** 540 * Mute the camera. 541 * 542 * When muted, black image data is output on all output streams. 543 */ 544 virtual status_t setCameraMute(bool enabled) = 0; 545 546 /** 547 * Whether the camera device supports zoom override. 548 */ 549 virtual bool supportsZoomOverride() = 0; 550 551 // Set/reset zoom override 552 virtual status_t setZoomOverride(int32_t zoomOverride) = 0; 553 554 /** 555 * Enable/disable camera service watchdog 556 */ 557 virtual status_t setCameraServiceWatchdog(bool enabled) = 0; 558 559 /** 560 * Get the status tracker of the camera device 561 */ 562 virtual wp<camera3::StatusTracker> getStatusTracker() = 0; 563 564 /** 565 * If the device is in eror state 566 */ 567 virtual bool hasDeviceError() = 0; 568 569 /** 570 * Set bitmask for image dump flag 571 */ setImageDumpMask(int mask)572 void setImageDumpMask(int mask) { mImageDumpMask = mask; } 573 574 /** 575 * Set stream use case overrides 576 */ setStreamUseCaseOverrides(const std::vector<int64_t> & useCaseOverrides)577 void setStreamUseCaseOverrides(const std::vector<int64_t>& useCaseOverrides) { 578 mStreamUseCaseOverrides = useCaseOverrides; 579 } 580 clearStreamUseCaseOverrides()581 void clearStreamUseCaseOverrides() {} 582 583 /** 584 * The injection camera session to replace the internal camera 585 * session. 586 */ 587 virtual status_t injectCamera(const std::string& injectedCamId, 588 sp<CameraProviderManager> manager) = 0; 589 590 /** 591 * Stop the injection camera and restore to internal camera session. 592 */ 593 virtual status_t stopInjection() = 0; 594 595 // Inject session parameters into an existing client. 596 virtual status_t injectSessionParams( 597 const CameraMetadata& sessionParams) = 0; 598 599 // Lock to synchronize onDeviceActive and onDeviceIdle callbacks when camera 600 // has been opened in shared mode. 601 mutable Mutex mSharedDeviceActiveLock; 602 protected: 603 bool mImageDumpMask = 0; 604 std::vector<int64_t> mStreamUseCaseOverrides; 605 }; 606 607 }; // namespace android 608 609 #endif 610