How to handle EOS in gstreamer's custom plugin? - plugins

I'm trying to develop my own, custom plugin with N request sink pads and M sometimes src pads. Sink pads are added to GstCollectPads object. I've managed to make plugin up & running, it receives buffers and process them the right way within gst_my_plugin_collected( GstCollectPads *pads ) callback, than i push the buffers to the peer of selected src pad.
These are the last lines in my *_collected(...) implementation.
281 GSList *it = pads->data;
282 for( it; it != NULL; it=it->next ) {
283 cdata = (GstCollectData*)(it->data);
284 outbuf = gst_collect_pads_peek( pads, cdata );
295 gst_pad_push( elem->srcpads[i++], outbuf );
298 }
299 return GST_FLOW_OK;
Sample pipeline:
gst-ndl-launch filesrc location=in.log ! myplugin ! filesink location=out.log
runs in the infinite loop processing all the time the same data from in.log file writing it to out.log file, just like it doesn't know when it reaches End-Of-File.
My guess is, I somehow need to tell my plugin that processing should stop, maybe by sending EOS message in some way, however I've got no idea how to do it. Thus my question is:
What should i do within my plugin in order to stop processing when End of file occurs?
// UPDATE:
It appears that my pipeline processes only first buffer in an infinite loop.
So my previous idea about sending EOS message was invalid, instead i must somehow remove
processed buffer in order to receive next one. Still don't know how to do it so any help will be appreciated.
What should i do after processing buffer from GstCollectData so that it won't process the same buffer again and again?

Ok maybe simpler answer:
gst_collect_pads_pop () instead of gst_collect_pads_peek ()?
Make sure to check for null.
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/GstCollectPads.html#gst-collect-pads-pop

Turns out it was just what i suspected at the begining, not handling EOS event.
In order to fix my issue i had to implement gst_collect_pads_event function,
its strange though that there is not a single word about this in GstCollectPads reference page.
(problem solved)

Related

Anylogic: Queue TimeOut blocks flow

I have a pretty simple Anylogic DE model where POs are launched regularly, and a certain amount of material gets to the incoming Queue in one shot (See Sample Picture below). Then the Manufacturing process starts using that material at a regular rate, but I want to check if the material in the queue gets outdated, so I'm using the TimeOut option of that queue, in order to scrap the outdated material (older than 40wks).
The problem is that every time that some material gets scrapped through this Timeout exit, the downstream Manufacturing process "stops" pulling more material, instead of continuing, and it does not get restarted until a new batch of material gets received into the Queue.
What am I doing wrong here? Thanks a lot in advance!!
Kindest regards
Your situation is interesting because there doesn't seem to be anything wrong with what you're doing. So even though what you are doing seems to be correct, I will provide you with a workaround. Instead of the Queue block, use a Wait block. You can assign a timeout and link the timeout port just like you did for the queue (seem image at the end of the answer).
In the On Enter field of the wait block (which I will assume is named Fridge), write the following code:
if( MFG.size() < MFG.capacity ) {
self.free(agent);
}
In the On Enter of MFG block write the following:
if( self.size() < self.capacity && Fridge.size() > 0 ) {
Fridge.free(Fridge.get(0));
}
And finally, in the On Exit of your MFG block write the following:
if( Fridge.size() > 0 ) {
Fridge.free(Fridge.get(0));
}
What we are doing in the above, is we are manually pushing the agents. Each time an agent is processed, the model checks if there is capacity to send more, if yes, a new agent is sent.
I know this is an unpleasant workaround, but it provides you with a solution until AnyLogic support can figure it out.

Reading from Socket Stream Blocking After Retrieval

I'm currently attempting to read an incoming message from a client socket, that, prior to the below procedure has already been connected to the server socket. The below procedure outputs the message, one character at a time, as it retrieves it from the stream.
The problem is that, when the stream is out of information, the call to Ada.Streams.Read is blocking, and stops the application flow completely. According to some examples, it would appear as though Offset should be set to 0 automatically at the end of the stream, but that never happens. Instead the application stops at the call to Read.
procedure Read_From (Channel : Sockets.Stream_Access) is
use Ada.Text_IO;
use Ada.Streams;
Data : Stream_Element_Array (1 .. 1);
Offset : Stream_Element_Offset;
begin
loop
Read (Channel.All, Data, Offset);
exit when Offset = 0;
Put (Character'Val (Data (1)));
end loop;
-- The application never reaches this point.
New_Line;
Put_Line ("Finished reading from client!");
end Read_From;
-- #param Channel `GNAT.Sockets.Stream (Client_Socket)`
I've also attempted the same process with GNAT.Sockets.Receive_Socket, but the same issue remains: the application flow is stopped completely, assumably awaiting further information from the stream, even though there is nothing more to retrieve.
Any pointers in the right direction would be highly appreciated!
Normally, you’d read a (binary) message from a stream knowing how much data needed to be read, so you could read until you’d got that much.
But, if you’re reading a text message from an externally-defined source, as it might be an HTTP request, there needs to be some terminator sequence so you can read character-by-character until you’ve read the terminator. In the case of an HTTP request, that’s a CR/LF/CR/LF sequence. Or it could be a null-terminated C string, in which case you’d be looking for the ASCII.NUL.
The Ada way to transfer variable-length text is to use String’Output/String’Input (see ARM 13.13.2(18)ff). What happens for a String (an array of Character) is that first the bounds are sent, then the content; on reception, the bounds are read, a String with those bounds is created, and the required number of bytes are read into the new String, which is then returned.
Basically that's how Ada streams work. The end of the stream only comes once you reach the final end of the stream, not just the current end of a buffer.
If you want to be able to interrupt reading, you have to use another representation of the connection than GNAT.Sockets.Stream_Access.

libspotify C sending zeros at the end of track

I'm using libspotify SDK, C library for win32.
I think to have a right setup, every session callback is registered. I don't understand why i can't receive the call for end_of_track, while music_delivery continues to be called with zero padding 22050 long frames.
I attempt to start playing first loading the track with sp_session_load; till it returns SP_ERROR_IS_LOADING I post a message on my message queue (synchronization method I've used, PostMessage win32 API) in order to reload again with same API sp_session_load. As soon as it returns SP_ERROR_OK I use the sp_session_play and the music_delivery starts immediately, with correct frames.
I don't know why at the end of track the libspotify runtime then start sending zero padded frames, instead of calling end_of_track callback.
In other conditions it works perfectly: I've used the sp_track obtained from a album browse, so the track is fully loaded at the moment I load to the current session for playing: with this track, it works fine with end_of_track called correctly. In the case with padding error, I search the track using its Spotify URI and got the results; in this case the track metadata are not still ready (at the play attempt) so I used that kind of "polling" on sp_session_load with PostMessage.
Can anybody help me?
I ran into the same problem and I think the issue was that I was consuming the data too fast without giving other threads time to do any work since I was spending all of my time in the music_delivery callback. I found that if I add some throttling and notify the main thread that it can wake up to do some processing, the extra zeros at the end of track is reduced to one delivery of 22,050 frames (or 500ms at 44.1kHz).
Here is an example of what I added to my callback, heavily borrowed from the jukebox.c example provided with the SDK:
/* Buffer 1 second of data, then notify the main thread to do some processing */
if (g_throttle > format->sample_rate) {
pthread_mutex_lock(&g_notify_mutex);
g_notify_do = 1;
pthread_cond_signal(&g_notify_cond);
pthread_mutex_unlock(&g_notify_mutex);
// Reset the throttle counter
g_throttle = 0;
return 0;
}
As I said, there was still 22,050 frames of zeros delivered before the track stopped, but I believe libspotify may purposely do this to ensure that the duration calculated by the number of frames received (song_duration_ms = total_frames_delivered / sample_rate * 1000) is greater than or equal to the duration reported by sp_track_duration. In my case, the track I was trying to stream was 172,000ms in duration, without the extra padding the duration calculated is 171,796ms, but with the padding it was 172,296ms.
Hope this helps.

socket receive loop never returns

I have a loop that reads from a socket in Lua:
socket = nmap.new_socket()
socket:connect(host, port)
socket:set_timeout(15000)
socket:send(command)
repeat
response,data = socket:receive_buf("\n", true)
output = output..data
until data == nil
Basically, the last line of the data does not contain a "\n" character, so is never read from the socket. But this loop just hangs and never completes. I basically need it to return whenever the "\n" delimeter is not recognised. Does anyone know a way to do this?
Cheers
Updated
to include socket code
Update2
OK I have got around the initial problem of waiting for a "\n" character by using the "receive_bytes" method.
New code:
--socket set as above
repeat
data = nil
response,data = socket:receive_bytes(5000)
output = output..data
until data == nil
return output
This works and I get the large complete block of data back. But I need to reduce the buffer size from 5000 bytes, as this is used in a recursive function and memory usage could get very high. I'm still having problems with my "until" condition however, and if I reduce the buffer size to a size that will require the method to loop, it just hangs after one iteration.
Update3
I have gotten around this problem using string.match and receive_bytes. I take in at least 80 bytes at a time. Then string.match checks to see if the data variable conatins a certain pattern. If so it exits. Its not the cleanest solution, but it works for what I need it to do. Here is the code:
repeat
response,data = socket:receive_bytes(80)
output = output..data
until string.match(data, "pattern")
return output
I believe the only way to deal with this situation in a socket is to set a timeout.
The following link has a little bit of info, but it's on http socket: lua http socket timeout
There is also this one (9.4 - Non-Preemptive Multithreading): http://www.lua.org/pil/9.4.html
And this question: http://lua-list.2524044.n2.nabble.com/luasocket-howto-read-write-Non-blocking-TPC-socket-td5792021.html
A good discussion on Socket can be found on this link:
http://nitoprograms.blogspot.com/2009/04/tcpip-net-sockets-faq.html
It's .NET but the concepts are general.
See update 3. Because the last part of the data is always the same pattern, I can read in a block of bytes and each time check if that block has the pattern. If it has the pattern it will mean that it is the end of the data, append to the output variable and exit.

How to get NSOutputStream to send or flush packets immediately

I am having an issue with latency when connecting to a bluetooth accessory using the External Accessory Framework. When sending data I get the following custom output in the console:
if( [stream hasSpaceAvailable] )
{
NSLog( #"Space avail" );
}
else {
NSLog(#"No space");
}
while( [stream hasSpaceAvailable] && ( [_outputBuffer length] > 0 ) )
{
/* write as many bytes as possible */
NSInteger written = [stream write:[_outputBuffer bytes] maxLength:[_outputBuffer length]];
NSLog( #"wrote %i out of %i bytes to the stream", written, [_outputBuffer length] );
if( written == -1 )
{
/* error, bad */
Log( #"Error writing bytes" );
break;
}
else if( written > 0 )
{
/* remove the bytes from the buffer that were written */
Log( #"erasing %i bytes", written );
[_outputBuffer replaceBytesInRange:NSMakeRange( 0, written ) withBytes:nil length:0 ];
}
}
This results with the following output where immediate pack buffer is the payload.
immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040010005
No space
immediate pack buffer-> 030040007
No space
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030010004
No space
immediate pack buffer-> 040000004
Space avail
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030000003
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream
Notice how it continually has "No Space" written which means that the method hasSpaceAvailable is returning false and forcing the data to be buffered until it returns true.
1) What I need to know is why is the happening? Is it waiting for an Ack from the BT hardware? If so how do you removing this blocking?
2) How do you do this so it sends immediately and we basically stream the data in real time without buffering?
3) Is there a hidden API method that will disable this blocking?
This is a real problem because there cannot be any delay/latency in sending the data to the device, it must be sent immediately in order for the hardware to be in sync with the iPhone commands. Please help.
What you're asking for is impossible with most hardware (which will finish sending the current packet before starting the next one), and impossible with the usual "stream" paradigm (which requires that data is received in order, so is bandwidth-limited).
It is also physically impossible to have zero latency unless the source and destination are coincident.
The actual problem seems to be that the underlying stream only queues one packet at a time, even if the packet is only 10 bytes long. I don't know why; possibly because it's intended as a very simple protocol.
The usual way of dealing with such a queue is to register for the appropriate delegate callbacks and send as much data as you can when the stream has space available, instead of waiting for the next time you attempt to send data (which appears to be what you're doing).
The problem is the HandleEvent delegate function is an asynchronous call.So every time it is not hitting the delegate.
What you can do is, have the collections of commands in an array at once, open the session, call the writeData Function.What happens here is, once the write data is called, you don't need the HandleEvent Function to be hit for every command.
Have a count incremented in writeData function for the count of array items,Until count == arrayItems, Delegate is not hit..
So all the commands from list are sent one by one.
I am facing the same issue but in different scenario.
Scenario: iPhone app is able to communicate the PED when gets connected for the first time. But when PED battery dies or switched off and then switched on, app is not able to communicate with PED in spite of active session and valid output stream. Output steam says its does not have spece to write anything.
Solution: When PED gets switched, app gets notified, and at that moment I make the app to kill EASession and create it again when PED gets connection. Not sure whether it is best solution. Please suggest another solution if there is any.