How to render YV12 video frames in Android - java

I have got YV12 video frames from MC67 mobile device imager. I want to display it on android surface.So far i unable to do it.
I am using following code.
MainTestActivity.java
public class MainTestActivity extends Activity {
protected static final String TAG = "CameraTestApp";
private Camera mCamera;
private Preview mPreview;
FrameLayout frmLayoutPreview;
Button btnStart;// Test Start button
Button btnRefreshReport ;//Refresh button
ByteArrayOutputStream out;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(ImageFormat.YV12);
setContentView(R.layout.main);
mCamera= Camera.open(42);
//parameters.setPictureFormat(ImageFormat.YV12);
mPreview = new Preview(this,mCamera);
frmLayoutPreview = (FrameLayout) findViewById(R.id.frmLayoutCameraPreview);
frmLayoutPreview.addView(mPreview);
btnStart = (Button) findViewById(R.id.btnStartTest);
btnStart.setOnClickListener(new OnClickListener () {
public void onClick(View v){
btnStart.setEnabled(false);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
btnRefreshReport.setEnabled(true);
}
});
btnRefreshReport= (Button) findViewById(R.id.btnRefreshReport);
btnRefreshReport.setOnClickListener(new OnClickListener () {
public void onClick(View v){
mCamera.stopPreview();
btnRefreshReport.setEnabled(false);
btnStart.setEnabled(true);
}
});
btnRefreshReport.setEnabled(false);
btnStart.setEnabled(true);
}
PreviewCallback mPreviewCallback = new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
};
#Override
public void onDestroy()
{
super.onDestroy();
this.mCamera.release();
}
}
Preview.java
class Preview extends SurfaceView implements SurfaceHolder.Callback {
public SurfaceHolder mHolder;
private Camera mCamera ;
private String TAG="CAMERA_TEST";
List<Integer> supportformats;//new code
String filename= "/sdcard/BB_FPS.txt";
Preview(Context context,Camera objCamera) {
super(context);
this.mCamera=objCamera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try
{
mCamera.setPreviewDisplay(holder);
}
catch (Exception e) {
Log.i(TAG, "SurfaceCreated error\t"+e.toString());
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.i(TAG, "SurfaceChanged invoked");
if (mHolder.getSurface() == null)
{
return;
}
try
{
mCamera.stopPreview();
}
catch (Exception e){}
try
{ mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (Exception e)
{
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
I tried to set picture format using setPictureFormat(ImageFormat.YV12) method.But it did not work either.Could some one help me here.

I did the same by converting to RGB using libyuv library. But I had to do it frame by frame.

Related

Accessing SurfaceView of an Activity in IntentService

Key Point: My application should be capable of running in background.
A rough structure of my application calls is:
HomeActivity(AppCompatActivity) -> MainActivity(AppCompatActivity) -> CameraRecorderService(IntentService) AND SensorService(Service)
Brief Explanation: On a button press in HomeActivity, MainActivity is triggered using Intent. As soon as MainActivity is called, in its onCreate() method, I call the two services i.e. CameraRecorderService and SensorService.
The CameraRecorderService records the video in an infinite loop unless it receives an event from SensorService.
The current application is working completely fine unless the app goes in background, i.e. I press the home button. It gives D/Camera﹕ app passed NULL surface , E/MediaRecorderJNI﹕ Application lost the surface.
The relevant code for MainActivity and CameraRecorderService are:
"MainActivity.java"
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
public static SurfaceView mSurfaceView; //declared static so that it can be accessed by Services
public static SurfaceHolder mSurfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Intent intent2 = new Intent(MainActivity.this, SensorService.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent2);
Intent intent = new Intent(MainActivity.this, CameraRecorderService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
ImageButton btnStop = (ImageButton) findViewById(R.id.stop);
btnStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopService(new Intent(MainActivity.this, CameraRecorderService.class));
stopService(new Intent(MainActivity.this, SensorService.class));
System.exit(0);
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
"CameraRecorderService.java"
public class CameraRecorderService extends IntentService {
public CameraRecorderService(){
super("CameraRecorderService");
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
static boolean accidentStatus = false;
boolean manualStopStatus = false;
int accidentOnVideoIndex = 0;
#Override
public void onCreate() {
super.onCreate();
mSurfaceView = MainActivity.mSurfaceView; //Getting the surface from Activity
mSurfaceHolder = MainActivity.mSurfaceHolder;
}
#Override
public void onDestroy() {
super.onDestroy();
manualStopStatus = true;
if(mRecordingStatus){
stopRecording();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
while(!accidentStatus){
int i =1;
while(i < 3) {
if (!accidentStatus && !manualStopStatus) {
accidentOnVideoIndex = i;
startRecording("someName" + i);
try {
Thread.sleep(5000);
if(mRecordingStatus)
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}else{
break;
}
}
}
if(!manualStopStatus) {
startRecording("someName3");
try {
Thread.sleep(5000);
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean startRecording(String fileName){
try {
mRecordingStatus = true;
mServiceCamera = Camera.open();
Camera.Parameters p = mServiceCamera.getParameters();
final List<Camera.Size> listSize = p.getSupportedPreviewSizes();
Camera.Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
mServiceCamera.setDisplayOrientation(90);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));
mMediaRecorder.setOutputFile("/somePath/" + fileName + ".mp4");
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
mRecordingStatus = false;
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mServiceCamera.stopPreview();
mMediaRecorder.release();
mServiceCamera.release();
mServiceCamera = null;
}
public static class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Accident!!");
accidentStatus = true;
}
}
I think the problem is that the SurfaceView is destroyed when Activity goes in onPause() state and as I have used a static SurfaceView it is nullified. And so the CameraRecorderService(IntentService) does not get the value from Activity because it runs on a separate thread.
But how do I solve this problem? As I said, the application works fine in foreground but the main purpose of my application is to run in background. Any suggestions are welcome!

getCameraInstance(0) returns null

The basic idea is if no face detected,it should return to Main(reset Activity) but after returning back to main ,getCameraInstance(0) returns null.
If i want to back to Main ,it will call the onPause() and release the cam and after main re-created the backCamera is already relased and it should problem-free create a new instance of back camera.Am i wrong ?
Thanks
ps :i get java.lang.RuntimeException: Fail to connect to camera service and that means i didnt release the camera correctly but i cant find my error.
Here is my code
public class MainActivity extends Activity{
....
private Camera mCameraBack=null;
private CameraPreviewBack mPreviewBack;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mCameraBack==null){
mCameraBack=getCameraInstance(0);
}
try{
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack=(FrameLayout)findViewById(R.id.camera_preview_back);
previewBack.addView(mPreviewBack);
}catch(Exception ex){
Log.d(TAG,"surfaceCreate");
ex.printStackTrace();
}
public void capture(View view){
mPreviewBack.takePicture();
...
}
#Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
if (mCameraBack != null) {
mCameraBack.stopPreview();
mCameraBack.release();
mCameraBack = null;
}
if (mPreviewBack != null) {
previewBack.removeView(mPreviewBack);
mPreviewBack = null;
}
}
#Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
if (mCameraBack == null) {
mCameraBack = getCameraInstance(0);
}
if (mPreviewBack == null) {
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack.addView(mPreviewBack);
}
}
public static Camera getCameraInstance(int cameraId){
Camera c = null;
try {
c = Camera.open(cameraId);
}
catch (Exception e){
}
return c; // returns null if camera is unavailable
}
}
and
public class CameraPreviewBack extends SurfaceView implements SurfaceHolder.Callback {
...
public CameraPreviewBack(Context context,Camera camera) {
super(context);
mCamera=camera;
this.context=context;
mHolder=getHolder();
mHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Surface created");
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(TAG, "mHolder failure");
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG, "Surface changed");
configureCamRotation();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void takePicture(){
..
task.execute();
try {
task.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
task.cancel(isFinished);
}
private PictureCallback getPictureCallback() {
PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera){
....
if(!detected){
Intent intentMain=new Intent(context, MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intentMain);
}
...
}
private class TakePictureTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
mCamera.takePicture(null, null, getPictureCallback());
try {
Thread.sleep(2000); // 3 second preview
} catch (InterruptedException e) {
}
return null;
}
}
newer swallow exceptions
like here:
catch (Exception e){
}
Print this exception Log.d(TAG, "Error when init camera", e); and maybe you will get:
Runtime Exception http://developer.android.com/reference/android/hardware/Camera.html#open(int)
releasing camera onDestroy and changing Intents in onPostExecute method of Asynctask solved my problem

Android - Recording Video in the Background

I am trying to develop an application in Android with the following feature: record video and audio seamlessly, even if the user has another application in the foreground. A common scenario for it would be: the user opens the app, starts recording, then opens a navigation app or receives a call. I want my app to keep recording.
I have put together some code, mainly inspired by this tutorial, which will be quoted below. I have encountered two problems, however:
1. When I press the "home" key, video recording freezes, but sound is fine
2. When I navigate back to the app, the preview is black
My questions are:
Is my goal possible on Android?
What am I doing wrong?
My code:
public class GlobalState extends Application {
private boolean recording = false;
private boolean loggingEnabled = true;
private Camera serviceCamera = null;
private CameraPreview cameraPreview = null;
#Override
public void onCreate() {
try {
serviceCamera = Camera.open();
} catch (Exception e) {
}
super.onCreate();
}
public boolean isRecording() {
return recording;
}
public boolean isLoggingEnabled() {
return loggingEnabled;
}
public void setRecording(boolean recording) {
this.recording = recording;
}
public void setCamera(Camera serviceCamera) {
this.serviceCamera = serviceCamera;
}
public Camera getCamera() {
return serviceCamera;
}
public void setCameraPreview(CameraPreview cameraPreview) {
this.cameraPreview = cameraPreview;
}
public CameraPreview getCameraPreview() {
return this.cameraPreview;
}
}
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private static final String TAG = "CameraPreview";
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
public class MainActivity extends Activity {
public String TAG = "DE-MainActivity";
ImageView mRecordView;
ImageView mMenuButtonView;
LinearLayout mMenuView;
TextView mVideosTextView;
TextView mSettingsTextView;
private Camera mCamera;
private CameraPreview mPreview;
GlobalState mAppState = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAppState = (GlobalState) getApplicationContext();
if (mAppState.isLoggingEnabled()) {
Log.v(TAG, "Activity: onCreate");
}
mCamera = mAppState.getCamera();
if (mAppState.getCameraPreview() == null) {
mPreview = new CameraPreview(this, mCamera);
mAppState.setCameraPreview(mPreview);
}
FrameLayout preview = (FrameLayout) findViewById(R.id.fl_camera);
preview.addView(mPreview);
mMenuView = (LinearLayout) findViewById(R.id.ll_menu_list);
mVideosTextView = (TextView) findViewById(R.id.tv_menu_item_videos);
mSettingsTextView = (TextView) findViewById(R.id.tv_menu_item_settings);
mRecordView = (ImageView) findViewById(R.id.iv_record);
mRecordView.setImageResource(R.drawable.btn_not_recording);
mRecordView.setAlpha((float) 0.5);
mRecordView.bringToFront();
mRecordView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mAppState.isRecording()) {
mRecordView.setImageResource(R.drawable.btn_recording);
mRecordView.setAlpha((float) 0.3);
startService(new Intent(MainActivity.this,
RecorderService.class));
} else {
mRecordView.setImageResource(R.drawable.btn_not_recording);
mRecordView.setAlpha((float) 0.5);
stopService(new Intent(MainActivity.this,
RecorderService.class));
}
}
});
mMenuButtonView = (ImageView) findViewById(R.id.iv_menu);
mMenuButtonView.setImageResource(R.drawable.btn_menu);
mMenuButtonView.setAlpha((float) 0.5);
mMenuButtonView.bringToFront();
mMenuButtonView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mMenuView.getVisibility() == View.VISIBLE) {
mMenuView.setVisibility(View.INVISIBLE);
} else {
mMenuView.setVisibility(View.VISIBLE);
}
}
});
mSettingsTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mAppState.isLoggingEnabled())
Log.v(TAG, "settings clicked!");
}
});
mVideosTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mAppState.isLoggingEnabled())
Log.v(TAG, "videos clicked!");
}
});
}
#Override
protected void onDestroy() {
if (mAppState.isLoggingEnabled())
Log.v(TAG, "APPLICATION EXIT!");
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
super.onDestroy();
}
public boolean onCreateOptionsMenu(Menu menu) {
if (mMenuView.getVisibility() == View.VISIBLE) {
mMenuView.setVisibility(View.INVISIBLE);
} else {
mMenuView.setVisibility(View.VISIBLE);
}
return false;
}
}
public class RecorderService extends Service {
private static final String TAG = "RecorderService";
private static Camera mServiceCamera;
private MediaRecorder mMediaRecorder;
private GlobalState mAppState;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
#Override
public void onCreate() {
mAppState = (GlobalState) getApplicationContext();
mServiceCamera = mAppState.getCamera();
if (mAppState.isLoggingEnabled())
Log.v(TAG, "onCreate");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (!mAppState.isRecording()) {
if (prepareVideoRecorder()) {
mMediaRecorder.start();
mAppState.setRecording(true);
} else {
releaseMediaRecorder();
}
}
return 5;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
if (mAppState.isLoggingEnabled())
Log.v(TAG, "onDestroy");
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mServiceCamera.lock(); // take camera access back from MediaRecorder
mAppState.setRecording(false);
super.onDestroy();
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
}
}
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type) {
File mediaStorageDir = new File(
Environment.getExternalStorageDirectory(), "DashEyeApp");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
private boolean prepareVideoRecorder() {
mMediaRecorder = new MediaRecorder();
mServiceCamera.unlock();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO)
.toString());
// Step 5: Set the preview output
// mMediaRecorder.setPreviewDisplay(mAppState.getCameraPreview().getHolder().getSurface());
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG,
"IllegalStateException preparing MediaRecorder: "
+ e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
}
I am sorry for the wall of text and I greatly appreciate any help!
my solution is fine, try it:
Service android:
import java.util.Calendar;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
public class BackgroundVideoRecorder extends Service implements
SurfaceHolder.Callback {
private WindowManager windowManager;
private SurfaceView surfaceView;
private Camera camera = null;
private MediaRecorder mediaRecorder = null;
int contTime = 0, duracaoGravacao = 30; //interval in seconds to record video
private class thread implements Runnable {
public void run() {
contTime++;
if (contTime >= duracaoGravacao) {
StopService();
}
tick_Handler.postDelayed(tick_thread, 1000);
}
}
Handler tick_Handler;
thread tick_thread;
Preferences pref;
#Override
public void onCreate() {
windowManager = (WindowManager) this
.getSystemService(Context.WINDOW_SERVICE);
surfaceView = new SurfaceView(this);
LayoutParams layoutParams = new WindowManager.LayoutParams(1, 1,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowManager.addView(surfaceView, layoutParams);
surfaceView.getHolder().addCallback(this);
tick_Handler = new Handler();
tick_thread = new thread();
VIDEO_RECORDER_FOLDER = new _Path().getPathVideo();
}
#Override
public void onStart(Intent intent, int startId) {
tick_Handler.post(tick_thread);
}
// Method called right after Surface created (initializing and starting
// MediaRecorder)
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
boolean found = false;
int i = 0;
try {
for (i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.CameraInfo newInfo = new Camera.CameraInfo();
Camera.getCameraInfo(i, newInfo);
if (newInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
found = true;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (found) {
camera = Camera.open(i);
} else {
camera = Camera.open();
}
Calendar lCDateTime = Calendar.getInstance();
String t = String.valueOf(lCDateTime.getTimeInMillis());
nomeArquivo = "hire_me_now_" + t + ".mp4";
nomeArquivo = nomeArquivo.replace(" ", "_").replace(":", "_")
.replace("-", "_");
String caminhoArquivo = VIDEO_RECORDER_FOLDER + "/" + nomeArquivo;
mediaRecorder = new MediaRecorder();
camera.unlock();
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_QVGA));
mediaRecorder.setVideoFrameRate(15);
mediaRecorder.setOutputFile(caminhoArquivo);
try {
mediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
}
mediaRecorder.start();
}
// Stop recording and remove SurfaceView
#Override
public void onDestroy() {
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
camera.lock();
camera.release();
windowManager.removeView(surfaceView);
}
protected void StopService() {
try {
this.stopSelf();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
It turns out that Android doesn't like that the preview gets destroyed (when, for example, the user hits the "Home" button) so it cuts out video recording.
The workaround to this is using WindowManager to set an overlay and, when the user hits the "Home" button, resize it to 1x1. I found the solution here. Many thanks to cman!
it can be done but from API level 23 you will need ask for camera permissions, you can refer to this answer https://stackoverflow.com/a/49919386/4604234

Android Camera activity takes time to render

I have a simple app.On Button click from the Main activity,I call another activity which just shows a preview from the front Camera.I observe that it takes around 4 seconds for the second activity to launch.I think its because of the time it takes to render the camera preview element in the second activity.This is way too long and I am looking for a way to reduce the rendering time of the second activity.Here is my code:
Main.java:
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnLaunchCamera = (Button) findViewById(R.id.launchCamera);
btnLaunchCamera.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Main.this, Cam.class));
}
});
}
}
Cam.java
public class Cam extends Activity {
private static int cameraId = 0;
private Camera camera;
//Adding for camera preview
public static FrameLayout preview;
public static CameraPreview mPreview;
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("Cam","Inside onCreate");
setContentView(R.layout.cam);
context = getApplicationContext();
// Do we have a camera?
try {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG).show();
} else {
cameraId = AppFunctions.findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
} else {
try {
camera = Camera.open(cameraId);
Log.d("Cam","camera id" + cameraId);
} catch (Exception e) {
e.printStackTrace();
}
try {
mPreview = new CameraPreview(this, camera);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e3) {
e3.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
Log.e("Cam","Inside onPause");
try {
if (camera != null) {
camera.release();
camera = null;
preview.removeView(mPreview);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
Log.e("Cam","Inside onResume");
try {
if(camera ==null) {
Log.d("Cam","in resume,camera is null");
try {
camera = android.hardware.Camera.open(cameraId);
mPreview = new CameraPreview(this, camera);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.e("Cam","Inside onDestroy");
if (camera != null) {
try {
camera.release();
camera = null;
preview.removeView(mPreview);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
cam.xml
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="453dp"
android:layout_height="400dp"
android:layout_marginLeft="250dp"
android:layout_marginTop="30dp"
android:padding="5dp" >
</FrameLayout>
CameraPreview.java
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
final static String TAG = "CameraPreview";
public CameraPreview(Context context, Camera camera) {
super(context);
try {
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} catch (Exception e) {
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(0);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG,"Inside SurfaceDestroyed");
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Please assist me on how I can reduce the rendering time for the second activity.Any help would be appreciated.Many thanks !

CameraView only works in emulator

I've written a litte Camera-Appliction after I have read this tutorial:
http://www.brighthub.com/mobile/google-android/articles/43414.aspx
In the emulator everything works fine (ok, there's no camera, but at least there are no errors ;) )
Then I tried to get it run on my HTC Wildfire S. But immediately after the start the app crashes.
Here's the code of my Activity, maybe somebody has an idea, how to solve the problem:
public class CameraView extends Activity implements SurfaceHolder.Callback {
android.hardware.Camera mCamera;
boolean mPreviewRunning = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_surface);
SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = android.hardware.Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if(mPreviewRunning) {
mCamera.stopPreview();
}
android.hardware.Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
mCamera.setParameters(params);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException ex) {
ex.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
}
};
}
You are getting an exception because you are trying to make the camera use a width and height it doesn't support. You are asking it to use the width and height of the SurfaceView, which rarely matches one of the supported preview sizes. Instead, try using the following:
public class CameraView extends Activity implements SurfaceHolder.Callback {
android.hardware.Camera mCamera;
boolean mPreviewRunning = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_surface);
SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e(TAG, "Exception in setPreviewDisplay()", t);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height, parameters);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.startPreview();
inPreview=true;
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
}
};
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width<=width && size.height<=height) {
if (result==null) {
result=size;
}
else {
int resultArea=result.width*result.height;
int newArea=size.width*size.height;
if (newArea>resultArea) {
result=size;
}
}
}
}
return(result);
}
}
This code is all adapted from the one I wrote for my book. I changed some of your code, so some variable names and imports might need to be fixed, but it should work fine.
getBestPreviewSize() is the magic method here which calculates the optimum and best camera preview size to use.

Categories

Resources