2013-06-10 35 views
6

Sto provando a costruire un camcorder di base che permetta all'utente di fare video rapidamente toccando lo schermo, questo sembrava semplice ma il problema principale che ho incontrato è che Android MediaRecorder non consente l'avvio rapido e il riavvio senza crash, se l'utente spara e poi si ferma e riprende rapidamente lo scatto si blocca sempre Im non sono sicuro se c'è un modo per risolvere direttamente questo quindi ho anche escogitato un altro metodo per raggiungere questo tentativo per registrare un singolo video ma cercando di ottenere un certo controllo su quando il mediaRecorder scrive effettivamente sul file. tuttavia non ero in grado di farlo funzionare completamente con FileDescriptor, di seguito incollerò il mio codice originale e il mio metodo che ho usato nel secondo tentativo di controllo della scrittura, c'è un modo per regolare entrambi i codici per ottenere quella funzionalità di pausa dopo? qualsiasi aiuto andrà un lungo cammino grazieMediaRecorder start() fallisce se chiamato troppo velocemente

Il mio primo tentativo con il modo comune di impostazione di un file da setOutPutFile():

public class MainActivity extends Activity implements SurfaceHolder.Callback { 

public static final String LOGTAG = "VIDEOCAPTURE"; 

private MediaRecorder recorder; 
private SurfaceHolder holder; 
private CamcorderProfile camcorderProfile; 
private Camera camera; 

boolean recording = false; 
boolean usecamera = true; 
boolean previewRunning = false; 

double timer = 0; 
ProgressBar pb; 
boolean neverEnd; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
      WindowManager.LayoutParams.FLAG_FULLSCREEN); 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW); 

    setContentView(R.layout.activity_main); 

    pb = (ProgressBar) findViewById(R.id.progressBar1); 
    pb.setProgress(0); 

    SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView); 
    holder = cameraView.getHolder(); 
    holder.addCallback(this); 
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

    cameraView.setClickable(true); 
    cameraView.setOnTouchListener(new OnTouchListener() { 
     public boolean onTouch(View v, MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_DOWN) { 

       recording = true; 
       new recordVideo().execute(); 
       Log.v(LOGTAG, "Recording Started"); 

       return true; 
      } else if (event.getAction() == MotionEvent.ACTION_UP) { 

       recording = false; 

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

private void prepareRecorder() { 
    recorder = new MediaRecorder(); 
    recorder.setPreviewDisplay(holder.getSurface()); 

    if (usecamera) { 
     camera.unlock(); 
     recorder.setCamera(camera); 
    } 

    recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 
    recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); 

    recorder.setProfile(camcorderProfile); 


    Calendar calendarTime = Calendar.getInstance(); 

//initial attempt using a file path with setoutputfile 

    File file = new File(Environment.getExternalStorageDirectory(), 
      String.valueOf(calendarTime.getTimeInMillis()) + ".mp4"); 

    if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.THREE_GPP) { 

     recorder.setOutputFile(file.getAbsolutePath()); 
    } else if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) { 

     recorder.setOutputFile(file.getAbsolutePath()); 
    } else { 

     recorder.setOutputFile(file.getAbsolutePath()); 

    } 
    // recorder.setMaxDuration(50000); // 50 seconds 
    // recorder.setMaxFileSize(5000000); // Approximately 5 megabytes 

    boolean initialized = false; 

    while (!initialized) { 
     try { 
      recorder.prepare(); 
      initialized = true; 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
      // finish(); 
      initialized = false; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      // finish(); 
      initialized = false; 
     } 
    } 

} 

public void surfaceCreated(SurfaceHolder holder) { 
    Log.v(LOGTAG, "surfaceCreated"); 

    if (usecamera) { 
     camera = Camera.open(); 

     try { 
      camera.setPreviewDisplay(holder); 
      camera.startPreview(); 
      previewRunning = true; 
     } catch (IOException e) { 
      Log.e(LOGTAG, e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 

} 

public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    Log.v(LOGTAG, "surfaceChanged"); 

    if (!recording && usecamera) { 
     if (previewRunning) { 
      camera.stopPreview(); 
     } 

     try { 
      Camera.Parameters p = camera.getParameters(); 

      p.setPreviewSize(camcorderProfile.videoFrameWidth, 
        camcorderProfile.videoFrameHeight); 
      p.setPreviewFrameRate(camcorderProfile.videoFrameRate); 

      camera.setParameters(p); 

      camera.setPreviewDisplay(holder); 
      camera.startPreview(); 
      previewRunning = true; 
     } catch (IOException e) { 
      Log.e(LOGTAG, e.getMessage()); 
      e.printStackTrace(); 
     } 

     prepareRecorder(); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    Log.v(LOGTAG, "surfaceDestroyed"); 
    if (recording) { 
     recorder.stop(); 
     recording = false; 
    } 
    recorder.release(); 
    if (usecamera) { 
     previewRunning = false; 
     // camera.lock(); 
     camera.release(); 
    } 
    finish(); 
} 

private class recordVideo extends AsyncTask<Void, Integer, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     // TODO Auto-generated method stub 

     try { 

      recorder.start(); 
      while (recording) { 

       Thread.sleep(100); 

       publishProgress(); 
      } 
      recorder.stop(); 
      recorder.release(); 
      recorder = null; 

      // recorder.release(); 

      Log.v(LOGTAG, "Recording Stopped"); 
      // Let's prepareRecorder so we can record again 
      prepareRecorder(); 

     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    @Override 
    protected void onProgressUpdate(Integer... values) { 
     // TODO Auto-generated method stub 
     super.onProgressUpdate(values); 

     if (recording) { 
      timer += 0.1; 
      pb.setProgress((int) (timer * 10)); 
     } 

    } 

} 
} 

Ecco il mio metodo che utilizza FileDescriptor, questo non ha funzionato, creato solo un file, ma non ha ancora scrivere ad esso:

//Pass it into setOutputFile() like this 
recorder.setOutputFile(getStreamFd()); 

    private FileDescriptor getStreamFd() { 
    ParcelFileDescriptor pipe = null; 
    try { 

     Calendar calendarTime = Calendar.getInstance(); 

     File file = new File(Environment.getExternalStorageDirectory(), 
       String.valueOf(calendarTime.getTimeInMillis()) + ".mp4"); 

     pipe = ParcelFileDescriptor.open(file, 
       ParcelFileDescriptor.MODE_CREATE 
         | ParcelFileDescriptor.MODE_APPEND 
         | ParcelFileDescriptor.MODE_WORLD_WRITEABLE); 

     byte[] buf = new byte[1024]; 
     int len; 

     FileOutputStream out = new FileOutputStream(FileDescriptor.out); 

     InputStream is = new FileInputStream(FileDescriptor.in); 

     while (usecamera) { 
         if(recordng){ 
         out.write(buf, 0, len); 
         } 

     } 

     is.close(); 
     out.close(); 

    } catch (IOException e) { 
     Log.e(getClass().getSimpleName(), "Exception opening pipe", e); 
    } 

    return pipe.getFileDescriptor(); 
} 
+1

sei riuscito a fare qualcosa? Ho lo stesso problema ... dopo aver ripetutamente fermato e avviato il registratore multimediale, dopo un po 'di tempo all'avvio() viene visualizzato il codice di errore "start failed -2147483648" ... – Hitman

risposta

0

chiamata cameraView.setClickable (vero) dopo prepareRecorder() e chiamare cameraView.setClickable (false) prima di chiamare prepareRecorder() su AsynkTask