mpegts: atsc: add STT table parsing

Adds the system time table structure and functions for convenient parsing of
it and for getting the UTC datetime that it represents. Also adds its
information dumping to the ts-parser example

https://bugzilla.gnome.org/show_bug.cgi?id=730435
This commit is contained in:
Thiago Santos 2014-05-22 01:47:48 -03:00 committed by Edward Hervey
parent 0c0379e8f0
commit 0c6bb561e0
5 changed files with 175 additions and 1 deletions

View file

@ -641,3 +641,114 @@ gst_mpegts_section_get_atsc_ett (GstMpegTsSection * section)
return (const GstMpegTsAtscETT *) section->cached_parsed;
}
/* STT */
static GstMpegTsAtscSTT *
_gst_mpegts_atsc_stt_copy (GstMpegTsAtscSTT * stt)
{
GstMpegTsAtscSTT *copy;
copy = g_slice_dup (GstMpegTsAtscSTT, stt);
copy->descriptors = g_ptr_array_ref (stt->descriptors);
return copy;
}
static void
_gst_mpegts_atsc_stt_free (GstMpegTsAtscSTT * stt)
{
if (stt->descriptors)
g_ptr_array_unref (stt->descriptors);
g_slice_free (GstMpegTsAtscSTT, stt);
}
G_DEFINE_BOXED_TYPE (GstMpegTsAtscSTT, gst_mpegts_atsc_stt,
(GBoxedCopyFunc) _gst_mpegts_atsc_stt_copy,
(GFreeFunc) _gst_mpegts_atsc_stt_free);
static gpointer
_parse_atsc_stt (GstMpegTsSection * section)
{
GstMpegTsAtscSTT *stt = NULL;
guint8 *data, *end;
guint16 daylight_saving;
stt = g_slice_new0 (GstMpegTsAtscSTT);
data = section->data;
end = data + section->section_length;
/* Skip already parsed data */
data += 8;
stt->protocol_version = GST_READ_UINT8 (data);
data += 1;
stt->system_time = GST_READ_UINT32_BE (data);
data += 4;
stt->gps_utc_offset = GST_READ_UINT8 (data);
data += 1;
daylight_saving = GST_READ_UINT16_BE (data);
data += 2;
stt->ds_status = daylight_saving >> 15;
stt->ds_dayofmonth = (daylight_saving >> 8) & 0x1F;
stt->ds_hour = daylight_saving & 0xFF;
stt->descriptors = gst_mpegts_parse_descriptors (data, end - data - 4);
if (stt->descriptors == NULL)
goto error;
return (gpointer) stt;
error:
if (stt)
_gst_mpegts_atsc_stt_free (stt);
return NULL;
}
/**
* gst_mpegts_section_get_atsc_stt:
* @section: a #GstMpegTsSection of type %GST_MPEGTS_SECTION_ATSC_STT
*
* Returns the #GstMpegTsAtscSTT contained in the @section.
*
* Returns: The #GstMpegTsAtscSTT contained in the section, or %NULL if an error
* happened.
*/
const GstMpegTsAtscSTT *
gst_mpegts_section_get_atsc_stt (GstMpegTsSection * section)
{
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_ATSC_STT,
NULL);
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
if (!section->cached_parsed)
section->cached_parsed =
__common_section_checks (section, 20, _parse_atsc_stt,
(GDestroyNotify) _gst_mpegts_atsc_stt_free);
return (const GstMpegTsAtscSTT *) section->cached_parsed;
}
#define GPS_TO_UTC_TICKS G_GINT64_CONSTANT(315964800)
static GstDateTime *
_gst_mpegts_atsc_gps_time_to_datetime (guint32 systemtime, guint8 gps_offset)
{
return gst_date_time_new_from_unix_epoch_utc (systemtime - gps_offset +
GPS_TO_UTC_TICKS);
}
GstDateTime *
gst_mpegts_atsc_stt_get_datetime_utc (GstMpegTsAtscSTT * stt)
{
if (stt->utc_datetime == NULL)
stt->utc_datetime = _gst_mpegts_atsc_gps_time_to_datetime (stt->system_time,
stt->gps_utc_offset);
if (stt->utc_datetime)
return gst_date_time_ref (stt->utc_datetime);
return NULL;
}

View file

@ -216,6 +216,36 @@ GType gst_mpegts_atsc_ett_get_type (void);
const GstMpegTsAtscETT *gst_mpegts_section_get_atsc_ett (GstMpegTsSection *section);
/* STT */
#define GST_TYPE_MPEGTS_ATSC_STT (gst_mpegts_atsc_stt_get_type ())
typedef struct _GstMpegTsAtscSTT GstMpegTsAtscSTT;
/**
* GstMpegTsAtscSTT:
*
* System Time Table (A65)
*
*/
struct _GstMpegTsAtscSTT
{
guint8 protocol_version;
guint32 system_time;
guint8 gps_utc_offset;
gboolean ds_status;
guint8 ds_dayofmonth;
guint8 ds_hour;
GPtrArray *descriptors;
GstDateTime *utc_datetime;
};
GType gst_mpegts_atsc_stt_get_type (void);
const GstMpegTsAtscSTT * gst_mpegts_section_get_atsc_stt (GstMpegTsSection * section);
/* FIXME receive a non-const parameter but we only provide a const getter */
GstDateTime * gst_mpegts_atsc_stt_get_datetime_utc (GstMpegTsAtscSTT * stt);
G_END_DECLS
#endif /* GST_MPEGTS_SECTION_H */

View file

@ -1067,6 +1067,10 @@ _identify_section (guint16 pid, guint8 table_id)
/* FIXME check pids reported on the MGT to confirm expectations */
return GST_MPEGTS_SECTION_ATSC_ETT;
/* FIXME : FILL */
case GST_MTS_TABLE_ID_ATSC_SYSTEM_TIME:
if (pid == 0x1ffb)
return GST_MPEGTS_SECTION_ATSC_STT;
break;
default:
/* Handle ranges */
if (table_id >= GST_MTS_TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT &&

View file

@ -55,6 +55,7 @@ GType gst_mpegts_section_get_type (void);
* @GST_MPEGTS_SECTION_ATSC_CVCT: ATSC Cable Virtual Channel Table (A65)
* @GST_MPEGTS_SECTION_ATSC_MGT: ATSC Master Guide Table (A65)
* @GST_MPEGTS_SECTION_ATSC_ETT: ATSC Extended Text Table (A65)
* @GST_MPEGTS_SECTION_ATSC_STT: ATSC System Time Table (A65)
*
* Types of #GstMpegTsSection that the library handles.
*/
@ -73,7 +74,8 @@ typedef enum {
GST_MPEGTS_SECTION_ATSC_TVCT,
GST_MPEGTS_SECTION_ATSC_CVCT,
GST_MPEGTS_SECTION_ATSC_MGT,
GST_MPEGTS_SECTION_ATSC_ETT
GST_MPEGTS_SECTION_ATSC_ETT,
GST_MPEGTS_SECTION_ATSC_STT
} GstMpegTsSectionType;
/**

View file

@ -639,6 +639,30 @@ dump_ett (GstMpegTsSection * section)
}
}
static void
dump_stt (GstMpegTsSection * section)
{
const GstMpegTsAtscSTT *stt = gst_mpegts_section_get_atsc_stt (section);
GstDateTime *dt;
gchar *dt_str = NULL;
g_assert (stt);
dt = gst_mpegts_atsc_stt_get_datetime_utc ((GstMpegTsAtscSTT *) stt);
if (dt)
dt_str = gst_date_time_to_iso8601_string (dt);
g_printf (" protocol_version : 0x%04x\n", stt->protocol_version);
g_printf (" system_time : 0x%08x\n", stt->system_time);
g_printf (" gps_utc_offset : %d\n", stt->gps_utc_offset);
g_printf (" daylight saving : %d day:%d hour:%d\n", stt->ds_status,
stt->ds_dayofmonth, stt->ds_hour);
g_printf (" utc datetime : %s", dt_str);
g_free (dt_str);
gst_date_time_unref (dt);
}
static void
dump_nit (GstMpegTsSection * section)
{
@ -839,6 +863,9 @@ dump_section (GstMpegTsSection * section)
case GST_MPEGTS_SECTION_ATSC_ETT:
dump_ett (section);
break;
case GST_MPEGTS_SECTION_ATSC_STT:
dump_stt (section);
break;
default:
g_printf (" Unknown section type\n");
break;