From c82ced18683e7c1d58aec2a855e391986f110a50 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 22 Feb 2017 03:01:31 +1100 Subject: [PATCH] qtdemux: Don't lose crypto info on a new moof We parse the next moof in advance of having pushed all samples from the previous one in some cases, and we'll still need the crypto info from the previous fragment so keep around any unused crypto info entries when adding new ones --- gst/isomp4/qtdemux.c | 54 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 392e0368ed..2f597db63a 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -3601,6 +3601,8 @@ qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream, QtDemuxCencSampleSetInfo *ss_info = NULL; guint8 size; gint i; + GPtrArray *old_crypto_info = NULL; + guint old_entries = 0; g_return_val_if_fail (qtdemux != NULL, FALSE); g_return_val_if_fail (stream != NULL, FALSE); @@ -3611,14 +3613,38 @@ qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream, ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info; if (ss_info->crypto_info) { - GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info"); - g_ptr_array_free (ss_info->crypto_info, TRUE); + old_crypto_info = ss_info->crypto_info; + /* Count number of non-null entries remaining at the tail end */ + for (i = old_crypto_info->len - 1; i >= 0; i--) { + if (g_ptr_array_index (old_crypto_info, i) == NULL) + break; + old_entries++; + } } ss_info->crypto_info = - g_ptr_array_new_full (sample_count, + g_ptr_array_new_full (sample_count + old_entries, (GDestroyNotify) qtdemux_gst_structure_free); + /* We preserve old entries because we parse the next moof in advance + * of consuming all samples from the previous moof, and otherwise + * we'd discard the corresponding crypto info for the samples + * from the previous fragment. */ + if (old_entries) { + GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries", + old_entries); + for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) { + g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info, + i)); + g_ptr_array_index (old_crypto_info, i) = NULL; + } + } + + if (old_crypto_info) { + /* Everything now belongs to the new array */ + g_ptr_array_free (old_crypto_info, TRUE); + } + for (i = 0; i < sample_count; ++i) { GstStructure *properties; guint16 n_subsamples = 0; @@ -5444,14 +5470,20 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux, goto exit; } - index = stream->sample_index - (stream->n_samples - info->crypto_info->len); + /* The end of the crypto_info array matches our n_samples position, + * so count backward from there */ + index = stream->sample_index - stream->n_samples + info->crypto_info->len; if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) { /* steal structure from array */ crypto_info = g_ptr_array_index (info->crypto_info, index); g_ptr_array_index (info->crypto_info, index) = NULL; - GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index); + GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index, + info->crypto_info->len); if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer"); + } else { + GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d", + index, stream->sample_index); } } @@ -5517,6 +5549,18 @@ gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux) stream->stbl_index = -1; /* no samples have yet been parsed */ stream->sample_index = -1; + if (stream->protection_scheme_info) { + /* Clear out any old cenc crypto info entries as we'll move to a new moof */ + if (stream->protection_scheme_type == FOURCC_cenc) { + QtDemuxCencSampleSetInfo *info = + (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info; + if (info->crypto_info) { + g_ptr_array_free (info->crypto_info, TRUE); + info->crypto_info = NULL; + } + } + } + if (stream->ra_entries == NULL) continue;