/* * Microsoft Smooth-Streaming fragment parsing library * * gstmssfragmentparser.h * * Copyright (C) 2016 Igalia S.L * Copyright (C) 2016 Metrological * Author: Philippe Normand <philn@igalia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library (COPYING); if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "gstmssfragmentparser.h" #include <gst/base/gstbytereader.h> #include <string.h> GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug); #define GST_CAT_DEFAULT mssdemux_debug void gst_mss_fragment_parser_init (GstMssFragmentParser * parser) { parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_INIT; } void gst_mss_fragment_parser_clear (GstMssFragmentParser * parser) { if (parser->moof) gst_isoff_moof_box_free (parser->moof); parser->moof = NULL; parser->current_fourcc = 0; } 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; }