amlqtdemux: CB1 Widevine H264 CBCS Playback Exception [1/1]
PD#SWPL-198185
Problem:
Widevine H264 CBCS Playback Exception
Solution:
Reslove amlqtdemux send uncrypt video data to drm as encrypt
data
Verify:
SC2
Change-Id: I634a6dd18b3fbb0427c88acaa3774aab87778c78
Signed-off-by: shipeng sun <shipeng.sun@amlogic.com>
diff --git a/aml-qtdemux/aml-qtdemux.c b/aml-qtdemux/aml-qtdemux.c
index 9ba6fb9..e05caa1 100644
--- a/aml-qtdemux/aml-qtdemux.c
+++ b/aml-qtdemux/aml-qtdemux.c
@@ -2747,7 +2747,8 @@
"encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
"kid", GST_TYPE_BUFFER, kid_buf, NULL);
GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
- "is_encrypted=%u, iv_size=%u constant_iv_size=%u", is_encrypted, iv_size, constant_iv_size);
+ "is_encrypted=%u, iv_size=%u constant_iv_size=%u crypt_block %u:%u",
+ is_encrypted, iv_size, constant_iv_size, crypt_byte_block, skip_byte_block);
gst_buffer_unref (kid_buf);
if (protection_scheme_type == AML_FOURCC_cbcs || protection_scheme_type == AML_FOURCC_cens) {
if (crypt_byte_block != 0 || skip_byte_block != 0) {
@@ -2925,6 +2926,7 @@
qtdemux->cenc_aux_sample_count = i;
return;
}
+
buf = gst_buffer_new_wrapped (data, iv_size);
gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf);
@@ -4054,6 +4056,147 @@
return TRUE;
}
+static void
+aml_qtdemux_parse_senc (GstAmlQTDemux * qtdemux, AmlQtDemuxStream * stream, GstByteReader * br)
+{
+ guint8 version = 0;
+ guint32 flags = 0;
+ gboolean use_subsample_encryption = FALSE;
+ guint16 subsample_count = 0;
+ guint32 byte_of_clear_data = 0;
+ guint32 byte_of_protected_data = 0;
+ guint32 sample_count = 0;
+ gint i, j;
+ guint iv_size = 8;
+ AmlQtDemuxCencSampleSetInfo *ss_info = NULL;
+
+ if (!stream->protection_scheme_info)
+ stream->protection_scheme_info = g_new0 (AmlQtDemuxCencSampleSetInfo, 1);
+
+ ss_info = (AmlQtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
+ if (!ss_info->default_properties) {
+ ss_info->default_properties =
+ gst_structure_new ("application/x-cenc",
+ "encrypted", G_TYPE_BOOLEAN, TRUE,
+ NULL);
+ }
+
+ if (ss_info->crypto_info) {
+ GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
+ g_ptr_array_free (ss_info->crypto_info, TRUE);
+ ss_info->crypto_info = NULL;
+ }
+
+ if (!gst_byte_reader_get_uint8 (br, &version)) {
+ GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
+ return;
+ }
+
+ GST_DEBUG_OBJECT (qtdemux, "version %d", version);
+
+ if (version > 0) {
+ return;
+ }
+
+ if (!gst_byte_reader_get_uint24_be (br, &flags)) {
+ GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
+ return;
+ }
+
+ if (flags & 0x000002) {
+ use_subsample_encryption = TRUE;
+ }
+
+ if (!gst_structure_get_uint (ss_info->default_properties, "iv_size", &iv_size)) {
+ GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
+ return;
+ }
+ GST_DEBUG_OBJECT (qtdemux, "iv_size %d", iv_size);
+
+ if (!gst_byte_reader_get_uint32_be (br, &sample_count)) {
+ GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
+ return;
+ }
+
+ ss_info->crypto_info =
+ g_ptr_array_new_full (sample_count,
+ (GDestroyNotify) aml_qtdemux_gst_structure_free);
+
+ for (i = 0; i < sample_count; i++) {
+ GstStructure *properties;
+ guint8 *data;
+ GstBuffer *buf;
+ GstBuffer *subsamples = NULL;
+
+ properties = aml_qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
+ if (properties == NULL) {
+ GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
+ qtdemux->cenc_aux_sample_count = i;
+ return;
+ }
+
+ if (iv_size > 0) {
+ if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
+ GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
+ gst_structure_free (properties);
+ qtdemux->cenc_aux_sample_count = i;
+ return;
+ }
+ buf = gst_buffer_new_wrapped (data, iv_size);
+ gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
+ gst_buffer_unref (buf);
+ } else {
+ const GValue *constant_iv_size_value =
+ gst_structure_get_value (properties, "constant_iv_size");
+ const GValue *constant_iv_value =
+ gst_structure_get_value (properties, "iv");
+ if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
+ GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
+ gst_structure_free (properties);
+ return;
+ }
+ gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
+ }
+
+ if (use_subsample_encryption) {
+ const GValue *kid_buf_value;
+ if (!gst_byte_reader_get_uint16_be (br, &subsample_count)
+ || subsample_count == 0) {
+ GST_ERROR_OBJECT (qtdemux,
+ "failed to get subsample count for sample %u", i);
+ gst_structure_free (properties);
+ qtdemux->cenc_aux_sample_count = i;
+ return;
+ }
+ GST_DEBUG_OBJECT (qtdemux, "subsample_count %d", subsample_count);
+
+ if (!gst_byte_reader_dup_data (br, subsample_count * 6, &data)) {
+ GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
+ i);
+ gst_structure_free (properties);
+ qtdemux->cenc_aux_sample_count = i;
+ return;
+ }
+ buf = gst_buffer_new_wrapped (data, subsample_count * 6);// guint16 clr + guint32 enc
+ kid_buf_value = gst_structure_get_value (ss_info->default_properties, "kid");
+
+ gst_structure_set (properties,
+ "subsample_count", G_TYPE_UINT, subsample_count,
+ "subsamples", GST_TYPE_BUFFER, buf, NULL);
+ gst_structure_set_value (properties, "kid", kid_buf_value);
+ gst_buffer_unref (buf);
+ } else {
+ gst_structure_set (properties,
+ "subsample_count", G_TYPE_UINT, 0,
+ "subsamples", GST_TYPE_BUFFER, NULL, NULL);
+ }
+
+ g_ptr_array_add (ss_info->crypto_info, properties);
+ }
+
+ qtdemux->cenc_aux_sample_count = sample_count;
+}
+
static gboolean
aml_qtdemux_parse_moof (GstAmlQTDemux * qtdemux, const guint8 * buffer, guint length,
guint64 moof_offset, AmlQtDemuxStream * stream)
@@ -4067,7 +4210,8 @@
gint64 base_offset, running_offset;
guint32 frag_num;
GstClockTime min_dts = GST_CLOCK_TIME_NONE;
-
+ GNode *senc_node;
+ GstByteReader senc_data;
/* NOTE @stream ignored */
moof_node = g_node_new ((guint8 *) buffer);
@@ -4159,7 +4303,16 @@
}
}
} else {
- GST_WARNING_OBJECT (qtdemux, "no saiz_node, may cbc1 audio");
+ GST_WARNING_OBJECT (qtdemux, "no saiz_node, may cbc1 audio, try parse senc");
+ senc_node =
+ aml_qtdemux_tree_get_child_by_type_full (traf_node, AML_FOURCC_senc,
+ &senc_data);
+ if (senc_node) {
+ GST_DEBUG_OBJECT (qtdemux, "parsing senc box");
+ aml_qtdemux_parse_senc (qtdemux, stream, &senc_data);
+ } else {
+ GST_WARNING_OBJECT (qtdemux, "no senc_node");
+ }
}
tfdt_node =
@@ -6055,7 +6208,7 @@
|| stream->protection_scheme_type == AML_FOURCC_cbc1
|| stream->protection_scheme_type == AML_FOURCC_cbcs
|| stream->protection_scheme_type == AML_FOURCC_cens)) {
- GstStructure *crypto_info;
+ GstStructure *crypto_info = NULL;
AmlQtDemuxCencSampleSetInfo *info =
(AmlQtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
gint index;
@@ -6069,49 +6222,8 @@
}
if (info->crypto_info == NULL) {
- /* cbc1 audio may has no saiz node, need update crypto info from default properties */
- if (stream->protection_scheme_type == AML_FOURCC_cbcs || stream->protection_scheme_type == AML_FOURCC_cens) {
- guint crypt_byte_block = 0;
- guint skip_byte_block = 0;
- guint iv_size = 0;
- guint constant_iv_size = 0;
-
- crypto_info = aml_qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
- gst_structure_get (crypto_info,
- "crypt_byte_block", G_TYPE_UINT, &crypt_byte_block,
- "skip_byte_block", G_TYPE_UINT, &skip_byte_block,
- "iv_size", G_TYPE_UINT, &iv_size,
- NULL);
- if (iv_size == 0) {
- if (!gst_structure_get_uint (crypto_info, "constant_iv_size", &constant_iv_size)) {
- GST_ERROR_OBJECT (qtdemux, "failed to get iv_size");
- } else {
- gst_structure_set (crypto_info, "iv_size", G_TYPE_UINT, constant_iv_size, NULL);
- }
- }
-
- meta = gst_buffer_get_protection_meta(buf);
- if (meta) {
- GST_DEBUG_OBJECT (qtdemux, "protection metadata name %s", gst_structure_get_name(meta->info));
- gst_structure_set (meta->info,
- "crypt_byte_block", G_TYPE_UINT, crypt_byte_block,
- "skip_byte_block", G_TYPE_UINT, skip_byte_block,
- NULL);
- } else {
- GST_INFO_OBJECT (qtdemux, "no cbcs protection metadata");
- }
-
- if (!meta && (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))) {
- GST_ERROR_OBJECT (qtdemux,
- "failed to attach cbcs metadata to buffer");
- aml_qtdemux_gst_structure_free (crypto_info);
- } else {
- GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
- }
- } else {
- GST_DEBUG_OBJECT (qtdemux,
- "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
- }
+ GST_DEBUG_OBJECT (qtdemux,
+ "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
} else {
/* The end of the crypto_info array matches our n_samples position,
* so count backward from there */
@@ -6135,6 +6247,13 @@
"crypt_byte_block", G_TYPE_UINT, &crypt_byte_block,
"skip_byte_block", G_TYPE_UINT, &skip_byte_block,
NULL);
+ if (crypt_byte_block == 0 && skip_byte_block == 0
+ && (0 == strncmp(GST_PAD_NAME (stream->pad), "audio", 5))) {
+ crypt_byte_block = 1;
+ gst_structure_set (crypto_info,
+ "crypt_byte_block", G_TYPE_UINT, crypt_byte_block,
+ NULL);
+ }
meta = gst_buffer_get_protection_meta(buf);
if (meta) {
GST_DEBUG_OBJECT (qtdemux, "protection metadata name %s", gst_structure_get_name(meta->info));