2016-07-15 18 views
0

Ich baue eine einfache Recorder-App. Ich möchte SurfaceView dynamisch anpassen, wenn es mit der Aufzeichnung beginnt. Wenn der Benutzer beispielsweise die Videoauflösung im Vorhinein in den Einstellungsaktivitäten auf 4: 3 setzt und auf die Schaltfläche "Aufnahme starten" klickt, möchte ich, dass SurfaceView seine Breite und Höhe in ein Verhältnis von 4: 3 ändert. Die SurfaceView ändert also ihre Größe, wenn die Aufnahmetaste gedrückt wird.android - Wie kann ich SurfaceView dynamisch ändern?

Ich kann SurfaceView ändern, wenn die App nichts aufnimmt, aber wenn ich versuche, es vor der Videoaufnahme zu ändern, ändert es die Ansicht, aber die Aufnahme wird nicht korrekt ausgeführt (es erzeugt einen stopFailed-Fehler, wenn ich die Aufnahme beendet habe).

Ich möchte, dass meine App die Größe von SurfaceView ändert und gleich danach mit der Aufzeichnung beginnt. Nicht bevor der Benutzer die Aufnahmetaste drückt!

Hier ist mein Code.

MainActivity.java

private boolean prepRecorder() { 
     mRecorder = new MediaRecorder(); 
     CamcorderProfile profile = getCurrentProfile(); 

     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters = setContinuesFocusMode(parameters); 

     Camera.Size desiredSize = null, optimalPreviewSize = null; 
     if (mVideoSizeIndex != -1) { 
      List<Camera.Size> supportedVidSizes = parameters.getSupportedVideoSizes(); 
      if (mVideoSizeIndex < supportedVidSizes.size()) { 
       desiredSize = supportedVidSizes.get(mVideoSizeIndex); 
       optimalPreviewSize = mSurface.getOptimalPreviewSize(
         parameters.getSupportedPreviewSizes(), desiredSize.width, desiredSize.height); 

       Point screenSize = getScreenSize(); 
       mSurface.resizePreview(optimalPreviewSize.width, optimalPreviewSize.height, screenSize.x, screenSize.y); 

       parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height); 
      } 
     } else { 
      parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight); 
     } 

     mCamera.setParameters(parameters); 
     mCamera.unlock(); 

     mRecorder.setCamera(mCamera); 
     mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
     mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mRecorder.setProfile(profile); 
     mRecorder.setPreviewDisplay(mSurface.getHolder().getSurface()); 

     mVideoPath = getMediaPath(); 
     if (mVideoPath != null) { 
      mRecorder.setOutputFile(mVideoPath); 
     } else { 
      return false; 
     } 

     if (desiredSize != null) { 
      mRecorder.setVideoSize(desiredSize.width, desiredSize.height); 
     } else { 
      mRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight); 
     } 

     // Orientation adjustment stuff..... 


     mTrackerThread = new VideoFileTrackerThread(new Handler(), this, mVideoPath); 
     mTrackerThread.start(); 
     mTrackerThread.prepareHandler(); 
     mTrackerThread.triggerHandler(); 

     try { 
      mRecorder.prepare(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return false; 
     } 
     return true; 
    } 

VideoSurfaceView.java

public void resizePreview(int desiredWidth, int desiredHeight, int screenWidth, int screenHeight) { 
    float videoProportion = (float) desiredWidth/(float) desiredHeight; 
    float screenProportion = (float) screenWidth/screenHeight; 

    ViewGroup.LayoutParams lp = this.getLayoutParams(); 
    if (videoProportion > screenProportion) { 
     lp.width = screenWidth; 
     lp.height = (int) ((float) screenWidth/videoProportion); 
    } else { 
     lp.width = (int) (videoProportion * (float) screenHeight); 
     lp.height = screenHeight; 
    } 

    this.setLayoutParams(lp); 
} 


public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
    final double ASPECT_TOLERANCE = 0.2; 
    double targetRatio = (double) w/h; 
    if (sizes == null) 
     return null; 

    Camera.Size optimalSize = null; 
    double minDiff = Double.MAX_VALUE; 

    int targetHeight = h; 

    for (Camera.Size size : sizes) { 
     if (size.width == w && size.height == h) { 
      optimalSize = size; 
      return optimalSize; 
     } 
     double ratio = (double) size.width/size.height; 
     if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 
      continue; 
     if (Math.abs(size.height - targetHeight) < minDiff) { 
      optimalSize = size; 
      minDiff = Math.abs(size.height - targetHeight); 
     } 
    } 

    if (optimalSize == null) { 
     minDiff = Double.MAX_VALUE; 
     for (Camera.Size size : sizes) { 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 
    } 
    return optimalSize; 
} 

Wenn ich resizePreview() Methode ausgeführt werden, wenn die App nicht aufnehmen wird, ist es die Ansicht vollkommen ändert; aber wenn ich es starte, wenn die Aufnahmetaste gedrückt wird, friert es die Benutzeroberfläche für eine Weile ein und die Videoausgabe wird nicht richtig gespeichert. Ist es möglich, dass der Haupt-Thread überlastet ist?

Vielen Dank im Voraus.

+0

Dies sollte helfen! http://stackoverflow.com/questions/20491499/resizing-surface-view-for-aspect-ratio-change-in-video-display-in-android – acac97

+0

@ acac97 Ich habe diese Frage bereits gesehen und implementiert .. Es funktioniert gut, wenn die App nichts aufzeichnet, aber ich möchte die Oberfläche ändern, wenn der Benutzer die Schaltfläche StartRecording drückt. –

+0

Stellen Sie außerdem sicher, dass Sie diese Schritte https://developer.android.com/reference/android/hardware/Camera.html durchlaufen haben – acac97

Antwort

1

Ich löste es. Es wurde wegen der onSurfaceChanged() Methode aufgerufen, wenn ich die Ansicht verkleinere. Ich habe mCamera.stopPreview(), mCamera.setPreviewDisplay() und mCamera.startPreview() entfernt und es funktioniert jetzt gut.

Verwandte Themen