static gboolean gst_isoff_traf_box_parse (GstTrafBox * traf, GstByteReader * reader) { gboolean had_tfhd = FALSE; memset (traf, 0, sizeof (*traf)); traf->trun = g_array_new (FALSE, FALSE, sizeof (GstTrunBox)); g_array_set_clear_func (traf->trun, (GDestroyNotify) gst_isoff_trun_box_clear); 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_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)) goto error; had_tfhd = TRUE; break; } case GST_ISOFF_FOURCC_TRUN:{ GstByteReader sub_reader; GstTrunBox trun; gst_byte_reader_get_sub_reader (reader, &sub_reader, size - header_size); if (!gst_isoff_trun_box_parse (&trun, &sub_reader)) goto error; g_array_append_val (traf->trun, trun); break; } default: gst_byte_reader_skip (reader, size - header_size); break; } } if (!had_tfhd) goto error; return TRUE; error: gst_isoff_traf_box_clear (traf); return FALSE; }
GstMoofBox * gst_isoff_moof_box_parse (GstByteReader * reader) { GstMoofBox *moof; gboolean had_mfhd = FALSE; moof = g_new0 (GstMoofBox, 1); moof->traf = g_array_new (FALSE, FALSE, sizeof (GstTrafBox)); g_array_set_clear_func (moof->traf, (GDestroyNotify) gst_isoff_traf_box_clear); 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_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)) goto error; had_mfhd = TRUE; break; } case GST_ISOFF_FOURCC_TRAF:{ GstByteReader sub_reader; GstTrafBox traf; gst_byte_reader_get_sub_reader (reader, &sub_reader, size - header_size); if (!gst_isoff_traf_box_parse (&traf, &sub_reader)) goto error; g_array_append_val (moof->traf, traf); break; } default: gst_byte_reader_skip (reader, size - header_size); break; } } if (!had_mfhd) goto error; return moof; error: gst_isoff_moof_box_free (moof); return NULL; }
GstIsoffParserResult gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer, guint * consumed) { GstIsoffParserResult res = GST_ISOFF_PARSER_OK; GstByteReader reader; GstMapInfo info; guint32 fourcc; if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) { *consumed = 0; return GST_ISOFF_PARSER_ERROR; } gst_byte_reader_init (&reader, info.data, info.size); if (parser->status == GST_ISOFF_SIDX_PARSER_INIT) { if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, NULL, &parser->size)) goto done; if (fourcc != GST_ISOFF_FOURCC_SIDX) { res = GST_ISOFF_PARSER_UNEXPECTED; gst_byte_reader_set_pos (&reader, 0); goto done; } if (parser->size == 0) { res = GST_ISOFF_PARSER_ERROR; gst_byte_reader_set_pos (&reader, 0); goto done; } /* Try again once we have enough data for the FullBox header */ if (gst_byte_reader_get_remaining (&reader) < 4) { gst_byte_reader_set_pos (&reader, 0); goto done; } } res = gst_isoff_sidx_parser_parse (parser, &reader, consumed); done: gst_buffer_unmap (buffer, &info); return res; }
gboolean gst_mss_fragment_parser_add_buffer (GstMssFragmentParser * parser, GstBuffer * buffer) { GstByteReader reader; GstMapInfo info; guint64 size; guint32 fourcc; guint header_size; gboolean error = FALSE; if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) { return FALSE; } gst_byte_reader_init (&reader, info.data, info.size); GST_TRACE ("Total buffer size: %u", gst_byte_reader_get_size (&reader)); do { parser->current_fourcc = 0; if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, &header_size, &size)) { break; } parser->current_fourcc = fourcc; GST_LOG ("box %" GST_FOURCC_FORMAT " size %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size); parser->current_fourcc = fourcc; if (parser->current_fourcc == GST_ISOFF_FOURCC_MOOF) { GstByteReader sub_reader; g_assert (parser->moof == NULL); gst_byte_reader_get_sub_reader (&reader, &sub_reader, size - header_size); parser->moof = gst_isoff_moof_box_parse (&sub_reader); if (parser->moof == NULL) { GST_ERROR ("Failed to parse moof"); error = TRUE; } } else if (parser->current_fourcc == GST_ISOFF_FOURCC_MDAT) { goto beach; } else { gst_byte_reader_skip (&reader, size - header_size); } } while (gst_byte_reader_get_remaining (&reader) > 0); beach: /* Do sanity check */ if (parser->current_fourcc != GST_ISOFF_FOURCC_MDAT || !parser->moof || parser->moof->traf->len == 0) error = TRUE; if (!error) { GstTrafBox *traf = &g_array_index (parser->moof->traf, GstTrafBox, 0); if (!traf->tfxd) { GST_ERROR ("no tfxd box"); error = TRUE; } else if (!traf->tfrf) { GST_ERROR ("no tfrf box"); error = TRUE; } } if (!error) parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED; GST_LOG ("Fragment parsing successful: %s", error ? "no" : "yes"); gst_buffer_unmap (buffer, &info); return !error; }