X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=593af02fdd796348aac72d3b621fa13239cffa3f;hb=cbb2e4da8042495531b406f745ee9d9e20448ef6;hp=f7fe004c0f45afb01ca137a36b81c133ba1f0612;hpb=a82325d16a1412f3474423fa3fa56bb85af1fb00;p=pulseview.git diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index f7fe004c..593af02f 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -76,7 +76,7 @@ const vector< shared_ptr >& DecodeSignal::decoder_stack() const return stack_; } -void DecodeSignal::stack_decoder(const srd_decoder *decoder) +void DecodeSignal::stack_decoder(const srd_decoder *decoder, bool restart_decode) { assert(decoder); @@ -98,7 +98,11 @@ void DecodeSignal::stack_decoder(const srd_decoder *decoder) stack_config_changed_ = true; auto_assign_signals(dec); commit_decoder_channels(); - begin_decode(); + + decoder_stacked((void*)dec.get()); + + if (restart_decode) + begin_decode(); } void DecodeSignal::remove_decoder(int index) @@ -111,6 +115,8 @@ void DecodeSignal::remove_decoder(int index) for (int i = 0; i < index; i++, iter++) assert(iter != stack_.end()); + decoder_removed(iter->get()); + // Delete the element stack_.erase(iter); @@ -230,12 +236,11 @@ void DecodeSignal::begin_decode() (srd_decoder_annotation_row *)l->data; assert(ann_row); - const Row row(row_index++, decc, ann_row); + const Row row(row_index++, dec.get(), ann_row); for (const GSList *ll = ann_row->ann_classes; ll; ll = ll->next) - class_rows_[make_pair(decc, - GPOINTER_TO_INT(ll->data))] = row; + class_rows_[make_pair(decc, GPOINTER_TO_INT(ll->data))] = row; } } @@ -437,15 +442,13 @@ int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id, int64_t result = 0; - try { - const DecodeSegment *segment = &(segments_.at(segment_id)); - if (include_processing) - result = segment->samples_decoded_incl; - else - result = segment->samples_decoded_excl; - } catch (out_of_range&) { - // Do nothing - } + if (segment_id >= segments_.size()) + return result; + + if (include_processing) + result = segments_[segment_id].samples_decoded_incl; + else + result = segments_[segment_id].samples_decoded_excl; return result; } @@ -467,20 +470,37 @@ vector DecodeSignal::get_rows(bool visible_only) const int row_index = 0; // Add a row for the decoder if it doesn't have a row list if (!decc->annotation_rows) - rows.emplace_back(row_index++, decc); + rows.emplace_back(row_index++, dec.get()); // Add the decoder rows for (const GSList *l = decc->annotation_rows; l; l = l->next) { const srd_decoder_annotation_row *const ann_row = (srd_decoder_annotation_row *)l->data; assert(ann_row); - rows.emplace_back(row_index++, decc, ann_row); + rows.emplace_back(row_index++, dec.get(), ann_row); } } return rows; } +uint64_t DecodeSignal::get_annotation_count(const decode::Row &row, + uint32_t segment_id) const +{ + if (segment_id >= segments_.size()) + return 0; + + const DecodeSegment *segment = &(segments_.at(segment_id)); + const map *rows = + &(segment->annotation_rows); + + const auto iter = rows->find(row); + if (iter != rows->end()) + return (*iter).second.get_annotation_count(); + + return 0; +} + void DecodeSignal::get_annotation_subset( vector &dest, const decode::Row &row, uint32_t segment_id, uint64_t start_sample, @@ -488,18 +508,15 @@ void DecodeSignal::get_annotation_subset( { lock_guard lock(output_mutex_); - try { - const DecodeSegment *segment = &(segments_.at(segment_id)); - const map *rows = - &(segment->annotation_rows); + if (segment_id >= segments_.size()) + return; - const auto iter = rows->find(row); - if (iter != rows->end()) - (*iter).second.get_annotation_subset(dest, - start_sample, end_sample); - } catch (out_of_range&) { - // Do nothing - } + const DecodeSegment *segment = &(segments_.at(segment_id)); + const map *rows = &(segment->annotation_rows); + + const auto iter = rows->find(row); + if (iter != rows->end()) + (*iter).second.get_annotation_subset(dest, start_sample, end_sample); } void DecodeSignal::get_annotation_subset( @@ -508,7 +525,7 @@ void DecodeSignal::get_annotation_subset( { // Note: We put all vectors and lists on the heap, not the stack - const vector rows = get_rows(true); + const vector rows = get_rows(); // Use forward_lists for faster merging forward_list *all_ann_list = new forward_list(); @@ -529,63 +546,141 @@ void DecodeSignal::get_annotation_subset( delete all_ann_list; } -uint32_t DecodeSignal::get_binary_data_chunk_count(uint32_t segment_id) const +uint32_t DecodeSignal::get_binary_data_chunk_count(uint32_t segment_id, + const Decoder* dec, uint32_t bin_class_id) const { - uint32_t count = 0; + if (segments_.size() == 0) + return 0; try { const DecodeSegment *segment = &(segments_.at(segment_id)); - count = segment->binary_data.size(); + + for (const DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id)) + return bc.chunks.size(); } catch (out_of_range&) { // Do nothing } - return count; + return 0; } -void DecodeSignal::get_binary_data_chunk(uint32_t segment_id, uint32_t chunk_id, +void DecodeSignal::get_binary_data_chunk(uint32_t segment_id, + const Decoder* dec, uint32_t bin_class_id, uint32_t chunk_id, const vector **dest, uint64_t *size) { try { const DecodeSegment *segment = &(segments_.at(segment_id)); - if (dest) - *dest = &(segment->binary_data.at(chunk_id).data); - if (size) - *size = segment->binary_data.at(chunk_id).data.size(); + + for (const DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id)) { + if (dest) *dest = &(bc.chunks.at(chunk_id).data); + if (size) *size = bc.chunks.at(chunk_id).data.size(); + return; + } } catch (out_of_range&) { // Do nothing } } -void DecodeSignal::get_binary_data_chunks_merged(uint32_t segment_id, - uint64_t start_sample, uint64_t end_sample, vector *dest) const +void DecodeSignal::get_merged_binary_data_chunks_by_sample(uint32_t segment_id, + const Decoder* dec, uint32_t bin_class_id, uint64_t start_sample, + uint64_t end_sample, vector *dest) const { assert(dest != nullptr); try { const DecodeSegment *segment = &(segments_.at(segment_id)); + const DecodeBinaryClass* bin_class = nullptr; + for (const DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id)) + bin_class = &bc; + // Determine overall size before copying to resize dest vector only once uint64_t size = 0; - int matches = 0; - for (const DecodeBinaryData& d : segment->binary_data) - if ((d.sample >= start_sample) && (d.sample < end_sample)) { - size += d.data.size(); + uint64_t matches = 0; + for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) + if ((chunk.sample >= start_sample) && (chunk.sample < end_sample)) { + size += chunk.data.size(); matches++; } dest->resize(size); - uint64_t index = 0; - for (const DecodeBinaryData& d : segment->binary_data) - if ((d.sample >= start_sample) && (d.sample < end_sample)) { - memcpy(dest->data() + index, d.data.data(), d.data.size()); - index += d.data.size(); + uint64_t offset = 0; + uint64_t matches2 = 0; + for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) + if ((chunk.sample >= start_sample) && (chunk.sample < end_sample)) { + memcpy(dest->data() + offset, chunk.data.data(), chunk.data.size()); + offset += chunk.data.size(); + matches2++; + + // Make sure we don't overwrite memory if the array grew in the meanwhile + if (matches2 == matches) + break; } } catch (out_of_range&) { // Do nothing } } +void DecodeSignal::get_merged_binary_data_chunks_by_offset(uint32_t segment_id, + const data::decode::Decoder* dec, uint32_t bin_class_id, uint64_t start, + uint64_t end, vector *dest) const +{ + assert(dest != nullptr); + + try { + const DecodeSegment *segment = &(segments_.at(segment_id)); + + const DecodeBinaryClass* bin_class = nullptr; + for (const DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id)) + bin_class = &bc; + + // Determine overall size before copying to resize dest vector only once + uint64_t size = 0; + uint64_t offset = 0; + for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) { + if (offset >= start) + size += chunk.data.size(); + offset += chunk.data.size(); + if (offset >= end) + break; + } + dest->resize(size); + + offset = 0; + uint64_t dest_offset = 0; + for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) { + if (offset >= start) { + memcpy(dest->data() + dest_offset, chunk.data.data(), chunk.data.size()); + dest_offset += chunk.data.size(); + } + offset += chunk.data.size(); + if (offset >= end) + break; + } + } catch (out_of_range&) { + // Do nothing + } +} + +const DecodeBinaryClass* DecodeSignal::get_binary_data_class(uint32_t segment_id, + const data::decode::Decoder* dec, uint32_t bin_class_id) const +{ + try { + const DecodeSegment *segment = &(segments_.at(segment_id)); + + for (const DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id)) + return &bc; + } catch (out_of_range&) { + // Do nothing + } + + return nullptr; +} void DecodeSignal::save_settings(QSettings &settings) const { @@ -1290,7 +1385,7 @@ void DecodeSignal::create_decode_segment() int row_index = 0; // Add a row for the decoder if it doesn't have a row list if (!decc->annotation_rows) - (segments_.back().annotation_rows)[Row(row_index++, decc)] = + (segments_.back().annotation_rows)[Row(row_index++, dec.get())] = decode::RowData(); // Add the decoder rows @@ -1299,13 +1394,21 @@ void DecodeSignal::create_decode_segment() (srd_decoder_annotation_row *)l->data; assert(ann_row); - const Row row(row_index++, decc, ann_row); + const Row row(row_index++, dec.get(), ann_row); // Add a new empty row data object - (segments_.back().annotation_rows)[row] = - decode::RowData(); + (segments_.back().annotation_rows)[row] = decode::RowData(); } } + + // Prepare our binary output classes + for (const shared_ptr& dec : stack_) { + uint32_t n = dec->get_binary_class_count(); + + for (uint32_t i = 0; i < n; i++) + segments_.back().binary_classes.push_back( + {dec.get(), dec->get_binary_class(i), deque()}); + } } void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signal) @@ -1340,7 +1443,9 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find((*r).second); else { // Failing that, use the decoder as a key - row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find(Row(0, decc)); + for (const shared_ptr& dec : ds->decoder_stack()) + if (dec->decoder() == decc) + row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find(Row(0, dec.get())); } if (row_iter == ds->segments_.at(ds->current_segment_id_).annotation_rows.end()) { @@ -1365,19 +1470,47 @@ void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal) if (ds->decode_interrupt_) return; + // Get the decoder and the binary data + assert(pdata->pdo); + assert(pdata->pdo->di); + const srd_decoder *const decc = pdata->pdo->di->decoder; + assert(decc); + const srd_proto_data_binary *const pdb = (const srd_proto_data_binary*)pdata->data; assert(pdb); + // Find the matching DecodeBinaryClass DecodeSegment* segment = &(ds->segments_.at(ds->current_segment_id_)); - segment->binary_data.emplace_back(); - DecodeBinaryData* bin_data = &(segment->binary_data.back()); + DecodeBinaryClass* bin_class = nullptr; + for (DecodeBinaryClass& bc : segment->binary_classes) + if ((bc.decoder->decoder() == decc) && (bc.info->bin_class_id == (uint32_t)pdb->bin_class)) + bin_class = &bc; + + if (!bin_class) { + qWarning() << "Could not find valid DecodeBinaryClass in segment" << + ds->current_segment_id_ << "for binary class ID" << pdb->bin_class << + ", segment only knows" << segment->binary_classes.size() << "classes"; + return; + } - bin_data->sample = pdata->start_sample; - bin_data->data.resize(pdb->size); - memcpy(bin_data->data.data(), pdb->data, pdb->size); + // Add the data chunk + bin_class->chunks.emplace_back(); + DecodeBinaryDataChunk* chunk = &(bin_class->chunks.back()); + + chunk->sample = pdata->start_sample; + chunk->data.resize(pdb->size); + memcpy(chunk->data.data(), pdb->data, pdb->size); + + // Find decoder class instance + Decoder* dec = nullptr; + for (const shared_ptr& d : ds->decoder_stack()) + if (d->decoder() == decc) { + dec = d.get(); + break; + } - ds->new_binary_data(ds->current_segment_id_); + ds->new_binary_data(ds->current_segment_id_, (void*)dec, pdb->bin_class); } void DecodeSignal::on_capture_state_changed(int state)