1

I am trying to convert some Objective C code provided in one of Apple's code examples here: https://developer.apple.com/library/mac/samplecode/avsubtitleswriterOSX/Listings/avsubtitleswriter_SubtitlesTextReader_m.html

The result I have come up with thus far is as follows:

func copySampleBuffer() -> CMSampleBuffer? {

    var textLength : Int = 0
    var sampleSize : Int = 0

    if (text != nil) {
        textLength = text!.characters.count
        sampleSize = text!.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
    }

    var sampleData = [UInt8]()

    // Append text length
    sampleData.append(UInt16(textLength).hiByte())
    sampleData.append(UInt16(textLength).loByte())

    // Append the text
    for char in (text?.utf16)! {
        sampleData.append(char.bigEndian.hiByte())
        sampleData.append(char.bigEndian.loByte())
    }

    if (self.forced) {
        // TODO
    }

    let samplePtr = UnsafeMutablePointer<[UInt8]>.alloc(1)
    samplePtr.memory = sampleData

    var sampleTiming = CMSampleTimingInfo()
    sampleTiming.duration = self.timeRange.duration;
    sampleTiming.presentationTimeStamp = self.timeRange.start;
    sampleTiming.decodeTimeStamp = kCMTimeInvalid;

    let formatDescription = copyFormatDescription()

    let dataBufferUMP = UnsafeMutablePointer<Optional<CMBlockBuffer>>.alloc(1)

    CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, samplePtr, sampleSize, kCFAllocatorMalloc, nil, 0, sampleSize, 0, dataBufferUMP);

    let sampleBufferUMP = UnsafeMutablePointer<Optional<CMSampleBuffer>>.alloc(1)

    CMSampleBufferCreate(kCFAllocatorDefault, dataBufferUMP.memory, true, nil, nil, formatDescription, 1, 1, &sampleTiming, 1, &sampleSize, sampleBufferUMP);

    let sampleBuffer = sampleBufferUMP.memory

    sampleBufferUMP.destroy()
    sampleBufferUMP.dealloc(1)

    dataBufferUMP.destroy()
    dataBufferUMP.dealloc(1)

    samplePtr.destroy()
    //Crash if I call dealloc here
    //Error is: error for object 0x10071e400: pointer being freed was not allocated
    //samplePtr.dealloc(1)

    return sampleBuffer;
}

I would like to avoid the "Unsafe*" types where possible, though I am not sure it is possible here. I also looked at using a struct and then somehow seeing to pack it somehow, but example I see seem to be based of sizeof, which uses the size of the definition, rather than the current size of the structure. This would have been the structure I would have used:

struct SubtitleAtom {
    var length : UInt16
    var text : [UInt16]
    var forced : Bool?
}

Any advice on most suitable Swift 2 code for this function would be appreciated.

Andre M
  • 6,649
  • 7
  • 52
  • 93

1 Answers1

1

so, at first, you code use this pattern

class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }

func foo() {
    let ptr = UnsafeMutablePointer<S>.alloc(1)
    let o = C()
    let fancy = S(objectRef: o)
    ptr.memory = fancy
    ptr.destroy() //deinit runs here!
    ptr.dealloc(1) //don't leak memory
}
// soon or later this code should crash :-)
(1..<1000).forEach{ i in
    foo()
    print(i)
}

Try it in a playground and most likely it crash :-). What's wrong with it? The trouble is your unbalanced retain / release cycles. How to write the same in the safe manner? You removed dealloc part. But try to do it in my snippet and see the result. The code crash again :-). The only safe way is to properly initialize and de-ininitialize (destroy) the underlying ptr's Memory as you can see in next snippet

class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }

func foo() {
    let ptr = UnsafeMutablePointer<S>.alloc(1)
    let o = C()
    let fancy = S(objectRef: o)
    ptr.initialize(fancy)
    ptr.destroy()
    ptr.dealloc(1)
}

(1..<1000).forEach{ i in
    foo()
    print(i)
}

Now the code is executed as expected and all retain / release cycles are balanced.

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • Thanks. Just to be clear alloc means number of instances of type, size of data or something else? Documentation is not altogether clear and all examples always provide '1' as value. – Andre M Feb 29 '16 at 18:59
  • 1
    @AndreM number of instances – user3441734 Feb 29 '16 at 19:00