2012-07-24 137 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); 

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

我不知道它实际上是有可能做到这一点,因为我不是最好的,在Java的黑客,但这里是我知道的:

  • Camera.unlock()是土生土长的方法,所以我不能真正看到它锁定我的方式背后的机制
  • Camera.Parameter有一个包含其所有参数的HashMap
  • Camera.setParameters(Parameters)接受HashMap,将其转换为字符串,并将其传递给本地方法
  • 我可以消除所有参数,但从HashMap中的割炬模式和相机仍然会接受它

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

编辑:

检查本机代码后,我可以看到,在我的CameraService.cpp到Camera.setParameters电话(参数)被拒绝,因为我的进程ID与摄像机服务记录的进程ID不匹配。所以看起来这是我的障碍。

EDIT2:

这样看来,所述MediaPlayerService是主服务,拍摄摄像机的控制当视频正在记录。我不知道这是否可行,但如果我可以在我自己的过程中以某种方式启动该服务,我应该可以跳过Camera.unlock()调用。

EDIT3:

最后一个选择是,如果我可以某种方式得到的指针CameraHardwareInterface。从外观上看,这是一个设备特定的接口,可能不包含PID检查。这个问题的主要问题是唯一可以找到它的指针位于CameraService中,并且CameraService不在说话。

Edit4:(几个月后)

在这一点上,我不认为这是可以做到什么,我本来想。我不想删除有人会回答的问题,但我不积极寻求答案。 (虽然接收到有效的答案会很棒。)

+1

我真的不明白为什么你会认为这是可能的。我希望视频录制可以完全控制摄像机。这需要特殊的编码才能让其他东西同时控制相机。 – 2012-10-16 01:08:40

+1

我完全同意,在这一点上我不认为这是可能的,但我现在只是在这个问题上离开这个问题,而不会有人奇迹般地找到方法。 – thepenguin77 2012-11-03 01:27:07

回答

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版本4.1.2的三星Galaxy S3上测试的。希望这种方法有帮助。

+0

我目前没有时间尝试这一点。但为什么这个工作?看起来,如果您当前正在录制,flash()将不会锁定相机,并且由于它已被解锁,camera.setParameters()将失败。并感谢成为第一个真正回答问题的人。 – thepenguin77 2013-02-14 04:02:27

+0

我在这里没有深入的了解,但我认为录音机会在调用start()和stop()之间获得一个独占锁。所以在这段时间内,其他进程对此资源的访问被拒绝,除了记录发生的ui主线程以外,并且由于它也处理ui动作调用,所以此方法应该工作得很好。 – fje 2013-02-14 21:29:14

+0

哦,所以只有UI线程才能改变flash状态? – thepenguin77 2013-02-15 02:08:40

-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 2012-09-04 05:22:59

+0

这不回答这个问题。问题是如何在录制视频时打开闪光灯。 – kunal18 2015-01-20 10:40:53

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

好的,首先,这并不能回答我的问题,而且有很多无用信息。 其次,它是从这里直接复制/粘贴: http://torch.googlecode.com/svn/trunk/src/com/colinmcdonough/android/torch/Torch.java – thepenguin77 2012-12-16 22:48:04

1

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