/*
* Copyright (C) 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.novoda.magicmirror.facerecognition;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import com.novoda.notils.logger.simple.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.CameraSource;
import java.io.IOException;
public class CameraSourcePreview extends ViewGroup {
private static final int DEFAULT_PREVIEW_WIDTH = 320;
private static final int DEFAULT_PREVIEW_HEIGHT = 240;
private Context context;
private boolean startRequested;
private boolean surfaceAvailable;
private CameraSource cameraSource;
private final SurfaceView surfaceView;
public CameraSourcePreview(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
startRequested = false;
surfaceAvailable = false;
surfaceView = new SurfaceView(context);
surfaceView.getHolder().addCallback(new SurfaceCallback());
addView(surfaceView);
}
public void start(CameraSource cameraSource) throws IOException {
if (cameraSource == null) {
stop();
return;
}
this.cameraSource = cameraSource;
startRequested = true;
startIfReady();
}
public void stop() {
if (cameraSource != null) {
cameraSource.stop();
}
}
private void startIfReady() throws IOException {
if (startRequested && surfaceAvailable) {
cameraSource.start(surfaceView.getHolder());
startRequested = false;
}
}
private class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder surface) {
surfaceAvailable = true;
try {
startIfReady();
} catch (IOException e) {
Log.e("Could not start camera source.", e);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surface) {
surfaceAvailable = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int width = DEFAULT_PREVIEW_WIDTH;
int height = DEFAULT_PREVIEW_HEIGHT;
if (cameraSource != null) {
Size size = cameraSource.getPreviewSize();
if (size != null) {
width = size.getWidth();
height = size.getHeight();
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode()) {
int tmp = width;
width = height;
height = tmp;
}
final int layoutWidth = right - left;
final int layoutHeight = bottom - top;
// Computes height and width for potentially doing fit width.
int childWidth = layoutWidth;
int childHeight = (int)(((float) layoutWidth / (float) width) * height);
// If height is too tall using fit width, does fit height instead.
if (childHeight > layoutHeight) {
childHeight = layoutHeight;
childWidth = (int)(((float) layoutHeight / (float) height) * width);
}
for (int i = 0; i < getChildCount(); ++i) {
getChildAt(i).layout(0, 0, childWidth, childHeight);
}
try {
startIfReady();
} catch (IOException e) {
Log.e("Could not start camera source.", e);
}
}
private boolean isPortraitMode() {
int orientation = context.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
return true;
}
Log.d("isPortraitMode returning false by default");
return false;
}
}