static void gst_cenc_decrypt_parse_pssh_box (GstCencDecrypt * self, GstBuffer * pssh) { GstMapInfo info; GstByteReader br; guint8 version; guint32 data_size; gst_buffer_map (pssh, &info, GST_MAP_READ); gst_byte_reader_init (&br, info.data, info.size); gst_byte_reader_skip_unchecked (&br, 8); version = gst_byte_reader_get_uint8_unchecked (&br); GST_DEBUG_OBJECT (self, "pssh version: %u", version); gst_byte_reader_skip_unchecked (&br, 19); if (version > 0) { /* Parse KeyIDs */ guint32 key_id_count = 0; const guint8 *key_id_data = NULL; const guint key_id_size = 16; key_id_count = gst_byte_reader_get_uint32_be_unchecked (&br); GST_DEBUG_OBJECT (self, "there are %u key IDs", key_id_count); key_id_data = gst_byte_reader_get_data_unchecked (&br, key_id_count * 16); while (key_id_count > 0) { gchar *key_id_string = gst_cenc_create_uuid_string (key_id_data); GST_DEBUG_OBJECT (self, "key_id: %s", key_id_string); g_free (key_id_string); key_id_data += key_id_size; --key_id_count; } } /* Parse Data */ data_size = gst_byte_reader_get_uint32_be_unchecked (&br); GST_DEBUG_OBJECT (self, "pssh data size: %u", data_size); if (data_size > 0U) { gpointer data = g_memdup (gst_byte_reader_get_data_unchecked (&br, data_size), data_size); GstBuffer *buf = gst_buffer_new_wrapped (data, data_size); GST_DEBUG_OBJECT (self, "cenc protection system data size: %" G_GSIZE_FORMAT, gst_buffer_get_size (buf)); gst_buffer_unref (buf); } gst_buffer_unmap (pssh, &info); }
/* gst_isoff_parse_box: * @reader: * @type: type that was found at the current position * @extended_type: (allow-none): extended type if type=='uuid' * @header_size: (allow-none): size of the box header (type, extended type and size) * @size: size of the complete box including type, extended type and size * * Advances the byte reader to the start of the box content. To skip * over the complete box, skip size - header_size bytes. * * Returns: TRUE if a box header could be parsed, FALSE if more data is needed */ gboolean gst_isoff_parse_box_header (GstByteReader * reader, guint32 * type, guint8 extended_type[16], guint * header_size, guint64 * size) { guint header_start_offset; guint32 size_field; header_start_offset = gst_byte_reader_get_pos (reader); if (gst_byte_reader_get_remaining (reader) < 8) goto not_enough_data; size_field = gst_byte_reader_get_uint32_be_unchecked (reader); *type = gst_byte_reader_get_uint32_le_unchecked (reader); if (size_field == 1) { if (gst_byte_reader_get_remaining (reader) < 8) goto not_enough_data; *size = gst_byte_reader_get_uint64_be_unchecked (reader); } else { *size = size_field; } if (*type == GST_ISOFF_FOURCC_UUID) { if (gst_byte_reader_get_remaining (reader) < 16) goto not_enough_data; if (extended_type) memcpy (extended_type, gst_byte_reader_get_data_unchecked (reader, 16), 16); } if (header_size) *header_size = gst_byte_reader_get_pos (reader) - header_start_offset; return TRUE; not_enough_data: gst_byte_reader_set_pos (reader, header_start_offset); return FALSE; }
static GstFlowReturn gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer) { GstH264Parse *h264parse = GST_H264_PARSE (GST_PAD_PARENT (pad)); if (h264parse->packetized && buffer) { GstByteReader br; GstBuffer *sub; GstFlowReturn ret = GST_FLOW_OK; guint32 len; const guint nl = h264parse->nal_length_size; GST_LOG_OBJECT (h264parse, "processing packet buffer of size %d", GST_BUFFER_SIZE (buffer)); gst_byte_reader_init_from_buffer (&br, buffer); while (ret == GST_FLOW_OK && gst_byte_reader_get_remaining (&br)) { GST_DEBUG_OBJECT (h264parse, "AVC nal offset %d", gst_byte_reader_get_pos (&br)); if (gst_byte_reader_get_remaining (&br) < nl) goto parse_failed; switch (nl) { case 4: len = gst_byte_reader_get_uint32_be_unchecked (&br); break; case 3: len = gst_byte_reader_get_uint24_be_unchecked (&br); break; case 2: len = gst_byte_reader_get_uint16_be_unchecked (&br); break; case 1: len = gst_byte_reader_get_uint8_unchecked (&br); break; default: goto not_negotiated; break; } GST_DEBUG_OBJECT (h264parse, "AVC nal size %d", len); if (gst_byte_reader_get_remaining (&br) < len) goto parse_failed; if (h264parse->split_packetized) { /* convert to NAL aligned byte stream input */ sub = gst_h264_parse_wrap_nal (h264parse, GST_H264_PARSE_FORMAT_BYTE, (guint8 *) gst_byte_reader_get_data_unchecked (&br, len), len); /* at least this should make sense */ GST_BUFFER_TIMESTAMP (sub) = GST_BUFFER_TIMESTAMP (buffer); GST_LOG_OBJECT (h264parse, "pushing NAL of size %d", len); ret = h264parse->parse_chain (pad, sub); } else { /* pass-through: no looking for frames (and nal processing), * so need to parse to collect data here */ /* NOTE: so if it is really configured to do so, * pre_push can/will still insert codec-data at intervals, * which is not really pure pass-through, but anyway ... */ gst_h264_parse_process_nal (h264parse, GST_BUFFER_DATA (buffer), gst_byte_reader_get_pos (&br) - nl, gst_byte_reader_get_pos (&br), len); gst_byte_reader_skip_unchecked (&br, len); } } if (h264parse->split_packetized) return ret; } exit: /* nal processing in pass-through might have collected stuff; * ensure nothing happens with this later on */ gst_adapter_clear (h264parse->frame_out); return h264parse->parse_chain (pad, buffer); /* ERRORS */ not_negotiated: { GST_DEBUG_OBJECT (h264parse, "insufficient data to split input"); return GST_FLOW_NOT_NEGOTIATED; } parse_failed: { if (h264parse->split_packetized) { GST_ELEMENT_ERROR (h264parse, STREAM, FAILED, (NULL), ("invalid AVC input data")); return GST_FLOW_ERROR; } else { /* do not meddle to much in this case */ GST_DEBUG_OBJECT (h264parse, "parsing packet failed"); goto exit; } } }