« WWDC 2010 に参加してきた率直な感想 | メイン | Windows から Mac に乗り換えたときのメモ »

2010年07月03日

[iPhone][AVFoundation] AVCaptureOutput のメモ あとで読む


自分専用メモなんで、意味不明かと思いますが是非スルーの方向で。

iOS4 からカメラのフレームバッファをキャプチャすることができるようになったんですが、その取扱がちーと面倒。

で、たまったバッドノウハウ忘れないようにメモ。

- kCVPixelBufferPixelFormatTypeKey

これは基本 kCVPixelFormatType_32BGRA が扱いやすい。iPhone 3G でもOK。あと使うのは YUV ですかね。420v ならモノクロ・フレームバッファも取りやすい。


- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

指定したフレームレートベースでこのdelegateメソッドが呼ばれる。すげー便利。
比較的安定して呼び出し時間を守ってくれるので、あとはパフォーマンスとの戦い。

これは GCD のキューから呼び出される形となるので UIKit と連携するケースなどは別途 MainThread に情報を渡してやる必要がある。
つまり中間バッファが必要。

が、iPhone 4 だと 1280x720 の BGRA とかまでサポートしてるので、ピクセルバッファだけで 3MB を超えてしまう。

で、さて、このピクセルバッファを非同期で処理するためにどっかに格納しようかと思うんだが・・・ここでいろいろ問題発生。


ピクセルバッファは CVPixelBufferRetain で Retain できるので、とりあえず Retain しとけばいいや、と思いきや iPhone 3G さんがそれを許してくれない。
具体的には、Video の PreviewLayer のフレームレートが極端に落ちるなどの影響がでて結構耐えられない状況になる。

あ、ちなみに Retain する前に CVPixelBufferLockBaseAddress でロックも必要です。


じゃぁ、というわけで ピックセルバッファをコピーすることになるんだけど、late copy するために vm_copy かけときゃいいや、と思いきや iPhone 3G さんがそれを許してくれない。
具体的には iPhone 3G さんだけ vm_copy 動かない。

まじで!?memcpy すんの?iPhone 3G 捨てるか?という選択に迫られるわけです・・・。

ただ、どの処理にせよ、iPhone 3G のサポートしている 400x304 というピクセルバッファを処理するのに 0.05秒はかかる。10fps 出すにはすべての処理を 0.1 秒以内に収めないといけないので、バッファをごにょごにょ処理するのは避けたいところ・・・


しかも、iPhone 3G だけは BGRA のアルファチャンネルをサポートしてないらしく、カラースキームにアルファチャンネルを指定すると BitmapContext で CGImage に戻せないという問題もあり、うーむ、なんだかなぁ、と。


と、そんなわけで、超ローテクな方法でしか対応はできないので、できるだけこの dispatch_queue の中で処理を完結させるように書かないとね、という結論でした。


あぁ、完全に意味不明だけど、書いとかないと自分で同じ間違い繰り返しそうだったのでメモのこしときます。。。


あ、その他メモ:

- Front カメラと Rear カメラは同時には起動できない
- フレームバッファをキャプチャしながら同時にムービーを録画、もできない
- その回避策として AVWriter があったんだけど iOS4 beta3 で削除されちゃったからもう無理
- H.264エンコーダー、ハードウェアで対応してるはずなんだけど API は公開されてないから使えない
- 別プロセスで音楽を流すのはできるんだけど、マイクを拾い出した瞬間、音楽配信してたプロセスは強制終了される。


それと、超マニアメモ:CVPixelBufferRef に入っている情報。結構いろんな情報が取れる(iPhone4)

< CVPixelBufferRef 0x1e3d60 width=480 height=360 bytesPerRow=1920 pixelFormat=BGRA attributes=<CFBasicHash 0x1b1180 [0x3e143d5c]>{type = immutable dict, count = 1,
entries =>
1 : <CFString 0x3e53cce4 [0x3e143d5c]>{contents = "PixelFormatDescription"} = <CFBasicHash 0x1b42e0 [0x3e143d5c]>{type = immutable dict, count = 7,
entries =>
0 : <CFString 0x3e53cc54 [0x3e143d5c]>{contents = "CGBitmapContextCompatibility"} = <CFBoolean 0x3e144788 [0x3e143d5c]>{value = true}
1 : <CFString 0x3e53ceb4 [0x3e143d5c]>{contents = "FillExtendedPixelsCallback"} = <CFData 0x1b7a90 [0x3e143d5c]>{length = 12, capacity = 12, bytes = 0x000000004594413300000000}
8 : <CFString 0x3e53ce34 [0x3e143d5c]>{contents = "BlackBlock"} = <CFData 0x1a96f0 [0x3e143d5c]>{length = 4, capacity = 4, bytes = 0x000000ff}
9 : <CFString 0x3e53ce94 [0x3e143d5c]>{contents = "CGBitmapInfo"} = <CFNumber 0x1bace0 [0x3e143d5c]>{value = +8196, type = kCFNumberSInt32Type}
10 : <CFString 0x3e53cc64 [0x3e143d5c]>{contents = "CGImageCompatibility"} = <CFBoolean 0x3e144788 [0x3e143d5c]>{value = true}
11 : <CFString 0x3e53cda4 [0x3e143d5c]>{contents = "PixelFormat"} = <CFNumber 0x197650 [0x3e143d5c]>{value = +1111970369, type = kCFNumberSInt32Type}
12 : <CFString 0x3e53ce24 [0x3e143d5c]>{contents = "BitsPerBlock"} = <CFNumber 0x1ab9b0 [0x3e143d5c]>{value = +32, type = kCFNumberSInt32Type}
}

}
 propagatedAttachments=<CFBasicHash 0x1e3e80 [0x3e143d5c]>{type = mutable dict, count = 4,
entries =>
1 : <CFString 0x1da590 [0x3e143d5c]>{contents = "MetadataDictionary"} = <CFBasicHash 0x1e3890 [0x3e143d5c]>{type = immutable dict, count = 29,
entries =>
0 : <CFString 0x1da5d0 [0x3e143d5c]>{contents = "ExposureTime"} = <CFNumber 0x1e33e0 [0x3e143d5c]>{value = +0.08316987826086956470, type = kCFNumberFloat64Type}
1 : <CFString 0x1da5f0 [0x3e143d5c]>{contents = "ISOSpeedRating"} = <CFNumber 0x1e33f0 [0x3e143d5c]>{value = +419, type = kCFNumberSInt64Type}
3 : <CFString 0x1da610 [0x3e143d5c]>{contents = "Fnumber"} = <CFNumber 0x1e3400 [0x3e143d5c]>{value = +2.79999999999999982236, type = kCFNumberFloat64Type}
4 : <CFString 0x1da630 [0x3e143d5c]>{contents = "sensorDGain"} = <CFNumber 0x1e3410 [0x3e143d5c]>{value = +256, type = kCFNumberSInt64Type}
5 : <CFString 0x1da650 [0x3e143d5c]>{contents = "AGC"} = <CFNumber 0x1e3420 [0x3e143d5c]>{value = +1464, type = kCFNumberSInt64Type}
6 : <CFString 0x1da660 [0x3e143d5c]>{contents = "AEAverage"} = <CFNumber 0x1e3430 [0x3e143d5c]>{value = +169, type = kCFNumberSInt64Type}
7 : <CFString 0x1e3110 [0x3e143d5c]>{contents = "AFStable"} = <CFNumber 0x10cce0 [0x3e143d5c]>{value = +1, type = kCFNumberSInt32Type}
8 : <CFString 0x1e3130 [0x3e143d5c]>{contents = "TemporalMotion"} = <CFNumber 0x1e3880 [0x3e143d5c]>{value = +237247, type = kCFNumberSInt64Type}
9 : <CFString 0x1e3150 [0x3e143d5c]>{contents = "ShutterSpeedValue"} = <CFNumber 0x1e3450 [0x3e143d5c]>{value = +3.58779506948601589755, type = kCFNumberFloat64Type}
10 : <CFString 0x1e3170 [0x3e143d5c]>{contents = "FullyExposed"} = <CFNumber 0x10cce0 [0x3e143d5c]>{value = +1, type = kCFNumberSInt32Type}
11 : <CFString 0x1e3190 [0x3e143d5c]>{contents = "ExposureBias"} = <CFNumber 0x1e3460 [0x3e143d5c]>{value = +0.0, type = kCFNumberFloat64Type}
12 : <CFString 0x1e31b0 [0x3e143d5c]>{contents = "AWBRGain"} = <CFNumber 0x1e3470 [0x3e143d5c]>{value = +133, type = kCFNumberSInt64Type}
13 : <CFString 0x1e31d0 [0x3e143d5c]>{contents = "OverflowOccurred"} = <CFBoolean 0x3e144790 [0x3e143d5c]>{value = false}
14 : <CFString 0x1e31f0 [0x3e143d5c]>{contents = "FocalLength"} = <CFNumber 0x1e3480 [0x3e143d5c]>{value = +3.85000000000000008882, type = kCFNumberFloat64Type}
15 : <CFString 0x1e3210 [0x3e143d5c]>{contents = "AWBGGain"} = <CFNumber 0x1e3490 [0x3e143d5c]>{value = +64, type = kCFNumberSInt64Type}
16 : <CFString 0x1e3230 [0x3e143d5c]>{contents = "ApertureValue"} = <CFNumber 0x1e34a0 [0x3e143d5c]>{value = +3.00000000000000000000, type = kCFNumberFloat64Type}
17 : <CFString 0x1e3250 [0x3e143d5c]>{contents = "SensorID"} = <CFNumber 0x1e34b0 [0x3e143d5c]>{value = +13904, type = kCFNumberSInt64Type}
18 : <CFString 0x1e3270 [0x3e143d5c]>{contents = "SNR"} = <CFNumber 0x1e34c0 [0x3e143d5c]>{value = +35.13407451801569436611, type = kCFNumberFloat64Type}
19 : <CFString 0x1e3280 [0x3e143d5c]>{contents = "OneFrameAEMode"} = <CFNumber 0x10cce0 [0x3e143d5c]>{value = +1, type = kCFNumberSInt32Type}
20 : <CFString 0x1e32a0 [0x3e143d5c]>{contents = "CurrentFocusPosition"} = <CFNumber 0x1e34d0 [0x3e143d5c]>{value = +186, type = kCFNumberSInt64Type}
22 : <CFString 0x1e32c0 [0x3e143d5c]>{contents = "AEStable"} = <CFNumber 0x10cce0 [0x3e143d5c]>{value = +1, type = kCFNumberSInt32Type}
27 : <CFString 0x1e32e0 [0x3e143d5c]>{contents = "ispDGain"} = <CFNumber 0x1e34e0 [0x3e143d5c]>{value = +256, type = kCFNumberSInt64Type}
28 : <CFString 0x1e3300 [0x3e143d5c]>{contents = "AWBBGain"} = <CFNumber 0x1e34f0 [0x3e143d5c]>{value = +198, type = kCFNumberSInt64Type}
30 : <CFString 0x1e3320 [0x3e143d5c]>{contents = "FocusScoresArray"} = <CFArray 0x1e3550 [0x3e143d5c]>{type = immutable, count = 5, values = (
0 : <CFNumber 0x1e3500 [0x3e143d5c]>{value = +4835, type = kCFNumberSInt64Type}
1 : <CFNumber 0x1e3510 [0x3e143d5c]>{value = +5044, type = kCFNumberSInt64Type}
2 : <CFNumber 0x1e3520 [0x3e143d5c]>{value = +5486, type = kCFNumberSInt64Type}
3 : <CFNumber 0x1e3530 [0x3e143d5c]>{value = +5670, type = kCFNumberSInt64Type}
4 : <CFNumber 0x1e3540 [0x3e143d5c]>{value = +189347, type = kCFNumberSInt64Type}
)}
33 : <CFString 0x1e3340 [0x3e143d5c]>{contents = "AFStatus"} = <CFNumber 0x10ccf0 [0x3e143d5c]>{value = +2, type = kCFNumberSInt32Type}
34 : <CFString 0x1e3360 [0x3e143d5c]>{contents = "AELimitsReached"} = <CFNumber 0x10e3a0 [0x3e143d5c]>{value = +0, type = kCFNumberSInt32Type}
37 : <CFString 0x1e3380 [0x3e143d5c]>{contents = "FocusPeakSumArray"} = <CFArray 0x1e35d0 [0x3e143d5c]>{type = immutable, count = 5, values = (
0 : <CFNumber 0x1e3580 [0x3e143d5c]>{value = +8103, type = kCFNumberSInt64Type}
1 : <CFNumber 0x1e3590 [0x3e143d5c]>{value = +8217, type = kCFNumberSInt64Type}
2 : <CFNumber 0x1e35a0 [0x3e143d5c]>{value = +8342, type = kCFNumberSInt64Type}
3 : <CFNumber 0x1e35b0 [0x3e143d5c]>{value = +8461, type = kCFNumberSInt64Type}
4 : <CFNumber 0x1e35c0 [0x3e143d5c]>{value = +24617, type = kCFNumberSInt64Type}
)}
38 : <CFString 0x1e33a0 [0x3e143d5c]>{contents = "BrightnessValue"} = <CFNumber 0x1e3600 [0x3e143d5c]>{value = -0.40476958246484440185, type = kCFNumberFloat64Type}
39 : <CFString 0x1e33c0 [0x3e143d5c]>{contents = "AWBStable"} = <CFNumber 0x10cce0 [0x3e143d5c]>{value = +1, type = kCFNumberSInt32Type}
}

4 : <CFString 0x1e37f0 [0x3e143d5c]>{contents = "CVImageBufferChromaSubsampling"} = <CFString 0x1e3a20 [0x3e143d5c]>{contents = "4:2:0"}
5 : <CFString 0x1e3820 [0x3e143d5c]>{contents = "CVImageBufferChromaLocationTopField"} = <CFString 0x1e3a30 [0x3e143d5c]>{contents = "Center"}
6 : <CFString 0x1e3850 [0x3e143d5c]>{contents = "CVImageBufferChromaLocationBottomField"} = <CFString 0x1e3a30 [0x3e143d5c]>{contents = "Center"}
}
 nonPropagatedAttachments=<CFBasicHash 0x1d1f70 [0x3e143d5c]>{type = mutable dict, count = 0,
entries =>
}
 iosurface=0x0>

Follow yoski on Twitter

ワード

投稿者 aka : 2010年07月03日 20:46  / 2010年07月 / メモ

トラックバック

人気ブログランキング - a++ My RSS 管理人ブログ

このエントリーのトラックバックURL:
http://210.188.206.194/mt-tb-sf.cgi/837

このリストは、次のエントリーを参照しています: [iPhone][AVFoundation] AVCaptureOutput のメモ:

» たかがiPhoneされどiPhone from iPhone
何気にはまってるiPhone。インターネットには沢山のiPhoneに関連したブログやHPがあり、つくづく見るほうもどれを見ていいか分かりません。 ブログ... [続きを読む]

トラックバック時刻: 2010年07月04日 16:11

コメント

コメントしてください

あわせて読みたい




保存しますか?


あとで読む | to read | フレッシュリーダー | フレッシュミーティング | RSSフィード.cc | あわせて読みたい | track feed MyRSS管理人