From: Soeren Apel Date: Wed, 17 May 2017 06:31:07 +0000 (+0200) Subject: DecodeSignal: Rework samplerate handling X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=a3ebd5561086f4fef6570b3ab5be0a5592724731 DecodeSignal: Rework samplerate handling Before, running an acquisition, then changing the samplerate and then running the acquisition again would result in the wrong (i.e. previous) samplerate to be used for SRD. This patch fixes this. --- diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index a7bcee59..339c85dd 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -221,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(); @@ -240,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); @@ -626,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) { @@ -647,6 +665,7 @@ void DecodeSignal::decode_data( delete[] chunk; break; } + delete[] chunk; { @@ -658,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; @@ -683,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); } @@ -692,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_); + if (srd_session_) + stop_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_); + // Create the session + srd_session_new(&srd_session_); + assert(srd_session_); - if (!di) { - error_message_ = tr("Failed to create decoder instance"); - srd_session_destroy(srd_session_); - return; - } - - 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_)); - - srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN, - DecodeSignal::annotation_callback, this); + if (prev_di) + srd_inst_stack(srd_session_, prev_di, di); - 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() diff --git a/pv/data/decodesignal.hpp b/pv/data/decodesignal.hpp index 2d4d4e0c..57887f1e 100644 --- a/pv/data/decodesignal.hpp +++ b/pv/data/decodesignal.hpp @@ -145,6 +145,8 @@ private: void logic_mux_proc(); + void query_input_metadata(); + void decode_data(const int64_t abs_start_samplenum, const int64_t sample_count); void decode_proc();