Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/src/includes/signed_video_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,24 @@ typedef struct {
// A new Public key has been detected. Signing an ongoing stream with a new key is not allowed. If
// this flag is set the |authenticity| is automatically set to SV_AUTH_RESULT_NOT_OK.
bool public_key_has_changed;
// NAL Unit statistics. Main usage is to track every single NAL Unit added for authentication.
//
// Total number of received Bitstream Units, that is all Bitstream Units added for validation.
unsigned int number_of_received_nalus;
// Total number of validated Bitstream Units, that is, how many of the received Bitstream Units
// that so far have been validated.
unsigned int number_of_validated_nalus;
// The number of Bitstream Units that currently are pending validation.
unsigned int number_of_pending_nalus;
// Frame statistics. Main usage is to know which frames to display as validated/authentic.
//
// Total number of received frames added for validation.
unsigned int number_of_received_frames;
// Total number of validated frames, that is, how many of the received frames that so far have
// been validated.
unsigned int number_of_validated_frames;
// The number of frames that currently are pending validation.
unsigned int number_of_pending_frames;
// The result of the Public key validation. If the Public key is present in the SEI/OBU Metadata,
// it has to be validated to associate the video with a source. If it is not feasible to validate
// the Public key, it should be validated manually to secure proper video authenticity.
Expand Down
24 changes: 23 additions & 1 deletion lib/src/legacy/legacy_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,9 @@ legacy_add_bu(legacy_sv_t *self, const uint8_t *bu_data, size_t bu_data_size)
self->validation_flags.has_auth_result = false;

self->accumulated_validation->number_of_received_nalus++;
if (bu.is_primary_slice) {
self->accumulated_validation->number_of_received_frames++;
}

svrc_t status = SV_UNKNOWN_FAILURE;
SV_TRY()
Expand Down Expand Up @@ -1113,6 +1116,23 @@ legacy_get_num_bu_items(legacy_sv_t *self)
return self->bu_list->num_items;
}

unsigned int
legacy_get_num_pending_frames(const legacy_sv_t *self)
{
if (!self || !self->bu_list) return 0;

unsigned int num_pending_frames = 0;
legacy_bu_list_item_t *item = self->bu_list->first_item;
while (item) {
if ((item->tmp_validation_status == 'P') && item->bu->is_primary_slice) {
num_pending_frames++;
}
item = item->next;
}

return num_pending_frames;
}

// Copied from signed_video_authenticity.c
static void
legacy_update_authenticity_report(legacy_sv_t *self)
Expand All @@ -1137,13 +1157,15 @@ legacy_update_authenticity_report(legacy_sv_t *self)
self->authenticity->latest_validation.authenticity = SV_AUTH_RESULT_VERSION_MISMATCH;
}
// Remove validated items from the list.
const unsigned int number_validated = legacy_bu_list_clean_up(self->bu_list);
unsigned int validated_frames = 0;
const unsigned int number_validated = legacy_bu_list_clean_up(self->bu_list, &validated_frames);
// Update the |accumulated_validation| w.r.t. the |latest_validation|.
update_accumulated_validation(self->latest_validation, self->accumulated_validation);
// Only update |number_of_validated_nalus| if the video is signed. Currently, unsigned videos are
// validated (as not OK) since SEIs are assumed to arrive within a GOP. From a statistics point of
// view, that is not strictly not correct.
if (self->accumulated_validation->authenticity != SV_AUTH_RESULT_NOT_SIGNED) {
self->accumulated_validation->number_of_validated_nalus += number_validated;
self->accumulated_validation->number_of_validated_frames += validated_frames;
}
}
8 changes: 6 additions & 2 deletions lib/src/legacy/legacy_bu_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,16 +477,20 @@ legacy_bu_list_get_str(const legacy_bu_list_t *list, LegacyBUListStringType str_

/* Cleans up the list by removing the validated items. */
unsigned int
legacy_bu_list_clean_up(legacy_bu_list_t *list)
legacy_bu_list_clean_up(legacy_bu_list_t *list, unsigned int *removed_frames)
{
if (!list) return 0;
if (!list || !removed_frames) return 0;

// Remove validated items.
unsigned int removed_items = 0;
legacy_bu_list_item_t *item = list->first_item;
*removed_frames = 0;
while (item && item->validation_status != 'P' && !item->need_second_verification) {
if (item->validation_status != 'M') {
removed_items++;
if (item->bu->is_primary_slice) {
(*removed_frames)++;
}
}
legacy_bu_list_remove_and_free(list, list->first_item);
item = list->first_item;
Expand Down
3 changes: 2 additions & 1 deletion lib/src/legacy/legacy_bu_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,12 @@ legacy_bu_list_get_str(const legacy_bu_list_t* list, LegacyBUListStringType str_
* information that was supposed to be presented to the end user.
*
* @param list The list to clean from validated items.
* @param removed_frames A pointer to where the number of removed frames is written.
*
* @return Number of removed items, excluding previously added 'missing' BUs.
*/
unsigned int
legacy_bu_list_clean_up(legacy_bu_list_t* list);
legacy_bu_list_clean_up(legacy_bu_list_t* list, unsigned int* removed_frames);

svrc_t
legacy_bu_list_update_status(legacy_bu_list_t* bu_list, bool update);
Expand Down
8 changes: 6 additions & 2 deletions lib/src/legacy/legacy_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ legacy_parse_h264_nalu_header(legacy_bu_info_t *nalu)
break;
}

// Primary slice only applies to picture NAL Units.
nalu->is_primary_slice &= (nalu->bu_type == BU_TYPE_I || nalu->bu_type == BU_TYPE_P);

// If the forbidden_zero_bit is set this is not a correct NALU header.
nalu_header_is_valid &= !forbidden_zero_bit;
return nalu_header_is_valid;
Expand Down Expand Up @@ -294,9 +297,7 @@ legacy_parse_h265_nalu_header(legacy_bu_info_t *nalu)
switch (nalu_type) {
// 0 to 5. Trailing non-IRAP pictures
case 0: // 0 TRAIL_N Coded slice segment of a non-TSA, non-STSA trailing picture VCL

case 1: // 1 TRAIL_R Coded slice segment of a non-TSA, non-STSA trailing picture VCL

nalu->bu_type = BU_TYPE_P;
nalu_header_is_valid = true;
break;
Expand Down Expand Up @@ -378,6 +379,9 @@ legacy_parse_h265_nalu_header(legacy_bu_info_t *nalu)
break;
}

// Primary slice only applies to picture NAL Units.
nalu->is_primary_slice &= (nalu->bu_type == BU_TYPE_I || nalu->bu_type == BU_TYPE_P);

// If the forbidden_zero_bit is set this is not a correct NALU header.
nalu_header_is_valid &= !forbidden_zero_bit;
return nalu_header_is_valid;
Expand Down
3 changes: 3 additions & 0 deletions lib/src/legacy_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,7 @@ legacy_sv_add_and_authenticate(legacy_sv_t *self,
int
legacy_get_num_bu_items(legacy_sv_t *self);

unsigned int
legacy_get_num_pending_frames(const legacy_sv_t *self);

#endif // __LEGACY_VALIDATION_H__
3 changes: 3 additions & 0 deletions lib/src/sv_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,9 @@ add_bitstream_unit(signed_video_t *self, const uint8_t *bu_data, size_t bu_data_
validation_flags->has_auth_result = false;

self->accumulated_validation->number_of_received_nalus++;
if (bu.is_primary_slice) {
self->accumulated_validation->number_of_received_frames++;
}
const bool nalus_pending_registration = !self->validation_flags.hash_algo_known;

svrc_t status = SV_UNKNOWN_FAILURE;
Expand Down
17 changes: 16 additions & 1 deletion lib/src/sv_authenticity.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ transfer_accumulated_validation(signed_video_accumulated_validation_t *dst,
dst->number_of_received_nalus = src->number_of_received_nalus;
dst->number_of_validated_nalus = src->number_of_validated_nalus;
dst->number_of_pending_nalus = src->number_of_pending_nalus;
dst->number_of_received_frames = src->number_of_received_frames;
dst->number_of_validated_frames = src->number_of_validated_frames;
dst->number_of_pending_frames = src->number_of_pending_frames;
dst->public_key_validation = src->public_key_validation;
dst->has_timestamp = src->has_timestamp;
dst->first_timestamp = src->first_timestamp;
Expand Down Expand Up @@ -201,6 +204,9 @@ sv_accumulated_validation_init(signed_video_accumulated_validation_t *self)
self->number_of_received_nalus = 0;
self->number_of_validated_nalus = 0;
self->number_of_pending_nalus = 0;
self->number_of_received_frames = 0;
self->number_of_validated_frames = 0;
self->number_of_pending_frames = 0;
self->public_key_validation = SV_PUBKEY_VALIDATION_NOT_FEASIBLE;
self->has_timestamp = false;
self->first_timestamp = 0;
Expand Down Expand Up @@ -278,14 +284,16 @@ sv_update_authenticity_report(signed_video_t *self)
self->authenticity->latest_validation.authenticity = SV_AUTH_RESULT_VERSION_MISMATCH;
}
// Remove validated items from the list.
const unsigned int number_of_validated_bu = bu_list_clean_up(self->bu_list);
unsigned int validated_frames = 0;
const unsigned int number_of_validated_bu = bu_list_clean_up(self->bu_list, &validated_frames);
// Update the |accumulated_validation| w.r.t. the |latest_validation|.
update_accumulated_validation(self->latest_validation, self->accumulated_validation);
// Only update |number_of_validated_bu| if the video is signed. Currently, unsigned
// videos are validated (as not OK) since SEIs are assumed to arrive within a GOP. From
// a statistics point of view, that is not strictly not correct.
if (self->accumulated_validation->authenticity != SV_AUTH_RESULT_NOT_SIGNED) {
self->accumulated_validation->number_of_validated_nalus += number_of_validated_bu;
self->accumulated_validation->number_of_validated_frames += validated_frames;
}
}

Expand Down Expand Up @@ -328,12 +336,16 @@ signed_video_get_authenticity_report(signed_video_t *self)
// If the video is (so far) not signed, number of pending Bitstream Units equals the
// number of added Bitstream Units for validation.
accumulated->number_of_pending_nalus = accumulated->number_of_received_nalus;
accumulated->number_of_pending_frames = accumulated->number_of_received_frames;
} else {
// At this point, all validated Bitstream Units up to the first pending Bitstream
// Unit have been removed from the |bu_list|, hence number of pending Bitstream
// Units equals number of items in the |bu_list|.
accumulated->number_of_pending_nalus =
self->legacy_sv ? legacy_get_num_bu_items(self->legacy_sv) : self->bu_list->num_items;
accumulated->number_of_pending_frames = self->legacy_sv
? legacy_get_num_pending_frames(self->legacy_sv)
: bu_list_get_num_pending_frames(self->bu_list);
}

SV_THROW(transfer_authenticity(authenticity_report, self->authenticity));
Expand Down Expand Up @@ -501,6 +513,9 @@ transfer_onvif_accumulated(signed_video_accumulated_validation_t *accumulated,
accumulated->number_of_received_nalus = onvif_accumulated->number_of_received_nalus;
accumulated->number_of_validated_nalus = onvif_accumulated->number_of_validated_nalus;
accumulated->number_of_pending_nalus = onvif_accumulated->number_of_pending_nalus;
accumulated->number_of_received_frames = onvif_accumulated->number_of_received_frames;
accumulated->number_of_validated_frames = onvif_accumulated->number_of_validated_frames;
accumulated->number_of_pending_frames = onvif_accumulated->number_of_pending_frames;
// Convert provenance result
switch (onvif_accumulated->provenance) {
case OMS_PROVENANCE_OK:
Expand Down
25 changes: 23 additions & 2 deletions lib/src/sv_bu_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,23 @@ bu_list_num_pending_items(const bu_list_t *list)
return num_pending_bu;
}

unsigned int
bu_list_get_num_pending_frames(const bu_list_t *list)
{
if (!list) return 0;

unsigned int num_pending_frames = 0;
bu_list_item_t *item = list->first_item;
while (item) {
if ((item->tmp_validation_status == 'P') && item->bu->is_primary_slice) {
num_pending_frames++;
}
item = item->next;
}

return num_pending_frames;
}

svrc_t
bu_list_update_status(bu_list_t *list, bool update)
{
Expand Down Expand Up @@ -639,18 +656,22 @@ bu_list_get_str(const bu_list_t *list, BitstreamUnitListStringType str_type)

/* Cleans up the list by removing the validated items. */
unsigned int
bu_list_clean_up(bu_list_t *list)
bu_list_clean_up(bu_list_t *list, unsigned int *removed_frames)
{
if (!list) {
if (!list || !removed_frames) {
return 0;
}

// Remove validated items.
unsigned int removed_items = 0;
bu_list_item_t *item = list->first_item;
*removed_frames = 0;
while (item && item->validation_status != 'P') {
if (item->validation_status != 'M') {
removed_items++;
if (item->bu->is_primary_slice) {
(*removed_frames)++;
}
}
bu_list_remove_and_free_item(list, list->first_item);
item = list->first_item;
Expand Down
13 changes: 12 additions & 1 deletion lib/src/sv_bu_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@ bu_list_get_stats(const bu_list_t* list,
int
bu_list_num_pending_items(const bu_list_t* list);

/**
* @brief Counts and returns number of frames pending validation
*
* @param list The |list| to count pending frames.
*
* @return Number of frames pending validation. Returns zero upon failure.
*/
unsigned int
bu_list_get_num_pending_frames(const bu_list_t* list);

/**
* @brief Updates or resets validation status of all items in a list
*
Expand Down Expand Up @@ -219,11 +229,12 @@ bu_list_get_str(const bu_list_t* list, BitstreamUnitListStringType str_type);
* was supposed to be presented to the end user.
*
* @param list The list to clean from validated items.
* @param removed_frames A pointer to where the number of removed frames is written.
*
* @return Number of removed items, excluding previously added 'missing' BUs.
*/
unsigned int
bu_list_clean_up(bu_list_t* list);
bu_list_clean_up(bu_list_t* list, unsigned int* removed_frames);

/**
* @brief Prints all items in the list
Expand Down
8 changes: 6 additions & 2 deletions lib/src/sv_codec_h26x.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ parse_h264_nalu_header(bu_info_t *bu)
break;
}

// Primary slice only applies to picture NAL Units.
bu->is_primary_slice &= (bu->bu_type == BU_TYPE_I || bu->bu_type == BU_TYPE_P);

// If the forbidden_zero_bit is set this is not a correct NALU header.
nalu_header_is_valid &= !forbidden_zero_bit;
return nalu_header_is_valid;
Expand Down Expand Up @@ -127,9 +130,7 @@ parse_h265_nalu_header(bu_info_t *bu)
switch (nalu_type) {
// 0 to 5. Trailing non-IRAP pictures
case 0: // 0 TRAIL_N Coded slice segment of a non-TSA, non-STSA trailing picture VCL

case 1: // 1 TRAIL_R Coded slice segment of a non-TSA, non-STSA trailing picture VCL

bu->bu_type = BU_TYPE_P;
nalu_header_is_valid = true;
break;
Expand Down Expand Up @@ -211,6 +212,9 @@ parse_h265_nalu_header(bu_info_t *bu)
break;
}

// Primary slice only applies to picture NAL Units.
bu->is_primary_slice &= (bu->bu_type == BU_TYPE_I || bu->bu_type == BU_TYPE_P);

// If the forbidden_zero_bit is set this is not a correct NALU header.
nalu_header_is_valid &= !forbidden_zero_bit;
return nalu_header_is_valid;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/sv_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#define DEFAULT_HASH_SIZE (256 / 8)

#define SV_VERSION_BYTES 3
#define SIGNED_VIDEO_VERSION "v2.3.2"
#define SIGNED_VIDEO_VERSION "v2.3.3"
#define SV_VERSION_MAX_STRLEN 19 // Longest possible string including 'ONVIF' prefix

#define DEFAULT_AUTHENTICITY_LEVEL SV_AUTHENTICITY_LEVEL_FRAME
Expand Down
3 changes: 3 additions & 0 deletions lib/src/sv_onvif.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ typedef struct {
unsigned int number_of_received_nalus;
unsigned int number_of_validated_nalus;
unsigned int number_of_pending_nalus;
unsigned int number_of_received_frames;
unsigned int number_of_validated_frames;
unsigned int number_of_pending_frames;
int64_t first_timestamp;
int64_t last_timestamp;
} onvif_media_signing_accumulated_validation_t;
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project('signed-video-framework', 'c',
version : '2.3.2',
version : '2.3.3',
meson_version : '>= 0.53.0',
default_options : [ 'warning_level=2',
'werror=true',
Expand Down
Loading
Loading