My Nexus 5 isn't supporting the HDR scene mode of the camera api (as well as the camera2 api). Is this due to the manufacturer support? If so, what I want to implement HDR scene mode in a custom camera app as in the stock camera?
I tried using both the camera APIs but none was supporting the SCENE_MODE_HDR parameter.
Using the android.hardware.camera api: (Logs HDR mode not supported)
List<String> sceneModes = params.getSupportedSceneModes();
if (sceneModes.contains(Camera.Parameters.SCENE_MODE_HDR)) {
Log.d("HDR", "HDR mode supported");
params.setSceneMode(Camera.Parameters.SCENE_MODE_HDR);
} else {
Log.d("HDR", "HDR mode not supported");
}
And using the android.hardware.camera2 api: (Logs HDR mode not supported)
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int[] sceneModes= characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES);
boolean isHDRsupported = false;
for (int sceneMode : sceneModes) {
if (sceneMode == CameraCharacteristics.CONTROL_SCENE_MODE_HDR) {
isHDRsupported = true;
break;
}
}
Log.d("HDR", "HDR mode " + (isHDRsupported ? "" : "not ") + "supported");
Am I missing something obvious here?
The Nexus 5 does not have support for an HDR scene mode.
The HDR+ mode in the included camera app is part of the application itself (there's a blog post about how it works on top of the camera2 API).
Did you try?
Camera.Parameters cameraParameters = camera.getParameters();
cameraParameters.setSceneMode(Camera.Parameters.SCENE_MODE_HDR);
camera.setParameters(cameraParameters);
Related
I'm using Camera Package for developing android app to turn on flash light, like this:
Camera mCamera = Camera.open();
List<String> flashModes = mCamera.getParameters().getSupportedFlashModes();
if(flashModes != null && flashModes.contains(Parameters.FLASH_MODE_TORCH)){
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
} else if (flashModes != null && flashModes.contains(Parameters.FLASH_MODE_ON)){
parameters.setFlashMode(Parameters.FLASH_MODE_ON);
mCamera.setParameters(parameters);
}
if(!previewing){
mCamera.startPreview();
previewing = true;
}
It check supporting camera flash modes, and adjust it. It works in Samsung Android devices, and some others, but doesn't works in LG V20, LG V30 and Mi Android. I searched for this and tried:
mCamera.autoFocus(Camera.AutoFocusCallback)
mCamera.setPreviewTexture(SurfaceTexture)
But nothing works. So I used Camera2 package for api>23, like:
CameraManager mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
mCameraManager.setTorchMode("0", true);
And it works, but in Samsung device, an notification show up "Flashlight turned on" and it's very annoying.
So, I need the way to turn on flashlight for all devices with Camera package, or not to show up "Flashlight turned on" notification using Camera2 package.
I look forward to your reply, thanks.
The answer in below link saves my life!
The SurfaceView is essential for some devices.
LED flashlight on Galaxy Nexus controllable by what API?
I've been working on an app that needs to turn the flashlight on and off on an Android phone. I need a way to turn on the flashlight across ALL versions of Android above API 15. The problem is, on older phones (API < 21), I have to use the traditional way (below). But on newer phones, like my Nexus 6P, I have to use the Camera2 interface (below the below). Is there one way to have the flashlight torch work on ALL versions of Android with one set of code?
Below:
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
camera.startPreview();
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.stopPreview();
// camera.release(); used later when app closes
Below the Below:
CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String cameraId = cameraManager.getCameraIdList()[0];
cameraManager.setTorchMode(cameraId, state); // state is either true or false
A possible solution is to segment different sdk versions during runtime to determine which method to choose:
private final int sdkVersion = Build.VERSION.SDK_INT;
if (sdkVersion < Build.VERSION_CODES.LOLLIPOP) {
//do old way
} else {
//do new way
}
More information here: How to support multiple android version in your code?
While googling, I've got this information that if I want to enable my camera to record high frame rate video on android device, I need to put specific parameters by device vendor for calling camera APIs.
For example, by calling the methods as below, I could enable my Galaxy S6 camera app recording 120 fps constantly.
camera = Camera.open();
Camera.Parameters parms = camera.getParameters();
// for 120fps
parms.set("fast-fps-mode", 2); // 2 for 120fps
parms.setPreviewFpsRange(120000, 120000);
But the problem is no all devices(including LG, and other vendors) support 120 fps(or higher). So I need to know maximum fps in API level in real-time when run my camera app for error handling.
In my case, Camera.Parameters.getSupportedPreviewFpsRange() not worked for me.
It only returns maximum 30000(meaning 30fps) even it could record at 120000(120 fps). I think it because recording at high frame rate(more than 30 fps) is strongly related with camera hardware property and that's why I need to call vendor specific APIs.
Is there a common way to get maximum fps by camera device in API level?
---------------------- EDIT ----------------------
On API21(LOLLIPOP), we could use StreamConfigurationMap to get maximum value for high speed fps recording. The usage is as below.
CameraManager manager = (CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Range<Integer>[] fpsRange = map.getHighSpeedVideoFpsRanges(); // this range intends available fps range of device's camera.
You can get that information via CamcoderProfile starting API-21 as follows:
for (String cameraId : manager.getCameraIdList()) {
int id = Integer.valueOf(cameraId);
if (CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_HIGH_SPEED_LOW)) {
CamcorderProfile profile = CamcorderProfile.get(id, CamcorderProfile.QUALITY_HIGH_SPEED_LOW);
int videoFrameRate = profile.videoFrameRate;
//...
}
}
This will give you the lowest available profile supporting high speed capture. I doubt there are many pre-Lollipop devices out there with such hardware possibilities (if any at all), so this should get you covered.
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.
I'm trying to develop an app which uses the Camera. So far it's been working well, except that I'm unable to force the orientation to be "portrait". It seems to work well if I force all activities to "landscape", because the camera preview seems to fit in landscape.
Is there anyway to use the Camera in portrait mode?
Android devices v2.2 and above contain and API to rotate the display to portrait. Devices below 2.2 are landscape only. Your best bet is to detect if the device is 2.2 and rotate 90 degrees. Fall back on landscape for devices under 2.2. The good news is most Android devices are on 2.2 and above.
Check out my answer here for more info:
Camera is wrong unless keyboard is open
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, acquire the camera and tell it where to draw.
mCamera = Camera.open();
Parameters params = mCamera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
}
try
{
mCamera.setPreviewDisplay(holder);
}
catch (IOException exception)
{
mCamera.release();
mCamera = null;
}
}
edit: I was in the midst of Adobe AIR for Android development when I answered this question, and looking back at it, I realize this question didn't pertain to Adobe AIR.
Adobe says:
On devices that can change the screen orientation, such as mobile phones, a Video object attached to the camera will only show upright video in a landscape-aspect orientation. Thus, mobile apps should use a landscape orientation when displaying video and should not auto-rotate.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Camera.html
If you do really want to use the camera in portrait mode, my suggestion is to rotate the video object.
Here's some sample code that rotates the video object (_video) by an angle in degrees (source was pulled from elsewhere on stackoverflow):
var matrix:Matrix = _video.transform.matrix;
var rect:Rectangle = _video.getBounds(this);
matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2)));
matrix.rotate((angle/180)*Math.PI);
matrix.translate(rect.left + (rect.width/2), rect.top + (rect.height/2));
_video.transform.matrix = matrix;