mpegts: ABI/API break: Use GPtrArray instead of GArray

While it was a great idea, various g-i based bindings don't support
GArray with entries greater than sizeof(gpointer) :(

So let's just make everybody happy by just using GPtrArray.

And since we're breaking the API, also rename the various descriptor fields
to no longer have the descriptor_ prefix.

It does cost a bit more in terms of memory/cpu usage, but makes it usable
from bindings.
This commit is contained in:
Edward Hervey 2013-08-21 08:40:16 +02:00
parent 006e7a3428
commit 5d06aed3e2
8 changed files with 211 additions and 156 deletions

View file

@ -67,12 +67,11 @@ gboolean
gst_mpegts_descriptor_parse_dvb_network_name (const GstMpegTsDescriptor * gst_mpegts_descriptor_parse_dvb_network_name (const GstMpegTsDescriptor *
descriptor, gchar ** name) descriptor, gchar ** name)
{ {
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE); g_return_val_if_fail (descriptor->tag == 0x40, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x40, FALSE);
*name = get_encoding_and_convert ((gchar *) descriptor->descriptor_data + 2, *name = get_encoding_and_convert ((gchar *) descriptor->data + 2,
descriptor->descriptor_data[1]); descriptor->data[1]);
return TRUE; return TRUE;
} }
@ -93,12 +92,11 @@ gst_mpegts_descriptor_parse_satellite_delivery_system (const GstMpegTsDescriptor
guint8 *data; guint8 *data;
guint8 tmp; guint8 tmp;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE);
g_return_val_if_fail (res != NULL, FALSE); g_return_val_if_fail (res != NULL, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x43, FALSE); g_return_val_if_fail (descriptor->tag == 0x43, FALSE);
data = (guint8 *) descriptor->descriptor_data + 2; data = (guint8 *) descriptor->data + 2;
#define BCD_UN(a) ((a) & 0x0f) #define BCD_UN(a) ((a) & 0x0f)
#define BCD_DEC(a) (((a) >> 4) & 0x0f) #define BCD_DEC(a) (((a) >> 4) & 0x0f)
@ -169,12 +167,11 @@ gst_mpegts_descriptor_parse_cable_delivery_system (const GstMpegTsDescriptor *
{ {
guint8 *data; guint8 *data;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE);
g_return_val_if_fail (res != NULL, FALSE); g_return_val_if_fail (res != NULL, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x44, FALSE); g_return_val_if_fail (descriptor->tag == 0x44, FALSE);
data = (guint8 *) descriptor->descriptor_data + 2; data = (guint8 *) descriptor->data + 2;
/* BCD in MHz, decimal place after the fourth character */ /* BCD in MHz, decimal place after the fourth character */
res->frequency = BCD_32 (data) * 100; res->frequency = BCD_32 (data) * 100;
data += 5; data += 5;
@ -235,11 +232,10 @@ gst_mpegts_descriptor_parse_dvb_service (const GstMpegTsDescriptor *
{ {
guint8 *data; guint8 *data;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE); g_return_val_if_fail (descriptor->tag == 0x48, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x48, FALSE);
data = (guint8 *) descriptor->descriptor_data + 2; data = (guint8 *) descriptor->data + 2;
if (service_type) if (service_type)
*service_type = *data; *service_type = *data;
@ -271,11 +267,10 @@ gst_mpegts_descriptor_parse_dvb_short_event (const GstMpegTsDescriptor *
{ {
guint8 *data; guint8 *data;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE); g_return_val_if_fail (descriptor->tag == 0x4D, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x4D, FALSE);
data = (guint8 *) descriptor->descriptor_data + 2; data = (guint8 *) descriptor->data + 2;
if (language_code) { if (language_code) {
*language_code = g_malloc0 (4); *language_code = g_malloc0 (4);

View file

@ -98,8 +98,13 @@ _parse_utc_time (guint8 * data)
static GstMpegTsEITEvent * static GstMpegTsEITEvent *
_gst_mpegts_eit_event_copy (GstMpegTsEITEvent * eit) _gst_mpegts_eit_event_copy (GstMpegTsEITEvent * eit)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsEITEvent *copy;
return NULL;
copy = g_slice_dup (GstMpegTsEITEvent, eit);
copy->start_time = gst_date_time_ref (eit->start_time);
copy->descriptors = g_ptr_array_ref (eit->descriptors);
return copy;
} }
static void static void
@ -107,7 +112,7 @@ _gst_mpegts_eit_event_free (GstMpegTsEITEvent * eit)
{ {
if (eit->start_time) if (eit->start_time)
gst_date_time_unref (eit->start_time); gst_date_time_unref (eit->start_time);
g_array_unref (eit->descriptors); g_ptr_array_unref (eit->descriptors);
g_slice_free (GstMpegTsEITEvent, eit); g_slice_free (GstMpegTsEITEvent, eit);
} }
@ -118,8 +123,12 @@ G_DEFINE_BOXED_TYPE (GstMpegTsEITEvent, gst_mpegts_eit_event,
static GstMpegTsEIT * static GstMpegTsEIT *
_gst_mpegts_eit_copy (GstMpegTsEIT * eit) _gst_mpegts_eit_copy (GstMpegTsEIT * eit)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsEIT *copy;
return NULL;
copy = g_slice_dup (GstMpegTsEIT, eit);
copy->events = g_ptr_array_ref (eit->events);
return copy;
} }
static void static void
@ -247,14 +256,18 @@ gst_mpegts_section_get_eit (GstMpegTsSection * section)
static GstMpegTsBATStream * static GstMpegTsBATStream *
_gst_mpegts_bat_stream_copy (GstMpegTsBATStream * bat) _gst_mpegts_bat_stream_copy (GstMpegTsBATStream * bat)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsBATStream *copy;
return NULL;
copy = g_slice_dup (GstMpegTsBATStream, bat);
copy->descriptors = g_ptr_array_ref (bat->descriptors);
return copy;
} }
static void static void
_gst_mpegts_bat_stream_free (GstMpegTsBATStream * bat) _gst_mpegts_bat_stream_free (GstMpegTsBATStream * bat)
{ {
g_array_unref (bat->descriptors); g_ptr_array_unref (bat->descriptors);
g_slice_free (GstMpegTsBATStream, bat); g_slice_free (GstMpegTsBATStream, bat);
} }
@ -265,14 +278,19 @@ G_DEFINE_BOXED_TYPE (GstMpegTsBATStream, gst_mpegts_bat_stream,
static GstMpegTsBAT * static GstMpegTsBAT *
_gst_mpegts_bat_copy (GstMpegTsBAT * bat) _gst_mpegts_bat_copy (GstMpegTsBAT * bat)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsBAT *copy;
return NULL;
copy = g_slice_dup (GstMpegTsBAT, bat);
copy->descriptors = g_ptr_array_ref (bat->descriptors);
copy->streams = g_ptr_array_ref (bat->streams);
return copy;
} }
static void static void
_gst_mpegts_bat_free (GstMpegTsBAT * bat) _gst_mpegts_bat_free (GstMpegTsBAT * bat)
{ {
g_array_unref (bat->descriptors); g_ptr_array_unref (bat->descriptors);
g_ptr_array_unref (bat->streams); g_ptr_array_unref (bat->streams);
g_slice_free (GstMpegTsBAT, bat); g_slice_free (GstMpegTsBAT, bat);
} }
@ -414,14 +432,18 @@ gst_mpegts_section_get_bat (GstMpegTsSection * section)
static GstMpegTsNITStream * static GstMpegTsNITStream *
_gst_mpegts_nit_stream_copy (GstMpegTsNITStream * nit) _gst_mpegts_nit_stream_copy (GstMpegTsNITStream * nit)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsNITStream *copy;
return NULL;
copy = g_slice_dup (GstMpegTsNITStream, nit);
copy->descriptors = g_ptr_array_ref (nit->descriptors);
return copy;
} }
static void static void
_gst_mpegts_nit_stream_free (GstMpegTsNITStream * nit) _gst_mpegts_nit_stream_free (GstMpegTsNITStream * nit)
{ {
g_array_unref (nit->descriptors); g_ptr_array_unref (nit->descriptors);
g_slice_free (GstMpegTsNITStream, nit); g_slice_free (GstMpegTsNITStream, nit);
} }
@ -432,14 +454,18 @@ G_DEFINE_BOXED_TYPE (GstMpegTsNITStream, gst_mpegts_nit_stream,
static GstMpegTsNIT * static GstMpegTsNIT *
_gst_mpegts_nit_copy (GstMpegTsNIT * nit) _gst_mpegts_nit_copy (GstMpegTsNIT * nit)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsNIT *copy = g_slice_dup (GstMpegTsNIT, nit);
return NULL;
copy->descriptors = g_ptr_array_ref (nit->descriptors);
copy->streams = g_ptr_array_ref (nit->streams);
return copy;
} }
static void static void
_gst_mpegts_nit_free (GstMpegTsNIT * nit) _gst_mpegts_nit_free (GstMpegTsNIT * nit)
{ {
g_array_unref (nit->descriptors); g_ptr_array_unref (nit->descriptors);
g_ptr_array_unref (nit->streams); g_ptr_array_unref (nit->streams);
g_slice_free (GstMpegTsNIT, nit); g_slice_free (GstMpegTsNIT, nit);
} }
@ -584,14 +610,17 @@ gst_mpegts_section_get_nit (GstMpegTsSection * section)
static GstMpegTsSDTService * static GstMpegTsSDTService *
_gst_mpegts_sdt_service_copy (GstMpegTsSDTService * sdt) _gst_mpegts_sdt_service_copy (GstMpegTsSDTService * sdt)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsSDTService *copy = g_slice_dup (GstMpegTsSDTService, sdt);
return NULL;
copy->descriptors = g_ptr_array_ref (sdt->descriptors);
return copy;
} }
static void static void
_gst_mpegts_sdt_service_free (GstMpegTsSDTService * sdt) _gst_mpegts_sdt_service_free (GstMpegTsSDTService * sdt)
{ {
g_array_unref (sdt->descriptors); g_ptr_array_unref (sdt->descriptors);
g_slice_free (GstMpegTsSDTService, sdt); g_slice_free (GstMpegTsSDTService, sdt);
} }
@ -602,8 +631,11 @@ G_DEFINE_BOXED_TYPE (GstMpegTsSDTService, gst_mpegts_sdt_service,
static GstMpegTsSDT * static GstMpegTsSDT *
_gst_mpegts_sdt_copy (GstMpegTsSDT * sdt) _gst_mpegts_sdt_copy (GstMpegTsSDT * sdt)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsSDT *copy = g_slice_dup (GstMpegTsSDT, sdt);
return NULL;
copy->services = g_ptr_array_ref (sdt->services);
return copy;
} }
static void static void
@ -769,8 +801,13 @@ gst_mpegts_section_get_tdt (GstMpegTsSection * section)
static GstMpegTsTOT * static GstMpegTsTOT *
_gst_mpegts_tot_copy (GstMpegTsTOT * tot) _gst_mpegts_tot_copy (GstMpegTsTOT * tot)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsTOT *copy = g_slice_dup (GstMpegTsTOT, tot);
return NULL;
if (tot->utc_time)
copy->utc_time = gst_date_time_ref (tot->utc_time);
copy->descriptors = g_ptr_array_ref (tot->descriptors);
return copy;
} }
static void static void
@ -778,7 +815,7 @@ _gst_mpegts_tot_free (GstMpegTsTOT * tot)
{ {
if (tot->utc_time) if (tot->utc_time)
gst_date_time_unref (tot->utc_time); gst_date_time_unref (tot->utc_time);
g_array_unref (tot->descriptors); g_ptr_array_unref (tot->descriptors);
g_slice_free (GstMpegTsTOT, tot); g_slice_free (GstMpegTsTOT, tot);
} }

View file

@ -137,7 +137,7 @@ struct _GstMpegTsNITStream
guint16 transport_stream_id; guint16 transport_stream_id;
guint16 original_network_id; guint16 original_network_id;
GArray *descriptors; GPtrArray *descriptors;
}; };
/** /**
@ -155,7 +155,7 @@ struct _GstMpegTsNIT
{ {
gboolean actual_network; gboolean actual_network;
GArray *descriptors; GPtrArray *descriptors;
GPtrArray *streams; GPtrArray *streams;
}; };
@ -178,7 +178,7 @@ struct _GstMpegTsBATStream
guint16 transport_stream_id; guint16 transport_stream_id;
guint16 original_network_id; guint16 original_network_id;
GArray *descriptors; GPtrArray *descriptors;
}; };
/** /**
@ -190,7 +190,7 @@ struct _GstMpegTsBATStream
*/ */
struct _GstMpegTsBAT struct _GstMpegTsBAT
{ {
GArray *descriptors; GPtrArray *descriptors;
GPtrArray *streams; GPtrArray *streams;
}; };
@ -216,7 +216,7 @@ struct _GstMpegTsSDTService
GstMpegTsRunningStatus running_status; GstMpegTsRunningStatus running_status;
gboolean free_CA_mode; gboolean free_CA_mode;
GArray *descriptors; GPtrArray *descriptors;
}; };
/** /**
@ -260,7 +260,7 @@ struct _GstMpegTsEITEvent
GstMpegTsRunningStatus running_status; GstMpegTsRunningStatus running_status;
gboolean free_CA_mode; gboolean free_CA_mode;
GArray *descriptors; GPtrArray *descriptors;
}; };
/** /**
@ -302,7 +302,7 @@ struct _GstMpegTsTOT
{ {
GstDateTime *utc_time; GstDateTime *utc_time;
GArray *descriptors; GPtrArray *descriptors;
}; };
GType gst_mpegts_tot_get_type (void); GType gst_mpegts_tot_get_type (void);

View file

@ -465,6 +465,27 @@ failed:
} }
} }
static GstMpegTsDescriptor *
_copy_descriptor (GstMpegTsDescriptor * desc)
{
GstMpegTsDescriptor *copy;
copy = g_slice_dup (GstMpegTsDescriptor, desc);
copy->data = g_memdup (desc->data, desc->length + 2);
return copy;
}
static void
_free_descriptor (GstMpegTsDescriptor * desc)
{
g_free ((gpointer) desc->data);
g_slice_free (GstMpegTsDescriptor, desc);
}
G_DEFINE_BOXED_TYPE (GstMpegTsDescriptor, gst_mpegts_descriptor,
(GBoxedCopyFunc) _copy_descriptor, (GBoxedFreeFunc) _free_descriptor);
/** /**
* gst_mpegts_parse_descriptors: * gst_mpegts_parse_descriptors:
* @buffer: (transfer none): descriptors to parse * @buffer: (transfer none): descriptors to parse
@ -479,20 +500,22 @@ failed:
* array of the parsed descriptors or %NULL if there was an error. * array of the parsed descriptors or %NULL if there was an error.
* Release with #g_array_unref when done with it. * Release with #g_array_unref when done with it.
*/ */
GArray * GPtrArray *
gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len) gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len)
{ {
GArray *res; GPtrArray *res;
guint8 length; guint8 length;
guint8 *data; guint8 *data;
guint i, nb_desc = 0; guint i, nb_desc = 0;
/* fast-path */ /* fast-path */
if (buf_len == 0) if (buf_len == 0)
return g_array_new (FALSE, FALSE, sizeof (GstMpegTsDescriptor)); return g_ptr_array_new ();
data = buffer; data = buffer;
GST_MEMDUMP ("Full descriptor array", buffer, buf_len);
while (data - buffer < buf_len) { while (data - buffer < buf_len) {
data++; /* skip tag */ data++; /* skip tag */
length = *data++; length = *data++;
@ -516,26 +539,28 @@ gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len)
return NULL; return NULL;
} }
res = g_array_sized_new (FALSE, FALSE, sizeof (GstMpegTsDescriptor), nb_desc); res = g_ptr_array_new_full (nb_desc + 1, (GDestroyNotify) _free_descriptor);
data = buffer; data = buffer;
for (i = 0; i < nb_desc; i++) { for (i = 0; i < nb_desc; i++) {
GstMpegTsDescriptor *desc = &g_array_index (res, GstMpegTsDescriptor, i); GstMpegTsDescriptor *desc = g_slice_new0 (GstMpegTsDescriptor);
desc->descriptor_data = data; desc->data = data;
desc->descriptor_tag = *data++; desc->tag = *data++;
desc->descriptor_length = *data++; desc->length = *data++;
GST_LOG ("descriptor 0x%02x length:%d", desc->descriptor_tag, /* Copy the data now that we known the size */
desc->descriptor_length); desc->data = g_memdup (desc->data, desc->length + 2);
GST_MEMDUMP ("descriptor", desc->descriptor_data + 2, GST_LOG ("descriptor 0x%02x length:%d", desc->tag, desc->length);
desc->descriptor_length); GST_MEMDUMP ("descriptor", desc->data + 2, desc->length);
/* Adjust for extended descriptors */ /* extended descriptors */
if (G_UNLIKELY (desc->descriptor_tag == 0x7f)) { if (G_UNLIKELY (desc->tag == 0x7f))
desc->descriptor_tag_extension = *data++; desc->tag_extension = *data;
desc->descriptor_length -= 1;
} data += desc->length;
data += desc->descriptor_length;
/* Set the descriptor in the array */
g_ptr_array_index (res, i) = desc;
} }
res->len = nb_desc; res->len = nb_desc;
@ -557,7 +582,7 @@ gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len)
* Returns: (transfer none): the first descriptor matchin @tag, else %NULL. * Returns: (transfer none): the first descriptor matchin @tag, else %NULL.
*/ */
const GstMpegTsDescriptor * const GstMpegTsDescriptor *
gst_mpegts_find_descriptor (GArray * descriptors, guint8 tag) gst_mpegts_find_descriptor (GPtrArray * descriptors, guint8 tag)
{ {
guint i, nb_desc; guint i, nb_desc;
@ -565,41 +590,13 @@ gst_mpegts_find_descriptor (GArray * descriptors, guint8 tag)
nb_desc = descriptors->len; nb_desc = descriptors->len;
for (i = 0; i < nb_desc; i++) { for (i = 0; i < nb_desc; i++) {
GstMpegTsDescriptor *desc = GstMpegTsDescriptor *desc = g_ptr_array_index (descriptors, i);
&g_array_index (descriptors, GstMpegTsDescriptor, i); if (desc->tag == tag)
if (desc->descriptor_tag == tag)
return (const GstMpegTsDescriptor *) desc; return (const GstMpegTsDescriptor *) desc;
} }
return NULL; return NULL;
} }
static GstMpegTsDescriptor *
_copy_descriptor (GstMpegTsDescriptor * desc)
{
GstMpegTsDescriptor *copy;
copy = g_new0 (GstMpegTsDescriptor, 1);
copy->descriptor_tag = desc->descriptor_tag;
copy->descriptor_tag_extension = desc->descriptor_tag_extension;
copy->descriptor_length = desc->descriptor_length;
copy->descriptor_data =
g_memdup (desc->descriptor_data, desc->descriptor_length);
return copy;
}
/* This freefunc will only ever be used with descriptors returned by the
* above function. That is why we free the descriptor data (unlike the
* descriptors created in _parse_descriptors()) */
static void
_free_descriptor (GstMpegTsDescriptor * desc)
{
g_free ((gpointer) desc->descriptor_data);
g_free (desc);
}
G_DEFINE_BOXED_TYPE (GstMpegTsDescriptor, gst_mpegts_descriptor,
(GBoxedCopyFunc) _copy_descriptor, (GBoxedFreeFunc) _free_descriptor);
/* GST_MTS_DESC_ISO_639_LANGUAGE (0x0A) */ /* GST_MTS_DESC_ISO_639_LANGUAGE (0x0A) */
/** /**
@ -621,14 +618,13 @@ gst_mpegts_descriptor_parse_iso_639_language (const GstMpegTsDescriptor *
guint i; guint i;
guint8 *data; guint8 *data;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE);
g_return_val_if_fail (res != NULL, FALSE); g_return_val_if_fail (res != NULL, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x0A, FALSE); g_return_val_if_fail (descriptor->tag == 0x0A, FALSE);
data = (guint8 *) descriptor->descriptor_data + 2; data = (guint8 *) descriptor->data + 2;
/* Each language is 3 + 1 bytes */ /* Each language is 3 + 1 bytes */
res->nb_language = descriptor->descriptor_length / 4; res->nb_language = descriptor->length / 4;
for (i = 0; i < res->nb_language; i++) { for (i = 0; i < res->nb_language; i++) {
memcpy (res->language[i], data, 3); memcpy (res->language[i], data, 3);
res->audio_type[i] = data[3]; res->audio_type[i] = data[3];
@ -654,12 +650,11 @@ gst_mpegts_descriptor_parse_logical_channel (const GstMpegTsDescriptor *
guint i; guint i;
guint8 *data; guint8 *data;
g_return_val_if_fail (descriptor != NULL g_return_val_if_fail (descriptor != NULL && descriptor->data != NULL, FALSE);
&& descriptor->descriptor_data != NULL, FALSE); g_return_val_if_fail (descriptor->tag == 0x83, FALSE);
g_return_val_if_fail (descriptor->descriptor_tag == 0x83, FALSE);
data = (guint8 *) descriptor->descriptor_data; data = (guint8 *) descriptor->data;
res->nb_channels = descriptor->descriptor_length / 4; res->nb_channels = descriptor->length / 4;
for (i = 0; i < res->nb_channels; i++) { for (i = 0; i < res->nb_channels; i++) {
res->channels[i].service_id = GST_READ_UINT16_BE (data); res->channels[i].service_id = GST_READ_UINT16_BE (data);

View file

@ -239,24 +239,25 @@ GType gst_mpegts_descriptor_get_type (void);
/** /**
* GstMpegTsDescriptor: * GstMpegTsDescriptor:
* @descriptor_tag: the type of descriptor * @tag: the type of descriptor
* @descriptor_tag_extension: the extended type (if @descriptor_tag is 0x7f) * @tag_extension: the extended type (if @descriptor_tag is 0x7f)
* @descriptor_length: the length of the descriptor content (excluding tag/length field) * @length: the length of the descriptor content (excluding tag/length field)
* @descriptor_data: the full descriptor data (including tag, extension, length) * @data: the full descriptor data (including tag, extension, length). The first
* two bytes are the @tag and @tag_extension.
* *
* Mpeg-TS descriptor (ISO/IEC 13818-1). * Mpeg-TS descriptor (ISO/IEC 13818-1).
*/ */
struct _GstMpegTsDescriptor struct _GstMpegTsDescriptor
{ {
guint8 descriptor_tag; guint8 tag;
guint8 descriptor_tag_extension; guint8 tag_extension;
guint8 descriptor_length; guint8 length;
const guint8 *descriptor_data; const guint8 *data;
}; };
GArray *gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len); GPtrArray *gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len);
const GstMpegTsDescriptor * gst_mpegts_find_descriptor (GArray *descriptors, const GstMpegTsDescriptor * gst_mpegts_find_descriptor (GPtrArray *descriptors,
guint8 tag); guint8 tag);
/* GST_MTS_DESC_ISO_639_LANGUAGE (0x0A) */ /* GST_MTS_DESC_ISO_639_LANGUAGE (0x0A) */

View file

@ -316,12 +316,27 @@ gst_message_new_mpegts_section (GstObject * parent, GstMpegTsSection * section)
return msg; return msg;
} }
static GstMpegTsPatProgram *
_mpegts_pat_program_copy (GstMpegTsPatProgram * orig)
{
return g_slice_dup (GstMpegTsPatProgram, orig);
}
static void
_mpegts_pat_program_free (GstMpegTsPatProgram * orig)
{
g_slice_free (GstMpegTsPatProgram, orig);
}
G_DEFINE_BOXED_TYPE (GstMpegTsPatProgram, gst_mpegts_pat_program,
(GBoxedCopyFunc) _mpegts_pat_program_copy,
(GFreeFunc) _mpegts_pat_program_free);
/* Program Association Table */ /* Program Association Table */
static gpointer static gpointer
_parse_pat (GstMpegTsSection * section) _parse_pat (GstMpegTsSection * section)
{ {
GArray *pat; GPtrArray *pat;
guint16 i = 0, nb_programs; guint16 i = 0, nb_programs;
GstMpegTsPatProgram *program; GstMpegTsPatProgram *program;
guint8 *data, *end; guint8 *data, *end;
@ -335,24 +350,26 @@ _parse_pat (GstMpegTsSection * section)
/* Initialize program list */ /* Initialize program list */
nb_programs = (end - 4 - data) / 4; nb_programs = (end - 4 - data) / 4;
pat = pat =
g_array_sized_new (FALSE, FALSE, sizeof (GstMpegTsPatProgram), g_ptr_array_new_full (nb_programs,
nb_programs); (GDestroyNotify) _mpegts_pat_program_free);
while (data < end - 4) { while (data < end - 4) {
program = &g_array_index (pat, GstMpegTsPatProgram, i); program = g_slice_new0 (GstMpegTsPatProgram);
program->program_number = GST_READ_UINT16_BE (data); program->program_number = GST_READ_UINT16_BE (data);
data += 2; data += 2;
program->network_or_program_map_PID = GST_READ_UINT16_BE (data) & 0x1FFF; program->network_or_program_map_PID = GST_READ_UINT16_BE (data) & 0x1FFF;
data += 2; data += 2;
g_ptr_array_index (pat, i) = program;
i++; i++;
} }
pat->len = nb_programs; pat->len = nb_programs;
if (data != end - 4) { if (data != end - 4) {
GST_ERROR ("at the end of PAT data != end - 4"); GST_ERROR ("at the end of PAT data != end - 4");
g_array_unref (pat); g_ptr_array_unref (pat);
return NULL; return NULL;
} }
@ -375,7 +392,7 @@ _parse_pat (GstMpegTsSection * section)
* #GstMpegTsPatProgram contained in the section, or %NULL if an error * #GstMpegTsPatProgram contained in the section, or %NULL if an error
* happened. Release with #g_ptr_array_unref when done. * happened. Release with #g_ptr_array_unref when done.
*/ */
GArray * GPtrArray *
gst_mpegts_section_get_pat (GstMpegTsSection * section) 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->section_type == GST_MPEGTS_SECTION_PAT, NULL);
@ -384,10 +401,10 @@ gst_mpegts_section_get_pat (GstMpegTsSection * section)
if (!section->cached_parsed) if (!section->cached_parsed)
section->cached_parsed = section->cached_parsed =
__common_desc_checks (section, 12, _parse_pat, __common_desc_checks (section, 12, _parse_pat,
(GDestroyNotify) g_array_unref); (GDestroyNotify) g_ptr_array_unref);
if (section->cached_parsed) if (section->cached_parsed)
return g_array_ref ((GArray *) section->cached_parsed); return g_ptr_array_ref ((GPtrArray *) section->cached_parsed);
return NULL; return NULL;
} }
@ -397,14 +414,18 @@ gst_mpegts_section_get_pat (GstMpegTsSection * section)
static GstMpegTsPMTStream * static GstMpegTsPMTStream *
_gst_mpegts_pmt_stream_copy (GstMpegTsPMTStream * pmt) _gst_mpegts_pmt_stream_copy (GstMpegTsPMTStream * pmt)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsPMTStream *copy;
return NULL;
copy = g_slice_dup (GstMpegTsPMTStream, pmt);
copy->descriptors = g_ptr_array_ref (pmt->descriptors);
return copy;
} }
static void static void
_gst_mpegts_pmt_stream_free (GstMpegTsPMTStream * pmt) _gst_mpegts_pmt_stream_free (GstMpegTsPMTStream * pmt)
{ {
g_array_unref (pmt->descriptors); g_ptr_array_unref (pmt->descriptors);
g_slice_free (GstMpegTsPMTStream, pmt); g_slice_free (GstMpegTsPMTStream, pmt);
} }
@ -415,14 +436,19 @@ G_DEFINE_BOXED_TYPE (GstMpegTsPMTStream, gst_mpegts_pmt_stream,
static GstMpegTsPMT * static GstMpegTsPMT *
_gst_mpegts_pmt_copy (GstMpegTsPMT * pmt) _gst_mpegts_pmt_copy (GstMpegTsPMT * pmt)
{ {
/* FIXME : IMPLEMENT */ GstMpegTsPMT *copy;
return NULL;
copy = g_slice_dup (GstMpegTsPMT, pmt);
copy->descriptors = g_ptr_array_ref (pmt->descriptors);
copy->streams = g_ptr_array_ref (pmt->streams);
return copy;
} }
static void static void
_gst_mpegts_pmt_free (GstMpegTsPMT * pmt) _gst_mpegts_pmt_free (GstMpegTsPMT * pmt)
{ {
g_array_unref (pmt->descriptors); g_ptr_array_unref (pmt->descriptors);
g_ptr_array_unref (pmt->streams); g_ptr_array_unref (pmt->streams);
g_slice_free (GstMpegTsPMT, pmt); g_slice_free (GstMpegTsPMT, pmt);
} }
@ -564,7 +590,7 @@ _parse_cat (GstMpegTsSection * section)
* #GstMpegTsDescriptor contained in the section, or %NULL if an error * #GstMpegTsDescriptor contained in the section, or %NULL if an error
* happened. Release with #g_array_unref when done. * happened. Release with #g_array_unref when done.
*/ */
GArray * GPtrArray *
gst_mpegts_section_get_cat (GstMpegTsSection * section) 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->section_type == GST_MPEGTS_SECTION_CAT, NULL);
@ -573,10 +599,10 @@ gst_mpegts_section_get_cat (GstMpegTsSection * section)
if (!section->cached_parsed) if (!section->cached_parsed)
section->cached_parsed = section->cached_parsed =
__common_desc_checks (section, 12, _parse_cat, __common_desc_checks (section, 12, _parse_cat,
(GDestroyNotify) g_array_unref); (GDestroyNotify) g_ptr_array_unref);
if (section->cached_parsed) if (section->cached_parsed)
return g_array_ref ((GArray *) section->cached_parsed); return g_ptr_array_ref ((GPtrArray *) section->cached_parsed);
return NULL; return NULL;
} }
@ -591,14 +617,14 @@ gst_mpegts_section_get_cat (GstMpegTsSection * section)
* #GstMpegTsDescriptor contained in the section, or %NULL if an error * #GstMpegTsDescriptor contained in the section, or %NULL if an error
* happened. Release with #g_array_unref when done. * happened. Release with #g_array_unref when done.
*/ */
GArray * GPtrArray *
gst_mpegts_section_get_tsdt (GstMpegTsSection * section) gst_mpegts_section_get_tsdt (GstMpegTsSection * section)
{ {
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_TSDT, NULL); g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_TSDT, NULL);
g_return_val_if_fail (section->cached_parsed || section->data, NULL); g_return_val_if_fail (section->cached_parsed || section->data, NULL);
if (section->cached_parsed) if (section->cached_parsed)
return g_array_ref ((GArray *) section->cached_parsed); return g_ptr_array_ref ((GPtrArray *) section->cached_parsed);
/* FIXME : parse TSDT */ /* FIXME : parse TSDT */
return NULL; return NULL;

View file

@ -157,6 +157,8 @@ struct _GstMpegTsSection
/* PAT */ /* PAT */
#define GST_TYPE_MPEGTS_PAT_PROGRAM (gst_mpegts_pat_program_get_type())
typedef struct _GstMpegTsPatProgram GstMpegTsPatProgram; typedef struct _GstMpegTsPatProgram GstMpegTsPatProgram;
/** /**
* GstMpegTsPatProgram: * GstMpegTsPatProgram:
@ -171,11 +173,12 @@ struct _GstMpegTsPatProgram
guint16 network_or_program_map_PID; guint16 network_or_program_map_PID;
}; };
GArray *gst_mpegts_section_get_pat (GstMpegTsSection *section); GPtrArray *gst_mpegts_section_get_pat (GstMpegTsSection *section);
GType gst_mpegts_pat_program_get_type (void);
/* CAT */ /* CAT */
GArray *gst_mpegts_section_get_cat (GstMpegTsSection *section); GPtrArray *gst_mpegts_section_get_cat (GstMpegTsSection *section);
/* PMT */ /* PMT */
typedef struct _GstMpegTsPMTStream GstMpegTsPMTStream; typedef struct _GstMpegTsPMTStream GstMpegTsPMTStream;
@ -312,7 +315,7 @@ struct _GstMpegTsPMTStream
guint8 stream_type; guint8 stream_type;
guint16 pid; guint16 pid;
GArray *descriptors; GPtrArray *descriptors;
}; };
/** /**
@ -330,7 +333,7 @@ struct _GstMpegTsPMT
{ {
guint16 pcr_pid; guint16 pcr_pid;
GArray *descriptors; GPtrArray *descriptors;
GPtrArray *streams; GPtrArray *streams;
}; };
@ -341,7 +344,7 @@ const GstMpegTsPMT *gst_mpegts_section_get_pmt (GstMpegTsSection *section);
/* TSDT */ /* TSDT */
GArray *gst_mpegts_section_get_tsdt (GstMpegTsSection *section); GPtrArray *gst_mpegts_section_get_tsdt (GstMpegTsSection *section);
/* generic */ /* generic */

View file

@ -120,20 +120,18 @@ dump_iso_639_language (GstMpegTsDescriptor * desc, guint spacing)
static void static void
dump_descriptors (GArray * descriptors, guint spacing) dump_descriptors (GPtrArray * descriptors, guint spacing)
{ {
guint i; guint i;
for (i = 0; i < descriptors->len; i++) { for (i = 0; i < descriptors->len; i++) {
GstMpegTsDescriptor *desc = GstMpegTsDescriptor *desc = g_ptr_array_index (descriptors, i);
&g_array_index (descriptors, GstMpegTsDescriptor, i);
g_printf ("%*s [descriptor 0x%02x (%s) length:%d]\n", spacing, "", g_printf ("%*s [descriptor 0x%02x (%s) length:%d]\n", spacing, "",
desc->descriptor_tag, descriptor_name (desc->descriptor_tag), desc->tag, descriptor_name (desc->tag), desc->length);
desc->descriptor_length); switch (desc->tag) {
switch (desc->descriptor_tag) {
case GST_MTS_DESC_REGISTRATION: case GST_MTS_DESC_REGISTRATION:
{ {
const guint8 *data = desc->descriptor_data + 2; const guint8 *data = desc->data + 2;
#define SAFE_CHAR(a) (g_ascii_isalnum(a) ? a : '.') #define SAFE_CHAR(a) (g_ascii_isalnum(a) ? a : '.')
g_printf ("%*s Registration : %c%c%c%c\n", spacing, "", g_printf ("%*s Registration : %c%c%c%c\n", spacing, "",
SAFE_CHAR (data[0]), SAFE_CHAR (data[1]), SAFE_CHAR (data[0]), SAFE_CHAR (data[1]),
@ -201,14 +199,14 @@ dump_descriptors (GArray * descriptors, guint spacing)
static void static void
dump_pat (GstMpegTsSection * section) dump_pat (GstMpegTsSection * section)
{ {
GArray *pat = gst_mpegts_section_get_pat (section); GPtrArray *pat = gst_mpegts_section_get_pat (section);
guint i, len; guint i, len;
len = pat->len; len = pat->len;
g_printf (" %d program(s):\n", len); g_printf (" %d program(s):\n", len);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
GstMpegTsPatProgram *patp = &g_array_index (pat, GstMpegTsPatProgram, i); GstMpegTsPatProgram *patp = g_ptr_array_index (pat, i);
g_print g_print
(" program_number:%6d (0x%04x), network_or_program_map_PID:0x%04x\n", (" program_number:%6d (0x%04x), network_or_program_map_PID:0x%04x\n",
@ -216,7 +214,7 @@ dump_pat (GstMpegTsSection * section)
patp->network_or_program_map_PID); patp->network_or_program_map_PID);
} }
g_array_unref (pat); g_ptr_array_unref (pat);
} }
static void static void