mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-07 00:31:01 +00:00
mpegts: Unify section checks and add BAT parsing
* Avoid repeating code everywhere, and instead provide all parsing information in one go. * Add BAT support * Refine BAT/CAT identification (by adding PID checks)
This commit is contained in:
parent
2fb7b87140
commit
ae4d6bb334
4 changed files with 256 additions and 206 deletions
|
@ -133,7 +133,7 @@ G_DEFINE_BOXED_TYPE (GstMpegTsEIT, gst_mpegts_eit,
|
|||
(GBoxedCopyFunc) _gst_mpegts_eit_copy, (GFreeFunc) _gst_mpegts_eit_free);
|
||||
|
||||
|
||||
static GstMpegTsEIT *
|
||||
static gpointer
|
||||
_parse_eit (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsEIT *eit = NULL;
|
||||
|
@ -141,13 +141,6 @@ _parse_eit (GstMpegTsSection * section)
|
|||
guint8 *data, *end, *duration_ptr;
|
||||
guint16 descriptors_loop_length;
|
||||
|
||||
/* fixed header + CRC == 16 */
|
||||
if (section->section_length < 18) {
|
||||
GST_WARNING ("PID %d invalid EIT size %d",
|
||||
section->pid, section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
eit = g_slice_new0 (GstMpegTsEIT);
|
||||
|
||||
data = section->data;
|
||||
|
@ -218,11 +211,11 @@ _parse_eit (GstMpegTsSection * section)
|
|||
goto error;
|
||||
}
|
||||
|
||||
return eit;
|
||||
return (gpointer) eit;
|
||||
|
||||
error:
|
||||
if (eit)
|
||||
gst_mpegts_section_unref (eit);
|
||||
_gst_mpegts_eit_free (eit);
|
||||
|
||||
return NULL;
|
||||
|
||||
|
@ -243,32 +236,32 @@ gst_mpegts_section_get_eit (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_EIT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_eit (section);
|
||||
section->destroy_parsed = (GDestroyNotify) _gst_mpegts_eit_free;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed = __common_desc_checks (section, 18, _parse_eit,
|
||||
(GDestroyNotify) _gst_mpegts_eit_free);
|
||||
|
||||
return (const GstMpegTsEIT *) section->cached_parsed;
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bouquet Association Table */
|
||||
static GstMpegTsBATStream *
|
||||
_gst_mpegts_bat_stream_copy (GstMpegTsBATStream * bat)
|
||||
{
|
||||
/* FIXME : IMPLEMENT */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_bat_stream_free (GstMpegTsBATStream * bat)
|
||||
{
|
||||
g_array_unref (bat->descriptors);
|
||||
g_slice_free (GstMpegTsBATStream, bat);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegTsBATStream, gst_mpegts_bat_stream,
|
||||
(GBoxedCopyFunc) _gst_mpegts_bat_stream_copy,
|
||||
(GFreeFunc) _gst_mpegts_bat_stream_free);
|
||||
|
||||
static GstMpegTsBAT *
|
||||
_gst_mpegts_bat_copy (GstMpegTsBAT * bat)
|
||||
{
|
||||
|
@ -279,12 +272,143 @@ _gst_mpegts_bat_copy (GstMpegTsBAT * bat)
|
|||
static void
|
||||
_gst_mpegts_bat_free (GstMpegTsBAT * bat)
|
||||
{
|
||||
/* FIXME: IMPLEMENT */
|
||||
g_array_unref (bat->descriptors);
|
||||
g_ptr_array_unref (bat->streams);
|
||||
g_slice_free (GstMpegTsBAT, bat);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegTsBAT, gst_mpegts_bat,
|
||||
(GBoxedCopyFunc) _gst_mpegts_bat_copy, (GFreeFunc) _gst_mpegts_bat_free);
|
||||
|
||||
static gpointer
|
||||
_parse_bat (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsBAT *bat = NULL;
|
||||
guint i = 0, allocated_streams = 12;
|
||||
guint8 *data, *end, *entry_begin;
|
||||
guint16 descriptors_loop_length, transport_stream_loop_length;
|
||||
|
||||
GST_DEBUG ("BAT");
|
||||
|
||||
bat = g_slice_new0 (GstMpegTsBAT);
|
||||
|
||||
data = section->data;
|
||||
end = data + section->section_length;
|
||||
|
||||
/* Skip already parsed data */
|
||||
data += 8;
|
||||
|
||||
descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
|
||||
data += 2;
|
||||
|
||||
/* see if the buffer is large enough */
|
||||
if (descriptors_loop_length && (data + descriptors_loop_length > end - 4)) {
|
||||
GST_WARNING ("PID %d invalid BAT descriptors loop length %d",
|
||||
section->pid, descriptors_loop_length);
|
||||
goto error;
|
||||
}
|
||||
bat->descriptors =
|
||||
gst_mpegts_parse_descriptors (data, descriptors_loop_length);
|
||||
if (bat->descriptors == NULL)
|
||||
goto error;
|
||||
data += descriptors_loop_length;
|
||||
|
||||
transport_stream_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
|
||||
data += 2;
|
||||
if (G_UNLIKELY (transport_stream_loop_length > (end - 4 - data))) {
|
||||
GST_WARNING
|
||||
("PID 0x%04x invalid BAT (transport_stream_loop_length too big)",
|
||||
section->pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bat->streams =
|
||||
g_ptr_array_new_full (allocated_streams,
|
||||
(GDestroyNotify) _gst_mpegts_bat_stream_free);
|
||||
|
||||
/* read up to the CRC */
|
||||
while (transport_stream_loop_length - 4 > 0) {
|
||||
GstMpegTsBATStream *stream = g_slice_new0 (GstMpegTsBATStream);
|
||||
|
||||
g_ptr_array_add (bat->streams, stream);
|
||||
|
||||
if (transport_stream_loop_length < 6) {
|
||||
/* each entry must be at least 6 bytes (+ 4bytes CRC) */
|
||||
GST_WARNING ("PID %d invalid BAT entry size %d",
|
||||
section->pid, transport_stream_loop_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
entry_begin = data;
|
||||
|
||||
stream->transport_stream_id = GST_READ_UINT16_BE (data);
|
||||
data += 2;
|
||||
|
||||
stream->original_network_id = GST_READ_UINT16_BE (data);
|
||||
data += 2;
|
||||
|
||||
descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
|
||||
data += 2;
|
||||
|
||||
GST_DEBUG ("descriptors_loop_length %d", descriptors_loop_length);
|
||||
|
||||
if (descriptors_loop_length && (data + descriptors_loop_length > end - 4)) {
|
||||
GST_WARNING
|
||||
("PID %d invalid BAT entry %d descriptors loop length %d (only have %"
|
||||
G_GSIZE_FORMAT ")", section->pid, section->subtable_extension,
|
||||
descriptors_loop_length, end - 4 - data);
|
||||
goto error;
|
||||
}
|
||||
stream->descriptors =
|
||||
gst_mpegts_parse_descriptors (data, descriptors_loop_length);
|
||||
if (stream->descriptors == NULL)
|
||||
goto error;
|
||||
|
||||
data += descriptors_loop_length;
|
||||
|
||||
i += 1;
|
||||
transport_stream_loop_length -= data - entry_begin;
|
||||
}
|
||||
|
||||
if (data != end - 4) {
|
||||
GST_WARNING ("PID %d invalid BAT parsed %d length %d",
|
||||
section->pid, (gint) (data - section->data), section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return (gpointer) bat;
|
||||
|
||||
error:
|
||||
if (bat)
|
||||
_gst_mpegts_bat_free (bat);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpegts_section_get_bat:
|
||||
* @section: a #GstMpegTsSection of type %GST_MPEGTS_SECTION_BAT
|
||||
*
|
||||
* Returns the #GstMpegTsBAT contained in the @section.
|
||||
*
|
||||
* Returns: The #GstMpegTsBAT contained in the section, or %NULL if an error
|
||||
* happened.
|
||||
*/
|
||||
const GstMpegTsBAT *
|
||||
gst_mpegts_section_get_bat (GstMpegTsSection * section)
|
||||
{
|
||||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_BAT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 16, _parse_bat,
|
||||
(GDestroyNotify) _gst_mpegts_bat_free);
|
||||
|
||||
return (const GstMpegTsBAT *) section->cached_parsed;
|
||||
}
|
||||
|
||||
|
||||
/* Network Information Table */
|
||||
|
||||
static GstMpegTsNITStream *
|
||||
|
@ -324,7 +448,7 @@ G_DEFINE_BOXED_TYPE (GstMpegTsNIT, gst_mpegts_nit,
|
|||
(GBoxedCopyFunc) _gst_mpegts_nit_copy, (GFreeFunc) _gst_mpegts_nit_free);
|
||||
|
||||
|
||||
static GstMpegTsNIT *
|
||||
static gpointer
|
||||
_parse_nit (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsNIT *nit = NULL;
|
||||
|
@ -334,13 +458,6 @@ _parse_nit (GstMpegTsSection * section)
|
|||
|
||||
GST_DEBUG ("NIT");
|
||||
|
||||
/* fixed header (no streams) + CRC == 16 */
|
||||
if (section->section_length < 16) {
|
||||
GST_WARNING ("PID %d invalid NIT size %d",
|
||||
section->pid, section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
nit = g_slice_new0 (GstMpegTsNIT);
|
||||
|
||||
data = section->data;
|
||||
|
@ -429,11 +546,11 @@ _parse_nit (GstMpegTsSection * section)
|
|||
goto error;
|
||||
}
|
||||
|
||||
return nit;
|
||||
return (gpointer) nit;
|
||||
|
||||
error:
|
||||
if (nit)
|
||||
gst_mpegts_section_unref (nit);
|
||||
_gst_mpegts_nit_free (nit);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -453,29 +570,12 @@ gst_mpegts_section_get_nit (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_NIT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_nit (section);
|
||||
section->destroy_parsed = (GDestroyNotify) _gst_mpegts_nit_free;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 16, _parse_nit,
|
||||
(GDestroyNotify) _gst_mpegts_nit_free);
|
||||
|
||||
return (const GstMpegTsNIT *) section->cached_parsed;
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -517,7 +617,7 @@ G_DEFINE_BOXED_TYPE (GstMpegTsSDT, gst_mpegts_sdt,
|
|||
(GBoxedCopyFunc) _gst_mpegts_sdt_copy, (GFreeFunc) _gst_mpegts_sdt_free);
|
||||
|
||||
|
||||
static GstMpegTsSDT *
|
||||
static gpointer
|
||||
_parse_sdt (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsSDT *sdt = NULL;
|
||||
|
@ -529,13 +629,6 @@ _parse_sdt (GstMpegTsSection * section)
|
|||
|
||||
GST_DEBUG ("SDT");
|
||||
|
||||
/* fixed header + CRC == 16 */
|
||||
if (section->section_length < 14) {
|
||||
GST_WARNING ("PID %d invalid SDT size %d",
|
||||
section->pid, section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sdt = g_slice_new0 (GstMpegTsSDT);
|
||||
|
||||
data = section->data;
|
||||
|
@ -564,7 +657,7 @@ _parse_sdt (GstMpegTsSection * section)
|
|||
|
||||
entry_begin = data;
|
||||
|
||||
if (sdt_info_length < 9) {
|
||||
if (sdt_info_length + 5 < 4) {
|
||||
/* each entry must be at least 5 bytes (+4 bytes for the CRC) */
|
||||
GST_WARNING ("PID %d invalid SDT entry size %d",
|
||||
section->pid, sdt_info_length);
|
||||
|
@ -631,37 +724,19 @@ gst_mpegts_section_get_sdt (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_SDT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_sdt (section);
|
||||
section->destroy_parsed = (GDestroyNotify) _gst_mpegts_sdt_free;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 15, _parse_sdt,
|
||||
(GDestroyNotify) _gst_mpegts_sdt_free);
|
||||
|
||||
return (const GstMpegTsSDT *) section->cached_parsed;
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time and Date Table (TDT) */
|
||||
static GstDateTime *
|
||||
static gpointer
|
||||
_parse_tdt (GstMpegTsSection * section)
|
||||
{
|
||||
/* FIXME : Add length check */
|
||||
return _parse_utc_time (section->data + 3);
|
||||
return (gpointer) _parse_utc_time (section->data + 3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -679,20 +754,14 @@ gst_mpegts_section_get_tdt (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_TDT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
section->cached_parsed = (gpointer) _parse_tdt (section);
|
||||
section->destroy_parsed = (GDestroyNotify) gst_date_time_unref;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 8, _parse_tdt,
|
||||
(GDestroyNotify) gst_date_time_unref);
|
||||
|
||||
return gst_date_time_ref ((GstDateTime *) section->cached_parsed);
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
if (section->cached_parsed)
|
||||
return gst_date_time_ref ((GstDateTime *) section->cached_parsed);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -716,15 +785,13 @@ _gst_mpegts_tot_free (GstMpegTsTOT * tot)
|
|||
G_DEFINE_BOXED_TYPE (GstMpegTsTOT, gst_mpegts_tot,
|
||||
(GBoxedCopyFunc) _gst_mpegts_tot_copy, (GFreeFunc) _gst_mpegts_tot_free);
|
||||
|
||||
static GstMpegTsTOT *
|
||||
static gpointer
|
||||
_parse_tot (GstMpegTsSection * section)
|
||||
{
|
||||
guint8 *data;
|
||||
GstMpegTsTOT *tot;
|
||||
guint16 desc_len;
|
||||
|
||||
/* FIXME : Check minimum length */
|
||||
|
||||
GST_DEBUG ("TOT");
|
||||
|
||||
tot = g_slice_new0 (GstMpegTsTOT);
|
||||
|
@ -738,7 +805,7 @@ _parse_tot (GstMpegTsSection * section)
|
|||
data += 2;
|
||||
tot->descriptors = gst_mpegts_parse_descriptors (data, desc_len);
|
||||
|
||||
return tot;
|
||||
return (gpointer) tot;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -756,27 +823,10 @@ gst_mpegts_section_get_tot (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_TOT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_tot (section);
|
||||
section->destroy_parsed = (GDestroyNotify) _gst_mpegts_tot_free;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 14, _parse_tot,
|
||||
(GDestroyNotify) _gst_mpegts_tot_free);
|
||||
|
||||
return (const GstMpegTsTOT *) section->cached_parsed;
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@ typedef struct _GstMpegTsBATStream GstMpegTsBATStream;
|
|||
typedef struct _GstMpegTsBAT GstMpegTsBAT;
|
||||
|
||||
#define GST_TYPE_MPEGTS_BAT (gst_mpegts_bat_get_type())
|
||||
#define GST_TYPE_MPEGTS_BAT_STREAM (gst_mpegts_bat_get_type())
|
||||
|
||||
struct _GstMpegTsBATStream
|
||||
{
|
||||
|
@ -195,6 +196,9 @@ struct _GstMpegTsBAT
|
|||
};
|
||||
|
||||
GType gst_mpegts_bat_get_type (void);
|
||||
GType gst_mpegts_bat_stream_get_type (void);
|
||||
|
||||
const GstMpegTsBAT *gst_mpegts_section_get_bat (GstMpegTsSection *section);
|
||||
|
||||
/* SDT */
|
||||
#define GST_TYPE_MPEGTS_SDT (gst_mpegts_sdt_get_type())
|
||||
|
|
|
@ -31,4 +31,10 @@ G_GNUC_INTERNAL void __initialize_descriptors (void);
|
|||
G_GNUC_INTERNAL guint32 _calc_crc32 (const guint8 *data, guint datalen);
|
||||
G_GNUC_INTERNAL gchar *get_encoding_and_convert (const gchar *text, guint length);
|
||||
|
||||
typedef gpointer (*GstMpegTsParseFunc) (GstMpegTsSection *section);
|
||||
G_GNUC_INTERNAL gpointer __common_desc_checks (GstMpegTsSection *section,
|
||||
guint minsize,
|
||||
GstMpegTsParseFunc parsefunc,
|
||||
GDestroyNotify destroynotify);
|
||||
|
||||
#endif /* _GST_MPEGTS_PRIVATE_H_ */
|
||||
|
|
|
@ -149,6 +149,37 @@ _calc_crc32 (const guint8 * data, guint datalen)
|
|||
return crc;
|
||||
}
|
||||
|
||||
gpointer
|
||||
__common_desc_checks (GstMpegTsSection * section, guint min_size,
|
||||
GstMpegTsParseFunc parsefunc, GDestroyNotify destroynotify)
|
||||
{
|
||||
gpointer res;
|
||||
|
||||
/* Check section is big enough */
|
||||
if (section->section_length < min_size) {
|
||||
GST_WARNING
|
||||
("PID:0x%04x table_id:0x%02x, section too small (Got %d, need at least %d)",
|
||||
section->pid, section->table_id, section->section_length, min_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If section has a CRC, check it */
|
||||
if (!section->short_section
|
||||
&& (_calc_crc32 (section->data, section->section_length) != 0)) {
|
||||
GST_WARNING ("PID:0x%04x table_id:0x%02x, Bad CRC on section", section->pid,
|
||||
section->table_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finally parse and set the destroy notify */
|
||||
res = parsefunc (section);
|
||||
if (res == NULL)
|
||||
GST_WARNING ("PID:0x%04x table_id:0x%02x, Failed to parse section",
|
||||
section->pid, section->table_id);
|
||||
else
|
||||
section->destroy_parsed = destroynotify;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -287,7 +318,7 @@ gst_message_new_mpegts_section (GstObject * parent, GstMpegTsSection * section)
|
|||
|
||||
|
||||
/* Program Association Table */
|
||||
static GArray *
|
||||
static gpointer
|
||||
_parse_pat (GstMpegTsSection * section)
|
||||
{
|
||||
GArray *pat;
|
||||
|
@ -326,7 +357,7 @@ _parse_pat (GstMpegTsSection * section)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return pat;
|
||||
return (gpointer) pat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -350,29 +381,14 @@ gst_mpegts_section_get_pat (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_PAT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 12, _parse_pat,
|
||||
(GDestroyNotify) g_array_unref);
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_pat (section);
|
||||
section->destroy_parsed = (GDestroyNotify) g_array_unref;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
|
||||
return g_array_ref ((GArray *) section->cached_parsed);
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
if (section->cached_parsed)
|
||||
return g_array_ref ((GArray *) section->cached_parsed);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -415,7 +431,7 @@ G_DEFINE_BOXED_TYPE (GstMpegTsPMT, gst_mpegts_pmt,
|
|||
(GBoxedCopyFunc) _gst_mpegts_pmt_copy, (GFreeFunc) _gst_mpegts_pmt_free);
|
||||
|
||||
|
||||
static GstMpegTsPMT *
|
||||
static gpointer
|
||||
_parse_pmt (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsPMT *pmt = NULL;
|
||||
|
@ -424,13 +440,6 @@ _parse_pmt (GstMpegTsSection * section)
|
|||
guint program_info_length;
|
||||
guint stream_info_length;
|
||||
|
||||
/* fixed header + CRC == 16 */
|
||||
if (section->section_length < 16) {
|
||||
GST_WARNING ("PID %d invalid PMT size %d",
|
||||
section->pid, section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
pmt = g_slice_new0 (GstMpegTsPMT);
|
||||
|
||||
data = section->data;
|
||||
|
@ -496,11 +505,11 @@ _parse_pmt (GstMpegTsSection * section)
|
|||
|
||||
g_assert (data == end - 4);
|
||||
|
||||
return pmt;
|
||||
return (gpointer) pmt;
|
||||
|
||||
error:
|
||||
if (pmt)
|
||||
gst_mpegts_section_unref (pmt);
|
||||
_gst_mpegts_pmt_free (pmt);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -520,34 +529,17 @@ gst_mpegts_section_get_pmt (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_PMT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
if (G_UNLIKELY (_calc_crc32 (section->data, section->section_length) != 0))
|
||||
goto bad_crc;
|
||||
|
||||
section->cached_parsed = (gpointer) _parse_pmt (section);
|
||||
section->destroy_parsed = (GDestroyNotify) _gst_mpegts_pmt_free;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 16, _parse_pmt,
|
||||
(GDestroyNotify) _gst_mpegts_pmt_free);
|
||||
|
||||
return (const GstMpegTsPMT *) section->cached_parsed;
|
||||
|
||||
bad_crc:
|
||||
{
|
||||
GST_WARNING ("Bad CRC on section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Conditional Access Table */
|
||||
static GArray *
|
||||
static gpointer
|
||||
_parse_cat (GstMpegTsSection * section)
|
||||
{
|
||||
guint8 *data;
|
||||
|
@ -558,7 +550,7 @@ _parse_cat (GstMpegTsSection * section)
|
|||
|
||||
/* descriptors */
|
||||
desc_len = section->section_length - 4 - 8;
|
||||
return gst_mpegts_parse_descriptors (data, desc_len);
|
||||
return (gpointer) gst_mpegts_parse_descriptors (data, desc_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -578,20 +570,14 @@ gst_mpegts_section_get_cat (GstMpegTsSection * section)
|
|||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_CAT, NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed) {
|
||||
section->cached_parsed = (gpointer) _parse_cat (section);
|
||||
section->destroy_parsed = (GDestroyNotify) g_array_unref;
|
||||
if (section->cached_parsed == NULL)
|
||||
goto parse_failure;
|
||||
}
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed =
|
||||
__common_desc_checks (section, 12, _parse_cat,
|
||||
(GDestroyNotify) g_array_unref);
|
||||
|
||||
return g_array_ref ((GArray *) section->cached_parsed);
|
||||
|
||||
parse_failure:
|
||||
{
|
||||
GST_WARNING ("Failure to parse section");
|
||||
return NULL;
|
||||
}
|
||||
if (section->cached_parsed)
|
||||
return g_array_ref ((GArray *) section->cached_parsed);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Transport Stream Description Table (TSDT) */
|
||||
|
@ -662,11 +648,15 @@ _identify_section (guint16 pid, guint8 table_id)
|
|||
return GST_MPEGTS_SECTION_PAT;
|
||||
break;
|
||||
case GST_MTS_TABLE_ID_CONDITIONAL_ACCESS:
|
||||
return GST_MPEGTS_SECTION_CAT;
|
||||
if (pid == 0x01)
|
||||
return GST_MPEGTS_SECTION_CAT;
|
||||
break;
|
||||
case GST_MTS_TABLE_ID_TS_PROGRAM_MAP:
|
||||
return GST_MPEGTS_SECTION_PMT;
|
||||
case GST_MTS_TABLE_ID_BOUQUET_ASSOCIATION:
|
||||
return GST_MPEGTS_SECTION_BAT;
|
||||
if (pid == 0x0011)
|
||||
return GST_MPEGTS_SECTION_BAT;
|
||||
break;
|
||||
case GST_MTS_TABLE_ID_NETWORK_INFORMATION_ACTUAL_NETWORK:
|
||||
case GST_MTS_TABLE_ID_NETWORK_INFORMATION_OTHER_NETWORK:
|
||||
if (pid == 0x0010)
|
||||
|
|
Loading…
Reference in a new issue