Vtk streaming encoding#35
Conversation
a57eaae to
7ad3479
Compare
|
FYI @Thibault-Pelletier @jourdain I am not a fan of the "window" terminology (the interface that handles the interaction and resize events). I remember we briefly discussed this at some point last year, but if you have any new naming ideas, I'd be happy to hear them |
43c6fcc to
1bf5570
Compare
1c5f358 to
fa45020
Compare
|
In general I like what you've done. |
fa45020 to
bc7e85e
Compare
|
Just an additional remark on this PR. vtkStreaming is currently leaking when resizing / rebuilding the encoder. |
with NVENC, VP9 seems to be ok |
80daa4a to
514ca00
Compare
Do we know the origin of the leak? |
| from weakref import WeakKeyDictionary, WeakValueDictionary | ||
|
|
||
| from trame_client.widgets.core import AbstractElement | ||
| from vtkmodules.vtkRenderingCore import vtkRenderWindow |
There was a problem hiding this comment.
RCA should not force VTK as a dependency.
We should have an easy path to handle vtkRenderWindow but it should not be forced if we plan to use RCA with a custom image generator.
There was a problem hiding this comment.
I've changed some imports on this matter. I now can run the vanilla example without having vtk installed. But if you can test on your side that nothing is missing it would be nice
44b3cf5 to
52b3afe
Compare
New available vtk-streaming wheel, v0.3.2, fixes the leak. |
52b3afe to
bcbba03
Compare
chore: rename window protocols and restructure video encoder feat(css): fix css for video decoder and add class names to components feat(logger): removed prints for logger info or warning feat(css): create css file that leverages new class names fix(rca): fixes video encoder with new wheel and update examples
bcbba03 to
fee73ff
Compare
|
Ready to merge @jourdain @Thibault-Pelletier |
| ] | ||
|
|
||
| self.name = kwargs.get("name") or f"trame_rca_{RemoteControlledArea._next_id}" | ||
| self.display = kwargs.get("display") |
There was a problem hiding this comment.
Do you want to provide a default in case nothing is provided?
self.display = kwargs.get("display", "image")
There was a problem hiding this comment.
Also do you know that self.display already exist because of that kwargs.
So a better way of writting it could be
def __init__(self, display="image", **kwargs):
super().__init__(
"remote-controlled-area",
display=display,
**kwargs,
)|
Looks good, but I guess I'll try it out before merging. |
edca7a7 to
0f64630
Compare
- resizing the frame is sufficient for the encoder to realize that it should shutdown existing session and open a new encoding session. - there was a bug upstream where setting width/height on the encoder did not bump the MTime of the encoder and so, the frame size was equal to the encoder size and the responsibility of re-initializing the context fell on the MTime logic which was flawed because the encoder did not bump the MTime. As a result, this code needed to manually call `_reset`. - this has been fixed upstream in Kitware/VTKStreaming#2, so I'm changing the code here.
|
|
||
| with layout.content: | ||
| view = rca.RemoteControlledArea( | ||
| display="video-decoder", |
There was a problem hiding this comment.
yup, the JS code for VideoDecoder needs reviewed.
There was a problem hiding this comment.
Follow up on this, I think the problem on my side is that we apply the pixel ratio twice (size sent by the browser is already the scaled up version). Commenting out the pixel ratio apply solves the problem and it was just hidden by the JS scaling for the image encoder.
@jourdain do you concur or is there an OS specific thing that may be happening here?
def update_size(self, origin, size):
# Resize to ten pixel min to avoid rendering problems
width = max(10, int(size.get("w", 300)))
height = max(10, int(size.get("h", 300)))
pixel_ratio = size.get("p", 1)
self._current_size = (width, height, pixel_ratio)
width = int(width * pixel_ratio * self._scale) # <-- incriminated lines
height = int(height * pixel_ratio * self._scale)|
I think the fps should not be hard-coded to 30. It gives an awful first impression for first-time users. Instead, we could be smart about it by getting the client's estimated refresh rate and transmit that to the server. let last = performance.now(), samples = [];
let fpsEstId;
function tick(now) {
samples.push(now - last); last = now;
if (samples.length >= 60) {
cancelAnimationFrame(fpsEstId);
const avg = samples.reduce((a,b)=>a+b)/samples.length;
// ~1000/avg is the refresh rate; send it to the server via state?
}
fpsEstId = requestAnimationFrame(tick);
}
fpsEstId = requestAnimationFrame(tick); |
The FPS can be manually set by the application to the desired value. It's actually something we do in trame-slicer with the snapshot RCA to limit the bandwidth for non interactive views to 10 FPS (switch is done interactively and can be changed through parameters). From my tests, 30 FPS works well in deployed applications on AWS with a reasonable bandwidth, but aiming higher may severely slow down the application as the application is not doing rendering only but also computation (although this bottleneck may be removed now that we have vtk streaming / NVENC). For first time users, we can easily increase the values in the examples. We can also add an option to have a smart FPS, but I would like to also be able to set a fixed target FPS and being able to toggle that from the application layer. EDIT: RCA will remain a bit more sluggish and add in some latency as you would have using any VNC / cloud streaming plateform but from my tests it remains a much nicer experience than using a desktop application (3D Slicer) through an AWS Appstream service. |

Handle video encoding using vtk-streaming lib
Changes:
utils.py(still exposing the classes)vtk_utils.py(still exposing the VtkWindow class)test_rca_utils.pypyproject.toml