Skip to content

Commit

Permalink
API change signed_video_get_sei(...) (#287)
Browse files Browse the repository at this point in the history
Now returns a pointer to the SEI/OBU Metadata memory. The memory
is transferred and the user is responsible for freeing it.
Also, payload_offset is made unsigned, since it cannot take
negative values.

Version is bumped to v2.0.2.

Co-authored-by: bjornvolcker <bjornvolcker@users.noreply.github.com>
  • Loading branch information
bjornvolcker and bjornvolcker authored Dec 19, 2024
1 parent 1fd0d6e commit 68178fa
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 121 deletions.
28 changes: 10 additions & 18 deletions lib/src/includes/signed_video_sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,19 +231,17 @@ signed_video_get_nalu_to_prepend(signed_video_t *self,
/**
* @brief Gets generated SEIs/OBU Metadata to add to the stream
*
* This function should be called before
* This function is recommended to be called before
* signed_video_add_nalu_for_signing_with_timestamp(...). The user has an option to
* provide this function with a |peek_nalu|, which is the same NAL Unit/OBU that is to be
* added for signing. Even though, the user does not have to call this function before
* adding NAL Units for signing, it is highly recommended to avoid missing or delaying
* SEIs/OBU Metadata.
* added for signing.
*
* These SEIs/OBU Metadata are generated by the Signed Video library and are complete NAL Units + 4
* start code bytes, or OBUs. Hence, the user can simply pull and prepend existing H26x NAL Units,
* or AV1 OBUs. Pull NAL Units/OBUs to prepend from signed_video_t one by one until no more
* generated SEIs/OBU Metadata exists, that is, when |sei_size| is zero.
*
* NOTE: The user is responsible for allocating memory for the |sei|.
* NOTE: The memory is transferred and the user is responsible for freeing memory of the |sei|.
*
* Here is an example code of usage:
*
Expand All @@ -256,29 +254,23 @@ signed_video_get_nalu_to_prepend(signed_video_t *self,
* // Handle error
* }
* SignedVideoReturnCode status;
* uint8_t *sei = NULL;
* size_t sei_size = 0;
* // The first call of the function is for getting the |sei_size|.
* status = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
* // The second call is to get the sei.
* // Get the SEI data.
* status = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
* while (status == SV_OK && sei_size > 0) {
* uint8_t *sei = malloc(sei_size);
* status = signed_video_get_sei(sv, sei, &sei_size, NULL, NULL, 0, NULL);
* if (status != SV_OK) {
* // True error. Handle it properly.
* }
* // Add the SEI to the stream according to the standard.
* // The user is responsible for freeing |sei|.
* // Check for more SEIs.
* status = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
* status = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
* }
* status = signed_video_add_nalu_for_signing_with_timestamp(sv, nalu, nalu_size, NULL);
* if (status != SV_OK) {
* // Handle error
* }
*
* @param self Pointer to the signed_video_t object in use.
* @param sei Pointer to the memory to which a complete SEI/OBU Metadata will be copied.
* If a NULL pointer is used, only the |sei_size| is updated.
* @param sei Pointer to the memory pointer to which a complete SEI/OBU Metadata is located.
* @param sei_size Pointer to where the size of the SEI/OBU Metadata is written.
* @param payload_offset Pointer to where the offset to the start of the SEI/OBU Metadata payload is
* written. This is useful if the SEI/OBU Metadata is added by the encoder, which would take the
Expand All @@ -297,9 +289,9 @@ signed_video_get_nalu_to_prepend(signed_video_t *self,
*/
SignedVideoReturnCode
signed_video_get_sei(signed_video_t *self,
uint8_t *sei,
uint8_t **sei,
size_t *sei_size,
int *payload_offset,
unsigned *payload_offset,
const uint8_t *peek_nalu,
size_t peek_nalu_size,
unsigned *num_pending_seis);
Expand Down
25 changes: 12 additions & 13 deletions lib/src/signed_video_h26x_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,15 +670,16 @@ get_latest_sei(signed_video_t *self, uint8_t *sei, size_t *sei_size)

SignedVideoReturnCode
signed_video_get_sei(signed_video_t *self,
uint8_t *sei,
uint8_t **sei,
size_t *sei_size,
int *payload_offset,
unsigned *payload_offset,
const uint8_t *peek_nalu,
size_t peek_nalu_size,
unsigned *num_pending_seis)
{

if (!self || !sei_size) return SV_INVALID_PARAMETER;
if (!self || !sei || !sei_size) return SV_INVALID_PARAMETER;
*sei = NULL;
*sei_size = 0;
if (payload_offset) {
*payload_offset = 0;
Expand Down Expand Up @@ -710,22 +711,20 @@ signed_video_get_sei(signed_video_t *self,
}

*sei_size = self->sei_data_buffer[0].completed_sei_size;
if (!sei) return SV_OK;
// Copy the SEI data to the provided pointer.
memcpy(sei, self->sei_data_buffer[0].sei, *sei_size);

// Reset the fetched SEI information from the sei buffer.
free(self->sei_data_buffer[0].sei);
--(self->num_of_completed_seis);
shift_sei_buffer_at_index(self, 0);
// Transfer the memory.
*sei = self->sei_data_buffer[0].sei;

// Get the offset to the start of the SEI payload if requested.
if (payload_offset) {
h26x_nalu_t nalu_info = parse_nalu_info(sei, *sei_size, self->codec, false, false);
h26x_nalu_t nalu_info = parse_nalu_info(*sei, *sei_size, self->codec, false, false);
free(nalu_info.nalu_data_wo_epb);
*payload_offset = nalu_info.payload - sei;
*payload_offset = (unsigned)(nalu_info.payload - *sei);
}

// Reset the fetched SEI information from the sei buffer.
--(self->num_of_completed_seis);
shift_sei_buffer_at_index(self, 0);

// Update |num_pending_seis| in case SEIs were fetched.
if (num_pending_seis) {
*num_pending_seis = self->sei_data_buffer_idx;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/signed_video_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ typedef struct _h26x_nalu_t h26x_nalu_t;
#define DEFAULT_HASH_SIZE (256 / 8)

#define SV_VERSION_BYTES 3
#define SIGNED_VIDEO_VERSION "v2.0.1"
#define SIGNED_VIDEO_VERSION "v2.0.2"
#define SV_VERSION_MAX_STRLEN 13 // Longest possible string

#define DEFAULT_AUTHENTICITY_LEVEL SV_AUTHENTICITY_LEVEL_FRAME
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.0.1',
version : '2.0.2',
meson_version : '>= 0.47.0',
default_options : [ 'warning_level=2',
'werror=true',
Expand Down
42 changes: 19 additions & 23 deletions tests/check/check_signed_video_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,7 @@ START_TEST(vendor_axis_communications_operation)
test_stream_item_t *p_nalu = test_stream_item_create_from_type('P', 1, codec);
test_stream_item_t *i_nalu_2 = test_stream_item_create_from_type('I', 2, codec);
test_stream_item_t *sei_item = NULL;
uint8_t *sei = NULL;
size_t sei_size = 0;

// Check generate private key.
Expand All @@ -1591,17 +1592,17 @@ START_TEST(vendor_axis_communications_operation)
ck_assert_int_eq(sv_rc, SV_OK);
sv_rc = signed_video_add_nalu_for_signing(sv, i_nalu_2->data, i_nalu_2->data_size);
ck_assert_int_eq(sv_rc, SV_OK);
sv_rc = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
ck_assert(sei_size > 0);
ck_assert_int_eq(sv_rc, SV_OK);
uint8_t *sei = malloc(sei_size);
sv_rc = signed_video_get_sei(sv, sei, &sei_size, NULL, NULL, 0, NULL);
sv_rc = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
ck_assert_int_eq(sv_rc, SV_OK);
ck_assert(sei_size > 0);
ck_assert(sei);
sei_item = test_stream_item_create(sei, sei_size, codec);
ck_assert(tag_is_present(sei_item, codec, VENDOR_AXIS_COMMUNICATIONS_TAG));
sv_rc = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
uint8_t *tmp_sei = NULL;
sv_rc = signed_video_get_sei(sv, &tmp_sei, &sei_size, NULL, NULL, 0, NULL);
ck_assert_int_eq(sv_rc, SV_OK);
ck_assert(sei_size == 0);
ck_assert_int_eq(sei_size, 0);
ck_assert(!tmp_sei);

signed_video_free(sv);

Expand Down Expand Up @@ -1682,18 +1683,14 @@ generate_and_set_private_key_on_camera_side(struct sv_setting setting,
sv_rc = signed_video_add_nalu_for_signing(sv, i_nalu_2->data, i_nalu_2->data_size);
ck_assert_int_eq(sv_rc, SV_OK);

uint8_t *sei = NULL;
size_t sei_size = 0;
sv_rc = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
ck_assert(sei_size > 0);
ck_assert_int_eq(sv_rc, SV_OK);
uint8_t *sei = malloc(sei_size);
sv_rc = signed_video_get_sei(sv, sei, &sei_size, NULL, NULL, 0, NULL);
sv_rc = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
ck_assert_int_eq(sv_rc, SV_OK);
ck_assert(sei_size > 0);
ck_assert(sei);
*sei_item = test_stream_item_create(sei, sei_size, setting.codec);
sv_rc = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);

ck_assert_int_eq(sv_rc, SV_OK);
ck_assert(sei_size == 0);
ck_assert(tag_is_present(*sei_item, setting.codec, PUBLIC_KEY_TAG) == add_public_key_to_sei);

test_stream_item_free(i_nalu);
Expand Down Expand Up @@ -1925,6 +1922,7 @@ START_TEST(no_emulation_prevention_bytes)
test_stream_item_t *i_nalu_2 = test_stream_item_create_from_type('I', 1, codec);

test_stream_item_t *sei_item = NULL;
uint8_t *sei = NULL;
size_t sei_size;

// Signing side
Expand Down Expand Up @@ -1952,12 +1950,9 @@ START_TEST(no_emulation_prevention_bytes)
sv, i_nalu_2->data, i_nalu_2->data_size, &g_testTimestamp);
ck_assert_int_eq(sv_rc, SV_OK);

sv_rc = signed_video_get_sei(sv, NULL, &sei_size, NULL, NULL, 0, NULL);
ck_assert_int_eq(sv_rc, SV_OK);
uint8_t *sei = malloc(sei_size);
sv_rc = signed_video_get_sei(sv, sei, &sei_size, NULL, NULL, 0, NULL);

sv_rc = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
ck_assert(sei_size != 0);
ck_assert(sei);
ck_assert_int_eq(sv_rc, SV_OK);

// Allocate memory for a new buffer to write to, and add emulation prevention bytes.
Expand All @@ -1970,14 +1965,15 @@ START_TEST(no_emulation_prevention_bytes)
size_t src_size = sei_size - 4;
write_byte_many(&sei_p, src, src_size, &last_two_bytes, true);
size_t sei_with_epb_size = sei_p - sei_with_epb;
signed_video_nalu_data_free(sei);
free(sei);

// Create a SEI.
sei_item = test_stream_item_create(sei_with_epb, sei_with_epb_size, codec);

sv_rc = signed_video_get_sei(sv, sei, &sei_size, NULL, NULL, 0, NULL);
sv_rc = signed_video_get_sei(sv, &sei, &sei_size, NULL, NULL, 0, NULL);
ck_assert_int_eq(sv_rc, SV_OK);
ck_assert(sei_size == 0);
ck_assert_int_eq(sei_size, 0);
ck_assert(!sei);

// Close signing side.
signed_video_free(sv);
Expand Down
Loading

0 comments on commit 68178fa

Please sign in to comment.