the original question concerned a webcam, which sends video frames via observables. these following frame processing (like filtering) takes longer than the cameras frame rate, which is why fresh video incoming frames might have to be discarded without postprocessing.
@tonfilm presented an elegant solution that is applicable in general (not only video processing) for situations where incoming observables might have to be discarded.
the situation in more detail:
- a camera provides new video frames as observables at a certain frame rate (e.g. 30fps)
- after the frames have come in, some CPU-intensive processing is to be applied. processing a frame takes longer than the frame interval of the camera → some incoming frames therefore have to be discarded before they are being processed.
- ideally the decision whether or not an incoming frame has to be discarded still takes place when they are in the observable context (i.e. not in VVVV/VLs main loop).
- also, all frame processing should take place in the observable context (to not block/throttle the main loop).
- when all nescessary work has finished the result can be retrieved in VL using e.g. HoldLatest(Reactive). (in the case of video frames they can be forwarded to VVVV as observables and displayed using UploadImage (Async)
general rule, try to use HoldLatest a late as possible, its actually pretty useful to stay out of the mainloop as long as possible, because then you don’t run into synchronzation troubles and often the event is on another thread which saves performance for the mainloop. also if the event fires not often or has a very low frame rate you save performance when you do more work there, because when the values update slowly you don’t need to do the calculation 60 timer per second
the solution suggested by @tonfilm works as follows:
- create a wrapper class “DataGate” that stores the data and has a field that signals whether or not some new data can be passed onwards for processing. it therefore has to fields:
- a boolean “gate”, acting as a flag
- a generic property, storing the data payload from the observable
observable processing is split in two parts.
- ForEach(Keep): whenever a new observable comes in, the flag of the DataGate object is checked.
- when the gate is closed, incoming data will be discarded, otherwise the payload data will be stored and the gate closed (SetDataAndCloseGate)
- the second ForEach(Reactive) retrieves the data payload and performs processing. only when the processing is finished the gate flag will be set to open again.
note: the “ToBackground” node in between the two loops is nescessary to move data references out from the event call stack, otherwise the references will be lost.
thanks again for your guidance!