diff --git a/camera/MultiCameraApplication/AndroidManifest.xml b/camera/MultiCameraApplication/AndroidManifest.xml
index 3be0329..27c5f0d 100644
--- a/camera/MultiCameraApplication/AndroidManifest.xml
+++ b/camera/MultiCameraApplication/AndroidManifest.xml
@@ -9,7 +9,7 @@
-
+
+ android:theme="@style/AppTheme"
+ android:requestLegacyExternalStorage="true">
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+ android:theme="@style/AppTheme.NoActionBar">">
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/ic_launcher-web.png b/camera/MultiCameraApplication/ic_launcher-web.png
deleted file mode 100644
index 0c90ffe..0000000
Binary files a/camera/MultiCameraApplication/ic_launcher-web.png and /dev/null differ
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/AutoFitTextureView.java b/camera/MultiCameraApplication/java/com/intel/multicamera/AutoFitTextureView.java
index 12ce3b5..e99dac6 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/AutoFitTextureView.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/AutoFitTextureView.java
@@ -26,12 +26,15 @@
public class AutoFitTextureView extends TextureView {
private int mRatioWidth = 0;
private int mRatioHeight = 0;
+
public AutoFitTextureView(Context context) {
this(context, null);
}
+
public AutoFitTextureView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
+
public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@@ -41,6 +44,7 @@ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
* on the ratio calculated from the parameters. Note that the actual sizes of parameters
* don't matter, that is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the
* same result.
+ *
* @param width Relative horizontal size
* @param height Relative vertical size
*/
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/BotmRightCam.java b/camera/MultiCameraApplication/java/com/intel/multicamera/BotmRightCam.java
deleted file mode 100644
index 3772ccd..0000000
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/BotmRightCam.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (c) 2019 Intel Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intel.multicamera;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.*;
-import android.content.pm.PackageManager;
-import android.graphics.ImageFormat;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.graphics.SurfaceTexture;
-import android.hardware.camera2.*;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.CamcorderProfile;
-import android.media.Image;
-import android.media.ImageReader;
-import android.media.MediaRecorder;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.util.Size;
-import android.util.SparseIntArray;
-import android.view.Surface;
-import android.view.TextureView;
-import android.view.View;
-import android.widget.Button;
-import android.widget.Toast;
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.preference.PreferenceManager;
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-public class BotmRightCam {
- Activity mActivity;
- private static final String TAG = "BotmRightCam";
- private String mNextVideoAbsolutePath;
- private CamcorderProfile mProfile;
- /**
- * An {@link AutoFitTextureView} for camera preview.
- */
- private AutoFitTextureView textureView;
- private Button takePictureButton, TakeVideoButton;
-
- private MediaRecorder mMediaRecorder;
- private String cameraId;
- protected CameraDevice cameraDevice;
- protected CameraCaptureSession cameraCaptureSessions;
- protected CaptureRequest captureRequest;
- protected CaptureRequest.Builder captureRequestBuilder;
- private Size imageDimension, previewSize;
- private ImageReader imageReader;
- private File file;
- private Handler mBackgroundHandler;
- private HandlerThread mBackgroundThread;
- private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
- private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
- private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
- private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
- private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
- private SharedPreferences settings;
- /**
- * Whether the app is recording video now
- */
- private boolean mIsRecordingVideo;
-
- // The video file that the hardware camera is about to record into
- // (or is recording into.
- private String mVideoFilename, mPictureFilename;
- private ContentValues mCurrentVideoValues, mCurrentPictureValues;
- byte[] jpegLength;
-
- /**
- * Orientation of the camera sensor
- */
- private int mSensorOrientation;
-
- static {
- ORIENTATIONS.append(Surface.ROTATION_0, 90);
- ORIENTATIONS.append(Surface.ROTATION_90, 0);
- ORIENTATIONS.append(Surface.ROTATION_180, 270);
- ORIENTATIONS.append(Surface.ROTATION_270, 180);
- }
-
- public BotmRightCam(Activity activity, AutoFitTextureView textureView, Button PictureButton,
- Button RecordButton) {
- Log.e(TAG, "constructor called");
- this.mActivity = activity;
- this.textureView = textureView;
- this.textureView.setSurfaceTextureListener(textureListener);
- this.ClickListeners(PictureButton, RecordButton);
- this.settings = PreferenceManager.getDefaultSharedPreferences(activity);
- }
-
- public void ClickListeners(Button PictureButton, Button RecordButton) {
- TakePicureOnClicked(PictureButton);
-
- StartVideoRecording(RecordButton);
- }
-
- private void TakePicureOnClicked(Button PictureButton) {
- takePictureButton = PictureButton;
- if (takePictureButton == null) return;
-
- takePictureButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- takePicture();
- Utils.broadcastNewPicture(mActivity.getApplicationContext(), mCurrentPictureValues);
- }
- });
- }
-
- private void StartVideoRecording(Button RecordButton) {
- TakeVideoButton = RecordButton;
- TakeVideoButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Intent i = new Intent(HomeScreenActivity.this, CameraActivity.class);
- System.out.println(" onCreate Record0");
- if (mIsRecordingVideo) {
- stopRecordingVideo();
- Utils.broadcastNewVideo(mActivity.getApplicationContext(), mCurrentVideoValues);
- takePictureButton.setVisibility(View.VISIBLE);
- } else {
- startRecordingVideo();
- takePictureButton.setVisibility(View.GONE);
- }
- }
- });
- }
-
- TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- // open your camera here
- openCamera(width, height);
- }
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- // Transform you image captured size according to the surface width and height
- configureTransform(width, height);
- }
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- return false;
- }
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- }
- };
-
- public void openCamera(int width, int height) {
- CameraManager manager = (CameraManager)mActivity.getSystemService(Context.CAMERA_SERVICE);
- Log.e(TAG, "is camera open");
- try {
- if (manager.getCameraIdList().length != 4) {
- Log.e(TAG, "this camera is not connected ");
- return;
- }
-
- cameraId = manager.getCameraIdList()[3];
- Log.e(TAG, "is camera open ID" + cameraId);
- CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
- StreamConfigurationMap map =
- characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (map == null) return;
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
-
- if (Key.compareTo("video_list") == 0) {
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
- previewSize = new Size(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- configureTransform(width, height);
- } else {
- previewSize = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG,
- "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
- configureTransform(width, height);
- }
- mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
- configureTransform(width, height);
- startBackgroundThread();
-
- manager.openCamera(cameraId, stateCallback, null);
-
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- Log.e(TAG, "openCamera X");
- }
-
- private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
- @Override
- public void onOpened(CameraDevice camera) {
- // This is called when the camera is open
- Log.e(TAG, "onOpened");
- cameraDevice = camera;
- createCameraPreview();
- }
- @Override
- public void onDisconnected(CameraDevice camera) {
- Log.e(TAG, "onDisconnected");
- closeCamera();
- }
- @Override
- public void onError(CameraDevice camera, int error) {
- Log.e(TAG, "onError");
- closeCamera();
- }
- };
-
- private void configureTransform(int viewWidth, int viewHeight) {
- if (null == textureView || null == previewSize) {
- return;
- }
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- Matrix matrix = new Matrix();
- RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight);
- RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
- float centerX = viewRect.centerX();
- float centerY = viewRect.centerY();
- if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
- float scale = Math.max((float)viewHeight / previewSize.getHeight(),
- (float)viewWidth / previewSize.getWidth());
- matrix.postScale(scale, scale, centerX, centerY);
- matrix.postRotate(90 * (rotation - 2), centerX, centerY);
- } else if (Surface.ROTATION_180 == rotation) {
- matrix.postRotate(180, centerX, centerY);
- }
- textureView.setTransform(matrix);
- }
-
- protected void createCameraPreview() {
- try {
- closePreviewSession();
- SurfaceTexture texture = textureView.getSurfaceTexture();
- if (texture == null) return;
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
-
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
-
- String videoQuality = settings.getString("video_list", "medium");
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
-
- if (Key.compareTo("video_list") == 0) {
- texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
- } else {
- texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
- }
-
- Surface surface = new Surface(texture);
- captureRequestBuilder =
- cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- captureRequestBuilder.addTarget(surface);
- cameraDevice.createCaptureSession(
- Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession cameraCaptureSession) {
- // The camera is already closed
- if (null == cameraDevice) {
- return;
- }
- // When the session is ready, we start displaying the preview.
- cameraCaptureSessions = cameraCaptureSession;
- updatePreview();
- }
- @Override
- public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
- Toast.makeText(mActivity, "Configuration change", Toast.LENGTH_SHORT)
- .show();
- }
- }, null);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- public void releaseMedia() {
- if (null != mMediaRecorder) {
- try {
- mMediaRecorder.stop();
- } catch (IllegalStateException ex) {
- Log.d(TAG, "Stop called before start");
- }
- mMediaRecorder.reset();
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
- }
-
- public void closeCamera() {
- closePreviewSession();
- if (null != cameraDevice) {
- cameraDevice.close();
- cameraDevice = null;
- }
- if (null != imageReader) {
- imageReader.close();
- imageReader = null;
- }
- releaseMedia();
- stopBackgroundThread();
- }
-
- /**
- * Starts a background thread and its {@link Handler}.
- */
- private void startBackgroundThread() {
- mBackgroundThread = new HandlerThread("Camera-4");
- mBackgroundThread.start();
- mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
- }
-
- /**
- * Stops the background thread and its {@link Handler}.
- */
- private void stopBackgroundThread() {
- if (mBackgroundThread != null) {
- mBackgroundThread.quitSafely();
- try {
- mBackgroundThread.join();
- mBackgroundThread = null;
- mBackgroundHandler = null;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- protected void updatePreview() {
- if (null == cameraDevice) {
- Log.e(TAG, "updatePreview error, return");
- }
- captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
- HandlerThread thread = new HandlerThread("Camera Preview");
- thread.start();
- Handler handler = new Handler(thread.getLooper());
- try {
- cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, handler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Retrieves the JPEG orientation from the specified screen rotation.
- *
- * @param rotation The screen rotation.
- * @return The JPEG orientation (one of 0, 90, 270, and 360)
- */
- private int getOrientation(int rotation) {
- // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
- // We have to take that into account and rotate JPEG properly.
- // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
- // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
- return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
- }
-
- protected void takePicture() {
- if (null == cameraDevice) {
- Log.e(TAG, "cameraDevice is null");
- return;
- }
-
- try {
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG, "Selected imageDimension" + imageDimension.getWidth() +
- imageDimension.getHeight());
- ImageReader reader = ImageReader.newInstance(
- imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.JPEG, 1);
- List outputSurfaces = new ArrayList(2);
- outputSurfaces.add(reader.getSurface());
- outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
- captureRequestBuilder =
- cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
- captureRequestBuilder.addTarget(reader.getSurface());
- captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,
- CameraMetadata.CONTROL_MODE_AUTO);
- // Orientation
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
-
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_IMAGE);
- if (fileDetails == null || fileDetails.length < 5) {
- Log.e(TAG, "Invalid file details");
- return;
- }
- mPictureFilename = fileDetails[3];
- mCurrentPictureValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_IMAGE, fileDetails,
- imageDimension.getWidth(), imageDimension.getHeight());
-
- file = new File(mPictureFilename);
-
- ImageReader.OnImageAvailableListener readerListener =
- new ImageReader.OnImageAvailableListener() {
- @Override
- public void onImageAvailable(ImageReader reader) {
- Image image = null;
- try {
- image = reader.acquireLatestImage();
- ByteBuffer buffer = image.getPlanes()[0].getBuffer();
- byte[] bytes = new byte[buffer.capacity()];
- buffer.get(bytes);
- jpegLength = bytes;
- mCurrentPictureValues.put(MediaStore.Images.ImageColumns.SIZE,
- jpegLength);
-
- save(bytes);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (image != null) {
- image.close();
- }
- }
- }
-
- private void save(byte[] bytes) throws IOException {
- OutputStream output = null;
- try {
- output = new FileOutputStream(file);
- output.write(bytes);
- } finally {
- if (null != output) {
- output.close();
- }
- }
- }
- };
- reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
- final CameraCaptureSession.CaptureCallback captureListener =
- new CameraCaptureSession.CaptureCallback() {
- @Override
- public void onCaptureCompleted(CameraCaptureSession session,
- CaptureRequest request,
- TotalCaptureResult result) {
- super.onCaptureCompleted(session, request, result);
- Toast.makeText(mActivity, "Saved:" + file, Toast.LENGTH_SHORT).show();
-
- createCameraPreview();
- }
- };
- cameraDevice.createCaptureSession(
- outputSurfaces, new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession session) {
- try {
- session.capture(captureRequestBuilder.build(), captureListener,
- mBackgroundHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onConfigureFailed(CameraCaptureSession session) {
- }
- }, mBackgroundHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /* Recording Start*/
- private void startRecordingVideo() {
- if (null == cameraDevice || !textureView.isAvailable()) {
- return;
- }
- try {
- closePreviewSession();
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
- setUpMediaRecorder();
- SurfaceTexture texture = textureView.getSurfaceTexture();
- if (texture == null) return;
- texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
- List surfaces = new ArrayList<>();
-
- // Set up Surface for the camera preview
- Surface previewSurface = new Surface(texture);
- surfaces.add(previewSurface);
- captureRequestBuilder.addTarget(previewSurface);
-
- // Set up Surface for the MediaRecorder
- Surface recorderSurface = mMediaRecorder.getSurface();
- surfaces.add(recorderSurface);
- captureRequestBuilder.addTarget(recorderSurface);
-
- // Start a capture session
- // Once the session starts, we can update the UI and start recording
- cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession camCaptureSession) {
- cameraCaptureSessions = camCaptureSession;
- updatePreview();
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- // UI
- TakeVideoButton.setText(R.string.stop);
- mIsRecordingVideo = true;
-
- // Start recording
- mMediaRecorder.start();
- }
- });
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- if (null != mActivity) {
- Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
- }
- }
- }, mBackgroundHandler);
- } catch (CameraAccessException | IOException e) {
- e.printStackTrace();
- }
- }
-
- private void setUpMediaRecorder() throws IOException {
- if (null == mActivity) {
- return;
- }
-
- mMediaRecorder = new MediaRecorder();
- mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
- mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
-
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_VIDEO);
- if (fileDetails == null || fileDetails.length < 5) {
- Log.e(TAG, "Invalid file details");
- return;
- }
- mVideoFilename = fileDetails[3];
- mCurrentVideoValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_VIDEO, fileDetails,
- mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- /**
- * set output file in media recorder
- */
- mMediaRecorder.setOutputFile(mVideoFilename);
- mMediaRecorder.setVideoEncodingBitRate(10000000);
- mMediaRecorder.setVideoFrameRate(30);
- mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
- mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
- mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
-
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- switch (mSensorOrientation) {
- case SENSOR_ORIENTATION_DEFAULT_DEGREES:
- mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
- break;
- case SENSOR_ORIENTATION_INVERSE_DEGREES:
- mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
- break;
- }
- try {
- mMediaRecorder.prepare();
- } catch (IOException ex) {
- Log.e(TAG, "prepare failed for " + mVideoFilename, ex);
- releaseMedia();
- throw new RuntimeException(ex);
- }
- }
-
- private void closePreviewSession() {
- System.out.println(" closePreviewSession");
- if (cameraCaptureSessions != null) {
- cameraCaptureSessions.close();
- cameraCaptureSessions = null;
- }
- }
-
- private void stopRecordingVideo() {
- mIsRecordingVideo = false;
- TakeVideoButton.setText(R.string.record);
-
- // Stop recording
- releaseMedia();
-
- if (null != mActivity) {
- Toast.makeText(mActivity, "Video saved: " + mVideoFilename, Toast.LENGTH_SHORT).show();
- Log.d(TAG, "Video saved: " + mVideoFilename);
- }
- mVideoFilename = null;
-
- createCameraPreview();
- }
-}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/BotmLeftCam.java b/camera/MultiCameraApplication/java/com/intel/multicamera/CameraBase.java
similarity index 58%
rename from camera/MultiCameraApplication/java/com/intel/multicamera/BotmLeftCam.java
rename to camera/MultiCameraApplication/java/com/intel/multicamera/CameraBase.java
index 1d7459d..43af603 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/BotmLeftCam.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/CameraBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
* Copyright (c) 2019 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,11 @@
package com.intel.multicamera;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
-import android.content.*;
-import android.content.pm.PackageManager;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.RectF;
@@ -33,9 +33,10 @@
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.net.Uri;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Message;
+import android.os.SystemClock;
import android.provider.MediaStore;
import android.util.Log;
import android.util.Size;
@@ -43,36 +44,34 @@
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
-import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceManager;
import java.io.*;
import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+import java.util.Optional;
-public class BotmLeftCam {
+public class CameraBase {
Activity mActivity;
- private static final String TAG = "BotmLeftCam";
- private String mNextVideoAbsolutePath;
+ private String TAG;
private CamcorderProfile mProfile;
/**
* An {@link AutoFitTextureView} for camera preview.
*/
private AutoFitTextureView textureView;
- private Button takePictureButton, TakeVideoButton;
+ private ImageButton FullScrn, SettingsView, takePictureButton, TakeVideoButton;
private MediaRecorder mMediaRecorder;
private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
- protected CaptureRequest captureRequest;
protected CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension, previewSize;
private ImageReader imageReader;
@@ -85,6 +84,13 @@ public class BotmLeftCam {
private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private SharedPreferences settings;
+ private FrameLayout frameView0;
+ private SurfaceTexture mSurfaceTexture;
+ private String Capture_Key, Video_key, SettingsKey;
+ private long mRecordingStartTime;
+ private boolean mRecordingTimeCountsDown = false;
+ private static final int MSG_UPDATE_RECORD_TIME = 5;
+
/**
* Whether the app is recording video now
*/
@@ -95,6 +101,8 @@ public class BotmLeftCam {
private String mVideoFilename, mPictureFilename;
private ContentValues mCurrentVideoValues, mCurrentPictureValues;
byte[] jpegLength;
+ private final Handler mHandler;
+ private TextView mRecordingTimeView;
/**
* Orientation of the camera sensor
@@ -108,23 +116,212 @@ public class BotmLeftCam {
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
- public BotmLeftCam(Activity activity, AutoFitTextureView textureView, Button PictureButton,
- Button RecordButton) {
- Log.e(TAG, "constructor called");
+ private RoundedThumbnailView mRoundedThumbnailView;
+ FrameLayout roundedThumbnailViewControlLayout;
+
+ private Uri mCurrentUri;
+ private String[] VideofileDetails;
+
+ public CameraBase(Activity activity, AutoFitTextureView mtextureView, ImageButton[] Button,
+ TextView RecordingTimeView, String[] data,
+ RoundedThumbnailView roundedThumbnailView) {
this.mActivity = activity;
- this.textureView = textureView;
- this.textureView.setSurfaceTextureListener(textureListener);
- this.ClickListeners(PictureButton, RecordButton);
+ this.textureView = mtextureView;
+ this.ClickListeners(Button[0], Button[1]);
+ SettingsView = Button[2];
+ FullScrn = Button[3];
this.settings = PreferenceManager.getDefaultSharedPreferences(activity);
+ cameraId = data[1];
+ TAG = data[0];
+ Capture_Key = data[2];
+ Video_key = data[3];
+ SettingsKey = data[4];
+ mHandler = new MainHandler();
+
+ mRecordingTimeView = RecordingTimeView;
+
+ mRoundedThumbnailView = roundedThumbnailView;
+
+ RoundedThumbnail_setOnClickListners();
+
+ roundedThumbnailViewControlLayout = mActivity.findViewById(R.id.control1);
+
+ Log.e(TAG, "constructor called");
+ }
+
+ private void RoundedThumbnail_setOnClickListners() {
+ mRoundedThumbnailView.setCallback(new RoundedThumbnailView.Callback() {
+ ImageView preView;
+
+ @Override
+ public void onHitStateFinished() {
+ ImageView preView;
+ ImageButton btnDelete, playButton, btnBack;
+ FrameLayout previewLayout;
+
+ String mimeType = Utils.getMimeTypeFromURI(mActivity, mCurrentUri);
+
+ previewLayout = mActivity.findViewById(R.id.previewLayout);
+ previewLayout.setVisibility(View.VISIBLE);
+
+ btnDelete = mActivity.findViewById(R.id.control_delete);
+ playButton = mActivity.findViewById(R.id.play_button);
+ preView = mActivity.findViewById(R.id.preview);
+ btnBack = mActivity.findViewById(R.id.control_back);
+
+ btnBack.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FrameLayout previewLayout;
+ previewLayout = mActivity.findViewById(R.id.previewLayout);
+ previewLayout.setVisibility(View.GONE);
+
+ mRoundedThumbnailView.hideThumbnail();
+ }
+ });
+
+ btnDelete.setOnClickListener(new View.OnClickListener() {
+ ImageView preView;
+
+ @Override
+ public void onClick(View v) {
+ preView = mActivity.findViewById(R.id.preview);
+
+ Uri uri = mCurrentUri;
+ File file = new File(Utils.getRealPathFromURI(mActivity, uri));
+ if (file.exists()) {
+ Log.e(TAG, " File Deleted ");
+ file.delete();
+ preView.setImageResource(android.R.color.background_dark);
+ }
+ }
+ });
+
+ if (mimeType.compareTo("video/mp4") == 0) {
+ VideoPreview(playButton, preView);
+
+ } else {
+ photoPreview(playButton, preView);
+ }
+ }
+ });
+ }
+
+ private void VideoPreview(ImageButton playButton, ImageView preView) {
+ final Optional bitmap =
+ Utils.getVideoThumbnail(mActivity.getContentResolver(), mCurrentUri);
+
+ playButton.setVisibility(View.VISIBLE);
+
+ playButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Utils.playVideo(mActivity, mCurrentUri, TAG);
+ }
+ });
+
+ preView.setVisibility(View.VISIBLE);
+ preView.setImageBitmap(bitmap.get());
+ }
+
+ private void photoPreview(ImageButton playButton, ImageView preView) {
+ Uri PhotoUri = mCurrentUri;
+
+ preView.setVisibility(View.VISIBLE);
+ playButton.setVisibility(View.GONE);
+ preView.setImageURI(PhotoUri);
}
- public void ClickListeners(Button PictureButton, Button RecordButton) {
+ /**
+ * This Handler is used to post message back onto the main thread of the
+ * application.
+ */
+ private class MainHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_RECORD_TIME: {
+ updateRecordingTime();
+ break;
+ }
+
+ default:
+ Log.v(TAG, "Unhandled message: " + msg.what);
+ break;
+ }
+ }
+ }
+
+ private void updateRecordingTime() {
+ if (!mIsRecordingVideo) {
+ return;
+ }
+ long now = SystemClock.uptimeMillis();
+ long delta = now - mRecordingStartTime;
+ long mMaxVideoDurationInMs;
+ mMaxVideoDurationInMs = Utils.getMaxVideoDuration(mActivity);
+
+ // Starting a minute before reaching the max duration
+ // limit, we'll countdown the remaining time instead.
+ boolean countdownRemainingTime =
+ (mMaxVideoDurationInMs != 0 && delta >= mMaxVideoDurationInMs - 60000);
+
+ long deltaAdjusted = delta;
+ if (countdownRemainingTime) {
+ deltaAdjusted = Math.max(0, mMaxVideoDurationInMs - deltaAdjusted) + 999;
+ }
+ String text;
+
+ long targetNextUpdateDelay;
+
+ text = Utils.millisecondToTimeString(deltaAdjusted, false);
+ targetNextUpdateDelay = 1000;
+
+ setRecordingTime(text);
+
+ if (mRecordingTimeCountsDown != countdownRemainingTime) {
+ // Avoid setting the color on every update, do it only
+ // when it needs changing.
+ mRecordingTimeCountsDown = countdownRemainingTime;
+
+ int color = mActivity.getResources().getColor(R.color.recording_time_remaining_text);
+
+ setRecordingTimeTextColor(color);
+ }
+
+ long actualNextUpdateDelay = targetNextUpdateDelay - (delta % targetNextUpdateDelay);
+ mHandler.sendEmptyMessageDelayed(MSG_UPDATE_RECORD_TIME, actualNextUpdateDelay);
+ }
+
+ public void setRecordingTime(String text) {
+ mRecordingTimeView.setText(text);
+ }
+
+ public void setRecordingTimeTextColor(int color) {
+ mRecordingTimeView.setTextColor(color);
+ }
+
+ public void showRecordingUI(boolean recording) {
+ if (recording) {
+ mRecordingTimeView.setText("");
+ mRecordingTimeView.setVisibility(View.VISIBLE);
+ mRecordingTimeView.announceForAccessibility(
+ mActivity.getResources().getString(R.string.video_recording_started));
+
+ } else {
+ mRecordingTimeView.announceForAccessibility(
+ mActivity.getResources().getString(R.string.video_recording_stopped));
+ mRecordingTimeView.setVisibility(View.GONE);
+ }
+ }
+
+ public void ClickListeners(ImageButton PictureButton, ImageButton RecordButton) {
TakePicureOnClicked(PictureButton);
StartVideoRecording(RecordButton);
}
- private void TakePicureOnClicked(Button PictureButton) {
+ private void TakePicureOnClicked(ImageButton PictureButton) {
takePictureButton = PictureButton;
if (takePictureButton == null) return;
@@ -132,25 +329,26 @@ private void TakePicureOnClicked(Button PictureButton) {
@Override
public void onClick(View v) {
takePicture();
- Utils.broadcastNewPicture(mActivity.getApplicationContext(), mCurrentPictureValues);
}
});
}
- private void StartVideoRecording(Button RecordButton) {
+ private void StartVideoRecording(ImageButton RecordButton) {
TakeVideoButton = RecordButton;
+
TakeVideoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- // Intent i = new Intent(HomeScreenActivity.this, CameraActivity.class);
- System.out.println(" onCreate Record0");
if (mIsRecordingVideo) {
stopRecordingVideo();
- Utils.broadcastNewVideo(mActivity.getApplicationContext(), mCurrentVideoValues);
+ showRecordingUI(mIsRecordingVideo);
+ TakeVideoButton.setImageResource(R.drawable.ic_capture_video);
takePictureButton.setVisibility(View.VISIBLE);
+ SettingsView.setEnabled(true);
+ SettingsView.setImageAlpha(200);
+
} else {
startRecordingVideo();
- takePictureButton.setVisibility(View.GONE);
}
}
});
@@ -160,17 +358,21 @@ public void onClick(View view) {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// open your camera here
+ mSurfaceTexture = surface;
openCamera(width, height);
}
+
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
configureTransform(width, height);
}
+
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
+
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@@ -178,39 +380,28 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
public void openCamera(int width, int height) {
CameraManager manager = (CameraManager)mActivity.getSystemService(Context.CAMERA_SERVICE);
- Log.e(TAG, "is camera open");
try {
- if (!((manager.getCameraIdList().length >= 3) &&
- (manager.getCameraIdList().length <= 4))) {
- Log.e(TAG, "this camera is not connected ");
- return;
- }
- cameraId = manager.getCameraIdList()[2];
- Log.e(TAG, "is camera open ID" + cameraId);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) return;
-
settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
- if (Key.compareTo("video_list") == 0) {
- String videoQuality = settings.getString("video_list", "medium");
+ String Key = GetChnagedPrefKey();
+
+ if (Key.compareTo(Capture_Key) == 0) {
+ previewSize = SettingsPrefUtil.sizeFromSettingString(
+ settings.getString(Capture_Key, "640x480"));
+ Log.d(TAG,
+ "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
+ } else {
+ String videoQuality = settings.getString(Video_key, "medium");
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
+ int quality = SettingsPrefUtil.getVideoQuality(0, videoQuality);
Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
mProfile = CamcorderProfile.get(0, quality);
previewSize = new Size(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- configureTransform(width, height);
- } else {
- previewSize = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG,
- "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
- configureTransform(width, height);
}
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
@@ -222,7 +413,7 @@ public void openCamera(int width, int height) {
} catch (CameraAccessException e) {
e.printStackTrace();
}
- Log.e(TAG, "openCamera X");
+ Log.e(TAG, "openCamera");
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@@ -231,20 +422,57 @@ public void onOpened(CameraDevice camera) {
// This is called when the camera is open
Log.e(TAG, "onOpened");
cameraDevice = camera;
+ Ui_Enable(true);
createCameraPreview();
}
+
@Override
public void onDisconnected(CameraDevice camera) {
Log.e(TAG, "onDisconnected");
+ frameView0 = mActivity.findViewById(R.id.control2);
+ frameView0.setVisibility(FrameLayout.INVISIBLE);
closeCamera();
+ Ui_Enable(false);
}
+
@Override
public void onError(CameraDevice camera, int error) {
Log.e(TAG, "onError");
closeCamera();
+ Ui_Enable(false);
+ }
+
+ @Override
+ public void onClosed(@NonNull CameraDevice camera) {
+ Log.e(TAG, "onClose");
+ super.onClosed(camera);
+ SurfaceUtil.clear(mSurfaceTexture);
+ Ui_Enable(false);
}
};
+ private void Ui_Enable(boolean flag) {
+ TakeVideoButton.setEnabled(flag);
+
+ takePictureButton.setEnabled(flag);
+
+ SettingsView.setEnabled(flag);
+
+ FullScrn.setEnabled(flag);
+
+ if (flag) {
+ TakeVideoButton.setImageResource(R.drawable.ic_capture_video);
+ takePictureButton.setImageResource(R.drawable.ic_capture_camera_normal);
+ SettingsView.setImageAlpha(200);
+ FullScrn.setImageAlpha(200);
+ } else {
+ TakeVideoButton.setImageResource(R.drawable.ic_capture_video_disabled);
+ takePictureButton.setImageResource(R.drawable.ic_capture_camera_disabled);
+ SettingsView.setImageAlpha(95);
+ FullScrn.setImageAlpha(95);
+ }
+ }
+
private void configureTransform(int viewWidth, int viewHeight) {
if (null == textureView || null == previewSize) {
return;
@@ -252,7 +480,10 @@ private void configureTransform(int viewWidth, int viewHeight) {
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight);
+ Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight +
+ "previewWidth: " + previewSize.getWidth() +
+ "previewHeight:" + previewSize.getHeight());
+
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
@@ -269,25 +500,68 @@ private void configureTransform(int viewWidth, int viewHeight) {
textureView.setTransform(matrix);
}
+ /**
+ * Retrieve a setting's value as a String, manually specifiying
+ * a default value.
+ */
+ public String getString(String key, String defaultValue) {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mActivity);
+ try {
+ return preferences.getString(key, defaultValue);
+ } catch (ClassCastException e) {
+ Log.w(TAG, "existing preference with invalid type,removing and returning default", e);
+ preferences.edit().remove(key).apply();
+ return defaultValue;
+ }
+ }
+
+ public String GetChnagedPrefKey() {
+ String Key = null;
+
+ switch (SettingsKey) {
+ case "pref_resolution":
+ Key = getString(SettingsKey, "capture_list");
+ break;
+ case "pref_resolution_1":
+ Key = getString(SettingsKey, "capture_list_1");
+ break;
+ case "pref_resolution_2":
+ Key = getString(SettingsKey, "capture_list_2");
+ break;
+ case "pref_resolution_3":
+ Key = getString(SettingsKey, "capture_list_3");
+ break;
+ default:
+ break;
+ }
+
+ return Key;
+ }
+
protected void createCameraPreview() {
try {
closePreviewSession();
SurfaceTexture texture = textureView.getSurfaceTexture();
if (texture == null) return;
+
settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- String videoQuality = settings.getString("video_list", "medium");
+ String Key = GetChnagedPrefKey();
+
+ imageDimension = SettingsPrefUtil.sizeFromSettingString(
+ settings.getString(Capture_Key, "640x480"));
+ String videoQuality = settings.getString(Video_key, "medium");
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
+ int quality = SettingsPrefUtil.getVideoQuality(0, videoQuality);
Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
mProfile = CamcorderProfile.get(0, quality);
- if (Key.compareTo("video_list") == 0) {
+
+ if (Key.compareTo(Video_key) == 0) {
+ previewSize = new Size(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
} else {
+ previewSize = imageDimension;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
}
@@ -307,8 +581,10 @@ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
+
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ closeCamera();
Toast.makeText(mActivity, "Configuration change", Toast.LENGTH_SHORT)
.show();
}
@@ -318,19 +594,6 @@ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
}
}
- public void releaseMedia() {
- if (null != mMediaRecorder) {
- try {
- mMediaRecorder.stop();
- } catch (IllegalStateException ex) {
- Log.d(TAG, "Stop called before start");
- }
- mMediaRecorder.reset();
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
- }
-
public void closeCamera() {
closePreviewSession();
if (null != cameraDevice) {
@@ -349,7 +612,7 @@ public void closeCamera() {
* Starts a background thread and its {@link Handler}.
*/
private void startBackgroundThread() {
- mBackgroundThread = new HandlerThread("Camera-3");
+ mBackgroundThread = new HandlerThread("Camera_1");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
@@ -407,8 +670,8 @@ protected void takePicture() {
try {
settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
+ imageDimension = SettingsPrefUtil.sizeFromSettingString(
+ settings.getString(Capture_Key, "640x480"));
Log.d(TAG, "Selected imageDimension" + imageDimension.getWidth() +
imageDimension.getHeight());
ImageReader reader = ImageReader.newInstance(
@@ -416,6 +679,10 @@ protected void takePicture() {
List outputSurfaces = new ArrayList(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
+
+ textureView.getSurfaceTexture().setDefaultBufferSize(imageDimension.getWidth(),
+ imageDimension.getHeight());
+
captureRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(reader.getSurface());
@@ -423,6 +690,7 @@ protected void takePicture() {
CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
+ final int mRotation = rotation;
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_IMAGE);
@@ -431,9 +699,9 @@ protected void takePicture() {
return;
}
mPictureFilename = fileDetails[3];
- mCurrentPictureValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_IMAGE, fileDetails,
- imageDimension.getWidth(), imageDimension.getHeight());
+ mCurrentPictureValues = Utils.getContentValues(
+ Utils.MEDIA_TYPE_IMAGE, fileDetails, imageDimension.getWidth(),
+ imageDimension.getHeight(), 0, new File(mPictureFilename).length());
file = new File(mPictureFilename);
@@ -483,7 +751,30 @@ public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
- Toast.makeText(mActivity, "Saved:" + file, Toast.LENGTH_SHORT).show();
+
+ Utils.broadcastNewPicture(mActivity.getApplicationContext(),
+ mCurrentPictureValues);
+
+ mCurrentUri = Utils.getCurrentPictureUri();
+
+ mRoundedThumbnailView.startRevealThumbnailAnimation("photo taken");
+
+ final Optional bitmap = Utils.generateThumbnail(
+ file, roundedThumbnailViewControlLayout.getWidth(),
+ roundedThumbnailViewControlLayout.getMeasuredHeight());
+
+ if (bitmap.isPresent()) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mRoundedThumbnailView.setThumbnail(
+ bitmap.get(), getOrientation(mRotation));
+ }
+ });
+
+ } else {
+ Log.e(TAG, "No bitmap image found: ");
+ }
createCameraPreview();
}
@@ -517,9 +808,9 @@ private void startRecordingVideo() {
try {
closePreviewSession();
settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String videoQuality = settings.getString("video_list", "medium");
+ String videoQuality = settings.getString(Video_key, "medium");
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
+ int quality = SettingsPrefUtil.getVideoQuality(0, videoQuality);
Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
mProfile = CamcorderProfile.get(0, quality);
@@ -552,11 +843,17 @@ public void onConfigured(@NonNull CameraCaptureSession camCaptureSession) {
@Override
public void run() {
// UI
- TakeVideoButton.setText(R.string.stop);
mIsRecordingVideo = true;
// Start recording
mMediaRecorder.start();
+ mRecordingStartTime = SystemClock.uptimeMillis();
+ takePictureButton.setVisibility(View.GONE);
+ SettingsView.setEnabled(false);
+ SettingsView.setImageAlpha(95);
+ showRecordingUI(mIsRecordingVideo);
+ TakeVideoButton.setImageResource(R.drawable.ic_stop_normal);
+ updateRecordingTime();
}
});
}
@@ -564,8 +861,10 @@ public void run() {
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
if (null != mActivity) {
- Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
+ Toast.makeText(mActivity, "Recording Failed", Toast.LENGTH_SHORT).show();
}
+
+ releaseMedia();
}
}, mBackgroundHandler);
} catch (CameraAccessException | IOException e) {
@@ -582,21 +881,21 @@ private void setUpMediaRecorder() throws IOException {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_VIDEO);
- if (fileDetails == null || fileDetails.length < 5) {
+ VideofileDetails = Utils.generateFileDetails(Utils.MEDIA_TYPE_VIDEO);
+ if (VideofileDetails == null || VideofileDetails.length < 5) {
Log.e(TAG, "Invalid file details");
return;
}
- mVideoFilename = fileDetails[3];
- mCurrentVideoValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_VIDEO, fileDetails,
- mProfile.videoFrameWidth, mProfile.videoFrameHeight);
+
+ mVideoFilename = VideofileDetails[3];
+ file = new File(mVideoFilename);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
/**
* set output file in media recorder
*/
mMediaRecorder.setOutputFile(mVideoFilename);
+
mMediaRecorder.setVideoEncodingBitRate(10000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
@@ -604,6 +903,7 @@ private void setUpMediaRecorder() throws IOException {
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
+
switch (mSensorOrientation) {
case SENSOR_ORIENTATION_DEFAULT_DEGREES:
mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
@@ -629,17 +929,55 @@ private void closePreviewSession() {
}
}
+ public void releaseMedia() {
+ if (null != mMediaRecorder) {
+ try {
+ mMediaRecorder.stop();
+ } catch (IllegalStateException ex) {
+ Log.d(TAG, "Stop called before start");
+ }
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+ }
+ }
+
+ private void saveVideo() {
+ long duration = SystemClock.uptimeMillis() - mRecordingStartTime;
+ if (duration > 0) {
+ //
+ } else {
+ Log.w(TAG, "Video duration <= 0 : " + duration);
+ }
+
+ mCurrentVideoValues = Utils.getContentValues(
+ Utils.MEDIA_TYPE_VIDEO, VideofileDetails, mProfile.videoFrameWidth,
+ mProfile.videoFrameHeight, duration, new File(mVideoFilename).length());
+
+ Utils.broadcastNewVideo(mActivity.getApplicationContext(), mCurrentVideoValues);
+ }
+
private void stopRecordingVideo() {
+ mHandler.removeMessages(MSG_UPDATE_RECORD_TIME);
mIsRecordingVideo = false;
- TakeVideoButton.setText(R.string.record);
- // Stop recording
releaseMedia();
- if (null != mActivity) {
- Toast.makeText(mActivity, "Video saved: " + mVideoFilename, Toast.LENGTH_SHORT).show();
- Log.d(TAG, "Video saved: " + mVideoFilename);
+ saveVideo();
+
+ mCurrentUri = Utils.getCurrentVideoUri();
+
+ mRoundedThumbnailView.startRevealThumbnailAnimation("Video taken");
+
+ final Optional bitmap =
+ Utils.getVideoThumbnail(mActivity.getContentResolver(), mCurrentUri);
+
+ if (bitmap.isPresent()) {
+ mRoundedThumbnailView.setThumbnail(bitmap.get(), 0);
+ } else {
+ Log.e(TAG, "No bitmap image found: ");
}
+
mVideoFilename = null;
createCameraPreview();
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/TopLeftCam.java b/camera/MultiCameraApplication/java/com/intel/multicamera/CtsCamIntents.java
similarity index 71%
rename from camera/MultiCameraApplication/java/com/intel/multicamera/TopLeftCam.java
rename to camera/MultiCameraApplication/java/com/intel/multicamera/CtsCamIntents.java
index 83c95d9..e888cbb 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/TopLeftCam.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/CtsCamIntents.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
* Copyright (c) 2019 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,9 @@
package com.intel.multicamera;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.*;
-import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.RectF;
@@ -34,10 +32,11 @@
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
import android.provider.MediaStore;
import android.util.Log;
import android.util.Size;
@@ -45,38 +44,36 @@
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
-import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceManager;
import java.io.*;
import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+import java.util.Optional;
-public class TopLeftCam {
+public class CtsCamIntents {
Activity mActivity;
- private static final String TAG = "TopLeftCam";
- private String mNextVideoAbsolutePath;
+ private static final String TAG = "CtsCamIntents";
private CamcorderProfile mProfile;
/**
* An {@link AutoFitTextureView} for camera preview.
*/
private AutoFitTextureView textureView;
- private Button takePictureButton, TakeVideoButton;
+ private ImageView takePictureButton, TakeVideoButton;
private MediaRecorder mMediaRecorder;
private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
- protected CaptureRequest captureRequest;
protected CaptureRequest.Builder captureRequestBuilder;
- private Size imageDimension, previewSize;
+ private Size previewSize;
private ImageReader imageReader;
private File file;
private Handler mBackgroundHandler;
@@ -89,10 +86,19 @@ public class TopLeftCam {
private SharedPreferences settings;
private Uri mCurrentVideoUri = null;
private ParcelFileDescriptor mVideoFileDescriptor = null;
+ private SurfaceTexture mSurfaceTexture;
+ private Surface mOutPutSurface;
+ private FrameLayout frameView0;
+ private long mRecordingStartTime;
+ private boolean mRecordingTimeCountsDown = false;
+ private static final int MSG_UPDATE_RECORD_TIME = 5;
+ private TextView mRecordingTimeView;
+ private final Handler mHandler;
+
/**
* Whether the app is recording video now
*/
- private boolean mIsRecordingVideo, onDoneClicked;
+ private boolean mIsRecordingVideo;
// The video file that the hardware camera is about to record into
// (or is recording into.
@@ -100,7 +106,7 @@ public class TopLeftCam {
private ContentValues mCurrentVideoValues, mCurrentPictureValues;
byte[] jpegLength;
- private boolean mIsVideoCaptureIntent, mIsImageCaptureIntent, mIsonDoneClicked;
+ private boolean mIsVideoCaptureIntent, mIsImageCaptureIntent;
/**
* Orientation of the camera sensor
*/
@@ -113,21 +119,107 @@ public class TopLeftCam {
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
- public TopLeftCam(Activity activity, AutoFitTextureView textureView, Button PictureButton,
- Button RecordButton) {
+ private String[] VideofileDetails;
+
+ public CtsCamIntents(Activity activity, AutoFitTextureView mtextureView,
+ ImageView PictureButton, ImageView RecordButton,
+ TextView RecordingTimeView) {
Log.e(TAG, "constructor called");
this.mActivity = activity;
- onDoneClicked = false;
mIsRecordingVideo = false;
mIsVideoCaptureIntent = isVideoCaptureIntent();
mIsImageCaptureIntent = isImageCaptureIntent();
- this.textureView = textureView;
- this.textureView.setSurfaceTextureListener(textureListener);
+ this.textureView = mtextureView;
this.ClickListeners(PictureButton, RecordButton);
this.settings = PreferenceManager.getDefaultSharedPreferences(activity);
+ mRecordingTimeView = RecordingTimeView;
+ mHandler = new MainHandler();
+ }
+
+ /**
+ * This Handler is used to post message back onto the main thread of the
+ * application.
+ */
+ private class MainHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_RECORD_TIME: {
+ updateRecordingTime();
+ break;
+ }
+
+ default:
+ Log.v(TAG, "Unhandled message: " + msg.what);
+ break;
+ }
+ }
+ }
+
+ private void updateRecordingTime() {
+ if (!mIsRecordingVideo) {
+ return;
+ }
+ long now = SystemClock.uptimeMillis();
+ long delta = now - mRecordingStartTime;
+ long mMaxVideoDurationInMs;
+ mMaxVideoDurationInMs = Utils.getMaxVideoDuration(mActivity);
+
+ // Starting a minute before reaching the max duration
+ // limit, we'll countdown the remaining time instead.
+ boolean countdownRemainingTime =
+ (mMaxVideoDurationInMs != 0 && delta >= mMaxVideoDurationInMs - 60000);
+
+ long deltaAdjusted = delta;
+ if (countdownRemainingTime) {
+ deltaAdjusted = Math.max(0, mMaxVideoDurationInMs - deltaAdjusted) + 999;
+ }
+ String text;
+
+ long targetNextUpdateDelay;
+
+ text = Utils.millisecondToTimeString(deltaAdjusted, false);
+ targetNextUpdateDelay = 1000;
+
+ setRecordingTime(text);
+
+ if (mRecordingTimeCountsDown != countdownRemainingTime) {
+ // Avoid setting the color on every update, do it only
+ // when it needs changing.
+ mRecordingTimeCountsDown = countdownRemainingTime;
+
+ int color = mActivity.getResources().getColor(R.color.recording_time_remaining_text);
+
+ setRecordingTimeTextColor(color);
+ }
+
+ long actualNextUpdateDelay = targetNextUpdateDelay - (delta % targetNextUpdateDelay);
+ mHandler.sendEmptyMessageDelayed(MSG_UPDATE_RECORD_TIME, actualNextUpdateDelay);
+ }
+
+ public void setRecordingTime(String text) {
+ mRecordingTimeView.setText(text);
+ }
+
+ public void setRecordingTimeTextColor(int color) {
+ mRecordingTimeView.setTextColor(color);
+ }
+
+ public void showRecordingUI(boolean recording) {
+ if (recording) {
+ mRecordingTimeView.announceForAccessibility(
+ mActivity.getResources().getString(R.string.video_recording_stopped));
+ mRecordingTimeView.setVisibility(View.GONE);
+
+ } else {
+ mRecordingTimeView.setText("");
+ mRecordingTimeView.setVisibility(View.VISIBLE);
+ mRecordingTimeView.announceForAccessibility(
+ mActivity.getResources().getString(R.string.video_recording_started));
+ }
}
public boolean isVideoCaptureIntent() {
@@ -140,73 +232,78 @@ public boolean isImageCaptureIntent() {
return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
}
- public void ClickListeners(Button PictureButton, Button RecordButton) {
+ public void ClickListeners(ImageView PictureButton, ImageView RecordButton) {
TakePictureOnClicked(PictureButton);
StartVideoRecording(RecordButton);
}
- private void TakePictureOnClicked(Button PictureButton) {
+ private void TakePictureOnClicked(ImageView PictureButton) {
takePictureButton = PictureButton;
if (takePictureButton == null) return;
takePictureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (!onDoneClicked) {
- onDoneClicked = false;
-
- takePicture();
-
- if (mIsImageCaptureIntent) {
- onDoneClicked = true;
- takePictureButton.setText(R.string.done);
- } else {
- Utils.broadcastNewPicture(mActivity.getApplicationContext(),
- mCurrentPictureValues);
- }
+ takePicture();
- } else if (mIsImageCaptureIntent) {
+ if (!mIsImageCaptureIntent) {
+ Utils.broadcastNewPicture(mActivity.getApplicationContext(),
+ mCurrentPictureValues);
+ } else {
mIsImageCaptureIntent = false;
- onDoneClicked = false;
- onDoneClicked();
}
}
});
}
- private void StartVideoRecording(Button RecordButton) {
+ private void StartVideoRecording(ImageView RecordButton) {
TakeVideoButton = RecordButton;
TakeVideoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if (mIsonDoneClicked) {
- mIsonDoneClicked = false;
- onDoneClicked();
- } else if (mIsRecordingVideo == true) {
+ if (mIsRecordingVideo == true) {
+ showRecordingUI(mIsRecordingVideo);
stopRecordingVideo();
- if (!mIsVideoCaptureIntent) takePictureButton.setVisibility(View.VISIBLE);
-
if (mIsVideoCaptureIntent) {
+ FrameLayout previewLayout =
+ mActivity.findViewById(R.id.intentPreviewLayout);
+ previewLayout.setVisibility(View.VISIBLE);
+ VideoPreview((ImageView)mActivity.findViewById(R.id.IntentPreview));
+
+ ImageButton IntentDone = mActivity.findViewById(R.id.IntentDone);
+
+ IntentDone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ doReturnToCaller(true);
+ }
+ });
mIsVideoCaptureIntent = false;
- TakeVideoButton.setText(R.string.done);
- mIsonDoneClicked = true;
- } else {
- Utils.broadcastNewVideo(mActivity.getApplicationContext(),
- mCurrentVideoValues);
}
} else if (mIsRecordingVideo == false) {
+ TakeVideoButton.setImageResource(R.drawable.ic_stop_normal);
startRecordingVideo();
+ showRecordingUI(mIsRecordingVideo);
takePictureButton.setVisibility(View.GONE);
}
}
});
}
- public void onDoneClicked() {
- doReturnToCaller(true);
+ private void VideoPreview(ImageView preView) {
+ final Optional bitmap =
+ Utils.getVideoThumbnail(mActivity.getContentResolver(), mCurrentVideoUri);
+
+ preView.setVisibility(View.VISIBLE);
+ preView.setImageBitmap(bitmap.get());
+ }
+
+ private void photoPreview(ImageView preView, Uri PhotoUri) {
+ preView.setVisibility(View.VISIBLE);
+ preView.setImageURI(PhotoUri);
}
private void doReturnToCaller(boolean valid) {
@@ -231,17 +328,23 @@ private void doReturnToCaller(boolean valid) {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// open your camera here
+ mSurfaceTexture = surface;
+ // Surface mSurface = new Surface(mSurfaceTexture);
+ // mSurface.release();
openCamera(width, height);
}
+
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
configureTransform(width, height);
}
+
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
+
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@@ -249,40 +352,18 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
public void openCamera(int width, int height) {
CameraManager manager = (CameraManager)mActivity.getSystemService(Context.CAMERA_SERVICE);
- Log.e(TAG, "is camera open");
try {
- if (!((manager.getCameraIdList().length >= 1) &&
- (manager.getCameraIdList().length <= 4))) {
- Log.e(TAG, "this camera is not connected ");
- return;
- }
-
cameraId = manager.getCameraIdList()[0];
- Log.e(TAG, "is camera open ID" + cameraId);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) return;
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
-
- if (Key.compareTo("video_list") == 0) {
- String videoQuality = settings.getString("video_list", "medium");
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
+ int total_psizes = map.getOutputSizes(ImageFormat.JPEG).length;
- mProfile = CamcorderProfile.get(0, quality);
- previewSize = new Size(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- configureTransform(width, height);
- } else {
- previewSize = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG,
- "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
- configureTransform(width, height);
- }
+ previewSize = map.getOutputSizes(SurfaceTexture.class)[total_psizes - 1];
+ Log.d(TAG, "camera preview width: " + previewSize.getWidth() +
+ " preview height: " + previewSize.getHeight());
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
@@ -294,7 +375,7 @@ public void openCamera(int width, int height) {
} catch (CameraAccessException e) {
e.printStackTrace();
}
- Log.e(TAG, "openCamera X");
+ Log.e(TAG, "openCamera");
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@@ -305,17 +386,28 @@ public void onOpened(CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
+
@Override
public void onDisconnected(CameraDevice camera) {
Log.e(TAG, "onDisconnected");
+ frameView0 = mActivity.findViewById(R.id.control1);
+ frameView0.setVisibility(FrameLayout.INVISIBLE);
closeCamera();
}
+
@Override
public void onError(CameraDevice camera, int error) {
Log.e(TAG, "onError");
closeCamera();
}
+
+ @Override
+ public void onClosed(@NonNull CameraDevice camera) {
+ Log.e(TAG, "onClose");
+ super.onClosed(camera);
+ SurfaceUtil.clear(mSurfaceTexture);
+ }
};
private void configureTransform(int viewWidth, int viewHeight) {
@@ -325,7 +417,9 @@ private void configureTransform(int viewWidth, int viewHeight) {
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight);
+ Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight +
+ "previewWidth: " + previewSize.getWidth() +
+ "previewHeight:" + previewSize.getHeight());
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
@@ -347,26 +441,11 @@ protected void createCameraPreview() {
closePreviewSession();
SurfaceTexture texture = textureView.getSurfaceTexture();
if (texture == null) return;
- int quality = -1;
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
- String videoQuality = settings.getString("video_list", "medium");
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
-
- quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
-
- if (Key.compareTo("video_list") == 0) {
- texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
- } else {
- texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
- }
+ texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface surface = new Surface(texture);
+ mOutPutSurface = surface;
captureRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
@@ -382,8 +461,10 @@ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
+
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ closeCamera();
Toast.makeText(mActivity, "Configuration change", Toast.LENGTH_SHORT)
.show();
}
@@ -393,19 +474,6 @@ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
}
}
- public void releaseMedia() {
- if (null != mMediaRecorder) {
- try {
- mMediaRecorder.stop();
- } catch (IllegalStateException ex) {
- Log.d(TAG, "Stop called before start");
- }
- mMediaRecorder.reset();
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
- }
-
public void closeCamera() {
closePreviewSession();
if (null != cameraDevice) {
@@ -416,7 +484,9 @@ public void closeCamera() {
imageReader.close();
imageReader = null;
}
- releaseMedia();
+ if (null != mMediaRecorder) {
+ releaseMedia();
+ }
closeVideoFileDescriptor();
stopBackgroundThread();
}
@@ -482,14 +552,11 @@ protected void takePicture() {
}
try {
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG, "Selected imageDimension " + imageDimension.getWidth() +
- imageDimension.getHeight());
+ Log.d(TAG,
+ "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
ImageReader reader = ImageReader.newInstance(
- imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.JPEG, 1);
+ previewSize.getWidth(), previewSize.getHeight(), ImageFormat.JPEG, 1);
List outputSurfaces = new ArrayList(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
@@ -508,10 +575,12 @@ protected void takePicture() {
return;
}
mPictureFilename = fileDetails[3];
- mCurrentPictureValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_IMAGE, fileDetails,
- imageDimension.getWidth(), imageDimension.getHeight());
-
+ mCurrentPictureValues = Utils.getContentValues(
+ Utils.MEDIA_TYPE_IMAGE, fileDetails, previewSize.getWidth(),
+ previewSize.getHeight(), 0, new File(mPictureFilename).length());
+ ContentResolver resolver = mActivity.getContentResolver();
+ final Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ new ContentValues(mCurrentPictureValues));
file = new File(mPictureFilename);
ImageReader.OnImageAvailableListener readerListener =
@@ -560,9 +629,27 @@ public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
- Toast.makeText(mActivity, "Saved:" + file, Toast.LENGTH_SHORT).show();
-
- createCameraPreview();
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ FrameLayout previewLayout =
+ mActivity.findViewById(R.id.intentPreviewLayout);
+ previewLayout.setVisibility(View.VISIBLE);
+ photoPreview(
+ (ImageView)mActivity.findViewById(R.id.IntentPreview),
+ uri);
+
+ ImageButton IntentDone =
+ mActivity.findViewById(R.id.IntentDone);
+
+ IntentDone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ doReturnToCaller(true);
+ }
+ });
+ }
+ });
}
};
cameraDevice.createCaptureSession(
@@ -593,13 +680,8 @@ private void startRecordingVideo() {
}
try {
closePreviewSession();
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
- mProfile = CamcorderProfile.get(0, quality);
+ mProfile = CamcorderProfile.get(0, CamcorderProfile.QUALITY_HIGH);
setUpMediaRecorder();
SurfaceTexture texture = textureView.getSurfaceTexture();
@@ -630,9 +712,9 @@ public void onConfigured(@NonNull CameraCaptureSession camCaptureSession) {
@Override
public void run() {
// UI
- TakeVideoButton.setText(R.string.stop);
mIsRecordingVideo = true;
-
+ mRecordingStartTime = SystemClock.uptimeMillis();
+ updateRecordingTime();
// Start recording
mMediaRecorder.start();
}
@@ -644,6 +726,8 @@ public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession
if (null != mActivity) {
Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
}
+
+ releaseMedia();
}
}, mBackgroundHandler);
} catch (CameraAccessException | IOException e) {
@@ -655,22 +739,22 @@ private void setUpMediaRecorder() throws IOException {
if (null == mActivity) {
return;
}
-
String result = null;
ContentResolver mContentResolver = mActivity.getContentResolver();
Intent intent = mActivity.getIntent();
- Bundle extras = intent.getExtras();
+ Bundle myExtras = intent.getExtras();
closeVideoFileDescriptor();
- if (mIsVideoCaptureIntent && extras != null) {
- Uri saveUri = extras.getParcelable(MediaStore.EXTRA_OUTPUT);
+ if (mIsVideoCaptureIntent && myExtras != null) {
+ Uri saveUri = myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
if (saveUri != null) {
try {
mVideoFileDescriptor = mContentResolver.openFileDescriptor(saveUri, "rw");
mCurrentVideoUri = saveUri;
mVideoFilename = Utils.getFileNameFromUri(saveUri);
+
} catch (java.io.FileNotFoundException ex) {
// invalid uri
Log.e(TAG, ex.toString());
@@ -684,25 +768,10 @@ private void setUpMediaRecorder() throws IOException {
if (mVideoFileDescriptor != null) {
mMediaRecorder.setOutputFile(mVideoFileDescriptor.getFileDescriptor());
- mVideoFilename = "CtsCameraIntents.mp4";
- } else {
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_VIDEO);
- if (fileDetails == null || fileDetails.length < 5) {
- Log.e(TAG, "Invalid file details");
- return;
- }
- mVideoFilename = fileDetails[3];
- mCurrentVideoValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_VIDEO, fileDetails,
- mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- /**
- * set output file in media recorder
- */
- mMediaRecorder.setOutputFile(mVideoFilename);
}
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+
mMediaRecorder.setVideoEncodingBitRate(10000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
@@ -735,17 +804,34 @@ private void closePreviewSession() {
}
}
+ private void saveVideo() {
+ long duration = SystemClock.uptimeMillis() - mRecordingStartTime;
+ if (duration > 0) {
+ //
+ } else {
+ Log.w(TAG, "Video duration <= 0 : " + duration);
+ }
+ }
+
+ public void releaseMedia() {
+ if (null != mMediaRecorder) {
+ try {
+ mMediaRecorder.stop();
+ } catch (IllegalStateException ex) {
+ Log.d(TAG, "Stop called before start");
+ }
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+ }
+ }
+
private void stopRecordingVideo() {
+ mHandler.removeMessages(MSG_UPDATE_RECORD_TIME);
+
mIsRecordingVideo = false;
- TakeVideoButton.setText(R.string.record);
- // Stop recording
releaseMedia();
-
- if (null != mActivity) {
- Toast.makeText(mActivity, "Video saved: " + mVideoFilename, Toast.LENGTH_SHORT).show();
- Log.d(TAG, "Video saved: " + mVideoFilename);
- }
mVideoFilename = null;
closeVideoFileDescriptor();
createCameraPreview();
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/CtsCameraIntentsActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/CtsCameraIntentsActivity.java
new file mode 100644
index 0000000..30e1132
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/CtsCameraIntentsActivity.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class CtsCameraIntentsActivity extends AppCompatActivity {
+ private static final String TAG = "CameraFullSrnActivity";
+ /**
+ * An {@link AutoFitTextureView} for camera preview.
+ */
+ private AutoFitTextureView mCam_textureView;
+
+ private ImageView mCam_PictureButton, mCam_RecordButton;
+
+ private CtsCamIntents CamIntents;
+
+ private TextView mRecordingTimeView;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate");
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ setContentView(R.layout.activity_multiview);
+ setContentView(R.layout.activity_itscameraintents);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ View decorView = getWindow().getDecorView();
+
+ int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ decorView.setSystemUiVisibility(uiOptions);
+
+ mCam_textureView = findViewById(R.id.textureview0);
+ if (mCam_textureView == null) return;
+
+ mCam_PictureButton = findViewById(R.id.Picture0);
+ mCam_RecordButton = findViewById(R.id.Record0);
+
+ Open_Cam();
+ }
+
+ public boolean isVideoCaptureIntent() {
+ String action = this.getIntent().getAction();
+ ;
+ return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
+ }
+
+ public boolean isImageCaptureIntent() {
+ String action = this.getIntent().getAction();
+ return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
+ }
+
+ public void Open_Cam() {
+ this.setTitle("CtsCamIntents");
+
+ if (isVideoCaptureIntent())
+ mCam_PictureButton.setVisibility(View.GONE);
+ else if (isImageCaptureIntent())
+ mCam_RecordButton.setVisibility(View.GONE);
+
+ mRecordingTimeView = findViewById(R.id.recording_time);
+
+ CamIntents = new CtsCamIntents(this, mCam_textureView, mCam_PictureButton,
+ mCam_RecordButton, mRecordingTimeView);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ Log.d(TAG, "onDestroy");
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ Log.e(TAG, "onPause");
+ closeCamera();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Log.d(TAG, "onResume");
+
+ if (mCam_textureView.isAvailable()) {
+ CamIntents.textureListener.onSurfaceTextureAvailable(
+ mCam_textureView.getSurfaceTexture(), mCam_textureView.getWidth(),
+ mCam_textureView.getHeight());
+ } else {
+ mCam_textureView.setSurfaceTextureListener(CamIntents.textureListener);
+ }
+ }
+
+ private void closeCamera() {
+ if (null != CamIntents) CamIntents.closeCamera();
+ }
+}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/MainActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/MainActivity.java
deleted file mode 100644
index 1b85b06..0000000
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/MainActivity.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (c) 2019 Intel Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intel.multicamera;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraManager;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.util.SparseIntArray;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.Surface;
-import android.view.View;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import androidx.core.app.ActivityCompat;
-
-public class MainActivity extends AppCompatActivity {
- private static final String TAG = "MainActivity";
- /**
- * An {@link AutoFitTextureView} for camera preview.
- */
- private AutoFitTextureView mTopLeftCam_textureView, mTopRightCam_textureView,
- mBotmLeftCam_textureView, mBotmRightCam_textureView;
-
- private Button mTopLeftCam_PictureButton, mTopRightCam_PictureButton,
- mBotmLeftCam_PictureButton, mBotmRightCam_PictureButton, mTopLeftCam_RecordButton,
- mTopRightCam_RecordButton, mBotmLeftCam_RecordButton, mBotmRightCam_RecordButton;
-
- private int numOfCameras;
- private static final int REQUEST_CAMERA_PERMISSION = 200;
- private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
- private FrameLayout frameView0, frameView1, frameView2, frameView3;
-
- private boolean mHasCriticalPermissions = false;
-
- TopLeftCam mTopLeftCam;
- TopRightCam mTopRightCam;
- BotmLeftCam mBotmLeftCam;
- BotmRightCam mBotmRightCam;
-
- static {
- ORIENTATIONS.append(Surface.ROTATION_0, 90);
- ORIENTATIONS.append(Surface.ROTATION_90, 0);
- ORIENTATIONS.append(Surface.ROTATION_180, 270);
- ORIENTATIONS.append(Surface.ROTATION_270, 180);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- checkPermissions();
- if (!mHasCriticalPermissions) {
- Log.v(TAG, "onCreate: Missing critical permissions.");
- finish();
- return;
- }
-
- setVisibilityFrameLayout();
- }
-
- public void Open_TopLeftCam() {
- mTopLeftCam_textureView = findViewById(R.id.textureview0);
- if (mTopLeftCam_textureView == null) return;
-
- mTopLeftCam_PictureButton = findViewById(R.id.Picture0);
- mTopLeftCam_RecordButton = findViewById(R.id.Record0);
-
- if (isVideoCaptureIntent())
- mTopLeftCam_PictureButton.setVisibility(View.GONE);
- else if (isImageCaptureIntent())
- mTopLeftCam_RecordButton.setVisibility(View.GONE);
-
- mTopLeftCam = new TopLeftCam(MainActivity.this, mTopLeftCam_textureView,
- mTopLeftCam_PictureButton, mTopLeftCam_RecordButton);
- }
-
- public void Open_TopRightCam() {
- mTopRightCam_textureView = findViewById(R.id.textureview1);
- if (mTopRightCam_textureView == null) return;
-
- mTopRightCam_PictureButton = findViewById(R.id.Picture1);
- mTopRightCam_RecordButton = findViewById(R.id.Record1);
-
- mTopRightCam = new TopRightCam(MainActivity.this, mTopRightCam_textureView,
- mTopRightCam_PictureButton, mTopRightCam_RecordButton);
- }
-
- public void Open_BotmLeftCam() {
- mBotmLeftCam_textureView = findViewById(R.id.textureview2);
- if (mBotmLeftCam_textureView == null) return;
-
- mBotmLeftCam_PictureButton = findViewById(R.id.Picture2);
- mBotmLeftCam_RecordButton = findViewById(R.id.Record2);
-
- mBotmLeftCam = new BotmLeftCam(MainActivity.this, mBotmLeftCam_textureView,
- mBotmLeftCam_PictureButton, mBotmLeftCam_RecordButton);
- }
-
- public void Open_BotmRightCam() {
- mBotmRightCam_textureView = findViewById(R.id.textureview3);
- if (mBotmRightCam_textureView == null) return;
-
- mBotmRightCam_PictureButton = findViewById(R.id.Picture3);
- mBotmRightCam_RecordButton = findViewById(R.id.Record3);
-
- mBotmRightCam = new BotmRightCam(MainActivity.this, mBotmRightCam_textureView,
- mBotmRightCam_PictureButton, mBotmRightCam_RecordButton);
- }
-
- public boolean isVideoCaptureIntent() {
- String action = this.getIntent().getAction();
- return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
- }
-
- public boolean isImageCaptureIntent() {
- String action = this.getIntent().getAction();
- return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
- }
-
- public void setVisibilityFrameLayout() {
- frameView0 = findViewById(R.id.control1);
- frameView1 = findViewById(R.id.control2);
- frameView2 = findViewById(R.id.control3);
- frameView3 = findViewById(R.id.control4);
-
- CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
- try {
- numOfCameras = manager.getCameraIdList().length;
- // if (numCameras != "") { numOfCameras = Integer.parseInt(numCameras); }
- Log.d(TAG, "onCreate Inside openCamera() Total Cameras: " +
- manager.getCameraIdList().length);
-
- if (numOfCameras == 1) {
- frameView1.setVisibility(FrameLayout.INVISIBLE);
- frameView2.setVisibility(FrameLayout.INVISIBLE);
- frameView3.setVisibility(FrameLayout.INVISIBLE);
- Open_TopLeftCam();
- } else if (numOfCameras == 2) {
- frameView2.setVisibility(FrameLayout.INVISIBLE);
- frameView3.setVisibility(FrameLayout.INVISIBLE);
- Open_TopLeftCam();
- Open_TopRightCam();
- } else if (numOfCameras == 3) {
- frameView3.setVisibility(FrameLayout.INVISIBLE);
- Open_TopLeftCam();
- Open_TopRightCam();
- Open_BotmLeftCam();
- } else if (numOfCameras == 4) {
- Open_TopLeftCam();
- Open_TopRightCam();
- Open_BotmLeftCam();
- Open_BotmRightCam();
- } else {
- Log.d(TAG, "No CAMERA CONNECTED");
- frameView0.setVisibility(FrameLayout.INVISIBLE);
- frameView1.setVisibility(FrameLayout.INVISIBLE);
- frameView2.setVisibility(FrameLayout.INVISIBLE);
- frameView3.setVisibility(FrameLayout.INVISIBLE);
- }
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions,
- int[] grantResults) {
- if (requestCode == REQUEST_CAMERA_PERMISSION) {
- if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
- // close the app
- Toast.makeText(MainActivity.this,
- "Sorry!!!, you can't use this app without granting permission",
- Toast.LENGTH_LONG)
- .show();
- finish();
- }
- }
- }
-
- private void manageTopLeftCam() {
- if (mTopLeftCam == null) {
- Open_TopLeftCam();
- frameView0.setVisibility(FrameLayout.VISIBLE);
- } else if (mTopLeftCam_textureView == null) {
- mTopLeftCam_textureView = findViewById(R.id.textureview0);
- if (mTopLeftCam_textureView == null) return;
- }
-
- if (mTopLeftCam_textureView.isAvailable()) {
- frameView0.setVisibility(FrameLayout.VISIBLE);
- mTopLeftCam.openCamera(mTopLeftCam_textureView.getWidth(),
- mTopLeftCam_textureView.getHeight());
- } else {
- mTopLeftCam_textureView.setSurfaceTextureListener(mTopLeftCam.textureListener);
- }
- }
-
- private void manageTopRightCam() {
- if (mTopRightCam == null) {
- Open_TopRightCam();
- frameView1.setVisibility(FrameLayout.VISIBLE);
-
- } else if (mTopRightCam_textureView == null) {
- mTopRightCam_textureView = findViewById(R.id.textureview1);
- if (mTopRightCam_textureView == null) return;
- }
-
- if (mTopRightCam_textureView.isAvailable()) {
- frameView1.setVisibility(FrameLayout.VISIBLE);
- mTopRightCam.openCamera(mTopRightCam_textureView.getWidth(),
- mTopRightCam_textureView.getHeight());
- } else {
- mTopRightCam_textureView.setSurfaceTextureListener(mTopRightCam.textureListener);
- }
- }
-
- private void manageBotmLeftCam() {
- if (mBotmLeftCam == null) {
- Open_BotmLeftCam();
- frameView2.setVisibility(FrameLayout.VISIBLE);
-
- } else if (mBotmLeftCam_textureView == null) {
- mBotmLeftCam_textureView = findViewById(R.id.textureview2);
- if (mBotmLeftCam_textureView == null) return;
- }
-
- if (mBotmLeftCam_textureView.isAvailable()) {
- frameView2.setVisibility(FrameLayout.VISIBLE);
- mBotmLeftCam.openCamera(mBotmLeftCam_textureView.getWidth(),
- mBotmLeftCam_textureView.getHeight());
- } else {
- mBotmLeftCam_textureView.setSurfaceTextureListener(mBotmLeftCam.textureListener);
- }
- }
-
- private void manageBotmRightCam() {
- if (mBotmRightCam == null) {
- Open_BotmRightCam();
- frameView3.setVisibility(FrameLayout.VISIBLE);
-
- } else if (mBotmRightCam_textureView == null) {
- mBotmRightCam_textureView = findViewById(R.id.textureview3);
- if (mBotmRightCam_textureView == null) return;
- }
-
- if (mBotmRightCam_textureView.isAvailable()) {
- frameView3.setVisibility(FrameLayout.VISIBLE);
- mBotmRightCam.openCamera(mBotmRightCam_textureView.getWidth(),
- mBotmRightCam_textureView.getHeight());
- } else {
- mBotmRightCam_textureView.setSurfaceTextureListener(mBotmRightCam.textureListener);
- }
- }
-
- /**
- * Checks if any of the needed Android runtime permissions are missing.
- * If they are, then launch the permissions activity under one of the following conditions:
- * a) The permissions dialogs have not run yet. We will ask for permission only once.
- * b) If the missing permissions are critical to the app running, we will display a fatal error
- * dialog. Critical permissions are: camera, microphone and storage. The app cannot run without
- * them. Non-critical permission is location.
- */
- private void checkPermissions() {
- if (ActivityCompat.checkSelfPermission(getApplicationContext(),
- Manifest.permission.CAMERA) ==
- PackageManager.PERMISSION_GRANTED &&
- ActivityCompat.checkSelfPermission(getApplicationContext(),
- Manifest.permission.RECORD_AUDIO) ==
- PackageManager.PERMISSION_GRANTED &&
- ActivityCompat.checkSelfPermission(getApplicationContext(),
- Manifest.permission.READ_EXTERNAL_STORAGE) ==
- PackageManager.PERMISSION_GRANTED) {
- mHasCriticalPermissions = true;
- } else {
- mHasCriticalPermissions = false;
- }
-
- if (!mHasCriticalPermissions) {
- Intent intent = new Intent(this, PermissionsActivity.class);
- startActivity(intent);
- finish();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- Log.e(TAG, "onResume");
-
- checkPermissions();
- if (!mHasCriticalPermissions) {
- Log.v(TAG, "onResume: Missing critical permissions.");
- finish();
- return;
- }
-
- CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
- try {
- numOfCameras = manager.getCameraIdList().length;
- Log.d(TAG, "onResume Total Cameras: " + manager.getCameraIdList().length);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
-
- if (numOfCameras == 1) {
- manageTopLeftCam();
- } else if (numOfCameras == 2) {
- manageTopLeftCam();
- manageTopRightCam();
- } else if (numOfCameras == 3) {
- manageTopLeftCam();
- manageBotmLeftCam();
- manageTopRightCam();
- } else if (numOfCameras == 4) {
- manageTopLeftCam();
- manageTopRightCam();
- manageBotmLeftCam();
- manageBotmRightCam();
- } else {
- Log.d(TAG, "onResume No CAMERA CONNECTED");
- frameView0.setVisibility(FrameLayout.INVISIBLE);
- frameView1.setVisibility(FrameLayout.INVISIBLE);
- frameView2.setVisibility(FrameLayout.INVISIBLE);
- frameView3.setVisibility(FrameLayout.INVISIBLE);
- }
- }
-
- private void closeCamera() {
- if (null != mTopLeftCam) mTopLeftCam.closeCamera();
-
- if (null != mTopRightCam) mTopRightCam.closeCamera();
-
- if (null != mBotmRightCam) mBotmRightCam.closeCamera();
-
- if (null != mBotmLeftCam) mBotmLeftCam.closeCamera();
- }
-
- @Override
- protected void onPause() {
- Log.e(TAG, "onPause");
- super.onPause();
- closeCamera();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
-
- // noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
- startActivity(intent);
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/MultiViewActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/MultiViewActivity.java
new file mode 100644
index 0000000..54df233
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/MultiViewActivity.java
@@ -0,0 +1,835 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseIntArray;
+import android.view.*;
+import android.widget.*;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+
+public class MultiViewActivity extends AppCompatActivity {
+ private static final String TAG = "MainActivity";
+ /**
+ * An {@link AutoFitTextureView} for camera preview.
+ */
+ private AutoFitTextureView mTopLeftCam_textureView, mTopRightCam_textureView,
+ mBotmLeftCam_textureView, mBotmRightCam_textureView;
+
+ private ImageButton mTopLeftCam_RecordButton, mTopLeftCam_PictureButton,
+ mTopRightCam_PictureButton, mBotmLeftCam_PictureButton, mBotmRightCam_PictureButton,
+ mTopRightCam_RecordButton, mBotmLeftCam_RecordButton, mBotmRightCam_RecordButton;
+
+ private ImageButton SettingView0, SettingView1, SettingView2, SettingView3, SettingClose0,
+ SettingClose1, SettingClose2, SettingClose3, FullScrn0, FullScrn1, FullScrn2, FullScrn3,
+ exitScrn0, exitScrn1, exitScrn2, exitScrn3;
+
+ private TextView mRecordingTimeView, mRecordingTimeView0, mRecordingTimeView1,
+ mRecordingTimeView2;
+
+ private int numOfCameras;
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+ private FrameLayout frameView0, frameView1, frameView2, frameView3;
+
+ private CameraBase mTopRightCam, mBotmLeftCam, mBotmRightCam, mTopLeftCam;
+
+ private SettingsPrefUtil Fragment, Fragment1, Fragment2, Fragment3;
+
+ public String[] CameraIds;
+ private boolean mHasCriticalPermissions;
+
+ static {
+ ORIENTATIONS.append(Surface.ROTATION_0, 90);
+ ORIENTATIONS.append(Surface.ROTATION_90, 0);
+ ORIENTATIONS.append(Surface.ROTATION_180, 270);
+ ORIENTATIONS.append(Surface.ROTATION_270, 180);
+ }
+
+ private int[] FrameVisibility;
+ private boolean exitScrnFlag;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setHomeButtonEnabled(true);
+ }
+
+ setContentView(R.layout.activity_multiview);
+
+ Log.e(TAG, "onCreate");
+
+ checkPermissions();
+ if (!mHasCriticalPermissions) {
+ Log.v(TAG, "onCreate: Missing critical permissions.");
+ finish();
+ return;
+ }
+
+ Settings_Init();
+
+ FullScrn_Init();
+
+ setVisibilityFrameLayout();
+
+ set_FrameVisibilities();
+ }
+
+ private void set_FrameVisibilities() {
+ FrameVisibility = new int[4];
+
+ FrameVisibility[0] = frameView0.getVisibility();
+ FrameVisibility[1] = frameView1.getVisibility();
+ FrameVisibility[2] = frameView2.getVisibility();
+ FrameVisibility[3] = frameView3.getVisibility();
+ }
+
+ /**
+ * Checks if any of the needed Android runtime permissions are missing.
+ * If they are, then launch the permissions activity under one of the following conditions:
+ * a) The permissions dialogs have not run yet. We will ask for permission only once.
+ * b) If the missing permissions are critical to the app running, we will display a fatal error
+ * dialog. Critical permissions are: camera, microphone and storage. The app cannot run without
+ * them. Non-critical permission is location.
+ */
+ private void checkPermissions() {
+ if (ActivityCompat.checkSelfPermission(getApplicationContext(),
+ Manifest.permission.CAMERA) ==
+ PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(getApplicationContext(),
+ Manifest.permission.RECORD_AUDIO) ==
+ PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(getApplicationContext(),
+ Manifest.permission.READ_EXTERNAL_STORAGE) ==
+ PackageManager.PERMISSION_GRANTED) {
+ mHasCriticalPermissions = true;
+ } else {
+ mHasCriticalPermissions = false;
+ }
+
+ if (!mHasCriticalPermissions) {
+ Intent intent = new Intent(this, PermissionsActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ }
+
+ private void FullScrn_Init() {
+ FullScrn0 = findViewById(R.id.imageView0);
+ FullScrn1 = findViewById(R.id.imageView1);
+ FullScrn2 = findViewById(R.id.imageView2);
+ FullScrn3 = findViewById(R.id.imageView3);
+
+ exitScrn0 = findViewById(R.id.exitFullScreen0);
+ exitScrn1 = findViewById(R.id.exitFullScreen1);
+ exitScrn2 = findViewById(R.id.exitFullScreen2);
+ exitScrn3 = findViewById(R.id.exitFullScreen3);
+ }
+
+ private void Settings_Init() {
+ SettingView0 = findViewById(R.id.SettingView0);
+ SettingView1 = findViewById(R.id.SettingView1);
+ SettingView2 = findViewById(R.id.SettingView2);
+ SettingView3 = findViewById(R.id.SettingView3);
+
+ SettingClose0 = findViewById(R.id.mSettingClose0);
+ SettingClose1 = findViewById(R.id.mSettingClose1);
+ SettingClose2 = findViewById(R.id.mSettingClose2);
+ SettingClose3 = findViewById(R.id.mSettingClose3);
+ }
+
+ public void GetCameraCnt() {
+ CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
+
+ try {
+ CameraIds = manager.getCameraIdList();
+ numOfCameras = manager.getCameraIdList().length;
+ Log.d(TAG, "Inside Settings Total Cameras: " + manager.getCameraIdList().length);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Open_TopLeftCam() {
+ String[] Data = new String[5];
+ ImageButton[] Buttons = new ImageButton[4];
+
+ mTopLeftCam_textureView = findViewById(R.id.textureview0);
+ if (mTopLeftCam_textureView == null) return;
+
+ mTopLeftCam_PictureButton = findViewById(R.id.Picture0);
+ mTopLeftCam_RecordButton = findViewById(R.id.Record0);
+
+ Buttons[0] = mTopLeftCam_PictureButton;
+ Buttons[1] = mTopLeftCam_RecordButton;
+ Buttons[2] = SettingView0;
+ Buttons[3] = FullScrn0;
+
+ mRecordingTimeView = findViewById(R.id.recording_time);
+
+ Data[0] = "TopLeftCam";
+ Data[1] = CameraIds[0];
+ Data[2] = "capture_list";
+ Data[3] = "video_list";
+ Data[4] = "pref_resolution";
+
+ RoundedThumbnailView roundedThumbnailView = findViewById(R.id.rounded_thumbnail_view);
+
+ mTopLeftCam = new CameraBase(this, mTopLeftCam_textureView, Buttons, mRecordingTimeView,
+ Data, roundedThumbnailView);
+ }
+
+ public void Open_TopRightCam() {
+ String[] Data = new String[5];
+ ImageButton[] Buttons = new ImageButton[4];
+ mTopRightCam_textureView = findViewById(R.id.textureview1);
+ if (mTopRightCam_textureView == null) return;
+
+ mTopRightCam_PictureButton = findViewById(R.id.Picture1);
+ mTopRightCam_RecordButton = findViewById(R.id.Record1);
+
+ Buttons[0] = mTopRightCam_PictureButton;
+ Buttons[1] = mTopRightCam_RecordButton;
+ Buttons[2] = SettingView1;
+ Buttons[3] = FullScrn1;
+
+ Data[0] = "TopRightCam";
+ Data[1] = CameraIds[1];
+ Data[2] = "capture_list_1";
+ Data[3] = "video_list_1";
+ Data[4] = "pref_resolution_1";
+
+ mRecordingTimeView0 = findViewById(R.id.recording_time0);
+
+ RoundedThumbnailView roundedThumbnailView = findViewById(R.id.rounded_thumbnail_view0);
+
+ mTopRightCam = new CameraBase(this, mTopRightCam_textureView, Buttons, mRecordingTimeView0,
+ Data, roundedThumbnailView);
+ }
+
+ public void Open_BotmLeftCam() {
+ String[] Data = new String[5];
+ ImageButton[] Buttons = new ImageButton[4];
+ mBotmLeftCam_textureView = findViewById(R.id.textureview2);
+ if (mBotmLeftCam_textureView == null) return;
+
+ mBotmLeftCam_PictureButton = findViewById(R.id.Picture2);
+ mBotmLeftCam_RecordButton = findViewById(R.id.Record2);
+
+ Buttons[0] = mBotmLeftCam_PictureButton;
+ Buttons[1] = mBotmLeftCam_RecordButton;
+ Buttons[2] = SettingView2;
+ Buttons[3] = FullScrn2;
+
+ Data[0] = "BotmLeftCam";
+ Data[1] = CameraIds[2];
+ Data[2] = "capture_list_2";
+ Data[3] = "video_list_2";
+ Data[4] = "pref_resolution_2";
+
+ mRecordingTimeView1 = findViewById(R.id.recording_time1);
+
+ RoundedThumbnailView roundedThumbnailView = findViewById(R.id.rounded_thumbnail_view1);
+
+ mBotmLeftCam = new CameraBase(this, mBotmLeftCam_textureView, Buttons, mRecordingTimeView1,
+ Data, roundedThumbnailView);
+ }
+
+ public void Open_BotmRightCam() {
+ String[] Data = new String[5];
+ ImageButton[] Buttons = new ImageButton[4];
+ mBotmRightCam_textureView = findViewById(R.id.textureview3);
+ if (mTopRightCam_textureView == null) return;
+
+ mBotmRightCam_PictureButton = findViewById(R.id.Picture3);
+ mBotmRightCam_RecordButton = findViewById(R.id.Record3);
+
+ Buttons[0] = mBotmRightCam_PictureButton;
+ Buttons[1] = mBotmRightCam_RecordButton;
+ Buttons[2] = SettingView3;
+ Buttons[3] = FullScrn3;
+
+ Data[0] = "BotmRightCam";
+ Data[1] = CameraIds[3];
+ Data[2] = "capture_list_3";
+ Data[3] = "video_list_3";
+ Data[4] = "pref_resolution_3";
+
+ mRecordingTimeView2 = findViewById(R.id.recording_time2);
+
+ RoundedThumbnailView roundedThumbnailView = findViewById(R.id.rounded_thumbnail_view2);
+
+ mBotmRightCam = new CameraBase(this, mBotmRightCam_textureView, Buttons,
+ mRecordingTimeView2, Data, roundedThumbnailView);
+ }
+
+ public void setVisibilityFrameLayout() {
+ frameView0 = findViewById(R.id.control1);
+ frameView1 = findViewById(R.id.control2);
+ frameView2 = findViewById(R.id.control3);
+ frameView3 = findViewById(R.id.control4);
+
+ GetCameraCnt();
+ Log.d(TAG, "onCreate Total Cameras: " + numOfCameras);
+
+ if (numOfCameras == 1) {
+ frameView1.setVisibility(FrameLayout.INVISIBLE);
+ frameView2.setVisibility(FrameLayout.INVISIBLE);
+ frameView3.setVisibility(FrameLayout.INVISIBLE);
+ Open_TopLeftCam();
+ } else if (numOfCameras == 2) {
+ frameView2.setVisibility(FrameLayout.INVISIBLE);
+ frameView3.setVisibility(FrameLayout.INVISIBLE);
+ Open_TopLeftCam();
+ } else if (numOfCameras == 3) {
+ frameView3.setVisibility(FrameLayout.INVISIBLE);
+ Open_TopLeftCam();
+ Open_TopRightCam();
+ Open_BotmLeftCam();
+ } else if (numOfCameras == 4) {
+ Open_TopLeftCam();
+ Open_TopRightCam();
+ Open_BotmLeftCam();
+ Open_BotmRightCam();
+ } else {
+ Log.d(TAG, "No CAMERA CONNECTED");
+ frameView0.setVisibility(FrameLayout.INVISIBLE);
+ frameView1.setVisibility(FrameLayout.INVISIBLE);
+ frameView2.setVisibility(FrameLayout.INVISIBLE);
+ frameView3.setVisibility(FrameLayout.INVISIBLE);
+ }
+ }
+
+ private void manageTopLeftCam() {
+ if (mTopLeftCam == null) {
+ Open_TopLeftCam();
+ frameView0.setVisibility(FrameLayout.VISIBLE);
+ FrameVisibility[0] = frameView0.getVisibility();
+ } else if (mTopLeftCam_textureView == null) {
+ mTopLeftCam_textureView = findViewById(R.id.textureview0);
+ }
+
+ if (mTopLeftCam_textureView.isAvailable()) {
+ mTopLeftCam.textureListener.onSurfaceTextureAvailable(
+ mTopLeftCam_textureView.getSurfaceTexture(), mTopLeftCam_textureView.getWidth(),
+ mTopLeftCam_textureView.getHeight());
+ } else {
+ mTopLeftCam_textureView.setSurfaceTextureListener(mTopLeftCam.textureListener);
+ }
+ }
+
+ private void manageTopRightCam() {
+ if (mTopRightCam == null) {
+ Open_TopRightCam();
+ frameView1.setVisibility(FrameLayout.VISIBLE);
+ FrameVisibility[1] = frameView1.getVisibility();
+
+ } else if (mTopRightCam_textureView == null) {
+ mTopRightCam_textureView = findViewById(R.id.textureview1);
+ }
+
+ if (mTopRightCam_textureView.isAvailable()) {
+ mTopRightCam.textureListener.onSurfaceTextureAvailable(
+ mTopRightCam_textureView.getSurfaceTexture(),
+ mTopRightCam_textureView.getWidth(), mTopRightCam_textureView.getHeight());
+ } else {
+ mTopRightCam_textureView.setSurfaceTextureListener(mTopRightCam.textureListener);
+ }
+ }
+
+ private void manageBotmLeftCam() {
+ if (mBotmLeftCam == null) {
+ Open_BotmLeftCam();
+ frameView2.setVisibility(FrameLayout.VISIBLE);
+ FrameVisibility[2] = frameView2.getVisibility();
+
+ } else if (mBotmLeftCam_textureView == null) {
+ mBotmLeftCam_textureView = findViewById(R.id.textureview2);
+ }
+
+ if (mBotmLeftCam_textureView.isAvailable()) {
+ mBotmLeftCam.textureListener.onSurfaceTextureAvailable(
+ mBotmLeftCam_textureView.getSurfaceTexture(),
+ mBotmLeftCam_textureView.getWidth(), mBotmLeftCam_textureView.getHeight());
+ } else {
+ mBotmLeftCam_textureView.setSurfaceTextureListener(mBotmLeftCam.textureListener);
+ }
+ }
+
+ private void manageBotmRightCam() {
+ if (mBotmRightCam == null) {
+ Open_BotmRightCam();
+ frameView3.setVisibility(FrameLayout.VISIBLE);
+ FrameVisibility[3] = frameView3.getVisibility();
+
+ } else if (mBotmRightCam_textureView == null) {
+ mBotmRightCam_textureView = findViewById(R.id.textureview3);
+ }
+
+ if (mBotmRightCam_textureView.isAvailable()) {
+ mBotmRightCam.textureListener.onSurfaceTextureAvailable(
+ mBotmRightCam_textureView.getSurfaceTexture(),
+ mBotmRightCam_textureView.getWidth(), mBotmRightCam_textureView.getHeight());
+ } else {
+ mBotmRightCam_textureView.setSurfaceTextureListener(mBotmRightCam.textureListener);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Log.e(TAG, "onResume");
+
+ GetCameraCnt();
+
+ if (numOfCameras == 1) {
+ manageTopLeftCam();
+ } else if (numOfCameras == 2) {
+ manageTopLeftCam();
+ manageTopRightCam();
+ } else if (numOfCameras == 3) {
+ manageTopLeftCam();
+ manageBotmLeftCam();
+ manageTopRightCam();
+ } else if (numOfCameras == 4) {
+ manageTopLeftCam();
+ manageTopRightCam();
+ manageBotmLeftCam();
+ manageBotmRightCam();
+
+ } else {
+ Log.d(TAG, "onResume No CAMERA CONNECTED");
+ frameView0.setVisibility(FrameLayout.INVISIBLE);
+ frameView1.setVisibility(FrameLayout.INVISIBLE);
+ frameView2.setVisibility(FrameLayout.INVISIBLE);
+ frameView3.setVisibility(FrameLayout.INVISIBLE);
+
+ FrameVisibility[0] = frameView0.getVisibility();
+ FrameVisibility[1] = frameView1.getVisibility();
+ FrameVisibility[2] = frameView2.getVisibility();
+ FrameVisibility[3] = frameView3.getVisibility();
+ }
+ }
+
+ private void closeCamera() {
+ if (null != mTopLeftCam) mTopLeftCam.closeCamera();
+
+ if (null != mTopRightCam) mTopRightCam.closeCamera();
+
+ if (null != mBotmRightCam) mBotmRightCam.closeCamera();
+
+ if (null != mBotmLeftCam) mBotmLeftCam.closeCamera();
+ }
+
+ @Override
+ protected void onPause() {
+ Log.e(TAG, "onPause");
+ super.onPause();
+
+ closeCamera();
+ }
+
+ public void settingView(View view) {
+ FrameLayout frameLayout;
+ Bundle bundle;
+
+ switch (view.getId()) {
+ case R.id.SettingView0:
+ frameLayout = findViewById(R.id.PrefScrnSettings0);
+
+ frameLayout.setVisibility(View.VISIBLE);
+ SettingClose0.setVisibility(View.VISIBLE);
+
+ bundle = new Bundle();
+ bundle.putString("Camera_id", CameraIds[0]);
+ bundle.putInt("root_preferences", R.xml.root_preferences);
+ bundle.putString("pref_resolution", "pref_resolution");
+ bundle.putString("video_list", "video_list");
+ bundle.putString("capture_list", "capture_list");
+
+ Fragment = new SettingsPrefUtil();
+ Fragment.setArguments(bundle);
+
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.PrefScrnSettings0, Fragment)
+ .commit();
+
+ SettingView0.setVisibility(View.GONE);
+ FullScrn0.setVisibility(View.GONE);
+ if (exitScrnFlag) exitScrn0.setVisibility(View.INVISIBLE);
+ mTopLeftCam_RecordButton.setVisibility(View.GONE);
+ mTopLeftCam_PictureButton.setVisibility(View.GONE);
+ break;
+ case R.id.SettingView1:
+ frameLayout = findViewById(R.id.PrefScrnSettings1);
+
+ frameLayout.setVisibility(View.VISIBLE);
+ SettingClose1.setVisibility(View.VISIBLE);
+
+ bundle = new Bundle();
+ bundle.putString("Camera_id", CameraIds[1]);
+ bundle.putInt("root_preferences", R.xml.root_preferences_1);
+ bundle.putString("pref_resolution", "pref_resolution_1");
+ bundle.putString("video_list", "video_list_1");
+ bundle.putString("capture_list", "capture_list_1");
+
+ Fragment1 = new SettingsPrefUtil();
+ Fragment1.setArguments(bundle);
+
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.PrefScrnSettings1, Fragment1)
+ .commit();
+
+ SettingView1.setVisibility(View.GONE);
+ FullScrn1.setVisibility(View.GONE);
+ if (exitScrnFlag) exitScrn1.setVisibility(View.INVISIBLE);
+ mTopRightCam_RecordButton.setVisibility(View.GONE);
+ mTopRightCam_PictureButton.setVisibility(View.GONE);
+ break;
+ case R.id.SettingView2:
+ frameLayout = findViewById(R.id.PrefScrnSettings2);
+
+ frameLayout.setVisibility(View.VISIBLE);
+ SettingClose2.setVisibility(View.VISIBLE);
+
+ bundle = new Bundle();
+ bundle.putString("Camera_id", CameraIds[2]);
+ bundle.putInt("root_preferences", R.xml.root_preferences_2);
+ bundle.putString("pref_resolution", "pref_resolution_2");
+ bundle.putString("video_list", "video_list_2");
+ bundle.putString("capture_list", "capture_list_2");
+
+ Fragment2 = new SettingsPrefUtil();
+ Fragment2.setArguments(bundle);
+
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.PrefScrnSettings2, Fragment2)
+ .commit();
+
+ SettingView2.setVisibility(View.GONE);
+ FullScrn2.setVisibility(View.GONE);
+ if (exitScrnFlag) exitScrn2.setVisibility(View.INVISIBLE);
+ mBotmLeftCam_RecordButton.setVisibility(View.GONE);
+ mBotmLeftCam_PictureButton.setVisibility(View.GONE);
+ break;
+ case R.id.SettingView3:
+ frameLayout = findViewById(R.id.PrefScrnSettings3);
+
+ frameLayout.setVisibility(View.VISIBLE);
+ SettingClose3.setVisibility(View.VISIBLE);
+
+ bundle = new Bundle();
+ bundle.putString("Camera_id", CameraIds[3]);
+ bundle.putInt("root_preferences", R.xml.root_preferences_3);
+ bundle.putString("pref_resolution", "pref_resolution_3");
+ bundle.putString("video_list", "video_list_3");
+ bundle.putString("capture_list", "capture_list_3");
+
+ Fragment3 = new SettingsPrefUtil();
+ Fragment3.setArguments(bundle);
+
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.PrefScrnSettings3, Fragment3)
+ .commit();
+
+ SettingView3.setVisibility(View.GONE);
+ FullScrn3.setVisibility(View.GONE);
+ if (exitScrnFlag) exitScrn3.setVisibility(View.INVISIBLE);
+ mBotmRightCam_RecordButton.setVisibility(View.GONE);
+ mBotmRightCam_PictureButton.setVisibility(View.GONE);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ public void settingClose(View view) {
+ FrameLayout frameLayout;
+
+ switch (view.getId()) {
+ case R.id.mSettingClose0:
+ frameLayout = findViewById(R.id.PrefScrnSettings0);
+
+ getFragmentManager().beginTransaction().remove(Fragment).commit();
+
+ frameLayout.setVisibility(View.GONE);
+ view.setVisibility(view.GONE);
+ SettingView0.setVisibility(View.VISIBLE);
+
+ if (!exitScrnFlag)
+ FullScrn0.setVisibility(View.VISIBLE);
+ else
+ exitScrn0.setVisibility(View.VISIBLE);
+
+ mTopLeftCam_RecordButton.setVisibility(View.VISIBLE);
+ mTopLeftCam_PictureButton.setVisibility(View.VISIBLE);
+
+ mTopLeftCam.createCameraPreview();
+
+ break;
+ case R.id.mSettingClose1:
+ frameLayout = findViewById(R.id.PrefScrnSettings1);
+
+ getFragmentManager().beginTransaction().remove(Fragment1).commit();
+
+ frameLayout.setVisibility(View.GONE);
+ view.setVisibility(view.GONE);
+ SettingView1.setVisibility(View.VISIBLE);
+
+ if (!exitScrnFlag)
+ FullScrn1.setVisibility(View.VISIBLE);
+ else
+ exitScrn1.setVisibility(View.VISIBLE);
+
+ mTopRightCam_RecordButton.setVisibility(View.VISIBLE);
+ mTopRightCam_PictureButton.setVisibility(View.VISIBLE);
+
+ mTopRightCam.createCameraPreview();
+
+ break;
+ case R.id.mSettingClose2:
+ frameLayout = findViewById(R.id.PrefScrnSettings2);
+ getFragmentManager().beginTransaction().remove(Fragment2).commit();
+
+ frameLayout.setVisibility(View.GONE);
+ view.setVisibility(view.GONE);
+ SettingView2.setVisibility(View.VISIBLE);
+
+ if (!exitScrnFlag)
+ FullScrn2.setVisibility(View.VISIBLE);
+ else
+ exitScrn2.setVisibility(View.VISIBLE);
+
+ mBotmLeftCam_RecordButton.setVisibility(View.VISIBLE);
+ mBotmLeftCam_PictureButton.setVisibility(View.VISIBLE);
+
+ mBotmLeftCam.createCameraPreview();
+
+ break;
+ case R.id.mSettingClose3:
+ frameLayout = findViewById(R.id.PrefScrnSettings3);
+ getFragmentManager().beginTransaction().remove(Fragment3).commit();
+
+ frameLayout.setVisibility(View.GONE);
+ view.setVisibility(view.GONE);
+ SettingView3.setVisibility(View.VISIBLE);
+
+ if (!exitScrnFlag)
+ FullScrn3.setVisibility(View.VISIBLE);
+ else
+ exitScrn3.setVisibility(View.VISIBLE);
+
+ mBotmRightCam_RecordButton.setVisibility(View.VISIBLE);
+ mBotmRightCam_PictureButton.setVisibility(View.VISIBLE);
+
+ mBotmRightCam.createCameraPreview();
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ public void enterFullScreen(View view) {
+ LinearLayout LinLayout1, LinLayout2;
+
+ LinLayout1 = findViewById(R.id.TopLayout);
+
+ LinLayout2 = findViewById(R.id.BtmLayout);
+
+ switch (view.getId()) {
+ case R.id.imageView0:
+ this.setTitle("TopLeftCam");
+ exitScrnFlag = true;
+ exitScrn0.setVisibility(View.VISIBLE);
+ FullScrn0.setVisibility(View.GONE);
+
+ frameView1.setVisibility(View.GONE);
+
+ LinLayout2.setVisibility(View.GONE);
+
+ break;
+ case R.id.exitFullScreen0:
+ this.setTitle("MultiCamera");
+ exitScrnFlag = false;
+
+ FullScrn0.setVisibility(View.VISIBLE);
+
+ exitScrn0.setVisibility(View.GONE);
+
+ switch (FrameVisibility[1]) {
+ case View.VISIBLE:
+
+ frameView1.setVisibility(View.VISIBLE);
+
+ break;
+
+ case View.INVISIBLE:
+
+ frameView1.setVisibility(View.INVISIBLE);
+
+ break;
+ default:
+ break;
+ }
+
+ FrameVisibility[1] = frameView1.getVisibility();
+
+ LinLayout2.setVisibility(View.VISIBLE);
+
+ break;
+ case R.id.imageView1:
+ this.setTitle("TopRightCam");
+ exitScrnFlag = true;
+ FullScrn1.setVisibility(View.GONE);
+ exitScrn1.setVisibility(View.VISIBLE);
+
+ frameView0.setVisibility(View.GONE);
+ LinLayout2.setVisibility(View.GONE);
+
+ break;
+ case R.id.exitFullScreen1:
+ this.setTitle("MultiCamera");
+
+ exitScrnFlag = false;
+ FullScrn1.setVisibility(View.VISIBLE);
+ exitScrn1.setVisibility(View.GONE);
+
+ switch (FrameVisibility[0]) {
+ case View.VISIBLE:
+
+ frameView0.setVisibility(View.VISIBLE);
+
+ break;
+
+ case View.INVISIBLE:
+
+ frameView0.setVisibility(View.INVISIBLE);
+
+ break;
+ default:
+ break;
+ }
+
+ FrameVisibility[0] = frameView0.getVisibility();
+
+ LinLayout2.setVisibility(View.VISIBLE);
+
+ break;
+
+ case R.id.imageView2:
+ this.setTitle("BotmLeftCam");
+
+ exitScrnFlag = true;
+ FullScrn2.setVisibility(View.GONE);
+ exitScrn2.setVisibility(View.VISIBLE);
+
+ frameView3.setVisibility(View.GONE);
+ LinLayout1.setVisibility(View.GONE);
+
+ break;
+ case R.id.exitFullScreen2:
+ this.setTitle("MultiCamera");
+
+ exitScrnFlag = false;
+ FullScrn2.setVisibility(View.VISIBLE);
+ exitScrn2.setVisibility(View.GONE);
+
+ switch (FrameVisibility[3]) {
+ case View.VISIBLE:
+
+ frameView3.setVisibility(View.VISIBLE);
+
+ break;
+
+ case View.INVISIBLE:
+
+ frameView3.setVisibility(View.INVISIBLE);
+
+ break;
+ default:
+ break;
+ }
+
+ FrameVisibility[3] = frameView3.getVisibility();
+
+ LinLayout1.setVisibility(View.VISIBLE);
+
+ break;
+ case R.id.imageView3:
+ this.setTitle("BotmRightCam");
+ exitScrnFlag = true;
+ FullScrn3.setVisibility(View.GONE);
+ exitScrn3.setVisibility(View.VISIBLE);
+
+ frameView2.setVisibility(View.GONE);
+ LinLayout1.setVisibility(View.GONE);
+
+ break;
+ case R.id.exitFullScreen3:
+ this.setTitle("MultiCamera");
+ exitScrnFlag = false;
+ FullScrn3.setVisibility(View.VISIBLE);
+ exitScrn3.setVisibility(View.GONE);
+
+ switch (FrameVisibility[2]) {
+ case View.VISIBLE:
+
+ frameView2.setVisibility(View.VISIBLE);
+
+ break;
+
+ case View.INVISIBLE:
+
+ frameView2.setVisibility(View.INVISIBLE);
+
+ break;
+ default:
+ break;
+ }
+
+ FrameVisibility[2] = frameView2.getVisibility();
+
+ LinLayout1.setVisibility(View.VISIBLE);
+
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/PermissionsActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/PermissionsActivity.java
index d790051..8cce815 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/PermissionsActivity.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/PermissionsActivity.java
@@ -37,44 +37,23 @@ public class PermissionsActivity extends QuickActivity {
private String TAG = "PermissionsActivity";
private static int PERMISSION_REQUEST_CODE = 1;
- private static int RESULT_CODE_OK = 1;
- private static int RESULT_CODE_FAILED = 2;
private int mIndexPermissionRequestCamera;
private int mIndexPermissionRequestMicrophone;
- private int mIndexPermissionRequestLocation;
private int mIndexPermissionRequestStorage;
private boolean mShouldRequestCameraPermission;
private boolean mShouldRequestMicrophonePermission;
- private boolean mShouldRequestLocationPermission;
private boolean mShouldRequestStoragePermission;
private int mNumPermissionsToRequest;
private boolean mFlagHasCameraPermission;
private boolean mFlagHasMicrophonePermission;
private boolean mFlagHasStoragePermission;
- /**
- * Close activity when secure app passes lock screen or screen turns
- * off.
-
- private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.v(TAG, "received intent, finishing: " + intent.getAction());
- finish();
- }
- };
- */
-
+
@Override
protected void onCreateTasks(Bundle savedInstanceState) {
setContentView(R.layout.permissions);
- // Filter for screen off so that we can finish permissions activity
- // when screen is off.
- // IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF);
- // registerReceiver(mShutdownReceiver, filter_screen_off);
-
Window win = getWindow();
win.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
@@ -89,7 +68,6 @@ protected void onResumeTasks() {
protected void onDestroyTasks() {
Log.v(TAG, "onDestroy: unregistering receivers");
- // unregisterReceiver(mShutdownReceiver);
}
/**
@@ -104,10 +82,8 @@ public boolean convertToBoolean(String value) {
if (value.compareTo("false") == 0) {
ret = false;
- Log.d(TAG, "####FALSE");
} else if (value.compareTo("true") == 0) {
- Log.d(TAG, "####TRUE");
ret = true;
}
@@ -123,7 +99,7 @@ public String getString(String key, String defaultValue) {
try {
return preferences.getString(key, defaultValue);
} catch (ClassCastException e) {
- Log.w(TAG, "existing preference with invalid type, removing and returning default", e);
+ Log.w(TAG, "existing preference with invalid type,removing and returning default", e);
preferences.edit().remove(key).apply();
return defaultValue;
}
@@ -149,7 +125,7 @@ private void checkPermissions() {
}
if (ActivityCompat.checkSelfPermission(getApplicationContext(),
- Manifest.permission.READ_EXTERNAL_STORAGE) !=
+ Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
mNumPermissionsToRequest++;
mShouldRequestStoragePermission = true;
@@ -160,11 +136,13 @@ private void checkPermissions() {
if (mNumPermissionsToRequest != 0) {
if (!convertToBoolean(getString("pref_has_seen_permissions_dialogs", "false"))) {
buildPermissionsRequest();
+
} else {
// Permissions dialog has already been shown, or we're on
// lockscreen, and we're still missing permissions.
handlePermissionsFailure();
}
+
} else {
handlePermissionsSuccess();
}
@@ -238,7 +216,7 @@ public void onRequestPermissionsResult(int requestCode, String permissions[],
}
private void handlePermissionsSuccess() {
- Intent intent = new Intent(this, MainActivity.class);
+ Intent intent = new Intent(this, MultiViewActivity.class);
startActivity(intent);
finish();
}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/QuickActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/QuickActivity.java
index b839edb..a2b99da 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/QuickActivity.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/QuickActivity.java
@@ -53,12 +53,18 @@
public abstract class QuickActivity extends Activity {
private String TAG = "QuickActivity";
- /** onResume tasks delay from secure lockscreen. */
+ /**
+ * onResume tasks delay from secure lockscreen.
+ */
private static final long ON_RESUME_DELAY_SECURE_MILLIS = 30;
- /** onResume tasks delay from non-secure lockscreen. */
+ /**
+ * onResume tasks delay from non-secure lockscreen.
+ */
private static final long ON_RESUME_DELAY_NON_SECURE_MILLIS = 15;
- /** A reference to the main handler on which to run lifecycle methods. */
+ /**
+ * A reference to the main handler on which to run lifecycle methods.
+ */
private Handler mMainHandler;
/**
@@ -67,9 +73,13 @@ public abstract class QuickActivity extends Activity {
*/
private boolean mSkippedFirstOnResume = false;
- /** When application execution started in SystemClock.elapsedRealtimeNanos(). */
+ /**
+ * When application execution started in SystemClock.elapsedRealtimeNanos().
+ */
protected long mExecutionStartNanoTime = 0;
- /** Was this session started with onCreate(). */
+ /**
+ * Was this session started with onCreate().
+ */
protected boolean mStartupOnCreate = false;
/**
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/RoundedThumbnailView.java b/camera/MultiCameraApplication/java/com/intel/multicamera/RoundedThumbnailView.java
new file mode 100644
index 0000000..41398d2
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/RoundedThumbnailView.java
@@ -0,0 +1,768 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+import java.util.Optional;
+
+/**
+ * A view that shows a pop-out effect for a thumbnail image as the new capture indicator design for
+ * Haleakala. When a photo is taken, this view will appear in the bottom right corner of the view
+ * finder to indicate the capture is done.
+ *
+ * Thumbnail cropping:
+ * (1) 100% width and vertically centered for portrait.
+ * (2) 100% height and horizontally centered for landscape.
+ *
+ * General behavior spec: Hide the capture indicator by fading out using fast_out_linear_in (150ms):
+ * (1) User open filmstrip.
+ * (2) User switch module.
+ * (3) User switch front/back camera.
+ * (4) User close app.
+ *
+ * Visual spec:
+ * (1) A 12dp spacing between mode option overlay and thumbnail.
+ * (2) A circular mask that excludes the corners of the preview image.
+ * (3) A solid white layer that sits on top of the preview and is also masked by 2).
+ * (4) The preview thumbnail image.
+ * (5) A 'ripple' which is just a white circular stroke.
+ *
+ * Animation spec:
+ * - For (2) only the scale animates, from 50%(24dp) to 114%(54dp) in 200ms then falls back to
+ * 100%(48dp) in 200ms. Both steps use the same easing: fast_out_slow_in.
+ * - For (3), change opacity from 50% to 0% over 150ms, easing is exponential.
+ * - For (4), doesn't animate.
+ * - For (5), starts animating after 100ms, when (1) is at its peak radius and all animations take
+ * 200ms, using linear_out_slow in. Opacity goes from 40% to 0%, radius goes from 40dp to 70dp,
+ * stroke width goes from 5dp to 1dp.
+ */
+public class RoundedThumbnailView extends View {
+ private static final String TAG = "RoundedThumbnailView";
+
+ // Configurations for the thumbnail pop-out effect.
+ private static final long THUMBNAIL_STRETCH_DURATION_MS = 200;
+ private static final long THUMBNAIL_SHRINK_DURATION_MS = 200;
+ private static final float THUMBNAIL_REVEAL_CIRCLE_OPACITY_BEGIN = 0.5f;
+ private static final float THUMBNAIL_REVEAL_CIRCLE_OPACITY_END = 0.0f;
+
+ // Configurations for the ripple effect.
+ private static final long RIPPLE_DURATION_MS = 200;
+ private static final float RIPPLE_OPACITY_BEGIN = 0.4f;
+ private static final float RIPPLE_OPACITY_END = 0.0f;
+
+ // Configurations for the hit-state effect.
+ private static final float HIT_STATE_CIRCLE_OPACITY_HIDDEN = -1.0f;
+ private static final float HIT_STATE_CIRCLE_OPACITY_BEGIN = 0.7f;
+ private static final float HIT_STATE_CIRCLE_OPACITY_END = 0.0f;
+ private static final long HIT_STATE_DURATION_MS = 150;
+
+ /**
+ * Defines call events.
+ */
+ public interface Callback { public void onHitStateFinished(); }
+
+ /**
+ * The registered callback.
+ */
+ private Optional mCallback;
+
+ // Fields for view layout.
+ private float mThumbnailPadding;
+ private RectF mViewRect;
+
+ // Fields for the thumbnail pop-out effect.
+ /**
+ * The animators to move the thumbnail.
+ */
+ private AnimatorSet mThumbnailAnimatorSet;
+ /**
+ * The current diameter for the thumbnail image.
+ */
+ private float mCurrentThumbnailDiameter;
+ /**
+ * The current reveal circle opacity.
+ */
+ private float mCurrentRevealCircleOpacity;
+ /**
+ * The duration of the stretch phase in thumbnail pop-out effect.
+ */
+ private long mThumbnailStretchDurationMs;
+ /**
+ * The duration of the shrink phase in thumbnail pop-out effect.
+ */
+ private long mThumbnailShrinkDurationMs;
+ /**
+ * The beginning diameter of the thumbnail for the stretch phase in
+ * thumbnail pop-out effect.
+ */
+ private float mThumbnailStretchDiameterBegin;
+ /**
+ * The ending diameter of the thumbnail for the stretch phase in thumbnail
+ * pop-out effect.
+ */
+ private float mThumbnailStretchDiameterEnd;
+ /**
+ * The beginning diameter of the thumbnail for the shrink phase in thumbnail
+ * pop-out effect.
+ */
+ private float mThumbnailShrinkDiameterBegin;
+ /**
+ * The ending diameter of the thumbnail for the shrink phase in thumbnail
+ * pop-out effect.
+ */
+ private float mThumbnailShrinkDiameterEnd;
+ /**
+ * Paint object for the reveal circle.
+ */
+ private final Paint mRevealCirclePaint;
+
+ // Fields for the ripple effect.
+ /**
+ * The start delay of the ripple effect.
+ */
+ private long mRippleStartDelayMs;
+ /**
+ * The duration of the ripple effect.
+ */
+ private long mRippleDurationMs;
+ /**
+ * The beginning diameter of the ripple ring.
+ */
+ private float mRippleRingDiameterBegin;
+ /**
+ * The ending diameter of the ripple ring.
+ */
+ private float mRippleRingDiameterEnd;
+ /**
+ * The beginning thickness of the ripple ring.
+ */
+ private float mRippleRingThicknessBegin;
+ /**
+ * The ending thickness of the ripple ring.
+ */
+ private float mRippleRingThicknessEnd;
+ /**
+ * A lazily loaded animator for the ripple effect.
+ */
+ private ValueAnimator mRippleAnimator;
+ /**
+ * The current ripple ring diameter which is updated by the ripple animator
+ * and used by onDraw().
+ */
+ private float mCurrentRippleRingDiameter;
+ /**
+ * The current ripple ring thickness which is updated by the ripple animator
+ * and used by onDraw().
+ */
+ private float mCurrentRippleRingThickness;
+ /**
+ * The current ripple ring opacity which is updated by the ripple animator
+ * and used by onDraw().
+ */
+ private float mCurrentRippleRingOpacity;
+ /**
+ * The paint used for drawing the ripple effect.
+ */
+ private final Paint mRipplePaint;
+
+ // Fields for the hit state effect.
+ /**
+ * The paint to draw hit state circle.
+ */
+ private final Paint mHitStateCirclePaint;
+ /**
+ * The current hit state circle opacity (0.0 - 1.0) which is updated by the
+ * hit state animator. If -1, the hit state circle won't be drawn.
+ */
+ private float mCurrentHitStateCircleOpacity;
+
+ /**
+ * The pending reveal request. This is created when start is called, but is
+ * not drawn until the thumbnail is available. Once the bitmap is available
+ * it is swapped into the foreground request.
+ */
+ private RevealRequest mPendingRequest;
+
+ /**
+ * The currently animating reveal request.
+ */
+ private RevealRequest mForegroundRequest;
+
+ /**
+ * The latest finished reveal request. Its thumbnail will be shown until
+ * a newer one replace it.
+ */
+ private RevealRequest mBackgroundRequest;
+
+ private View.OnClickListener mOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Trigger the hit state animation. Fade out the hit state white
+ // circle by changing the alpha.
+ final ValueAnimator hitStateAnimator = ValueAnimator.ofFloat(
+ HIT_STATE_CIRCLE_OPACITY_BEGIN, HIT_STATE_CIRCLE_OPACITY_END);
+ hitStateAnimator.setDuration(HIT_STATE_DURATION_MS);
+ hitStateAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
+ hitStateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mCurrentHitStateCircleOpacity = (Float)valueAnimator.getAnimatedValue();
+ invalidate();
+ }
+ });
+ hitStateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+
+ mCurrentHitStateCircleOpacity = HIT_STATE_CIRCLE_OPACITY_HIDDEN;
+
+ if (mCallback.isPresent()) {
+ mCallback.get().onHitStateFinished();
+ }
+ }
+ });
+ hitStateAnimator.start();
+ }
+ };
+
+ /**
+ * Constructs a RoundedThumbnailView.
+ */
+ public RoundedThumbnailView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mCallback = Optional.empty();
+
+ // Make the view clickable.
+ setClickable(true);
+ setOnClickListener(mOnClickListener);
+
+ mThumbnailPadding = getResources().getDimension(R.dimen.rounded_thumbnail_padding);
+
+ // Load thumbnail pop-out effect constants.
+ mThumbnailStretchDurationMs = THUMBNAIL_STRETCH_DURATION_MS;
+ mThumbnailShrinkDurationMs = THUMBNAIL_SHRINK_DURATION_MS;
+ mThumbnailStretchDiameterBegin =
+ getResources().getDimension(R.dimen.rounded_thumbnail_diameter_min);
+ mThumbnailStretchDiameterEnd =
+ getResources().getDimension(R.dimen.rounded_thumbnail_diameter_max);
+ mThumbnailShrinkDiameterBegin = mThumbnailStretchDiameterEnd;
+ mThumbnailShrinkDiameterEnd =
+ getResources().getDimension(R.dimen.rounded_thumbnail_diameter_normal);
+ // Load ripple effect constants.
+ float startDelayRatio = 0.5f;
+ mRippleStartDelayMs = (long)(mThumbnailStretchDurationMs * startDelayRatio);
+ mRippleDurationMs = RIPPLE_DURATION_MS;
+ mRippleRingDiameterEnd =
+ getResources().getDimension(R.dimen.rounded_thumbnail_ripple_ring_diameter_max);
+
+ mViewRect = new RectF(0, 0, mRippleRingDiameterEnd, mRippleRingDiameterEnd);
+
+ mRippleRingDiameterBegin =
+ getResources().getDimension(R.dimen.rounded_thumbnail_ripple_ring_diameter_min);
+ mRippleRingThicknessBegin =
+ getResources().getDimension(R.dimen.rounded_thumbnail_ripple_ring_thick_max);
+ mRippleRingThicknessEnd =
+ getResources().getDimension(R.dimen.rounded_thumbnail_ripple_ring_thick_min);
+
+ mCurrentHitStateCircleOpacity = HIT_STATE_CIRCLE_OPACITY_HIDDEN;
+ // Draw the reveal while circle.
+ mHitStateCirclePaint = new Paint();
+ mHitStateCirclePaint.setAntiAlias(true);
+ mHitStateCirclePaint.setColor(Color.WHITE);
+ mHitStateCirclePaint.setStyle(Paint.Style.FILL);
+
+ mRipplePaint = new Paint();
+ mRipplePaint.setAntiAlias(true);
+ mRipplePaint.setColor(Color.WHITE);
+ mRipplePaint.setStyle(Paint.Style.STROKE);
+
+ mRevealCirclePaint = new Paint();
+ mRevealCirclePaint.setAntiAlias(true);
+ mRevealCirclePaint.setColor(Color.WHITE);
+ mRevealCirclePaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Ignore the spec since the size should be fixed.
+ int desiredSize = (int)mRippleRingDiameterEnd;
+ setMeasuredDimension(desiredSize, desiredSize);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ final float centerX = canvas.getWidth() / 2;
+ final float centerY = canvas.getHeight() / 2;
+
+ final float viewDiameter = mRippleRingDiameterEnd;
+ final float finalDiameter = mThumbnailShrinkDiameterEnd;
+
+ canvas.clipRect(mViewRect);
+
+ // Draw the thumbnail of latest finished reveal request.
+ if (mBackgroundRequest != null) {
+ Paint thumbnailPaint = mBackgroundRequest.getThumbnailPaint();
+ if (thumbnailPaint != null) {
+ // Draw the old thumbnail with the final diameter.
+ float scaleRatio = finalDiameter / viewDiameter;
+
+ canvas.save();
+ canvas.scale(scaleRatio, scaleRatio, centerX, centerY);
+ canvas.drawRoundRect(mViewRect, centerX, centerY, thumbnailPaint);
+ canvas.restore();
+ }
+ }
+
+ // Draw animated parts (thumbnail and ripple) if there exists a reveal request.
+ if (mForegroundRequest != null) {
+ // Draw ripple ring first or the ring will cover thumbnail.
+ if (mCurrentRippleRingThickness > 0) {
+ // Draw the ripple ring.
+ mRipplePaint.setAlpha((int)(mCurrentRippleRingOpacity * 255));
+ mRipplePaint.setStrokeWidth(mCurrentRippleRingThickness);
+
+ canvas.save();
+ canvas.drawCircle(centerX, centerY, mCurrentRippleRingDiameter / 2, mRipplePaint);
+ canvas.restore();
+ }
+
+ // Achieve the animation effect by scaling the transformation matrix.
+ float scaleRatio = mCurrentThumbnailDiameter / mRippleRingDiameterEnd;
+
+ canvas.save();
+ canvas.scale(scaleRatio, scaleRatio, centerX, centerY);
+
+ // Draw the new popping up thumbnail.
+ Paint thumbnailPaint = mForegroundRequest.getThumbnailPaint();
+ if (thumbnailPaint != null) {
+ canvas.drawRoundRect(mViewRect, centerX, centerY, thumbnailPaint);
+ }
+
+ // Draw the reveal while circle.
+ mRevealCirclePaint.setAlpha((int)(mCurrentRevealCircleOpacity * 255));
+ canvas.drawCircle(centerX, centerY, mRippleRingDiameterEnd / 2, mRevealCirclePaint);
+
+ canvas.restore();
+ }
+
+ // Draw hit state circle if necessary.
+ if (mCurrentHitStateCircleOpacity != HIT_STATE_CIRCLE_OPACITY_HIDDEN) {
+ canvas.save();
+ final float scaleRatio = finalDiameter / viewDiameter;
+ canvas.scale(scaleRatio, scaleRatio, centerX, centerY);
+
+ // Draw the hit state while circle.
+ mHitStateCirclePaint.setAlpha((int)(mCurrentHitStateCircleOpacity * 255));
+ canvas.drawCircle(centerX, centerY, mRippleRingDiameterEnd / 2, mHitStateCirclePaint);
+ canvas.restore();
+ }
+ }
+
+ /**
+ * Sets the callback.
+ *
+ * @param callback The callback to be set.
+ */
+ public void setCallback(Callback callback) {
+ mCallback = Optional.of(callback);
+ }
+
+ /**
+ * Gets the padding size with mode options and preview edges.
+ *
+ * @return The padding size with mode options and preview edges.
+ */
+ public float getThumbnailPadding() {
+ return mThumbnailPadding;
+ }
+
+ /**
+ * Gets the diameter of the thumbnail image after the revealing animation.
+ *
+ * @return The diameter of the thumbnail image after the revealing animation.
+ */
+ public float getThumbnailFinalDiameter() {
+ return mThumbnailShrinkDiameterEnd;
+ }
+
+ /**
+ * Starts the thumbnail revealing animation.
+ *
+ * @param accessibilityString An accessibility String to be announced during the revealing
+ * animation.
+ */
+ public void startRevealThumbnailAnimation(String accessibilityString) {
+ // MainThread.checkMainThread();
+ // Create a new request.
+ mPendingRequest = new RevealRequest(getMeasuredWidth(), accessibilityString);
+ }
+
+ /**
+ * Updates the thumbnail image.
+ *
+ * @param thumbnailBitmap The thumbnail image to be shown.
+ * @param rotation The orientation of the image in degrees.
+ */
+ public void setThumbnail(final Bitmap thumbnailBitmap, final int rotation) {
+ // MainThread.checkMainThread();
+
+ if (mPendingRequest != null) {
+ mPendingRequest.setThumbnailBitmap(thumbnailBitmap, rotation);
+
+ runPendingRequestAnimation();
+ } else {
+ Log.e(TAG, "Pending thumb was null!");
+ }
+ }
+
+ /**
+ * Hide the thumbnail.
+ */
+ public void hideThumbnail() {
+
+ setVisibility(GONE);
+
+ clearAnimations();
+
+ // Remove all pending reveal requests.
+ mPendingRequest = null;
+ mForegroundRequest = null;
+ mBackgroundRequest = null;
+ }
+
+ /**
+ * Stop currently running animators.
+ */
+ private void clearAnimations() {
+ // Stop currently running animators.
+ if (mThumbnailAnimatorSet != null && mThumbnailAnimatorSet.isRunning()) {
+ mThumbnailAnimatorSet.removeAllListeners();
+ mThumbnailAnimatorSet.cancel();
+ // Release the animator so that a new instance will be created and
+ // its listeners properly reconnected. Fix for b/19034435
+ mThumbnailAnimatorSet = null;
+ }
+
+ if (mRippleAnimator != null && mRippleAnimator.isRunning()) {
+ mRippleAnimator.removeAllListeners();
+ mRippleAnimator.cancel();
+ // Release the animator so that a new instance will be created and
+ // its listeners properly reconnected. Fix for b/19034435
+ mRippleAnimator = null;
+ }
+ }
+
+ public void Invisible() {
+ setVisibility(INVISIBLE);
+ }
+
+ /**
+ * Set the foreground request to the background, complete it, and run the
+ * animation for the pending thumbnail.
+ */
+ private void runPendingRequestAnimation() {
+ // Shift foreground to background, and pending to foreground.
+ if (mForegroundRequest != null) {
+ mBackgroundRequest = mForegroundRequest;
+ mBackgroundRequest.finishRippleAnimation();
+ mBackgroundRequest.finishThumbnailAnimation();
+ }
+
+ mForegroundRequest = mPendingRequest;
+ mPendingRequest = null;
+
+ // Make this view visible.
+
+ setVisibility(VISIBLE);
+
+ // Ensure there are no running animations.
+ clearAnimations();
+
+ Interpolator stretchInterpolator;
+ stretchInterpolator = new AccelerateDecelerateInterpolator();
+
+ // The first phase of thumbnail animation. Stretch the thumbnail to the maximal size.
+ ValueAnimator stretchAnimator =
+ ValueAnimator.ofFloat(mThumbnailStretchDiameterBegin, mThumbnailStretchDiameterEnd);
+ stretchAnimator.setDuration(mThumbnailStretchDurationMs);
+ stretchAnimator.setInterpolator(stretchInterpolator);
+ stretchAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mCurrentThumbnailDiameter = (Float)valueAnimator.getAnimatedValue();
+ float fraction = valueAnimator.getAnimatedFraction();
+ float opacityDiff =
+ THUMBNAIL_REVEAL_CIRCLE_OPACITY_END - THUMBNAIL_REVEAL_CIRCLE_OPACITY_BEGIN;
+ mCurrentRevealCircleOpacity =
+ THUMBNAIL_REVEAL_CIRCLE_OPACITY_BEGIN + fraction * opacityDiff;
+ invalidate();
+ }
+ });
+
+ // The second phase of thumbnail animation. Shrink the thumbnail to the final size.
+ Interpolator shrinkInterpolator = stretchInterpolator;
+ ValueAnimator shrinkAnimator =
+ ValueAnimator.ofFloat(mThumbnailShrinkDiameterBegin, mThumbnailShrinkDiameterEnd);
+ shrinkAnimator.setDuration(mThumbnailShrinkDurationMs);
+ shrinkAnimator.setInterpolator(shrinkInterpolator);
+ shrinkAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mCurrentThumbnailDiameter = (Float)valueAnimator.getAnimatedValue();
+ invalidate();
+ }
+ });
+
+ // The stretch and shrink animators play sequentially.
+ mThumbnailAnimatorSet = new AnimatorSet();
+ mThumbnailAnimatorSet.playSequentially(stretchAnimator, shrinkAnimator);
+ mThumbnailAnimatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mForegroundRequest != null) {
+ // Mark the thumbnail animation as finished.
+ mForegroundRequest.finishThumbnailAnimation();
+ processRevealRequests();
+ }
+ }
+ });
+
+ // Start thumbnail animation immediately.
+ mThumbnailAnimatorSet.start();
+
+ // When start shrinking the thumbnail, a ripple effect is triggered at the same time.
+ mRippleAnimator = ValueAnimator.ofFloat(mRippleRingDiameterBegin, mRippleRingDiameterEnd);
+ mRippleAnimator.setDuration(mRippleDurationMs);
+ mRippleAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mForegroundRequest != null) {
+ mForegroundRequest.finishRippleAnimation();
+ processRevealRequests();
+ }
+ }
+ });
+ mRippleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mCurrentRippleRingDiameter = (Float)valueAnimator.getAnimatedValue();
+ float fraction = valueAnimator.getAnimatedFraction();
+ mCurrentRippleRingThickness =
+ mRippleRingThicknessBegin +
+ fraction * (mRippleRingThicknessEnd - mRippleRingThicknessBegin);
+ mCurrentRippleRingOpacity = RIPPLE_OPACITY_BEGIN +
+ fraction * (RIPPLE_OPACITY_END - RIPPLE_OPACITY_BEGIN);
+ invalidate();
+ }
+ });
+
+ // Start ripple animation after delay.
+ mRippleAnimator.setStartDelay(mRippleStartDelayMs);
+ mRippleAnimator.start();
+
+ // Announce the accessibility string.
+ // announceForAccessibility(mForegroundRequest.getAccessibilityString());
+ }
+
+ private void processRevealRequests() {
+ if (mForegroundRequest != null && mForegroundRequest.isFinished()) {
+ mBackgroundRequest = mForegroundRequest;
+ mForegroundRequest = null;
+ }
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return true;
+ }
+
+ /**
+ * Encapsulates necessary information for a complete thumbnail reveal animation.
+ */
+ private static class RevealRequest {
+ // The size of the thumbnail.
+ private float mViewSize;
+
+ // The accessibility string.
+ private String mAccessibilityString;
+
+ // The cached Paint object to draw the thumbnail.
+ private Paint mThumbnailPaint;
+
+ // The flag to indicate if thumbnail animation of this request is full-filled.
+ private boolean mThumbnailAnimationFinished;
+
+ // The flag to indicate if ripple animation of this request is full-filled.
+ private boolean mRippleAnimationFinished;
+
+ /**
+ * Constructs a reveal request. Use setThumbnailBitmap() to specify a source bitmap for the
+ * thumbnail.
+ *
+ * @param viewSize The size of the capture indicator view.
+ * @param accessibilityString The accessibility string of the request.
+ */
+ public RevealRequest(float viewSize, String accessibilityString) {
+ mAccessibilityString = accessibilityString;
+ mViewSize = viewSize;
+ }
+
+ /**
+ * Returns the accessibility string.
+ *
+ * @return the accessibility string.
+ */
+ public String getAccessibilityString() {
+ return mAccessibilityString;
+ }
+
+ /**
+ * Returns the paint object which can be used to draw the thumbnail on a Canvas.
+ *
+ * @return the paint object which can be used to draw the thumbnail on a Canvas.
+ */
+ public Paint getThumbnailPaint() {
+ return mThumbnailPaint;
+ }
+
+ /**
+ * Used to precompute the thumbnail paint from the given source bitmap.
+ */
+ private void precomputeThumbnailPaint(Bitmap srcBitmap, int rotation) {
+ // Lazy loading the thumbnail paint object.
+ if (mThumbnailPaint == null) {
+ // Can't create a paint object until the thumbnail bitmap is available.
+ if (srcBitmap == null) {
+ return;
+ }
+ // The original bitmap should be a square shape.
+ if (srcBitmap.getWidth() != srcBitmap.getHeight()) {
+ return;
+ }
+
+ // Create a bitmap shader for the paint.
+ BitmapShader shader =
+ new BitmapShader(srcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+ if (srcBitmap.getWidth() != mViewSize) {
+ // Create a transformation matrix for the bitmap shader if the size is not
+ // matched.
+ RectF srcRect =
+ new RectF(0.0f, 0.0f, srcBitmap.getWidth(), srcBitmap.getHeight());
+ RectF dstRect = new RectF(0.0f, 0.0f, mViewSize, mViewSize);
+
+ Matrix shaderMatrix = new Matrix();
+
+ // Scale the shader to fit the destination view size.
+ shaderMatrix.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.FILL);
+
+ // Rotate the image around the given source rect point.
+ shaderMatrix.preRotate(rotation, srcRect.width() / 2, srcRect.height() / 2);
+
+ shader.setLocalMatrix(shaderMatrix);
+ }
+
+ // Create the paint for drawing the thumbnail in a circle.
+ mThumbnailPaint = new Paint();
+ mThumbnailPaint.setAntiAlias(true);
+ mThumbnailPaint.setShader(shader);
+ }
+ }
+
+ /**
+ * Checks if the request is full-filled.
+ *
+ * @return True if both thumbnail animation and ripple animation are finished
+ */
+ public boolean isFinished() {
+ return mThumbnailAnimationFinished && mRippleAnimationFinished;
+ }
+
+ /**
+ * Marks the thumbnail animation is finished.
+ */
+ public void finishThumbnailAnimation() {
+ mThumbnailAnimationFinished = true;
+ }
+
+ /**
+ * Marks the ripple animation is finished.
+ */
+ public void finishRippleAnimation() {
+ mRippleAnimationFinished = true;
+ }
+
+ /**
+ * Updates the thumbnail image.
+ *
+ * @param thumbnailBitmap The thumbnail image to be shown.
+ * @param rotation The orientation of the image in degrees.
+ */
+ public void setThumbnailBitmap(Bitmap thumbnailBitmap, int rotation) {
+ Bitmap originalBitmap = thumbnailBitmap;
+ // Crop the image if it is not square.
+ if (originalBitmap.getWidth() != originalBitmap.getHeight()) {
+ originalBitmap = cropCenterBitmap(originalBitmap);
+ }
+
+ precomputeThumbnailPaint(originalBitmap, rotation);
+ }
+
+ /**
+ * Obtains a square bitmap by cropping the center of a bitmap. If the given image is
+ * portrait, the cropped image keeps 100% original width and vertically centered to the
+ * original image. If the given image is landscape, the cropped image keeps 100% original
+ * height and horizontally centered to the original image.
+ *
+ * @param srcBitmap the bitmap image to be cropped in the center.
+ * @return a result square bitmap.
+ */
+ private Bitmap cropCenterBitmap(Bitmap srcBitmap) {
+ int srcWidth = srcBitmap.getWidth();
+ int srcHeight = srcBitmap.getHeight();
+ Bitmap dstBitmap;
+ if (srcWidth >= srcHeight) {
+ dstBitmap = Bitmap.createBitmap(srcBitmap, srcWidth / 2 - srcHeight / 2, 0,
+ srcHeight, srcHeight);
+ } else {
+ dstBitmap = Bitmap.createBitmap(srcBitmap, 0, srcHeight / 2 - srcWidth / 2,
+ srcWidth, srcWidth);
+ }
+ return dstBitmap;
+ }
+ }
+}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsActivity.java b/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsActivity.java
index bf385e1..d2fef0f 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsActivity.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsActivity.java
@@ -16,28 +16,13 @@
package com.intel.multicamera;
-import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.CamcorderProfile;
import android.os.Bundle;
import android.util.Log;
-import android.util.Size;
-import android.util.SparseArray;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceGroup;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
public class SettingsActivity extends AppCompatActivity {
private String TAG = "settings";
@@ -52,105 +37,19 @@ protected void onCreate(Bundle savedInstanceState) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
- CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
-
- try {
- GlobalVariable.numOfCameras = manager.getCameraIdList().length;
- Log.d(TAG, "Inside Settings Total Cameras: " + manager.getCameraIdList().length);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
-
- if (GlobalVariable.numOfCameras != 0) getSupportedSize(manager);
-
getFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
- public void getSupportedSize(CameraManager manager) {
- try {
- String camerId;
-
- GlobalVariable.camerId = manager.getCameraIdList()[0];
-
- camerId = GlobalVariable.camerId;
-
- CameraCharacteristics characteristics = manager.getCameraCharacteristics(camerId);
-
- StreamConfigurationMap map =
- characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (map == null) {
- }
-
- GlobalVariable.SupportedSizes =
- new ArrayList<>(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)));
-
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
public static class SettingsFragment
extends PreferenceFragment implements OnSharedPreferenceChangeListener {
public String TAG = "SettingsFragment";
- public static final String SIZE_LARGE = "large";
- public static final String SIZE_MEDIUM = "medium";
- public static final String SIZE_SMALL = "small";
-
- public static String DEFAULT_KEY = "capture_list";
-
- public String[] mCamcorderProfileNames;
- private static final String SIZE_SETTING_STRING_DIMENSION_DELIMITER = "x";
-
- public static SparseArray sCachedSelectedVideoQualities =
- new SparseArray(3);
- private static String mPrefChangedKey = null;
- static boolean isPrefChangedKeyChanged = false;
- /** The selected {@link CamcorderProfile} qualities. */
- public static class SelectedVideoQualities {
- public int large = -1;
- public int medium = -1;
- public int small = -1;
-
- public int getFromSetting(String sizeSetting) {
- // Sanitize the value to be either small, medium or large. Default
- // to the latter.
- if (!SIZE_SMALL.equals(sizeSetting) && !SIZE_MEDIUM.equals(sizeSetting)) {
- sizeSetting = SIZE_LARGE;
- }
-
- if (SIZE_LARGE.equals(sizeSetting)) {
- return large;
- } else if (SIZE_MEDIUM.equals(sizeSetting)) {
- return medium;
- } else {
- return small;
- }
- }
- }
-
- /** Video qualities sorted by size. */
- public static int[] sVideoQualities =
- new int[] {// CamcorderProfile.QUALITY_HIGH,
- CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P,
- CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF,
- CamcorderProfile.QUALITY_QVGA, CamcorderProfile.QUALITY_QCIF,
- CamcorderProfile.QUALITY_LOW};
-
- static SelectedVideoQualities VideoQualities;
- public int numOfCameras = GlobalVariable.numOfCameras;
- public String camerId = GlobalVariable.camerId;
- ;
- public List PictureSizes = GlobalVariable.SupportedSizes;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- setPreferencesFromResource(R.xml.root_preferences, rootKey);
- mCamcorderProfileNames = getResources().getStringArray(R.array.camcorder_profile_names);
-
- isPrefChangedKeyChanged = false;
+ setPreferencesFromResource(R.xml.settings, rootKey);
}
@Override
@@ -160,24 +59,6 @@ public void onResume() {
Log.d(TAG, "SettingsFragment onResume");
- /* Put in the summaries for the currently set values.
- final PreferenceScreen Multi_Cam =
- (PreferenceScreen) findPreference("multi_usb_cam_list");*/
-
- setVisibilities();
-
- if (numOfCameras > 0) {
- VideoQualities = getSelectedVideoQualities(0);
-
- // Put in the summaries for the currently set values.
- final PreferenceGroup Prf_Resolution =
- (PreferenceGroup)findPreference("pref_resolution");
-
- fillEntriesAndSummaries(Prf_Resolution);
- }
-
- Log.d(TAG, "SettingsFragment onResume end");
-
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(
this);
}
@@ -191,310 +72,6 @@ public void onPause() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String Key) {
- setSummary(findPreference(Key));
- mPrefChangedKey = Key;
- isPrefChangedKeyChanged = true;
- }
-
- public static String getchangedPrefKey() {
- if (isPrefChangedKeyChanged == true) {
- return mPrefChangedKey;
- } else {
- return DEFAULT_KEY;
- }
- }
-
- /**
- * Set the summary for the given preference. The given preference needs
- * to be a {@link ListPreference}.
- */
- private void setSummary(Preference preference) {
- if (!(preference instanceof ListPreference)) {
- return;
- }
-
- ListPreference listPreference = (ListPreference)preference;
- if (listPreference.getKey().equals("capture_list")) {
- setSummaryForSelection(PictureSizes, listPreference);
- } else if (listPreference.getKey().equals("video_list")) {
- setSummaryForSelection(VideoQualities, listPreference);
- } else {
- listPreference.setSummary(listPreference.getEntry());
- }
- }
-
- /**
- * This is used to serialize a size to a string for storage in settings
- *
- * @param size The size to serialize.
- * @return the string to be saved in preferences
- */
- private static String sizeToSettingString(Size size) {
- return size.getWidth() + SIZE_SETTING_STRING_DIMENSION_DELIMITER + size.getHeight();
- }
-
- /**
- * Sets the summary for the given list preference.
- *
- * @param displayableSizes The human readable preferred sizes
- * @param preference The preference for which to set the summary.
- */
- private void setSummaryForSelection(List displayableSizes,
- ListPreference preference) {
- String setting = preference.getValue();
- if (setting == null || !setting.contains("x")) {
- return;
- }
- Size settingSize = sizeFromSettingString(setting);
- if (settingSize == null) {
- return;
- }
- preference.setSummary(getSizeSummaryString(settingSize));
- }
-
- /**
- * Sets the summary for the given list preference.
- *
- * @param selectedQualities The selected video qualities.
- * @param preference The preference for which to set the summary.
- */
- private void setSummaryForSelection(SelectedVideoQualities selectedQualities,
- ListPreference preference) {
- if (selectedQualities == null) {
- return;
- }
-
- int selectedQuality = selectedQualities.getFromSetting(preference.getValue());
- Log.d(TAG, "SettingsFragment selectedQuality " + selectedQuality);
- preference.setSummary(mCamcorderProfileNames[selectedQuality]);
- }
-
- /**
- * This parses a setting string and returns the representative size.
- *
- * @param sizeSettingString The string that stored in settings to represent a size.
- * @return the represented Size.
- */
- public static Size sizeFromSettingString(String sizeSettingString) {
- if (sizeSettingString == null) {
- return null;
- }
- String[] parts = sizeSettingString.split(SIZE_SETTING_STRING_DIMENSION_DELIMITER);
- if (parts.length != 2) {
- return null;
- }
-
- try {
- int width = Integer.parseInt(parts[0]);
- int height = Integer.parseInt(parts[1]);
- return new Size(width, height);
- } catch (NumberFormatException ex) {
- return null;
- }
- }
-
- /**
- * @param size The photo resolution.
- * @return A human readable and translated string for labeling the
- * picture size in megapixels.
- */
- private String getSizeSummaryString(Size size) {
- int width = size.getWidth();
- int height = size.getHeight();
- String result = getResources().getString(R.string.setting_summary_width_and_height,
- width, height);
- return result;
- }
-
- /**
- * Depending on camera availability on the device, this removes settings
- * for cameras the device doesn't have.
- */
- private void setVisibilities() {
- Log.d(TAG, "SettingsFragment setVisibilities");
-
- PreferenceGroup Prf_Resolution = (PreferenceGroup)findPreference("pref_resolution");
- PreferenceGroup Prf_Src = (PreferenceGroup)findPreference("pref_Source");
- if (numOfCameras == 0) {
- recursiveDelete(Prf_Resolution, findPreference("capture_list"));
- recursiveDelete(Prf_Resolution, findPreference("video_list"));
-
- recursiveDelete(Prf_Src, findPreference("multi_usb_cam_list"));
- }
- }
-
- /**
- * Recursively go through settings and fill entries and summaries of our
- * preferences.
- */
-
- private void fillEntriesAndSummaries(PreferenceGroup group) {
- for (int i = 0; i < group.getPreferenceCount(); ++i) {
- Preference pref = group.getPreference(i);
- if (pref instanceof PreferenceGroup) {
- fillEntriesAndSummaries((PreferenceGroup)pref);
- }
- setSummary(pref);
- setEntries(pref);
- }
- }
-
- /**
- * Recursively traverses the tree from the given group as the route and
- * tries to delete the preference. Traversal stops once the preference
- * was found and removed.
- */
- private boolean recursiveDelete(PreferenceGroup group, Preference preference) {
- Log.d(TAG, "SettingsFragment recursiveDelete");
-
- if (group == null) {
- Log.d(TAG, "attempting to delete from null preference group");
- return false;
- }
- if (preference == null) {
- Log.d(TAG, "attempting to delete null preference");
- return false;
- }
- if (group.removePreference(preference)) {
- Log.d(TAG, "Removal was successful.");
- return true;
- }
-
- for (int i = 0; i < group.getPreferenceCount(); ++i) {
- Preference pref = group.getPreference(i);
- if (pref instanceof PreferenceGroup) {
- if (recursiveDelete((PreferenceGroup)pref, preference)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Set the entries for the given preference. The given preference needs
- * to be a {@link ListPreference}
- */
- private void setEntries(Preference preference) {
- if (!(preference instanceof ListPreference)) {
- return;
- }
-
- ListPreference listPreference = (ListPreference)preference;
- if (listPreference.getKey().equals("capture_list")) {
- setEntriesForSelection(PictureSizes, listPreference);
- } else if (listPreference.getKey().equals("video_list")) {
- setEntriesForSelection(VideoQualities, listPreference);
- }
- }
-
- /**
- * Sets the entries for the given list preference.
- *
- * @param selectedSizes The possible S,M,L entries the user can choose
- * from.
- * @param preference The preference to set the entries for.
- */
- private void setEntriesForSelection(List selectedSizes, ListPreference preference) {
- if (selectedSizes == null) {
- return;
- }
-
- String[] entries = new String[selectedSizes.size()];
- String[] entryValues = new String[selectedSizes.size()];
- for (int i = 0; i < selectedSizes.size(); i++) {
- Size size = selectedSizes.get(i);
- entries[i] = getSizeSummaryString(size);
- entryValues[i] = sizeToSettingString(size);
- }
- preference.setEntries(entries);
- preference.setEntryValues(entryValues);
- }
-
- /**
- * Sets the entries for the given list preference.
- *
- * @param selectedQualities The possible S,M,L entries the user can
- * choose from.
- * @param preference The preference to set the entries for.
- */
- private void setEntriesForSelection(SelectedVideoQualities selectedQualities,
- ListPreference preference) {
- if (selectedQualities == null) {
- return;
- }
-
- // Avoid adding double entries at the bottom of the list which
- // indicates that not at least 3 qualities are supported.
- ArrayList entries = new ArrayList();
- entries.add(mCamcorderProfileNames[selectedQualities.large]);
- if (selectedQualities.medium != selectedQualities.large) {
- entries.add(mCamcorderProfileNames[selectedQualities.medium]);
- }
- if (selectedQualities.small != selectedQualities.medium) {
- entries.add(mCamcorderProfileNames[selectedQualities.small]);
- }
- preference.setEntries(entries.toArray(new String[0]));
- }
-
- /**
- * Determines the video quality for large/medium/small for the given camera.
- * Returns the one matching the given setting. Defaults to 'large' of the
- * qualitySetting does not match either large. medium or small.
- *
- * @param qualitySetting One of 'large', 'medium', 'small'.
- * @param cameraId The ID of the camera for which to get the quality
- * setting.
- * @return The CamcorderProfile quality setting.}
- */
-
- static int getVideoQuality(int cameraId, String qualitySetting) {
- return getSelectedVideoQualities(cameraId).getFromSetting(qualitySetting);
- }
-
- static SelectedVideoQualities getSelectedVideoQualities(int cameraId) {
- if (sCachedSelectedVideoQualities.get(cameraId) != null) {
- return sCachedSelectedVideoQualities.get(cameraId);
- }
-
- // Go through the sizes in descending order, see if they are supported,
- // and set large/medium/small accordingly.
- // If no quality is supported at all, the first call to
- // getNextSupportedQuality will throw an exception.
- // If only one quality is supported, then all three selected qualities
- // will be the same.
- int largeIndex = getNextSupportedVideoQualityIndex(cameraId, -1);
- int mediumIndex = getNextSupportedVideoQualityIndex(cameraId, largeIndex);
- int smallIndex = getNextSupportedVideoQualityIndex(cameraId, mediumIndex);
- VideoQualities = new SelectedVideoQualities();
- VideoQualities.large = sVideoQualities[largeIndex];
- VideoQualities.medium = sVideoQualities[mediumIndex];
- VideoQualities.small = sVideoQualities[smallIndex];
- sCachedSelectedVideoQualities.put(cameraId, VideoQualities);
- return VideoQualities;
- }
-
- /*
- * Starting from 'start' this method returns the next supported video
- * quality.
- */
- static int getNextSupportedVideoQualityIndex(int cameraId, int start) {
- for (int i = start + 1; i < sVideoQualities.length; ++i) {
- if (CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])) {
- // We found a new supported quality.
- return i;
- }
- }
-
- // Failed to find another supported quality.
- if (start < 0 || start >= sVideoQualities.length) {
- // This means we couldn't find any supported quality.
- throw new IllegalArgumentException("Could not find supported video qualities.");
- }
-
- // We previously found a larger supported size. In this edge case, just
- // return the same index as the previous size.
- return start;
}
}
-}
+}
\ No newline at end of file
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsPrefUtil.java b/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsPrefUtil.java
new file mode 100644
index 0000000..7d3b24c
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/SettingsPrefUtil.java
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.CamcorderProfile;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Size;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceGroup;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class SettingsPrefUtil
+ extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
+ public static String TAG = "SettingsPrefUtil";
+
+ public static final String SIZE_LARGE = "large";
+ public static final String SIZE_MEDIUM = "medium";
+ public static final String SIZE_SMALL = "small";
+
+ public String[] mCamcorderProfileNames;
+ private static final String SIZE_SETTING_STRING_DIMENSION_DELIMITER = "x";
+
+ public static SparseArray sCachedSelectedVideoQualities =
+ new SparseArray<>(3);
+
+ private String CameraId;
+ private int root_preferences;
+ private String pref_resolution;
+ private String video_list, capture_list;
+ public List PictureSizes;
+ static final Size SIZE_4K = new Size(3840, 2160);
+ static final Size SIZE_1080P = new Size(1920, 1080);
+ static final Size SIZE_720P = new Size(1280, 720);
+ static final Size SIZE_480P = new Size(640, 480);
+ static final Size SIZE_240P = new Size(320, 240);
+
+ /**
+ * The selected {@link CamcorderProfile} qualities.
+ */
+
+ public static class SelectedVideoQualities {
+ public int large = -1;
+ public int medium = -1;
+ public int small = -1;
+
+ public int getFromSetting(String sizeSetting) {
+ // Sanitize the value to be either small, medium or large. Default
+ // to the latter.
+ if (!SIZE_SMALL.equals(sizeSetting) && !SIZE_MEDIUM.equals(sizeSetting)) {
+ sizeSetting = SIZE_LARGE;
+ }
+
+ if (SIZE_LARGE.equals(sizeSetting)) {
+ return large;
+ } else if (SIZE_MEDIUM.equals(sizeSetting)) {
+ return medium;
+ } else {
+ return small;
+ }
+ }
+ }
+
+ public void getSupportedSize(String camerId) {
+ try {
+ List ImageDimentions;
+
+ CameraManager manager =
+ (CameraManager)getActivity().getSystemService(Context.CAMERA_SERVICE);
+
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(camerId);
+
+ StreamConfigurationMap map =
+ characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ if (map == null) {
+ }
+
+ ImageDimentions = new ArrayList<>(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)));
+
+ PictureSizes = new ArrayList(Arrays.asList());
+
+ Log.d(TAG, " @@ getSupportedSize onResume @@" + CameraId);
+
+ for (Size size : ImageDimentions) {
+ if (size.equals(SIZE_240P)) {
+ PictureSizes.add(SIZE_240P);
+
+ } else if (size.equals(SIZE_480P)) {
+ PictureSizes.add(SIZE_480P);
+
+ } else if (size.equals(SIZE_720P)) {
+ PictureSizes.add(SIZE_720P);
+
+ } else if (size.equals(SIZE_1080P)) {
+ PictureSizes.add(SIZE_1080P);
+
+ } else if (size.equals(SIZE_4K)) {
+ PictureSizes.add(SIZE_4K);
+ }
+ }
+
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Video qualities sorted by size.
+ */
+ public static int[] sVideoQualities =
+ new int[] {// CamcorderProfile.QUALITY_HIGH,
+ CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P,
+ CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF,
+ CamcorderProfile.QUALITY_QVGA, CamcorderProfile.QUALITY_QCIF,
+ CamcorderProfile.QUALITY_LOW};
+
+ static SelectedVideoQualities VideoQualities;
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ switch (getArguments().getInt("root_preferences")) {
+ case R.xml.root_preferences:
+ root_preferences = R.xml.root_preferences;
+ CameraId = getArguments().getString("Camera_id");
+ break;
+ case R.xml.root_preferences_1:
+ root_preferences = R.xml.root_preferences_1;
+ CameraId = getArguments().getString("Camera_id");
+ break;
+ case R.xml.root_preferences_2:
+ root_preferences = R.xml.root_preferences_2;
+ CameraId = getArguments().getString("Camera_id");
+ break;
+ case R.xml.root_preferences_3:
+ root_preferences = R.xml.root_preferences_3;
+ CameraId = getArguments().getString("Camera_id");
+ break;
+ default:
+ break;
+ }
+
+ setPreferencesFromResource(root_preferences, rootKey);
+ mCamcorderProfileNames = getResources().getStringArray(R.array.camcorder_profile_names);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v;
+ v = super.onCreateView(inflater, container, savedInstanceState);
+
+ switch (getArguments().getString("pref_resolution")) {
+ case "pref_resolution":
+ pref_resolution = "pref_resolution";
+ break;
+ case "pref_resolution_1":
+ pref_resolution = "pref_resolution_1";
+ break;
+ case "pref_resolution_2":
+ pref_resolution = "pref_resolution_2";
+ break;
+ case "pref_resolution_3":
+ pref_resolution = "pref_resolution_3";
+ break;
+ default:
+ break;
+ }
+
+ switch (getArguments().getString("video_list")) {
+ case "video_list":
+ video_list = "video_list";
+ break;
+ case "video_list_1":
+ video_list = "video_list_1";
+ break;
+ case "video_list_2":
+ video_list = "video_list_2";
+ break;
+ case "video_list_3":
+ video_list = "video_list_3";
+ break;
+ default:
+ break;
+ }
+
+ switch (getArguments().getString("capture_list")) {
+ case "capture_list":
+ capture_list = "capture_list";
+ break;
+ case "capture_list_1":
+ capture_list = "capture_list_1";
+ break;
+ case "capture_list_2":
+ capture_list = "capture_list_2";
+ break;
+ case "capture_list_3":
+ capture_list = "capture_list_3";
+ break;
+
+ default:
+ break;
+ }
+
+ VideoQualities = getSelectedVideoQualities(0);
+
+ getSupportedSize(CameraId);
+
+ // Put in the summaries for the currently set values.
+ final PreferenceGroup Prf_Resolution = (PreferenceGroup)findPreference(pref_resolution);
+
+ fillEntriesAndSummaries(Prf_Resolution);
+
+ return v;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // final Activity activity = this.getActivity();
+ Log.d(TAG, " @@ SettingsFragment onResume @@" + CameraId);
+
+ VideoQualities = getSelectedVideoQualities(0);
+
+ getSupportedSize(CameraId);
+
+ // Put in the summaries for the currently set values.
+ final PreferenceGroup Prf_Resolution = (PreferenceGroup)findPreference(pref_resolution);
+
+ fillEntriesAndSummaries(Prf_Resolution);
+
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+
+ Log.d(TAG, "SettingsFragment onResume end");
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // final Activity activity = this.getActivity();
+ Log.d(TAG, " @@ SettingsFragment onPause @@" + CameraId);
+ getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
+ this);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(TAG, " @@ SettingsFragment onDestroy @@" + CameraId);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String Key) {
+ setSummary(findPreference(Key));
+
+ switch (Key) {
+ case "capture_list":
+ sharedPreferences.edit().putString("pref_resolution", Key).apply();
+ break;
+ case "capture_list_1":
+ sharedPreferences.edit().putString("pref_resolution_1", Key).apply();
+ break;
+ case "capture_list_2":
+ sharedPreferences.edit().putString("pref_resolution_2", Key).apply();
+ break;
+ case "capture_list_3":
+ sharedPreferences.edit().putString("pref_resolution_3", Key).apply();
+ break;
+ case "video_list":
+ sharedPreferences.edit().putString("pref_resolution", Key).apply();
+ break;
+ case "video_list_1":
+ sharedPreferences.edit().putString("pref_resolution_1", Key).apply();
+ break;
+ case "video_list_2":
+ sharedPreferences.edit().putString("pref_resolution_2", Key).apply();
+ break;
+ case "video_list_3":
+ sharedPreferences.edit().putString("pref_resolution_3", Key).apply();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Set the summary for the given preference. The given preference needs
+ * to be a {@link ListPreference}.
+ */
+ private void setSummary(Preference preference) {
+ if (!(preference instanceof ListPreference)) {
+ return;
+ }
+
+ ListPreference listPreference = (ListPreference)preference;
+ if (listPreference.getKey().equals(capture_list)) {
+ setSummaryForSelection(PictureSizes, listPreference);
+ } else if (listPreference.getKey().equals(video_list)) {
+ setSummaryForSelection(VideoQualities, listPreference);
+ } else {
+ listPreference.setSummary(listPreference.getEntry());
+ }
+ }
+
+ /**
+ * This is used to serialize a size to a string for storage in settings
+ *
+ * @param size The size to serialize.
+ * @return the string to be saved in preferences
+ */
+ private static String sizeToSettingString(Size size) {
+ return size.getWidth() + SIZE_SETTING_STRING_DIMENSION_DELIMITER + size.getHeight();
+ }
+
+ /**
+ * Sets the summary for the given list preference.
+ *
+ * @param displayableSizes The human readable preferred sizes
+ * @param preference The preference for which to set the summary.
+ */
+ private void setSummaryForSelection(List displayableSizes, ListPreference preference) {
+ String setting = preference.getValue();
+ if (setting == null || !setting.contains("x")) {
+ return;
+ }
+ Size settingSize = sizeFromSettingString(setting);
+ if (settingSize == null) {
+ return;
+ }
+ preference.setSummary(getSizeSummaryString(settingSize));
+ }
+
+ /**
+ * Sets the summary for the given list preference.
+ *
+ * @param selectedQualities The selected video qualities.
+ * @param preference The preference for which to set the summary.
+ */
+ private void setSummaryForSelection(SelectedVideoQualities selectedQualities,
+ ListPreference preference) {
+ if (selectedQualities == null) {
+ return;
+ }
+
+ int selectedQuality = selectedQualities.getFromSetting(preference.getValue());
+ Log.d(TAG, "SettingsFragment selectedQuality " + selectedQuality);
+ preference.setSummary(mCamcorderProfileNames[selectedQuality]);
+ }
+
+ /**
+ * This parses a setting string and returns the representative size.
+ *
+ * @param sizeSettingString The string that stored in settings to represent a size.
+ * @return the represented Size.
+ */
+ public static Size sizeFromSettingString(String sizeSettingString) {
+ if (sizeSettingString == null) {
+ return null;
+ }
+ String[] parts = sizeSettingString.split(SIZE_SETTING_STRING_DIMENSION_DELIMITER);
+ if (parts.length != 2) {
+ return null;
+ }
+
+ try {
+ int width = Integer.parseInt(parts[0]);
+ int height = Integer.parseInt(parts[1]);
+ return new Size(width, height);
+ } catch (NumberFormatException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * @param size The photo resolution.
+ * @return A human readable and translated string for labeling the
+ * picture size in megapixels.
+ */
+ private String getSizeSummaryString(Size size) {
+ int width = size.getWidth();
+ int height = size.getHeight();
+ String result =
+ getResources().getString(R.string.setting_summary_width_and_height, width, height);
+ return result;
+ }
+
+ /**
+ * Depending on camera availability on the device, this removes settings
+ * for cameras the device doesn't have.
+ */
+ private void setVisibilities() {
+ Log.d(TAG, "SettingsFragment setVisibilities");
+
+ PreferenceGroup Prf_Resolution = (PreferenceGroup)findPreference("pref_resolution");
+ PreferenceGroup Prf_Src = (PreferenceGroup)findPreference("pref_Source");
+ if (CameraId == null) {
+ recursiveDelete(Prf_Resolution, findPreference("capture_list"));
+ recursiveDelete(Prf_Resolution, findPreference("video_list"));
+
+ recursiveDelete(Prf_Src, findPreference("multi_usb_cam_list"));
+ }
+ }
+
+ /**
+ * Recursively go through settings and fill entries and summaries of our
+ * preferences.
+ */
+
+ private void fillEntriesAndSummaries(PreferenceGroup group) {
+ for (int i = 0; i < group.getPreferenceCount(); ++i) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof PreferenceGroup) {
+ fillEntriesAndSummaries((PreferenceGroup)pref);
+ }
+ setSummary(pref);
+ setEntries(pref);
+ }
+ }
+
+ /**
+ * Recursively traverses the tree from the given group as the route and
+ * tries to delete the preference. Traversal stops once the preference
+ * was found and removed.
+ */
+ private boolean recursiveDelete(PreferenceGroup group, Preference preference) {
+ Log.d(TAG, "SettingsFragment recursiveDelete");
+
+ if (group == null) {
+ Log.d(TAG, "attempting to delete from null preference group");
+ return false;
+ }
+ if (preference == null) {
+ Log.d(TAG, "attempting to delete null preference");
+ return false;
+ }
+ if (group.removePreference(preference)) {
+ Log.d(TAG, "Removal was successful.");
+ return true;
+ }
+
+ for (int i = 0; i < group.getPreferenceCount(); ++i) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof PreferenceGroup) {
+ if (recursiveDelete((PreferenceGroup)pref, preference)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Set the entries for the given preference. The given preference needs
+ * to be a {@link ListPreference}
+ */
+ private void setEntries(Preference preference) {
+ if (!(preference instanceof ListPreference)) {
+ return;
+ }
+
+ ListPreference listPreference = (ListPreference)preference;
+ if (listPreference.getKey().equals(capture_list)) {
+ setEntriesForSelection(PictureSizes, listPreference);
+ } else if (listPreference.getKey().equals(video_list)) {
+ setEntriesForSelection(VideoQualities, listPreference);
+ }
+ }
+
+ /**
+ * Sets the entries for the given list preference.
+ *
+ * @param selectedSizes The possible S,M,L entries the user can choose
+ * from.
+ * @param preference The preference to set the entries for.
+ */
+ private void setEntriesForSelection(List selectedSizes, ListPreference preference) {
+ if (selectedSizes == null) {
+ return;
+ }
+
+ String[] entries = new String[selectedSizes.size()];
+ String[] entryValues = new String[selectedSizes.size()];
+ for (int i = 0; i < selectedSizes.size(); i++) {
+ Size size = selectedSizes.get(i);
+ entries[i] = getSizeSummaryString(size);
+ entryValues[i] = sizeToSettingString(size);
+ }
+ preference.setEntries(entries);
+ preference.setEntryValues(entryValues);
+ }
+
+ /**
+ * Sets the entries for the given list preference.
+ *
+ * @param selectedQualities The possible S,M,L entries the user can
+ * choose from.
+ * @param preference The preference to set the entries for.
+ */
+ private void setEntriesForSelection(SelectedVideoQualities selectedQualities,
+ ListPreference preference) {
+ if (selectedQualities == null) {
+ return;
+ }
+
+ // Avoid adding double entries at the bottom of the list which
+ // indicates that not at least 3 qualities are supported.
+ ArrayList entries = new ArrayList();
+ entries.add(mCamcorderProfileNames[selectedQualities.large]);
+ if (selectedQualities.medium != selectedQualities.large) {
+ entries.add(mCamcorderProfileNames[selectedQualities.medium]);
+ }
+ if (selectedQualities.small != selectedQualities.medium) {
+ entries.add(mCamcorderProfileNames[selectedQualities.small]);
+ }
+ preference.setEntries(entries.toArray(new String[0]));
+ }
+
+ /**
+ * Determines the video quality for large/medium/small for the given camera.
+ * Returns the one matching the given setting. Defaults to 'large' of the
+ * qualitySetting does not match either large. medium or small.
+ *
+ * @param qualitySetting One of 'large', 'medium', 'small'.
+ * @param cameraId The ID of the camera for which to get the quality
+ * setting.
+ * @return The CamcorderProfile quality setting.}
+ */
+
+ static int getVideoQuality(int cameraId, String qualitySetting) {
+ return getSelectedVideoQualities(cameraId).getFromSetting(qualitySetting);
+ }
+
+ static SelectedVideoQualities getSelectedVideoQualities(int cameraId) {
+ if (sCachedSelectedVideoQualities.get(cameraId) != null) {
+ return sCachedSelectedVideoQualities.get(cameraId);
+ }
+
+ // Go through the sizes in descending order, see if they are supported,
+ // and set large/medium/small accordingly.
+ // If no quality is supported at all, the first call to
+ // getNextSupportedQuality will throw an exception.
+ // If only one quality is supported, then all three selected qualities
+ // will be the same.
+ int largeIndex = getNextSupportedVideoQualityIndex(cameraId, -1);
+ int mediumIndex = getNextSupportedVideoQualityIndex(cameraId, largeIndex);
+ int smallIndex = getNextSupportedVideoQualityIndex(cameraId, mediumIndex);
+ VideoQualities = new SelectedVideoQualities();
+ VideoQualities.large = sVideoQualities[largeIndex];
+ VideoQualities.medium = sVideoQualities[mediumIndex];
+ VideoQualities.small = sVideoQualities[smallIndex];
+ sCachedSelectedVideoQualities.put(cameraId, VideoQualities);
+ return VideoQualities;
+ }
+
+ /*
+ * Starting from 'start' this method returns the next supported video
+ * quality.
+ */
+ static int getNextSupportedVideoQualityIndex(int cameraId, int start) {
+ for (int i = start + 1; i < sVideoQualities.length; ++i) {
+ if (CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])) {
+ // We found a new supported quality.
+ return i;
+ }
+ }
+
+ // Failed to find another supported quality.
+ if (start < 0 || start >= sVideoQualities.length) {
+ // This means we couldn't find any supported quality.
+ throw new IllegalArgumentException("Could not find supported video qualities.");
+ }
+
+ // We previously found a larger supported size. In this edge case, just
+ // return the same index as the previous size.
+ return start;
+ }
+}
\ No newline at end of file
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/SurfaceUtil.java b/camera/MultiCameraApplication/java/com/intel/multicamera/SurfaceUtil.java
new file mode 100644
index 0000000..16ad523
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/SurfaceUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.graphics.SurfaceTexture;
+import android.opengl.GLES20;
+import javax.microedition.khronos.egl.*;
+
+public class SurfaceUtil {
+ private static final int[] ATTRIB_LIST = new int[] {
+ EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8, EGL10.EGL_NONE,
+ };
+
+ // http://stackoverflow.com/a/21564236/2681195
+ public static void clear(SurfaceTexture mTexture) {
+ EGL10 egl = (EGL10)EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ int[] version = new int[2];
+ egl.eglInitialize(display, version);
+
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] numConfig = new int[1];
+ egl.eglChooseConfig(display, ATTRIB_LIST, configs, 1, numConfig);
+
+ EGLSurface surface = egl.eglCreateWindowSurface(display, configs[0], mTexture, null);
+ EGLContext context = egl.eglCreateContext(display, configs[0], EGL10.EGL_NO_CONTEXT, null);
+
+ egl.eglMakeCurrent(display, surface, surface, context);
+
+ GLES20.glClearColor(0, 0, 1, 0);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+
+ egl.eglSwapBuffers(display, surface);
+ egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_CONTEXT);
+ egl.eglDestroyContext(display, context);
+ egl.eglDestroySurface(display, surface);
+ }
+}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/Thumbnail.java b/camera/MultiCameraApplication/java/com/intel/multicamera/Thumbnail.java
new file mode 100644
index 0000000..1562766
--- /dev/null
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/Thumbnail.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.multicamera;
+
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
+import java.io.FileDescriptor;
+
+public class Thumbnail {
+ public static Bitmap createVideoThumbnailBitmap(FileDescriptor fd, int targetWidth) {
+ return createVideoThumbnailBitmap(null, fd, targetWidth);
+ }
+
+ public static Bitmap createVideoThumbnailBitmap(String filePath, int targetWidth) {
+ return createVideoThumbnailBitmap(filePath, null, targetWidth);
+ }
+
+ private static Bitmap createVideoThumbnailBitmap(String filePath, FileDescriptor fd,
+ int targetWidth) {
+ Bitmap bitmap = null;
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ try {
+ if (filePath != null) {
+ retriever.setDataSource(filePath);
+ } else {
+ retriever.setDataSource(fd);
+ }
+ bitmap = retriever.getFrameAtTime(-1);
+ } catch (IllegalArgumentException ex) {
+ // Assume this is a corrupt video file
+ } catch (RuntimeException ex) {
+ // Assume this is a corrupt video file.
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException ex) {
+ // Ignore failures while cleaning up.
+ }
+ }
+ if (bitmap == null) return null;
+
+ // Scale down the bitmap if it is bigger than we need.
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+ if (width > targetWidth) {
+ float scale = (float)targetWidth / width;
+ int w = Math.round(scale * width);
+ int h = Math.round(scale * height);
+ bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
+ }
+ return bitmap;
+ }
+}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/TopRightCam.java b/camera/MultiCameraApplication/java/com/intel/multicamera/TopRightCam.java
deleted file mode 100644
index 21e73c2..0000000
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/TopRightCam.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (c) 2019 Intel Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intel.multicamera;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.*;
-import android.content.pm.PackageManager;
-import android.graphics.ImageFormat;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.graphics.SurfaceTexture;
-import android.hardware.camera2.*;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.CamcorderProfile;
-import android.media.Image;
-import android.media.ImageReader;
-import android.media.MediaRecorder;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.util.Size;
-import android.util.SparseIntArray;
-import android.view.Surface;
-import android.view.TextureView;
-import android.view.View;
-import android.widget.Button;
-import android.widget.Toast;
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.preference.PreferenceManager;
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-public class TopRightCam {
- Activity mActivity;
- private static final String TAG = "TopRightCam";
- private String mNextVideoAbsolutePath;
- private CamcorderProfile mProfile;
- /**
- * An {@link AutoFitTextureView} for camera preview.
- */
- private AutoFitTextureView textureView;
- private Button takePictureButton, TakeVideoButton;
-
- private MediaRecorder mMediaRecorder;
- private String cameraId;
- protected CameraDevice cameraDevice;
- protected CameraCaptureSession cameraCaptureSessions;
- protected CaptureRequest captureRequest;
- protected CaptureRequest.Builder captureRequestBuilder;
- private Size imageDimension, previewSize;
- private ImageReader imageReader;
- private File file;
- private Handler mBackgroundHandler;
- private HandlerThread mBackgroundThread;
- private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
- private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
- private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
- private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
- private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
- private SharedPreferences settings;
- /**
- * Whether the app is recording video now
- */
- private boolean mIsRecordingVideo;
-
- // The video file that the hardware camera is about to record into
- // (or is recording into.
- private String mVideoFilename, mPictureFilename;
- private ContentValues mCurrentVideoValues, mCurrentPictureValues;
- byte[] jpegLength;
-
- /**
- * Orientation of the camera sensor
- */
- private int mSensorOrientation;
-
- static {
- ORIENTATIONS.append(Surface.ROTATION_0, 90);
- ORIENTATIONS.append(Surface.ROTATION_90, 0);
- ORIENTATIONS.append(Surface.ROTATION_180, 270);
- ORIENTATIONS.append(Surface.ROTATION_270, 180);
- }
-
- public TopRightCam(Activity activity, AutoFitTextureView textureView, Button PictureButton,
- Button RecordButton) {
- Log.e(TAG, "constructor called");
- this.mActivity = activity;
- this.textureView = textureView;
- this.textureView.setSurfaceTextureListener(textureListener);
- this.ClickListeners(PictureButton, RecordButton);
- this.settings = PreferenceManager.getDefaultSharedPreferences(activity);
- }
-
- public void ClickListeners(Button PictureButton, Button RecordButton) {
- TakePicureOnClicked(PictureButton);
-
- StartVideoRecording(RecordButton);
- }
-
- private void TakePicureOnClicked(Button PictureButton) {
- takePictureButton = PictureButton;
- if (takePictureButton == null) return;
-
- takePictureButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- takePicture();
- Utils.broadcastNewPicture(mActivity.getApplicationContext(), mCurrentPictureValues);
- }
- });
- }
-
- private void StartVideoRecording(Button RecordButton) {
- TakeVideoButton = RecordButton;
- TakeVideoButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Intent i = new Intent(HomeScreenActivity.this, CameraActivity.class);
- System.out.println(" onCreate Record0");
- if (mIsRecordingVideo) {
- stopRecordingVideo();
- Utils.broadcastNewVideo(mActivity.getApplicationContext(), mCurrentVideoValues);
- takePictureButton.setVisibility(View.VISIBLE);
- } else {
- startRecordingVideo();
- takePictureButton.setVisibility(View.GONE);
- }
- }
- });
- }
-
- TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- // open your camera here
- openCamera(width, height);
- }
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- // Transform you image captured size according to the surface width and height
- configureTransform(width, height);
- }
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- return false;
- }
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- }
- };
-
- public void openCamera(int width, int height) {
- CameraManager manager = (CameraManager)mActivity.getSystemService(Context.CAMERA_SERVICE);
- Log.e(TAG, "is camera open");
- try {
- if (!((manager.getCameraIdList().length >= 2) &&
- (manager.getCameraIdList().length <= 4))) {
- Log.e(TAG, "this camera is not connected ");
- return;
- }
- cameraId = manager.getCameraIdList()[1];
- Log.e(TAG, "is camera open ID" + cameraId);
- CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
- StreamConfigurationMap map =
- characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (map == null) return;
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
-
- if (Key.compareTo("video_list") == 0) {
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
- previewSize = new Size(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- configureTransform(width, height);
- } else {
- previewSize = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG,
- "Selected imageDimension" + previewSize.getWidth() + previewSize.getHeight());
- configureTransform(width, height);
- }
-
- mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
- configureTransform(width, height);
- startBackgroundThread();
-
- manager.openCamera(cameraId, stateCallback, null);
-
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- Log.e(TAG, "openCamera X");
- }
-
- private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
- @Override
- public void onOpened(CameraDevice camera) {
- // This is called when the camera is open
- Log.e(TAG, "onOpened");
- cameraDevice = camera;
- createCameraPreview();
- }
- @Override
- public void onDisconnected(CameraDevice camera) {
- Log.e(TAG, "onDisconnected");
- closeCamera();
- }
- @Override
- public void onError(CameraDevice camera, int error) {
- Log.e(TAG, "onError");
- closeCamera();
- }
- };
-
- private void configureTransform(int viewWidth, int viewHeight) {
- if (null == textureView || null == previewSize) {
- return;
- }
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- Matrix matrix = new Matrix();
- RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
- Log.e(TAG, "configureTransform() viewWidth: " + viewWidth + " viewHeight: " + viewHeight);
- RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
- float centerX = viewRect.centerX();
- float centerY = viewRect.centerY();
- if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
- bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
- matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
- float scale = Math.max((float)viewHeight / previewSize.getHeight(),
- (float)viewWidth / previewSize.getWidth());
- matrix.postScale(scale, scale, centerX, centerY);
- matrix.postRotate(90 * (rotation - 2), centerX, centerY);
- } else if (Surface.ROTATION_180 == rotation) {
- matrix.postRotate(180, centerX, centerY);
- }
- textureView.setTransform(matrix);
- }
-
- protected void createCameraPreview() {
- try {
- closePreviewSession();
- SurfaceTexture texture = textureView.getSurfaceTexture();
- if (texture == null) return;
-
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String Key = SettingsActivity.SettingsFragment.getchangedPrefKey();
-
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
-
- if (Key.compareTo("video_list") == 0) {
- texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
- } else {
- texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
- }
-
- Surface surface = new Surface(texture);
- captureRequestBuilder =
- cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- captureRequestBuilder.addTarget(surface);
- cameraDevice.createCaptureSession(
- Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession cameraCaptureSession) {
- // The camera is already closed
- if (null == cameraDevice) {
- return;
- }
- // When the session is ready, we start displaying the preview.
- cameraCaptureSessions = cameraCaptureSession;
- updatePreview();
- }
- @Override
- public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
- Toast.makeText(mActivity, "Configuration change", Toast.LENGTH_SHORT)
- .show();
- }
- }, null);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- public void releaseMedia() {
- if (null != mMediaRecorder) {
- try {
- mMediaRecorder.stop();
- } catch (IllegalStateException ex) {
- Log.d(TAG, "Stop called before start");
- }
- mMediaRecorder.reset();
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
- }
-
- public void closeCamera() {
- closePreviewSession();
- if (null != cameraDevice) {
- cameraDevice.close();
- cameraDevice = null;
- }
- if (null != imageReader) {
- imageReader.close();
- imageReader = null;
- }
- releaseMedia();
- stopBackgroundThread();
- }
-
- /**
- * Starts a background thread and its {@link Handler}.
- */
- private void startBackgroundThread() {
- mBackgroundThread = new HandlerThread("Camera_1");
- mBackgroundThread.start();
- mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
- }
-
- /**
- * Stops the background thread and its {@link Handler}.
- */
- private void stopBackgroundThread() {
- if (mBackgroundThread != null) {
- mBackgroundThread.quitSafely();
- try {
- mBackgroundThread.join();
- mBackgroundThread = null;
- mBackgroundHandler = null;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- protected void updatePreview() {
- if (null == cameraDevice) {
- Log.e(TAG, "updatePreview error, return");
- }
- captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
- HandlerThread thread = new HandlerThread("Camera Preview");
- thread.start();
- Handler handler = new Handler(thread.getLooper());
- try {
- cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, handler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Retrieves the JPEG orientation from the specified screen rotation.
- *
- * @param rotation The screen rotation.
- * @return The JPEG orientation (one of 0, 90, 270, and 360)
- */
- private int getOrientation(int rotation) {
- // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
- // We have to take that into account and rotate JPEG properly.
- // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
- // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
- return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
- }
-
- protected void takePicture() {
- if (null == cameraDevice) {
- Log.e(TAG, "cameraDevice is null");
- return;
- }
-
- try {
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- imageDimension = SettingsActivity.SettingsFragment.sizeFromSettingString(
- settings.getString("capture_list", "640x480"));
- Log.d(TAG, "Selected imageDimension: " + imageDimension.getWidth() +
- imageDimension.getHeight());
- ImageReader reader = ImageReader.newInstance(
- imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.JPEG, 1);
- List outputSurfaces = new ArrayList(2);
- outputSurfaces.add(reader.getSurface());
- outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
- captureRequestBuilder =
- cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
- captureRequestBuilder.addTarget(reader.getSurface());
- captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,
- CameraMetadata.CONTROL_MODE_AUTO);
- // Orientation
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
-
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_IMAGE);
- if (fileDetails == null || fileDetails.length < 5) {
- Log.e(TAG, "Invalid file details");
- return;
- }
- mPictureFilename = fileDetails[3];
- mCurrentPictureValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_IMAGE, fileDetails,
- imageDimension.getWidth(), imageDimension.getHeight());
-
- file = new File(mPictureFilename);
-
- ImageReader.OnImageAvailableListener readerListener =
- new ImageReader.OnImageAvailableListener() {
- @Override
- public void onImageAvailable(ImageReader reader) {
- Image image = null;
- try {
- image = reader.acquireLatestImage();
- ByteBuffer buffer = image.getPlanes()[0].getBuffer();
- byte[] bytes = new byte[buffer.capacity()];
- buffer.get(bytes);
- jpegLength = bytes;
- mCurrentPictureValues.put(MediaStore.Images.ImageColumns.SIZE,
- jpegLength);
-
- save(bytes);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (image != null) {
- image.close();
- }
- }
- }
-
- private void save(byte[] bytes) throws IOException {
- OutputStream output = null;
- try {
- output = new FileOutputStream(file);
- output.write(bytes);
- } finally {
- if (null != output) {
- output.close();
- }
- }
- }
- };
- reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
- final CameraCaptureSession.CaptureCallback captureListener =
- new CameraCaptureSession.CaptureCallback() {
- @Override
- public void onCaptureCompleted(CameraCaptureSession session,
- CaptureRequest request,
- TotalCaptureResult result) {
- super.onCaptureCompleted(session, request, result);
- Toast.makeText(mActivity, "Saved:" + file, Toast.LENGTH_SHORT).show();
-
- createCameraPreview();
- }
- };
- cameraDevice.createCaptureSession(
- outputSurfaces, new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession session) {
- try {
- session.capture(captureRequestBuilder.build(), captureListener,
- mBackgroundHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onConfigureFailed(CameraCaptureSession session) {
- }
- }, mBackgroundHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- /* Recording Start*/
- private void startRecordingVideo() {
- if (null == cameraDevice || !textureView.isAvailable()) {
- return;
- }
- try {
- closePreviewSession();
- settings = PreferenceManager.getDefaultSharedPreferences(mActivity);
- String videoQuality = settings.getString("video_list", "medium");
-
- int quality = SettingsActivity.SettingsFragment.getVideoQuality(0, videoQuality);
- Log.d(TAG, "Selected video quality for '" + videoQuality + "' is " + quality);
-
- mProfile = CamcorderProfile.get(0, quality);
- setUpMediaRecorder();
- SurfaceTexture texture = textureView.getSurfaceTexture();
- if (texture == null) return;
- texture.setDefaultBufferSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
- List surfaces = new ArrayList<>();
-
- // Set up Surface for the camera preview
- Surface previewSurface = new Surface(texture);
- surfaces.add(previewSurface);
- captureRequestBuilder.addTarget(previewSurface);
-
- // Set up Surface for the MediaRecorder
- Surface recorderSurface = mMediaRecorder.getSurface();
- surfaces.add(recorderSurface);
- captureRequestBuilder.addTarget(recorderSurface);
-
- // Start a capture session
- // Once the session starts, we can update the UI and start recording
- cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession camCaptureSession) {
- cameraCaptureSessions = camCaptureSession;
- updatePreview();
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- // UI
- TakeVideoButton.setText(R.string.stop);
- mIsRecordingVideo = true;
-
- // Start recording
- mMediaRecorder.start();
- }
- });
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- if (null != mActivity) {
- Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
- }
- }
- }, mBackgroundHandler);
- } catch (CameraAccessException | IOException e) {
- e.printStackTrace();
- }
- }
-
- private void setUpMediaRecorder() throws IOException {
- if (null == mActivity) {
- return;
- }
-
- mMediaRecorder = new MediaRecorder();
- mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
- mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
-
- String fileDetails[] = Utils.generateFileDetails(Utils.MEDIA_TYPE_VIDEO);
- if (fileDetails == null || fileDetails.length < 5) {
- Log.e(TAG, "Invalid file details");
- return;
- }
- mVideoFilename = fileDetails[3];
- mCurrentVideoValues =
- Utils.getContentValues(Utils.MEDIA_TYPE_VIDEO, fileDetails,
- mProfile.videoFrameWidth, mProfile.videoFrameHeight);
-
- mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- /**
- * set output file in media recorder
- */
- mMediaRecorder.setOutputFile(mVideoFilename);
-
- mMediaRecorder.setVideoEncodingBitRate(10000000);
- mMediaRecorder.setVideoFrameRate(30);
- mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
- mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
- mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
-
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- switch (mSensorOrientation) {
- case SENSOR_ORIENTATION_DEFAULT_DEGREES:
- mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
- break;
- case SENSOR_ORIENTATION_INVERSE_DEGREES:
- mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
- break;
- }
- try {
- mMediaRecorder.prepare();
- } catch (IOException ex) {
- Log.e(TAG, "prepare failed for " + mVideoFilename, ex);
- releaseMedia();
- throw new RuntimeException(ex);
- }
- }
-
- private void closePreviewSession() {
- System.out.println(" closePreviewSession");
- if (cameraCaptureSessions != null) {
- cameraCaptureSessions.close();
- cameraCaptureSessions = null;
- }
- }
-
- private void stopRecordingVideo() {
- mIsRecordingVideo = false;
- TakeVideoButton.setText(R.string.record);
-
- // Stop recording
- releaseMedia();
-
- if (null != mActivity) {
- Toast.makeText(mActivity, "Video saved: " + mVideoFilename, Toast.LENGTH_SHORT).show();
- Log.d(TAG, "Video saved: " + mVideoFilename);
- }
- mVideoFilename = null;
-
- createCameraPreview();
- }
-}
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/Utils.java b/camera/MultiCameraApplication/java/com/intel/multicamera/Utils.java
index 32a3289..a4c4b09 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/Utils.java
+++ b/camera/MultiCameraApplication/java/com/intel/multicamera/Utils.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2014 The Android Open Source Project
* Copyright (c) 2019 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,28 +17,29 @@
package com.intel.multicamera;
-import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.*;
-import android.content.pm.PackageManager;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.*;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.CamcorderProfile;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.graphics.Point;
import android.net.Uri;
import android.os.Environment;
+import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.util.Log;
-import android.util.Size;
-import android.util.SparseIntArray;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
-import java.util.List;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
+import javax.microedition.khronos.opengles.GL11;
public class Utils {
private static final String TAG = "Utils";
@@ -48,13 +50,28 @@ public class Utils {
public static final String IMAGE_FILE_NAME_FORMAT = "'IMG'_yyyyMMdd_HHmmss";
public static final String VIDEO_FILE_NAME_FORMAT = "'VID'_yyyyMMdd_HHmmss";
- /** See android.hardware.Camera.ACTION_NEW_PICTURE. */
+ /**
+ * See android.hardware.Camera.ACTION_NEW_PICTURE.
+ */
public static final String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
- /** See android.hardware.Camera.ACTION_NEW_VIDEO. */
+ /**
+ * See android.hardware.Camera.ACTION_NEW_VIDEO.
+ */
public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
private static final String VIDEO_BASE_URI = "content://media/external/video/media";
+ private static final int MAX_PEEK_BITMAP_PIXELS = 1600000; // 1.6 * 4 MBs.
+
+ private static Uri mCurrentPictureUri, mCurrentVideoUri;
+
+ /**
+ * Has to be in sync with the receiving MovieActivity.
+ */
+ public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
+
+ private static final int DOWN_SAMPLE_FACTOR = 4;
+
@SuppressLint("SimpleDateFormat")
public static File createOutputmediaStorageDir() {
// To be safe, you should check that the SDCard is mounted
@@ -100,9 +117,19 @@ public static void broadcastNewPicture(Context context, ContentValues values) {
Log.v(TAG, "Current Picture URI: " + uri);
}
+ mCurrentPictureUri = uri;
+
context.sendBroadcast(new Intent(ACTION_NEW_PICTURE, uri));
}
+ public static Uri getCurrentPictureUri() {
+ return mCurrentPictureUri;
+ }
+
+ public static Uri getCurrentVideoUri() {
+ return mCurrentVideoUri;
+ }
+
public static void broadcastNewVideo(Context context, ContentValues values) {
Uri uri = null;
ContentResolver resolver = context.getContentResolver();
@@ -117,6 +144,7 @@ public static void broadcastNewVideo(Context context, ContentValues values) {
} finally {
Log.v(TAG, "Current video URI: " + uri);
}
+ mCurrentVideoUri = uri;
context.sendBroadcast(new Intent(ACTION_NEW_VIDEO, uri));
}
@@ -164,7 +192,7 @@ public static String[] generateFileDetails(int type) {
}
public static ContentValues getContentValues(int type, String fileDetails[], int width,
- int height) {
+ int height, long duration, long size) {
if (fileDetails.length < 5) {
Log.e(TAG, "Invalid file details");
return null;
@@ -185,6 +213,8 @@ public static ContentValues getContentValues(int type, String fileDetails[], int
contentValue.put(MediaStore.Images.ImageColumns.DATA, fileDetails[3]);
contentValue.put(MediaStore.MediaColumns.WIDTH, width);
contentValue.put(MediaStore.MediaColumns.HEIGHT, height);
+ contentValue.put(MediaStore.Images.ImageColumns.SIZE, size);
+
} else if (MEDIA_TYPE_VIDEO == type) {
contentValue = new ContentValues(9);
contentValue.put(MediaStore.Video.Media.TITLE, fileDetails[0]);
@@ -198,7 +228,329 @@ public static ContentValues getContentValues(int type, String fileDetails[], int
contentValue.put(MediaStore.Video.Media.HEIGHT, height);
contentValue.put(MediaStore.Video.Media.RESOLUTION,
Integer.toString(width) + "x" + Integer.toString(height));
+ contentValue.put(MediaStore.Video.Media.DURATION, duration);
+ contentValue.put(MediaStore.Video.Media.SIZE, size);
}
return contentValue;
}
+
+ /**
+ * Returns the maximum video recording duration (in milliseconds).
+ */
+ public static int getMaxVideoDuration(Context context) {
+ int duration = 0; // in milliseconds, 0 means unlimited.
+ try {
+ duration =
+ 0; // context.getResources().getInteger(R.integer.max_video_recording_length);
+ } catch (Resources.NotFoundException ex) {
+ }
+ return duration;
+ }
+
+ public static String millisecondToTimeString(long milliSeconds, boolean displayCentiSeconds) {
+ long seconds = milliSeconds / 1000; // round down to compute seconds
+ long minutes = seconds / 60;
+ long hours = minutes / 60;
+ long remainderMinutes = minutes - (hours * 60);
+ long remainderSeconds = seconds - (minutes * 60);
+
+ StringBuilder timeStringBuilder = new StringBuilder();
+
+ // Hours
+ if (hours > 0) {
+ if (hours < 10) {
+ timeStringBuilder.append('0');
+ }
+ timeStringBuilder.append(hours);
+
+ timeStringBuilder.append(':');
+ }
+
+ // Minutes
+ if (remainderMinutes < 10) {
+ timeStringBuilder.append('0');
+ }
+ timeStringBuilder.append(remainderMinutes);
+ timeStringBuilder.append(':');
+
+ // Seconds
+ if (remainderSeconds < 10) {
+ timeStringBuilder.append('0');
+ }
+ timeStringBuilder.append(remainderSeconds);
+
+ // Centi seconds
+ if (displayCentiSeconds) {
+ timeStringBuilder.append('.');
+ long remainderCentiSeconds = (milliSeconds - seconds * 1000) / 10;
+ if (remainderCentiSeconds < 10) {
+ timeStringBuilder.append('0');
+ }
+ timeStringBuilder.append(remainderCentiSeconds);
+ }
+
+ return timeStringBuilder.toString();
+ }
+
+ /**
+ * Load the thumbnail of an image from an {@link InputStream}.
+ *
+ * @param stream The input stream of the image.
+ * @param imageWidth Image width.
+ * @param imageHeight Image height.
+ * @param widthBound The bound of the width of the decoded image.
+ * @param heightBound The bound of the height of the decoded image.
+ * @param orientation The orientation of the image. The image will be rotated
+ * clockwise in degrees.
+ * @param maximumPixels The bound for the number of pixels of the decoded image.
+ * @return {@code null} if the decoding failed.
+ */
+ public static Bitmap loadImageThumbnailFromStream(InputStream stream, int imageWidth,
+ int imageHeight, int widthBound,
+ int heightBound, int orientation,
+ int maximumPixels) {
+ /** 32K buffer. */
+ byte[] decodeBuffer = new byte[32 * 1024];
+
+ if (orientation % 180 != 0) {
+ int dummy = imageHeight;
+ imageHeight = imageWidth;
+ imageWidth = dummy;
+ }
+
+ // Generate Bitmap of maximum size that fits into widthBound x heightBound.
+ // Algorithm: start with full size and step down in powers of 2.
+ int targetWidth = imageWidth;
+ int targetHeight = imageHeight;
+ int sampleSize = 1;
+ while (targetHeight > heightBound || targetWidth > widthBound ||
+ targetHeight > GL11.GL_MAX_TEXTURE_SIZE || targetWidth > GL11.GL_MAX_TEXTURE_SIZE ||
+ targetHeight * targetWidth > maximumPixels) {
+ sampleSize <<= 1;
+ targetWidth = imageWidth / sampleSize;
+ targetHeight = imageWidth / sampleSize;
+ }
+
+ // For large (> MAXIMUM_TEXTURE_SIZE) high aspect ratio (panorama)
+ // Bitmap requests:
+ // Step 1: ask for double size.
+ // Step 2: scale maximum edge down to MAXIMUM_TEXTURE_SIZE.
+ //
+ // Here's the step 1: double size.
+ if ((heightBound > GL11.GL_MAX_TEXTURE_SIZE || widthBound > GL11.GL_MAX_TEXTURE_SIZE) &&
+ targetWidth * targetHeight < maximumPixels / 4 && sampleSize > 1) {
+ sampleSize >>= 2;
+ }
+
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inSampleSize = sampleSize;
+ opts.inTempStorage = decodeBuffer;
+ Bitmap b = BitmapFactory.decodeStream(stream, null, opts);
+
+ if (b == null) {
+ return null;
+ }
+
+ // Step 2: scale maximum edge down to maximum texture size.
+ // If Bitmap maximum edge > MAXIMUM_TEXTURE_SIZE, which can happen for panoramas,
+ // scale to fit in MAXIMUM_TEXTURE_SIZE.
+ if (b.getWidth() > GL11.GL_MAX_TEXTURE_SIZE || b.getHeight() > GL11.GL_MAX_TEXTURE_SIZE) {
+ int maxEdge = Math.max(b.getWidth(), b.getHeight());
+ b = Bitmap.createScaledBitmap(b, b.getWidth() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge,
+ b.getHeight() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge,
+ false);
+ }
+
+ // Not called often because most modes save image data non-rotated.
+ if (orientation != 0 && b != null) {
+ Matrix m = new Matrix();
+ m.setRotate(orientation);
+ b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false);
+ }
+
+ return b;
+ }
+
+ public static Optional generateThumbnail(File path, int boundingWidthPx,
+ int boundingHeightPx) {
+ final Bitmap bitmap;
+
+ /*if (getAttributes().isRendering()) {
+ return Storage.getPlaceholderForSession(data.getUri());
+ } else {*/
+
+ FileInputStream stream;
+
+ try {
+ stream = new FileInputStream(path);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "### File not found ###:" + path.getPath());
+ return Optional.empty();
+ }
+ int width = 1280;
+ int height = 720; //.getDimensions().getHeight();
+ int orientation = 0;
+
+ Point dim = resizeToFill(width, height, orientation, boundingWidthPx, boundingHeightPx);
+
+ // If the orientation is not vertical
+ if (orientation % 180 != 0) {
+ int dummy = dim.x;
+ dim.x = dim.y;
+ dim.y = dummy;
+ }
+
+ bitmap = loadImageThumbnailFromStream(stream, width, height, (int)(dim.x * 0.7f),
+ (int)(dim.y * 0.7), 0, MAX_PEEK_BITMAP_PIXELS);
+
+ return Optional.ofNullable(bitmap);
+ //}
+ }
+
+ /**
+ * Calculates a new dimension to fill the bound with the original aspect
+ * ratio preserved.
+ *
+ * @param imageWidth The original width.
+ * @param imageHeight The original height.
+ * @param imageRotation The clockwise rotation in degrees of the image which
+ * the original dimension comes from.
+ * @param boundWidth The width of the bound.
+ * @param boundHeight The height of the bound.
+ * @returns The final width/height stored in Point.x/Point.y to fill the
+ * bounds and preserve image aspect ratio.
+ */
+ public static Point resizeToFill(int imageWidth, int imageHeight, int imageRotation,
+ int boundWidth, int boundHeight) {
+ if (imageRotation % 180 != 0) {
+ // Swap width and height.
+ int savedWidth = imageWidth;
+ imageWidth = imageHeight;
+ imageHeight = savedWidth;
+ }
+
+ Point p = new Point();
+ p.x = boundWidth;
+ p.y = boundHeight;
+
+ // In some cases like automated testing, image height/width may not be
+ // loaded, to avoid divide by zero fall back to provided bounds.
+ if (imageWidth != 0 && imageHeight != 0) {
+ if (imageWidth * boundHeight > boundWidth * imageHeight) {
+ p.y = imageHeight * p.x / imageWidth;
+ } else {
+ p.x = imageWidth * p.y / imageHeight;
+ }
+ } else {
+ Log.w(TAG, "zero width/height, falling back to bounds (w|h|bw|bh):" + imageWidth + "|" +
+ imageHeight + "|" + boundWidth + "|" + boundHeight);
+ }
+
+ return p;
+ }
+
+ /**
+ * Rotates and/or mirrors the bitmap. If a new bitmap is created, the
+ * original bitmap is recycled.
+ */
+ public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) {
+ if ((degrees != 0 || mirror) && b != null) {
+ Matrix m = new Matrix();
+ // Mirror first.
+ // horizontal flip + rotation = -rotation + horizontal flip
+ if (mirror) {
+ m.postScale(-1, 1);
+ degrees = (degrees + 360) % 360;
+ if (degrees == 0 || degrees == 180) {
+ m.postTranslate(b.getWidth(), 0);
+ } else if (degrees == 90 || degrees == 270) {
+ m.postTranslate(b.getHeight(), 0);
+ } else {
+ throw new IllegalArgumentException("Invalid degrees=" + degrees);
+ }
+ }
+ if (degrees != 0) {
+ // clockwise
+ m.postRotate(degrees, (float)b.getWidth() / 2, (float)b.getHeight() / 2);
+ }
+
+ try {
+ Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true);
+ if (b != b2) {
+ b.recycle();
+ b = b2;
+ }
+ } catch (OutOfMemoryError ex) {
+ // We have no memory to rotate. Return the original bitmap.
+ }
+ }
+ return b;
+ }
+
+ public static Optional getVideoThumbnail(ContentResolver mContentResolver, Uri uri) {
+ Bitmap bitmap = null;
+ ParcelFileDescriptor mVideoFileDescriptor;
+
+ try {
+ mVideoFileDescriptor = mContentResolver.openFileDescriptor(uri, "r");
+ bitmap = Thumbnail.createVideoThumbnailBitmap(mVideoFileDescriptor.getFileDescriptor(),
+ 720);
+ } catch (java.io.FileNotFoundException ex) {
+ // invalid uri
+ Log.e(TAG, ex.toString());
+ }
+
+ if (bitmap != null) {
+ // MetadataRetriever already rotates the thumbnail. We should rotate
+ // it to match the UI orientation (and mirror if it is front-facing camera).
+ bitmap = rotateAndMirror(bitmap, 0, false);
+ }
+ return Optional.ofNullable(bitmap);
+ }
+
+ public static Intent getVideoPlayerIntent(Uri uri) {
+ return new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "video/*");
+ }
+
+ public static void playVideo(Activity activity, Uri uri, String title) {
+ try {
+ Intent intent = getVideoPlayerIntent(uri)
+ .putExtra(Intent.EXTRA_TITLE, title)
+ .putExtra(KEY_TREAT_UP_AS_BACK, true);
+ activity.startActivity(intent);
+
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "cant play video");
+ }
+ }
+
+ public static String getRealPathFromURI(Context context, Uri contentUri) {
+ Cursor cursor = null;
+ int column_index;
+ try {
+ String[] proj = {MediaStore.Images.Media.DATA, MediaStore.Video.Media.DATA};
+ cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
+
+ if (getMimeTypeFromURI(context, contentUri).compareTo("video/mp4") == 0) {
+ column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
+ cursor.moveToFirst();
+
+ } else {
+ column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ cursor.moveToFirst();
+ }
+
+ return cursor.getString(column_index);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ public static String getMimeTypeFromURI(Context context, Uri uri) {
+ ContentResolver cR = context.getContentResolver();
+ String type = cR.getType(uri);
+ return type;
+ }
}
diff --git a/camera/MultiCameraApplication/res/drawable-v24/ic_launcher_foreground.xml b/camera/MultiCameraApplication/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 1f6bb29..0000000
--- a/camera/MultiCameraApplication/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/camera/MultiCameraApplication/res/drawable/bg_text_on_preview.xml b/camera/MultiCameraApplication/res/drawable/bg_text_on_preview.xml
new file mode 100644
index 0000000..cdc2b04
--- /dev/null
+++ b/camera/MultiCameraApplication/res/drawable/bg_text_on_preview.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/drawable/ic_back_normal.png b/camera/MultiCameraApplication/res/drawable/ic_back_normal.png
new file mode 100644
index 0000000..d326323
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_back_normal.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_capture_camera_disabled.png b/camera/MultiCameraApplication/res/drawable/ic_capture_camera_disabled.png
new file mode 100644
index 0000000..af6833f
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_capture_camera_disabled.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_capture_camera_normal.png b/camera/MultiCameraApplication/res/drawable/ic_capture_camera_normal.png
new file mode 100644
index 0000000..21bd151
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_capture_camera_normal.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_capture_video.png b/camera/MultiCameraApplication/res/drawable/ic_capture_video.png
new file mode 100644
index 0000000..6dba337
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_capture_video.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_capture_video_disabled.png b/camera/MultiCameraApplication/res/drawable/ic_capture_video_disabled.png
new file mode 100644
index 0000000..299c01c
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_capture_video_disabled.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_confirm.png b/camera/MultiCameraApplication/res/drawable/ic_confirm.png
new file mode 100644
index 0000000..6894bd2
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_confirm.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_control_play.png b/camera/MultiCameraApplication/res/drawable/ic_control_play.png
new file mode 100644
index 0000000..2de5b4f
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_control_play.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_exitscreeen.png b/camera/MultiCameraApplication/res/drawable/ic_exitscreeen.png
new file mode 100644
index 0000000..cbbdca5
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_exitscreeen.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_full_screen.png b/camera/MultiCameraApplication/res/drawable/ic_full_screen.png
new file mode 100644
index 0000000..8cff8ff
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_full_screen.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_launcher_foreground.xml b/camera/MultiCameraApplication/res/drawable/ic_launcher_foreground.xml
deleted file mode 100644
index f8e8dca..0000000
--- a/camera/MultiCameraApplication/res/drawable/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
diff --git a/camera/MultiCameraApplication/res/drawable/ic_menu_cancel_holo_light.png b/camera/MultiCameraApplication/res/drawable/ic_menu_cancel_holo_light.png
new file mode 100644
index 0000000..335deaa
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_menu_cancel_holo_light.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_menu_trash.xml b/camera/MultiCameraApplication/res/drawable/ic_menu_trash.xml
new file mode 100644
index 0000000..cb94342
--- /dev/null
+++ b/camera/MultiCameraApplication/res/drawable/ic_menu_trash.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/drawable/ic_record.png b/camera/MultiCameraApplication/res/drawable/ic_record.png
new file mode 100644
index 0000000..a36626a
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_record.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_recording_indicator.png b/camera/MultiCameraApplication/res/drawable/ic_recording_indicator.png
new file mode 100755
index 0000000..aa8781d
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_recording_indicator.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_settings_black_24dp.xml b/camera/MultiCameraApplication/res/drawable/ic_settings_black_24dp.xml
index 7f2f06c..314de0f 100644
--- a/camera/MultiCameraApplication/res/drawable/ic_settings_black_24dp.xml
+++ b/camera/MultiCameraApplication/res/drawable/ic_settings_black_24dp.xml
@@ -1,5 +1,5 @@
+ android:width="35dp" xmlns:android="http://schemas.android.com/apk/res/android">
diff --git a/camera/MultiCameraApplication/res/drawable/ic_settings_normal.png b/camera/MultiCameraApplication/res/drawable/ic_settings_normal.png
new file mode 100644
index 0000000..61f70b4
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_settings_normal.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_settings_normal_disabled.png b/camera/MultiCameraApplication/res/drawable/ic_settings_normal_disabled.png
new file mode 100644
index 0000000..aff3b03
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_settings_normal_disabled.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_stop_normal.png b/camera/MultiCameraApplication/res/drawable/ic_stop_normal.png
new file mode 100644
index 0000000..299aca3
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_stop_normal.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_trash_disabled.png b/camera/MultiCameraApplication/res/drawable/ic_trash_disabled.png
new file mode 100644
index 0000000..1f1a215
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_trash_disabled.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/ic_trash_normal.png b/camera/MultiCameraApplication/res/drawable/ic_trash_normal.png
new file mode 100644
index 0000000..e0a9ff6
Binary files /dev/null and b/camera/MultiCameraApplication/res/drawable/ic_trash_normal.png differ
diff --git a/camera/MultiCameraApplication/res/drawable/photo_selector.xml b/camera/MultiCameraApplication/res/drawable/photo_selector.xml
new file mode 100644
index 0000000..80ece7d
--- /dev/null
+++ b/camera/MultiCameraApplication/res/drawable/photo_selector.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/drawable/transparent_button_background.xml b/camera/MultiCameraApplication/res/drawable/transparent_button_background.xml
new file mode 100644
index 0000000..fa35789
--- /dev/null
+++ b/camera/MultiCameraApplication/res/drawable/transparent_button_background.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/drawable/video_selector.xml b/camera/MultiCameraApplication/res/drawable/video_selector.xml
new file mode 100644
index 0000000..4daeb16
--- /dev/null
+++ b/camera/MultiCameraApplication/res/drawable/video_selector.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/layout/activity_itscameraintents.xml b/camera/MultiCameraApplication/res/layout/activity_itscameraintents.xml
new file mode 100644
index 0000000..3389cdc
--- /dev/null
+++ b/camera/MultiCameraApplication/res/layout/activity_itscameraintents.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/layout/activity_main.xml b/camera/MultiCameraApplication/res/layout/activity_multiview.xml
similarity index 61%
rename from camera/MultiCameraApplication/res/layout/activity_main.xml
rename to camera/MultiCameraApplication/res/layout/activity_multiview.xml
index 33bb882..7651273 100644
--- a/camera/MultiCameraApplication/res/layout/activity_main.xml
+++ b/camera/MultiCameraApplication/res/layout/activity_multiview.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".MultiViewActivity">
-
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/camera/MultiCameraApplication/res/layout/botmleftcam.xml b/camera/MultiCameraApplication/res/layout/botmleftcam.xml
new file mode 100644
index 0000000..d89271d
--- /dev/null
+++ b/camera/MultiCameraApplication/res/layout/botmleftcam.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/layout/botmrightcam.xml b/camera/MultiCameraApplication/res/layout/botmrightcam.xml
new file mode 100644
index 0000000..8b4a7bc
--- /dev/null
+++ b/camera/MultiCameraApplication/res/layout/botmrightcam.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/layout/content_main.xml b/camera/MultiCameraApplication/res/layout/content_main.xml
index f11fad7..b4c895a 100644
--- a/camera/MultiCameraApplication/res/layout/content_main.xml
+++ b/camera/MultiCameraApplication/res/layout/content_main.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
- tools:context=".MainActivity"
+ tools:context=".MultiViewActivity"
tools:showIn="@layout/activity_main">
+ android:baselineAligned="false"
+ android:orientation="horizontal">
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:baselineAligned="false"
+ android:orientation="horizontal">
-
-
-
+
-
+
-
-
-
diff --git a/camera/MultiCameraApplication/res/layout/intentpreview.xml b/camera/MultiCameraApplication/res/layout/intentpreview.xml
new file mode 100644
index 0000000..21d0a5f
--- /dev/null
+++ b/camera/MultiCameraApplication/res/layout/intentpreview.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/layout/permissions.xml b/camera/MultiCameraApplication/res/layout/permissions.xml
index eec475b..46034e0 100644
--- a/camera/MultiCameraApplication/res/layout/permissions.xml
+++ b/camera/MultiCameraApplication/res/layout/permissions.xml
@@ -1,5 +1,5 @@
-
+ #fff
+ #00000000
+ #e7e7e7
+ #ffffffff
+ #4c000000
+ #00000000
+ #26000000
+ #99000000
+
+ #4285f4
+ #db4437
+ #0f9d58
+ #ab47bc
+ #ff9e00
+ #00acc1
+
+ #262626
+ #4C000000
+
+ #1b1b1b
+
+ #4c000000
+
+ #33FFFFFF
+ #4CFFFFFF
+ @color/main_color_global
+ #FF76A7F9
+ @android:color/black
+
+ #2962FF
+
+ #2DFFFFFF
+
+ #00838F
diff --git a/camera/MultiCameraApplication/res/values/dimens.xml b/camera/MultiCameraApplication/res/values/dimens.xml
index 59a0b0c..975b3c0 100644
--- a/camera/MultiCameraApplication/res/values/dimens.xml
+++ b/camera/MultiCameraApplication/res/values/dimens.xml
@@ -1,3 +1,18 @@
16dp
+
+ 56dp
+ 48dp
+ 60dp
+
+ 12dp
+ 48dp
+ 24dp
+ 54dp
+ 40dp
+ 70dp
+ 5dp
+ 1dp
+
+ 48dp
diff --git a/camera/MultiCameraApplication/res/values/ic_launcher_background.xml b/camera/MultiCameraApplication/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..09a756b
--- /dev/null
+++ b/camera/MultiCameraApplication/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #26A69A
+
\ No newline at end of file
diff --git a/camera/MultiCameraApplication/res/values/strings.xml b/camera/MultiCameraApplication/res/values/strings.xml
index b97c7ef..476d7c0 100644
--- a/camera/MultiCameraApplication/res/values/strings.xml
+++ b/camera/MultiCameraApplication/res/values/strings.xml
@@ -47,10 +47,10 @@
Capture ResolutionVideo Quality
- %1$dx%2$d
+ %1$dx%2$d
- Multi-USB Cameras
+ USB CamerasOne
@@ -64,9 +64,38 @@
Camera error
- The app does not have critical permissions needed to run. Please check your permissions settings.
+ The app does not have critical permissions needed to run.
+ Please check your permissions settings.
+ Dismiss
+
+ READ ME
+
+ 1. Use ItsCameraIntentsTest OPTION for testing CAMERA INTENTS \n\n
+ 2. For MULTI CAMERA VIEW select 2nd option \n
+
+
+ CAMERA INTENTS TEST
+ MULTI CAMERA VIEW
+
+
+ Video recording has started.
+
+ Video recording has stopped.
+
+
+ Play Video
+
+
+ Can\'t play video.
+
+
+ Delete
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/values/styles.xml b/camera/MultiCameraApplication/res/values/styles.xml
index 96a6f8c..36a0645 100644
--- a/camera/MultiCameraApplication/res/values/styles.xml
+++ b/camera/MultiCameraApplication/res/values/styles.xml
@@ -10,12 +10,36 @@
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/xml/root_preferences.xml b/camera/MultiCameraApplication/res/xml/root_preferences.xml
index 72a8bf5..7df1c1d 100644
--- a/camera/MultiCameraApplication/res/xml/root_preferences.xml
+++ b/camera/MultiCameraApplication/res/xml/root_preferences.xml
@@ -1,17 +1,17 @@
@@ -41,17 +41,4 @@
-
-
-
-
-
diff --git a/camera/MultiCameraApplication/res/xml/root_preferences_1.xml b/camera/MultiCameraApplication/res/xml/root_preferences_1.xml
new file mode 100644
index 0000000..76240f7
--- /dev/null
+++ b/camera/MultiCameraApplication/res/xml/root_preferences_1.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/xml/root_preferences_2.xml b/camera/MultiCameraApplication/res/xml/root_preferences_2.xml
new file mode 100644
index 0000000..474bb64
--- /dev/null
+++ b/camera/MultiCameraApplication/res/xml/root_preferences_2.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/res/xml/root_preferences_3.xml b/camera/MultiCameraApplication/res/xml/root_preferences_3.xml
new file mode 100644
index 0000000..24988bd
--- /dev/null
+++ b/camera/MultiCameraApplication/res/xml/root_preferences_3.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/camera/MultiCameraApplication/java/com/intel/multicamera/GlobalVariable.java b/camera/MultiCameraApplication/res/xml/settings.xml
similarity index 50%
rename from camera/MultiCameraApplication/java/com/intel/multicamera/GlobalVariable.java
rename to camera/MultiCameraApplication/res/xml/settings.xml
index e6e5415..3428df0 100644
--- a/camera/MultiCameraApplication/java/com/intel/multicamera/GlobalVariable.java
+++ b/camera/MultiCameraApplication/res/xml/settings.xml
@@ -1,4 +1,4 @@
-/*
+
+
+
+
+
+
+
+
+
+
+
+
-package com.intel.multicamera;
-import android.util.Size;
-import java.util.List;
-public class GlobalVariable {
- public static String message;
- public static int numOfCameras;
- public static List SupportedSizes;
- public static String camerId;
-}