discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Discuss-gnuradio] Can a tagged stream block be a source block?


From: David Marmoy
Subject: [Discuss-gnuradio] Can a tagged stream block be a source block?
Date: Thu, 4 Dec 2014 14:17:05 +0100

Hi

I am implementing a complete protocol in a module where most of the MAC layer will be placed in a tagged stream block. I intend to start out implementing the transmit chain and then the receive chain. 
The problem I have run into is that until I get to the receive chain, the MAC layer block will need to function as a source, but is that at all possible based on a tagged stream block? 

At the moment the block crashes (silently) in line 102 of the gr::tagged_stream_block::general_work.
The line in question contains: if(d_n_input_items_reqd[0] == 0)

I believe the cause of the crash is that d_n_input_items_reqd is not set or not set to a valid value by the parse_length_tags method, since it is responsible for extracting the length tags on all input ports, but this block, being configured as a source block, does not have any input ports. 

Would it be possible to overcome this by overriding the parse_length_tags method and setting d_n_input_items_reqd to something valid?
And if yes, what would be a valid value?

My implementation of calculate_output_stream_length just returns a constant integer.

Best regards
David Marmoy

For convenience here is the relevant code from gr::tagged_stream_block:

void
  tagged_stream_block::parse_length_tags(const std::vector<std::vector<tag_t> > &tags,
                                         gr_vector_int &n_input_items_reqd)
  {
    for(unsigned i = 0; i < tags.size(); i++) {
      for(unsigned k = 0; k < tags[i].size(); k++) {
        if(tags[i][k].key == d_length_tag_key) {
          n_input_items_reqd[i] = pmt::to_long(tags[i][k].value);
          remove_item_tag(i, tags[i][k]);
        }
      }
    }
  }

int
  tagged_stream_block::general_work(int noutput_items,
                                    gr_vector_int &ninput_items,
                                    gr_vector_const_void_star &input_items,
                                    gr_vector_void_star &output_items)
  {
    if(d_length_tag_key_str.empty()) {
      return work(noutput_items, ninput_items, input_items, output_items);
    }

    if(d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call
      std::vector<std::vector<tag_t> > tags(input_items.size(), std::vector<tag_t>());
      for(unsigned i = 0; i < input_items.size(); i++) {
        get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1);
      }
      d_n_input_items_reqd.assign(input_items.size(), -1);
      parse_length_tags(tags, d_n_input_items_reqd);
    }
    for(unsigned i = 0; i < input_items.size(); i++) {
      if(d_n_input_items_reqd[i] == -1) {
        GR_LOG_FATAL(d_logger, boost::format("Missing a required length tag on port %1% at item #%2%") % i % nitems_read(i));
        throw std::runtime_error("Missing length tag.");
      }
      if(d_n_input_items_reqd[i] > ninput_items[i]) {
        return 0;
      }
    }

    int min_output_size = calculate_output_stream_length(d_n_input_items_reqd);
    if(noutput_items < min_output_size) {
      set_min_noutput_items(min_output_size);
      return 0;
    }
    set_min_noutput_items(1);

    // WORK CALLED HERE //
    int n_produced = work(noutput_items, d_n_input_items_reqd, input_items, output_items);
    //////////////////////

    if(n_produced == WORK_DONE) {
      return n_produced;
    }
    for(int i = 0; i < (int) d_n_input_items_reqd.size(); i++) {
      consume(i, d_n_input_items_reqd[i]);
    }
    if (n_produced > 0) {
      update_length_tags(n_produced, output_items.size());
    }

    d_n_input_items_reqd.assign(input_items.size(), 0);

    return n_produced;
  }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]