Accessing Telephoto lens using Camera2 or CameraX in S21 ultra - android

I’m trying to access telephoto lens on Samsung S21 ultra using Camera2 and CameraX API. It list down two back and two front cameras. See in snapshot attached. But none of these is Telephoto lens. Two cameras accessible via APIs are WIDE and UW lens but Telephoto and Periscope Telephoto are missing.
Can someone confirm if Samsung S21 Ultra telephoto camera is opened to be used in third party apps and can be accessed via Camera2 APIs?
I was also thinking of binding multiple physical cameras to a single logical camera and we can access them but while trying to retrieve physical camera ids from logical cameras. However I’m always getting null value when printing these. See code snippet below.
fun findDualCameras(manager: CameraManager, facing: Int? = null): Array<DualCamera> {
val dualCameras = ArrayList<DualCamera>()
// Iterate over all the available camera characteristics
manager.cameraIdList.map {
Pair(manager.getCameraCharacteristics(it), it)
}.filter {
// Filter by cameras facing the requested direction
facing == null || it.first.get(CameraCharacteristics.LENS_FACING) == facing
}.filter {
// Filter by logical cameras
it.first.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)!!.contains(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
)
}.forEach {
// All possible pairs from the list of physical cameras are valid results
// NOTE: There could be N physical cameras as part of a logical camera grouping
val physicalCameras = it.first.physicalCameraIds.toTypedArray()
for (idx1 in physicalCameras.indices) {
for (idx2 in (idx1 + 1) until physicalCameras.size) {
dualCameras.add(
DualCamera(
it.second, physicalCameras[idx1], physicalCameras[idx2]
)
)
}
}
}
return dualCameras.toTypedArray()
}
Is there any other possibility to access the Telescope camera directly in S21 ultra or Can we get stream from telescope camera indirectly in S21 ultra?

Related

In android if I have min api 21 does cameraX cover all devices or do I need to maintain a camera1 implementation for older devices?

I currently have an app with a minimum api of 21 that has both a camera1 and a camera2 implementation. Based on the following code I select whether to use camera1 or camera2:
val cameraIds = manager.cameraIdList
for (id in cameraIds) {
val info = manager.getCameraCharacteristics(id)
val facing = info.get(CameraCharacteristics.LENS_FACING)!!
val level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)!!
val hasFullLevel = level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL
val syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY)!!
val hasEnoughCapability = syncLatency == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL
// All these are guaranteed by
// CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking
// for only the things we care about expands range of devices we can run on.
// We want:
// - Back-facing camera
// - Per-frame synchronization (so that exposure can be changed every frame)
if (facing == CameraCharacteristics.LENS_FACING_BACK && (hasFullLevel || hasEnoughCapability)) {
// Found suitable camera - get info, open, and set up outputs
foundCamera = true
break
}
}
I plan to, in the near future update to cameraX and I would love to drop the camera1 implementation and have one unified cameraX implementation. Does anyone have experience with cameraX and whether it handles all the cases that I was previously using the camera1 fallback for? A lot of our customers are in developing markets and therefore we need to maintain support for as many older devices as possible.
cameraX does not have a Camera API1 fallback. They rely on camera2 LEGACY support, but yes, the library includes many workarounds for specific problems. Please look at the list of devices they tested: https://developer.android.com/training/camerax/devices.
You don't explain what are "all the cases" you were previously using the camera1 fallback for, but if you have such list, you can go through the release notes to check whether they are addressed by the current version of the library. If they are not, you are welcome to add them to the issues list.

Checking Android device camera video supports at least 30fps

I need to have a function that tells whether I the phone's camera video supports at least 30fps.
I'm using both camera1 and camera2 api, depending on the phone's camera2 support (or lack thereof)
I though about using this :
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameras = manager.cameraIdList
for (camera in cameras) {
val cc = manager.getCameraCharacteristics(camera)
val fpsRange = cc.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES)!!
--> Log.d("TAG", "fps : ${fpsRange.find { it.lower == 30 && it.upper == 30 }}") // is this correct?
}
but I'm not sure whether it's the right solution, I don't understand the ranges that I get and whether I chose the right CameraCharacteristics.
That expression will evaluate to true for a fixed 30fps frame rate (minimum frame rate=maximum frame rate=30). That will be generally supported on all Android devices, since it's required for standard video recording.

Continuously taking pictures using Camera2 API

I'm working on a project where I need to constantly take pictures with some defined resolution, quality and waiting period. The user is able to start/stop the capturing of pictures, the user can also run it with a preview or without a preview (as to do other things with his phone).
I have everything working fine most of the time for most devices but in some strange cases I see bad/blurred pictures. It is worth mentioning that the device is on the move.
Here is my current request:
private fun setRequestParams(builder: CaptureRequest.Builder) {
builder.set(CaptureRequest.BLACK_LEVEL_LOCK, false)
builder.set(CaptureRequest.CONTROL_AWB_LOCK, false)
builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_AE_LOCK, false)
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
builder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0)
builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 0)
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
builder.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.CONTROL_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG)
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,getRange())
builder.set(CaptureRequest.JPEG_QUALITY,pictureConfig.quality.toByte())
val capabilities = cameraCharacteristics?.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
val isManualFocusSupported : Boolean? = capabilities?.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)
if (isManualFocusSupported != null && isManualFocusSupported ) {
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF)
builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f)
}
}
As I mentioned above, The user can either capture photos on foreground or background, for that I create 3 requests, I realized in some phones if there is no linked Surface the camera automatically closes, that's why I use the dummyView.
private val previewRequest: CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(preview!!)
setRequestParams(this)
}.build()
}
private val backgroundPreviewRequest : CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(dummyPreview!!)
}.build()
}
private val captureRequest: CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
addTarget(imageReader!!.surface)
setRequestParams(this)
}.build()
}
When everything is ready I capture a photo :
captureSession?.setRepeatingRequest(previewRequest, null, cameraPreviewHandler)
captureSession?.capture(captureRequest,null, cameraHandler)
When the onImageAvailable is called I capture again. Sometimes I save the image, but if the capture is during the waiting period I just let it continue. Usually the waiting period is of 400ms.
My questions are:
My pictures are sometimes blurred and sometimes not (on the same capturing session) is there something to improve on the request ?
Phones of similar model (SM-A705FN) give inconsistent results. Same phone give partially blurred images when another phone gives good results. Is it possible that the camera's hardware was overused ?
In some phones the camera stops taking pictures without ever calling the camera error callback. Is there a way to know that my picture was lost somewhere ?
In some phones my code doesn't work at all for example Samsung A7 but it works on the Samsung A10 (which is less powerful)
PS: I was using repeatingRequest with almost identical request params but find out that even though the output was slightly higher (pictures were taken faster) the quality was poorer.

Android camera API blurry image on Samsung devices

After implementing the camera2 API for the inApp camera I noticed that on Samsung devices the images appear blurry. After searching about that I found the Sasmung Camera SDK (http://developer.samsung.com/galaxy#camera). So after implementing the SDK on Samsung Galaxy S7 the images are fine now, but on Galaxy S6 they are still blurry. Someone experienced those kind of issues with Samsung devices?
EDIT:
To complement #rcsumners comment. I am setting autofocus by using
mPreviewBuilder.set(SCaptureRequest.CONTROL_AF_TRIGGER, SCaptureRequest.CONTROL_AF_TRIGGER_START);
mSCameraSession.capture(mPreviewBuilder.build(), new SCameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) {
isAFTriggered = true;
}
}, mBackgroundHandler);
It is a long exposure image where the use has to take an image of a static non moving object. For this I am using the CONTROL_AF_MODE_MACRO
mCaptureBuilder.set(SCaptureRequest.CONTROL_AF_MODE, SCaptureRequest.CONTROL_AF_MODE_MACRO);
and also I am enabling auto flash if it is available
requestBuilder.set(SCaptureRequest.CONTROL_AE_MODE,
SCaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
I am not really an expert in this API, I mostly followed the SDK example app.
There could be a number of issues causing this problem. One prominent one is the dimensions of your output image
I ran Camera2 API and the preview is clear, but the output was quite blurry
val characteristics: CameraCharacteristics? = cameraManager.getCameraCharacteristics(cameraId)
val size = characteristics?.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.getOutputSizes(ImageFormat.JPEG) // The issue
val width = imageDimension.width
val height = imageDimension.height
if (size != null) {
width = size[0].width; height = size[0].height
}
val imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 5)
The code below was returning a dimension about 245*144 which was way to small to be sent to the image reader. Some how the output was stretching the image making it end up been blurry. Therefore I removed this line below.
val size = characteristics?.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.getOutputSizes(ImageFormat.JPEG) // this was returning a small
Setting the width and height manually resolved the issue.
You're setting the AF trigger for one frame, but then are you waiting for AF to complete? For AF_MODE_MACRO (are you verifying the device lists support for this AF mode?) you need to wait for AF_STATE_FOCUSED_LOCKED before the image is guaranteed to be stable and sharp. (You may also receive NOT_FOCUSED_LOCKED if the AF algorithm can't reach sharp focus, which could be because the object is just too close for the lens, or the scene is too confusing)
On most modern devices, it's recommended to use CONTINUOUS_PICTURE and not worry about AF triggering unless you really want to lock focus for some time period. In that mode, the device will continuously try to focus to the best of its ability. I'm not sure all that many devices support MACRO, to begin with.

How to set EXPOSURE_TIME and FRAME_DURATION, CaptureRequest.Builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,x) dose not work

I want to adjust the exposure time and frame duration of an Adroid phone. I read some papers saying Android doesn't provide exposure time setting API. I tried using HTC m8x phone whose camera itself support different exposure time from 4 to 1/8000, so I guess there should some way to change it in an app.
The method get(CaptureRequest.EXPOSURE_TIME) returns null. After I used CaptureRequest.Builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,x), the CaptureRequest.SENSOR_EXPOSURE_TIME becomes x, but the preview effect in the phone doesn't change.
I checked the authority of HTC m8x, the code is as :
Activity activity = getActivity();
CameraManager manager =(CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics= manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
if (characteristics.get(CameraCharacteristics.LENS_FACING)== CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
int level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
boolean hasFullLevel
= (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
int syncLatency = characteristics.get(CameraCharacteristics.SYNC_MAX_LATENCY);
boolean hasManualControl = hasCapability(capabilities,CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
boolean hasEnoughCapability = hasManualControl &&syncLatency == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
// All these are guaranteed by
// CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking for only
// the things we care about expands range of devices we can run on
// We want:
// - Back-facing camera
// - Manual sensor control
// - Per-frame synchronization (so that exposure can be changed every frame)
if ( hasFullLevel !! hasEnoughCapability) {
mCameraId = cameraId;
return;}
}
There is no camera id returned.
characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) =2;
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1;
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1;
capabilities =0;
characteristics.get(CameraCharacteristics.SYNC_MAX_LATENCY) =-1
CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL = 0;
So does this show I don't have the authority to change exposure time of HTC m8x phone? Will root the phone help?
It looks like your phone ships with Android 4.x and the new camera2 API requires Lollipop/API 21. If you have upgraded to API21, yes, if it does have full control it would tell you it does support manual exposure control... if it has limited support...
check REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR for the individual control you want like exposure...
if it has legacy support, no it doesn't support manual controls.

Categories

Resources