Reputation: 11
I already have implemented all the functions but when the data comes first time, its playing but when the data comes second time its going in Asset is not playable. I'm not able to confirm why it's happening.
private func receiveMessage() { webSocketTask?.receive { [weak self] result in guard let self = self else { return }
switch result {
case .success(let message):
switch message {
case .string(let text):
self.handleIncomingMessage(text)
case .data(let data):
self.appendDataToBuffer(data)
@unknown default:
print("Unknown message type received")
}
// Continue receiving messages
self.receiveMessage()
case .failure(let error):
print("Failed to receive message: \(error)")
// Check WebSocket state
if let state = self.webSocketTask?.state {
print("WebSocket state: \(state)")
// If the connection is still active, try receiving again
if state == .running {
self.receiveMessage()
} else {
print("WebSocket is not running. State: \(state)")
}
}
}
}
}
This is how I'm appending the data from websocket
func appendDataToBuffer(_ data: Data) {
self.dataBuffer.append(data)
bufferQueue.async { [weak self] in
guard let self = self else { return }
if !self.isProcessingBuffer {
self.startProcessingLoop()
}
}
}
private func startProcessingLoop() {
processingQueue.async { [weak self] in
guard let self = self else { return }
self.isProcessingBuffer = true
while self.isStreamingActive {
var chunk: Data?
self.bufferQueue.sync {
let dynamicChunkSize = self.determineChunkSize()
if self.dataBuffer.count >= dynamicChunkSize {
print("Is Databuffer Count is greater than dynamic chunk size \(self.dataBuffer.count >= dynamicChunkSize)")
chunk = self.dataBuffer.prefix(dynamicChunkSize)
self.dataBuffer.removeFirst(dynamicChunkSize)
}
}
guard let chunkToProcess = chunk else {
usleep(100_000)
continue
}
self.processVideoChunk(chunkToProcess)
}
self.isProcessingBuffer = false
}
}
private func processVideoChunk(_ chunk: Data) { // Store the chunk in memory videoChunks.append(chunk) {
// Combine all chunks into a single Data object
let combinedData = Data(videoChunks.joined())
// Create an AVAsset from the combined data
guard let tempURL = createTemporaryURL(with: combinedData) else {
logger.error("Failed to create temporary URL for video data")
return
}
DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) { [weak self] in
guard let self = self else { return }
// Load the AVAsset asynchronously
let asset = AVAsset(url: tempURL)
asset.loadValuesAsynchronously(forKeys: ["playable"]) {
var error: NSError? = nil
let status = asset.statusOfValue(forKey: "playable", error: &error)
DispatchQueue.main.async {
if status == .loaded {
self.logger.log("Asset loaded successfully")
if asset.isPlayable {
self.logger.log("Asset is playable")
let playerItem = AVPlayerItem(asset: asset)
self.delegate?.pausePlayer()
// Use delegate to start the video playback
self.delegate?.startVideo(playerItem: playerItem)
self.isProcessingBuffer = false
// Clean up temporary URL
try? FileManager.default.removeItem(at: tempURL)
self.clearChunks()
} else {
self.logger.error("Asset is not playable")
try? FileManager.default.removeItem(at: tempURL)
self.clearChunks()
self.isProcessingBuffer = false
}
} else {
self.logger.error("Error loading asset: \(error?.localizedDescription ?? "Unknown error")")
}
}
}
}
}
}
Its playing for 2-3 seconds then its falling in Asset is not playable I'm not able to identify what is problem with that.
The data that I'm getting is binary data and I want to show it on my avplayer. Data is of Live Streaming Camera.
Upvotes: 1
Views: 23