summaryrefslogtreecommitdiff
path: root/gst-libs/gst/isoff
diff options
context:
space:
mode:
authorSeungha Yang <sh.yang@lge.com>2017-06-02 23:19:36 +0900
committerReynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>2017-08-25 17:21:11 -0700
commit3db9152ec6a9a55b009dcc9d5f02ec60080af4db (patch)
tree2f739bacf463a0149853176a6437b38ebdd44c43 /gst-libs/gst/isoff
parent7d06ecb3a4f1344a1ea146c818c73a83ce137661 (diff)
downloadgstreamer-plugins-bad-3db9152ec6a9a55b009dcc9d5f02ec60080af4db.tar.gz
isoff: Add parsing moov and tfdt
To extract isobmff level timestamp, moov and tfdt parsing is required. https://bugzilla.gnome.org/show_bug.cgi?id=777825
Diffstat (limited to 'gst-libs/gst/isoff')
-rw-r--r--gst-libs/gst/isoff/gstisoff.c278
-rw-r--r--gst-libs/gst/isoff/gstisoff.h52
2 files changed, 324 insertions, 6 deletions
diff --git a/gst-libs/gst/isoff/gstisoff.c b/gst-libs/gst/isoff/gstisoff.c
index efb997407..7aef9b4cc 100644
--- a/gst-libs/gst/isoff/gstisoff.c
+++ b/gst-libs/gst/isoff/gstisoff.c
@@ -232,6 +232,34 @@ error:
}
static gboolean
+gst_isoff_tfdt_box_parse (GstTfdtBox * tfdt, GstByteReader * reader)
+{
+ gint8 version;
+
+ memset (tfdt, 0, sizeof (*tfdt));
+
+ if (gst_byte_reader_get_remaining (reader) < 4)
+ return FALSE;
+
+ version = gst_byte_reader_get_uint8_unchecked (reader);
+
+ if (!gst_byte_reader_skip (reader, 3))
+ return FALSE;
+
+ if (version == 1) {
+ if (!gst_byte_reader_get_uint64_be (reader, &tfdt->decode_time))
+ return FALSE;
+ } else {
+ guint32 dec_time = 0;
+ if (!gst_byte_reader_get_uint32_be (reader, &dec_time))
+ return FALSE;
+ tfdt->decode_time = dec_time;
+ }
+
+ return TRUE;
+}
+
+static gboolean
gst_isoff_traf_box_parse (GstTrafBox * traf, GstByteReader * reader)
{
gboolean had_tfhd = FALSE;
@@ -241,10 +269,13 @@ gst_isoff_traf_box_parse (GstTrafBox * traf, GstByteReader * reader)
g_array_set_clear_func (traf->trun,
(GDestroyNotify) gst_isoff_trun_box_clear);
+ traf->tfdt.decode_time = GST_CLOCK_TIME_NONE;
+
while (gst_byte_reader_get_remaining (reader) > 0) {
guint32 fourcc;
guint header_size;
guint64 size;
+ GstByteReader sub_reader;
if (!gst_isoff_parse_box_header (reader, &fourcc, NULL, &header_size,
&size))
@@ -254,8 +285,6 @@ gst_isoff_traf_box_parse (GstTrafBox * traf, GstByteReader * reader)
switch (fourcc) {
case GST_ISOFF_FOURCC_TFHD:{
- GstByteReader sub_reader;
-
gst_byte_reader_get_sub_reader (reader, &sub_reader,
size - header_size);
if (!gst_isoff_tfhd_box_parse (&traf->tfhd, &sub_reader))
@@ -263,8 +292,14 @@ gst_isoff_traf_box_parse (GstTrafBox * traf, GstByteReader * reader)
had_tfhd = TRUE;
break;
}
+ case GST_ISOFF_FOURCC_TFDT:{
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_tfdt_box_parse (&traf->tfdt, &sub_reader))
+ goto error;
+ break;
+ }
case GST_ISOFF_FOURCC_TRUN:{
- GstByteReader sub_reader;
GstTrunBox trun;
gst_byte_reader_get_sub_reader (reader, &sub_reader,
@@ -297,6 +332,7 @@ gst_isoff_moof_box_parse (GstByteReader * reader)
{
GstMoofBox *moof;
gboolean had_mfhd = FALSE;
+ GstByteReader sub_reader;
INITIALIZE_DEBUG_CATEGORY;
@@ -318,8 +354,6 @@ gst_isoff_moof_box_parse (GstByteReader * reader)
switch (fourcc) {
case GST_ISOFF_FOURCC_MFHD:{
- GstByteReader sub_reader;
-
gst_byte_reader_get_sub_reader (reader, &sub_reader,
size - header_size);
if (!gst_isoff_mfhd_box_parse (&moof->mfhd, &sub_reader))
@@ -328,7 +362,6 @@ gst_isoff_moof_box_parse (GstByteReader * reader)
break;
}
case GST_ISOFF_FOURCC_TRAF:{
- GstByteReader sub_reader;
GstTrafBox traf;
gst_byte_reader_get_sub_reader (reader, &sub_reader,
@@ -362,6 +395,239 @@ gst_isoff_moof_box_free (GstMoofBox * moof)
g_free (moof);
}
+static gboolean
+gst_isoff_mdhd_box_parse (GstMdhdBox * mdhd, GstByteReader * reader)
+{
+ guint8 version;
+
+ memset (mdhd, 0, sizeof (*mdhd));
+
+ if (gst_byte_reader_get_remaining (reader) < 4)
+ return FALSE;
+
+ version = gst_byte_reader_get_uint8_unchecked (reader);
+
+ if (!gst_byte_reader_skip (reader, 3))
+ return FALSE;
+
+ /* skip {creation, modification}_time, we don't have interest */
+ if (version == 1) {
+ if (!gst_byte_reader_skip (reader, 16))
+ return FALSE;
+ } else {
+ if (!gst_byte_reader_skip (reader, 8))
+ return FALSE;
+ }
+
+ if (!gst_byte_reader_get_uint32_be (reader, &mdhd->timescale))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_isoff_hdlr_box_parse (GstHdlrBox * hdlr, GstByteReader * reader)
+{
+ memset (hdlr, 0, sizeof (*hdlr));
+
+ if (gst_byte_reader_get_remaining (reader) < 4)
+ return FALSE;
+
+ /* version & flag */
+ if (!gst_byte_reader_skip (reader, 4))
+ return FALSE;
+
+ /* pre_defined = 0 */
+ if (!gst_byte_reader_skip (reader, 4))
+ return FALSE;
+
+ if (!gst_byte_reader_get_uint32_le (reader, &hdlr->handler_type))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_isoff_mdia_box_parse (GstMdiaBox * mdia, GstByteReader * reader)
+{
+ gboolean had_mdhd = FALSE, had_hdlr = FALSE;
+ while (gst_byte_reader_get_remaining (reader) > 0) {
+ guint32 fourcc;
+ guint header_size;
+ guint64 size;
+ GstByteReader sub_reader;
+
+ if (!gst_isoff_parse_box_header (reader, &fourcc, NULL, &header_size,
+ &size))
+ return FALSE;
+ if (gst_byte_reader_get_remaining (reader) < size - header_size)
+ return FALSE;
+
+ switch (fourcc) {
+ case GST_ISOFF_FOURCC_MDHD:{
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_mdhd_box_parse (&mdia->mdhd, &sub_reader))
+ return FALSE;
+
+ had_mdhd = TRUE;
+ break;
+ }
+ case GST_ISOFF_FOURCC_HDLR:{
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_hdlr_box_parse (&mdia->hdlr, &sub_reader))
+ return FALSE;
+
+ had_hdlr = TRUE;
+ break;
+ }
+ default:
+ gst_byte_reader_skip (reader, size - header_size);
+ break;
+ }
+ }
+
+ if (!had_mdhd || !had_hdlr)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_isoff_tkhd_box_parse (GstTkhdBox * tkhd, GstByteReader * reader)
+{
+ guint8 version;
+
+ memset (tkhd, 0, sizeof (*tkhd));
+
+ if (gst_byte_reader_get_remaining (reader) < 4)
+ return FALSE;
+
+ if (!gst_byte_reader_get_uint8 (reader, &version))
+ return FALSE;
+
+ if (!gst_byte_reader_skip (reader, 3))
+ return FALSE;
+
+ /* skip {creation, modification}_time, we don't have interest */
+ if (version == 1) {
+ if (!gst_byte_reader_skip (reader, 16))
+ return FALSE;
+ } else {
+ if (!gst_byte_reader_skip (reader, 8))
+ return FALSE;
+ }
+
+ if (!gst_byte_reader_get_uint32_be (reader, &tkhd->track_id))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_isoff_trak_box_parse (GstTrakBox * trak, GstByteReader * reader)
+{
+ gboolean had_mdia = FALSE, had_tkhd = FALSE;
+ while (gst_byte_reader_get_remaining (reader) > 0) {
+ guint32 fourcc;
+ guint header_size;
+ guint64 size;
+ GstByteReader sub_reader;
+
+ if (!gst_isoff_parse_box_header (reader, &fourcc, NULL, &header_size,
+ &size))
+ return FALSE;
+ if (gst_byte_reader_get_remaining (reader) < size - header_size)
+ return FALSE;
+
+ switch (fourcc) {
+ case GST_ISOFF_FOURCC_MDIA:{
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_mdia_box_parse (&trak->mdia, &sub_reader))
+ return FALSE;
+
+ had_mdia = TRUE;
+ break;
+ }
+ case GST_ISOFF_FOURCC_TKHD:{
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_tkhd_box_parse (&trak->tkhd, &sub_reader))
+ return FALSE;
+
+ had_tkhd = TRUE;
+ break;
+ }
+ default:
+ gst_byte_reader_skip (reader, size - header_size);
+ break;
+ }
+ }
+
+ if (!had_tkhd || !had_mdia)
+ return FALSE;
+
+ return TRUE;
+}
+
+GstMoovBox *
+gst_isoff_moov_box_parse (GstByteReader * reader)
+{
+ GstMoovBox *moov;
+ gboolean had_trak = FALSE;
+ moov = g_new0 (GstMoovBox, 1);
+ moov->trak = g_array_new (FALSE, FALSE, sizeof (GstTrakBox));
+
+ while (gst_byte_reader_get_remaining (reader) > 0) {
+ guint32 fourcc;
+ guint header_size;
+ guint64 size;
+
+ if (!gst_isoff_parse_box_header (reader, &fourcc, NULL, &header_size,
+ &size))
+ goto error;
+ if (gst_byte_reader_get_remaining (reader) < size - header_size)
+ goto error;
+
+ switch (fourcc) {
+ case GST_ISOFF_FOURCC_TRAK:{
+ GstByteReader sub_reader;
+ GstTrakBox trak;
+
+ gst_byte_reader_get_sub_reader (reader, &sub_reader,
+ size - header_size);
+ if (!gst_isoff_trak_box_parse (&trak, &sub_reader))
+ goto error;
+
+ had_trak = TRUE;
+ g_array_append_val (moov->trak, trak);
+ break;
+ }
+ default:
+ gst_byte_reader_skip (reader, size - header_size);
+ break;
+ }
+ }
+
+ if (!had_trak)
+ goto error;
+
+ return moov;
+
+error:
+ gst_isoff_moov_box_free (moov);
+ return NULL;
+}
+
+void
+gst_isoff_moov_box_free (GstMoovBox * moov)
+{
+ g_array_free (moov->trak, TRUE);
+ g_free (moov);
+}
+
void
gst_isoff_sidx_parser_init (GstSidxParser * parser)
{
diff --git a/gst-libs/gst/isoff/gstisoff.h b/gst-libs/gst/isoff/gstisoff.h
index ee160aa10..c2f03909b 100644
--- a/gst-libs/gst/isoff/gstisoff.h
+++ b/gst-libs/gst/isoff/gstisoff.h
@@ -45,9 +45,20 @@ gboolean gst_isoff_parse_box_header (GstByteReader * reader, guint32 * type, gui
#define GST_ISOFF_FOURCC_TFHD GST_MAKE_FOURCC('t','f','h','d')
#define GST_ISOFF_FOURCC_TRUN GST_MAKE_FOURCC('t','r','u','n')
#define GST_ISOFF_FOURCC_TRAF GST_MAKE_FOURCC('t','r','a','f')
+#define GST_ISOFF_FOURCC_TFDT GST_MAKE_FOURCC('t','f','d','t')
#define GST_ISOFF_FOURCC_MDAT GST_MAKE_FOURCC('m','d','a','t')
+#define GST_ISOFF_FOURCC_MOOV GST_MAKE_FOURCC('m','o','o','v')
+#define GST_ISOFF_FOURCC_TRAK GST_MAKE_FOURCC('t','r','a','k')
+#define GST_ISOFF_FOURCC_TKHD GST_MAKE_FOURCC('t','k','h','d')
+#define GST_ISOFF_FOURCC_MDIA GST_MAKE_FOURCC('m','d','i','a')
+#define GST_ISOFF_FOURCC_MDHD GST_MAKE_FOURCC('m','d','h','d')
+#define GST_ISOFF_FOURCC_HDLR GST_MAKE_FOURCC('h','d','l','r')
#define GST_ISOFF_FOURCC_SIDX GST_MAKE_FOURCC('s','i','d','x')
+/* handler type */
+#define GST_ISOFF_FOURCC_SOUN GST_MAKE_FOURCC('s','o','u','n')
+#define GST_ISOFF_FOURCC_VIDE GST_MAKE_FOURCC('v','i','d','e')
+
#define GST_ISOFF_SAMPLE_FLAGS_IS_LEADING(flags) (((flags) >> 26) & 0x03)
#define GST_ISOFF_SAMPLE_FLAGS_SAMPLE_DEPENDS_ON(flags) (((flags) >> 24) & 0x03)
#define GST_ISOFF_SAMPLE_FLAGS_SAMPLE_IS_DEPENDED_ON(flags) (((flags) >> 22) & 0x03)
@@ -122,9 +133,15 @@ typedef struct _GstTrunSample
} sample_composition_time_offset;
} GstTrunSample;
+typedef struct _GstTdftBox
+{
+ guint64 decode_time;
+} GstTfdtBox;
+
typedef struct _GstTrafBox
{
GstTfhdBox tfhd;
+ GstTfdtBox tfdt;
GArray *trun;
} GstTrafBox;
@@ -137,6 +154,41 @@ typedef struct _GstMoofBox
GstMoofBox * gst_isoff_moof_box_parse (GstByteReader *reader);
void gst_isoff_moof_box_free (GstMoofBox *moof);
+typedef struct _GstTkhdBox
+{
+ guint32 track_id;
+} GstTkhdBox;
+
+typedef struct _GstMdhdBox
+{
+ guint32 timescale;
+} GstMdhdBox;
+
+typedef struct _GstHdlrBox
+{
+ guint32 handler_type;
+} GstHdlrBox;
+
+typedef struct _GstMdiaBox
+{
+ GstMdhdBox mdhd;
+ GstHdlrBox hdlr;
+} GstMdiaBox;
+
+typedef struct _GstTrakBox
+{
+ GstTkhdBox tkhd;
+ GstMdiaBox mdia;
+} GstTrakBox;
+
+typedef struct _GstMoovBox
+{
+ GArray *trak;
+} GstMoovBox;
+
+GstMoovBox * gst_isoff_moov_box_parse (GstByteReader *reader);
+void gst_isoff_moov_box_free (GstMoovBox *moov);
+
typedef struct _GstSidxBoxEntry
{
gboolean ref_type;