2012-07-24 12 views
26

Androidデバイスでカメラのフラッシュを制御する方法が必要です。ストロボライトアプリを作っていて、ストロボを点滅させてビデオを撮ると、ファンブレードのように高速で動いているオブジェクトを記録することができます。ビデオの録画中にカメラのフラッシュを有効にする

フラッシュは、ビデオプレビューを開始し、カメラのパラメータでFLASH_MODE_TORCHを設定することによってのみ有効にすることができます。これは次のようになります:

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

プレビューが開始されたら、そのパラメータを前後に移動してライトをオンまたはオフにすることができます。これはビデオを録画しようとするまでうまく動作します。問題は、カメラをMediaRecorderに渡すために、私はまずそれをロック解除する必要があるということです。

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

ロックが解除された後、カメラのパラメータを変更できなくなり、フラッシュの状態を変更することができなくなりました。

  • Camera.unlockを()ネイティブです:

    私がせいぜいここJavaは、ハッキングが、いないよので、これを実行することが実際に可能であるならば、私は知らないが、私が知っているものですこの方法は、私は本当にそれが出て私をロック方法の背後にあるメカニズムを見ることはできません

  • Camera.Parameterは、そのパラメータ
  • Camera.setParameters(パラメータ)の全てが含まれているHashMapを取るHashMapを持っているに変換文字列に変換し、それをネイティブメソッドに渡します。
  • HashMapからTORCH-MODEを選択すると、カメラは引き続きそれを受け入れます。

私はまだカメラにアクセスできますが、私はそれを聞くことはできません。 (どのCamera.unlockの目的(の一種である))

編集:

ネイティブコードを調べた後、私はCamera.setParametersにCameraService.cpp私の呼び出し(パラメータ)であるため拒否され得ることを見ることができます私のプロセスIDは、カメラサービスが記録しているプロセスIDと一致しません。だから、それが私のハードルだと思われます。

EDIT2:

MediaPlayerServiceは、ビデオが録画されたときに、カメラの制御を取る主要サービスであるように思われます。私はそれが可能かどうかは分かりませんが、自分のプロセスで何とかそのサービスを開始できたら、Camera.unlock()呼び出しをスキップすることができます。

EDIT3:私は何とかCameraHardwareInterfaceへのポインタを取得することができれば

一つの最後のオプションは次のようになります。その外観から見ると、これはデバイス固有のインターフェイスであり、おそらくPIDチェックは含まれていません。しかし、この主な問題は、私がそれへのポインタを見つけることができる唯一の場所はCameraServiceであり、CameraServiceは話していないということです。

Edit4:(数ヶ月後に)

この時点で、私は私が最初に望んで行うことが可能ですとは思いません。私は、誰かがそれに答える機会を逃して質問を削除したくないのですが、私は積極的に答えを求めていません。 (ただし、有効な回答を受信することは素晴らしいだろう。)

+1

これが可能だと思われる理由は本当にわかりません。私はビデオ録画がカメラの完全な制御を取ると思います。それは、他の何かがカメラを同時に制御できるようにするために特別なコーディングを必要とするでしょう。 –

+1

私は完全に同意します、私はそれが可能であるとは思わない、どちらかといえば、誰かが奇跡的に方法を見つけるオフチャンスでこの時点で質問をここに残しているだけです。 – thepenguin77

答えて

10

これを試してみてください、私は同様の問題に遭遇しました。ユーザーは、光の状況に応じてニーズに合わせて記録中にフラッシュモードを変更することができます。私は以下のソリューションに来たいくつかの調査研究の後:

私はあなたがすでに適切なSurfaceViewとその必要なコールバックとSurfaceHolderを設定したことを、前提としています。私が行った最初の事は(宣言されていない変数はグローバルです)このコードを提供していた。

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(); 
    }  
} 
私の次のステップは、レコーダーを初期化し、準備していた

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(); 
    } 
} 

それは注意することが重要です、そのcamera.unlockを()は、メディアレコーダーの初期化処理全体の前に呼び出されなければなりません。それはまた、各setプロパティの適切な順序を認識していなければなりません。そうしないと、prepare()またはstart()を呼び出すときにIllegalStateExceptionが発生します。録音に関しては、私はこれを行います。これは通常、ビュー要素によってトリガーされます。

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

     //TODO: do stuff.... 

     recording = false; 
    } else { 
     recording = true; 

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

これで、最終的に正しく記録できます。しかし、そのフラッシュは何ですか?最後になりましたが、ここでの舞台裏魔法が来る:

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(); 
    } 
} 

毎回は私がしても、記録時に、フラッシュモードを変更することができるのonClickアクションを経由してそのメソッドを呼び出します。カメラを適切にロックするだけです。録音中にメディアレコーダーがロックを取得すると、カメラのロック/アンロックを再度行う必要はありません。それは動作しません。これはAndroid-Version 4.1.2のSamsung Galaxy S3でテストされました。このアプローチが役立つことを願っています。

+0

私は現在、試す時間がありませんこれはアウト。しかし、なぜこれは機能しますか?現在録画中の場合、flash()はカメラをロックせず、既にロックが解除されているので、camera.setParameters()は失敗します。実際に質問に答えた最初の人に感謝します。 – thepenguin77

+0

私はここで深い洞察を持っていませんが、私は、レコーダーがstart()とstop()の間で排他ロックを取得すると仮定します。したがって、このリソースへの他のプロセスへのアクセスは、その間に拒否されます。ただし、記録が行われるメインスレッド以外は、uiアクションコールも処理されるため、このアプローチはうまくいくはずです。 – fje

+0

ああ、UIスレッドだけがフラッシュ状態を変更することができますか? – thepenguin77

-2

は、デバイスのカメラにアクセスするには、AndroidマニフェストでCAMERA許可を宣言する必要があります。また、アプリケーションによって使用されるカメラ機能を宣言するには、<uses-feature>マニフェスト要素を必ず含めるようにしてください。あなたがカメラやオートフォーカス機能、あなたのマニフェストを使用している場合たとえば、次を含める必要があります。

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

トーチのサポートをチェックするサンプルは次のようなものになります。オンにするに

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

をあなたは、単にトーチをオフにするには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); 

カメラパラメータを設定上のトーチは、Camera.Parameters.FLASH_MODE_OFF

を設定しました
+1

これはまったく役に立たない。私はフラッシュをオンにする方法を知っている、ビデオが記録している間、問題はフラッシュを切り替えることです。 – thepenguin77

+0

これは質問に答えません。質問は、ビデオの録画中にフラッシュをオンにする方法です。 – kunal18

0

...うまくいけば、それは動作します。.. :)

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

まず最初に、これは私の質問に全く答えず、無用な情報がたくさんあります。 第2に、ここから直接コピー/貼り付けされています: http://torch.googlecode.com/svn/trunk/src/com/colinmcdonough/android/torch/Torch.java – thepenguin77

1

メディアレコーダー、使用camera.lock()、その後、あなたがカメラに設定したいものは何でもパラメータ設定を準備した後。 録画を開始する前に、camera.unlock()を呼び出す必要があります。メディアレコーダーを停止した後で、camera.lock()を呼び出してプレビューを開始する必要があります。 お楽しみください!

関連する問題