录制video时启用相机闪光灯

在录制video时,我需要一种方法来控制Android设备上的相机闪光灯。 我正在制作闪光灯应用程序,使用闪烁的闪光灯拍摄video会导致logging高速移动的物体(如风扇叶片)。

只能通过启动video预览并在相机参数中设置FLASH_MODE_TORCH来启用闪光灯。 这看起来像这样:

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

一旦预览开始,我可以来回翻转该参数来打开和closures灯光。 这很好,直到我试图录制video。 麻烦的是,为了把相机给MediaRecorder,我首先必须解锁它。

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

解锁后,我不能再改变摄像机参数,因此无法改变闪光灯状态。

我不知道是否真的有可能做到这一点,因为我不是最好的Java黑客,但这是我所知道的:

  • Camera.unlock()是一个本地方法,所以我不能真正看到它locking我的方式背后的机制
  • Camera.Parameter有一个包含其所有参数的HashMap
  • Camera.setParameters(Parameters)接受HashMap,将其转换为string,并将其传递给本地方法
  • 我可以从HashMap中除掉TORCH-MODE的所有参数,相机仍然可以接受

所以,我仍然可以访问相机,但它不会听我讲的任何东西。 (这是Camera.unlock()的目的)

编辑:

检查本机代码后,我可以看到在CameraService.cpp中,我对Camera.setParameters(Parameters)的调用被拒绝,因为我的进程ID与摄像机服务logging的进程ID不匹配。 所以这似乎是我的障碍。

EDIT2:

看起来, MediaPlayerService是在录制video时控制相机的主要服务。 我不知道是否有可能,但如果我可以在我自己的过程中以某种方式启动该服务,我应该可以跳过Camera.unlock()调用。

EDIT3:

最后一个选项是,如果我能以某种方式得到一个指向CameraHardwareInterface的指针。 从外观来看,这是一个设备特定的接口,可能不包括PID检查。 但是,这个问题的主要问题是我唯一可以find指针的地方是在CameraService中,CameraService不在说话。

编辑4 :(几个月后)

在这一点上,我不认为有可能做我原本想做的事情。 我不想删除这个问题,因为有人会回答这个问题,但我并不积极地寻求答案。 (虽然,收到一个有效的答案将是真棒。)

Solutions Collecting From Web of "录制video时启用相机闪光灯"

我遇到了类似的问题。 用户应该能够在logging期间改变闪光模式以根据光线情况来满足他们的需要。 经过一些调查研究,我得出了以下解决scheme:

我假设你已经用适当的callback设置了一个合适的SurfaceView和SurfaceHolder。 我做的第一件事是提供这个代码(没有声明的variables是全局variables):

 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()必须在媒体logging器的整个初始化过程之前被调用。 这也说明了每个set属性的正确顺序,否则在调用prepare()或start()时会得到一个IllegalStateExceptionexception。 谈到录音,我这样做。 这通常会由一个视图元素触发:

 public void record(View view) { if (recording) { recorder.stop(); //TODO: do stuff.... recording = false; } else { recording = true; initialize(); recorder.start(); } } 

所以现在,我终于可以正确logging。 但是闪光灯是什么? 最后但并非最不重要的是幕后的魔术:

 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操作调用该方法时,即使在录制过程中,我也可以更改闪光灯模式。 只要照顾妥善locking相机。 录制过程中,媒体录制器locking后,您不必再次locking/解锁相机。 它甚至不工作。 这是在Android版本4.1.2的三星Galaxy S3上testing的。 希望这种方法有帮助。

准备媒体logging器后,使用camera.lock(),然后设置任何你想要设置到相机的参数。 但在开始录制之前,您需要调用camera.unlock(),并且在停止媒体录制器之后,您需要调用camera.lock()以开始预览。 请享用!!!

试试这个..希望它会工作.. 🙂

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

要访问设备相机,您必须在Android清单中声明CAMERA权限。 还要确保包含<uses-feature> manifest元素来声明应用程序使用的相机function。 例如,如果您使用相机和自动对焦function,则清单应包含以下内容:

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

要closures手电筒,请设置Camera.Parameters.FLASH_MODE_OFF