Skip to content

Adding unlink command#11

Open
paulharter wants to merge 4 commits into
roc-streaming:mainfrom
paulharter:unlink
Open

Adding unlink command#11
paulharter wants to merge 4 commits into
roc-streaming:mainfrom
paulharter:unlink

Conversation

@paulharter
Copy link
Copy Markdown
Contributor

Adds support for the unlink command in the roc-toolkit. This is useful to allow removal of endpoints without deleting the whole VAD, this in turn allows any applications using the VAD to continue doing so while streaming connections are made/unmade.

It seems to work ok in my testing but maybe I'm missing out some underlying additional clean up that ought be be done when unlinking a slot?

I have also added in a check on the number of tracks which modifies max_packet_size and max_frame_size to accommodate them with larger buffer sizes.

I had a little trouble getting grpc to compile with cmake 4 and so moved grpc on to v1.72.0. This has the unwanted side effect of removing the functions used in tool/main.cpp grpc_init. It looks like grpc have changed the way they manage log levels - I wasn't sure what the best solution to this is as it touches the rest of roc-vad's logging. If you have a suggestion I can look at fixing this.

P

Copy link
Copy Markdown
Member

@gavv gavv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for PR!

Comment thread driver/device.cpp
Comment on lines +319 to +325
for (unsigned i=0; i<info_.remote_endpoints.size(); ++i){
if (info_.remote_endpoints[i].slot == slot) {
info_.remote_endpoints.erase(info_.remote_endpoints.begin() + i);
return true;
}
}
return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor suggestions:

  1. Inline remove_slot_endpoint_() into unlink(). Manipulations with endpoint vectors are done directly in bind() and connect(), so it would be easier to follow if unlink() behaves similarly.

  2. Cover both remote_endpoints (updated by connect) and local_endpoints (updated by bind)

  3. Use std::remove_if:

Suggested change
for (unsigned i=0; i<info_.remote_endpoints.size(); ++i){
if (info_.remote_endpoints[i].slot == slot) {
info_.remote_endpoints.erase(info_.remote_endpoints.begin() + i);
return true;
}
}
return false;
if (auto new_end = std::remove_if(info_.remote_endpoints.begin(),
info_.remote_endpoints.end(),
[slot](const auto& endpoint) { return endpoint.slot == slot; });
new_end != info_.remote_endpoints.end()) {
info_.remote_endpoints.erase(new_end, info_.remote_endpoints.end());
}
// same for local_endpoints

Comment thread driver/driver_service.cpp
rvpb::RvNone* response)
{
return execute_command_("unlink", [=]() {
int slot = request->has_slot() ? request->slot() : 0;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Let's add roc_slot DEFAULT_SLOT = 0 to constants.hpp and use it here instead of 0.

Comment thread driver/receiver.cpp
Comment on lines +139 to +141
void Receiver::unlink(roc_slot slot)
{
throw std::invalid_argument("receiver device does not support unlink() currently");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason? I'd expect it should work for receiver too.

Comment thread driver/receiver.cpp
Comment on lines +29 to +32
if (device_encoding.channel_layout == ROC_CHANNEL_LAYOUT_MULTITRACK && device_encoding.channel_count > 4) {
net_context_config.max_packet_size = device_encoding.channel_count * 512;
net_context_config.max_frame_size = device_encoding.channel_count * 1024;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two suggestions:

  1. Extract this into max_packet_size() and max_frame_size() methods of DeviceLocalEncoding and reuse them in sender and receiver.

  2. Rework formulas roughly like this:

    max_frame_size = channel_count * 1024 * 4
    max_packet_size = channel_count * 1024 * 4 + 128
    

    Here, 1024 is max samples per packet, 4 is max bytes per sample, and 128 is max packet header size.

(Let me now if this approach works on your setup)

Comment on lines +70 to +74
if (use_uid_) {
fmt::println("unlinked device with uid \"{}\"", index_or_uid_);
} else {
fmt::println("unlinked device with index {}", index_);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (use_uid_) {
fmt::println("unlinked device with uid \"{}\"", index_or_uid_);
} else {
fmt::println("unlinked device with index {}", index_);
}
if (use_uid_) {
fmt::println("unlinked slot {} of device with uid \"{}\"",
slot_.value_or(0),
index_or_uid_);
} else {
fmt::println(
"unlinked slot {} of device with index {}", slot_.value_or(0), index_);
}

@gavv
Copy link
Copy Markdown
Member

gavv commented Jun 11, 2025

It seems to work ok in my testing but maybe I'm missing out some underlying additional clean up that ought be be done when unlinking a slot?

Looks legit.

I had a little trouble getting grpc to compile with cmake 4 and so moved grpc on to v1.72.0. [...] If you have a suggestion I can look at fixing this.

Thank you.

In another project, I did something like this:

// from grpc/third_party/abseil-cpp
#include <absl/log/check.h>
#include <absl/log/globals.h>
#include <absl/log/initialize.h>
#include <absl/log/log.h>
#include <absl/log/log_sink.h>
#include <absl/log/log_sink_registry.h>

class GrpcSink : public absl::LogSink
{
public:
    void Send(const absl::LogEntry& entry) override
    {
        // pass entry.log_severity() entry.text_message() to spdlog
    }
};

// in the beginning of main():

absl::InitializeLog();

absl::SetVLogLevel("*grpc*/*", 2);
absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);

GrpcSink grpc_sink;
absl::AddLogSink(&grpc_sink);

// before returning from main:

grpc_shutdown();

absl::RemoveLogSink(&grpc_sink);

spdlog::shutdown();

Would be great if you could add GrpcSink to tool/ and use it in main().

@gavv
Copy link
Copy Markdown
Member

gavv commented Jun 11, 2025

Regarding cmake 4:

  • I've pushed a commit that fixes it for roc-toolkit: roc-streaming/roc-toolkit@7d7d73c

    Since roc-vad pulls roc-toolkit master, it should be enough to do a full clean and rebuild to use it.

  • You may also need to bump libASPL to v3.1.2 in dependencies.cmake

@gavv
Copy link
Copy Markdown
Member

gavv commented Jun 11, 2025

BTW, may I ask, are you using roc-vad in some project or personally? Just curious!

@gavv gavv added the S-needs-revision status: Author should revise PR and address feedback label Jun 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-needs-revision status: Author should revise PR and address feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants