+ // Perform the muxing of signal data into the output data
+ uint8_t* output = new uint8_t[(end - start) * output_segment->unit_size()];
+ unsigned int signal_count = signal_data.size();
+
+ for (int64_t sample_cnt = 0; sample_cnt < (end - start); sample_cnt++) {
+ int bitpos = 0;
+ uint8_t bytepos = 0;
+
+ const int out_sample_pos = sample_cnt * output_segment->unit_size();
+ for (unsigned int i = 0; i < output_segment->unit_size(); i++)
+ output[out_sample_pos + i] = 0;
+
+ for (unsigned int i = 0; i < signal_count; i++) {
+ const int in_sample_pos = sample_cnt * segments[i]->unit_size();
+ const uint8_t in_sample = 1 &
+ ((signal_data[i][in_sample_pos + signal_in_bytepos[i]]) >> (signal_in_bitpos[i]));
+
+ const uint8_t out_sample = output[out_sample_pos + bytepos];
+
+ output[out_sample_pos + bytepos] = out_sample | (in_sample << bitpos);
+
+ bitpos++;
+ if (bitpos > 7) {
+ bitpos = 0;
+ bytepos++;
+ }
+ }
+ }
+
+ output_segment->append_payload(output, (end - start) * output_segment->unit_size());
+ delete[] output;
+
+ for (const uint8_t* data : signal_data)
+ delete[] data;
+}
+
+void DecodeSignal::logic_mux_proc()
+{
+ uint32_t segment_id = 0;
+
+ assert(logic_mux_data_);
+
+ shared_ptr<LogicSegment> output_segment = logic_mux_data_->logic_segments().front();
+ assert(output_segment);
+
+ output_segment->set_samplerate(get_input_samplerate(0));
+
+ do {
+ const uint64_t input_sample_count = get_working_sample_count(segment_id);
+ const uint64_t output_sample_count = output_segment->get_sample_count();
+
+ const uint64_t samples_to_process =
+ (input_sample_count > output_sample_count) ?
+ (input_sample_count - output_sample_count) : 0;
+
+ // Process the samples if necessary...
+ if (samples_to_process > 0) {
+ const uint64_t unit_size = output_segment->unit_size();
+ const uint64_t chunk_sample_count = DecodeChunkLength / unit_size;
+
+ uint64_t processed_samples = 0;
+ do {
+ const uint64_t start_sample = output_sample_count + processed_samples;
+ const uint64_t sample_count =
+ min(samples_to_process - processed_samples, chunk_sample_count);
+
+ mux_logic_samples(segment_id, start_sample, start_sample + sample_count);
+ processed_samples += sample_count;
+
+ // ...and process the newly muxed logic data
+ decode_input_cond_.notify_one();
+ } while (processed_samples < samples_to_process);
+ }
+
+ if (samples_to_process == 0) {
+ // TODO Optimize this by caching the input segment count and only
+ // querying it when the cached value was reached
+ if (segment_id < get_input_segment_count() - 1) {
+ // Process next segment
+ segment_id++;
+
+ try {
+ output_segment = logic_mux_data_->logic_segments().at(segment_id);
+ } catch (out_of_range) {
+ qDebug() << "Muxer error for" << name() << ": no logic mux segment" \
+ << segment_id << "in logic_mux_proc(), mux segments size is" \
+ << logic_mux_data_->logic_segments().size();
+ return;
+ }
+
+ output_segment->set_samplerate(get_input_samplerate(segment_id));
+
+ } else {
+ // All segments have been processed
+ logic_mux_data_invalid_ = false;
+
+ // Wait for more input
+ unique_lock<mutex> logic_mux_lock(logic_mux_mutex_);
+ logic_mux_cond_.wait(logic_mux_lock);
+ }
+ }
+ } while (!logic_mux_interrupt_);
+}
+
+void DecodeSignal::query_input_metadata()
+{
+ // Update the samplerate and start time because we cannot start
+ // the libsrd session without the current samplerate
+
+ // TODO Currently we assume all channels have the same sample rate
+ // and start time
+ bool samplerate_valid = false;
+ data::DecodeChannel *any_channel;
+ shared_ptr<Logic> logic_data;
+
+ do {
+ any_channel = &(*find_if(channels_.begin(), channels_.end(),
+ [](data::DecodeChannel ch) { return ch.assigned_signal; }));
+
+ logic_data = any_channel->assigned_signal->logic_data();
+
+ if (!logic_data) {
+ // Wait until input data is available or an interrupt was requested
+ unique_lock<mutex> input_wait_lock(input_mutex_);
+ decode_input_cond_.wait(input_wait_lock);
+ }
+ } while (!logic_data && !decode_interrupt_);
+
+ if (decode_interrupt_)
+ return;
+
+ do {
+ if (!logic_data->logic_segments().empty()) {
+ shared_ptr<LogicSegment> first_segment =
+ any_channel->assigned_signal->logic_data()->logic_segments().front();
+
+ // We only need valid metadata in the first decode segment
+ // so that start_srd_session() can use it
+ segments_.at(current_segment_id_).start_time = first_segment->start_time();
+ segments_.at(current_segment_id_).samplerate = first_segment->samplerate();
+
+ if (segments_.at(current_segment_id_).samplerate > 0)
+ samplerate_valid = true;
+ }
+
+ if (!samplerate_valid) {
+ // Wait until input data is available or an interrupt was requested
+ unique_lock<mutex> input_wait_lock(input_mutex_);
+ decode_input_cond_.wait(input_wait_lock);
+ }
+ } while (!samplerate_valid && !decode_interrupt_);