X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=339c85dd01dd0305879bce1dc88d3fde6d8ec6e3;hp=0e49398a44dc71757f6f2f531654629251adb2c6;hb=a3ebd5561086f4fef6570b3ab5be0a5592724731;hpb=e91883bb2d8e1f23078a7cd02bc5a7f4e3c9556c diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index 0e49398a..339c85dd 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -65,10 +65,6 @@ DecodeSignal::DecodeSignal(pv::Session &session) : { connect(&session_, SIGNAL(capture_state_changed(int)), this, SLOT(on_capture_state_changed(int))); - connect(&session_, SIGNAL(data_received()), - this, SLOT(on_data_received())); - connect(&session_, SIGNAL(frame_ended()), - this, SLOT(on_frame_ended())); set_name(tr("Empty decoder signal")); } @@ -225,13 +221,6 @@ void DecodeSignal::begin_decode() } } - // TODO Currently we assume all channels have the same sample rate - auto any_channel = find_if(channels_.begin(), channels_.end(), - [](data::DecodeChannel ch) { return ch.assigned_signal; }); - shared_ptr first_segment = - any_channel->assigned_signal->logic_data()->logic_segments().front(); - samplerate_ = first_segment->samplerate(); - // Free the logic data and its segment(s) if it needs to be updated if (logic_mux_data_invalid_) logic_mux_data_.reset(); @@ -244,12 +233,6 @@ void DecodeSignal::begin_decode() logic_mux_data_->push_segment(segment_); } - // Update the samplerate and start time - start_time_ = segment_->start_time(); - samplerate_ = segment_->samplerate(); - if (samplerate_ == 0.0) - samplerate_ = 1.0; - // Make sure the logic output data is complete and up-to-date logic_mux_interrupt_ = false; logic_mux_thread_ = std::thread(&DecodeSignal::logic_mux_proc, this); @@ -257,6 +240,9 @@ void DecodeSignal::begin_decode() // Decode the muxed logic data decode_interrupt_ = false; decode_thread_ = std::thread(&DecodeSignal::decode_proc, this); + + // Receive notifications when new sample data is available + connect_input_notifiers(); } QString DecodeSignal::error_message() const @@ -588,7 +574,6 @@ void DecodeSignal::mux_logic_samples(const int64_t start, const int64_t end) void DecodeSignal::logic_mux_proc() { do { - const uint64_t input_sample_count = get_working_sample_count(); const uint64_t output_sample_count = segment_->get_sample_count(); @@ -628,6 +613,37 @@ void DecodeSignal::logic_mux_proc() decode_input_cond_.notify_one(); } +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; + + auto any_channel = find_if(channels_.begin(), channels_.end(), + [](data::DecodeChannel ch) { return ch.assigned_signal; }); + + shared_ptr logic_data = + any_channel->assigned_signal->logic_data(); + + do { + if (!logic_data->logic_segments().empty()) { + shared_ptr first_segment = + any_channel->assigned_signal->logic_data()->logic_segments().front(); + start_time_ = first_segment->start_time(); + samplerate_ = first_segment->samplerate(); + if (samplerate_ > 0) + samplerate_valid = true; + } + + // Wait until input data is available or an interrupt was requested + unique_lock input_wait_lock(input_mutex_); + decode_input_cond_.wait(input_wait_lock); + } while (!samplerate_valid && !decode_interrupt_); +} + void DecodeSignal::decode_data( const int64_t abs_start_samplenum, const int64_t sample_count) { @@ -649,6 +665,7 @@ void DecodeSignal::decode_data( delete[] chunk; break; } + delete[] chunk; { @@ -660,6 +677,11 @@ void DecodeSignal::decode_data( void DecodeSignal::decode_proc() { + query_input_metadata(); + + if (decode_interrupt_) + return; + start_srd_session(); uint64_t sample_count; @@ -685,7 +707,7 @@ void DecodeSignal::decode_proc() // Make sure all annotations are known to the frontend new_annotations(); - // Wait for new input data or an interrupt request + // Wait for new input data or an interrupt was requested unique_lock input_wait_lock(input_mutex_); decode_input_cond_.wait(input_wait_lock); } @@ -694,37 +716,38 @@ void DecodeSignal::decode_proc() void DecodeSignal::start_srd_session() { - if (!srd_session_) { - // Create the session - srd_session_new(&srd_session_); - assert(srd_session_); - - // Create the decoders - srd_decoder_inst *prev_di = nullptr; - for (const shared_ptr &dec : stack_) { - srd_decoder_inst *const di = dec->create_decoder_inst(srd_session_); + if (srd_session_) + stop_srd_session(); - if (!di) { - error_message_ = tr("Failed to create decoder instance"); - srd_session_destroy(srd_session_); - return; - } + // Create the session + srd_session_new(&srd_session_); + assert(srd_session_); - if (prev_di) - srd_inst_stack(srd_session_, prev_di, di); + // Create the decoders + srd_decoder_inst *prev_di = nullptr; + for (const shared_ptr &dec : stack_) { + srd_decoder_inst *const di = dec->create_decoder_inst(srd_session_); - prev_di = di; + if (!di) { + error_message_ = tr("Failed to create decoder instance"); + srd_session_destroy(srd_session_); + return; } - // Start the session - srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE, - g_variant_new_uint64(samplerate_)); + if (prev_di) + srd_inst_stack(srd_session_, prev_di, di); - srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN, - DecodeSignal::annotation_callback, this); - - srd_session_start(srd_session_); + prev_di = di; } + + // Start the session + srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE, + g_variant_new_uint64(samplerate_)); + + srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN, + DecodeSignal::annotation_callback, this); + + srd_session_start(srd_session_); } void DecodeSignal::stop_srd_session() @@ -736,6 +759,22 @@ void DecodeSignal::stop_srd_session() } } +void DecodeSignal::connect_input_notifiers() +{ + // Disconnect the notification slot from the previous set of signals + disconnect(this, SLOT(on_data_received())); + + // Connect the currently used signals to our slot + for (data::DecodeChannel &ch : channels_) { + if (!ch.assigned_signal) + continue; + + shared_ptr logic_data = ch.assigned_signal->logic_data(); + connect(logic_data.get(), SIGNAL(samples_added(QObject*, uint64_t, uint64_t)), + this, SLOT(on_data_received())); + } +} + void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signal) { assert(pdata); @@ -793,10 +832,5 @@ void DecodeSignal::on_data_received() logic_mux_cond_.notify_one(); } -void DecodeSignal::on_frame_ended() -{ - logic_mux_cond_.notify_one(); -} - } // namespace data } // namespace pv