# カメラライブラリの使用方法 (overview)

ここでは、カメラライブラリを利用してカメラを使用する際に注意する点などを説明します。

## カメラ画像の取得方法について

カメラから撮影された画像は、新規DMAを使用して取得するようになっています。
そのため、カメラがキャプチャを行っている最中に他の部分でDMAを使用するなど、カメラが使用する新規DMAより優先度の高い AHBバスへのアクセスが存在すると、カメラ画像の転送が間に合わずバッファエラーが発生することがあるので、注意が必要です。
カメラのキャプチャを開始する手順は、一般的には以下のようになります。

1. `CAMERA_DmaRecvAsync()`でキャプチャ開始後に新規DMA転送が行われる準備をする。
2. `CAMERA_ClearBuffer()`でカメラ内部のバッファをクリアします。
3. `CAMERA_I2CActivate()`で内側カメラ、もしくは外側カメラを起動します。
4. `CAMERA_StartCapture()`、もしくは `CAMERA_Start()`でキャプチャを開始する

3. については、1. もしくは 2. の前のタイミングで呼び出しても問題ありません。
`CAMERA_DmaRecvAsync()`は全てのデータ（1フレームの画像）の転送が完了すると、 完了コールバックが呼ばれるので、そのコールバック関数内で次のフレームの画像を取得するため、同様に `CAMERA_DmaRecvAsync()`を呼び出す必要があります。

### 例

> `void CameraDmaRecvIntr(void* arg)
> {
> CAMERA_DmaRecvAsync(... CameraDmaRecvIntr, NULL);
> }
> ...
> CAMERA_DmaRecvAsync(... CameraDmaRecvIntr, NULL);
> CAMERA_ClearBuffer();
> CAMERA_StartCapture();
> `

カメラ画像の転送が間に合わずにバッファエラーが発生した場合は、`CAMERA_SetBufferErrorCallback()`で指定したコールバックが呼ばれることになります。
バッファエラーが発生した場合は、一度キャプチャと使用していた新規DMAを停止させた後に、再度キャプチャを開始するといった復帰処理が必要となります。

### 例

> `void CameraIntrError(CAMERAResult result)
> {
> CAMERA_StopCapture();
> MI_StopNDma(...);
> CAMERA_DmaRecvAsync(...);
> CAMERA_ClearBuffer();
> CAMERA_StartCapture();
> }
> ...
> CAMERA_SetBufferErrorCallback(CameraIntrError);
> `

## カメラ設定の変更について

カメラの設定関数は同時に一つしか呼び出せないようになっています。
そのため、カメラの設定関数の非同期版を連続で呼び出す等した場合には、二回目の関数呼び出しが失敗することになります。
また、カメラのキャプチャ中に使用することのできない設定関数が一部存在します。
具体的な関数名については、`CAMERA_IsBusy()`のリファレンスを参照してください。
例えば、カメラのVsync中にこれらの関数でパラメータを変更したい場合には、カメラのVSYNC割り込みコールバック内で
`CAMERA_StopCapture() -> CAMERA_SetXXX() -> CAMERA_StartCapture()`
の順で呼び出す必要があります。

## 解像度とトリミングの違いについて

例えば、`CAMERA_I2CSize()`に`CAMERA_SIZE_VGA`を 指定した上で、`CAMERA_SetTrimmingParamsCenter()`等で256x192に トリミングして取得した画像と、`CAMERA_I2CSize()`に `CAMERA_SIZE_DS_LCD`を指定して取得した画像は、得られる画像のサイズは同じなため 新規DMAで転送される量も同等となり、動作の重さに違いはありません。
しかし、トリミングしてサイズを縮小した画像とカメラ解像度を下げて縮小した画像では、画角(視野角)が違うため、 カメラ解像度が変えただけでは映る範囲は変わりませんが、トリミングした場合は映る範囲が狭まります。

## カメラの終了処理について

カメラの終了処理を行う順番、タイミングによっては、`CAMERA_StopCapture()`、 `CAMERA_I2Activate(CAMERA_SELECT_NONE)`を呼び出したにも関わらず、 `CAMERA_IsBusy()`が TRUE を返すようになります。
この状態になったとしても、内側カメラ、外側カメラどちらかを有効にすれば、 `CAMERA_IsBusy()`は FALSE を返すようになるため問題はありません。
確実に`CAMERA_IsBusy()`が FALSE を返すようにしたい場合は、 `CAMERA_StopCapture()`を呼び出した後に `CAMERA_IsBusy()`が FALSE を返すことを確認したうえで `CAMERA_I2CActivate(CAMERA_SELECT_NONE)`を呼び出す必要があります。

## スリープモードから復帰した際のカメラの処理について

スリープモードへ移行する際に、カメラは自動的にスタンバイ状態 （`CAMERA_I2CActivate(CAMERA_SELECT_NONE)`）に入ります。
スリープ復帰時にカメラを有効にしたい場合は、`CAMERA_I2CActivate()`を呼び出すなど、アプリケーション側で対処する必要があります。

## カメラ誤動作時の復帰処理について

構造上、カメラは静電気・機械的衝撃などによって画像データを取得できなくなる恐れがあります。
このような現象が発生した場合、カメラライブラリは内部で自動的に再起動処理を行います。再起動処理完了後には `CAMERA_SetRebootCallback()`で登録したコールバック関数が呼ばれます。
この再起動処理では、カメラ設定は直前の状態に自動で再設定されるため、アプリ側で特に対応を行う必要はありません。
再起動処理中にカメラのAPIを実行しようとした場合には、`CAMRA_RESULT_ILLEGAL_STATUS`が 返ることになるため、必要ならば`CAMERA_SetRebootCallback()`にセットした コールバック関数が呼ばれた後に、そのAPIのやり直しを行ってください。
コールバック関数の引数に`CAMERA_RESULT_FATAL_ERROR`が入っていた場合は 再起動処理に失敗したことを示し、カメラが物理的に故障している可能性があります。
その際には、電源を入れ直すことで復旧する可能性もありますので、ユーザに対してメッセージを表示して対応することを推奨します。
なお、DSiカメラでは以下の様なメッセージを表示し、以降の処理は行わないようになっております。
「エラーが発生しました。本体の電源ボタンを押して電源をOFFにして、本体の取扱説明書の指示に従ってください。」

## キャプチャ画像が稀にずれる現象について

カメラのキャプチャ実行中に特定のカメラ設定関数を呼び出すと、キャプチャ画像がずれる現象が稀に発生することがあります。
この現象は検知することができないため、以下のカメラ設定関数は一旦キャプチャを停止した後に呼び出し、設定が変更されたことを 確認してからキャプチャを開始するようにしてください。

`
- CAMERA_I2CActivate*()
- CAMERA_I2CSize*()
- CAMERA_I2CFrameRate*()
- CAMERA_I2CEffect*()
- CAMERA_I2CFlip*()
- CAMERA_I2CPhotoMode*()
- CAMERA_I2CExposure*()
- CAMERA_I2CAutoExposure()
- CAMERA_I2CAutoWhiteBalance()
- CAMERA_I2CContextSwitch*()(CAMERA_CONTEXT_B から CAMERA_CONTEXT_A への切り替え時のみ)
`

## 参照

`CAMERA 関数一覧
`

## 履歴

2009/11/11 キャプチャ画像が稀にずれる現象についての説明追記
2009/01/06 CAMERA_RESULT_FATAL_ERROR が発生した場合の対応方法について追記
2009/01/05 説明の意図が伝わるように修正
2008/09/11 初版