[libdvbpsi-devel] [PATCH 1/3] Support for the content labelling descriptor
Daniel Kamil Kozar
dkk089 at gmail.com
Wed Jun 10 00:53:24 CEST 2015
This patch provides decoding and generation of the content labelling descriptor.
---
src/Makefile.am | 2 +
src/descriptors/dr_24.c | 356 ++++++++++++++++++++++++++++++++++++++++++++++++
src/descriptors/dr_24.h | 130 ++++++++++++++++++
3 files changed, 488 insertions(+)
create mode 100644 src/descriptors/dr_24.c
create mode 100644 src/descriptors/dr_24.h
diff --git a/src/Makefile.am b/src/Makefile.am
index e47715f..8be8258 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@ pkginclude_HEADERS = dvbpsi.h psi.h descriptor.h demux.h \
descriptors/dr_14.h \
descriptors/dr_1b.h \
descriptors/dr_1c.h \
+ descriptors/dr_24.h \
descriptors/dr_40.h \
descriptors/dr_41.h \
descriptors/dr_42.h \
@@ -101,6 +102,7 @@ descriptors_src = descriptors/dr_02.c \
descriptors/dr_14.c \
descriptors/dr_1b.c \
descriptors/dr_1c.c \
+ descriptors/dr_24.c \
descriptors/dr_40.c \
descriptors/dr_41.c \
descriptors/dr_42.c \
diff --git a/src/descriptors/dr_24.c b/src/descriptors/dr_24.c
new file mode 100644
index 0000000..0405c1f
--- /dev/null
+++ b/src/descriptors/dr_24.c
@@ -0,0 +1,356 @@
+/*
+Copyright (C) 2015 Daniel Kamil Kozar
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#include "../dvbpsi.h"
+#include "../dvbpsi_private.h"
+#include "../descriptor.h"
+
+#include "dr_24.h"
+
+/* the minimum size of a valid content labelling descriptor. it consists of
+ * metadata_application_format, content_{reference_id_record_flag, time_base_
+ * indicator}, and a reserved field. they all sum up to 24 bits. */
+#define DR_24_MIN_SIZE 3
+
+static int decode_content_reference_id(dvbpsi_content_labelling_dr_t *p_decoded,
+ const uint8_t **pp_data, uint8_t *pi_left)
+{
+ uint8_t i_left = *pi_left;
+ const uint8_t *p_data = *pp_data;
+
+ if(i_left < 1)
+ return 1;
+
+ p_decoded->i_content_reference_id_record_length = *p_data;
+ i_left--; p_data++;
+
+ /* H.222.0 says that content_reference_id_record_length "shall not be coded
+ * with the value '0'". reject such data as invalid. */
+ if(i_left < p_decoded->i_content_reference_id_record_length ||
+ p_decoded->i_content_reference_id_record_length == 0)
+ return 1;
+
+ p_decoded->p_content_reference_id = malloc(
+ p_decoded->i_content_reference_id_record_length);
+ if(!p_decoded->p_content_reference_id)
+ return 1;
+
+ memcpy(p_decoded->p_content_reference_id, p_data,
+ p_decoded->i_content_reference_id_record_length);
+ i_left -= p_decoded->i_content_reference_id_record_length;
+ p_data += p_decoded->i_content_reference_id_record_length;
+
+ *pp_data = p_data;
+ *pi_left = i_left;
+
+ return 0;
+}
+
+static int decode_content_time_base_indicator(dvbpsi_content_labelling_dr_t
+ *p_decoded, const uint8_t **pp_data, uint8_t *pi_left)
+{
+ const uint8_t *p_data = *pp_data;
+ uint8_t i_left = *pi_left;
+
+ if(p_decoded->i_content_time_base_indicator == 1 ||
+ p_decoded->i_content_time_base_indicator == 2)
+ {
+ if(i_left < 10)
+ return 1;
+
+ p_decoded->i_content_time_base_value =
+ (((uint64_t)(p_data[0] & 0x01)) << 32) |
+ ((uint64_t)p_data[1] << 24) |
+ ((uint64_t)p_data[2] << 16) |
+ ((uint64_t)p_data[3] << 8) |
+ (uint64_t)p_data[4];
+
+ p_decoded->i_metadata_time_base_value =
+ (((uint64_t)(p_data[5] & 0x01)) << 32) |
+ ((uint64_t)p_data[6] << 24) |
+ ((uint64_t)p_data[7] << 16) |
+ ((uint64_t)p_data[8] << 8) |
+ (uint64_t)p_data[9];
+
+ p_data += 10; i_left -= 10;
+ }
+
+ if(p_decoded->i_content_time_base_indicator == 2)
+ {
+ if(i_left < 1)
+ return 1;
+
+ p_decoded->i_contentId = *p_data & 0x7f;
+ p_data++; i_left--;
+ }
+
+ if(p_decoded->i_content_time_base_indicator >= 3 &&
+ p_decoded->i_content_time_base_indicator <= 7)
+ {
+ if(i_left < 1)
+ return 1;
+
+ p_decoded->i_time_base_association_data_length = *p_data;
+ p_data++; i_left--;
+
+ if(i_left < p_decoded->i_time_base_association_data_length)
+ return 1;
+
+ if(p_decoded->i_time_base_association_data_length)
+ {
+ p_decoded->p_time_base_association_data = malloc(
+ p_decoded->i_time_base_association_data_length);
+ if(!p_decoded->p_time_base_association_data)
+ return 1;
+
+ memcpy(p_decoded->p_time_base_association_data, p_data,
+ p_decoded->i_time_base_association_data_length);
+ }
+
+ p_data += p_decoded->i_time_base_association_data_length;
+ i_left -= p_decoded->i_time_base_association_data_length;
+ }
+
+ *pp_data = p_data;
+ *pi_left = i_left;
+
+ return 0;
+}
+
+dvbpsi_content_labelling_dr_t* dvbpsi_DecodeContentLabellingDr(
+ dvbpsi_descriptor_t * p_descriptor)
+{
+ dvbpsi_content_labelling_dr_t *p_decoded;
+ const uint8_t *p_data = p_descriptor->p_data;
+ uint8_t i_left = p_descriptor->i_length;
+
+ /* check the tag. */
+ if (!dvbpsi_CanDecodeAsDescriptor(p_descriptor, 0x24))
+ return NULL;
+
+ /* don't decode twice. */
+ if (dvbpsi_IsDescriptorDecoded(p_descriptor))
+ return p_descriptor->p_decoded;
+
+ /* simplest descriptors of this type contain 3 bytes of payload. */
+ if (p_descriptor->i_length < DR_24_MIN_SIZE)
+ return NULL;
+
+ p_decoded = malloc(sizeof(*p_decoded));
+ if (!p_decoded)
+ return NULL;
+
+ /* set the pointers to NULL so we can safely free() them in err: */
+ p_decoded->p_content_reference_id = NULL;
+ p_decoded->p_time_base_association_data = NULL;
+ p_decoded->p_private_data = NULL;
+
+ p_decoded->i_metadata_application_format =
+ ((uint16_t)p_data[0] << 8) | (uint16_t)p_data[1];
+ i_left -= 2; p_data += 2;
+
+ if(p_decoded->i_metadata_application_format == 0xFFFF)
+ {
+ if(i_left < 4)
+ goto err;
+
+ p_decoded->i_metadata_application_format_identifier =
+ ((uint32_t)p_data[0] << 24) |
+ ((uint32_t)p_data[1] << 16) |
+ ((uint32_t)p_data[2] << 8) |
+ (uint32_t)p_data[3];
+ i_left -= 4; p_data += 4;
+ }
+
+ if(i_left < 1)
+ goto err;
+
+ p_decoded->b_content_reference_id_record_flag = (*p_data & 0x80);
+ p_decoded->i_content_time_base_indicator = ((*p_data & 0x78) >> 3);
+ i_left--; p_data++;
+
+ if(p_decoded->b_content_reference_id_record_flag &&
+ decode_content_reference_id(p_decoded, &p_data, &i_left) != 0)
+ goto err;
+
+ if(p_decoded->i_content_time_base_indicator &&
+ decode_content_time_base_indicator(p_decoded, &p_data, &i_left) != 0)
+ goto err;
+
+ p_decoded->i_private_data_len = i_left;
+ if(p_decoded->i_private_data_len)
+ {
+ p_decoded->p_private_data = malloc(p_decoded->i_private_data_len);
+ if(!p_decoded->p_private_data)
+ goto err;
+
+ memcpy(p_decoded->p_private_data, p_data, p_decoded->i_private_data_len);
+ }
+
+ p_descriptor->p_decoded = p_decoded;
+ return p_decoded;
+
+err:
+ free(p_decoded->p_private_data);
+ free(p_decoded->p_time_base_association_data);
+ free(p_decoded->p_content_reference_id);
+ free(p_decoded);
+ return NULL;
+}
+
+static unsigned int generate_get_descriptor_size(const
+ dvbpsi_content_labelling_dr_t * p_decoded)
+{
+ unsigned int size = DR_24_MIN_SIZE + p_decoded->i_private_data_len;
+
+ if(p_decoded->i_metadata_application_format == 0xFFFF)
+ size += 4;
+
+ if(p_decoded->b_content_reference_id_record_flag)
+ size += p_decoded->i_content_reference_id_record_length + 1;
+
+ if(p_decoded->i_content_time_base_indicator == 1 ||
+ p_decoded->i_content_time_base_indicator == 2)
+ size += 10;
+
+ if(p_decoded->i_content_time_base_indicator == 2)
+ size += 1;
+
+ if(p_decoded->i_content_time_base_indicator >= 3 &&
+ p_decoded->i_content_time_base_indicator <= 7)
+ size += p_decoded->i_time_base_association_data_length + 1;
+
+ return size;
+}
+
+static bool generate_check_struct_valid(const
+ dvbpsi_content_labelling_dr_t * p_decoded)
+{
+ /* check if the pointers are valid if relevant sizes are nonzero. also,
+ * check if i_content_reference_id_record_length isn't zero if the flag is
+ * set, as this is explicitly forbidden by H.222.0. */
+ if((p_decoded->b_content_reference_id_record_flag &&
+ !p_decoded->i_content_reference_id_record_length) ||
+ (p_decoded->i_content_reference_id_record_length &&
+ !p_decoded->p_content_reference_id))
+ return false;
+
+ if(p_decoded->i_time_base_association_data_length &&
+ !p_decoded->p_time_base_association_data)
+ return false;
+
+ if(p_decoded->i_private_data_len && !p_decoded->p_private_data)
+ return false;
+
+ return true;
+}
+
+dvbpsi_descriptor_t * dvbpsi_GenContentLabellingDr(
+ dvbpsi_content_labelling_dr_t * p_decoded)
+{
+ unsigned int size;
+ dvbpsi_descriptor_t * p_descriptor;
+ uint8_t *p_data;
+
+ if(!generate_check_struct_valid(p_decoded))
+ return NULL;
+
+ size = generate_get_descriptor_size(p_decoded);
+ if(size > 253) /* maximum possible descriptor payload size. */
+ return NULL;
+
+ p_descriptor = dvbpsi_NewDescriptor(0x24, size, NULL);
+ if (!p_descriptor)
+ return NULL;
+
+ p_data = p_descriptor->p_data;
+
+ p_data[0] = (p_decoded->i_metadata_application_format & 0xFF00) >> 8;
+ p_data[1] = (p_decoded->i_metadata_application_format & 0x00FF);
+ p_data += 2;
+
+ if(p_decoded->i_metadata_application_format == 0xFFFF)
+ {
+ p_data[0] = (p_decoded->i_metadata_application_format_identifier & 0xFF000000) >> 24;
+ p_data[1] = (p_decoded->i_metadata_application_format_identifier & 0x00FF0000) >> 16;
+ p_data[2] = (p_decoded->i_metadata_application_format_identifier & 0x0000FF00) >> 8;
+ p_data[3] = (p_decoded->i_metadata_application_format_identifier & 0x000000FF);
+ p_data += 4;
+ }
+
+ *p_data = ((p_decoded->b_content_reference_id_record_flag ? 1 : 0) << 7) |
+ ((p_decoded->i_content_time_base_indicator & 0xf) << 6) |
+ 0x07;
+ p_data++;
+
+ if(p_decoded->b_content_reference_id_record_flag)
+ {
+ *p_data = p_decoded->i_content_reference_id_record_length;
+ memcpy(p_data + 1, p_decoded->p_content_reference_id,
+ p_decoded->i_content_reference_id_record_length);
+ p_data += (p_decoded->i_content_reference_id_record_length + 1);
+ }
+
+ if(p_decoded->i_content_time_base_indicator == 1 ||
+ p_decoded->i_content_time_base_indicator == 2)
+ {
+ p_data[0] = 0xfe | ((p_decoded->i_content_time_base_value & 0x100000000) >> 32);
+ p_data[1] = (p_decoded->i_content_time_base_value & 0xFF000000) >> 24;
+ p_data[2] = (p_decoded->i_content_time_base_value & 0x00FF0000) >> 16;
+ p_data[3] = (p_decoded->i_content_time_base_value & 0x0000FF00) >> 8;
+ p_data[4] = (p_decoded->i_content_time_base_value & 0x000000FF);
+
+ p_data[5] = 0xfe | ((p_decoded->i_metadata_time_base_value & 0x100000000) >> 32);
+ p_data[6] = (p_decoded->i_metadata_time_base_value & 0xFF000000) >> 24;
+ p_data[7] = (p_decoded->i_metadata_time_base_value & 0x00FF0000) >> 16;
+ p_data[8] = (p_decoded->i_metadata_time_base_value & 0x0000FF00) >> 8;
+ p_data[9] = (p_decoded->i_metadata_time_base_value & 0x000000FF);
+
+ p_data += 10;
+ }
+
+ if(p_decoded->i_content_time_base_indicator == 2)
+ {
+ *p_data = 0x80 | (p_decoded->i_contentId & 0x7f);
+ p_data++;
+ }
+
+ if(p_decoded->i_content_time_base_indicator >= 3 &&
+ p_decoded->i_content_time_base_indicator <= 7)
+ {
+ *p_data = p_decoded->i_time_base_association_data_length;
+ memcpy(p_data + 1, p_decoded->p_time_base_association_data,
+ p_decoded->i_time_base_association_data_length);
+ p_data += (p_decoded->i_time_base_association_data_length + 1);
+ }
+
+ memcpy(p_data, p_decoded->p_private_data, p_decoded->i_private_data_len);
+ return p_descriptor;
+}
diff --git a/src/descriptors/dr_24.h b/src/descriptors/dr_24.h
new file mode 100644
index 0000000..5fdf211
--- /dev/null
+++ b/src/descriptors/dr_24.h
@@ -0,0 +1,130 @@
+/*
+Copyright (C) 2015 Daniel Kamil Kozar
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*!
+ * \file <dr_24.h>
+ * \author Daniel Kamil Kozar <dkk089 at gmail.com>
+ * \brief Application interface for the content labelling descriptor decoder and
+ * generator.
+ *
+ * Application interface for the content labelling descriptor decoder and
+ * generator. This descriptor's definition can be found in ISO/IEC 13818-1:2015
+ * section 2.6.56.
+ */
+
+#ifndef _DVBPSI_DR_24_H_
+#define _DVBPSI_DR_24_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * \struct dvbpsi_content_labelling_dr_s
+ * \brief Content labelling descriptor structure.
+ *
+ * This structure is used to store a decoded content labelling descriptor.
+ * (ISO/IEC 13818-1 section 2.6.56).
+ */
+
+/*!
+ * \typedef struct dvbpsi_content_labelling_dr_s dvbpsi_content_labelling_dr_t
+ * \brief dvbpsi_content_labelling_dr_t type definition.
+ */
+typedef struct dvbpsi_content_labelling_dr_s
+{
+ uint16_t i_metadata_application_format; /*!< metadata_application_format */
+
+ /*! metadata_application_format_identifier
+ * \warning Valid only if \c i_metadata_application_format is \c 0xFFFF . */
+ uint32_t i_metadata_application_format_identifier;
+
+ /*! content_reference_id_record_flag */
+ bool b_content_reference_id_record_flag;
+ uint8_t i_content_time_base_indicator; /*!< content_time_base_indicator */
+
+ /*! content_reference_id_record_length
+ * \warning Valid only if \c b_content_reference_id_record_flag is true. */
+ uint8_t i_content_reference_id_record_length;
+
+ /*! content_reference_id_byte
+ * An array of \c i_content_reference_id_record_length bytes. Memory is
+ * allocated by the decoder when decoding, and by the caller when generating.
+ * \warning Valid only if \c b_content_reference_id_record_flag is true. */
+ uint8_t *p_content_reference_id;
+
+ /*! content_time_base_value
+ * \warning Valid only if \c i_content_time_base_indicator is 1 or 2. */
+ uint64_t i_content_time_base_value;
+
+ /*! metadata_time_base_value
+ * \warning Valid only if \c i_content_time_base_indicator is 1 or 2. */
+ uint64_t i_metadata_time_base_value;
+
+ /*! contentId
+ * \warning Valid only if \c i_content_time_base_indicator is 2. */
+ uint8_t i_contentId;
+
+ /*! time_base_association_data_length
+ * \warning Valid only if \c i_content_time_base_indicator is 3, 4, 5, 6,
+ * or 7. */
+ uint8_t i_time_base_association_data_length;
+
+ /*! time_base_association_data
+ * An array of \c i_time_base_association_data_length bytes. Memory is
+ * allocated by the decoder when decoding, and by the caller when generating.
+ * \note This field is marked as reserved, but access to it is nevertheless
+ * provided if applications want to use it.
+ * \warning Valid only if \c i_content_time_base_indicator is 3, 4, 5, 6,
+ * or 7. */
+ uint8_t *p_time_base_association_data;
+
+ /*! private_data_len */
+ uint8_t i_private_data_len;
+
+ /*! private_data
+ * \note An array of \c i_private_data_len bytes at the end of the
+ * descriptor. Memory is allocated by the decoder when decoding, and by the
+ * caller when generating. */
+ uint8_t *p_private_data;
+} dvbpsi_content_labelling_dr_t;
+
+/*!
+ * \brief Content labelling descriptor decoder.
+ * \param p_descriptor pointer to the descriptor structure
+ * \return A pointer to a new content labelling descriptor structure which
+ * contains the decoded data.
+ */
+dvbpsi_content_labelling_dr_t* dvbpsi_DecodeContentLabellingDr(
+ dvbpsi_descriptor_t * p_descriptor);
+
+/*!
+ * \brief Content labelling descriptor generator.
+ * \param p_decoded pointer to a decoded content labelling descriptor structure.
+ * \return a pointer to a new descriptor structure which contains encoded data.
+ */
+dvbpsi_descriptor_t * dvbpsi_GenContentLabellingDr(
+ dvbpsi_content_labelling_dr_t * p_decoded);
+
+#ifdef __cplusplus
+}
+#endif
+
+#else
+#error "Multiple inclusions of dr_24.h"
+#endif
--
2.4.2
More information about the libdvbpsi-devel
mailing list