Statistics
| Branch: | Tag: | Revision:

securesmartcam / app / src / main / java / org / witness / obscuracam / video / VideoCam.java @ 41590feb

History | View | Annotate | Download (11.3 KB)

1
package org.witness.obscuracam.video;
2

    
3
import java.io.File;
4
import java.io.FileNotFoundException;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.io.OutputStream;
8
import java.util.Vector;
9

    
10
import org.witness.obscuracam.ObscuraApp;
11
import org.witness.sscphase1.R;
12

    
13
import android.app.Activity;
14
import android.app.AlertDialog;
15
import android.app.ProgressDialog;
16
import android.content.DialogInterface;
17
import android.content.Intent;
18
import android.content.pm.ActivityInfo;
19
import android.content.res.Configuration;
20
import android.graphics.Bitmap;
21
import android.graphics.Bitmap.CompressFormat;
22
import android.graphics.Canvas;
23
import android.graphics.Matrix;
24
import android.graphics.Paint;
25
import android.graphics.RectF;
26
import android.hardware.Camera;
27
import android.media.CamcorderProfile;
28
import android.media.MediaRecorder;
29
import android.net.Uri;
30
import android.os.Bundle;
31
import android.os.Environment;
32
import android.os.SystemClock;
33
import android.util.Log;
34
import android.view.Display;
35
import android.view.MotionEvent;
36
import android.view.SurfaceHolder;
37
import android.view.SurfaceView;
38
import android.view.View;
39
import android.view.View.OnClickListener;
40
import android.view.View.OnTouchListener;
41
import android.view.Window;
42
import android.view.WindowManager;
43
import android.widget.Button;
44

    
45
public class VideoCam extends Activity implements OnTouchListener, OnClickListener, MediaRecorder.OnInfoListener, 
46
                                                                                                                        MediaRecorder.OnErrorListener, SurfaceHolder.Callback, Camera.PreviewCallback 
47
{         
48
        public static final int PLAY = 0;
49
        public static final int SHARE = 1;
50
        
51
        public static final String LOGTAG = ObscuraApp.TAG;
52
                        
53
        private MediaRecorder recorder;
54
        private SurfaceHolder holder;
55
        private CamcorderProfile camcorderProfile;
56
        private Camera camera;        
57
        
58
        // Vector of ObscureRegion objects
59
        private Vector<ObscureRegion> obscureRegions = new Vector<ObscureRegion>();
60
        
61
        boolean recording = false;
62
        boolean usecamera = true;
63
        boolean previewRunning = false;
64
                
65
        long recordStartTime = 0;
66
        
67
        Button recordButton;
68
        
69
        Camera.Parameters p;
70
                
71
        File savePath;
72
        File recordingFile;
73
        File saveFile;
74
        
75
        File redactSettingsFile;
76
        
77
        File overlayImage; 
78

    
79
        ProgressDialog progressDialog;
80
        AlertDialog choiceDialog;
81
        
82
        
83
        Display display; 
84
        int screenWidth;
85
        int screenHeight;
86
        
87
        float calcDefaultXSize;
88
        float calcDefaultYSize;
89

    
90
        private void createCleanSavePath() {
91
                savePath = Environment.getExternalStorageDirectory();
92
                
93
                Log.v(LOGTAG,"savePath:" + savePath.getPath());
94
                if (savePath.exists()) {
95
                        Log.v(LOGTAG,"savePath exists!");
96
                } else {
97
                        Log.v(LOGTAG,"savePath DOES NOT exist!");
98
                        savePath.mkdirs();
99

    
100
                }
101
                
102
                try {
103
                        saveFile = File.createTempFile("output", ".mp4", savePath);
104
                } catch (IOException e) {
105
                        e.printStackTrace();
106
                }
107

    
108
                /*
109
                File[] existingFiles = savePath.listFiles();
110
                if (existingFiles != null) {
111
                        for (int i = 0; i < existingFiles.length; i++) {
112
                                existingFiles[i].delete();
113
                        }
114
                }
115
                */
116
        }
117
        
118
        @Override
119
        public void onCreate(Bundle savedInstanceState) {
120
                super.onCreate(savedInstanceState);
121
                
122
                requestWindowFeature(Window.FEATURE_NO_TITLE);
123
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
124
                                WindowManager.LayoutParams.FLAG_FULLSCREEN);
125
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
126
        
127
                camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
128
        
129
                setContentView(R.layout.video_camera_view);
130
                
131
                recordButton = (Button) this.findViewById(R.id.RecordButton);
132
                recordButton.setOnClickListener(this);                
133
                
134
                SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
135
                holder = cameraView.getHolder();
136
                holder.addCallback(this);
137
                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
138
                        
139
                cameraView.setOnTouchListener(this);
140
                
141
                display = getWindowManager().getDefaultDisplay(); 
142
                screenWidth = display.getWidth();
143
                screenHeight = display.getHeight();                
144
                
145
                redactSettingsFile = new File(Environment.getExternalStorageDirectory(),"redact_unsort.txt");
146
                
147
        }
148
        
149
        private void prepareRecorder() {
150
            recorder = new MediaRecorder();
151
                recorder.setPreviewDisplay(holder.getSurface());
152
                
153
                if (usecamera) {
154
                        camera.unlock();
155
                        recorder.setCamera(camera);
156
                }
157
                
158
                recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
159
                recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
160
        
161
                recorder.setProfile(camcorderProfile);
162
                
163
                calcDefaultXSize = (float)camcorderProfile.videoFrameWidth/(float)screenWidth * (float)ObscureRegion.DEFAULT_X_SIZE;
164
                calcDefaultYSize = (float)camcorderProfile.videoFrameHeight/(float)screenHeight * (float)ObscureRegion.DEFAULT_Y_SIZE;
165
                
166
                createCleanSavePath();
167
                
168
                try {
169
                        
170
                        // This is all very sloppy
171
                        if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.THREE_GPP) {
172
                                recordingFile = File.createTempFile("videocapture", ".3gp", savePath);
173
                                Log.v(LOGTAG,"Recording at: " + recordingFile.getAbsolutePath());
174
                                recorder.setOutputFile(recordingFile.getAbsolutePath());
175
                        } else if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) {
176
                            recordingFile = File.createTempFile("videocapture", ".mp4", savePath);
177
                                Log.v(LOGTAG,"Recording at: " + recordingFile.getAbsolutePath());
178
                                recorder.setOutputFile(recordingFile.getAbsolutePath());
179
                        } else {
180
                            recordingFile = File.createTempFile("videocapture", ".mp4", savePath);
181
                                Log.v(LOGTAG,"Recording at: " + recordingFile.getAbsolutePath());
182
                                recorder.setOutputFile(recordingFile.getAbsolutePath());
183
                        }
184
                //recorder.setMaxDuration(50000); // 50 seconds
185
                //recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
186
                
187
                        recorder.prepare();
188
                } catch (IOException e) {
189
                        Log.v(LOGTAG,"Couldn't create file");
190
                        e.printStackTrace();
191
                        finish();
192
                } catch (IllegalStateException e) {
193
                        e.printStackTrace();
194
                        finish();
195
                }
196
        }
197

    
198
        public void onClick(View v) {
199
                if (recording) {
200
                        recorder.stop();
201
                        if (usecamera) {
202
                                try {
203
                                        camera.reconnect();
204
                                } catch (IOException e) {
205
                                        e.printStackTrace();
206
                                }
207
                        }                        
208
                        // recorder.release();
209
                        recording = false;
210
                        Log.v(LOGTAG, "Recording Stopped");
211
                        
212
                        //TODO: this should now launch the VideoEditor
213
                        
214
                } else {
215
                        recording = true;
216
                        recordStartTime = SystemClock.uptimeMillis();
217
                        recorder.start();
218
                        Log.v(LOGTAG, "Recording Started");
219
                }
220
        }
221
        
222
        public void surfaceCreated(SurfaceHolder holder) {
223
                Log.v(LOGTAG, "surfaceCreated");
224
                
225
                if (usecamera) {
226
                        camera = Camera.open();
227
                        
228
                        try {
229
                                camera.setPreviewDisplay(holder);
230
                                camera.startPreview();
231
                                previewRunning = true;
232
                        }
233
                        catch (IOException e) {
234
                                Log.e(LOGTAG,e.getMessage());
235
                                e.printStackTrace();
236
                        }        
237
                }                
238
                
239
        }
240
        
241
        
242
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
243
                Log.v(LOGTAG, "surfaceChanged");
244
        
245
                if (!recording && usecamera) {
246
                        if (previewRunning){
247
                                camera.stopPreview();
248
                        }
249
        
250
                        try {
251
                                Camera.Parameters p = camera.getParameters();
252
        
253
                                 p.setPreviewSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
254
                             p.setPreviewFrameRate(camcorderProfile.videoFrameRate);
255
                                
256
                                camera.setParameters(p);
257
                                
258
                                camera.setPreviewDisplay(holder);
259
                                camera.startPreview();
260
                                previewRunning = true;
261
                        }
262
                        catch (IOException e) {
263
                                Log.e(LOGTAG,e.getMessage());
264
                                e.printStackTrace();
265
                        }        
266

    
267
                        prepareRecorder();        
268
                }
269
        }
270
        
271
        
272
        public void surfaceDestroyed(SurfaceHolder holder) {
273
                Log.v(LOGTAG, "surfaceDestroyed");
274
                if (recording) {
275
                        recorder.stop();
276
                        recording = false;
277
                }
278
                recorder.release();
279
                if (usecamera) {
280
                        previewRunning = false;
281
                        camera.lock();
282
                        camera.release();
283
                }
284
                finish();
285
        }
286

    
287
        public void onPreviewFrame(byte[] b, Camera c) {
288
                
289
        }
290
        
291
    @Override
292
    public void onConfigurationChanged(Configuration conf) 
293
    {
294
        super.onConfigurationChanged(conf);
295
    }        
296
            
297
    private void createOverlayImage() {
298
                try {
299
                        overlayImage = new File(savePath,"overlay.jpg");
300
                        
301
                    Bitmap overlayBitmap = Bitmap.createBitmap(720, 480, Bitmap.Config.RGB_565);
302
                    Canvas obscuredCanvas = new Canvas(overlayBitmap);
303
                    Paint obscuredPaint = new Paint();   
304
                    Matrix obscuredMatrix = new Matrix();
305
                
306
                    obscuredCanvas.drawOval(new RectF(10,10,100,100), obscuredPaint);
307
                    
308
                    OutputStream overlayImageFileOS = new FileOutputStream(overlayImage);
309
                        overlayBitmap.compress(CompressFormat.JPEG, 90, overlayImageFileOS);
310
                } catch (FileNotFoundException e) {
311
                        e.printStackTrace();
312
                }
313
    }
314
    
315
        
316
        private void showPlayShareDialog() {
317
                progressDialog.cancel();
318

    
319
                AlertDialog.Builder builder = new AlertDialog.Builder(VideoCam.this);
320
                builder.setMessage("Play or Share?")
321
                        .setCancelable(true)
322
                        .setPositiveButton("Play", new DialogInterface.OnClickListener() {
323
                                public void onClick(DialogInterface dialog, int id) {
324
                                        playVideo();
325
                                }
326
                        })
327
                        .setNegativeButton("Share", new DialogInterface.OnClickListener() {
328
                    public void onClick(DialogInterface dialog, int id) {
329
                            shareVideo();
330
                    }
331
                    });
332
                AlertDialog alert = builder.create();
333
                alert.show();
334
        }
335
        
336
        private void playVideo() {
337
            Intent intent = new Intent(android.content.Intent.ACTION_VIEW); 
338
                    Uri data = Uri.parse(savePath.getPath()+"/output.mp4");
339
                    intent.setDataAndType(data, "video/mp4"); 
340
                    startActivityForResult(intent,PLAY);
341
        }
342
        
343
        private void shareVideo() {
344
            Intent share = new Intent(Intent.ACTION_SEND);
345
            share.setType("video/mp4");
346
            share.putExtra(Intent.EXTRA_STREAM, Uri.parse(savePath.getPath()+"/output.mp4"));
347
            startActivityForResult(Intent.createChooser(share, "Share Video"),SHARE);     
348
        }
349
        
350
        protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
351
                super.onActivityResult(requestCode, resultCode, intent);
352
                showPlayShareDialog();
353
        }
354

    
355
        public void onInfo(MediaRecorder mr, int what, int extra) {
356
                
357
        }
358

    
359
        public void onError(MediaRecorder mr, int what, int extra) {
360
                
361
        }
362
        
363
        int startTime = 0;
364
        float startX = 0;
365
        float startY = 0;
366
        
367
        public boolean onTouch(View v, MotionEvent event) {
368
                
369
                boolean handled = false;
370

    
371
                float x = event.getX()/(float)screenWidth * (float)camcorderProfile.videoFrameWidth;
372
                float y = event.getY()/(float)screenHeight * (float)camcorderProfile.videoFrameHeight;
373

    
374
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
375
                
376
                        case MotionEvent.ACTION_DOWN:
377
                                // Single Finger down
378
                                
379
                                if (recording) {
380
                                        startTime = (int)(SystemClock.uptimeMillis() - recordStartTime);
381
                                        startX = x;
382
                                        startY = y;
383
                                        
384
                                        //ObscureRegion singleFingerRegion = new ObscureRegion(SystemClock.uptimeMillis() - recordStartTime,x,y);
385
                                        //obscureRegions.add(singleFingerRegion);
386
                                }
387

    
388
                                handled = true;
389
                                
390
                                break;
391
                                
392
                        case MotionEvent.ACTION_POINTER_DOWN:
393
                                
394
                                break;
395
                                
396
                        case MotionEvent.ACTION_UP:
397
                                // Single Finger Up
398
                                
399
                                if (recording) {                                        
400
                                        ObscureRegion singleFingerUpRegion = new ObscureRegion(startTime,x,y);
401
                                        obscureRegions.add(singleFingerUpRegion);
402
                                }
403
                                
404
                                break;
405
                                
406
                        case MotionEvent.ACTION_POINTER_UP:
407
                                
408
                                break;
409
                                
410
                        case MotionEvent.ACTION_MOVE:
411
                                // Calculate distance moved
412
                                
413
                                if (recording) {
414
                                        ObscureRegion oneFingerMoveRegion = new ObscureRegion(startTime,x,y);
415
                                        obscureRegions.add(oneFingerMoveRegion);
416
                                        
417
                                        startTime = (int)(SystemClock.uptimeMillis() - recordStartTime);
418
                                        startX = x;
419
                                        startY = y;
420
                                }
421
                                
422
                                handled = true;
423

    
424
                                break;
425
                }
426

    
427
                return handled; // indicate event was handled        
428
        }        
429
}