mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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:
parent
0c0379e8f0
commit
0c6bb561e0
5 changed files with 175 additions and 1 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue