質問するログイン新規登録

回答編集履歴

2

追記1

2018/08/03 09:19

投稿

u39ueda
u39ueda

スコア950

answer CHANGED
@@ -1,4 +1,63 @@
1
1
  `func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)` がメインスレッド以外から呼ばれていませんか?
2
2
  `sampleBufferCallbackQueue` にセットされているDispatchQueueから呼ばれるようです。
3
3
 
4
- もしメインスレッドから呼んでいた場合は `getByteArrayFromImage()` の実行を`CVPixelBufferUnlockBaseAddress()` の前に移動してみてはどうでしょうか。
4
+ もしメインスレッドから呼んでいた場合は `getByteArrayFromImage()` の実行を`CVPixelBufferUnlockBaseAddress()` の前に移動してみてはどうでしょうか。
5
+
6
+ #### 追記
7
+
8
+ 実際に試してみましたが以下のような問題があるようです。
9
+
10
+ - メインスレッドでfor文をぶん回しているせいで処理に時間がかかっている
11
+ →バックグラウンドスレッドで実行させればマシになる(それでもカクカクだけど)
12
+ →for文をコメントアウトするならそのままでもOK
13
+ - 真っ白に表示されるのはforで真っ白に塗り潰しているから
14
+ →コメントアウト
15
+ - rawDataが画像として使っている間に解放されてしまってクラッシュする
16
+ 今クラッシュしていないのはよくわからない。CPU使用率100%だから?
17
+ →UnsafeMutablePointer.allocate(capacity:)を使ってスコープを抜けても解放されないようにする
18
+
19
+ rawDataを解放されないようにするのと、for文をコメントアウトすれば動きました。
20
+ 変更前のコードはコメントアウトしてありますので見比べてください。
21
+
22
+ ```Swift
23
+ func getByteArrayFromImage(imageRef: CGImage) -> UIImage {
24
+ let editedimage:UIImage
25
+
26
+ let width_n :Int = Int((imageRef.width))
27
+ let height_n :Int = Int((imageRef.height))
28
+
29
+ let data = imageRef.dataProvider!.data
30
+ let length = CFDataGetLength(data)
31
+ // var rawData = [UInt8](repeating: 0, count: length)
32
+ let rawData = UnsafeMutablePointer<UInt8>.allocate(capacity: length)
33
+
34
+ // CFDataGetBytes(data, CFRange(location: 0, length: length), &rawData)
35
+ CFDataGetBytes(data, CFRange(location: 0, length: length), rawData)
36
+ // for文で回すならUnsafeMutableBufferPointerを使う
37
+ let rawDataBuffer = UnsafeMutableBufferPointer<UInt8>(start: rawData, count: length)
38
+ //for (index, _) in rawData.enumerated() {
39
+ // rawData[index] = 255
40
+ //}
41
+
42
+ // let provider = CGDataProvider(dataInfo: nil, data: &rawData, size: length,releaseData: releaseData)
43
+ let provider = CGDataProvider(dataInfo: nil, data: rawData, size: length,releaseData: releaseData)
44
+ let colorSpaceRef = imageRef.colorSpace
45
+ let bitmapInfo_n = imageRef.bitmapInfo
46
+ let bitsPerComponent:Int = imageRef.bitsPerComponent
47
+ let bitsPerPixel = imageRef.bitsPerPixel
48
+ let bytesPerRow_n = imageRef.bytesPerRow
49
+ let cgImage = CGImage(width: width_n, height: height_n, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow:bytesPerRow_n, space: colorSpaceRef!, bitmapInfo: bitmapInfo_n, provider: provider!, decode: nil, shouldInterpolate: false, intent: .defaultIntent)
50
+
51
+ editedimage = UIImage(cgImage:cgImage!, scale:1.0, orientation:UIImageOrientation.right)
52
+
53
+ // (2) editedimageには画像データが正常に入っている
54
+ return editedimage
55
+
56
+ }
57
+
58
+ // releaseDataの定義が見当たらなかったので適当に実装しました
59
+ func releaseData(info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, length: Int) {
60
+ print(#function, info ?? "nil", data, length)
61
+ data.deallocate()
62
+ }
63
+ ```

1

他の可能性を追記

2018/08/03 09:19

投稿

u39ueda
u39ueda

スコア950

answer CHANGED
@@ -1,2 +1,4 @@
1
1
  `func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)` がメインスレッド以外から呼ばれていませんか?
2
- `sampleBufferCallbackQueue` にセットされているDispatchQueueから呼ばれるようです。
2
+ `sampleBufferCallbackQueue` にセットされているDispatchQueueから呼ばれるようです。
3
+
4
+ もしメインスレッドから呼んでいた場合は `getByteArrayFromImage()` の実行を`CVPixelBufferUnlockBaseAddress()` の前に移動してみてはどうでしょうか。