Copy qtmux from revision 148 of the gst-qtmux repository.
[platform/upstream/gst-plugins-good.git] / gst / quicktime / 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 #include "descriptors.h"
21
22 /**
23  * Some mp4 structures (descriptors) use a coding scheme for
24  * representing its size.
25  * It is grouped in bytes. The 1st bit set to 1 means we need another byte,
26  * 0 otherwise. The remaining 7 bits are the useful values.
27  *
28  * The next set of functions handle those values
29  */
30
31 /**
32  * Gets an unsigned integer and packs it into a 'expandable size' format
33  * (as used by mp4 descriptors)
34  * @size: the integer to be parsed
35  * @ptr: the array to place the result
36  * @array_size: the size of ptr array
37  */
38 static void
39 expandable_size_parse (guint64 size, guint8 * ptr, guint32 array_size)
40 {
41   int index = 0;
42
43   memset (ptr, 0, sizeof (array_size));
44   while (size > 0 && index < array_size) {
45     ptr[index++] = (size > 0x7F ? 0x80 : 0x0) | (size & 0x7F);
46     size = size >> 7;
47   }
48 }
49
50 /**
51  * Gets how many positions in an array holding an 'expandable size'
52  * are really used
53  *
54  * @ptr: the array with the 'expandable size'
55  * @array_size: the size of ptr array
56  *
57  * Returns: the number of really used positions
58  */
59 static guint64
60 expandable_size_get_length (guint8 * ptr, guint32 array_size)
61 {
62   gboolean next = TRUE;
63   guint32 index = 0;
64
65   while (next && index < array_size) {
66     next = ((ptr[index] & 0x80) == 1);
67     index++;
68   }
69   return index;
70 }
71
72 /*
73  * Initializers below
74  */
75
76 static void
77 desc_base_descriptor_init (BaseDescriptor * bd, guint8 tag, guint32 size)
78 {
79   bd->tag = tag;
80   expandable_size_parse (size, bd->size, 4);
81 }
82
83 static void
84 desc_dec_specific_info_init (DecoderSpecificInfoDescriptor * dsid)
85 {
86   desc_base_descriptor_init (&dsid->base, DECODER_SPECIFIC_INFO_TAG, 0);
87   dsid->length = 0;
88   dsid->data = NULL;
89 }
90
91 DecoderSpecificInfoDescriptor *
92 desc_dec_specific_info_new ()
93 {
94   DecoderSpecificInfoDescriptor *desc =
95       g_new0 (DecoderSpecificInfoDescriptor, 1);
96   desc_dec_specific_info_init (desc);
97   return desc;
98 }
99
100 static void
101 desc_dec_conf_desc_init (DecoderConfigDescriptor * dcd)
102 {
103   desc_base_descriptor_init (&dcd->base, DECODER_CONFIG_DESC_TAG, 0);
104   dcd->dec_specific_info = NULL;
105 }
106
107 static void
108 desc_sl_conf_desc_init (SLConfigDescriptor * sl)
109 {
110   desc_base_descriptor_init (&sl->base, SL_CONFIG_DESC_TAG, 0);
111   sl->predefined = 0x2;
112 }
113
114 void
115 desc_es_init (ESDescriptor * es)
116 {
117   desc_base_descriptor_init (&es->base, ES_DESCRIPTOR_TAG, 0);
118
119   es->id = 0;
120   es->flags = 0;
121   es->depends_on_es_id = 0;
122   es->ocr_es_id = 0;
123   es->url_length = 0;
124   es->url_string = NULL;
125
126   desc_dec_conf_desc_init (&es->dec_conf_desc);
127   desc_sl_conf_desc_init (&es->sl_conf_desc);
128 }
129
130 ESDescriptor *
131 desc_es_descriptor_new ()
132 {
133   ESDescriptor *es = g_new0 (ESDescriptor, 1);
134
135   desc_es_init (es);
136   return es;
137 }
138
139 /*
140  * Deinitializers/Destructors below
141  */
142
143 static void
144 desc_base_descriptor_clear (BaseDescriptor * base)
145 {
146 }
147
148 void
149 desc_dec_specific_info_free (DecoderSpecificInfoDescriptor * dsid)
150 {
151   desc_base_descriptor_clear (&dsid->base);
152   if (dsid->data) {
153     g_free (dsid->data);
154     dsid->data = NULL;
155   }
156   g_free (dsid);
157 }
158
159 static void
160 desc_dec_conf_desc_clear (DecoderConfigDescriptor * dec)
161 {
162   desc_base_descriptor_clear (&dec->base);
163   if (dec->dec_specific_info) {
164     desc_dec_specific_info_free (dec->dec_specific_info);
165   }
166 }
167
168 static void
169 desc_sl_config_descriptor_clear (SLConfigDescriptor * sl)
170 {
171   desc_base_descriptor_clear (&sl->base);
172 }
173
174 void
175 desc_es_descriptor_clear (ESDescriptor * es)
176 {
177   desc_base_descriptor_clear (&es->base);
178   if (es->url_string) {
179     g_free (es->url_string);
180     es->url_string = NULL;
181   }
182   desc_dec_conf_desc_clear (&es->dec_conf_desc);
183   desc_sl_config_descriptor_clear (&es->sl_conf_desc);
184 }
185
186 void
187 desc_es_descriptor_free (ESDescriptor * es)
188 {
189   desc_es_descriptor_clear (es);
190   g_free (es);
191 }
192
193 /*
194  * Size handling functions below
195  */
196
197 void
198 desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor * dsid,
199     guint32 size)
200 {
201   if (dsid->data) {
202     g_free (dsid->data);
203   }
204   dsid->data = g_new0 (guint8, size);
205   dsid->length = size;
206 }
207
208 static void
209 desc_base_descriptor_set_size (BaseDescriptor * bd, guint32 size)
210 {
211   expandable_size_parse (size, bd->size, 4);
212 }
213
214 static guint64
215 desc_base_descriptor_get_size (BaseDescriptor * bd)
216 {
217   guint64 size = 0;
218
219   size += sizeof (guint8);
220   size += expandable_size_get_length (bd->size, 4) * sizeof (guint8);
221   return size;
222 }
223
224 static guint64
225 desc_sl_config_descriptor_get_size (SLConfigDescriptor * sl_desc)
226 {
227   guint64 size = 0;
228   guint64 extra_size = 0;
229
230   size += desc_base_descriptor_get_size (&sl_desc->base);
231   /* predefined */
232   extra_size += sizeof (guint8);
233
234   desc_base_descriptor_set_size (&sl_desc->base, extra_size);
235
236   return size + extra_size;
237 }
238
239 static guint64
240 desc_dec_specific_info_get_size (DecoderSpecificInfoDescriptor * dsid)
241 {
242   guint64 size = 0;
243   guint64 extra_size = 0;
244
245   size += desc_base_descriptor_get_size (&dsid->base);
246   extra_size += sizeof (guint8) * dsid->length;
247   desc_base_descriptor_set_size (&dsid->base, extra_size);
248   return size + extra_size;
249 }
250
251 static guint64
252 desc_dec_config_descriptor_get_size (DecoderConfigDescriptor * dec_desc)
253 {
254   guint64 size = 0;
255   guint64 extra_size = 0;
256
257   size += desc_base_descriptor_get_size (&dec_desc->base);
258   /* object type */
259   extra_size += sizeof (guint8);
260   /* stream type */
261   extra_size += sizeof (guint8);
262   /* buffer size */
263   extra_size += sizeof (guint8) * 3;
264   /* max bitrate */
265   extra_size += sizeof (guint32);
266   /* avg bitrate */
267   extra_size += sizeof (guint32);
268   if (dec_desc->dec_specific_info) {
269     extra_size += desc_dec_specific_info_get_size (dec_desc->dec_specific_info);
270   }
271
272   desc_base_descriptor_set_size (&dec_desc->base, extra_size);
273   return size + extra_size;
274 }
275
276 static guint64
277 desc_es_descriptor_get_size (ESDescriptor * es)
278 {
279   guint64 size = 0;
280   guint64 extra_size = 0;
281
282   size += desc_base_descriptor_get_size (&es->base);
283   /* id */
284   extra_size += sizeof (guint16);
285   /* flags */
286   extra_size += sizeof (guint8);
287   /* depends_on_es_id */
288   if (es->flags & 0x80) {
289     extra_size += sizeof (guint16);
290   }
291   if (es->flags & 0x40) {
292     /* url_length */
293     extra_size += sizeof (guint8);
294     /* url */
295     extra_size += sizeof (gchar) * es->url_length;
296   }
297   if (es->flags & 0x20) {
298     /* ocr_es_id */
299     extra_size += sizeof (guint16);
300   }
301
302   extra_size += desc_dec_config_descriptor_get_size (&es->dec_conf_desc);
303   extra_size += desc_sl_config_descriptor_get_size (&es->sl_conf_desc);
304
305   desc_base_descriptor_set_size (&es->base, extra_size);
306
307   return size + extra_size;
308 }
309
310 static gboolean
311 desc_es_descriptor_check_stream_dependency (ESDescriptor * es)
312 {
313   return es->flags & 0x80;
314 }
315
316 static gboolean
317 desc_es_descriptor_check_url_flag (ESDescriptor * es)
318 {
319   return es->flags & 0x40;
320 }
321
322 static gboolean
323 desc_es_descriptor_check_ocr (ESDescriptor * es)
324 {
325   return es->flags & 0x20;
326 }
327
328 /* Copy/Serializations Functions below */
329
330 static guint64
331 desc_base_descriptor_copy_data (BaseDescriptor * desc, guint8 ** buffer,
332     guint64 * size, guint64 * offset)
333 {
334   guint64 original_offset = *offset;
335
336   prop_copy_uint8 (desc->tag, buffer, size, offset);
337   prop_copy_uint8_array (desc->size, expandable_size_get_length (desc->size, 4),
338       buffer, size, offset);
339   return original_offset - *offset;
340 }
341
342 static guint64
343 desc_sl_config_descriptor_copy_data (SLConfigDescriptor * desc,
344     guint8 ** buffer, guint64 * size, guint64 * offset)
345 {
346   guint64 original_offset = *offset;
347
348   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
349     return 0;
350   }
351   /* predefined attribute */
352   prop_copy_uint8 (desc->predefined, buffer, size, offset);
353
354   return *offset - original_offset;
355 }
356
357 static guint64
358 desc_dec_specific_info_copy_data (DecoderSpecificInfoDescriptor * desc,
359     guint8 ** buffer, guint64 * size, guint64 * offset)
360 {
361   guint64 original_offset = *offset;
362
363   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
364     return 0;
365   }
366   prop_copy_uint8_array (desc->data, desc->length, buffer, size, offset);
367
368   return *offset - original_offset;
369 }
370
371 static guint64
372 desc_dec_config_descriptor_copy_data (DecoderConfigDescriptor * desc,
373     guint8 ** buffer, guint64 * size, guint64 * offset)
374 {
375   guint64 original_offset = *offset;
376
377   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
378     return 0;
379   }
380
381   prop_copy_uint8 (desc->object_type, buffer, size, offset);
382
383   prop_copy_uint8 (desc->stream_type, buffer, size, offset);
384   prop_copy_uint8_array (desc->buffer_size_DB, 3, buffer, size, offset);
385
386   prop_copy_uint32 (desc->max_bitrate, buffer, size, offset);
387   prop_copy_uint32 (desc->avg_bitrate, buffer, size, offset);
388
389   if (desc->dec_specific_info) {
390     if (!desc_dec_specific_info_copy_data (desc->dec_specific_info, buffer,
391             size, offset)) {
392       return 0;
393     }
394   }
395
396   return *offset - original_offset;
397 }
398
399 guint64
400 desc_es_descriptor_copy_data (ESDescriptor * desc, guint8 ** buffer,
401     guint64 * size, guint64 * offset)
402 {
403   guint64 desc_size;
404   guint64 original_offset = *offset;
405
406   /* must call this twice to have size fields of all contained descriptors set
407    * correctly, and to have the size of the size fields taken into account */
408   desc_size = desc_es_descriptor_get_size (desc);
409   desc_size = desc_es_descriptor_get_size (desc);
410
411   if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
412     return 0;
413   }
414   /* id and flags */
415   prop_copy_uint16 (desc->id, buffer, size, offset);
416   prop_copy_uint8 (desc->flags, buffer, size, offset);
417
418   if (desc_es_descriptor_check_stream_dependency (desc)) {
419     prop_copy_uint16 (desc->depends_on_es_id, buffer, size, offset);
420   }
421
422   if (desc_es_descriptor_check_url_flag (desc)) {
423     prop_copy_size_string (desc->url_string, desc->url_length, buffer, size,
424         offset);
425   }
426
427   if (desc_es_descriptor_check_ocr (desc)) {
428     prop_copy_uint16 (desc->ocr_es_id, buffer, size, offset);
429   }
430
431   if (!desc_dec_config_descriptor_copy_data (&desc->dec_conf_desc, buffer, size,
432           offset)) {
433     return 0;
434   }
435
436   if (!desc_sl_config_descriptor_copy_data (&desc->sl_conf_desc, buffer, size,
437           offset)) {
438     return 0;
439   }
440
441   return *offset - original_offset;
442 }