mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
mpegts: atsc: add ETT structures and parsing
ETT (extended text table) contains ATSC text information with descriptions of virtual channels and events. The text can be internationalized and also compressed. https://bugzilla.gnome.org/show_bug.cgi?id=730435
This commit is contained in:
parent
32d8022820
commit
7ced36eccd
4 changed files with 272 additions and 1 deletions
|
@ -396,3 +396,222 @@ gst_mpegts_section_get_atsc_mgt (GstMpegTsSection * section)
|
|||
|
||||
return (const GstMpegTsAtscMGT *) section->cached_parsed;
|
||||
}
|
||||
|
||||
static GstMpegTsAtscStringSegment *
|
||||
_gst_mpegts_atsc_string_segment_copy (GstMpegTsAtscStringSegment * seg)
|
||||
{
|
||||
GstMpegTsAtscStringSegment *copy;
|
||||
|
||||
copy = g_slice_dup (GstMpegTsAtscStringSegment, seg);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_atsc_string_segment_free (GstMpegTsAtscStringSegment * seg)
|
||||
{
|
||||
if (seg->cached_string)
|
||||
g_free (seg->cached_string);
|
||||
g_slice_free (GstMpegTsAtscStringSegment, seg);
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_atsc_string_segment_decode_string (GstMpegTsAtscStringSegment * seg)
|
||||
{
|
||||
g_return_if_fail (seg->cached_string == NULL);
|
||||
|
||||
if (seg->compression_type != 0) {
|
||||
GST_FIXME ("Compressed strings not yet supported");
|
||||
return;
|
||||
}
|
||||
/* FIXME check encoding */
|
||||
|
||||
seg->cached_string =
|
||||
g_strndup ((gchar *) seg->compressed_data, seg->compressed_data_size);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gst_mpegts_atsc_string_segment_get_string (GstMpegTsAtscStringSegment * seg)
|
||||
{
|
||||
if (!seg->cached_string)
|
||||
_gst_mpegts_atsc_string_segment_decode_string (seg);
|
||||
|
||||
return seg->cached_string;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegTsAtscStringSegment, gst_mpegts_atsc_string_segment,
|
||||
(GBoxedCopyFunc) _gst_mpegts_atsc_string_segment_copy,
|
||||
(GFreeFunc) _gst_mpegts_atsc_string_segment_free);
|
||||
|
||||
static GstMpegTsAtscMultString *
|
||||
_gst_mpegts_atsc_mult_string_copy (GstMpegTsAtscMultString * mstring)
|
||||
{
|
||||
GstMpegTsAtscMultString *copy;
|
||||
|
||||
copy = g_slice_dup (GstMpegTsAtscMultString, mstring);
|
||||
copy->segments = g_ptr_array_ref (mstring->segments);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_atsc_mult_string_free (GstMpegTsAtscMultString * mstring)
|
||||
{
|
||||
g_ptr_array_unref (mstring->segments);
|
||||
g_slice_free (GstMpegTsAtscMultString, mstring);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegTsAtscMultString, gst_mpegts_atsc_mult_string,
|
||||
(GBoxedCopyFunc) _gst_mpegts_atsc_mult_string_copy,
|
||||
(GFreeFunc) _gst_mpegts_atsc_mult_string_free);
|
||||
|
||||
static GstMpegTsAtscETT *
|
||||
_gst_mpegts_atsc_ett_copy (GstMpegTsAtscETT * ett)
|
||||
{
|
||||
GstMpegTsAtscETT *copy;
|
||||
|
||||
copy = g_slice_dup (GstMpegTsAtscETT, ett);
|
||||
copy->messages = g_ptr_array_ref (ett->messages);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_atsc_ett_free (GstMpegTsAtscETT * ett)
|
||||
{
|
||||
g_ptr_array_unref (ett->messages);
|
||||
g_slice_free (GstMpegTsAtscETT, ett);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegTsAtscETT, gst_mpegts_atsc_ett,
|
||||
(GBoxedCopyFunc) _gst_mpegts_atsc_ett_copy,
|
||||
(GFreeFunc) _gst_mpegts_atsc_ett_free);
|
||||
|
||||
static gpointer
|
||||
_parse_ett (GstMpegTsSection * section)
|
||||
{
|
||||
GstMpegTsAtscETT *ett = NULL;
|
||||
guint i = 0;
|
||||
guint8 *data, *end;
|
||||
guint8 num_strings;
|
||||
|
||||
ett = g_slice_new0 (GstMpegTsAtscETT);
|
||||
|
||||
data = section->data;
|
||||
end = data + section->section_length;
|
||||
|
||||
/* Skip already parsed data */
|
||||
data += 8;
|
||||
|
||||
ett->protocol_version = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
ett->etm_id = GST_READ_UINT32_BE (data);
|
||||
data += 4;
|
||||
|
||||
ett->messages = g_ptr_array_new_with_free_func ((GDestroyNotify)
|
||||
_gst_mpegts_atsc_mult_string_free);
|
||||
|
||||
if (end - data > 4) {
|
||||
/* 1 is the minimum entry size, so no need to check here */
|
||||
num_strings = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
|
||||
for (i = 0; i < num_strings; i++) {
|
||||
GstMpegTsAtscMultString *mstring;
|
||||
guint8 num_segments;
|
||||
gint j;
|
||||
|
||||
mstring = g_slice_new0 (GstMpegTsAtscMultString);
|
||||
g_ptr_array_add (ett->messages, mstring);
|
||||
mstring->segments =
|
||||
g_ptr_array_new_full (num_strings,
|
||||
(GDestroyNotify) _gst_mpegts_atsc_string_segment_free);
|
||||
|
||||
/* each entry needs at least 4 bytes (lang code and segments number */
|
||||
if (end - data < 4 + 4) {
|
||||
GST_WARNING ("PID %d invalid ETT entry length %d",
|
||||
section->pid, (gint) (end - 4 - data));
|
||||
goto error;
|
||||
}
|
||||
|
||||
mstring->iso_639_langcode[0] = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
mstring->iso_639_langcode[1] = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
mstring->iso_639_langcode[2] = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
num_segments = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
|
||||
for (j = 0; j < num_segments; j++) {
|
||||
GstMpegTsAtscStringSegment *seg;
|
||||
|
||||
seg = g_slice_new0 (GstMpegTsAtscStringSegment);
|
||||
g_ptr_array_add (mstring->segments, seg);
|
||||
|
||||
/* each entry needs at least 4 bytes (lang code and segments number */
|
||||
if (end - data < 3 + 4) {
|
||||
GST_WARNING ("PID %d invalid ETT entry length %d",
|
||||
section->pid, (gint) (end - 4 - data));
|
||||
goto error;
|
||||
}
|
||||
|
||||
seg->compression_type = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
seg->mode = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
seg->compressed_data_size = GST_READ_UINT8 (data);
|
||||
data += 1;
|
||||
|
||||
if (end - data < seg->compressed_data_size + 4) {
|
||||
GST_WARNING ("PID %d invalid ETT entry length %d",
|
||||
section->pid, (gint) (end - 4 - data));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (seg->compressed_data_size)
|
||||
seg->compressed_data = data;
|
||||
data += seg->compressed_data_size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (data != end - 4) {
|
||||
GST_WARNING ("PID %d invalid ETT parsed %d length %d",
|
||||
section->pid, (gint) (data - section->data), section->section_length);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return (gpointer) ett;
|
||||
|
||||
error:
|
||||
if (ett)
|
||||
_gst_mpegts_atsc_ett_free (ett);
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpegts_section_get_atsc_ett:
|
||||
* @section: a #GstMpegTsSection of type %GST_MPEGTS_SECTION_ATSC_ETT
|
||||
*
|
||||
* Returns the #GstMpegTsAtscETT contained in the @section.
|
||||
*
|
||||
* Returns: The #GstMpegTsAtscETT contained in the section, or %NULL if an error
|
||||
* happened.
|
||||
*/
|
||||
const GstMpegTsAtscETT *
|
||||
gst_mpegts_section_get_atsc_ett (GstMpegTsSection * section)
|
||||
{
|
||||
g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_ATSC_ETT,
|
||||
NULL);
|
||||
g_return_val_if_fail (section->cached_parsed || section->data, NULL);
|
||||
|
||||
if (!section->cached_parsed)
|
||||
section->cached_parsed = __common_section_checks (section, 17, _parse_ett,
|
||||
(GDestroyNotify) _gst_mpegts_atsc_ett_free);
|
||||
|
||||
return (const GstMpegTsAtscETT *) section->cached_parsed;
|
||||
}
|
||||
|
|
|
@ -169,6 +169,53 @@ GType gst_mpegts_atsc_mgt_table_get_type (void);
|
|||
|
||||
const GstMpegTsAtscMGT * gst_mpegts_section_get_atsc_mgt (GstMpegTsSection * section);
|
||||
|
||||
/* ETT */
|
||||
|
||||
#define GST_TYPE_MPEGTS_ATSC_STRING_SEGMENT (gst_mpegts_atsc_string_segment_get_type())
|
||||
#define GST_TYPE_MPEGTS_ATSC_MULT_STRING (gst_mpegts_atsc_mult_string_get_type())
|
||||
#define GST_TYPE_MPEGTS_ATSC_ETT (gst_mpegts_atsc_ett_get_type())
|
||||
|
||||
typedef struct _GstMpegTsAtscStringSegment GstMpegTsAtscStringSegment;
|
||||
typedef struct _GstMpegTsAtscMultString GstMpegTsAtscMultString;
|
||||
typedef struct _GstMpegTsAtscETT GstMpegTsAtscETT;
|
||||
|
||||
struct _GstMpegTsAtscStringSegment {
|
||||
guint8 compression_type;
|
||||
guint8 mode;
|
||||
guint8 compressed_data_size;
|
||||
guint8 *compressed_data;
|
||||
|
||||
gchar *cached_string;
|
||||
};
|
||||
|
||||
const gchar * gst_mpegts_atsc_string_segment_get_string (GstMpegTsAtscStringSegment * seg);
|
||||
|
||||
struct _GstMpegTsAtscMultString {
|
||||
gchar iso_639_langcode[4];
|
||||
GPtrArray *segments;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstMpegTsAtscETT:
|
||||
* @events: (element-type FIXME): List of texts
|
||||
*
|
||||
* Extended Text Table (ATSC)
|
||||
*
|
||||
*/
|
||||
struct _GstMpegTsAtscETT
|
||||
{
|
||||
guint16 protocol_version;
|
||||
guint32 etm_id;
|
||||
|
||||
GPtrArray *messages;
|
||||
};
|
||||
|
||||
GType gst_mpegts_atsc_string_segment_get_type (void);
|
||||
GType gst_mpegts_atsc_mult_string_get_type (void);
|
||||
GType gst_mpegts_atsc_ett_get_type (void);
|
||||
|
||||
const GstMpegTsAtscETT *gst_mpegts_section_get_atsc_ett (GstMpegTsSection *section);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_MPEGTS_SECTION_H */
|
||||
|
|
|
@ -1063,6 +1063,9 @@ _identify_section (guint16 pid, guint8 table_id)
|
|||
case GST_MTS_TABLE_ID_ATSC_EVENT_INFORMATION:
|
||||
/* FIXME check pids reported on the MGT to confirm expectations */
|
||||
return GST_MPEGTS_SECTION_EIT;
|
||||
case GST_MTS_TABLE_ID_ATSC_CHANNEL_OR_EVENT_EXTENDED_TEXT:
|
||||
/* FIXME check pids reported on the MGT to confirm expectations */
|
||||
return GST_MPEGTS_SECTION_ATSC_ETT;
|
||||
/* FIXME : FILL */
|
||||
default:
|
||||
/* Handle ranges */
|
||||
|
|
|
@ -54,6 +54,7 @@ GType gst_mpegts_section_get_type (void);
|
|||
* @GST_MPEGTS_SECTION_ATSC_TVCT: ATSC Terrestrial Virtual Channel Table (A65)
|
||||
* @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)
|
||||
*
|
||||
* Types of #GstMpegTsSection that the library handles.
|
||||
*/
|
||||
|
@ -71,7 +72,8 @@ typedef enum {
|
|||
GST_MPEGTS_SECTION_TOT,
|
||||
GST_MPEGTS_SECTION_ATSC_TVCT,
|
||||
GST_MPEGTS_SECTION_ATSC_CVCT,
|
||||
GST_MPEGTS_SECTION_ATSC_MGT
|
||||
GST_MPEGTS_SECTION_ATSC_MGT,
|
||||
GST_MPEGTS_SECTION_ATSC_ETT
|
||||
} GstMpegTsSectionType;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue