2012-07-24 16 views
26

Potrzebuję sposobu sterowania lampą aparatu na urządzeniu z Androidem podczas nagrywania wideo. Robię aplikację stroboskopową, a robienie filmów z błyskającym światłem stroboskopowym umożliwiłoby rejestrowanie obiektów poruszających się z dużą prędkością, takich jak łopatki wentylatora.Włączanie lampy błyskowej podczas nagrywania wideo

Lampa błyskowa może być włączona tylko poprzez uruchomienie podglądu wideo i ustawienie FLASH_MODE_TORCH w parametrach kamery. To wyglądałoby tak:

Camera c = Camera.open(); 
Camera.Parameters p = c.getParameters(); 
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); 
c.setParameters(p); 
c.startPreview(); 

Po uruchomieniu podglądu mogę przełączyć ten parametr w tę iz powrotem, aby włączyć i wyłączyć światło. Działa to dobrze, dopóki nie spróbuję nagrać wideo. Problem polega na tym, że aby przekazać aparat do MediaRecorder, najpierw muszę go odblokować.

MediaRecorder m = new MediaRecorder(); 
c.unlock();  // the killer 
m.setCamera(c); 

Po tym odblokowaniu nie mogę już zmienić parametrów kamery i dlatego nie można zmienić stanu lampy błyskowej.

ja nie wiem, czy to jest rzeczywiście możliwe, aby to zrobić, ponieważ nie jestem najlepszy w java-hacking, ale tutaj jest to, co ja wiem:

  • Camera.unlock() jest rodowitym metoda, więc nie mogę naprawdę zobaczyć mechanizm tył sposób blokuje mnie
  • Camera.Parameter ma HashMap, który zawiera wszystkie jego parametry
  • Camera.setParameters (parametry) wykonuje HashMap, konwertuje go do ciąg i przekazuje go natywnej metodzie
  • Mogę wyeliminować wszystkie parametry, ale TORCH-MODE z HashMap i aparatu fotograficznego nadal będzie go akceptować.

Tak więc nadal mogę uzyskać dostęp do kamery, ale nie będzie ona niczego słyszała. (Co jest raczej w celu Camera.unlock())

Edit:

Po zbadaniu kodu macierzystego, widzę, że w CameraService.cpp moje rozmowy do Camera.setParameters (parametry) się odrzucony, ponieważ mój identyfikator procesu nie jest zgodny z identyfikatorem procesu, który zarejestrowała usługa aparatu fotograficznego. Wygląda więc na to, że to moja przeszkoda.

Edit2:

Wydaje się, że MediaPlayerService jest podstawową usługą, która przejmuje kontrolę aparatu podczas nagrywania wideo. Nie wiem, czy to możliwe, ale gdybym mógł jakoś uruchomić tę usługę w moim własnym procesie, powinienem móc pominąć wywołanie Camera.unlock().

Edit3:

Ostatnią opcją byłoby, gdybym mógł jakoś wskaźnik do CameraHardwareInterface. Wygląda na to, że jest to interfejs specyficzny dla urządzenia i prawdopodobnie nie obejmuje sprawdzania PID. Głównym problemem jest to, że jedynym miejscem, w którym mogę znaleźć wskaźnik, jest CameraService, a CameraService nie mówi.

Edit4: (kilka miesięcy później)

W tym momencie, nie sądzę, że jest możliwe, aby zrobić to, co początkowo chciał. Nie chcę usuwać pytania z wykluczonej szansy, że ktoś na nie odpowie, ale nie szukam odpowiedzi. (Chociaż otrzymanie prawidłowej odpowiedzi byłoby niesamowite.)

+1

Naprawdę nie rozumiem, dlaczego uważasz, że to możliwe. Spodziewam się, że nagrywanie wideo będzie miało pełną kontrolę nad aparatem. Wymagałoby to specjalnego kodowania, aby umożliwić innym sterowanie kamerą w tym samym czasie. –

+1

Całkowicie się zgadzam, nie sądzę, że w tej chwili jest to możliwe, po prostu pozostawiam pytanie tutaj na tym punkcie, że ktoś nieoczekiwanie znalazł sposób. – thepenguin77

Odpowiedz

10

I napotkał podobny problem. Użytkownik powinien mieć możliwość zmiany trybu błysku podczas nagrywania, aby spełnić ich wymagania w zależności od oświetlenia. Po przeprowadzeniu kilku badań dochodzę do następującego rozwiązania:

Zakładam, że już skonfigurowałeś odpowiedni SurfaceView i SurfaceHolder z wymaganymi callbackami. Pierwszą rzeczą, jaką zrobiłem było dostarczenie tego kodu (nie zadeklarowane zmienne są globalne):

public void surfaceCreated(SurfaceHolder holder) { 
    try { 
     camera = Camera.open(); 

     parameters = camera.getParameters(); 
     parameters.setFlashMode(Parameters.FLASH_MODE_OFF); 

     camera.setParameters(parameters); 
     camera.setPreviewDisplay(holder); 
     camera.startPreview(); 

     recorder = new MediaRecorder(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    }  
} 

Moim następnym krokiem było inicjowanie i przygotowywanie dyktafonu:

private void initialize() { 
    camera.unlock(); 

    recorder.setCamera(camera); 
    recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 
    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
    recorder.setVideoFrameRate(20); 
    recorder.setOutputFile(filePath); 

    try { 
     recorder.prepare(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
     finish(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     finish(); 
    } 
} 

ważne jest, aby pamiętać, że camera.unlock() musi być wywołany PRZED całym procesem inicjowania rekordera multimedialnego. Powiedział również, że należy pamiętać o właściwej kolejności każdej ustawionej właściwości, w przeciwnym razie otrzymasz wyjątek IllegalStateException podczas wywoływania metody prepare() lub start(). Jeśli chodzi o nagrywanie, robię to. Zazwyczaj jest to wywoływane przez element widoku:

public void record(View view) { 
    if (recording) { 
     recorder.stop(); 

     //TODO: do stuff.... 

     recording = false; 
    } else { 
     recording = true; 

     initialize(); 
     recorder.start(); 
    } 
} 

Teraz mogę w końcu prawidłowo nagrywać. Ale co to za błysk? Last but not least, tu pojawia się magia za kulisami:

public void flash(View view) { 
    if(!recording) { 
     camera.lock(); 
    } 

    parameters.setFlashMode(parameters.getFlashMode().equals(Parameters.FLASH_MODE_TORCH) ? Parameters.FLASH_MODE_OFF : Parameters.FLASH_MODE_TORCH); 
    camera.setParameters(parameters); 

    if(!recording) { 
     camera.unlock(); 
    } 
} 

Everytime I wywołanie tej metody poprzez działania onClick mogę zmienić tryb lampy błyskowej, nawet podczas nagrywania. Po prostu zadbaj o odpowiednie zamknięcie kamery. Po zapisaniu blokady przez nagrywarkę podczas nagrywania, nie musisz ponownie blokować/odblokowywać aparatu. To nawet nie działa. Zostało to przetestowane na Samsung Galaxy S3 z Androidem w wersji 4.1.2. Mam nadzieję, że to podejście pomaga.

+0

Obecnie nie mam czasu, aby wypróbować to na zewnątrz. Ale dlaczego to działa? Wygląda na to, że jeśli aktualnie nagrywasz, flash() nie zablokuje kamery, a ponieważ została już odblokowana, kamera camera.setParameters() zawiedzie. I dziękuję, że jesteś pierwszą osobą, która naprawdę odpowiada na pytanie. – thepenguin77

+0

Nie mam tutaj głębokiego wglądu, ale zakładam, że rejestrator uzyskuje wyłączny blokadę między wywołaniami() i stop(). Tak więc dostęp do innych procesów dla tego źródła zasobów jest zabroniony w tym czasie, z wyjątkiem głównego wątku interfejsu użytkownika, w którym odbywa się nagrywanie, a ponieważ obsługuje on również wywołania akcji ui, to podejście powinno działać dobrze. – fje

+0

Och, więc tylko wątek UI może zmienić stan flasha? – thepenguin77

-2

Aby uzyskać dostęp do kamery urządzenia, musisz zadeklarować uprawnienie CAMERA w swoim Manifestu Android. Pamiętaj również o włączeniu elementu manifestu <uses-feature>, aby zadeklarować funkcje kamery używane przez aplikację. Na przykład, w przypadku korzystania z funkcji aparatu i auto-focus, Twój Manifest powinien zawierać następujące elementy:

<uses-permission android:name="android.permission.CAMERA" /> 
<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" /> 

próbce, która sprawdza wsparcie palnika może wyglądać mniej więcej tak:

//Create camera and parameter objects 
private Camera mCamera; 
private Camera.Parameters mParameters; 
private boolean mbTorchEnabled = false; 

//... later in a click handler or other location, assuming that the mCamera object has already been instantiated with Camera.open() 
mParameters = mCamera.getParameters(); 

//Get supported flash modes 
List flashModes = mParameters.getSupportedFlashModes(); 

//Make sure that torch mode is supported 
//EDIT - wrong and dangerous to check for torch support this way 
//if(flashModes != null && flashModes.contains("torch")){ 
if(flashModes != null && flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)){ 
    if(mbTorchEnabled){ 
     //Set the flash parameter to off 
     mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); 
    } 
    else{ 
     //Set the flash parameter to use the torch 
     mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); 
    } 

    //Commit the camera parameters 
    mCamera.setParameters(mParameters); 

    mbTorchEnabled = !mbTorchEnabled; 
} 

Aby włączyć palnik na, wystarczy ustawić parametr kamera Camera.Parameters.FLASH_MODE_TORCH

Camera mCamera; 
Camera.Parameters mParameters; 

//Get a reference to the camera/parameters 
mCamera = Camera.open(); 
mParameters = mCamera.getParameters(); 

//Set the torch parameter 
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); 

//Comit camera parameters 
mCamera.setParameters(mParameters); 

aby włączyć latarkę wyłączyć, ustawić Camera.Parameters.FLASH_MODE_OFF

+1

To naprawdę nie pomaga. Wiem, jak włączyć lampę błyskową, problem polega na przełączaniu lampy błyskowej podczas nagrywania wideo. – thepenguin77

+0

To nie odpowiada na pytanie. Pytanie brzmi, jak włączyć lampę błyskową podczas nagrywania wideo. – kunal18

0

Spróbuj .. mam nadzieję, że to będzie działać .. :)

private static Torch torch; 

      public Torch() { 
      super(); 
      torch = this; 
      } 

      public static Torch getTorch() { 
      return torch; 
      } 

      private void getCamera() { 
      if (mCamera == null) { 
       try { 
       mCamera = Camera.open(); 
       } catch (RuntimeException e) { 
       Log.e(TAG, "Camera.open() failed: " + e.getMessage()); 
       } 
      } 
      } 
     public void toggleLight(View view) { 
      toggleLight(); 
      } 

      private void toggleLight() { 
      if (lightOn) { 
       turnLightOff(); 
      } else { 
       turnLightOn(); 
      } 
      } 

      private void turnLightOn() { 
      if (!eulaAgreed) { 
       return; 
      } 
      if (mCamera == null) { 
       Toast.makeText(this, "Camera not found", Toast.LENGTH_LONG); 
        button.setBackgroundColor(COLOR_WHITE); 
       return; 
      } 
      lightOn = true; 
      Parameters parameters = mCamera.getParameters(); 
      if (parameters == null) { 
        button.setBackgroundColor(COLOR_WHITE); 
       return; 
     } 
      List<String> flashModes = parameters.getSupportedFlashModes(); 
       if (flashModes == null) { 
        button.setBackgroundColor(COLOR_WHITE); 
       return; 
      } 
      String flashMode = parameters.getFlashMode(); 
      Log.i(TAG, "Flash mode: " + flashMode); 
      Log.i(TAG, "Flash modes: " + flashModes); 
      if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) { 
        if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) { 
       parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); 
       mCamera.setParameters(parameters); 
       button.setBackgroundColor(COLOR_LIGHT); 
       startWakeLock(); 
       } else { 
       Toast.makeText(this, "Flash mode (torch) not supported", 
        Toast.LENGTH_LONG); 
         button.setBackgroundColor(COLOR_WHITE); 
       Log.e(TAG, "FLASH_MODE_TORCH not supported"); 
       } 
      } 
      } 
     private void turnLightOff() { 
      if (lightOn) { 
        button.setBackgroundColor(COLOR_DARK); 
       lightOn = false; 
       if (mCamera == null) { 
       return; 
       } 
       Parameters parameters = mCamera.getParameters(); 
       if (parameters == null) { 
       return; 
       } 
       List<String> flashModes = parameters.getSupportedFlashModes(); 
       String flashMode = parameters.getFlashMode(); 
        if (flashModes == null) { 
       return; 
       } 
       Log.i(TAG, "Flash mode: " + flashMode); 
       Log.i(TAG, "Flash modes: " + flashModes); 
       if (!Parameters.FLASH_MODE_OFF.equals(flashMode)) { 
         if (flashModes.contains(Parameters.FLASH_MODE_OFF)) { 
        parameters.setFlashMode(Parameters.FLASH_MODE_OFF); 
        mCamera.setParameters(parameters); 
        stopWakeLock(); 
       } else { 
        Log.e(TAG, "FLASH_MODE_OFF not supported"); 
       } 
       } 
      } 
      } 
    private void startPreview() { 
     if (!previewOn && mCamera != null) { 
      mCamera.startPreview(); 
      previewOn = true; 
     } 
     } 

     private void stopPreview() { 
     if (previewOn && mCamera != null) { 
      mCamera.stopPreview(); 
      previewOn = false; 
     } 
     } 

     private void startWakeLock() { 
     if (wakeLock == null) { 
      Log.d(TAG, "wakeLock is null, getting a new WakeLock"); 
      PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
      Log.d(TAG, "PowerManager acquired"); 
      wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG); 
      Log.d(TAG, "WakeLock set"); 
     } 
     wakeLock.acquire(); 
     Log.d(TAG, "WakeLock acquired"); 
     } 

     private void stopWakeLock() { 
     if (wakeLock != null) { 
      wakeLock.release(); 
      Log.d(TAG, "WakeLock released"); 
     } 
     } 
    @Override 
     public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (Eula.show(this)) { 
      eulaAgreed = true; 
     } 
     setContentView(R.layout.main); 
     button = findViewById(R.id.button); 
     surfaceView = (SurfaceView) this.findViewById(R.id.surfaceview); 
     surfaceHolder = surfaceView.getHolder(); 
     surfaceHolder.addCallback(this); 
     surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     disablePhoneSleep(); 
     Log.i(TAG, "onCreate"); 
     } 
+0

OK, więc przede wszystkim nie odpowiada to w ogóle na moje pytanie i ma wiele nieprzydatnych informacji. Po drugie, jest to bezpośrednia kopia/wklej tutaj: http://torch.googlecode.com/svn/trunk/src/com/colinmcdonough/android/torch/Torch.java – thepenguin77

1

Po przygotowaniu rejestratora multimedialnego użyj funkcji camera.lock(), a następnie ustaw dowolne parametry, które chcesz ustawić w kamerze. Ale przed rozpoczęciem nagrywania musisz zadzwonić do camera.unlock(), a po zatrzymaniu rejestratora musisz zadzwonić do camera.lock(), aby rozpocząć podgląd. Ciesz się !!!

Powiązane problemy