1 /*
2 * Microsoft Smooth-Streaming fragment parsing library
3 *
4 * gstmssfragmentparser.h
5 *
6 * Copyright (C) 2016 Igalia S.L
7 * Copyright (C) 2016 Metrological
8 * Author: Philippe Normand <philn@igalia.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library (COPYING); if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
24 */
25
26 #include "gstmssfragmentparser.h"
27 #include <gst/base/gstbytereader.h>
28 #include <string.h>
29
30 GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
31 #define GST_CAT_DEFAULT mssdemux_debug
32
33 void
gst_mss_fragment_parser_init(GstMssFragmentParser * parser)34 gst_mss_fragment_parser_init (GstMssFragmentParser * parser)
35 {
36 parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_INIT;
37 }
38
39 void
gst_mss_fragment_parser_clear(GstMssFragmentParser * parser)40 gst_mss_fragment_parser_clear (GstMssFragmentParser * parser)
41 {
42 if (parser->moof)
43 gst_isoff_moof_box_free (parser->moof);
44 parser->moof = NULL;
45 parser->current_fourcc = 0;
46 }
47
48 gboolean
gst_mss_fragment_parser_add_buffer(GstMssFragmentParser * parser,GstBuffer * buffer)49 gst_mss_fragment_parser_add_buffer (GstMssFragmentParser * parser,
50 GstBuffer * buffer)
51 {
52 GstByteReader reader;
53 GstMapInfo info;
54 guint64 size;
55 guint32 fourcc;
56 guint header_size;
57 gboolean error = FALSE;
58
59 if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
60 return FALSE;
61 }
62
63 gst_byte_reader_init (&reader, info.data, info.size);
64 GST_TRACE ("Total buffer size: %u", gst_byte_reader_get_size (&reader));
65
66 do {
67 parser->current_fourcc = 0;
68
69 if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, &header_size,
70 &size)) {
71 break;
72 }
73
74 parser->current_fourcc = fourcc;
75
76 GST_LOG ("box %" GST_FOURCC_FORMAT " size %" G_GUINT64_FORMAT,
77 GST_FOURCC_ARGS (fourcc), size);
78
79 parser->current_fourcc = fourcc;
80
81 if (parser->current_fourcc == GST_ISOFF_FOURCC_MOOF) {
82 GstByteReader sub_reader;
83
84 g_assert (parser->moof == NULL);
85 gst_byte_reader_get_sub_reader (&reader, &sub_reader, size - header_size);
86 parser->moof = gst_isoff_moof_box_parse (&sub_reader);
87 if (parser->moof == NULL) {
88 GST_ERROR ("Failed to parse moof");
89 error = TRUE;
90 }
91 } else if (parser->current_fourcc == GST_ISOFF_FOURCC_MDAT) {
92 goto beach;
93 } else {
94 gst_byte_reader_skip (&reader, size - header_size);
95 }
96 } while (gst_byte_reader_get_remaining (&reader) > 0);
97
98 beach:
99
100 /* Do sanity check */
101 if (parser->current_fourcc != GST_ISOFF_FOURCC_MDAT || !parser->moof ||
102 parser->moof->traf->len == 0)
103 error = TRUE;
104
105 if (!error) {
106 GstTrafBox *traf = &g_array_index (parser->moof->traf, GstTrafBox, 0);
107 if (!traf->tfxd) {
108 GST_ERROR ("no tfxd box");
109 error = TRUE;
110 } else if (!traf->tfrf) {
111 GST_ERROR ("no tfrf box");
112 error = TRUE;
113 }
114 }
115
116 if (!error)
117 parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED;
118
119 GST_LOG ("Fragment parsing successful: %s", error ? "no" : "yes");
120 gst_buffer_unmap (buffer, &info);
121 return !error;
122 }
123