/*
* Copyright (C) 2011 Google Inc.
*
* 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.cellbots.logger;
import android.content.Context;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* View that handles the video recording functionality. Parts of this code were
* taken from memofy's tutorial at:
* http://memofy.com/memofy/show/2008c618f15fc61801ca038cbfe138/how-to-use-mediarecorder-in-android
*
* @author clchen@google.com (Charles L. Chen)
*/
public class FrontCamcorderPreview extends AbstractCamcorderPreview implements
SurfaceHolder.Callback, MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
public static final String TAG = "CELLBOTS LOGGER";
private LoggerApplication application;
private MediaRecorder recorder;
private SurfaceHolder holder;
private FileOutputStream fos;
private static final int FRAME_RATE = 15;
private static final int CIF_WIDTH = 640;
private static final int CIF_HEIGHT = 480;
private boolean initialized;
private Camera camera;
private boolean previewing = false;
public FrontCamcorderPreview(Context context, AttributeSet attrs) {
super(context, attrs);
application = (LoggerApplication) context.getApplicationContext();
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startPreview();
}
@Override
public void startPreview() {
Log.v(TAG, "startPreview");
if (camera == null) {
// If the activity is paused and resumed, camera device has been
// released and we need to open the camera.
try {
camera = Camera.open(1);
} catch (NoSuchMethodError e) {
// Method call not available below API level 9. We can't access
// the front camera.
e.printStackTrace();
return;
}
}
if (previewing) {
camera.stopPreview();
previewing = false;
}
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
try {
camera.setDisplayOrientation(90);
camera.startPreview();
previewing = true;
} catch (Throwable ex) {
closeCamera();
throw new RuntimeException("startPreview failed", ex);
}
initializeRecording();
}
private void closeCamera() {
Log.v(TAG, "closeCamera");
if (camera == null) {
Log.d(TAG, "already stopped.");
return;
}
// If we don't lock the camera, release() will fail.
camera.lock();
camera.release();
camera = null;
previewing = false;
}
@Override
public void initializeRecording() {
if (!initialized) {
if (camera == null) {
camera = Camera.open(1);
camera.setDisplayOrientation(90);
}
camera.unlock();
recorder = new MediaRecorder();
recorder.setOnErrorListener(this);
recorder.setOnInfoListener(this);
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
String path = application.getVideoFilepath();
Log.i(TAG, "Video file to use: " + path);
final File file = new File(path);
final File directory = file.getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
try {
throw new IOException(
"Path to file could not be created. " + directory.getAbsolutePath());
} catch (IOException e) {
Log.e(TAG, "Directory could not be created. " + e.toString());
}
}
if (file.exists()) {
file.delete();
}
if (recorder != null) {
try {
file.createNewFile();
fos = new FileOutputStream(path);
recorder.setOutputFile(fos.getFD());
recorder.setVideoSize(CIF_WIDTH, CIF_HEIGHT);
recorder.setVideoFrameRate(FRAME_RATE);
recorder.setPreviewDisplay(holder.getSurface());
recorder.prepare();
} catch (IllegalStateException e) {
Log.e("ls", e.toString(), e);
} catch (IOException e) {
Log.e("ls", e.toString(), e);
}
}
initialized = true;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void onError(MediaRecorder mediaRecorder, int what, int extra) {
Log.e(TAG, "Error received in media recorder: " + what + ", " + extra);
}
@Override
public void onInfo(MediaRecorder mediaRecorder, int what, int extra) {
Log.e(TAG, "Info received from media recorder: " + what + ", " + extra);
}
@Override
public void releaseRecorder() throws IOException {
if (recorder != null) {
recorder.reset();
recorder.release();
}
if (fos != null) {
fos.close();
}
closeCamera();
initialized = false;
}
@Override
public void startRecording() {
recorder.start();
}
@Override
public void stopRecording() {
if (recorder != null) {
recorder.stop();
}
}
}