qtdemux: Add/Fix comments on the various structure variables
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / gstisoff.c
1 /*
2  * ISO File Format parsing library
3  *
4  * gstisoff.h
5  *
6  * Copyright (C) 2015 Samsung Electronics. All rights reserved.
7  *   Author: Thiago Santos <thiagoss@osg.samsung.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library (COPYING); if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "gstisoff.h"
26 #include <gst/base/gstbytereader.h>
27
28 void
29 gst_isoff_qt_sidx_parser_init (GstSidxParser * parser)
30 {
31   parser->status = GST_ISOFF_QT_SIDX_PARSER_INIT;
32   parser->cumulative_entry_size = 0;
33   parser->sidx.entries = NULL;
34   parser->sidx.entries_count = 0;
35 }
36
37 void
38 gst_isoff_qt_sidx_parser_clear (GstSidxParser * parser)
39 {
40   g_free (parser->sidx.entries);
41   parser->sidx.entries = NULL;
42 }
43
44 static void
45 gst_isoff_qt_parse_sidx_entry (GstSidxBoxEntry * entry, GstByteReader * reader)
46 {
47   guint32 aux;
48
49   aux = gst_byte_reader_get_uint32_be_unchecked (reader);
50   entry->ref_type = aux >> 31;
51   entry->size = aux & 0x7FFFFFFF;
52   entry->duration = gst_byte_reader_get_uint32_be_unchecked (reader);
53   aux = gst_byte_reader_get_uint32_be_unchecked (reader);
54   entry->starts_with_sap = aux >> 31;
55   entry->sap_type = ((aux >> 28) & 0x7);
56   entry->sap_delta_time = aux & 0xFFFFFFF;
57 }
58
59 GstIsoffParserResult
60 gst_isoff_qt_sidx_parser_add_data (GstSidxParser * parser,
61     const guint8 * buffer, gint length, guint * consumed)
62 {
63   GstIsoffParserResult res = GST_ISOFF_QT_PARSER_OK;
64   GstByteReader reader;
65   gsize remaining;
66   guint32 fourcc;
67
68   gst_byte_reader_init (&reader, buffer, length);
69
70   switch (parser->status) {
71     case GST_ISOFF_QT_SIDX_PARSER_INIT:
72       if (gst_byte_reader_get_remaining (&reader) < GST_ISOFF_QT_FULL_BOX_SIZE) {
73         break;
74       }
75
76       parser->size = gst_byte_reader_get_uint32_be_unchecked (&reader);
77       fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
78       if (fourcc != GST_ISOFF_QT_FOURCC_SIDX) {
79         res = GST_ISOFF_QT_PARSER_UNEXPECTED;
80         gst_byte_reader_set_pos (&reader, 0);
81         break;
82       }
83       if (parser->size == 1) {
84         if (gst_byte_reader_get_remaining (&reader) < 12) {
85           gst_byte_reader_set_pos (&reader, 0);
86           break;
87         }
88
89         parser->size = gst_byte_reader_get_uint64_be_unchecked (&reader);
90       }
91       if (parser->size == 0) {
92         res = GST_ISOFF_QT_PARSER_ERROR;
93         gst_byte_reader_set_pos (&reader, 0);
94         break;
95       }
96       parser->sidx.version = gst_byte_reader_get_uint8_unchecked (&reader);
97       parser->sidx.flags = gst_byte_reader_get_uint24_le_unchecked (&reader);
98
99       parser->status = GST_ISOFF_QT_SIDX_PARSER_HEADER;
100
101     case GST_ISOFF_QT_SIDX_PARSER_HEADER:
102       remaining = gst_byte_reader_get_remaining (&reader);
103       if (remaining < 12 + (parser->sidx.version == 0 ? 8 : 16)) {
104         break;
105       }
106
107       parser->sidx.ref_id = gst_byte_reader_get_uint32_be_unchecked (&reader);
108       parser->sidx.timescale =
109           gst_byte_reader_get_uint32_be_unchecked (&reader);
110       if (parser->sidx.version == 0) {
111         parser->sidx.earliest_pts =
112             gst_byte_reader_get_uint32_be_unchecked (&reader);
113         parser->sidx.first_offset = parser->sidx.earliest_pts =
114             gst_byte_reader_get_uint32_be_unchecked (&reader);
115       } else {
116         parser->sidx.earliest_pts =
117             gst_byte_reader_get_uint64_be_unchecked (&reader);
118         parser->sidx.first_offset =
119             gst_byte_reader_get_uint64_be_unchecked (&reader);
120       }
121       /* skip 2 reserved bytes */
122       gst_byte_reader_skip_unchecked (&reader, 2);
123       parser->sidx.entries_count =
124           gst_byte_reader_get_uint16_be_unchecked (&reader);
125
126       GST_LOG ("Timescale: %" G_GUINT32_FORMAT, parser->sidx.timescale);
127       GST_LOG ("Earliest pts: %" G_GUINT64_FORMAT, parser->sidx.earliest_pts);
128       GST_LOG ("First offset: %" G_GUINT64_FORMAT, parser->sidx.first_offset);
129
130       parser->cumulative_pts =
131           gst_util_uint64_scale_int_round (parser->sidx.earliest_pts,
132           GST_SECOND, parser->sidx.timescale);
133
134       if (parser->sidx.entries_count) {
135         parser->sidx.entries =
136             g_malloc (sizeof (GstSidxBoxEntry) * parser->sidx.entries_count);
137       }
138       parser->sidx.entry_index = 0;
139
140       parser->status = GST_ISOFF_QT_SIDX_PARSER_DATA;
141
142     case GST_ISOFF_QT_SIDX_PARSER_DATA:
143       while (parser->sidx.entry_index < parser->sidx.entries_count) {
144         GstSidxBoxEntry *entry =
145             &parser->sidx.entries[parser->sidx.entry_index];
146
147         remaining = gst_byte_reader_get_remaining (&reader);
148         if (remaining < 12)
149           break;
150
151         entry->offset = parser->cumulative_entry_size;
152         entry->pts = parser->cumulative_pts;
153         gst_isoff_qt_parse_sidx_entry (entry, &reader);
154         entry->duration = gst_util_uint64_scale_int_round (entry->duration,
155             GST_SECOND, parser->sidx.timescale);
156         parser->cumulative_entry_size += entry->size;
157         parser->cumulative_pts += entry->duration;
158
159         GST_LOG ("Sidx entry %d) offset: %" G_GUINT64_FORMAT ", pts: %"
160             GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT " - size %"
161             G_GUINT32_FORMAT, parser->sidx.entry_index, entry->offset,
162             GST_TIME_ARGS (entry->pts), GST_TIME_ARGS (entry->duration),
163             entry->size);
164
165         parser->sidx.entry_index++;
166       }
167
168       if (parser->sidx.entry_index == parser->sidx.entries_count)
169         parser->status = GST_ISOFF_QT_SIDX_PARSER_FINISHED;
170       else
171         break;
172     case GST_ISOFF_QT_SIDX_PARSER_FINISHED:
173       parser->sidx.entry_index = 0;
174       res = GST_ISOFF_QT_PARSER_DONE;
175       break;
176   }
177
178   *consumed = gst_byte_reader_get_pos (&reader);
179   return res;
180 }
181
182 GstIsoffParserResult
183 gst_isoff_qt_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer,
184     guint * consumed)
185 {
186   GstIsoffParserResult res = GST_ISOFF_QT_PARSER_OK;
187   GstMapInfo info;
188
189   if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
190     *consumed = 0;
191     return GST_ISOFF_QT_PARSER_ERROR;
192   }
193
194   res =
195       gst_isoff_qt_sidx_parser_add_data (parser, info.data, info.size,
196       consumed);
197
198   gst_buffer_unmap (buffer, &info);
199   return res;
200 }