Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improved cameraview #361

Merged
merged 5 commits into from
Feb 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.3.0'
ext.kotlin_version = '1.3.20'
repositories {
google()
jcenter()
Expand Down Expand Up @@ -91,8 +91,9 @@ android {
}
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
renderscriptTargetApi 16
renderscriptSupportModeEnabled true

// renderscriptTargetApi 16
// renderscriptSupportModeEnabled true

ndk {
abiFilters "armeabi", "armeabi-v7a", "x86"
Expand Down Expand Up @@ -149,15 +150,14 @@ dependencies {
implementation 'me.angrybyte.picker:picker:1.3.1'
implementation 'com.github.stfalcon:frescoimageviewer:0.5.0'
implementation 'com.facebook.fresco:fresco:1.10.0'
// implementation 'com.github.derlio.waveform:library:1.0.3@aar'
implementation 'com.github.derlio:audio-waveform:v1.0.1'
implementation 'org.firezenk:audiowaves:1.1@aar'
implementation 'com.maxproj.simplewaveform:app:1.0.0'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.4'
implementation('com.mikepenz:aboutlibraries:6.1.1@aar') {
transitive = true
}
implementation 'com.asksira.android:cameraviewplus:0.9.5'

implementation 'com.github.halilozercan:BetterVideoPlayer:1.1.0'
implementation 'io.github.silvaren:easyrs:0.5.3'
implementation 'org.jcodec:jcodec:0.2.3'
Expand All @@ -180,4 +180,7 @@ dependencies {

// android-job
implementation 'com.evernote:android-job:1.2.6'

// new camera view: https://github.com/natario1/CameraView
implementation 'com.otaliastudios:cameraview:2.0.0-beta02'
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
import android.util.Log;
import android.view.Surface;

import com.google.android.cameraview.CameraView;
import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.Facing;
import com.otaliastudios.cameraview.Frame;
import com.otaliastudios.cameraview.FrameProcessor;
import com.otaliastudios.cameraview.Size;

import org.havenapp.main.PreferenceManager;
import org.havenapp.main.Utils;
Expand All @@ -46,7 +50,7 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import androidx.renderscript.RenderScript;
import androidx.annotation.NonNull;

import io.github.silvaren.easyrs.tools.Nv21Image;

Expand Down Expand Up @@ -102,7 +106,7 @@ public class CameraViewHolder {
private File videoFile;

//for managing bitmap processing
private RenderScript renderScript;
//private RenderScript renderScript;

private ServiceConnection mConnection = new ServiceConnection() {

Expand All @@ -123,12 +127,11 @@ public CameraViewHolder(Activity context, CameraView cameraView) {
//super(context);
this.context = context;
this.cameraView = cameraView;
this.renderScript = RenderScript.create(context); // where context can be your activity, application, etc.
//this.renderScript = RenderScript.create(context); // where context can be your activity, application, etc.

prefs = new PreferenceManager(context);

task = new MotionDetector(
renderScript,
updateHandler,
motionSensitivity);

Expand Down Expand Up @@ -202,28 +205,37 @@ public void addListener(MotionDetector.MotionListener listener) {
* (preferred is 640x480)
* in order to minimize CPU usage
*/
public synchronized void startCamera() {
public void startCamera() {


updateCamera();

cameraView.start();
cameraView.open();

cameraView.setOnFrameListener((data, width, height, rotationDegrees) -> {
cameraView.addFrameProcessor(new FrameProcessor() {
@Override
public void process(@NonNull Frame frame) {

long now = System.currentTimeMillis();
if (now < CameraViewHolder.this.lastTimestamp + PREVIEW_INTERVAL)
return;
long now = System.currentTimeMillis();
if (now < CameraViewHolder.this.lastTimestamp + PREVIEW_INTERVAL)
return;

CameraViewHolder.this.lastTimestamp = now;
CameraViewHolder.this.lastTimestamp = now;

if (!doingVideoProcessing) {
if (frame.getData() != null && frame.getSize() != null) {

Log.i("CameraViewHolder", "Processing new image");
byte[] data = frame.getData();
Size size = frame.getSize();
int width = size.getWidth();
int height = size.getHeight();
int rot = getCorrectCameraOrientation(cameraView.getFacing(),frame.getRotation());

mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rotationDegrees));
} else {
mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rotationDegrees));
if (!doingVideoProcessing) {
mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rot));
} else {
mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rot));
}
}
}
});

Expand All @@ -234,12 +246,10 @@ public void updateCamera ()
{
switch (prefs.getCamera()) {
case PreferenceManager.FRONT:
if (cameraView.getFacing() != CameraView.FACING_FRONT)
cameraView.setFacing(CameraView.FACING_FRONT);
cameraView.setFacing(Facing.FRONT);
break;
case PreferenceManager.BACK:
if (cameraView.getFacing() != CameraView.FACING_BACK)
cameraView.setFacing(CameraView.FACING_BACK);
cameraView.setFacing(Facing.BACK);
break;
default:
// camera = null;
Expand Down Expand Up @@ -275,7 +285,8 @@ public void updateCamera ()
private void recordNewFrame (byte[] data, int width, int height, int rotationDegrees)
{

Bitmap bitmap = Nv21Image.nv21ToBitmap(renderScript, data, width, height);
Bitmap bitmap = MotionDetector.convertImage(data, width, height);
//Nv21Image.nv21ToBitmap(renderScript, data, width, height);

bitmap = Bitmap.createBitmap(bitmap,0,0,width,height,mtxVideoRotate,true);

Expand Down Expand Up @@ -321,8 +332,8 @@ private synchronized void processNewFrame (byte[] data, int width, int height, i
data,
width,
height,
cameraView.getDefaultOrientation(),
cameraView.getFacing());
rotationDegrees,
cameraView.getFacing()==Facing.FRONT);

lastPic = data;

Expand All @@ -349,12 +360,12 @@ private synchronized boolean recordVideo() {

mtxVideoRotate = new Matrix();

if (cameraView.getFacing() == CameraView.FACING_FRONT) {
mtxVideoRotate.postRotate(-cameraView.getDefaultOrientation());
if (cameraView.getFacing() == Facing.FRONT) {
mtxVideoRotate.postRotate(-cameraView.getRotation());
mtxVideoRotate.postScale(-1, 1, cameraView.getWidth() / 2, cameraView.getHeight() / 2);
}
else
mtxVideoRotate.postRotate(cameraView.getDefaultOrientation());
mtxVideoRotate.postRotate(cameraView.getRotation());

doingVideoProcessing = true;

Expand All @@ -374,13 +385,10 @@ private synchronized boolean recordVideo() {
public synchronized void stopCamera ()
{
if (cameraView != null) {
cameraView.stop();
cameraView.close();
}
}

public int getCameraFacing() {
return cameraView.getFacing();
}

public void destroy ()
{
Expand All @@ -391,7 +399,7 @@ public void destroy ()
stopCamera();
}

public int getCorrectCameraOrientation(int facing, int orientation) {
public int getCorrectCameraOrientation(Facing facing, int orientation) {

int rotation = context.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
Expand All @@ -416,7 +424,7 @@ public int getCorrectCameraOrientation(int facing, int orientation) {
}

int result;
if(facing == CameraView.FACING_FRONT){
if(facing == Facing.FRONT){
result = (orientation + degrees) % 360;
result = (360 - result) % 360;
}else{
Expand Down
31 changes: 22 additions & 9 deletions src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.os.Handler;

import com.google.android.cameraview.CameraView;

import org.havenapp.main.sensors.media.ImageCodec;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import androidx.renderscript.RenderScript;
import io.github.silvaren.easyrs.tools.Nv21Image;

/**
* Task doing all image processing in backgrounds,
Expand All @@ -42,7 +44,7 @@ public class MotionDetector {

private IMotionDetector detector;

private RenderScript renderScript;
//private RenderScript renderScript;

private int detectColor = Color.YELLOW;

Expand All @@ -58,10 +60,10 @@ public void addListener(MotionListener listener) {
}

public MotionDetector(
RenderScript renderScript,

Handler updateHandler,
int motionSensitivity) {
this.renderScript = renderScript;
// this.renderScript = renderScript;
this.handler = updateHandler;
this.motionSensitivity = motionSensitivity;
detector = new LuminanceMotionDetector();
Expand All @@ -84,7 +86,7 @@ public void detect(byte[] rawOldPic,
int width,
int height,
int rotationDegrees,
int cameraFacing) {
boolean facingFront) {

int[] newPicLuma = ImageCodec.N21toLuma(rawNewPic, width, height);
if (rawOldPic != null) {
Expand Down Expand Up @@ -118,7 +120,7 @@ public void detect(byte[] rawOldPic,

Matrix mtx = new Matrix();

if (cameraFacing == CameraView.FACING_FRONT) {
if (facingFront) {
mtx.postRotate(-rotationDegrees);
mtx.postScale(-1, 1, width / 2, height / 2);
}
Expand All @@ -129,7 +131,8 @@ public void detect(byte[] rawOldPic,
Bitmap newBitmap
= Bitmap.createBitmap(Bitmap.createBitmap(newPic, width, height, Bitmap.Config.ARGB_4444), 0, 0, width, height, mtx, true);

Bitmap rawBitmap = Bitmap.createBitmap(Nv21Image.nv21ToBitmap(renderScript, rawNewPic, width, height),0,0,width,height,mtx,true);
Bitmap rawBitmap = convertImage(rawNewPic,width,height);
//Bitmap.createBitmap(Nv21Image.nv21ToBitmap(renderScript, rawNewPic, width, height),0,0,width,height,mtx,true);

handler.post(() -> {
for (MotionListener listener : listeners) {
Expand Down Expand Up @@ -162,5 +165,15 @@ public void detect(byte[] rawOldPic,

}

public static Bitmap convertImage (byte[] nv21bytearray, int width, int height)
{
YuvImage yuvImage = new YuvImage(nv21bytearray, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, os);
byte[] jpegByteArray = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
return bitmap;
}


}
26 changes: 15 additions & 11 deletions src/main/java/org/havenapp/main/service/MonitorService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@


import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
Expand All @@ -26,6 +24,7 @@
import android.telephony.SmsManager;
import android.text.TextUtils;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import org.havenapp.main.HavenApp;
Expand Down Expand Up @@ -57,8 +56,6 @@ public class MonitorService extends Service {
/**
* To show a notification on service start
*/
private NotificationManager manager;
private NotificationChannel mChannel;
private final static String channelId = "monitor_id";
private final static CharSequence channelName = "Haven notifications";
private final static String channelDescription= "Important messages from Haven";
Expand Down Expand Up @@ -129,16 +126,10 @@ public void onCreate() {

mApp = (HavenApp)getApplication();

manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
mPrefs = new PreferenceManager(this);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mChannel = new NotificationChannel(channelId, channelName,
NotificationManager.IMPORTANCE_HIGH);
mChannel.setDescription(channelDescription);
mChannel.setLightColor(Color.RED);
mChannel.setImportance(NotificationManager.IMPORTANCE_MIN);
manager.createNotificationChannel(mChannel);
setupNotificationChannel();
}

startSensors();
Expand All @@ -153,6 +144,19 @@ public void onCreate() {
wakeLock.acquire();
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void setupNotificationChannel ()
{
android.app.NotificationManager manager = (android.app.NotificationManager)getSystemService(NOTIFICATION_SERVICE);
android.app.NotificationChannel channel;
channel = new android.app.NotificationChannel(channelId, channelName,
android.app.NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(channelDescription);
channel.setLightColor(Color.RED);
channel.setImportance(android.app.NotificationManager.IMPORTANCE_MIN);
manager.createNotificationChannel(channel);
}

public static MonitorService getInstance ()
{
return sInstance;
Expand Down
Loading