Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / gst / isomp4 / descriptors.c
1 /* Quicktime muxer plugin for GStreamer
2  * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 /*
20  * Unless otherwise indicated, Source Code is licensed under MIT license.
21  * See further explanation attached in License Statement (distributed in the file
22  * LICENSE).
23  *
24  * Permission is hereby granted, free of charge, to any person obtaining a copy of
25  * this software and associated documentation files (the "Software"), to deal in
26  * the Software without restriction, including without limitation the rights to
27  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28  * of the Software, and to permit persons to whom the Software is furnished to do
29  * so, subject to the following conditions:
30  *
31  * The above copyright notice and this permission notice shall be included in all
32  * copies or substantial portions of the Software.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40  * SOFTWARE.
41  */
42
43 #include "descriptors.h"
44
45 /*
46  * Some mp4 structures (descriptors) use a coding scheme for
47  * representing its size.
48  * It is grouped in bytes. The 1st bit set to 1 means we need another byte,
49  * 0 otherwise. The remaining 7 bits are the useful values.
50  *
51  * The next set of functions handle those values
52  */
53
54 /*
55  * Gets an unsigned integer and packs it into a 'expandable size' format
56  * (as used by mp4 descriptors)
57  * @size: the integer to be parsed
58  * @ptr: the array to place the result
59  * @array_size: the size of ptr array
60  */
61 static void
62 expandable_size_parse (guint64 size, guint8 * ptr, guint32 array_size)
63 {
64   int index = 0;
65
66   memset (ptr, 0, sizeof (array_size));
67   while (size > 0 && index < array_size) {
68     ptr[index++] = (size > 0x7F ? 0x80 : 0x0) | (size & 0x7F);
69     size = size >> 7;
70   }
71 }
72
73 /*
74  * Gets how many positions in an array holding an 'expandable size'
75  * are really used
76  *
77  * @ptr: the array with the 'expandable size'
78  * @array_size: the size of ptr array
79  *
80  * Returns: the number of really used positions
81  */
82 static guint64
83 expandable_size_get_length (guint8 * ptr, guint32 array_size)
84 {
85   gboolean next = TRUE;
86   guint32 index = 0;
87
88   while (next && index < array_size) {
89     next = ((ptr[index] & 0x80) == 1);
90     index++;
91   }
92   return index;
93 }
94
95 /*
96  * Initializers below
97  */
98
99 static void
100 desc_base_descriptor_init (BaseDescriptor * bd, guint8 tag, guint32 size)
101 {
102   bd->tag = tag;
103   expandable_size_parse (size, bd->size, 4);
104 }
105
106 static void
107 desc_dec_specific_info_init (DecoderSpecificInfoDescriptor * dsid)
108 {
109   desc_base_descriptor_init (&dsid->base, DECODER_SPECIFIC_INFO_TAG, 0);
110   dsid->length = 0;
111   dsid->data = NULL;
112 }
113
114 DecoderSpecificInfoDescriptor *
115 desc_dec_specific_info_new (void)
116 {
117   DecoderSpecificInfoDescriptor *desc =
118       g_new0 (DecoderSpecificInfoDescriptor, 1);
119   desc_dec_specific_info_init (desc);
120   return desc;
121 }
122
123 static void
124 desc_dec_conf_desc_init (DecoderConfigDescriptor * dcd)
125 {
126   desc_base_descriptor_init (&dcd->base, DECODER_CONFIG_DESC_TAG, 0);
127   dcd->dec_specific_info = NULL;
128 }
129
130 static void
131 desc_sl_conf_desc_init (SLConfigDescriptor * sl)
132 {
133   desc_base_descriptor_init (&sl->base, SL_CONFIG_DESC_TAG, 0);
134   sl->predefined = 0x2;
135 }
136
137 void
138 desc_es_init (ESDescriptor * es)
139 {
140   desc_base_descriptor_init (&es->base, ES_DESCRIPTOR_TAG, 0);
141
142   es->id = 0;
143   es->flags = 0;
144   es->depends_on_es_id = 0;
145   es->ocr_es_id = 0;
146   es->url_length = 0;
147   es->url_string = NULL;
148
149   desc_dec_conf_desc_init (&es->dec_conf_desc);
150   desc_sl_conf_desc_init (&es->sl_conf_desc);
151 }
152
153 ESDescriptor *
154 desc_es_descriptor_new (void)
155 {
156   ESDescriptor *es = g_new0 (ESDescriptor, 1);
157
158   desc_es_init (es);
159   return es;
160 }
161
162 /*
163  * Deinitializers/Destructors below
164  */
165
166 static void
167 desc_base_descriptor_clear (BaseDescriptor * base)
168 {
169 }
170
171 void
172 desc_dec_specific_info_free (DecoderSpecificInfoDescriptor * dsid)
173 {
174   desc_base_descriptor_clear (&dsid->base);
175   if (dsid->data) {
176     g_free (dsid->data);
177     dsid->data = NULL;
178   }
179   g_free (dsid);
180 }
181
182 static void
183 desc_dec_conf_desc_clear (DecoderConfigDescriptor * dec)
184 {
185   desc_base_descriptor_clear (&dec->base);
186   if (dec->dec_specific_info) {
187     desc_dec_specific_info_free (dec->dec_specific_info);
188   }
189 }
190
191 static void
192 desc_sl_config_descriptor_clear (SLConfigDescriptor * sl)
193 {
194   desc_base_descriptor_clear (&sl->base);
195 }
196
197 void
198 desc_es_descriptor_clear (ESDescriptor * es)
199 {
200   desc_base_descriptor_clear (&es->base);
201   if (es->url_string) {
202     g_free (es->url_string);
203     es->url_string = NULL;
204   }
205   desc_dec_conf_desc_clear (&es->dec_conf_desc);
206   desc_sl_config_descriptor_clear (&es->sl_conf_desc);
207 }
208
209 /*
210  * Size handling functions below
211  */
212
213 void
214 desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor * dsid,
215     guint32 size)
216 {
217   if (dsid->data) {
218     g_free (dsid->data);
219   }
220   dsid->data = g_new0 (guint8, size);
221   dsid->length = size;
222 }
223
224 static void
225 desc_base_descriptor_set_size (BaseDescriptor * bd, guint32 size)
226 {
227   expandable_size_parse (size, bd->size, 4);
228 }
229
230 static guint64
231 desc_base_descriptor_get_size (BaseDescriptor * bd)
232 {
233   guint64 size = 0;
234
235   size += sizeof (guint8);
236   size += expandable_size_get_length (bd->size, 4) * sizeof (guint8);
237   return size;
238 }
239
240 static guint64
241 desc_sl_config_descriptor_get_size (SLConfigDescriptor * sl_desc)
242 {
243   guint64 size = 0;
244   guint64 extra_size = 0;
245
246   size += desc_base_descriptor_get_size (&sl_desc->base);
247   /* predefined */
248   extra_size += sizeof (guint8);
249
250   desc_base_descriptor_set_size (&sl_desc->base, extra_size);
251
252   return size + extra_size;
253 }
254
255 static guint64
256 desc_dec_specific_info_get_size (DecoderSpecificInfoDescriptor * dsid)
257 {
258   guint64 size = 0;
259   guint64 extra_size = 0;
260
261   size += desc_base_descriptor_get_size (&dsid->base);
262   extra_size += sizeof (guint8) * dsid->length;
263   desc_base_descriptor_set_size (&dsid->base, extra_size);
264   return size + extra_size;
265 }
266
267 static guint64
268 desc_dec_config_descriptor_get_size (DecoderConfigDescriptor * dec_desc)
269 {
270   guint64 size = 0;
271   guint64 extra_size = 0;
272
273   size += desc_base_descriptor_get_size (&dec_desc->base);
274   /* object type */
275   extra_size += sizeof (guint8);
276   /* stream type */
277   extra_size += sizeof (guint8);
278   /* buffer size */
279   extra_size += sizeof (guint8) * 3;
280   /* max bitrate */
281   extra_size += sizeof (guint32);
282   /* avg bitrate */
283   extra_size += sizeof (guint32);
284   if (dec_desc->dec_specific_info) {
285     extra_size += desc_dec_specific_info_get_size (dec_desc->dec_specific_info);
286   }
287
288   desc_base_descriptor_set_size (&dec_desc->base, extra_size);
289   return size + extra_size;
290 }
291
292 static guint64
293 desc_es_descriptor_get_size (ESDescriptor * es)
294 {
295   guint64 size = 0;
296   guint64 extra_size = 0;
297
298   size += desc_base_descriptor_get_size (&es->base);
299   /* id */
300   extra_size += sizeof (guint16);
301   /* flags */
302   extra_size += sizeof (guint8);
303   /* depends_on_es_id */
304   if (es->flags & 0x80) {
305     extra_size += sizeof (guint16);
306   }
307   if (es->flags & 0x40) {
308     /* url_length */
309     extra_size += sizeof (guint8);
310     /* url */
311     extra_size += sizeof (gchar) * es->url_length;
312   }
313   if (es->flags & 0x20) {
314     /* ocr_es_id */
315     extra_size += sizeof (guint16);
316   }
317
318   extra_size += desc_dec_config_descriptor_get_size (&es->dec_conf_desc);
319   extra_size += desc_sl_config_descriptor_get_size (&es->sl_conf_desc);
320
321   desc_base_descriptor_set_size (&es->base, extra_size);
322
323   return size + extra_size;
324 }
325
326 static gboolean
327 desc_es_descriptor_check_stream_dependency (ESDescriptor * es)
328 {
329   return es->flags & 0x80;
330 }
331
332 static gboolean
333 desc_es_descriptor_check_url_flag (ESDescriptor * es)
334 {
335   return es->flags & 0x40;
336 }
337
338 static gboolean
339 desc_es_descriptor_check_ocr (ESDescriptor * es)
340 {
341   return es->flags & 0x20;
342 }
343
344 /* Copy/Serializations Functions below */
345
346 static guint64
347 desc_base_descriptor_copy_data (BaseDescriptor * desc, guint8 ** buffer,
348     guint64 * size, guint64 * offset)
349 {
350   guint64 original_offset = *offset;
351
352   prop_copy_uint8 (desc->tag, buffer, size, offset);
353   prop_copy_uint8_array (desc->size, expandable_size_get_length (desc->size, 4),
354       buffer, size, offset);
355   return original_offset - *offset;
356 }
357
358 static guint64
359 desc_sl_config_descriptor_copy_data (SLConfigDescriptor * desc,
360     guint8 ** buffer, guint64 * size, guint64 * offset)
361 {
362   guint64 original_offset = *offset;
363
364   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
365     return 0;
366   }
367   /* predefined attribute */
368   prop_copy_uint8 (desc->predefined, buffer, size, offset);
369
370   return *offset - original_offset;
371 }
372
373 static guint64
374 desc_dec_specific_info_copy_data (DecoderSpecificInfoDescriptor * desc,
375     guint8 ** buffer, guint64 * size, guint64 * offset)
376 {
377   guint64 original_offset = *offset;
378
379   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
380     return 0;
381   }
382   prop_copy_uint8_array (desc->data, desc->length, buffer, size, offset);
383
384   return *offset - original_offset;
385 }
386
387 static guint64
388 desc_dec_config_descriptor_copy_data (DecoderConfigDescriptor * desc,
389     guint8 ** buffer, guint64 * size, guint64 * offset)
390 {
391   guint64 original_offset = *offset;
392
393   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
394     return 0;
395   }
396
397   prop_copy_uint8 (desc->object_type, buffer, size, offset);
398
399   prop_copy_uint8 (desc->stream_type, buffer, size, offset);
400   prop_copy_uint8_array (desc->buffer_size_DB, 3, buffer, size, offset);
401
402   prop_copy_uint32 (desc->max_bitrate, buffer, size, offset);
403   prop_copy_uint32 (desc->avg_bitrate, buffer, size, offset);
404
405   if (desc->dec_specific_info) {
406     if (!desc_dec_specific_info_copy_data (desc->dec_specific_info, buffer,
407             size, offset)) {
408       return 0;
409     }
410   }
411
412   return *offset - original_offset;
413 }
414
415 guint64
416 desc_es_descriptor_copy_data (ESDescriptor * desc, guint8 ** buffer,
417     guint64 * size, guint64 * offset)
418 {
419   guint64 original_offset = *offset;
420
421   /* must call this twice to have size fields of all contained descriptors set
422    * correctly, and to have the size of the size fields taken into account */
423   desc_es_descriptor_get_size (desc);
424   desc_es_descriptor_get_size (desc);
425
426   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
427     return 0;
428   }
429   /* id and flags */
430   prop_copy_uint16 (desc->id, buffer, size, offset);
431   prop_copy_uint8 (desc->flags, buffer, size, offset);
432
433   if (desc_es_descriptor_check_stream_dependency (desc)) {
434     prop_copy_uint16 (desc->depends_on_es_id, buffer, size, offset);
435   }
436
437   if (desc_es_descriptor_check_url_flag (desc)) {
438     prop_copy_size_string (desc->url_string, desc->url_length, buffer, size,
439         offset);
440   }
441
442   if (desc_es_descriptor_check_ocr (desc)) {
443     prop_copy_uint16 (desc->ocr_es_id, buffer, size, offset);
444   }
445
446   if (!desc_dec_config_descriptor_copy_data (&desc->dec_conf_desc, buffer, size,
447           offset)) {
448     return 0;
449   }
450
451   if (!desc_sl_config_descriptor_copy_data (&desc->sl_conf_desc, buffer, size,
452           offset)) {
453     return 0;
454   }
455
456   return *offset - original_offset;
457 }