androidカメラにフラッシュを追加(s 5 pv 210)
7443 ワード
昨日はちょうどフラッシュを持ってきたので、今日は簡単にまとめました.大まかに言えば、具体的には私も深く研究していませんが、効果は確かにあります.
まずandroidが写真を撮るときに実行する関数コードを見つけます.
packages/apps/Camera/src/com/android/camera/Camera.java
この場所を見つけます.
device/samsung/proprietary/libcamera
ライブラリファイルはここにあります.次はSeccameraHWInterfaceに入ります.cppファイル検索takepictureは以下の通りです.
SecCameraでhでは、次の3つの関数インタフェースが見つかります.
SecCameraでcppには以下のようなものがあります.
カーネルの下にあるdrivers/media/video/
v4l2-ioctl.c次のコードがあります.
コードはdrivers/media/video/samsung/ficm/ov 2640である.c
この関数の最初の部分を見てみましょう
ov 2640_の変更s_ctrlは次のとおりです.
写真を撮る前にフラッシュの設定を加えて、これはライブラリに設定してもappに設定してもいいです.私は直接ライブラリに設定しました.パスは私は打っていません.前の関連関数はすべて与えられました.以下のようにします.
まずandroidが写真を撮るときに実行する関数コードを見つけます.
packages/apps/Camera/src/com/android/camera/Camera.java
この場所を見つけます.
mCameraDevice.setParameters(mParameters);
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,
mPostViewPictureCallback, new JpegPictureCallback(loc));
mPreviewing = false;
私の理解によると、ここは写真を撮るときに実行されます.ここでは呼び出したcameraライブラリのtakepictureの下にライブラリファイルを見つけます.device/samsung/proprietary/libcamera
ライブラリファイルはここにあります.次はSeccameraHWInterfaceに入ります.cppファイル検索takepictureは以下の通りです.
status_t CameraHardwareSec::takePicture()
{
LOGV("%s :", __func__);
stopPreview();
Mutex::Autolock lock(mStateLock);
if (mCaptureInProgress) {
LOGE("%s : capture already in progress", __func__);
return INVALID_OPERATION;
}
if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
LOGE("%s : couldn't run picture thread", __func__);
return INVALID_OPERATION;
}
mCaptureInProgress = true;
return NO_ERROR;
}
の中のmPictureThread->runは写真を撮るもので、具体的には分析しません.次にフラッシュのインタフェースを探しますSecCameraでhでは、次の3つの関数インタフェースが見つかります.
bool getFlashSupport(void);
int setFlashMode(int flash_mode);
int getFlashMode(void);
フラッシュを設定するためのsetFlashModeインタフェースで、この関数を見つけます.SecCameraでcppには以下のようなものがあります.
int SecCamera::setFlashMode(int flash_mode)
{
LOGV("%s(flash_mode(%d))", __func__, flash_mode);
if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {
LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
return -1;
}
if (m_params->flash_mode != flash_mode) {
m_params->flash_mode = flash_mode;
if (m_flag_camera_start) {
if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {
LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);
return -1;
}
}
}
return 0;
}
ここでfimcが呼び出されます.v4l2_s_ctrl関数コードは次のとおりです.static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value)
{
struct v4l2_control ctrl;
int ret;
ctrl.id = id;
ctrl.value = value;
//LOGD("%s :--------------------------value is %d",__func__,value);//add dao
ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl);
if (ret < 0) {
LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d
",
__func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);
return ret;
}
return ctrl.value;
}
ここでioctlを行いました.次にカーネルの中に行ってみましょう.カーネルの下にあるdrivers/media/video/
v4l2-ioctl.c次のコードがあります.
case VIDIOC_S_CTRL:
{
struct v4l2_control *p = arg;
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
break;
dbgarg(cmd, "id=0x%x, value=%d
", p->id, p->value);
if (ops->vidioc_s_ctrl) {
ret = ops->vidioc_s_ctrl(file, fh, p);
break;
}
if (!ops->vidioc_s_ext_ctrls)
break;
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
ctrls.count = 1;
ctrls.controls = &ctrl;
ctrl.id = p->id;
ctrl.value = p->value;
if (check_ext_ctrls(&ctrls, 1))
ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
break;
}
すぐにカメラドライブにこのような設定があることを思い出しました.コードはdrivers/media/video/samsung/ficm/ov 2640である.c
static const struct v4l2_subdev_core_ops ov2640_core_ops = {
.init = ov2640_init, /* initializing API */
.s_config = ov2640_s_config, /* Fetch platform data */
.queryctrl = ov2640_queryctrl,
.querymenu = ov2640_querymenu,
.g_ctrl = ov2640_g_ctrl,
.s_ctrl = ov2640_s_ctrl,
};
ここにs_がありますctrl、事実はov 2640を実行したことを証明した.s_ctrlがどのように呼び出されたのかについては深く研究されていない.この関数の最初の部分を見てみましょう
static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_state *state = to_state(sd);
int err = 0;
int value = ctrl->value;
switch (ctrl->id) {
case V4L2_CID_CAMERA_FLASH_MODE:
case V4L2_CID_CAMERA_BRIGHTNESS:
break;
最初はフラッシュのオプションで、ファイルシステムにフラッシュを設定したのはこれが入ってきたのですが、何の処理もせずに飛び出しました.次にフラッシュ駆動を増やします.static int flash_ctrl(int mode)
{
int err;
err = gpio_request(S5PV210_GPD0(2), "GPD0"); //power
if (err) {
printk(KERN_ERR "failed to request GPD0 for "
"flashlight power control
");
return err;
}
gpio_direction_output(S5PV210_GPD0(2), 1);
err = gpio_request(S5PV210_GPD0(3), "GPD0"); //mode
if (err) {
printk(KERN_ERR "failed to request GPD0 for "
"flashlight mode control
");
return err;
}
/*
high is flash mode,low is torch mode
*/
switch(mode) {
case FLASH_MODE_ON:
gpio_direction_output(S5PV210_GPD0(3), 1);
break;
case FLASH_MODE_TORCH:
gpio_direction_output(S5PV210_GPD0(3), 0);
break;
default:
break;
}
mdelay(100);
gpio_direction_output(S5PV210_GPD0(2), 0);
gpio_free(S5PV210_GPD0(2));
gpio_free(S5PV210_GPD0(3));
return err;
}
回路は出さないで、流れがはっきりして、みんなはよくしました.ov 2640_の変更s_ctrlは次のとおりです.
case V4L2_CID_CAMERA_FLASH_MODE:
err = flash_ctrl(value);
break;
関連設定のみが変更され、その他は変更されません.今インタフェースはすべて書き終わって、ファイルシステムを見ています.写真を撮る前にフラッシュの設定を加えて、これはライブラリに設定してもappに設定してもいいです.私は直接ライブラリに設定しました.パスは私は打っていません.前の関連関数はすべて与えられました.以下のようにします.
status_t CameraHardwareSec::takePicture()
{
LOGV("%s :", __func__);
stopPreview();
Mutex::Autolock lock(mStateLock);
if (mCaptureInProgress) {
LOGE("%s : capture already in progress", __func__);
return INVALID_OPERATION;
}
mSecCamera->setFlashMode(FLASH_MODE_ON);//add by dao
if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
LOGE("%s : couldn't run picture thread", __func__);
return INVALID_OPERATION;
}
mCaptureInProgress = true;
return NO_ERROR;
}
写真を撮る前にFlashModeをFLASHに設定MODE_ONモード、結果はこのように駄目なことを発見して、半日やってやっと問題の所在を発見して、直接setFlashModeを以下のように変更します:int SecCamera::setFlashMode(int flash_mode)
{
LOGV("%s(flash_mode(%d))", __func__, flash_mode);
fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode);
/*
if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {
LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
return -1;
}
if (m_params->flash_mode != flash_mode) {
m_params->flash_mode = flash_mode;
if (m_flag_camera_start) {
if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {
LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);
return -1;
}
}
}
*/
return 0;
}
ライブラリとカーネルを再コンパイルし、ダウンロードした結果、テストに成功しました.