Skip to content

Instantly share code, notes, and snippets.

@omarojo
Created May 5, 2017 14:53
Show Gist options
  • Save omarojo/14e513130f92237f812c215928aaefba to your computer and use it in GitHub Desktop.
Save omarojo/14e513130f92237f812c215928aaefba to your computer and use it in GitHub Desktop.
LF Custom Static Buffer
import lf
import UIKit
import XCGLogger
import AVFoundation
let sampleRate:Double = 44_100
final class LiveViewController: UIViewController {
//.....
//
var PTS = kCMTimeZero
var timer : Timer? = nil
var testSamplePixelBuffer : CVPixelBuffer? = nil
func startPushingCustomContent(){
createOncePixelBuffer()
//start a timer to run at desired framerate.
self.timer = Timer.scheduledTimer(timeInterval: 1.0 / Double(30), //30 fps
target: self,
selector: #selector(pushCustomBuffer),
userInfo: nil,
repeats: true);
}
func createOncePixelBuffer(){
let myimage = UIImage(named: "myimage")!
self.testSamplePixelBuffer = pixelBufferFromImage(image: myimage); //creates a pixelbufffer from an image
}
func stopPushingCustomContent(){
PTS = kCMTimeZero
self.timer?.invalidate();
}
//MARK: Custom Content Stream
func pushCustomBuffer (){
if let imageBuffer = self.testSamplePixelBuffer {
var timingInfo:CMSampleTimingInfo = CMSampleTimingInfo(
duration: CMTimeMake(1,30),
presentationTimeStamp: self.PTS,
decodeTimeStamp: kCMTimeInvalid
)
var videoFormatDescription:CMVideoFormatDescription? = nil
var status = CMVideoFormatDescriptionCreateForImageBuffer(
kCFAllocatorDefault,
imageBuffer,
&videoFormatDescription
)
var sampleBuffer:CMSampleBuffer? = nil
status = CMSampleBufferCreateForImageBuffer(
kCFAllocatorDefault,
imageBuffer,
true,
nil,
nil,
videoFormatDescription!,
&timingInfo,
&sampleBuffer
)
//if status != 0{
if let buffer:CMSampleBuffer = sampleBuffer {
rtmpStream.appendSampleBuffer(buffer, withType: .video);
}
//}
//increment our timestamp
self.PTS = CMTimeAdd(self.PTS, CMTimeMake(1, 30));
}
}
//// UTIL...
func pixelBufferFromImage(image: UIImage) -> CVPixelBuffer {
let ciimage = CIImage(image: image)
let cgimage = convertCIImageToCGImage(inputImage: ciimage!)
/*
NSDictionary *options = @{(id)kCVPixelBufferCGImageCompatibilityKey: @YES,
(id)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES};
*/
// stupid CFDictionary stuff
let cfnumPointer = UnsafeMutablePointer<UnsafeRawPointer>.allocate(capacity: 1)
let cfnum = CFNumberCreate(kCFAllocatorDefault, .intType, cfnumPointer)
let keys: [CFString] = [kCVPixelBufferCGImageCompatibilityKey, kCVPixelBufferCGBitmapContextCompatibilityKey, kCVPixelBufferBytesPerRowAlignmentKey]
let values: [CFTypeRef] = [kCFBooleanTrue, kCFBooleanTrue, cfnum!]
let keysPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1)
let valuesPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1)
keysPointer.initialize(to: keys)
valuesPointer.initialize(to: values)
let options = CFDictionaryCreate(kCFAllocatorDefault, keysPointer, valuesPointer, keys.count, nil, nil)
let width = cgimage!.width
let height = cgimage!.height
// let pxbuffer = UnsafeMutablePointer<CVPixelBuffer?>.allocate(capacity: 1)
var pxbuffer: CVPixelBuffer?
// if pxbuffer = nil, you will get status = -6661
var status = CVPixelBufferCreate(kCFAllocatorDefault, width, height,
kCVPixelFormatType_32ARGB, options, &pxbuffer)
debugPrint("status = \(status)")
// status = CVPixelBufferLockBaseAddress(pxbuffer.pointee!, CVPixelBufferLockFlags(rawValue: 0));
status = CVPixelBufferLockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0));
// let bufferAddress = CVPixelBufferGetBaseAddress(pxbuffer.pointee!);
let bufferAddress = CVPixelBufferGetBaseAddress(pxbuffer!);
// debugPrint("pxbuffer.memory = \(pxbuffer.pointee)")
debugPrint("pxbuffer.memory = \(pxbuffer)")
let rgbColorSpace = CGColorSpaceCreateDeviceRGB();
//debugPrint("rgbColorSpace = \(rgbColorSpace)")
// let bytesperrow = CVPixelBufferGetBytesPerRow(pxbuffer.pointee!)
let bytesperrow = CVPixelBufferGetBytesPerRow(pxbuffer!)
let context = CGContext(data: bufferAddress,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: bytesperrow,
space: rgbColorSpace,
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue);
//debugPrint("context = \(context.debugDescription)")
context?.draw(cgimage!, in: CGRect(x:0, y:0, width:CGFloat(width), height:CGFloat(height)));
// status = CVPixelBufferUnlockBaseAddress(pxbuffer.pointee!, CVPixelBufferLockFlags(rawValue: 0));
status = CVPixelBufferUnlockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0));
return pxbuffer!;
}
func convertCIImageToCGImage(inputImage: CIImage) -> CGImage!{
let context = CIContext(options: nil)
return context.createCGImage(inputImage, from: inputImage.extent)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment