diff options
author | Seungha Yang <sh.yang@lge.com> | 2017-06-02 23:19:36 +0900 |
---|---|---|
committer | Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com> | 2017-08-25 17:21:11 -0700 |
commit | 3db9152ec6a9a55b009dcc9d5f02ec60080af4db (patch) | |
tree | 2f739bacf463a0149853176a6437b38ebdd44c43 /gst-libs/gst/isoff | |
parent | 7d06ecb3a4f1344a1ea146c818c73a83ce137661 (diff) | |
download | gstreamer-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.c | 278 | ||||
-rw-r--r-- | gst-libs/gst/isoff/gstisoff.h | 52 |
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; |