]> sigrok.org Git - pulseview.git/blobdiff - pv/data/decodesignal.cpp
DecodeSignal: Reset and re-use existing decoder sessions
[pulseview.git] / pv / data / decodesignal.cpp
index 1eff9119f319de72fb1bfde4d1f13ec93e7228d6..df385be8d99ce397ed9aba327247f37e0176983b 100644 (file)
@@ -129,6 +129,8 @@ bool DecodeSignal::toggle_decoder_visibility(int index)
 
 void DecodeSignal::reset_decode()
 {
+       terminate_srd_session();
+
        if (decode_thread_.joinable()) {
                decode_interrupt_ = true;
                decode_input_cond_.notify_one();
@@ -157,6 +159,8 @@ void DecodeSignal::reset_decode()
 
 void DecodeSignal::begin_decode()
 {
+       terminate_srd_session();
+
        if (decode_thread_.joinable()) {
                decode_interrupt_ = true;
                decode_input_cond_.notify_one();
@@ -361,7 +365,7 @@ int64_t DecodeSignal::get_working_sample_count(uint32_t segment_id) const
                        try {
                                const shared_ptr<LogicSegment> segment = logic_data->logic_segments().at(segment_id);
                                count = min(count, (int64_t)segment->get_sample_count());
-                       } catch (out_of_range) {
+                       } catch (out_of_range&) {
                                return 0;
                        }
                }
@@ -378,7 +382,7 @@ int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id) const
        try {
                const DecodeSegment *segment = &(segments_.at(segment_id));
                result = segment->samples_decoded;
-       } catch (out_of_range) {
+       } catch (out_of_range&) {
                // Do nothing
        }
 
@@ -431,7 +435,7 @@ void DecodeSignal::get_annotation_subset(
                if (iter != rows->end())
                        (*iter).second.get_annotation_subset(dest,
                                start_sample, end_sample);
-       } catch (out_of_range) {
+       } catch (out_of_range&) {
                // Do nothing
        }
 }
@@ -607,7 +611,7 @@ uint32_t DecodeSignal::get_input_samplerate(uint32_t segment_id) const
                        try {
                                const shared_ptr<LogicSegment> segment = logic_data->logic_segments().at(segment_id);
                                samplerate = segment->samplerate();
-                       } catch (out_of_range) {
+                       } catch (out_of_range&) {
                                // Do nothing
                        }
                        break;
@@ -736,7 +740,7 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
                        shared_ptr<LogicSegment> segment;
                        try {
                                segment = logic_data->logic_segments().at(segment_id);
-                       } catch (out_of_range) {
+                       } catch (out_of_range&) {
                                qDebug() << "Muxer error for" << name() << ":" << ch.assigned_signal->name() \
                                        << "has no logic segment" << segment_id;
                                return;
@@ -756,7 +760,7 @@ void DecodeSignal::mux_logic_samples(uint32_t segment_id, const int64_t start, c
        shared_ptr<LogicSegment> output_segment;
        try {
                output_segment = logic_mux_data_->logic_segments().at(segment_id);
-       } catch (out_of_range) {
+       } catch (out_of_range&) {
                qDebug() << "Muxer error for" << name() << ": no logic mux segment" \
                        << segment_id << "in mux_logic_samples(), mux segments size is" \
                        << logic_mux_data_->logic_segments().size();
@@ -807,7 +811,8 @@ void DecodeSignal::logic_mux_proc()
 
        // Create initial logic mux segment
        shared_ptr<LogicSegment> output_segment =
-               make_shared<LogicSegment>(*logic_mux_data_, logic_mux_unit_size_, 0);
+               make_shared<LogicSegment>(*logic_mux_data_, segment_id,
+                       logic_mux_unit_size_, 0);
        logic_mux_data_->push_segment(output_segment);
 
        output_segment->set_samplerate(get_input_samplerate(0));
@@ -847,7 +852,8 @@ void DecodeSignal::logic_mux_proc()
                                segment_id++;
 
                                output_segment =
-                                       make_shared<LogicSegment>(*logic_mux_data_, logic_mux_unit_size_, 0);
+                                       make_shared<LogicSegment>(*logic_mux_data_, segment_id,
+                                               logic_mux_unit_size_, 0);
                                logic_mux_data_->push_segment(output_segment);
 
                                output_segment->set_samplerate(get_input_samplerate(segment_id));
@@ -946,7 +952,7 @@ void DecodeSignal::decode_proc()
 
                                try {
                                        input_segment = logic_mux_data_->logic_segments().at(current_segment_id_);
-                               } catch (out_of_range) {
+                               } catch (out_of_range&) {
                                        qDebug() << "Decode error for" << name() << ": no logic mux segment" \
                                                << current_segment_id_ << "in decode_proc(), mux segments size is" \
                                                << logic_mux_data_->logic_segments().size();
@@ -972,12 +978,34 @@ void DecodeSignal::decode_proc()
                        }
                }
        } while (error_message_.isEmpty() && !decode_interrupt_);
+
+       // Potentially reap decoders when the application no longer is
+       // interested in their (pending) results.
+       if (decode_interrupt_)
+               terminate_srd_session();
 }
 
 void DecodeSignal::start_srd_session()
 {
-       if (srd_session_)
-               stop_srd_session();
+       uint64_t samplerate;
+
+       if (srd_session_) {
+               // When a decoder stack was created before, re-use it
+               // for the next stream of input data, after terminating
+               // potentially still executing operations, and resetting
+               // internal state. Skip the rather expensive (teardown
+               // and) construction of another decoder stack.
+
+               // TODO Reduce redundancy, use a common code path for
+               // the meta/cb/start sequence?
+               terminate_srd_session();
+               srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
+                       g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
+               srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN,
+                       DecodeSignal::annotation_callback, this);
+               srd_session_start(srd_session_);
+               return;
+       }
 
        // Create the session
        srd_session_new(&srd_session_);
@@ -991,6 +1019,7 @@ void DecodeSignal::start_srd_session()
                if (!di) {
                        error_message_ = tr("Failed to create decoder instance");
                        srd_session_destroy(srd_session_);
+                       srd_session_ = nullptr;
                        return;
                }
 
@@ -1001,8 +1030,10 @@ void DecodeSignal::start_srd_session()
        }
 
        // Start the session
-       srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
-               g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
+       samplerate = segments_.at(current_segment_id_).samplerate;
+       if (samplerate)
+               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);
@@ -1010,6 +1041,17 @@ void DecodeSignal::start_srd_session()
        srd_session_start(srd_session_);
 }
 
+void DecodeSignal::terminate_srd_session()
+{
+       // Call the "terminate and reset" routine for the decoder stack
+       // (if available). This does not harm those stacks which already
+       // have completed their operation, and reduces response time for
+       // those stacks which still are processing data while the
+       // application no longer wants them to.
+       if (srd_session_)
+               srd_session_terminate_reset(srd_session_);
+}
+
 void DecodeSignal::stop_srd_session()
 {
        if (srd_session_) {
@@ -1033,7 +1075,7 @@ void DecodeSignal::connect_input_notifiers()
                const data::SignalBase *signal = ch.assigned_signal;
                connect(signal, SIGNAL(samples_cleared()),
                        this, SLOT(on_data_cleared()));
-               connect(signal, SIGNAL(samples_added(QObject*, uint64_t, uint64_t)),
+               connect(signal, SIGNAL(samples_added(uint64_t, uint64_t, uint64_t)),
                        this, SLOT(on_data_received()));
        }
 }