summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesper Larsen <jesper.larsen@ixonos.com>2013-10-28 14:44:13 +0100
committerJesper Larsen <jesper.larsen@ixonos.com>2014-02-06 14:00:28 +0100
commit930cde73a7313d29335d93637e8609b612cf9df4 (patch)
treec9a555e54240001b99b58523b24a35a36c996d7e
parentb1c5143b79be4285584a3905eeb8b7e0d42ddce9 (diff)
mpegts: Add functions to packetize section
Sections needs to be packetized for use in i.e. mpegtsmux. These functions handles the generic common parts of a GstMpegTsSection
-rw-r--r--gst-libs/gst/mpegts/gstmpegts-private.h3
-rw-r--r--gst-libs/gst/mpegts/gstmpegtsdescriptor.c26
-rw-r--r--gst-libs/gst/mpegts/gstmpegtssection.c74
-rw-r--r--gst-libs/gst/mpegts/gstmpegtssection.h5
4 files changed, 108 insertions, 0 deletions
diff --git a/gst-libs/gst/mpegts/gstmpegts-private.h b/gst-libs/gst/mpegts/gstmpegts-private.h
index 7607b813e..7387014b0 100644
--- a/gst-libs/gst/mpegts/gstmpegts-private.h
+++ b/gst-libs/gst/mpegts/gstmpegts-private.h
@@ -37,7 +37,10 @@ G_GNUC_INTERNAL void _free_descriptor (GstMpegTsDescriptor *descriptor);
G_GNUC_INTERNAL GstMpegTsDescriptor *_new_descriptor (guint8 tag, guint8 length);
G_GNUC_INTERNAL GstMpegTsDescriptor *_new_descriptor_with_extension (guint8 tag,
guint8 tag_extension, guint8 length);
+G_GNUC_INTERNAL void _packetize_descriptor_array (GPtrArray * array,
+ guint8 ** out_data);
G_GNUC_INTERNAL GstMpegTsSection *_gst_mpegts_section_init (guint16 pid, guint8 table_id);
+G_GNUC_INTERNAL void _packetize_common_section (GstMpegTsSection * section, gsize length);
typedef gpointer (*GstMpegTsParseFunc) (GstMpegTsSection *section);
G_GNUC_INTERNAL gpointer __common_desc_checks (GstMpegTsSection *section,
diff --git a/gst-libs/gst/mpegts/gstmpegtsdescriptor.c b/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
index a49adfdc8..35a8f89fd 100644
--- a/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
+++ b/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
@@ -627,6 +627,32 @@ failed:
}
}
+void
+_packetize_descriptor_array (GPtrArray * array, guint8 ** out_data)
+{
+ guint i;
+ guint8 header_size;
+ GstMpegTsDescriptor *descriptor;
+
+ g_return_if_fail (out_data != NULL);
+ g_return_if_fail (*out_data != NULL);
+
+ if (array == NULL)
+ return;
+
+ for (i = 0; i < array->len; i++) {
+ descriptor = g_ptr_array_index (array, i);
+
+ if (descriptor->tag == GST_MTS_DESC_DVB_EXTENSION)
+ header_size = 3;
+ else
+ header_size = 2;
+
+ memcpy (*out_data, descriptor->data, descriptor->length + header_size);
+ *out_data += descriptor->length + header_size;
+ }
+}
+
GstMpegTsDescriptor *
_new_descriptor (guint8 tag, guint8 length)
{
diff --git a/gst-libs/gst/mpegts/gstmpegtssection.c b/gst-libs/gst/mpegts/gstmpegtssection.c
index 6a2bed506..054a07737 100644
--- a/gst-libs/gst/mpegts/gstmpegtssection.c
+++ b/gst-libs/gst/mpegts/gstmpegtssection.c
@@ -733,6 +733,44 @@ _gst_mpegts_section_init (guint16 pid, guint8 table_id)
return section;
}
+void
+_packetize_common_section (GstMpegTsSection * section, gsize length)
+{
+ guint8 *data;
+
+ section->section_length = length;
+ data = section->data = g_malloc (length);
+
+ /* table_id - 8 bit uimsbf */
+ *data++ = section->table_id;
+
+ /* section_syntax_indicator - 1 bit
+ reserved - 3 bit
+ section_length - 12 bit uimsbf */
+ GST_WRITE_UINT16_BE (data, (section->section_length - 3) | 0x7000);
+
+ if (!section->short_section)
+ *data |= 0x80;
+
+ data += 2;
+
+ /* subtable_extension - 16 bit uimsbf */
+ GST_WRITE_UINT16_BE (data, section->subtable_extension);
+ data += 2;
+
+ /* reserved - 2 bit
+ version_number - 5 bit uimsbf
+ current_next_indicator - 1 bit */
+ *data++ =
+ 0xC0 | ((section->version_number & 0x1F) << 1) | (section->
+ current_next_indicator & 0x01);
+
+ /* section_number - 8 bit uimsbf */
+ *data++ = section->section_number;
+ /* last_section_number - 8 bit uimsbf */
+ *data++ = section->last_section_number;
+}
+
/**
* gst_mpegts_section_new:
* @pid: the PID to which this section belongs
@@ -808,3 +846,39 @@ short_packet:
return NULL;
}
}
+
+/**
+ * gst_mpegts_section_packetize:
+ * @section: (transfer none): the #GstMpegTsSection that holds the data
+ * @output_size: (out): #gsize to hold the size of the data
+ *
+ * If the data in @section has aldready been packetized, the data pointer is returned
+ * immediately. Otherwise, the data field is allocated and populated.
+ *
+ * Returns: (transfer none): pointer to section data, or %NULL on fail
+ */
+guint8 *
+gst_mpegts_section_packetize (GstMpegTsSection * section, gsize * output_size)
+{
+ guint8 *crc;
+ g_return_val_if_fail (section != NULL, NULL);
+ g_return_val_if_fail (output_size != NULL, NULL);
+ g_return_val_if_fail (section->packetizer != NULL, NULL);
+
+ /* Section data has already been packetized */
+ if (section->data)
+ return section->data;
+
+ if (!section->packetizer (section))
+ return NULL;
+
+ if (!section->short_section) {
+ /* Update the CRC in the last 4 bytes of the section */
+ crc = section->data + section->section_length - 4;
+ GST_WRITE_UINT32_BE (crc, _calc_crc32 (section->data, crc - section->data));
+ }
+
+ *output_size = section->section_length;
+
+ return section->data;
+}
diff --git a/gst-libs/gst/mpegts/gstmpegtssection.h b/gst-libs/gst/mpegts/gstmpegtssection.h
index fd4db98d1..077a074ab 100644
--- a/gst-libs/gst/mpegts/gstmpegtssection.h
+++ b/gst-libs/gst/mpegts/gstmpegtssection.h
@@ -104,6 +104,8 @@ typedef enum {
} GstMpegTsSectionTableID;
+typedef gboolean (*GstMpegTsPacketizeFunc) (GstMpegTsSection *section);
+
/**
* GstMpegTsSection:
* @section_type: The type of section
@@ -156,6 +158,7 @@ struct _GstMpegTsSection
* FIXME : Maybe make public later on when allowing creation of
* sections to that people can create private short sections ? */
gboolean short_section;
+ GstMpegTsPacketizeFunc packetizer;
};
@@ -364,6 +367,8 @@ GstMpegTsSection *gst_mpegts_section_new (guint16 pid,
guint8 * data,
gsize data_size);
+guint8 *gst_mpegts_section_packetize (GstMpegTsSection * section, gsize * output_size);
+
G_END_DECLS
#endif /* GST_MPEGTS_SECTION_H */