2017-07-26 8 views
5

Ich habe den Android-Dienst unten für die Aufnahme der Frontkamera im Hintergrund geschrieben geschrieben. Das funktioniert sehr gut. Aber jetzt möchte ich auch ein Foto alle 5 Sekunden während der Aufnahme machen. Ist das irgendwie möglich? Wenn ich versuche, eine zweite Kamera zu öffnen (in einem anderen Dienst), erhalte ich einen Fehler.Aufnahme während der Aufnahme von Video auf Android

public class RecorderService extends Service implements SurfaceHolder.Callback { 

    private WindowManager windowManager; 
    private SurfaceView surfaceView; 
    private Camera camera = null; 
    private MediaRecorder mediaRecorder = null; 

    @Override 
    public void onCreate() { 
     // Create new SurfaceView, set its size to 1x1, move it to the top left corner and set this service as a callback 
     windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); 
     surfaceView = new SurfaceView(this); 
     WindowManager.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); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     Intent notificationIntent = new Intent(this, MainActivity.class); 

     PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 
       notificationIntent, 0); 

     Notification notification = new NotificationCompat.Builder(this) 
       //.setSmallIcon(R.mipmap.app_icon) 
       .setContentTitle("Background Video Recorder") 
       .setContentText("") 
       .setContentIntent(pendingIntent).build(); 

     startForeground(MainActivity.NOTIFICATION_ID_RECORDER_SERVICE, notification); 
     return Service.START_NOT_STICKY; 
    } 

    // Method called right after Surface created (initializing and starting MediaRecorder) 
    @Override 
    public void surfaceCreated(SurfaceHolder surfaceHolder) { 
     camera = Camera.open(1); 
     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_720P)); 

     FileUtil.createDir("/storage/emulated/0/Study/Camera"); 
     mediaRecorder.setOutputFile("/storage/emulated/0/Study/Camera/" + Long.toString(System.currentTimeMillis()) + ".mp4"); 

     try { mediaRecorder.prepare(); } catch (Exception e) {} 
     mediaRecorder.start(); 

     try { 
      camera.setPreviewDisplay(surfaceHolder); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     Runnable runnable = new PictureThread(camera); 
     Thread thread = new Thread(runnable); 
     thread.start(); 
    } 

    // Stop recording and remove SurfaceView 
    @Override 
    public void onDestroy() { 
     mediaRecorder.stop(); 
     mediaRecorder.reset(); 
     mediaRecorder.release(); 

     camera.lock(); 
     camera.release(); 

     windowManager.removeView(surfaceView); 
    } 

    @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; } 
} 

bearbeiten: Ich habe jetzt einen Thread PictureThread geschrieben. Dieser Thread startet von RecorderService und versucht, ein Bild während der Videoaufnahme aufzunehmen.

public class PictureThread implements Runnable { 
    private final static String TAG = PictureThread.class.getSimpleName(); 

    private Camera camera; 

    PictureThread(Camera camera) { 
     this.camera = camera; 
    } 

    @Override 
    public void run() { 
     camera.startPreview(); 
     camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
    } 

    Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() { 
     public void onShutter() { 
     } 
    }; 

    Camera.PictureCallback rawCallback = new Camera.PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera camera) { 
     } 
    }; 

    Camera.PictureCallback jpegCallback = new Camera.PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera camera) { 
      Log.i(TAG, "onPictureTaken - jpeg"); 
     } 
    }; 
} 

Leider jpegCallback wird nie aufgerufen (das heißt die Log-Nachricht wird nie gedruckt). Wenn ich die Kamera-App meines Tablets öffne, kann ich während der Videoaufnahme Bilder machen, das sollte also möglich sein.

Ich habe auch das Camera2 API-Beispiel wie von Alex Cohn vorgeschlagen (https://github.com/mobapptuts/android_camera2_api_video_app) versucht. Das Aufnehmen eines Videos funktioniert und auch das Aufnehmen eines Bildes funktioniert, aber wenn ich versuche, während der Aufnahme ein Bild aufzunehmen, wird kein Bild erzeugt (aber auch kein Fehler). Trotzdem habe ich festgestellt, dass diese Beispiel-App nicht sehr zuverlässig funktioniert (vielleicht gibt es eine andere Beispiel-App).

Edit 2: Die shutterCallback und rawCallback von takePicture wird aufgerufen, aber die Daten des rawCallback ist null. Die jpegCallback wird nie aufgerufen .. Irgendeine Idee warum und wie das gelöst werden kann? Ich habe auch versucht, im Thread für eine gewisse Zeit zu warten, um die Callback-Zeit für den Aufruf zu geben, und ich habe versucht, die Callbacks in meiner Hauptaktivität statisch zu machen (so dass es nicht Müll gesammelt wird). Nichts hat geklappt.

+0

Daten auf RawCallback ist Null, auch ohne Aufzeichnung. In den letzten 10 Jahren habe ich kein Gerät gesehen, das aussagekräftige Daten zu diesem Rückruf lieferte. Wie für jpegCallback, was macht Sie glauben, dass es funktionieren sollte? –

+0

@AlexCohn Warum sollte der jpegCallback nicht funktionieren? Habe ich einen Fehler gemacht? Mit der Android Stock Camera App kann ich während der Aufnahme Bilder machen, also glaube ich sollte es funktionieren ... – machinery

+0

Welches Gerät ist das? –

Antwort

4

Edit:

Mit der Klarstellung:

Die alte Kamera-API unterstützt Aufruf Takepicture(), während Video aufgezeichnet wird, wenn Camera.Parameters.isVideoSnapshotSupported Berichte wahr auf das Gerät Frage.

Halten Sie einfach an der gleichen Kamera-Instanz, die Sie in den MediaRecorder übergeben, und rufen Sie Camera.takePicture() darauf auf.

Camera2 unterstützt dies auch mit mehr Flexibilität, indem eine Sitzung mit Vorschau-, Aufzeichnungs- und JPEG-Ausgaben gleichzeitig erstellt wird.

Ursprüngliche Antwort:

Wenn Sie Bilder mit der Kamera zurück bedeuten nehmen, während sie mit der Frontkamera Aufnahme - das ist geräteabhängig. Einige Geräte verfügen über genügend Hardwareressourcen, um mehrere Kameras gleichzeitig ausführen zu können, die meisten jedoch nicht (sie teilen sich die Verarbeitungshardware zwischen den beiden Kameras).

Die einzige Möglichkeit festzustellen, ob mehrere Kameras gleichzeitig verwendet werden können, ist das Öffnen einer zweiten Kamera, wenn diese bereits geöffnet ist. Wenn es funktioniert, solltest du gut gehen; Wenn nicht, unterstützt dieses Gerät nicht mehrere Kameras gleichzeitig.

+0

Ich möchte Video von der Frontkamera aufnehmen und gleichzeitig ein Bild von der Frontkamera aufnehmen. – machinery

+0

Ich habe eine Änderung an meinem ursprünglichen Beitrag vorgenommen. Die Verwendung von Camera.takePicture() funktionierte nicht, obwohl mein Gerät während der Aufnahme Bilder aufnehmen könnte. – machinery

1

Nein, Sie können keine separaten Kamerainstanzen für Videoaufnahmen und Standbildaufnahmen öffnen. Die veraltete Kamera-API ist für solche Aufgaben nicht zuverlässig (siehe z. B. Android camera parameter IsVideoSnapshotSupported incorrectly set to false über Samsung S4).

Sie können camera2 API (auf Geräten, die diesen Modus unterstützen) verwenden, um verschiedene Formate und Auflösungen von derselben Kamera-Instanz zu erfassen. Hier ist ein Video-Tutorial: https://www.nigeapptuts.com/android-video-app-still-capture-recording/

+0

camera2 API klingt interessant. Wenn ich Sie richtig verstehe, kann ich eine Kamera-Instanz erstellen und dann diese Instanz verwenden, um sowohl Video von der vorderen Kamera aufzunehmen als auch gleichzeitig Bilder von der vorderen Kamera aufzunehmen. Könnten Sie ein Beispiel vorstellen, wie dies erreicht werden könnte? Das wäre sehr nett. – machinery

+0

https://www.nigeapptuts.com/android-video-app-still-capture-recording/ –

+0

Ich habe eine Bearbeitung zu meinem ursprünglichen Beitrag mit meinem neuen Ansatz gemacht. – machinery

Verwandte Themen