nariakiiwatani / ofxNDI

NewTek NDI SDK Wrapper for openFrameworks.
https://ndi.tv/
MIT License
103 stars 19 forks source link

multiple streams from and to multiple computers #9

Closed stephanschulz closed 2 years ago

stephanschulz commented 5 years ago

Hi again. I have a question and hope you know the answer.

If I have 3 computers each run my OF app. Each app is sending the mic audio out via NDI. Now I need those same 3 computers with those same OF apps, to receive the NDI audio from all the others. Is that possible? Do the received streams appear as separate inputs? Do they have an ID or IP that can identify them by?

Thanks for your advice.

nariakiiwatani commented 5 years ago

Hi. I'm glad you seem to develop something with my addon!

Do they have an ID or IP that can identify them by?

Yes, you can identify them before connecting by checking ofxNDI::Source. I updated receiver examples so that you can see how to.

Do the received streams appear as separate inputs?

Yes. You will have ofxNDIRecvAudioFrameSync instances for each sender. You can get separate streams via ofxNDIRecvAudioFrameSync::decodeTo.

stephanschulz commented 5 years ago

cool. will give it a try. so if i know i will receive from 3 sources i would make a vector audio_; and set them up as in your example-audio-receiver example.

what if the receiver starts but not all sources/senders are running yet. would the receiver pick new sources up when they start sending? or do i need to auto sources = ofxNDI::listSources(); do what you do in setup once in a while to detect them?

nariakiiwatani commented 5 years ago

so if i know i will receive from 3 sources i would make a vector audio_; and set them up as in your example-audio-receiver example.

Yep. good luck! :)

what if the receiver starts but not all sources/senders are running yet.

I gave a quick test for kind of "connecting to future source". It seems to be possible by initializing ofxNDI::Source manually and edit p_ndi_name or p_url_address. (_note : if p_ndi_name was not blank, p_url_address would be ignored._) Then pass it to ofxNDIReceiver::setup.

teganscott commented 5 years ago

Hi @nariakiiwatani I am working on the same project as Stephan and am trying to solve the problem of having multiple audio streams at once. It seems to stream fine for a second until it picks up the second stream.

I have separate ofxNDIRecvAudioFrameSync for each instance of NDI audio streaming. In AudioOut I'm currently just listening to one ofxNDIRecvAudioFrameSync stored in a vector and using decodeTo to set it to the buffer.

If I use one ofxNDIReceiver for all instances of ofxNDIRecvAudioFrameSync I get a "BAD_ACCESS" error on NDIlib_recv_instance_t getInstance() const { return instance_;

If I use a receiver for each instance of ofxNDIRecvAudioFrameSync it works for a second and then throws an error for ofxNDIReceiver::isConnected() once the second stream is added.

Should there only be one ofxNDIReceiver per application? If so, how should it call the setup() method with multiple ofxNDI::Source Thank you for your help :)

nariakiiwatani commented 5 years ago

Hi, Could you show me the minimum source code to reproduce the error?

teganscott commented 5 years ago

Okay, dug a little deeper. When a new ofxNDIRecvAudioFrameSync is generated with each instance of the source then the connection issue occurs. If I overwrite the audio_ defined in the header and add it to the vector no connection issues occur, but of course, overwrites the previous instances and can no longer hear them through the buffer in AudioOut()

Here is the code, it is based on the example-audio-receiver project Thank you for getting back so quickly

https://gist.github.com/teganscott/c5b9f9db094cfc8eb8fa759ba0230ba1

nariakiiwatani commented 5 years ago

I found what's going on!

in your code, the second (when i==1) receivers.push_back(receive); causes the vector's reallocation. ref: https://stackoverflow.com/questions/5410035/when-does-a-stdvector-reallocate-its-memory-array

This means the original receiver which you added as receiver[0] is copied then its destructor is called. Therefore, the NDIlib_recv_instance_t instance_ and NDIlib_framesync_instance_t frame_sync_ go invalid.

There are many ways to fix it, the easiest one is, adding receivers.reserve(names.size()); before for loop.

For ofxNDI addon, maybe I should delete the copy constructor of ofxNDIReciever. But I have to consider deeper. give me time.

Thank you!

teganscott commented 5 years ago

Excellent that did the trick, thank you :)

2bbb commented 5 years ago

if you want to clear problem about resize about std::vector without delete copy operator, maybe you have to implement r-value constructor and r-value copy operator for std::swap that will not make invalid it.

good luck!

nariakiiwatani commented 5 years ago

@2bbb Ah hah, that's better! thank you!

2bbb commented 5 years ago

ah, but maybe you have to delete l-value copy cons and operator. and i think your understanding about universal reference is incomplete. let's study!