mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
stream: Add get_stream_info() API calls
This is a new API call for streamers. It will allow peeking into the internal settings of streamers. The exact content of this call is device-specific. It varies a lot between RFNoC- and non-RFNoC devices. It can be used as follows: ```python my_usrp = uhd.usrp.MultiUSRP(device_args) rx_streamer = my_usrp.get_rx_stream(stream_args) print(rx_streamer.get_stream_info(0)) # Shows info about the streamer ``` For most use cases, this API is not required. It can help for debugging (e.g., compare flow control parameters with expectations, or identify EPIDs for a better understanding of Wireshark output), or it can be used for remote streaming, when a 3rd party application needs to know internal settings of streamers.
This commit is contained in:
parent
2af4ddb962
commit
2378080dbe
@ -350,6 +350,16 @@ public:
|
||||
*/
|
||||
virtual void post_input_action(
|
||||
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
|
||||
|
||||
/*! Return information about the current streamer object
|
||||
*
|
||||
* The contents of the returned dictionary depend on the current hardware
|
||||
* setup, the arguments with which this streamer was created, etc.
|
||||
*
|
||||
* \param chan The channel number for which to get stream info
|
||||
* \returns dictionary of streamer information
|
||||
*/
|
||||
virtual device_addr_t get_stream_info(const size_t chan = 0) const = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -422,6 +432,16 @@ public:
|
||||
*/
|
||||
virtual void post_output_action(
|
||||
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
|
||||
|
||||
/*! Return information about the current streamer object
|
||||
*
|
||||
* The contents of the returned dictionary depend on the current hardware
|
||||
* setup, the arguments with which this streamer was created, etc.
|
||||
*
|
||||
* \param chan The channel number for which to get stream info
|
||||
* \returns dictionary of streamer information
|
||||
*/
|
||||
virtual device_addr_t get_stream_info(const size_t chan = 0) const = 0;
|
||||
};
|
||||
|
||||
} // namespace uhd
|
||||
|
||||
@ -166,6 +166,7 @@ public:
|
||||
* \param epids Source and destination endpoint IDs
|
||||
* \param num_recv_frames Num frames to reserve from the recv link
|
||||
* \param fc_params Parameters for flow control
|
||||
* \param xport_args Stream transport arguments
|
||||
* \param disconnect Callback function to disconnect the links
|
||||
*/
|
||||
chdr_rx_data_xport(uhd::transport::io_service::sptr io_srv,
|
||||
@ -175,6 +176,7 @@ public:
|
||||
const uhd::rfnoc::sep_id_pair_t& epids,
|
||||
const size_t num_recv_frames,
|
||||
const fc_params_t& fc_params,
|
||||
const uhd::device_addr_t& xport_args,
|
||||
disconnect_callback_t disconnect);
|
||||
|
||||
/*! Destructor
|
||||
@ -218,6 +220,37 @@ public:
|
||||
return _mtu - _hdr_len;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get transport configuration information
|
||||
*
|
||||
* \return device_addr_t containing transport configuration parameters
|
||||
*/
|
||||
uhd::device_addr_t get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info = _xport_args;
|
||||
info["fc_freq_bytes"] = std::to_string(_fc_params.freq.bytes);
|
||||
info["fc_freq_packets"] = std::to_string(_fc_params.freq.packets);
|
||||
info["recv_capacity_bytes"] = std::to_string(_fc_params.buff_capacity.bytes);
|
||||
info["recv_capacity_packets"] = std::to_string(_fc_params.buff_capacity.packets);
|
||||
info["mtu"] = std::to_string(_mtu);
|
||||
info["chdr_hdr_len"] = std::to_string(_hdr_len);
|
||||
info["src_epid"] = std::to_string(_remote_epid);
|
||||
info["dst_epid"] = std::to_string(_epid);
|
||||
|
||||
// Determine flow control mode
|
||||
if (_fc_params.freq.bytes == 0 && _fc_params.freq.packets == 0) {
|
||||
info["fc_mode"] = "off";
|
||||
} else if (_fc_params.freq.packets == MAX_FC_FREQ_PKTS) {
|
||||
info["fc_mode"] = "byte";
|
||||
} else if (_fc_params.freq.bytes == MAX_FC_FREQ_BYTES) {
|
||||
info["fc_mode"] = "packet";
|
||||
} else {
|
||||
info["fc_mode"] = "mixed";
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Gets an RX frame buffer containing a recv packet
|
||||
*
|
||||
@ -442,9 +475,18 @@ private:
|
||||
// Local / Sink EPID
|
||||
sep_id_t _epid;
|
||||
|
||||
// Remote / Source EPID
|
||||
sep_id_t _remote_epid;
|
||||
|
||||
//! The CHDR width in bytes.
|
||||
size_t _chdr_w_bytes;
|
||||
|
||||
// Flow control parameters
|
||||
fc_params_t _fc_params;
|
||||
|
||||
// Transport arguments
|
||||
uhd::device_addr_t _xport_args;
|
||||
|
||||
// Disconnect callback
|
||||
disconnect_callback_t _disconnect;
|
||||
};
|
||||
|
||||
@ -298,6 +298,13 @@ public:
|
||||
_send_io->wait_for_dest_ready(UINT_MAX, 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get transport configuration information
|
||||
*
|
||||
* \return device_addr_t containing transport configuration parameters
|
||||
*/
|
||||
uhd::device_addr_t get_xport_info() const;
|
||||
|
||||
/*!
|
||||
* Writes header into frame buffer and returns payload pointer
|
||||
*
|
||||
@ -492,6 +499,9 @@ private:
|
||||
//! The size of the send frame
|
||||
size_t _frame_size;
|
||||
|
||||
// Flow control parameters
|
||||
fc_params_t _fc_params;
|
||||
|
||||
// Disconnect callback
|
||||
disconnect_callback_t _disconnect;
|
||||
};
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <uhd/convert.hpp>
|
||||
#include <uhd/exception.hpp>
|
||||
#include <uhd/stream.hpp>
|
||||
#include <uhd/types/device_addr.hpp>
|
||||
#include <uhd/types/endianness.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhdlib/transport/rx_streamer_zero_copy.hpp>
|
||||
@ -79,6 +80,7 @@ public:
|
||||
: _zero_copy_streamer(num_ports)
|
||||
, _in_buffs(num_ports)
|
||||
, _chans_connected(num_ports, false)
|
||||
, _stream_info(num_ports, stream_args.args)
|
||||
{
|
||||
if (stream_args.cpu_format.empty()) {
|
||||
throw uhd::value_error("[rx_stream] Must provide a cpu_format!");
|
||||
@ -127,6 +129,49 @@ public:
|
||||
return _spp;
|
||||
}
|
||||
|
||||
//! Get stream info
|
||||
uhd::device_addr_t get_stream_info(const size_t chan) const override
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_stream_info");
|
||||
}
|
||||
|
||||
// Start with filtered base stream info (exclude underscore keys)
|
||||
uhd::device_addr_t stream_info;
|
||||
for (const auto& key : _stream_info[chan].keys()) {
|
||||
if (!key.empty() && key[0] != '_') {
|
||||
stream_info[key] = _stream_info[chan][key];
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get transport info and merge it
|
||||
try {
|
||||
uhd::device_addr_t xport_info = _zero_copy_streamer.get_xport_info(chan);
|
||||
// Merge transport info into stream info, filtering out keys starting with
|
||||
// underscore
|
||||
for (const auto& key : xport_info.keys()) {
|
||||
if (!key.empty() && key[0] != '_') {
|
||||
stream_info[key] = xport_info[key];
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
// If getting transport info fails, just return the basic stream info
|
||||
// This handles cases where transport doesn't support get_xport_info()
|
||||
}
|
||||
|
||||
return stream_info;
|
||||
}
|
||||
|
||||
//! Update stream info
|
||||
void update_stream_info(
|
||||
const size_t chan, const std::string& key, const std::string& value)
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for update_stream_info");
|
||||
}
|
||||
_stream_info[chan][key] = value;
|
||||
}
|
||||
|
||||
/*! Get width of each over-the-wire item component. For complex items,
|
||||
* returns the width of one component only (real or imaginary).
|
||||
*/
|
||||
@ -208,6 +253,7 @@ protected:
|
||||
void set_scale_factor(const size_t chan, const double scale_factor)
|
||||
{
|
||||
_converters[chan]->set_scalar(scale_factor);
|
||||
_stream_info[chan]["scale_factor"] = std::to_string(scale_factor);
|
||||
}
|
||||
|
||||
//! set maximum number of sample (per packet)
|
||||
@ -404,6 +450,8 @@ private:
|
||||
for (size_t i = 0; i < num_ports; i++) {
|
||||
_converters.push_back(convert::get_converter(id)());
|
||||
_converters.back()->set_scalar(1 / 32767.0);
|
||||
_stream_info[i]["cpu_format"] = stream_args.cpu_format;
|
||||
_stream_info[i]["otw_format"] = stream_args.otw_format;
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,6 +500,9 @@ private:
|
||||
// Flag to store if all channels are connected. This is to speed up the lookup
|
||||
// of all channels' connected-status.
|
||||
bool _all_chans_connected = false;
|
||||
|
||||
// Stream information storage
|
||||
std::vector<uhd::device_addr_t> _stream_info;
|
||||
};
|
||||
|
||||
}} // namespace uhd::transport
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
#include <uhd/config.hpp>
|
||||
#include <uhd/exception.hpp>
|
||||
#include <uhd/types/device_addr.hpp>
|
||||
#include <uhd/types/metadata.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhdlib/transport/get_aligned_buffs.hpp>
|
||||
@ -127,6 +128,21 @@ public:
|
||||
return _xports.size();
|
||||
}
|
||||
|
||||
//! Get transport info for a specific channel
|
||||
uhd::device_addr_t get_xport_info(const size_t chan) const
|
||||
{
|
||||
if (chan >= _xports.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_xport_info");
|
||||
}
|
||||
|
||||
if (!_xports[chan]) {
|
||||
return uhd::device_addr_t(); // Return empty if no transport connected
|
||||
}
|
||||
|
||||
// Call get_xport_info() on the underlying transport
|
||||
return _xports[chan]->get_xport_info();
|
||||
}
|
||||
|
||||
//! Configures tick rate for conversion of timestamp
|
||||
void set_tick_rate(const double rate)
|
||||
{
|
||||
|
||||
@ -110,6 +110,7 @@ public:
|
||||
, _zero_buffs(num_chans, &_zero)
|
||||
, _out_buffs(num_chans)
|
||||
, _chans_connected(num_chans, false)
|
||||
, _stream_info(num_chans, stream_args.args)
|
||||
{
|
||||
if ((stream_args.args.cast<std::string>("transmit_policy", "default")
|
||||
== "stop_on_seq_error")
|
||||
@ -154,6 +155,49 @@ public:
|
||||
return _spp;
|
||||
}
|
||||
|
||||
//! Get stream info
|
||||
uhd::device_addr_t get_stream_info(const size_t chan) const override
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_stream_info");
|
||||
}
|
||||
|
||||
// Start with filtered base stream info (exclude underscore keys)
|
||||
uhd::device_addr_t stream_info;
|
||||
for (const auto& key : _stream_info[chan].keys()) {
|
||||
if (!key.empty() && key[0] != '_') {
|
||||
stream_info[key] = _stream_info[chan][key];
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get transport info and merge it
|
||||
try {
|
||||
uhd::device_addr_t xport_info = _zero_copy_streamer.get_xport_info(chan);
|
||||
// Merge transport info into stream info, filtering out keys starting with
|
||||
// underscore
|
||||
for (const auto& key : xport_info.keys()) {
|
||||
if (!key.empty() && key[0] != '_') {
|
||||
stream_info[key] = xport_info[key];
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
// If getting transport info fails, just return the basic stream info
|
||||
// This handles cases where transport doesn't support get_xport_info()
|
||||
}
|
||||
|
||||
return stream_info;
|
||||
}
|
||||
|
||||
//! Update stream info
|
||||
void update_stream_info(
|
||||
const size_t chan, const std::string& key, const std::string& value)
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for update_stream_info");
|
||||
}
|
||||
_stream_info[chan][key] = value;
|
||||
}
|
||||
|
||||
/*! Get width of each over-the-wire item component. For complex items,
|
||||
* returns the width of one component only (real or imaginary).
|
||||
*/
|
||||
@ -391,6 +435,7 @@ protected:
|
||||
void set_scale_factor(const size_t chan, const double scale_factor)
|
||||
{
|
||||
_converters[chan]->set_scalar(scale_factor);
|
||||
_stream_info[chan]["scale_factor"] = std::to_string(scale_factor);
|
||||
}
|
||||
|
||||
//! Configures sample rate for conversion of timestamp
|
||||
@ -483,6 +528,8 @@ private:
|
||||
for (size_t i = 0; i < num_chans; i++) {
|
||||
_converters.push_back(convert::get_converter(id)());
|
||||
_converters.back()->set_scalar(32767.0);
|
||||
_stream_info[i]["cpu_format"] = stream_args.cpu_format;
|
||||
_stream_info[i]["otw_format"] = stream_args.otw_format;
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,6 +576,9 @@ private:
|
||||
// Flag to store if all channels are connected. This is to speed up the lookup
|
||||
// of all channels' connected-status.
|
||||
bool _all_chans_connected = false;
|
||||
|
||||
// Stream information storage
|
||||
std::vector<uhd::device_addr_t> _stream_info;
|
||||
};
|
||||
|
||||
}} // namespace uhd::transport
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <uhd/config.hpp>
|
||||
#include <uhd/exception.hpp>
|
||||
#include <uhd/stream.hpp>
|
||||
#include <uhd/types/metadata.hpp>
|
||||
#include <vector>
|
||||
@ -76,6 +77,18 @@ public:
|
||||
_bytes_per_item = bpi;
|
||||
}
|
||||
|
||||
//! Get transport configuration information for the specified channel
|
||||
uhd::device_addr_t get_xport_info(const size_t channel) const
|
||||
{
|
||||
if (channel >= _xports.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_xport_info");
|
||||
}
|
||||
if (!_xports[channel]) {
|
||||
throw uhd::runtime_error("Channel not connected");
|
||||
}
|
||||
return _xports[channel]->get_xport_info();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Gets a set of frame buffers, one per channel.
|
||||
*
|
||||
|
||||
@ -38,12 +38,16 @@ chdr_rx_data_xport::chdr_rx_data_xport(uhd::transport::io_service::sptr io_srv,
|
||||
const uhd::rfnoc::sep_id_pair_t& epids,
|
||||
const size_t num_recv_frames,
|
||||
const fc_params_t& fc_params,
|
||||
const uhd::device_addr_t& xport_args,
|
||||
disconnect_callback_t disconnect)
|
||||
: _fc_state(epids, fc_params.freq)
|
||||
, _mtu(recv_link->get_recv_frame_size())
|
||||
, _fc_sender(pkt_factory, epids)
|
||||
, _epid(epids.second)
|
||||
, _remote_epid(epids.first)
|
||||
, _chdr_w_bytes(chdr_w_to_bits(pkt_factory.get_chdr_w()) / 8)
|
||||
, _fc_params(fc_params)
|
||||
, _xport_args(xport_args)
|
||||
, _disconnect(disconnect)
|
||||
{
|
||||
UHD_LOG_TRACE("XPORT::RX_DATA_XPORT",
|
||||
|
||||
@ -42,6 +42,7 @@ chdr_tx_data_xport::chdr_tx_data_xport(uhd::transport::io_service::sptr io_srv,
|
||||
, _epid(epids.first)
|
||||
, _chdr_w_bytes(chdr_w_to_bits(pkt_factory.get_chdr_w()) / 8)
|
||||
, _frame_size(send_link->get_send_frame_size())
|
||||
, _fc_params(fc_params)
|
||||
, _disconnect(disconnect)
|
||||
{
|
||||
UHD_LOG_TRACE("XPORT::TX_DATA_XPORT",
|
||||
@ -299,3 +300,33 @@ chdr_tx_data_xport::configure_sep(io_service::sptr io_srv,
|
||||
fc_freq_ratio,
|
||||
fc_headroom_ratio);
|
||||
}
|
||||
|
||||
uhd::device_addr_t chdr_tx_data_xport::get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["mtu"] = std::to_string(_mtu);
|
||||
info["frame_size"] = std::to_string(_frame_size);
|
||||
info["src_epid"] = std::to_string(_epid);
|
||||
info["dst_epid"] = std::to_string(_send_header.get_dst_epid());
|
||||
info["send_capacity_bytes"] = std::to_string(_fc_params.buff_capacity.bytes);
|
||||
info["send_capacity_packets"] = std::to_string(_fc_params.buff_capacity.packets);
|
||||
|
||||
// For TX transport, flow control mode is determined by buffer capacity
|
||||
// TX sends strc packets for resync, so if buff_capacity is non-zero, FC is enabled
|
||||
if (_fc_params.buff_capacity.bytes == 0 && _fc_params.buff_capacity.packets == 0) {
|
||||
info["fc_mode"] = "off";
|
||||
} else {
|
||||
// TX uses buffer-based flow control - mode depends on non-zero capacity field
|
||||
if (_fc_params.buff_capacity.packets > 0
|
||||
&& _fc_params.buff_capacity.bytes == MAX_FC_CAPACITY_BYTES) {
|
||||
info["fc_mode"] = "packet";
|
||||
} else if (_fc_params.buff_capacity.bytes > 0
|
||||
&& _fc_params.buff_capacity.packets == MAX_FC_CAPACITY_PKTS) {
|
||||
info["fc_mode"] = "byte";
|
||||
} else {
|
||||
info["fc_mode"] = "mixed";
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -134,6 +134,7 @@ void export_stream(py::module& m)
|
||||
py::arg("timeout") = 0.1)
|
||||
.def("get_num_channels", &uhd::rx_streamer::get_num_channels)
|
||||
.def("get_max_num_samps", &uhd::rx_streamer::get_max_num_samps)
|
||||
.def("get_stream_info", &uhd::rx_streamer::get_stream_info, py::arg("chan") = 0)
|
||||
.def("issue_stream_cmd", &uhd::rx_streamer::issue_stream_cmd);
|
||||
|
||||
py::class_<tx_streamer, tx_streamer::sptr>(m, "tx_streamer", "See: uhd::tx_streamer")
|
||||
@ -145,6 +146,7 @@ void export_stream(py::module& m)
|
||||
py::arg("timeout") = 0.1)
|
||||
.def("get_num_channels", &tx_streamer::get_num_channels)
|
||||
.def("get_max_num_samps", &tx_streamer::get_max_num_samps)
|
||||
.def("get_stream_info", &uhd::tx_streamer::get_stream_info, py::arg("chan") = 0)
|
||||
.def("recv_async_msg",
|
||||
&wrap_recv_async_msg,
|
||||
py::arg("async_metadata"),
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <uhd/stream.hpp>
|
||||
#include <uhd/transport/vrt_if_packet.hpp>
|
||||
#include <uhd/transport/zero_copy.hpp>
|
||||
#include <uhd/types/device_addr.hpp>
|
||||
#include <uhd/types/metadata.hpp>
|
||||
#include <uhd/utils/byteswap.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
@ -802,9 +803,18 @@ private:
|
||||
class recv_packet_streamer : public recv_packet_handler, public rx_streamer
|
||||
{
|
||||
public:
|
||||
recv_packet_streamer(const size_t max_num_samps)
|
||||
recv_packet_streamer(const size_t max_num_samps, uhd::device_addr_t stream_args)
|
||||
: _max_num_samps(max_num_samps)
|
||||
, _base_stream_args(stream_args)
|
||||
, _stream_info(this->size(), stream_args)
|
||||
{
|
||||
_max_num_samps = max_num_samps;
|
||||
}
|
||||
|
||||
//! Override resize to also resize stream info
|
||||
void resize(const size_t size)
|
||||
{
|
||||
recv_packet_handler::resize(size);
|
||||
_stream_info.resize(size, _base_stream_args);
|
||||
}
|
||||
|
||||
size_t get_num_channels(void) const override
|
||||
@ -839,8 +849,28 @@ public:
|
||||
throw uhd::not_implemented_error("post_input_action is not implemented here!");
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_stream_info(const size_t chan) const override
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_stream_info");
|
||||
}
|
||||
return _stream_info[chan];
|
||||
}
|
||||
|
||||
void update_stream_info(
|
||||
const size_t chan, const std::string& key, const std::string& value)
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for update_stream_info");
|
||||
}
|
||||
_stream_info[chan][key] = value;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _max_num_samps;
|
||||
|
||||
uhd::device_addr_t _base_stream_args;
|
||||
std::vector<uhd::device_addr_t> _stream_info;
|
||||
};
|
||||
|
||||
}}} // namespace uhd::transport::sph
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <uhd/stream.hpp>
|
||||
#include <uhd/transport/vrt_if_packet.hpp>
|
||||
#include <uhd/transport/zero_copy.hpp>
|
||||
#include <uhd/types/device_addr.hpp>
|
||||
#include <uhd/types/metadata.hpp>
|
||||
#include <uhd/utils/byteswap.hpp>
|
||||
#include <uhd/utils/tasks.hpp>
|
||||
@ -389,12 +390,21 @@ private:
|
||||
class send_packet_streamer : public send_packet_handler, public tx_streamer
|
||||
{
|
||||
public:
|
||||
send_packet_streamer(const size_t max_num_samps)
|
||||
send_packet_streamer(const size_t max_num_samps, uhd::device_addr_t stream_args)
|
||||
: _max_num_samps(max_num_samps)
|
||||
, _base_stream_args(stream_args)
|
||||
, _stream_info(this->size(), stream_args)
|
||||
{
|
||||
_max_num_samps = max_num_samps;
|
||||
this->set_max_samples_per_packet(_max_num_samps);
|
||||
}
|
||||
|
||||
//! Override resize to also resize stream info
|
||||
void resize(const size_t size)
|
||||
{
|
||||
send_packet_handler::resize(size);
|
||||
_stream_info.resize(size, _base_stream_args);
|
||||
}
|
||||
|
||||
size_t get_num_channels(void) const override
|
||||
{
|
||||
return this->size();
|
||||
@ -425,8 +435,28 @@ public:
|
||||
throw uhd::not_implemented_error("post_output_action is not implemented here!");
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_stream_info(const size_t chan) const override
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for get_stream_info");
|
||||
}
|
||||
return _stream_info[chan];
|
||||
}
|
||||
|
||||
void update_stream_info(
|
||||
const size_t chan, const std::string& key, const std::string& value)
|
||||
{
|
||||
if (chan >= _stream_info.size()) {
|
||||
throw uhd::index_error("Invalid channel index for update_stream_info");
|
||||
}
|
||||
_stream_info[chan][key] = value;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _max_num_samps;
|
||||
|
||||
uhd::device_addr_t _base_stream_args;
|
||||
std::vector<uhd::device_addr_t> _stream_info;
|
||||
};
|
||||
|
||||
}}} // namespace uhd::transport::sph
|
||||
|
||||
@ -144,7 +144,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
std::shared_ptr<sph::recv_packet_streamer> my_streamer =
|
||||
std::make_shared<sph::recv_packet_streamer>(spp);
|
||||
std::make_shared<sph::recv_packet_streamer>(spp, args.args);
|
||||
|
||||
// init some streamer stuff
|
||||
my_streamer->resize(args.channels.size());
|
||||
@ -209,7 +209,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
std::shared_ptr<sph::send_packet_streamer> my_streamer =
|
||||
std::make_shared<sph::send_packet_streamer>(spp);
|
||||
std::make_shared<sph::send_packet_streamer>(spp, args.args);
|
||||
|
||||
// init some streamer stuff
|
||||
my_streamer->resize(args.channels.size());
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "../../transport/super_send_packet_handler.hpp"
|
||||
#include "b200_impl.hpp"
|
||||
#include "b200_regs.hpp"
|
||||
#include <uhd/utils/cast.hpp>
|
||||
#include <uhd/utils/math.hpp>
|
||||
#include <uhdlib/usrp/common/async_packet_handler.hpp>
|
||||
#include <uhdlib/usrp/common/validate_subdev_spec.hpp>
|
||||
@ -213,6 +214,10 @@ void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate)
|
||||
my_streamer->set_samp_rate(rate);
|
||||
const double adj = _radio_perifs[dspno].ddc->get_scaling_adjustment();
|
||||
my_streamer->set_scale_factor(adj);
|
||||
// Update scale factor for all channels
|
||||
for (size_t chan = 0; chan < my_streamer->get_num_channels(); chan++) {
|
||||
my_streamer->update_stream_info(chan, "scale_factor", uhd::cast::to_str(adj));
|
||||
}
|
||||
_codec_mgr->check_bandwidth(rate, "Rx");
|
||||
}
|
||||
|
||||
@ -240,6 +245,10 @@ void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate)
|
||||
my_streamer->set_samp_rate(rate);
|
||||
const double adj = _radio_perifs[dspno].duc->get_scaling_adjustment();
|
||||
my_streamer->set_scale_factor(adj);
|
||||
// Update scale factor for all channels
|
||||
for (size_t chan = 0; chan < my_streamer->get_num_channels(); chan++) {
|
||||
my_streamer->update_stream_info(chan, "scale_factor", uhd::cast::to_str(adj));
|
||||
}
|
||||
_codec_mgr->check_bandwidth(rate, "Tx");
|
||||
}
|
||||
|
||||
@ -440,7 +449,7 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
if (not my_streamer)
|
||||
my_streamer = std::make_shared<sph::recv_packet_streamer>(spp);
|
||||
my_streamer = std::make_shared<sph::recv_packet_streamer>(spp, args.args);
|
||||
my_streamer->resize(args.channels.size());
|
||||
|
||||
// init some streamer stuff
|
||||
@ -453,6 +462,8 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t& args_)
|
||||
id.output_format = args.cpu_format;
|
||||
id.num_outputs = 1;
|
||||
my_streamer->set_converter(id);
|
||||
my_streamer->update_stream_info(stream_i, "cpu_format", args.cpu_format);
|
||||
my_streamer->update_stream_info(stream_i, "otw_format", args.otw_format);
|
||||
|
||||
perif.framer->clear();
|
||||
perif.framer->set_nsamps_per_packet(spp);
|
||||
@ -472,6 +483,7 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t& args_)
|
||||
std::bind(&rx_vita_core_3000::issue_stream_command,
|
||||
perif.framer,
|
||||
std::placeholders::_1));
|
||||
my_streamer->update_stream_info(stream_i, "sid", uhd::cast::to_str(sid));
|
||||
perif.rx_streamer = my_streamer; // store weak pointer
|
||||
|
||||
// sets all tick and samp rates on this streamer
|
||||
@ -569,7 +581,7 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
if (not my_streamer)
|
||||
my_streamer = std::make_shared<sph::send_packet_streamer>(spp);
|
||||
my_streamer = std::make_shared<sph::send_packet_streamer>(spp, args.args);
|
||||
my_streamer->resize(args.channels.size());
|
||||
|
||||
// init some streamer stuff
|
||||
@ -582,6 +594,8 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t& args_)
|
||||
id.output_format = args.otw_format + "_item32_le";
|
||||
id.num_outputs = 1;
|
||||
my_streamer->set_converter(id);
|
||||
my_streamer->update_stream_info(stream_i, "cpu_format", args.cpu_format);
|
||||
my_streamer->update_stream_info(stream_i, "otw_format", args.otw_format);
|
||||
|
||||
perif.deframer->clear();
|
||||
perif.deframer->setup(args);
|
||||
@ -594,8 +608,9 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t& args_)
|
||||
_async_task_data->async_md,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
my_streamer->set_xport_chan_sid(
|
||||
stream_i, true, radio_index ? B200_TX_DATA1_SID : B200_TX_DATA0_SID);
|
||||
const auto sid = radio_index ? B200_TX_DATA1_SID : B200_TX_DATA0_SID;
|
||||
my_streamer->set_xport_chan_sid(stream_i, true, sid);
|
||||
my_streamer->update_stream_info(stream_i, "sid", uhd::cast::to_str(sid));
|
||||
my_streamer->set_enable_trailer(false); // TODO not implemented trailer support
|
||||
// yet
|
||||
perif.tx_streamer = my_streamer; // store weak pointer
|
||||
|
||||
@ -332,6 +332,7 @@ mpmd_mboard_impl::mpmd_mb_iface::make_rx_data_transport(
|
||||
epids,
|
||||
recv_link->get_num_recv_frames(),
|
||||
fc_params,
|
||||
xport_args,
|
||||
[io_srv_mgr, recv_link, send_link]() {
|
||||
io_srv_mgr->disconnect_links(recv_link, send_link);
|
||||
});
|
||||
|
||||
@ -375,6 +375,13 @@ public:
|
||||
"post_input_action is currently not implemented here!");
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_stream_info(const size_t /*chan*/) const override
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["max_num_samps"] = std::to_string(_max_num_samps);
|
||||
return info;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _max_num_samps;
|
||||
soft_time_ctrl::sptr _stc;
|
||||
@ -445,6 +452,13 @@ public:
|
||||
"post_output_action is currently not implemented here!");
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_stream_info(const size_t /*chan*/) const override
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["max_num_samps"] = std::to_string(_max_num_samps);
|
||||
return info;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _max_num_samps;
|
||||
soft_time_ctrl::sptr _stc;
|
||||
|
||||
@ -462,7 +462,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
std::shared_ptr<sph::recv_packet_streamer> my_streamer =
|
||||
std::make_shared<sph::recv_packet_streamer>(spp);
|
||||
std::make_shared<sph::recv_packet_streamer>(spp, args.args);
|
||||
|
||||
// init some streamer stuff
|
||||
my_streamer->resize(args.channels.size());
|
||||
@ -540,7 +540,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t& args_)
|
||||
|
||||
// make the new streamer given the samples per packet
|
||||
std::shared_ptr<sph::send_packet_streamer> my_streamer =
|
||||
std::make_shared<sph::send_packet_streamer>(spp);
|
||||
std::make_shared<sph::send_packet_streamer>(spp, args.args);
|
||||
|
||||
// init some streamer stuff
|
||||
my_streamer->resize(args.channels.size());
|
||||
|
||||
@ -277,6 +277,7 @@ uhd::rfnoc::chdr_rx_data_xport::uptr x300_impl::x300_mb_iface::make_rx_data_tran
|
||||
epids,
|
||||
recv_link->get_num_recv_frames(),
|
||||
fc_params,
|
||||
xport_args,
|
||||
[io_srv_mgr, recv_link, send_link]() {
|
||||
io_srv_mgr->disconnect_links(recv_link, send_link);
|
||||
});
|
||||
|
||||
@ -109,6 +109,14 @@ public:
|
||||
return get_mtu() - get_chdr_hdr_len();
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["type"] = "mock_rx_data_xport";
|
||||
info["mtu"] = std::to_string(get_mtu());
|
||||
return info;
|
||||
}
|
||||
|
||||
private:
|
||||
mock_recv_link::sptr _recv_link;
|
||||
size_t _seq_num = 0;
|
||||
@ -901,3 +909,53 @@ BOOST_AUTO_TEST_CASE(test_recv_zero_samples)
|
||||
// 1 seconds
|
||||
BOOST_CHECK_LE(elapsed_time.count(), 1.5);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_get_stream_info)
|
||||
{
|
||||
const std::string cpu_format("fc32");
|
||||
const std::string otw_format("sc16");
|
||||
const size_t num_chans = 2;
|
||||
|
||||
auto recv_links = make_links(num_chans);
|
||||
|
||||
// Create stream args with both formats
|
||||
uhd::stream_args_t stream_args(cpu_format, otw_format);
|
||||
auto streamer = std::make_shared<mock_rx_streamer>(num_chans, stream_args);
|
||||
streamer->set_tick_rate(TICK_RATE);
|
||||
streamer->set_samp_rate(SAMP_RATE);
|
||||
|
||||
// Connect channels
|
||||
for (size_t i = 0; i < num_chans; i++) {
|
||||
mock_rx_data_xport::uptr xport(
|
||||
std::make_unique<mock_rx_data_xport>(recv_links[i]));
|
||||
streamer->set_scale_factor(i, SCALE_FACTOR);
|
||||
streamer->connect_channel(i, std::move(xport));
|
||||
}
|
||||
|
||||
// Test stream info for each channel
|
||||
for (size_t chan = 0; chan < num_chans; chan++) {
|
||||
uhd::device_addr_t stream_info = streamer->get_stream_info(chan);
|
||||
|
||||
// Check basic stream info
|
||||
BOOST_CHECK_EQUAL(stream_info["cpu_format"], cpu_format);
|
||||
BOOST_CHECK_EQUAL(stream_info["otw_format"], otw_format);
|
||||
BOOST_CHECK_EQUAL(stream_info["scale_factor"], std::to_string(SCALE_FACTOR));
|
||||
|
||||
// Check transport info is merged
|
||||
BOOST_CHECK_EQUAL(stream_info["type"], "mock_rx_data_xport");
|
||||
BOOST_CHECK_EQUAL(stream_info["mtu"], std::to_string(FRAME_SIZE));
|
||||
|
||||
// Test that no underscore-prefixed keys are present
|
||||
for (const auto& key : stream_info.keys()) {
|
||||
BOOST_CHECK(key.empty() || key[0] != '_');
|
||||
}
|
||||
|
||||
std::cout << "RX Channel " << chan << " stream info:" << std::endl;
|
||||
for (const auto& key : stream_info.keys()) {
|
||||
std::cout << " " << key << " = " << stream_info[key] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Test invalid channel index
|
||||
BOOST_CHECK_THROW(streamer->get_stream_info(num_chans), uhd::index_error);
|
||||
}
|
||||
|
||||
@ -91,6 +91,14 @@ public:
|
||||
return get_mtu() - sizeof(packet_info_t);
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["type"] = "mock_rx_data_xport";
|
||||
info["mtu"] = std::to_string(get_mtu());
|
||||
return info;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _buff_size;
|
||||
buff_t::uptr _buff;
|
||||
@ -164,6 +172,14 @@ public:
|
||||
return get_mtu() - sizeof(packet_info_t);
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["type"] = "mock_tx_data_xport";
|
||||
info["mtu"] = std::to_string(get_mtu());
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
size_t _buff_size;
|
||||
@ -335,6 +351,7 @@ static std::shared_ptr<rx_streamer_mock_link> make_rx_streamer_mock_link(
|
||||
epids,
|
||||
send_link->get_num_send_frames(),
|
||||
fc_params,
|
||||
uhd::device_addr_t(), // Empty xport_args for test
|
||||
[io_srv = io_srv, recv_link, send_link]() {
|
||||
io_srv->detach_recv_link(recv_link);
|
||||
io_srv->detach_send_link(send_link);
|
||||
|
||||
@ -70,6 +70,14 @@ public:
|
||||
return get_mtu() - get_chdr_hdr_len();
|
||||
}
|
||||
|
||||
uhd::device_addr_t get_xport_info() const
|
||||
{
|
||||
uhd::device_addr_t info;
|
||||
info["type"] = "mock_tx_data_xport";
|
||||
info["mtu"] = std::to_string(get_mtu());
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
mock_send_link::sptr _send_link;
|
||||
@ -699,3 +707,55 @@ BOOST_AUTO_TEST_CASE(test_spp)
|
||||
streamer->get_max_num_samps(), max_pyld / sizeof(std::complex<uint16_t>));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_get_stream_info)
|
||||
{
|
||||
const std::string cpu_format("fc32");
|
||||
const std::string otw_format("sc16");
|
||||
const size_t num_chans = 3;
|
||||
|
||||
auto send_links = make_links(num_chans);
|
||||
|
||||
// Create stream args with both formats
|
||||
uhd::stream_args_t stream_args(cpu_format, otw_format);
|
||||
auto streamer = std::make_shared<mock_tx_streamer>(num_chans, stream_args);
|
||||
streamer->set_tick_rate(TICK_RATE);
|
||||
streamer->set_samp_rate(SAMP_RATE);
|
||||
|
||||
// Connect channels with different scale factors
|
||||
for (size_t i = 0; i < num_chans; i++) {
|
||||
mock_tx_data_xport::uptr xport(
|
||||
std::make_unique<mock_tx_data_xport>(send_links[i]));
|
||||
const double scale = SCALE_FACTOR * (i + 1); // Different scale per channel
|
||||
streamer->set_scale_factor(i, scale);
|
||||
streamer->connect_channel(i, std::move(xport));
|
||||
}
|
||||
|
||||
// Test stream info for each channel
|
||||
for (size_t chan = 0; chan < num_chans; chan++) {
|
||||
uhd::device_addr_t stream_info = streamer->get_stream_info(chan);
|
||||
|
||||
// Check basic stream info
|
||||
BOOST_CHECK_EQUAL(stream_info["cpu_format"], cpu_format);
|
||||
BOOST_CHECK_EQUAL(stream_info["otw_format"], otw_format);
|
||||
const double expected_scale = SCALE_FACTOR * (chan + 1);
|
||||
BOOST_CHECK_EQUAL(stream_info["scale_factor"], std::to_string(expected_scale));
|
||||
|
||||
// Check transport info is merged
|
||||
BOOST_CHECK_EQUAL(stream_info["type"], "mock_tx_data_xport");
|
||||
BOOST_CHECK_EQUAL(stream_info["mtu"], std::to_string(FRAME_SIZE));
|
||||
|
||||
// Test that no underscore-prefixed keys are present
|
||||
for (const auto& key : stream_info.keys()) {
|
||||
BOOST_CHECK(key.empty() || key[0] != '_');
|
||||
}
|
||||
|
||||
std::cout << "TX Channel " << chan << " stream info:" << std::endl;
|
||||
for (const auto& key : stream_info.keys()) {
|
||||
std::cout << " " << key << " = " << stream_info[key] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Test invalid channel index
|
||||
BOOST_CHECK_THROW(streamer->get_stream_info(num_chans), uhd::index_error);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user