From 72dbe7e0a60147e5de637f754057fa32ed04fe4a Mon Sep 17 00:00:00 2001 From: bjornvolcker Date: Fri, 6 Dec 2024 15:28:49 +0100 Subject: [PATCH] Synchronizes SEIs for legacy code At validation starts, SEIs are not synchronized with an I-frame. It is unknown how many SEIs that cannot be used to validate frames, since they sign GOPs not present. This commit loops through all possible validation cases with the SEI by temporarily use tmp_validation_status and a few more flags. The validation_status is then updated when the SEI is not feasible to use in a validation. --- lib/src/legacy/legacy_h26x_auth.c | 169 ++++++++++++++++--------- lib/src/legacy/legacy_h26x_common.c | 4 +- lib/src/legacy/legacy_h26x_internal.h | 5 + lib/src/legacy/legacy_h26x_nalu_list.c | 58 +++++++-- lib/src/legacy/legacy_h26x_nalu_list.h | 3 + 5 files changed, 169 insertions(+), 70 deletions(-) diff --git a/lib/src/legacy/legacy_h26x_auth.c b/lib/src/legacy/legacy_h26x_auth.c index bc21e70..9f770f0 100644 --- a/lib/src/legacy/legacy_h26x_auth.c +++ b/lib/src/legacy/legacy_h26x_auth.c @@ -138,13 +138,13 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // legacy_verify_hashes_without_sei(). switch (self->gop_info->verified_signature_hash) { case -1: - sei->validation_status = 'E'; + sei->tmp_validation_status = 'E'; return legacy_verify_hashes_without_sei(self); case 0: - sei->validation_status = 'N'; + sei->tmp_validation_status = 'N'; return legacy_verify_hashes_without_sei(self); case 1: - assert(sei->validation_status == 'P'); + assert(sei->tmp_validation_status == 'P'); break; default: // We should not end up here. @@ -169,7 +169,7 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // against the feasible hashes in the received |hash_list|. while (item && !(found_next_gop || found_item_after_sei)) { // If this item is not Pending, move to the next one. - if (item->validation_status != 'P') { + if (item->tmp_validation_status != 'P') { item = item->next; continue; } @@ -178,7 +178,7 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // Check if this is the item right after the |sei|. found_item_after_sei = (item->prev == sei); // Check if this |is_first_nalu_in_gop|, but not used before. - found_next_gop = (item->nalu->is_first_nalu_in_gop && !item->need_second_verification); + found_next_gop = (item->nalu->is_first_nalu_in_gop && !item->tmp_need_second_verification); // If this is a SEI, it is not part of the hash list and should not be verified. if (item->nalu->is_gop_sei) { item = item->next; @@ -190,7 +190,17 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // Fetch the |hash_to_verify|, which normally is the item->hash, but if this is NALU has been // used in a previous verification we use item->second_hash. - uint8_t *hash_to_verify = item->need_second_verification ? item->second_hash : item->hash; + uint8_t *hash_to_verify = item->tmp_need_second_verification ? item->second_hash : item->hash; + // If the item is the very first (hashable) item in the stream, both the |second_hash| and the + // |hash| will be identical. The |hash| is actually wrong since it should have been hashed with + // reference. Since it is not feasible to use that hash there is no reason to try to match it + // against the hashes in the list. Below it is determined if one should |skip_check|. + const bool has_same_hash = + (item->second_hash && (memcmp(item->second_hash, item->hash, hash_size) == 0)); + const bool is_first_received_nalu = + item->nalu->is_first_nalu_in_gop && has_same_hash && !item->tmp_need_second_verification; + const bool is_first_stream_sei = (num_expected_hashes == 1); + const bool skip_check = is_first_received_nalu && !is_first_stream_sei; // Compare |hash_to_verify| against all the |expected_hashes| since the |latest_match_idx|. Stop // when we get a match or reach the end. @@ -199,17 +209,17 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, while (compare_idx < num_expected_hashes) { uint8_t *expected_hash = &expected_hashes[compare_idx * hash_size]; - if (memcmp(hash_to_verify, expected_hash, hash_size) == 0) { + if (memcmp(hash_to_verify, expected_hash, hash_size) == 0 && !skip_check) { // We have a match. Set validation_status and add missing nalus if we have detected any. - if (item->second_hash && !item->need_second_verification && + if (item->second_hash && !item->tmp_need_second_verification && item->nalu->is_first_nalu_in_gop) { // If this |is_first_nalu_in_gop| it should be verified twice. If this the first time we // signal that we |need_second_verification|. DEBUG_LOG("This NALU needs a second verification"); - item->need_second_verification = true; + item->tmp_need_second_verification = true; } else { - item->validation_status = item->first_verification_not_authentic ? 'N' : '.'; - item->need_second_verification = false; + item->tmp_validation_status = item->tmp_first_verification_not_authentic ? 'N' : '.'; + item->tmp_need_second_verification = false; } // Add missing items to |nalu_list|. int num_detected_missing_nalus = @@ -229,15 +239,15 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, if (latest_match_idx != compare_idx) { // We have compared against all feasible hashes in |hash_list| without a match. Mark as NOT // OK, or keep pending for second use. - if (item->second_hash && !item->need_second_verification) { - item->need_second_verification = true; + if (item->second_hash && !item->tmp_need_second_verification) { + item->tmp_need_second_verification = true; // If this item will be used in a second verification the flag // |first_verification_not_authentic| is set. - item->first_verification_not_authentic = true; + item->tmp_first_verification_not_authentic = true; } else { // Reset |need_second_verification|. - item->need_second_verification = false; - item->validation_status = 'N'; + item->tmp_need_second_verification = false; + item->tmp_validation_status = 'N'; } // Update counters. num_invalid_nalus_since_latest_match++; @@ -254,7 +264,7 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // first item. If the first item needs a second opinion, that is, it has already been verified // once, we append that item. Otherwise, prepend it with missing items. const bool append = - nalu_list->first_item->second_hash && !nalu_list->first_item->need_second_verification; + nalu_list->first_item->second_hash && !nalu_list->first_item->tmp_need_second_verification; // No need to check the return value. A failure only affects the statistics. In the worst case // we may signal SV_AUTH_RESULT_OK instead of SV_AUTH_RESULT_OK_WITH_MISSING_INFO. legacy_h26x_nalu_list_add_missing(nalu_list, num_missing_nalus, append, nalu_list->first_item); @@ -266,10 +276,10 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, if (last_used_item) { if (latest_match_idx != compare_idx) { // Last verified hash is invalid. - last_used_item->first_verification_not_authentic = true; + last_used_item->tmp_first_verification_not_authentic = true; // Give this NALU a second verification because it could be that it is present in the next GOP // and brought in here due to some lost NALUs. - last_used_item->need_second_verification = true; + last_used_item->tmp_need_second_verification = true; } else { // Last received hash is valid. Check if there are unused hashes in |hash_list|. Note that the // index of the hashes span from 0 to |num_expected_hashes| - 1, so if |latest_match_idx| = @@ -291,7 +301,7 @@ legacy_verify_hashes_with_hash_list(legacy_sv_t *self, // Done with the SEI. Mark as valid, because if we failed verifying the |document_hash| we would // not be here. - sei->validation_status = '.'; + sei->tmp_validation_status = '.'; if (num_expected_nalus) *num_expected_nalus = num_expected_hashes; if (num_received_nalus) *num_received_nalus = num_verified_hashes; @@ -316,13 +326,14 @@ legacy_set_validation_status_of_items_used_in_gop_hash(legacy_h26x_nalu_list_t * if (item->used_in_gop_hash) { // Items used in two verifications should not have |validation_status| set until it has been // used twice. If this is the first time we set the flag |first_verification_not_authentic|. - if (item->second_hash && !item->need_second_verification) { + if (item->second_hash && !item->tmp_need_second_verification) { DEBUG_LOG("This NALU needs a second verification"); - item->need_second_verification = true; - item->first_verification_not_authentic = (validation_status != '.') ? true : false; + item->tmp_need_second_verification = true; + item->tmp_first_verification_not_authentic = (validation_status != '.') ? true : false; } else { - item->validation_status = item->first_verification_not_authentic ? 'N' : validation_status; - item->need_second_verification = false; + item->tmp_validation_status = + item->tmp_first_verification_not_authentic ? 'N' : validation_status; + item->tmp_need_second_verification = false; num_marked_items++; } } @@ -428,7 +439,7 @@ legacy_verify_hashes_without_sei(legacy_sv_t *self) bool found_next_gop = false; while (item && !found_next_gop) { // Skip non-pending items. - if (item->validation_status != 'P') { + if (item->tmp_validation_status != 'P') { item = item->next; continue; } @@ -436,16 +447,16 @@ legacy_verify_hashes_without_sei(legacy_sv_t *self) // A new GOP starts if the NALU |is_first_nalu_in_gop|. Such a NALU is hashed twice; as an // initial hash AND as a linking hash between GOPs. If this is the first time is is used in // verification it also marks the start of a new GOP. - found_next_gop = item->nalu->is_first_nalu_in_gop && !item->need_second_verification; + found_next_gop = item->nalu->is_first_nalu_in_gop && !item->tmp_need_second_verification; // Mark the item as 'Not Authentic' or keep it for a second verification. if (found_next_gop) { // Keep the item pending and mark the first verification as not authentic. - item->need_second_verification = true; - item->first_verification_not_authentic = true; - } else if (item->validation_status == 'P') { - item->need_second_verification = false; - item->validation_status = 'N'; + item->tmp_need_second_verification = true; + item->tmp_first_verification_not_authentic = true; + } else if (item->tmp_validation_status == 'P') { + item->tmp_need_second_verification = false; + item->tmp_validation_status = 'N'; num_marked_items++; } item = item->next; @@ -576,7 +587,8 @@ legacy_validate_authenticity(legacy_sv_t *self) num_received_nalus = -1; // If validation was tried with the very first SEI in stream it cannot be part at. // Reset the first validation to be able to validate a segment in the middle of the stream. - self->validation_flags.reset_first_validation = (self->gop_info->num_sent_nalus == 1); + self->validation_flags.reset_first_validation = + (self->gop_info->num_sent_nalus == 1) || !has_valid_nalus; } } if (latest->public_key_has_changed) valid = SV_AUTH_RESULT_NOT_OK; @@ -600,6 +612,37 @@ legacy_remove_used_in_gop_hash(legacy_h26x_nalu_list_t *nalu_list) } } +/* Updates validation status for SEI that is |in_validation|. */ +static void +legacy_update_sei_validation(legacy_sv_t *self, + bool reset_in_validation, + char *get_validation_status, + char *set_validation_status) +{ + legacy_h26x_nalu_list_item_t *item = self->nalu_list->first_item; + while (item) { + if (item->nalu && item->nalu->is_gop_sei && item->in_validation) { + if (reset_in_validation) { + item->in_validation = false; + } + if (get_validation_status) { + if (item->tmp_validation_status == '.') { + *get_validation_status = item->tmp_validation_status; + } + item->tmp_validation_status = item->validation_status; + } + if (set_validation_status) { + if (item->next && item->next->nalu) { + item->validation_status = *set_validation_status; + item->tmp_validation_status = *set_validation_status; + } + } + break; + } + item = item->next; + } +} + /* Computes the gop_hash of the oldest pending GOP in the nalu_list and completes the recursive * operation with the hash of the |sei|. */ static svrc_t @@ -637,7 +680,7 @@ legacy_compute_gop_hash(legacy_sv_t *self, legacy_h26x_nalu_list_item_t *sei) item = nalu_list->first_item; while (item && !(found_next_gop || found_item_after_sei)) { // If this item is not Pending, move to the next one. - if (item->validation_status != 'P') { + if (item->tmp_validation_status != 'P') { item = item->next; continue; } @@ -646,7 +689,7 @@ legacy_compute_gop_hash(legacy_sv_t *self, legacy_h26x_nalu_list_item_t *sei) // Check if this is the item after the |sei|. found_item_after_sei = (item->prev == sei); // Check if this |is_first_nalu_in_gop|, but used in verification for the first time. - found_next_gop = (item->nalu->is_first_nalu_in_gop && !item->need_second_verification); + found_next_gop = (item->nalu->is_first_nalu_in_gop && !item->tmp_need_second_verification); // If this is the SEI associated with the GOP, or any SEI, we skip it. The SEI hash will be // added to |gop_hash| as the last hash. if (item->nalu->is_gop_sei) { @@ -656,7 +699,7 @@ legacy_compute_gop_hash(legacy_sv_t *self, legacy_h26x_nalu_list_item_t *sei) // Fetch the |hash_to_add|, which normally is the item->hash, but if the item has been used // ones in verification we use the |second_hash|. - hash_to_add = item->need_second_verification ? item->second_hash : item->hash; + hash_to_add = item->tmp_need_second_verification ? item->second_hash : item->hash; // Copy to the |nalu_hash| slot in the memory and update the gop_hash. memcpy(nalu_hash, hash_to_add, hash_size); SV_THROW(legacy_update_gop_hash(self->crypto_handle, gop_info)); @@ -703,6 +746,9 @@ legacy_prepare_for_validation(legacy_sv_t *self) svrc_t status = SV_UNKNOWN_FAILURE; SV_TRY() legacy_h26x_nalu_list_item_t *sei = legacy_h26x_nalu_list_get_next_sei_item(nalu_list); + if (sei) { + sei->in_validation = true; + } if (sei && !sei->has_been_decoded) { // Decode the SEI and set signature->hash const uint8_t *tlv_data = sei->nalu->tlv_data; @@ -728,7 +774,7 @@ legacy_prepare_for_validation(legacy_sv_t *self) #ifdef SV_VENDOR_AXIS_COMMUNICATIONS // If "Axis Communications AB" can be identified from the |product_info|, get // |supplemental_authenticity| from |vendor_handle|. - if (self->product_info->manufacturer && + if (sei && self->product_info->manufacturer && strcmp(self->product_info->manufacturer, "Axis Communications AB") == 0) { sv_vendor_axis_supplemental_authenticity_t *supplemental_authenticity = NULL; @@ -816,8 +862,9 @@ legacy_has_pending_gop(legacy_sv_t *self) legacy_gop_state_update(gop_state, item->nalu); // Collect statistics from pending and hashable NALUs only. The others are either out of date or // not part of the validation. - if (item->validation_status == 'P' && item->nalu && item->nalu->is_hashable) { - num_pending_gop_ends += (item->nalu->is_first_nalu_in_gop && !item->need_second_verification); + if (item->tmp_validation_status == 'P' && item->nalu && item->nalu->is_hashable) { + num_pending_gop_ends += + (item->nalu->is_first_nalu_in_gop && !item->tmp_need_second_verification); found_pending_gop_sei |= item->nalu->is_gop_sei; found_pending_nalu_after_gop_sei |= last_hashable_item && last_hashable_item->nalu->is_gop_sei; @@ -909,6 +956,9 @@ legacy_maybe_validate_gop(legacy_sv_t *self, legacy_h26x_nalu_t *nalu) svrc_t status = SV_UNKNOWN_FAILURE; SV_TRY() + bool update_validation_status = false; + bool public_key_has_changed = false; + char sei_validation_status = 'U'; // Keep validating as long as there are pending GOPs. bool stop_validating = false; while (legacy_has_pending_gop(self) && !stop_validating) { @@ -917,7 +967,11 @@ legacy_maybe_validate_gop(legacy_sv_t *self, legacy_h26x_nalu_t *nalu) latest->number_of_expected_picture_nalus = -1; latest->number_of_received_picture_nalus = -1; latest->number_of_pending_picture_nalus = -1; - latest->public_key_has_changed = false; + latest->public_key_has_changed = public_key_has_changed; + + if (validation_flags->is_first_validation) { + legacy_update_sei_validation(self, true, NULL, NULL); + } SV_THROW(legacy_prepare_for_validation(self)); @@ -930,33 +984,34 @@ legacy_maybe_validate_gop(legacy_sv_t *self, legacy_h26x_nalu_t *nalu) legacy_validate_authenticity(self); } + if (validation_flags->is_first_validation && (latest->authenticity != SV_AUTH_RESULT_OK)) { + legacy_update_sei_validation(self, false, &sei_validation_status, NULL); + } // The flag |is_first_validation| is used to ignore the first validation if we start the // validation in the middle of a stream. Now it is time to reset it. validation_flags->is_first_validation = !validation_flags->signing_present; if (validation_flags->reset_first_validation) { validation_flags->is_first_validation = true; - legacy_h26x_nalu_list_item_t *item = self->nalu_list->first_item; - while (item) { - if (item->nalu && item->nalu->is_first_nalu_in_gop) { - item->need_second_verification = false; - item->first_verification_not_authentic = false; - break; - } - item = item->next; - } + validation_flags->reset_first_validation = false; + } else { + update_validation_status = true; } self->gop_info->verified_signature_hash = -1; self->validation_flags.has_auth_result = true; - - // All statistics but pending NALUs have already been collected. - latest->number_of_pending_picture_nalus = legacy_h26x_nalu_list_num_pending_items(nalu_list); - - DEBUG_LOG("Validated GOP as %s", kLegacyAuthResultValidStr[latest->authenticity]); - DEBUG_LOG("Expected number of NALUs = %d", latest->number_of_expected_picture_nalus); - DEBUG_LOG("Received number of NALUs = %d", latest->number_of_received_picture_nalus); - DEBUG_LOG("Number of pending NALUs = %d", latest->number_of_pending_picture_nalus); + public_key_has_changed |= latest->public_key_has_changed; + } + SV_THROW(legacy_h26x_nalu_list_update_status(nalu_list, update_validation_status)); + if (validation_flags->is_first_validation) { + legacy_update_sei_validation(self, false, NULL, &sei_validation_status); } + // All statistics but pending NALUs have already been collected. + latest->number_of_pending_picture_nalus = legacy_h26x_nalu_list_num_pending_items(nalu_list); + + DEBUG_LOG("Validated GOP as %s", kLegacyAuthResultValidStr[latest->authenticity]); + DEBUG_LOG("Expected number of NALUs = %d", latest->number_of_expected_picture_nalus); + DEBUG_LOG("Received number of NALUs = %d", latest->number_of_received_picture_nalus); + DEBUG_LOG("Number of pending NALUs = %d", latest->number_of_pending_picture_nalus); SV_CATCH() SV_DONE(status) diff --git a/lib/src/legacy/legacy_h26x_common.c b/lib/src/legacy/legacy_h26x_common.c index 8d8cd5e..81f0dbe 100644 --- a/lib/src/legacy/legacy_h26x_common.c +++ b/lib/src/legacy/legacy_h26x_common.c @@ -819,7 +819,9 @@ legacy_hash_and_add_for_auth(legacy_sv_t *self, legacy_h26x_nalu_list_item_t *it // Check if we have a potential transition to a new GOP. This happens if the current NALU // |is_first_nalu_in_gop|. If we have lost the first NALU of a GOP we can still make a guess by // checking if |has_sei| flag is set. It is set if the previous hashable NALU was SEI. - if (nalu->is_first_nalu_in_gop || (gop_state->validate_after_next_nalu && !nalu->is_gop_sei)) { + if (nalu->is_first_nalu_in_gop || + (gop_state->validate_after_next_nalu && !nalu->is_gop_sei && + gop_info->global_gop_counter_is_synced)) { // Updates counters and reset flags. gop_info->has_reference_hash = false; diff --git a/lib/src/legacy/legacy_h26x_internal.h b/lib/src/legacy/legacy_h26x_internal.h index 837b68a..f2b3798 100644 --- a/lib/src/legacy/legacy_h26x_internal.h +++ b/lib/src/legacy/legacy_h26x_internal.h @@ -118,6 +118,11 @@ struct _legacy_h26x_nalu_list_item_st { bool has_been_decoded; // Marks a SEI as decoded. Decoding it twice might overwrite vital // information. bool used_in_gop_hash; // Marks the NALU as being part of a computed |gop_hash|. + bool in_validation; // Marks the SEI that is currently up for use. Necessary for synchronization. + // Temporary flags used before updating the final ones. + char tmp_validation_status; + bool tmp_need_second_verification; + bool tmp_first_verification_not_authentic; // Linked list legacy_h26x_nalu_list_item_t diff --git a/lib/src/legacy/legacy_h26x_nalu_list.c b/lib/src/legacy/legacy_h26x_nalu_list.c index 57d343e..b5a4344 100644 --- a/lib/src/legacy/legacy_h26x_nalu_list.c +++ b/lib/src/legacy/legacy_h26x_nalu_list.c @@ -68,6 +68,7 @@ legacy_h26x_nalu_list_item_create(const legacy_h26x_nalu_t *nalu) item->nalu = (legacy_h26x_nalu_t *)nalu; item->taken_ownership_of_nalu = false; item->validation_status = legacy_get_validation_status_from_nalu(nalu); + item->tmp_validation_status = item->validation_status; return item; } @@ -312,6 +313,8 @@ legacy_h26x_nalu_list_add_missing(legacy_h26x_nalu_list_t *list, SV_THROW_IF(!missing_nalu, SV_MEMORY); missing_nalu->validation_status = 'M'; + missing_nalu->tmp_validation_status = 'M'; + missing_nalu->in_validation = true; if (append) { legacy_h26x_nalu_list_item_append_item(item, missing_nalu); } else { @@ -339,28 +342,30 @@ legacy_h26x_nalu_list_remove_missing_items(legacy_h26x_nalu_list_t *list) bool found_first_pending_nalu = false; bool found_decoded_sei = false; + int num_removed_items = 0; legacy_h26x_nalu_list_item_t *item = list->first_item; while (item && !(found_first_pending_nalu && found_decoded_sei)) { // Reset the invalid verification failure if we have not past the first pending item. - if (!found_first_pending_nalu) item->first_verification_not_authentic = false; + if (!found_first_pending_nalu) item->tmp_first_verification_not_authentic = false; // Remove the missing NALU in the front. - if (item->validation_status == 'M' && (item == list->first_item)) { + if (item->tmp_validation_status == 'M' && item->in_validation) { const legacy_h26x_nalu_list_item_t *item_to_remove = item; item = item->next; legacy_h26x_nalu_list_remove_and_free_item(list, item_to_remove); + num_removed_items++; continue; } - if (item->has_been_decoded && item->validation_status != 'U') { + if (item->has_been_decoded && item->tmp_validation_status != 'U' && item->in_validation) { // Usually, these items were added because we verified hashes with a SEI not associated with // this recording. This can happen if we export to file or fast forward in a recording. The // SEI used to generate these missing items is set to 'U'. - item->validation_status = 'U'; found_decoded_sei = true; } - if (item->validation_status == 'P') found_first_pending_nalu = true; + if (item->tmp_validation_status == 'P') found_first_pending_nalu = true; item = item->next; } + if (num_removed_items > 0) DEBUG_LOG("Removed %d missing items to list", num_removed_items); } /* Searches for, and returns, the next pending SEI item. */ @@ -371,7 +376,7 @@ legacy_h26x_nalu_list_get_next_sei_item(const legacy_h26x_nalu_list_t *list) legacy_h26x_nalu_list_item_t *item = list->first_item; while (item) { - if (item->nalu && item->nalu->is_gop_sei && item->validation_status == 'P') break; + if (item->nalu && item->nalu->is_gop_sei && item->tmp_validation_status == 'P') break; item = item->next; } return item; @@ -397,17 +402,25 @@ legacy_h26x_nalu_list_get_stats(const legacy_h26x_nalu_list_t *list, // From the list, get number of invalid NALUs and number of missing NALUs. legacy_h26x_nalu_list_item_t *item = list->first_item; while (item) { - if (item->validation_status == 'M') local_num_missing_nalus++; - if (item->validation_status == 'N' || item->validation_status == 'E') local_num_invalid_nalus++; - if (item->validation_status == '.') { + if (item->tmp_validation_status == 'M') local_num_missing_nalus++; + if (item->nalu && item->nalu->is_gop_sei) { + if (item->in_validation && + (item->tmp_validation_status == 'N' || item->tmp_validation_status == 'E')) + local_num_invalid_nalus++; + } else { + if (item->tmp_validation_status == 'N' || item->tmp_validation_status == 'E') + local_num_invalid_nalus++; + } + if (item->tmp_validation_status == '.') { // Do not count SEIs, since they are marked valid if the signature could be verified, which // happens for out-of-sync SEIs for example. has_valid_nalus |= !(item->nalu && item->nalu->is_gop_sei); } - if (item->validation_status == 'P') { + if (item->tmp_validation_status == 'P') { // Count NALUs that were verified successfully the first time and waiting for a second // verification. - has_valid_nalus |= item->need_second_verification && !item->first_verification_not_authentic; + has_valid_nalus |= + item->tmp_need_second_verification && !item->tmp_first_verification_not_authentic; } item = item->next; } @@ -427,7 +440,7 @@ legacy_h26x_nalu_list_num_pending_items(const legacy_h26x_nalu_list_t *list) int num_pending_nalus = 0; legacy_h26x_nalu_list_item_t *item = list->first_item; while (item) { - if (item->validation_status == 'P') num_pending_nalus++; + if (item->tmp_validation_status == 'P') num_pending_nalus++; item = item->next; } @@ -486,3 +499,24 @@ legacy_h26x_nalu_list_clean_up(legacy_h26x_nalu_list_t *list) return removed_items; } + +svrc_t +legacy_h26x_nalu_list_update_status(legacy_h26x_nalu_list_t *list, bool update) +{ + if (!list) return SV_INVALID_PARAMETER; + + legacy_h26x_nalu_list_item_t *item = list->first_item; + while (item) { + if (update) { + item->first_verification_not_authentic = item->tmp_first_verification_not_authentic; + item->need_second_verification = item->tmp_need_second_verification; + item->validation_status = item->tmp_validation_status; + } else { + item->tmp_first_verification_not_authentic = item->first_verification_not_authentic; + item->tmp_need_second_verification = item->need_second_verification; + item->tmp_validation_status = item->validation_status; + } + item = item->next; + } + return SV_OK; +} diff --git a/lib/src/legacy/legacy_h26x_nalu_list.h b/lib/src/legacy/legacy_h26x_nalu_list.h index 7245169..1794edc 100644 --- a/lib/src/legacy/legacy_h26x_nalu_list.h +++ b/lib/src/legacy/legacy_h26x_nalu_list.h @@ -197,4 +197,7 @@ legacy_h26x_nalu_list_get_str(const legacy_h26x_nalu_list_t* list, unsigned int legacy_h26x_nalu_list_clean_up(legacy_h26x_nalu_list_t* list); +svrc_t +legacy_h26x_nalu_list_update_status(legacy_h26x_nalu_list_t* nalu_list, bool update); + #endif // __LEGACY_H26X_NALU_LIST_H__