29

ビデオの録画中に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);

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

私はJavaハッキングが得意ではないので、これが実際に可能かどうかはわかりませんが、私が知っていることは次のとおりです。

  • Camera.unlock()はネイティブメソッドであるため、ロックアウトの背後にあるメカニズムを実際に確認することはできません。
  • Camera.Parameterには、すべてのパラメーターを含むHashMapがあります
  • Camera.setParameters(Parameters)は、HashMapを取得して文字列に変換し、ネイティブメソッドに渡します。
  • すべてのパラメーターを削除できますが、HashMapからTORCH-MODEを使用すると、カメラは引き続きそれを受け入れます。

だから、私はまだカメラにアクセスできますが、私が言ったことは何も聞きません。(これはCamera.unlock()の目的の一種です)

編集:

ネイティブコードを調べたところ、CameraService.cppで、カメラサービスが記録しているプロセスIDとプロセスIDが一致しないため、Camera.setParameters(Parameters)への呼び出しが拒否されていることがわかります。ですから、それが私のハードルのように見えます。

Edit2:

MediaPlayerServiceは、ビデオの録画時にカメラを制御する主要なサービスであるように見えます。可能かどうかはわかりませんが、どういうわけか自分のプロセスでそのサービスを開始できれば、Camera.unlock()呼び出しをスキップできるはずです。

Edit3:

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

Edit4 :(数か月後)

現時点では、本来やりたかったことはできないと思います。誰かが答えるという偶然の機会に質問を削除したくありませんが、私は積極的に答えを求めていません。(ただし、有効な回答を受け取るのは素晴らしいことです。)

4

4 に答える 4

15

同様の問題が発生しました。ユーザーは、光の状況に応じてニーズに合わせて、録画中にフラッシュモードを変更できる必要があります。いくつかの調査研究の後、私は次の解決策に到達しました:

適切な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バージョン4.1.2を搭載したSamsungGalaxyS3でテストされました。このアプローチがお役に立てば幸いです。

于 2013-02-13T14:22:21.310 に答える
1

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

于 2015-03-05T11:18:24.097 に答える
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");
      }
于 2012-11-28T06:49:59.533 に答える
-3

デバイスのカメラにアクセスするには、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

于 2012-09-03T17:49:00.283 に答える