When NSStream NSStreamEventHasSpaceAvailable event called? - ios

I cant really understand this event.
I'm hoping that it is called when the sending queue (or something similar internal structure) is done sending previously written packets.
Is it a correct assumption?
I'm working on a video streamer over Multipeer connectivity, and I want to use this property to decide if I should drop a camera frame (if there is no NSStreamEventHasSpaceAvailable), or I can submit it for NSOutputStream.
Imagine a BlueTooth connection, where I really need to drop a lot of camera frame, instead of submit every frame to NSStream.

The NSStreamEventHasSpaceAvailable event indicates that you can write (at least one byte!) to the stream without blocking. That does not mean that previously written data is completely
delivered to the other endpoint of the connection.

Related

Send audio buffer in parts to a server from an iOS device's microphone

I am trying to build an iOS application that streams audio coming directly from the input (or mic) of a device. What I am thinking is that every certain period of time, I'd have to send the audio buffer to the server, so that the server sends it to another client that might want to listen. I am planning to use WebSockets for the server-side implementation.
Is there a way to grab just a specific stream of buffer from the input (mic) of the iOS device and send it to the server while the user speaks another bit and so on and so forth? I am thinking that if I could start an AVAudioRecorder perhaps with AVAudioEngine and record every 1 second or half a second, but I think that that would create too much of a delay and possibly lost streams in the transition process.
Is there a better way to accomplish this? I am really interested in understanding the science behind it. If this is not the best approach please tell me which one it is and maybe a basic idea for its implementation or something that could point me in the right direction.
I found the answer to my own question!! The answer lies in the AVFoundation framework, specifically AVCaptureAudioDataOutput and its delegate that will send you a buffer as soon as the input source captures it.

Is there a way to have a future complete when a Stream is "done" without actually draining the messages, in Dart?

I want to see if the other side gave up and closed the sink of a StreamChannel, without actually reading the messages yet.
(I'm going to be handing the stream to someone else, so i can't listen() to it, since you're only allowed to listen once per stream.)
[posting for a friend, credit to them for asking the question]
In short, no.
There is no concept of "giving up". If you put events into a non-broadcast stream, they'll stay there until someone listens to the stream (which is why you shouldn't put data there until someone listens, you're just wasting memory).
That includes the done event, and you won't get to the done event without first reading all the preceding events. That's the core abstraction of a stream - a source of events accessed in order, it's not done until it's actually done.
What I think you are looking for is a "side channel" that can communicate information about the stream without going through the stream (that is, out-of-band).
Something like that can surely be built - in about one gazillion different ways, depending on what you want, but it's just not something that a Stream supports by default, nor does a StreamChannel, if I read it correctly (I have never used a StreamChannel myself).

Bonjour/NSNetService Data written to NSOutputStream never makes it to the other side (includesPeerToPeer = true)

I have an iOS app that establish a peer-to-peer connection through Bonjour/NSNetService. (based on the WiTap sample code)
In some cases, both devices won’t receive data anymore after a few seconds while they are still able to write data out (i.e. without an error being reported).
The data written to the NSOutputStream never makes it to the NSInputStream of the other side.
The strange part is that sending and receiving works right after the connection is established. It seems to go bad after a few seconds.
If I set includesPeerToPeer = false it is not happening anymore. Does anyone having the same issue? I need to use peer to peer because is required to use bluetooth.
Thanks
My first guess would be that you're writing data to the stream before you get a stream event telling you that it is ready to accept more data.
If that isn't the problem, then either it's a bug in your code (which you haven't posted any of) or... well, it is possible that the class in question still doesn't work correctly. See:
https://developer.apple.com/library/ios/qa/qa1546/_index.html
If that's the case, you might have to drop down to Core Foundation briefly.

how to detect connection lost in vlcj

I am playing network streams in my VLCJ application. Sometimes network connections are lost and I want to know this moments in my VLCJ application. I tried Error event but it is not fired. It is only fired when there is no network connection and I try to play a stream. When network is gone, last frame of video is freezed and nothing else is happened. How can I detect that video playing is stopped due to network connection lost?
There is no LibVLC API to detect that condition, and so there is no way to do it with vlcj either.
You could conceivably capture the native log and parse it looking for those errors, but that's a really poor approach frankly.
You should check Media state. Either in separate thread in loop with delay or - ( I use libVLCSharp in c# ) - there should be something like an event in Media that State had been changed. In c# it is Media.EventManager.StateChanged event.

Playing back a WAV file streamed gradually over a network connection in iOS

I'm working with a third party API that behaves as follows:
I have to connect to its URL and make my request, which involves POSTing request data;
the remote server then sends back, "chunk" at a time, the corresponding WAV data (which I receive in my NSURLConnectionDataDelegate's didReceiveData callback).
By "chunk" for argument's sake, we mean some arbitrary "next portion" of the data, with no guarantee that it corresponds to any meaningful division of the audio (e.g. it may not be aligned to a specific multiple of audio frames, the number of bytes in each chunk is just some arbitrary number that can be different for each chunk, etc).
Now-- correct me if I'm wrong, I can't simply use an AVAudioPlayer because I need to POST to my URL, so I need to pull back the data "manually" via an NSURLConnection.
So... given the above, what is then the most painless way for me to play back that audio as it comes down the wire? (I appreciate that I could concatenate all the arrays of bytes and then pass the whole thing to an AVAudioPlayer at the end-- only that this will delay the start of playback as I have to wait for all the data.)
I will give a bird's eye view to the solution. I think that this will help you a great deal in the direction to find a concrete, coded solution.
iOS provides a zoo of audio APIs and several of them can be used to play audio. Which one of them you choose depends on your particular requirements. As you wrote already, the AVAudioPlayer class is not suitable for your case, because with this one, you need to know all the audio data in the moment you start playing audio. Obviously, this is not the case for streaming, so we have to look for an alternative.
A good tradeoff between ease of use and versatility are the Audio Queue Services, which I recommend for you. Another alternative would be Audio Units, but they are a low level C API and therefor less intuitive to use and they have many pitfalls. So stick to Audio Queues.
Audio Queues allow you to define callback functions which are called from the API when it needs more audio data for playback - similarly to the callback of your network code, which gets called when there is data available.
Now the difficulty is how to connect two callbacks, one which supplies data and one which requests data. For this, you have to use a buffer. More specifically, a queue (don't confuse this queue with the Audio Queue stuff. Audio Queue Services is the name of an API. On the other hand, the queue I'm talking about next is a container object). For clarity, I will call this one buffer-queue.
To fill data into the buffer-queue you will use the network callback function, which supplies data to you from the network. And data will be taken out of the buffer-queue by the audio callback function, which is called by the Audio Queue Services when it needs more data.
You have to find a buffer-queue implementation which supports concurrent access (aka it is thread safe), because it will be accessed from two different threads, the audio thread and the network thread.
Alternatively to finding an already thread safe buffer-queue implementation, you can take care of the thread safety on your own, e.g. by executing all code dealing with the buffer-queue on a certain dispatch queue (3rd kind of queue here; yes, Apple and IT love them).
Now, what happens if either
The audio callback is called and your buffer-queue is empty, or
The network callback is called and your buffer-queue is already full?
In both cases, the respective callback function can't proceed normally. The audio callback function can't supply audio data if there is none available and the network callback function can't store incoming data if the buffer-queue is full.
In these cases, I would first try out blocking further execution until more data is available or respectively space is available to store data. On the network side, this will most likely work. On the audio side, this might cause problems. If it causes problems on the audio side, you have an easy solution: if you have no data, simply supply silence as data. That means that you need to supply zero-frames to the Audio Queue Services, which it will play as silence to fill the gap until more data is available from the network.
This is the concept that all streaming players use when suddenly the audio stops and it tells you "buffering" next to some kind of spinning icon indicating that you have to wait and nobody knows for how long.

Resources