Skip to content

Commit 2be8c80

Browse files
authored
Merge pull request #361 from guardianproject/dev_new_cameraview
improved cameraview
2 parents a51704c + 4aa51f7 commit 2be8c80

6 files changed

Lines changed: 114 additions & 71 deletions

File tree

build.gradle

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.3.0'
2+
ext.kotlin_version = '1.3.20'
33
repositories {
44
google()
55
jcenter()
@@ -91,8 +91,9 @@ android {
9191
}
9292
multiDexEnabled true
9393
vectorDrawables.useSupportLibrary = true
94-
renderscriptTargetApi 16
95-
renderscriptSupportModeEnabled true
94+
95+
// renderscriptTargetApi 16
96+
// renderscriptSupportModeEnabled true
9697

9798
ndk {
9899
abiFilters "armeabi", "armeabi-v7a", "x86"
@@ -149,15 +150,14 @@ dependencies {
149150
implementation 'me.angrybyte.picker:picker:1.3.1'
150151
implementation 'com.github.stfalcon:frescoimageviewer:0.5.0'
151152
implementation 'com.facebook.fresco:fresco:1.10.0'
152-
// implementation 'com.github.derlio.waveform:library:1.0.3@aar'
153153
implementation 'com.github.derlio:audio-waveform:v1.0.1'
154154
implementation 'org.firezenk:audiowaves:1.1@aar'
155155
implementation 'com.maxproj.simplewaveform:app:1.0.0'
156156
implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.4'
157157
implementation('com.mikepenz:aboutlibraries:6.1.1@aar') {
158158
transitive = true
159159
}
160-
implementation 'com.asksira.android:cameraviewplus:0.9.5'
160+
161161
implementation 'com.github.halilozercan:BetterVideoPlayer:1.1.0'
162162
implementation 'io.github.silvaren:easyrs:0.5.3'
163163
implementation 'org.jcodec:jcodec:0.2.3'
@@ -180,4 +180,7 @@ dependencies {
180180

181181
// android-job
182182
implementation 'com.evernote:android-job:1.2.6'
183+
184+
// new camera view: https://github.com/natario1/CameraView
185+
implementation 'com.otaliastudios:cameraview:2.0.0-beta02'
183186
}

src/main/java/org/havenapp/main/sensors/motion/CameraViewHolder.java

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
import android.util.Log;
2626
import android.view.Surface;
2727

28-
import com.google.android.cameraview.CameraView;
28+
import com.otaliastudios.cameraview.CameraView;
29+
import com.otaliastudios.cameraview.Facing;
30+
import com.otaliastudios.cameraview.Frame;
31+
import com.otaliastudios.cameraview.FrameProcessor;
32+
import com.otaliastudios.cameraview.Size;
2933

3034
import org.havenapp.main.PreferenceManager;
3135
import org.havenapp.main.Utils;
@@ -46,7 +50,7 @@
4650
import java.util.concurrent.ThreadPoolExecutor;
4751
import java.util.concurrent.TimeUnit;
4852

49-
import androidx.renderscript.RenderScript;
53+
import androidx.annotation.NonNull;
5054

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

@@ -102,7 +106,7 @@ public class CameraViewHolder {
102106
private File videoFile;
103107

104108
//for managing bitmap processing
105-
private RenderScript renderScript;
109+
//private RenderScript renderScript;
106110

107111
private ServiceConnection mConnection = new ServiceConnection() {
108112

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

128132
prefs = new PreferenceManager(context);
129133

130134
task = new MotionDetector(
131-
renderScript,
132135
updateHandler,
133136
motionSensitivity);
134137

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

207210

208211
updateCamera();
209212

210-
cameraView.start();
213+
cameraView.open();
211214

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

214-
long now = System.currentTimeMillis();
215-
if (now < CameraViewHolder.this.lastTimestamp + PREVIEW_INTERVAL)
216-
return;
219+
long now = System.currentTimeMillis();
220+
if (now < CameraViewHolder.this.lastTimestamp + PREVIEW_INTERVAL)
221+
return;
217222

218-
CameraViewHolder.this.lastTimestamp = now;
223+
CameraViewHolder.this.lastTimestamp = now;
219224

220-
if (!doingVideoProcessing) {
225+
if (frame.getData() != null && frame.getSize() != null) {
221226

222-
Log.i("CameraViewHolder", "Processing new image");
227+
byte[] data = frame.getData();
228+
Size size = frame.getSize();
229+
int width = size.getWidth();
230+
int height = size.getHeight();
231+
int rot = getCorrectCameraOrientation(cameraView.getFacing(),frame.getRotation());
223232

224-
mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rotationDegrees));
225-
} else {
226-
mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rotationDegrees));
233+
if (!doingVideoProcessing) {
234+
mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rot));
235+
} else {
236+
mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rot));
237+
}
238+
}
227239
}
228240
});
229241

@@ -234,12 +246,10 @@ public void updateCamera ()
234246
{
235247
switch (prefs.getCamera()) {
236248
case PreferenceManager.FRONT:
237-
if (cameraView.getFacing() != CameraView.FACING_FRONT)
238-
cameraView.setFacing(CameraView.FACING_FRONT);
249+
cameraView.setFacing(Facing.FRONT);
239250
break;
240251
case PreferenceManager.BACK:
241-
if (cameraView.getFacing() != CameraView.FACING_BACK)
242-
cameraView.setFacing(CameraView.FACING_BACK);
252+
cameraView.setFacing(Facing.BACK);
243253
break;
244254
default:
245255
// camera = null;
@@ -275,7 +285,8 @@ public void updateCamera ()
275285
private void recordNewFrame (byte[] data, int width, int height, int rotationDegrees)
276286
{
277287

278-
Bitmap bitmap = Nv21Image.nv21ToBitmap(renderScript, data, width, height);
288+
Bitmap bitmap = MotionDetector.convertImage(data, width, height);
289+
//Nv21Image.nv21ToBitmap(renderScript, data, width, height);
279290

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

@@ -321,8 +332,8 @@ private synchronized void processNewFrame (byte[] data, int width, int height, i
321332
data,
322333
width,
323334
height,
324-
cameraView.getDefaultOrientation(),
325-
cameraView.getFacing());
335+
rotationDegrees,
336+
cameraView.getFacing()==Facing.FRONT);
326337

327338
lastPic = data;
328339

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

350361
mtxVideoRotate = new Matrix();
351362

352-
if (cameraView.getFacing() == CameraView.FACING_FRONT) {
353-
mtxVideoRotate.postRotate(-cameraView.getDefaultOrientation());
363+
if (cameraView.getFacing() == Facing.FRONT) {
364+
mtxVideoRotate.postRotate(-cameraView.getRotation());
354365
mtxVideoRotate.postScale(-1, 1, cameraView.getWidth() / 2, cameraView.getHeight() / 2);
355366
}
356367
else
357-
mtxVideoRotate.postRotate(cameraView.getDefaultOrientation());
368+
mtxVideoRotate.postRotate(cameraView.getRotation());
358369

359370
doingVideoProcessing = true;
360371

@@ -374,13 +385,10 @@ private synchronized boolean recordVideo() {
374385
public synchronized void stopCamera ()
375386
{
376387
if (cameraView != null) {
377-
cameraView.stop();
388+
cameraView.close();
378389
}
379390
}
380391

381-
public int getCameraFacing() {
382-
return cameraView.getFacing();
383-
}
384392

385393
public void destroy ()
386394
{
@@ -391,7 +399,7 @@ public void destroy ()
391399
stopCamera();
392400
}
393401

394-
public int getCorrectCameraOrientation(int facing, int orientation) {
402+
public int getCorrectCameraOrientation(Facing facing, int orientation) {
395403

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

418426
int result;
419-
if(facing == CameraView.FACING_FRONT){
427+
if(facing == Facing.FRONT){
420428
result = (orientation + degrees) % 360;
421429
result = (360 - result) % 360;
422430
}else{

src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@
88

99

1010
import android.graphics.Bitmap;
11+
import android.graphics.BitmapFactory;
1112
import android.graphics.Color;
13+
import android.graphics.ImageFormat;
1214
import android.graphics.Matrix;
15+
import android.graphics.Rect;
16+
import android.graphics.YuvImage;
1317
import android.os.Handler;
1418

15-
import com.google.android.cameraview.CameraView;
1619

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

22+
import java.io.ByteArrayOutputStream;
1923
import java.util.ArrayList;
2024
import java.util.List;
2125

22-
import androidx.renderscript.RenderScript;
23-
import io.github.silvaren.easyrs.tools.Nv21Image;
2426

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

4345
private IMotionDetector detector;
4446

45-
private RenderScript renderScript;
47+
//private RenderScript renderScript;
4648

4749
private int detectColor = Color.YELLOW;
4850

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

6062
public MotionDetector(
61-
RenderScript renderScript,
63+
6264
Handler updateHandler,
6365
int motionSensitivity) {
64-
this.renderScript = renderScript;
66+
// this.renderScript = renderScript;
6567
this.handler = updateHandler;
6668
this.motionSensitivity = motionSensitivity;
6769
detector = new LuminanceMotionDetector();
@@ -84,7 +86,7 @@ public void detect(byte[] rawOldPic,
8486
int width,
8587
int height,
8688
int rotationDegrees,
87-
int cameraFacing) {
89+
boolean facingFront) {
8890

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

119121
Matrix mtx = new Matrix();
120122

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

132-
Bitmap rawBitmap = Bitmap.createBitmap(Nv21Image.nv21ToBitmap(renderScript, rawNewPic, width, height),0,0,width,height,mtx,true);
134+
Bitmap rawBitmap = convertImage(rawNewPic,width,height);
135+
//Bitmap.createBitmap(Nv21Image.nv21ToBitmap(renderScript, rawNewPic, width, height),0,0,width,height,mtx,true);
133136

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

163166
}
164167

168+
public static Bitmap convertImage (byte[] nv21bytearray, int width, int height)
169+
{
170+
YuvImage yuvImage = new YuvImage(nv21bytearray, ImageFormat.NV21, width, height, null);
171+
ByteArrayOutputStream os = new ByteArrayOutputStream();
172+
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, os);
173+
byte[] jpegByteArray = os.toByteArray();
174+
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
175+
return bitmap;
176+
}
177+
165178

166179
}

src/main/java/org/havenapp/main/service/MonitorService.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212

1313
import android.annotation.SuppressLint;
14-
import android.app.NotificationChannel;
15-
import android.app.NotificationManager;
1614
import android.app.PendingIntent;
1715
import android.app.Service;
1816
import android.content.Intent;
@@ -26,6 +24,7 @@
2624
import android.telephony.SmsManager;
2725
import android.text.TextUtils;
2826

27+
import androidx.annotation.RequiresApi;
2928
import androidx.core.app.NotificationCompat;
3029

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

130127
mApp = (HavenApp)getApplication();
131128

132-
manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
133129
mPrefs = new PreferenceManager(this);
134130

135131
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
136-
mChannel = new NotificationChannel(channelId, channelName,
137-
NotificationManager.IMPORTANCE_HIGH);
138-
mChannel.setDescription(channelDescription);
139-
mChannel.setLightColor(Color.RED);
140-
mChannel.setImportance(NotificationManager.IMPORTANCE_MIN);
141-
manager.createNotificationChannel(mChannel);
132+
setupNotificationChannel();
142133
}
143134

144135
startSensors();
@@ -153,6 +144,19 @@ public void onCreate() {
153144
wakeLock.acquire();
154145
}
155146

147+
@RequiresApi(api = Build.VERSION_CODES.O)
148+
private void setupNotificationChannel ()
149+
{
150+
android.app.NotificationManager manager = (android.app.NotificationManager)getSystemService(NOTIFICATION_SERVICE);
151+
android.app.NotificationChannel channel;
152+
channel = new android.app.NotificationChannel(channelId, channelName,
153+
android.app.NotificationManager.IMPORTANCE_HIGH);
154+
channel.setDescription(channelDescription);
155+
channel.setLightColor(Color.RED);
156+
channel.setImportance(android.app.NotificationManager.IMPORTANCE_MIN);
157+
manager.createNotificationChannel(channel);
158+
}
159+
156160
public static MonitorService getInstance ()
157161
{
158162
return sInstance;

0 commit comments

Comments
 (0)