Hi list,
I've been hunting down a bandwidth problem in my little streaming plugin, and finally realized that the performance bottleneck actually is cRemux and its internal resultBuffer.
The resultBuffer is initialized with resultBuffer->SetTimeouts(0, 100), in other words, if no data is available, cRemux::Get will wait up to 100ms for data to arrive. Thats fine as long as cRemux is filled from another thread, but wastes time if cRemux is only filled from within the same thread.
Unfortunately, the resultBuffer is completely hidden inside the cRemux, so I cannot change this behavior. Does anyone have good ideas how to avoid this without spawning another thread? (the thread would actually just copy data from one buffer to another...)
This resultBuffer is really some kind of black hole, no way to control it, no way to know how much is in it...
Cheers,
Udo
Udo Richter wrote:
Hi list,
I've been hunting down a bandwidth problem in my little streaming plugin, and finally realized that the performance bottleneck actually is cRemux and its internal resultBuffer.
The resultBuffer is initialized with resultBuffer->SetTimeouts(0, 100), in other words, if no data is available, cRemux::Get will wait up to 100ms for data to arrive. Thats fine as long as cRemux is filled from another thread, but wastes time if cRemux is only filled from within the same thread.
Unfortunately, the resultBuffer is completely hidden inside the cRemux, so I cannot change this behavior. Does anyone have good ideas how to avoid this without spawning another thread? (the thread would actually just copy data from one buffer to another...)
This resultBuffer is really some kind of black hole, no way to control it, no way to know how much is in it...
Well, we could introduce
cRemux::SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
Klaus
Klaus Schmidinger wrote:
Udo Richter wrote:
Hi list,
I've been hunting down a bandwidth problem in my little streaming plugin, and finally realized that the performance bottleneck actually is cRemux and its internal resultBuffer.
The resultBuffer is initialized with resultBuffer->SetTimeouts(0, 100), in other words, if no data is available, cRemux::Get will wait up to 100ms for data to arrive. Thats fine as long as cRemux is filled from another thread, but wastes time if cRemux is only filled from within the same thread.
Unfortunately, the resultBuffer is completely hidden inside the cRemux, so I cannot change this behavior. Does anyone have good ideas how to avoid this without spawning another thread? (the thread would actually just copy data from one buffer to another...)
This resultBuffer is really some kind of black hole, no way to control it, no way to know how much is in it...
Well, we could introduce
cRemux::SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
Klaus
Haven't gotten any response on this suggestion so far. Would this solve your problem?
Klaus
Klaus Schmidinger wrote:
Well, we could introduce
cRemux::SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
Klaus
Haven't gotten any response on this suggestion so far. Would this solve your problem?
Oh, sorry. Yes, of course, this would work. My current workaround is to gain access using dirty tricks, so this is welcome. Access to Available() may be useful too. Or, for a bigger rewrite, what about making class cRemux : public cRingBufferLinear?
Cheers,
Udo
Udo Richter wrote:
Klaus Schmidinger wrote:
Well, we could introduce
cRemux::SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
Klaus
Haven't gotten any response on this suggestion so far. Would this solve your problem?
Oh, sorry. Yes, of course, this would work. My current workaround is to gain access using dirty tricks, so this is welcome. Access to Available() may be useful too. Or, for a bigger rewrite, what about making class cRemux : public cRingBufferLinear?
cRemux::Get() returns the number of currently available bytes.
Klaus
Klaus Schmidinger wrote:
cRemux::Get() returns the number of currently available bytes.
The number of currently available bytes *in one memory block*.
Without providing additional data through Put(), calls to Get() and Del() (deleting all data delivered by Get()) may succeed several times, before all internal buffers are drained and Get() returns Count=0. Usually it takes 1-2 calls to Get(), but sometimes up to 50 successful calls are possible.
Cheers,
Udo
Udo Richter wrote:
Klaus Schmidinger wrote:
cRemux::Get() returns the number of currently available bytes.
The number of currently available bytes *in one memory block*.
Without providing additional data through Put(), calls to Get() and Del() (deleting all data delivered by Get()) may succeed several times, before all internal buffers are drained and Get() returns Count=0. Usually it takes 1-2 calls to Get(), but sometimes up to 50 successful calls are possible.
I'm afraid I don't understand.
Why would you need access to the internal Available() function of the buffer?
Klaus
Klaus Schmidinger wrote:
I'm afraid I don't understand.
Why would you need access to the internal Available() function of the buffer?
There's no need to if the playback source can provide lots of data quickly and in advance. However, a network stream source is much more un-reliable, so knowing how much data is ready for playback would be nice. (Even nicer would be to know whether the output device did run out of data.)
Currently, my incoming buffers are empty most times, with an unknown amount of playback data in several hidden buffers. As a workaround, my remuxer doesn't get new data until Get() returns Count=0. But there are enough other buffers left...
Cheers,
Udo
Udo Richter wrote:
Klaus Schmidinger wrote:
I'm afraid I don't understand.
Why would you need access to the internal Available() function of the buffer?
There's no need to if the playback source can provide lots of data quickly and in advance. However, a network stream source is much more un-reliable, so knowing how much data is ready for playback would be nice. (Even nicer would be to know whether the output device did run out of data.)
Currently, my incoming buffers are empty most times, with an unknown amount of playback data in several hidden buffers. As a workaround, my remuxer doesn't get new data until Get() returns Count=0. But there are enough other buffers left...
Well, maybe I don't really understand your problem, but wouldn't it be better if you just run two separate threads, one that writes into cRemux and another that reads from it? That's how cRemux is supposed to be used, and apparently it works fine that way.
Klaus
Klaus Schmidinger wrote:
Well, maybe I don't really understand your problem, but wouldn't it be better if you just run two separate threads, one that writes into cRemux and another that reads from it? That's how cRemux is supposed to be used, and apparently it works fine that way.
Its not a 'problem', as it now works quite well. The current data flow is socket -> 2mb incoming buffer -> pre processing -> remuxing -> PlayPes, and it runs in a single thread from beginning to end. I could split this into several threads, but why? Why use a separate thread (plus all the syncing that would be required) just for copying from one buffer to the next?
Another reason not to thread cRemux: I still manage to keep 1.2.6 compatibility, and the 1.2.6 remuxer is only single threaded.
Cheers,
Udo
Udo Richter wrote:
Klaus Schmidinger wrote:
Well, maybe I don't really understand your problem, but wouldn't it be better if you just run two separate threads, one that writes into cRemux and another that reads from it? That's how cRemux is supposed to be used, and apparently it works fine that way.
Its not a 'problem', as it now works quite well. The current data flow is socket -> 2mb incoming buffer -> pre processing -> remuxing -> PlayPes, and it runs in a single thread from beginning to end. I could split this into several threads, but why? Why use a separate thread (plus all the syncing that would be required) just for copying from one buffer to the next?
Another reason not to thread cRemux: I still manage to keep 1.2.6 compatibility, and the 1.2.6 remuxer is only single threaded.
Yes, but I decided to make it multi threaded because I had trouble with it ;-)
Klaus