谷歌眼镜XE22 Android MediaRecorder stop()冻结了应用程序

时间:2015-05-25 04:59:03

标签: android multithreading video google-glass android-mediarecorder

我是android编程的新手,我正在尝试将视频收集为mp4文件和传感器数据,并将其写入dat文件。 我已设法开始录制但停止录制会冻结应用程序。 分为两个阶段。

第一阶段: SurfaceView用于将传感器读数作为文本叠加到视频输入上。 SurfaceView在UI线程上运行,而传感器日志记录和MediaRecorder在不同的线程上运行。 根据需要生成相机预览。

第二阶段: 现在我尝试开始录制,并将带有时间戳的相关传感器数据写入文件。 我正在使用Media Recorder来实现这一目标。当我试图停止录制整个程序挂起。 在调试模式下,代码不会冻结在mediaRecorder.stop()但生成的mp4文件已损坏,我无法使用视频播放器(VLC)打开它。

根据需要记录传感器读数。此外,即使我没有记录传感器值,视频录制也不起作用。

有人可以帮我解决这个问题吗?

主要活动:

package priyaman.com.glassdatavisualizer;

import com.google.android.glass.media.Sounds;
import com.google.android.glass.touchpad.Gesture;
import com.google.android.glass.touchpad.GestureDetector;
import com.google.android.glass.widget.CardBuilder;
import com.google.android.glass.widget.CardScrollAdapter;
import com.google.android.glass.widget.CardScrollView;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;

import priyaman.com.glassdatavisualizer.controllers.CameraController;
import priyaman.com.glassdatavisualizer.controllers.DrawViewController;
import priyaman.com.glassdatavisualizer.controllers.SensorController;
import priyaman.com.glassdatavisualizer.controllers.SensorThread;
import priyaman.com.glassdatavisualizer.service.MotionSensorService;
import priyaman.com.glassdatavisualizer.utilities.CameraUtils;

public class GlassVisualizerActivity extends Activity {

    private Camera camera;
    private CameraController cameraController;
    private GestureDetector mGestureDetector;
    private SensorController sensorController;
    private SensorThread sensorThread = null;
    private DrawViewController drawView;
    FrameLayout alParent;
    public  GestureDetector createGestureDetector(final Context context)
    {
        GestureDetector gestureDetector = new GestureDetector(context);
        //Create a base listener for generic gestures
        gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
            @Override
            public boolean onGesture(Gesture gesture) {
                if(priyaman.com.glassdatavisualizer.utilities.Log.D) priyaman.com.glassdatavisualizer.utilities.Log.d("gesture = " + gesture);
                if (gesture == Gesture.TAP) {
                    cameraController.releaseCamera();
                    if(cameraController.isRecording){
                        cameraController.stopRecordingThread.run();//recordThread.run();
                        cameraController = new CameraController(context,camera);
                    }else{
                        cameraController.recordThread.run();//startRecording();
                        }

                    return true;
                } else if (gesture == Gesture.TWO_TAP) {
                    //handleGestureTwoTap();
                    //doStopService();


                    return true;
                }
                return false;
            }
        });
        return gestureDetector;
    }

    @Override
    protected void onCreate(Bundle bundle) {
        Log.d("Debug:", "onCreate: GlassVisualizerActivity");
        super.onCreate(bundle);

        camera = CameraUtils.getCameraInstance();
        Camera.Parameters params = camera.getParameters();
        params.setRecordingHint(true);
        camera.setParameters(params);
        cameraController = new CameraController(this, camera);
        //this.setContentView(cameraController);
        mGestureDetector = this.createGestureDetector(this);
        drawView = new DrawViewController(this,cameraController);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        if (cameraController != null){
            alParent = new FrameLayout(this);
            alParent.setLayoutParams(new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.FILL_PARENT,
                    FrameLayout.LayoutParams.FILL_PARENT));

            //doStartService();
            alParent.addView(cameraController);
            alParent.addView(drawView);
            this.setContentView(alParent);
            //sensorController = new SensorController(this,drawView);
            sensorThread = new SensorThread(this,drawView);
            sensorThread.run();
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (cameraController != null) {
            cameraController.releaseCamera();
        }
        //doStartService();

        // Set the view
        //alParent.addView(drawView);
        //alParent.addView(cameraController);
        this.setContentView(alParent);
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event)
    {
        if (mGestureDetector != null) {
            return mGestureDetector.onMotionEvent(event);
        }
        return false;
    }


@Override
protected void onPause() {
    if (cameraController != null) {
        cameraController.releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        cameraController.releaseCamera();              // release the camera immediately on pause event
    }

    super.onPause();
}


}

绘制SurfaceView:

package priyaman.com.glassdatavisualizer.controllers;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import priyaman.com.glassdatavisualizer.utilities.Log;
import priyaman.com.glassdatavisualizer.utilities.Utilities;

/**
 * Created by priya_000 on 5/20/2015.
 */
public class DrawViewController extends SurfaceView implements SurfaceHolder.Callback{

    private Paint textPaint = new Paint();
    public SurfaceHolder surfaceHolder = null;
    private Context context = null;
    private CameraController cameraController = null;

    public DrawViewController(Context context, CameraController cameraController) {
        super(context);
        this.context = context;

        textPaint = new Paint();
        textPaint.setARGB(255, 200, 0, 0);
        textPaint.setTextSize(20);
        setWillNotDraw(false);
        surfaceHolder = getHolder();
        this.cameraController = cameraController;
    }

    @Override
    protected void onDraw(Canvas canvas){
        String content = "";
        int counter = 50;
        if(Utilities.logSensorValues){
            canvas.drawText("Recording:",50,20,textPaint);
        }
        if(Utilities.lastSensorValuesAccelerometer != null) {
            content += "Accelerometer:\n" + Utilities.lastSensorValuesAccelerometer.toString() + "\n";
            canvas.drawText("Accelerometer:\n" + Utilities.lastSensorValuesAccelerometer.toString(), 50, counter+=25, textPaint);
        }
        if(Utilities.lastSensorValuesGravity != null) {
            content += "Gravity:\n" + Utilities.lastSensorValuesGravity.toString() + "\n";
            canvas.drawText("Gravity:\n" + Utilities.lastSensorValuesGravity.toString() , 50, counter+=25, textPaint);
        }
        if(Utilities.lastSensorValuesLinearAcceleration != null) {
            content += "Linear Acceleration:\n" + Utilities.lastSensorValuesLinearAcceleration.toString() + "\n";
            canvas.drawText( "Linear Acceleration:\n" + Utilities.lastSensorValuesLinearAcceleration.toString() , 50, counter+=25, textPaint);
        }
        if(Utilities.lastSensorValuesGyroscope != null) {
            content += "Gyroscope:\n" + Utilities.lastSensorValuesGyroscope.toString() + "\n";
            canvas.drawText( "Gyroscope:\n" + Utilities.lastSensorValuesGyroscope.toString() , 50, counter+=25, textPaint);
        }
        if(Utilities.lastSensorValuesRotationVector != null) {
            content += "Rotation Vector:\n" + Utilities.lastSensorValuesRotationVector.toString() + "\n";
            canvas.drawText( "Rotation Vector:\n" + Utilities.lastSensorValuesRotationVector.toString() , 50, counter+=25, textPaint);
        }
        Log.d("Values Published:" + content);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Canvas c = holder.lockCanvas();
        if(c!=null)
            draw(c);
        if(c!=null)
            holder.unlockCanvasAndPost(c);

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Canvas c = holder.lockCanvas();
        if(c!=null)
            draw(c);
        if(c!=null)
            holder.unlockCanvasAndPost(c);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
         cameraController.releaseCamera();
    }
}

相机相关SurfaceView:

package priyaman.com.glassdatavisualizer.controllers;

import android.content.Context;
import android.graphics.Rect;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import priyaman.com.glassdatavisualizer.utilities.Log;

import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import priyaman.com.glassdatavisualizer.R;
import priyaman.com.glassdatavisualizer.utilities.CameraUtils;
import priyaman.com.glassdatavisualizer.utilities.Utilities;

/**
 * Created by priya_000 on 5/19/2015.
 */
public class CameraController extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder finalView;
    private Camera camera;
    private MediaRecorder mediaRecorder;
    public boolean isRecording = false;
    public RecThread recordThread = null;
    public StopRecordingThread stopRecordingThread = null;
    public CameraController(Context context, Camera camera){
        super(context);
        Log.d("In Camera Controller Constructor");
        this.camera = camera;
        finalView = getHolder();
        finalView.addCallback(this);
        finalView.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mediaRecorder = new MediaRecorder();
        recordThread = new RecThread(mediaRecorder);
        stopRecordingThread = new StopRecordingThread((mediaRecorder));
    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.v("In create surface");
        try {
            if(camera==null){
                camera = CameraUtils.getCameraInstance();
                if(camera == null)
                    return;
                //setMeteringParams();
            }

            camera.setPreviewDisplay(holder);

        } catch (IOException e1) {
            Log.e("Error in surface creation",e1);
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        //Log that camera controller destroyed
        Log.d("In surface destroyed:Camera Controller Destroyed");
        if(camera!= null)
            camera.stopPreview();
        releaseCamera();
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
        Log.d("In Surface Changed");
        if (holder.getSurface() == null){
            // preview surface does not exist
            return;
        }
        // stop preview before making changes
        try {
            camera.stopPreview();
        } catch (Exception e){
        }
        try {
            //setMeteringParams();
            camera.setPreviewDisplay(holder);
            camera.startPreview();

        } catch (Exception e){

        }
    }

    public class RecThread implements Runnable{
        MediaRecorder mediaRecorder = null;
        public RecThread(MediaRecorder mediaRecorder){
            this.mediaRecorder = mediaRecorder;
        }

        public void run(){
            startRecording();
        }

        public boolean prepareVideoRecorder(){
            Log.d("Preparing Video Recorder");
            try {
                if (camera == null) {
                    camera = CameraUtils.getCameraInstance();
                }
                camera.unlock();
                //mediaRecorder = new MediaRecorder();
                mediaRecorder.setCamera(camera);
                //mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                try {
                    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
                }catch(Exception e){
                    Log.e("Exception caught in setting profile");
                    e.printStackTrace();
                }
                //mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                //mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                mediaRecorder.setPreviewDisplay(finalView.getSurface());
                File outputFile = CameraUtils.getOutputMediaFile(CameraUtils.MEDIA_TYPE_VIDEO);
                Utilities.sensorFileName = outputFile.getName();
                Utilities.logSensorValues = true;
                mediaRecorder.setOutputFile(outputFile.toString());

                try {
                    mediaRecorder.prepare();
                } catch (IllegalStateException e) {
                    Log.d("IllegalStateException preparing MediaRecorder: " + e.getMessage());
                    releaseMediaRecorder();
                    return false;
                } catch (IOException e) {
                    Log.d("IOException preparing MediaRecorder: " + e.getMessage());
                    releaseMediaRecorder();
                    return false;
                }
                //return true;
            }catch(Exception e){
                Log.e("Error in prepare Video Recorder",e);
                e.printStackTrace();
                return false;
            }finally{
                //this.releaseCamera();
                //Log.d("Camera released");
                //return false;
                 Log.d("In finally block");
            }
            return true;
        }

        public void startRecording(){
            Log.d("In Start Recording");
            Log.d("Camera is :" + String.valueOf(camera==null));
            if(isRecording){
                Log.i("Stopping Recording");
                Utilities.logSensorValues = false;
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    public void run() {
                        Log.i("Sleeping for 1 sec after stopping recording");
                    }
                }, 1000);
                mediaRecorder.stop();

                Log.i("Video Stored@");
                releaseMediaRecorder();
                try {
                    //camera.reconnect();
                    //camera.lock();
                    if(camera == null){
                        camera = CameraUtils.getCameraInstance();
                    }

                    camera.setPreviewDisplay(getHolder());
                    camera.lock();
                    camera.startPreview();
                }catch(Exception e){
                    Log.e("Preview display on setpreview after release media recotrdr",e);
                }


                isRecording = false;
            }else{
                if(prepareVideoRecorder()){
                    mediaRecorder.start();
                    Log.i("Started Recording");
                    isRecording = true;
                }
            }
        }
    }

    public void releaseMediaRecorder(){
        if (mediaRecorder != null) {
            mediaRecorder.reset();   // clear recorder configuration
            mediaRecorder.release(); // release the recorder object

            //mediaRecorder = null; //Not setting it to null as it is required for reuse
          /*  try {
                camera.lock();           // lock camera for later use
            }catch(Exception e){
                e.printStackTrace();
            }*/
        }
    }

    public void releaseCamera(){
        if (camera != null){
            camera.release();        // release the camera for other applications
            camera = null;
        }
    }

    public class StopRecordingThread implements Runnable{
        MediaRecorder mediaRecorder = null;
        public StopRecordingThread(MediaRecorder mediaRecorder){
            this.mediaRecorder = mediaRecorder;
        }
        public void run(){
            Log.i("Stopping Recording");
            Utilities.isStopping = true;
            mediaRecorder.stop();
            Log.i("Video Stored@" );
            releaseMediaRecorder();
            Utilities.isStopping = false;
            try {
                //camera.reconnect();
                //camera.lock();
                if(camera == null){
                    camera = CameraUtils.getCameraInstance();
                }

                camera.setPreviewDisplay(getHolder());
                camera.lock();
                camera.startPreview();
            }catch(Exception e){
                Log.e("Preview display on setpreview after release media recotrdr",e);
            }

            Utilities.logSensorValues = false;
            isRecording = false;
        }
    }


}

传感器线程:

package priyaman.com.glassdatavisualizer.controllers;

import android.content.Context;

/**
 * Created by priya_000 on 5/22/2015.
 */
public class SensorThread extends Thread {
    SensorController sensorController;
    Context context = null;
    DrawViewController drawView = null;
    public SensorThread(Context context, DrawViewController drawView){
        this.context = context;
        this.drawView = drawView;
    }
    public void run(){
        sensorController = new SensorController(context, drawView);

    }
}
package priyaman.com.glassdatavisualizer.controllers;

import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Environment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import priyaman.com.glassdatavisualizer.beans.SensorValueStruct;
import priyaman.com.glassdatavisualizer.utilities.CameraUtils;
import priyaman.com.glassdatavisualizer.utilities.Log;
import priyaman.com.glassdatavisualizer.utilities.Utilities;

/**
 * Created by priya_000 on 5/21/2015.
 */
public class SensorController implements SensorEventListener {

    private Context context;
    private DrawViewController drawView;
    // Sensor manager
    private SensorManager mSensorManager = null;

    // Motion sensors
    private Sensor mSensorAccelerometer = null;
    private Sensor mSensorGravity = null;
    private Sensor mSensorLinearAcceleration = null;
    private Sensor mSensorGyroscope = null;
    private Sensor mSensorRotationVector = null;
    String mediaStorageDir = null;

    private void initializeSensorManager()
    {
        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
        mSensorLinearAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
        mSensorGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        mSensorRotationVector = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
    }


    public SensorController(Context context, DrawViewController drawView){
            Log.d("onServiceStart() called.");
            this.context = context;
            this.drawView = drawView;
            initializeSensorManager();
            mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
            mSensorManager.registerListener(this, mSensorGravity, SensorManager.SENSOR_DELAY_NORMAL);
            mSensorManager.registerListener(this, mSensorLinearAcceleration, SensorManager.SENSOR_DELAY_NORMAL);
            mSensorManager.registerListener(this, mSensorGyroscope, SensorManager.SENSOR_DELAY_NORMAL);
            mSensorManager.registerListener(this, mSensorRotationVector, SensorManager.SENSOR_DELAY_NORMAL);

            mediaStorageDir = CameraUtils.getOutputMediaFile(3).toString();
    }
    @Override
    public void onSensorChanged(SensorEvent event) {

        Log.d("onSensorChanged() called.");

        processMotionSensorData(event);
        if(Utilities.logSensorValues){
            StringBuffer strBuf = new StringBuffer();
            if(Utilities.lastSensorValuesAccelerometer != null) {
                strBuf.append("Accelerometer:\n" + Utilities.lastSensorValuesAccelerometer.toString() + "\n");
            }
            if(Utilities.lastSensorValuesGravity != null) {
                strBuf.append("Gravity:\n" + Utilities.lastSensorValuesGravity.toString() + "\n");
            }
            if(Utilities.lastSensorValuesLinearAcceleration != null) {
                strBuf.append("Linear Acceleration:\n" + Utilities.lastSensorValuesLinearAcceleration.toString() + "\n");
            }
            if(Utilities.lastSensorValuesGyroscope != null) {
                strBuf.append("Gyroscope:\n" + Utilities.lastSensorValuesGyroscope.toString() + "\n");
            }
            if(Utilities.lastSensorValuesRotationVector != null) {
                strBuf.append("Rotation Vector:\n" + Utilities.lastSensorValuesRotationVector.toString() + "\n");
            }
            if(Utilities.lastSensorValuesRotationVector != null) {
                strBuf.append("Timestamp:\n" + Utilities.lastSensorValuesRotationVector.getTimestamp() + "\n");
            }

            writeToFile(strBuf.toString());
        }
        if(!Utilities.isStopping)
            drawView.invalidate();
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        Log.d("onAccuracyChanged() called.");
    }

    private void processMotionSensorData(SensorEvent event)
    {
        long now = System.currentTimeMillis();

        Sensor sensor = event.sensor;
        int type = sensor.getType();
        long timestamp = event.timestamp;
        float[] values = event.values;
        int accuracy = event.accuracy;
        SensorValueStruct data = new SensorValueStruct(type, timestamp, values, accuracy);

        switch(type) {
            case Sensor.TYPE_ACCELEROMETER:
                Utilities.lastSensorValuesAccelerometer = data;
                break;
            case Sensor.TYPE_GRAVITY:
                Utilities.lastSensorValuesGravity = data;
                break;
            case Sensor.TYPE_LINEAR_ACCELERATION:
                Utilities.lastSensorValuesLinearAcceleration = data;
                break;
            case Sensor.TYPE_GYROSCOPE:
                Utilities.lastSensorValuesGyroscope = data;
                break;
            case Sensor.TYPE_ROTATION_VECTOR:
                Utilities.lastSensorValuesRotationVector = data;
                break;
            default:
                Log.w("Unknown type: " + type);
        }



    }

    private void writeToFile(String data) {
        try {
            //OutputStreamWriter outputStreamWriter = new FileOutputStream(new File(mediaStorageDir),true);//new OutputStreamWriter(context.openFileOutput(mediaStorageDir, Context.MODE_PRIVATE));
            FileOutputStream outputStreamWriter = new FileOutputStream(new File(mediaStorageDir),true);//new OutputStreamWriter(context.openFileOutput(mediaStorageDir, Context.MODE_PRIVATE));
            outputStreamWriter.write(data.getBytes());
            outputStreamWriter.close();
        }
        catch (IOException e) {
            Log.e("Exception" + "File write failed: " + e.toString());
        }
    }

}

0 个答案:

没有答案