Most 3rd party camera applications relies on DirectShow to control the camera. However, on some devices, DirectShow doesn't expose the full camera capabilities. For example, on a Dopod 838Pro, DirectShow only allows recording up to 176x144 7.5fps while the built-in camera can do much better. Further investigation shows that the built-in camera app (and some 3rd party apps such as CoolCamera) do not use DirectShow but instead relies on a proprietary camera API to control the camera. This API exposes the full capabilities of the camera. This web page lists which devices expose usable camera modes via DirectShow and those which cause problems.
On a Dopod 838Pro device, the camera API is hidden in \Windows\HTCCamera1.dll. Calling several functions inside this dll could turn on the camera and the flashlight. However, getting the camera to work properly without proper API documentation seems to be an impossible task. Attempt was made to reverse engineering the HTCCamera1.dll and CoolCamera using Interactive Disassembler (IDA). However, it was not clear from the disassembly how the camera raw frame buffer was retrieved. The part of the code which retrieves the camera data has probably been obfuscated.
The following code shows how to init the camera, turn on the flashlight and then turn it off:
test = 1
result = Camera_Init(test)
test = 0
result = Camera_Begin(test)
result = Camera_FlashLight(CameraPropertyState.STATE_ON)
MessageBox.Show("Flashligh ON. Click OK to turn off.")
result = Camera_FlashLight(CameraPropertyState.STATE_OFF)
result = Camera_Deinit()
<DllImport("HTCCamera1.dll")> _
Private Shared Function Camera_Init(ByRef input As Int32) As Boolean
End Function
<DllImport("HTCCamera1.dll")> _
Private Shared Function Camera_Begin(ByRef input As Int32) As Boolean
End Function
<DllImport("HTCCamera1.dll")> _
Private Shared Function Camera_End(ByRef input As Int32) As Boolean
End Function
Enum CameraPropertyState As Integer
STATE_ON = 1
STATE_OFF = 2
End Enum
<DllImport("HTCCamera1.dll")> _
Private Shared Function Camera_FlashLight(ByVal state As CameraPropertyState) As Boolean
End Function
<DllImport("HTCCamera1.dll")> _
Private Shared Function Camera_Deinit() As Boolean
End Function
Another way to control the flashlight is to use DeviceIOControl. This does not rely on HTCCamera1.dll but is still device-specific
DWORD dwDIOC=0x90002024; //device io (device specific)
int Mode_int = 1;
DeviceIoControl(hCam, dwDIOC, LPVOID(&Mode_int), sizeof(Mode_int), 0, NULL, NULL, NULL);
MessageBox(GetActiveWindow(), L"OK to turn off", L"Flash Light", MB_OK);
Mode_int = 2;
DeviceIoControl(hCam, dwDIOC, LPVOID(&Mode_int), sizeof(Mode_int), 0, NULL, NULL, NULL);
Thanks for your post. Using this article and some other resources online I was able to create this simple but functional VB.NET class. I hope it helps some one out there. For more code and .NET Stuff visit www.eKoshka.com
ReplyDelete------------------------------------------------
Imports System.Runtime.InteropServices
Public Class CameraControl
' Nested Types
Public Enum FlashModes As Integer
[On] = 1
Off = 2
End Enum
Public Enum FlashLightCommands As Integer
DisableNormal = 2
EnableBright = 3
EnableNormal = 1
ResetBright = 4
End Enum
Private enmFlashMode As FlashModes = FlashModes.Off
Private blnCameraIsInitialized As Boolean = False
' Methods
Public Sub New()
'Me.Initialize()
End Sub
Protected Overrides Sub Finalize()
Me.Deinitialize()
MyBase.Finalize()
End Sub
Public Sub Initialize()
' check if camera is available
Dim num As UInteger = 1
Dim num2 As UInteger = 0
Dim num3 As Integer = 0
Try
' try to initialize camera
num3 = CameraControl.Camera_Init(num, num2)
Catch ex As Exception
MessageBox.Show("Error finding the DLL or the 'Camera_Deinit' entry point: " + ex.Message)
End Try
If num3 = 1 Then
blnCameraIsInitialized = True
Else
MessageBox.Show("Error initializing the camera, received error code: " + num3.ToString(), "Error")
End If
End Sub
Public Sub Deinitialize()
' deinitialize camera
If blnCameraIsInitialized Then
CameraControl.Camera_Deinit()
blnCameraIsInitialized = False
End If
End Sub
Public Property FlashMode() As FlashModes
Get
Return Me.enmFlashMode
End Get
Set(ByVal value As FlashModes)
Me.enmFlashMode = value
If blnCameraIsInitialized Then
If Me.enmFlashMode = FlashModes.On Then
Camera_FlashLight(FlashLightCommands.EnableNormal)
ElseIf Me.enmFlashMode = FlashModes.Off Then
Camera_FlashLight(FlashLightCommands.DisableNormal)
End If
End If
End Set
End Property
#Region "Win32 Wrapers"
_
Shared Function Camera_Init(ByVal param1 As Integer, ByRef param2 As Integer) As Integer
End Function
_
Shared Function Camera_Begin(ByRef input As Int32) As Integer
End Function
_
Shared Function Camera_End(ByRef input As Int32) As Integer
End Function
_
Private Shared Function Camera_FlashLight(ByVal state As FlashLightCommands) As Integer
End Function
_
Shared Function Camera_Deinit() As Integer
End Function
#End Region
End Class
------------------------------------------------
Thanks for your comment. This is the first comment ever on my blog :) I believe your camera class will help other readers as well.
ReplyDeleteOn a side note, your DllImport declarations are not displayed properly, probably because of a bug in blogspot (see http://minhdanh2002.blogspot.com/2009/05/inconveniences-while-posting-to-blogger.html) that handles the 'less than sign' incorrectly.
It's OK. People can see this post correctly on my blog at http://ekoshka.com/?p=144
ReplyDelete