diff --git a/apps/signer/gst-plugin/gstsigning.c b/apps/signer/gst-plugin/gstsigning.c index a0a2ec8..49c7efb 100644 --- a/apps/signer/gst-plugin/gstsigning.c +++ b/apps/signer/gst-plugin/gstsigning.c @@ -164,55 +164,46 @@ create_buffer_with_current_time(GstSigning *signing) return buf; } -static void -free_nalu_data(gpointer data) -{ - signed_video_nalu_data_free(data); -} - -/* Prepend NALUs according to results from Signed Video lib calls. Returns the number of NALUs - * that were prepended to |current_au|, or -1 on error. */ +/* Prepend seis fetched from Signed Video lib. + * Returns the number of nalus that were prepended to @current_au, + * or -1 on error. */ static gint -prepend_nalus(GstSigning *signing, GstBuffer *current_au) +get_and_add_sei(GstSigning *signing, GstBuffer * current_au, gint idx, const guint8 * peek_nalu, gsize peek_nalu_size) { - SignedVideoReturnCode sv_rc = SV_UNKNOWN_FAILURE; - signed_video_nalu_to_prepend_t nalu_to_prepend = {0}; + SignedVideoReturnCode sv_rc; gint prepend_count = 0; - - sv_rc = signed_video_get_nalu_to_prepend(signing->priv->signed_video, &nalu_to_prepend); - while (sv_rc == SV_OK && nalu_to_prepend.prepend_instruction != SIGNED_VIDEO_PREPEND_NOTHING) { - gpointer data = nalu_to_prepend.nalu_data; - gsize size = nalu_to_prepend.nalu_data_size; + guint8 *sei = NULL; + gsize sei_size = 0; + + /* Brief description of API. For more details see the public header file. + * SignedVideoReturnCode + * signed_video_get_sei(signed_video_t *self, uint8_t **sei, size_t *sei_size, + * unsigned *payload_offset, const uint8_t *peek_nalu, + * size_t peek_nalu_size, unsigned *num_pending_seis); */ + sv_rc = signed_video_get_sei (signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, peek_nalu_size, NULL); + while (sv_rc == SV_OK && sei_size > 0 && sei) { GstMemory *prepend_mem; - // Write size into NALU header. The size value should be the data size, minus the size of the - // size value itself - GST_WRITE_UINT32_BE(data, size - sizeof(guint32)); - - GST_DEBUG_OBJECT(signing, "create a %" G_GSIZE_FORMAT "bytes nalu to prepend", size); - prepend_mem = gst_memory_new_wrapped(0, data, size, 0, size, data, free_nalu_data); - - switch (nalu_to_prepend.prepend_instruction) { - case SIGNED_VIDEO_PREPEND_NALU: - GST_DEBUG_OBJECT(signing, "prepend nalu to current AU"); - gst_buffer_prepend_memory(current_au, prepend_mem); - prepend_count++; - break; - default: - GST_FIXME_OBJECT( - signing, "unsupported prepend instruction %d", nalu_to_prepend.prepend_instruction); - break; - } + /* Write size into nalu header. The size value should be the data size, + * minus the size of the size value itself. */ + GST_WRITE_UINT32_BE(sei, (guint32)(sei_size - sizeof(guint32))); + + GST_DEBUG_OBJECT(signing, "preped sei of size %" G_GSIZE_FORMAT " to current AU", sei_size); + prepend_mem = gst_memory_new_wrapped(0, sei, sei_size, 0, sei_size, sei, g_free); + gst_buffer_insert_memory(current_au, idx, prepend_mem); + prepend_count++; - sv_rc = signed_video_get_nalu_to_prepend(signing->priv->signed_video, &nalu_to_prepend); + sv_rc = signed_video_get_sei(signing->priv->signed_video, &sei, &sei_size, NULL, peek_nalu, peek_nalu_size, NULL); } - if (sv_rc != SV_OK) goto get_nalu_failed; + if (sv_rc != SV_OK) { + goto get_sei_failed; + } return prepend_count; -get_nalu_failed: - GST_ERROR_OBJECT(signing, "signed_video_get_nalu_to_prepend failed"); +get_sei_failed: + GST_ERROR_OBJECT(signing, "signed_video_get_sei failed"); return -1; } @@ -224,7 +215,7 @@ gst_signing_transform_ip(GstBaseTransform *trans, GstBuffer *buf) guint idx = 0; GstMemory *nalu_mem = NULL; GstMapInfo map_info; - gint prepend_count = 0; + gboolean got_sei = false; priv->last_pts = GST_BUFFER_PTS(buf); // last_pts is an GstClockTime object, which is measured in nanoseconds. @@ -242,6 +233,26 @@ gst_signing_transform_ip(GstBaseTransform *trans, GstBuffer *buf) goto map_failed; } + /* SEIs generated by the Signed Video lib should be passed in as any nalu. The reason + * for this is that not all are signed and hence 'floating around' in the stream. + * Therefore, pull and add them before adding the current nalu. */ + gint add_count = get_and_add_sei(signing, buf, idx, &(map_info.data[4]), map_info.size - 4); + if (add_count < 0) { + GST_ELEMENT_ERROR(signing, STREAM, FAILED, ("failed to add nalus"), (NULL)); + goto get_and_add_sei_failed; + } + if (add_count > 0) { + gst_memory_unmap(nalu_mem, &map_info); + /* Get the newly added seis. They need to be added for signing like any other + * Bitstream Unit. */ + nalu_mem = gst_buffer_peek_memory(buf, idx); + if (G_UNLIKELY(!gst_memory_map(nalu_mem, &map_info, GST_MAP_READ))) { + GST_ELEMENT_ERROR(signing, RESOURCE, FAILED, ("Failed to map memory"), (NULL)); + goto map_failed; + } + got_sei = true; + } + // Depending on bitstream format the start code is optional, hence libsigned-video supports // both. Therefore, since the start code in the pipeline temporarily may have been replaced by // the picture data size this format is violated. To pass in valid input data, skip the first @@ -254,19 +265,12 @@ gst_signing_transform_ip(GstBaseTransform *trans, GstBuffer *buf) goto add_nalu_failed; } - prepend_count = prepend_nalus(signing, buf); - if (prepend_count < 0) { - GST_ELEMENT_ERROR(signing, STREAM, FAILED, ("failed to prepend nalus"), (NULL)); - goto prepend_nalus_failed; - } - gst_memory_unmap(nalu_mem, &map_info); - idx += prepend_count; // Move past prepended nalus idx++; // Go to next nalu } - if (prepend_count > 0) { + if (got_sei) { // Push an event to produce a message saying SEIs have been added. GstStructure *structure = gst_structure_new( SIGNING_STRUCTURE_NAME, SIGNING_FIELD_NAME, G_TYPE_STRING, "signed", NULL); @@ -275,11 +279,11 @@ gst_signing_transform_ip(GstBaseTransform *trans, GstBuffer *buf) GST_ELEMENT_ERROR(signing, STREAM, FAILED, ("failed to push message"), (NULL)); } } - GST_DEBUG_OBJECT(signing, "push AU with %d nalus", gst_buffer_n_memory(buf)); + GST_DEBUG_OBJECT(signing, "push AU with %d Bitstream Units", gst_buffer_n_memory(buf)); return GST_FLOW_OK; -prepend_nalus_failed: +get_and_add_sei_failed: add_nalu_failed: gst_memory_unmap(nalu_mem, &map_info); map_failed: @@ -298,8 +302,8 @@ push_access_unit_at_eos(GstSigning *signing) } au = create_buffer_with_current_time(signing); - if (prepend_nalus(signing, au) < 0) { - GST_ERROR_OBJECT(signing, "failed to prepend nalus"); + if (get_and_add_sei(signing, au, 0, NULL, 0) < 0) { + GST_ERROR_OBJECT(signing, "failed to get SEIs"); goto prepend_failed; } @@ -363,13 +367,11 @@ setup_signing(GstSigning *signing, GstCaps *caps) GST_ERROR_OBJECT(signing, "could not create Signed Video object"); goto create_failed; } - if (signed_video_generate_private_key( - SIGN_ALGO_ECDSA, PATH_TO_KEY_FILES, &private_key, &private_key_size) != SV_OK) { + if (signed_video_generate_ecdsa_private_key(PATH_TO_KEY_FILES, &private_key, &private_key_size) != SV_OK) { GST_DEBUG_OBJECT(signing, "failed to generate pem file"); goto generate_private_key_failed; } - if (signed_video_set_private_key( - priv->signed_video, SIGN_ALGO_ECDSA, private_key, private_key_size) != SV_OK) { + if (signed_video_set_private_key_new(priv->signed_video, private_key, private_key_size) != SV_OK) { GST_DEBUG_OBJECT(signing, "failed to set private key content"); goto set_private_key_failed; } diff --git a/apps/validator/main.c b/apps/validator/main.c index 6070b31..a85eb20 100644 --- a/apps/validator/main.c +++ b/apps/validator/main.c @@ -528,10 +528,10 @@ on_source_message(GstBus __attribute__((unused)) *bus, GstMessage *message, Vali } gint num_unsigned_gops = (data->invalid_gops || data->valid_gops_with_missing || data->valid_gops) ? 0 : data->no_sign_gops; if (is_unsigned) { - fprintf(f, "Number of unsigned NAL Units: %u\n", data->auth_report->accumulated_validation.number_of_received_nalus); + fprintf(f, "Number of unsigned Bitstream Units: %u\n", data->auth_report->accumulated_validation.number_of_received_nalus); } else { fprintf(f, "Number of valid GOPs: %d\n", data->valid_gops); - fprintf(f, "Number of valid GOPs with missing NALUs: %d\n", data->valid_gops_with_missing); + fprintf(f, "Number of valid GOPs with missing BUs: %d\n", data->valid_gops_with_missing); fprintf(f, "Number of invalid GOPs: %d\n", data->invalid_gops); fprintf(f, "Number of GOPs without signature: %d\n", num_unsigned_gops); } diff --git a/test-files/signed_test_h264.mp4 b/test-files/signed_test_h264.mp4 index c4ca079..d35b8bf 100644 Binary files a/test-files/signed_test_h264.mp4 and b/test-files/signed_test_h264.mp4 differ