+ unique_lock<mutex> input_lock(input_mutex_);
+
+ // Do wait if we decoded all samples but we're still capturing
+ // Do not wait if we're done capturing
+ while (!decode_interrupt_ && !frame_complete_ &&
+ (samples_decoded_ >= sample_count_) &&
+ (session_.get_capture_state() != Session::Stopped)) {
+
+ decode_input_cond_.wait(input_lock);
+ }
+
+ // Return value is valid if we're not aborting the decode,
+ return boost::make_optional(!decode_interrupt_ &&
+ // and there's more work to do...
+ (samples_decoded_ < sample_count_ || !frame_complete_) &&
+ // and if the end of the data hasn't been reached yet
+ (!((samples_decoded_ >= sample_count_) && (session_.get_capture_state() == Session::Stopped))),
+ sample_count_);
+}
+
+void DecodeSignal::decode_data(
+ const int64_t abs_start_samplenum, const int64_t sample_count,
+ srd_session *const session)
+{
+ const unsigned int unit_size = segment_->unit_size();
+ const unsigned int chunk_sample_count = DecodeChunkLength / unit_size;
+
+ for (int64_t i = abs_start_samplenum;
+ !decode_interrupt_ && (i < (abs_start_samplenum + sample_count));
+ i += chunk_sample_count) {
+
+ const int64_t chunk_end = min(i + chunk_sample_count,
+ abs_start_samplenum + sample_count);
+
+ const uint8_t* chunk = segment_->get_samples(i, chunk_end);
+
+ if (srd_session_send(session, i, chunk_end, chunk,
+ (chunk_end - i) * unit_size, unit_size) != SRD_OK) {
+ error_message_ = tr("Decoder reported an error");
+ delete[] chunk;
+ break;
+ }
+ delete[] chunk;
+
+ {
+ lock_guard<mutex> lock(output_mutex_);
+ samples_decoded_ = chunk_end;
+ }
+ }
+}
+
+void DecodeSignal::decode_proc()
+{
+ optional<int64_t> sample_count;
+ srd_session *session;
+ srd_decoder_inst *prev_di = nullptr;
+
+ // Prevent any other decode threads from accessing libsigrokdecode
+ lock_guard<mutex> srd_lock(global_srd_mutex_);
+
+ // Create the session
+ srd_session_new(&session);
+ assert(session);
+
+ // Create the decoders
+ for (const shared_ptr<decode::Decoder> &dec : stack_) {
+ srd_decoder_inst *const di = dec->create_decoder_inst(session);
+
+ if (!di) {
+ error_message_ = tr("Failed to create decoder instance");
+ srd_session_destroy(session);
+ return;
+ }
+
+ if (prev_di)
+ srd_inst_stack(session, prev_di, di);
+
+ prev_di = di;
+ }
+
+ // Get the initial sample count
+ {
+ unique_lock<mutex> input_lock(input_mutex_);
+ sample_count = sample_count_ = get_working_sample_count();
+ }
+
+ // Start the session
+ srd_session_metadata_set(session, SRD_CONF_SAMPLERATE,
+ g_variant_new_uint64(samplerate_));
+
+ srd_pd_output_callback_add(session, SRD_OUTPUT_ANN,
+ DecodeSignal::annotation_callback, this);
+
+ srd_session_start(session);
+
+ int64_t abs_start_samplenum = 0;
+ do {
+ decode_data(abs_start_samplenum, *sample_count, session);
+ abs_start_samplenum = *sample_count;
+ } while (error_message_.isEmpty() && (sample_count = wait_for_data()));
+
+ // Make sure all annotations are known to the frontend