<更新>
- 2016.06.02 - まあAVFrameに関しては全部無視してください。extended_dataの存在を今更気づきました。
僕は会社でiOSようの動画プレーヤーを作っている人です。
今年の後半はObjective Cで作られているコードをSwift 3に変わる企画を立て、やってます。
実に楽しい作業です。
作業の中で一番面倒くさいところは、Cで作成されている配列とstructに関連するものが多いです。そこで、ま、すぐれた方には簡単なことだと思いますが。僕にはどんでもない難しかったものなので、同じ悩みを持ってる方のため、ここに短いソースを上げてみます。
まずCでのAVFrameの一部です。
typedef struct AVFrame {
...
uint8_t *data[AV_NUM_DATA_POINTERS]; // AV_NUM_DATA_POINTERS = 8
...
CのAVFrameの構造体はでコーディングされたデータをuint8_t型のポインターの配列の変数に保管しでいます。
問題はswiftはCの配列をtupleと扱ってしまうことです。
swiftで変わったAVFrameの一部です。
public struct AVFrame {
public var data: (UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?, UnsafeMutablePointer<UInt8>?)
tupleは目に見るのは楽だけど、実に使用するには沢山の問題があります。一々にハードコーディングするしかないし、配列の数がなん百、なん千、なん万を超えたら、Xcodeが気絶することもあります。なんでarrayでやってくれないのかな疑問です。
変更するコードは以下のようです
let tuplePointer: UnsafePointer<(UnsafePointer<UInt8>?, UnsafePointer<UInt8>?, ...)> = withUnsafePointer(to: $tuplePointer){$0}
let unsignedInteger8Buffer: UnsafePointer<UnsafePointer<UInt8>?> = UnsafePointer(tuplePointer.withMemoryRebound(to: (UnsafePointer<UInt8>?.self)!, capacity: 8){$0}
let bufferPointer: UnsafeBufferPointer<UnsafePointer<UInt8>?> = UnsafeBufferPointer(start: unsignedInteger8Buffer, count: 8)
let arr = Array(bufferPointer)
- withMemoryRebound関数はポインターの形態を変わる関数です。toの引数には変更したいタイプを入れて、capacityにはタイプのサイズに当たる単位を何個持つかを関数に知らせます。ここではAVFrameが最大8個のdataを持っているので、8に入れました。
- UnsafeBufferPointerを初期化しながらstart引数にunsignedIntegerBufferを入れて、countには8を入れます。
- UnsafeBufferPointerをArrayの初期化の引数で入れます。
で、簡単にtupleがArrayで変わりますた。