Tú Trần
Tú Trần

Reputation: 1

Calculate current recorded video capacity with CMSampleBuffer and AVAssetWriter

I do video recording with AVCaptureVideoDataOutputSampleBufferDelegate and function func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) I use AVAssetWriter to save the received CMSampleBuffers as videos to the generated url. I need to let users see the continuously updated recorded video capacity. I accumulated the CMSampleBuffer to display with the calculateSampleBufferSize function but the results are not accurate. Does anyone know how to calculate it correctly from the CMSampleBuffer? Thank you.

Here is the code I implemented

    func writeBufferVideoToFile(assetWriter: AVAssetWriter,
                                sampleBuffer: CMSampleBuffer) {
        guard isRecoding else {
            return
        }
        // Setup start record
        if assetWriter.status == .unknown {
            totalBytesWritten = 0
            assetWriter.startWriting()
            assetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
        }
        // Record data
        if let assetWriterInput = assetWriter.currentInput,
           assetWriterInput.isReadyForMoreMediaData {
            // Calculate the total number of bytes written
            totalBytesWritten += Double(calculateSampleBufferSize(sampleBuffer: sampleBuffer))
            // Record
            assetWriterInput.append(sampleBuffer)
        }
    }

    func calculateSampleBufferSize(sampleBuffer: CMSampleBuffer) -> Int {
        guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return 0
        }
        
        CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
        let size = CVPixelBufferGetDataSize(imageBuffer)
        CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
        
        return size
    }

Upvotes: 0

Views: 65

Answers (1)

Rob Napier
Rob Napier

Reputation: 299345

You're currently computing the size of the raw, uncompressed image buffer. This is almost certainly not what you're writing. Generally your AVAssetWriter is configured to write to a compressed container (such as a QuickTime or MPEG-4). You appear to want the size of that final data.

To get that final output data, implement a AVAssetWriterDelegate and assign it as the delegate. That object will be called every time there is output data to write. You can check its size there.

I cannot remember immediately if the delegate is used when you use one of the URL-based init. If it isn't, you'll need to use the non-URL init, and have your delegate write the file itself, for example by using FileHandle.

Upvotes: 0

Related Questions