CVPixelBufferからCMSampleBufferに変換

### 実現したかった内容
1. Flutterでリアルタイムに取得した画像をUint8形式へ変換
2. 画像ごとにMethodChannelでプラットフォーム（Swift）に送る
3. SwiftでUint8からCMSampleBufferに変換する

というような処理を作成していました。その際、Uint8からCVPixelBufferまでの変換は調べると沢山の例が出てきたのですが、CVPixelBufferをCMSampleBufferに変換する例は少なく、実装するのに苦労していました。
今回は自分で作ってみてひとまず動いた例を紹介します。

### 変換に必要な物

- CVPixelBuffer（用意済み）
- CMSampleTimingInfo
- CMVideoFormatDescription

### CMSampleTimingInfoを用意
画像の時間情報を生成します。単位はナノ秒を使用し、Dateを拡張してタイムスタンプを生成しています。
```swift
let timeScale = CMTimeScale(NSEC_PER_SEC)
let pts = CMTime(value:CMTimeValue(Date().currentTimeNanoSec()),
                    timescale: timeScale)
var timingInfo: CMSampleTimingInfo = CMSampleTimingInfo(duration: CMTime.invalid,
                                                        presentationTimeStamp: pts,
                                                        decodeTimeStamp: CMTime.invalid)
```
```swift
extension Date {
    func currentTimeNanoSec() -> Int64 {
        return Int64(self.timeIntervalSince1970*1000000000)
    }   
}
```

### CMVideoFormatDescriptionを用意
フォーマットの情報を生成します。
```swift
var videoInfo: CMVideoFormatDescription?
CMVideoFormatDescriptionCreateForImageBuffer(allocator: nil,
                                                imageBuffer: cvPixelBuffer,
                                                formatDescriptionOut: &videoInfo)
```

### CMSampleBufferを生成
```swift
var cmSampleBuffer: CMSampleBuffer?                                         
CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault,
                                    imageBuffer: cvPixelBuffer,
                                    dataReady: true,
                                    makeDataReadyCallback: nil,
                                    refcon: nil,
                                    formatDescription: videoInfo!,
                                    sampleTiming: &timingInfo,
                                    sampleBufferOut: &cmSampleBuffer)
```

### 記述したコード全体

```swift
let timeScale = CMTimeScale(NSEC_PER_SEC)
let pts = CMTime(value:CMTimeValue(Date().currentTimeNanoSec()),
                    timescale: timeScale)
var timingInfo: CMSampleTimingInfo = CMSampleTimingInfo(duration: CMTime.invalid,
                                                        presentationTimeStamp: pts,
                                                        decodeTimeStamp: CMTime.invalid)
                                                        
var videoInfo: CMVideoFormatDescription?
CMVideoFormatDescriptionCreateForImageBuffer(allocator: nil,
                                                imageBuffer: cvPixelBuffer,
                                                formatDescriptionOut: &videoInfo)
                                                
var cmSampleBuffer: CMSampleBuffer?                                         
CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault,
                                    imageBuffer: cvPixelBuffer,
                                    dataReady: true,
                                    makeDataReadyCallback: nil,
                                    refcon: nil,
                                    formatDescription: videoInfo!,
                                    sampleTiming: &timingInfo,
                                    sampleBufferOut: &cmSampleBuffer)

extension Date {
    func currentTimeNanoSec() -> Int64 {
        return Int64(self.timeIntervalSince1970*1000000000)
    }   
}
```

恐らくもっとスマートなやり方があると思うのですが、困っている方の参考になれば幸いです。