vcgencmd: Apply ASLR
[platform/adaptation/broadcom/libomxil-vc4.git] / containers / core / containers_utils.c
1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the copyright holder nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "containers/containers.h"
32 #include "containers/core/containers_common.h"
33 #include "containers/core/containers_utils.h"
34
35 /******************************************************************************
36 Defines.
37 ******************************************************************************/
38 #define BITMAPINFOHEADER_SIZE_MAX 40
39 #define MAX_EXTENSION_SIZE 4
40
41 #define VC_CONTAINER_ES_FORMAT_MAGIC ((uint32_t)VC_FOURCC('m','a','g','f'))
42 #define EXTRADATA_SIZE_DEFAULT 32
43 #define EXTRADATA_SIZE_MAX (10*1024)
44
45 /*****************************************************************************/
46 typedef struct VC_CONTAINER_ES_FORMAT_PRIVATE_T
47 {
48    VC_CONTAINER_ES_FORMAT_T format;
49    VC_CONTAINER_ES_SPECIFIC_FORMAT_T type;
50
51    uint32_t magic;
52
53    unsigned int extradata_size;
54    uint8_t *extradata;
55
56    uint8_t buffer[EXTRADATA_SIZE_DEFAULT];
57
58 } VC_CONTAINER_ES_FORMAT_PRIVATE_T;
59
60 /*****************************************************************************/
61 VC_CONTAINER_ES_FORMAT_T *vc_container_format_create(unsigned int extradata_size)
62 {
63    VC_CONTAINER_ES_FORMAT_PRIVATE_T *private;
64    VC_CONTAINER_STATUS_T status;
65
66    private = malloc(sizeof(*private));
67    if(!private) return 0;
68    memset(private, 0, sizeof(*private));
69
70    private->magic = VC_CONTAINER_ES_FORMAT_MAGIC;
71    private->format.type = (void *)&private->type;
72    private->extradata_size = EXTRADATA_SIZE_DEFAULT;
73
74    status = vc_container_format_extradata_alloc(&private->format, extradata_size);
75    if(status != VC_CONTAINER_SUCCESS)
76    {
77       free(private);
78       return NULL;
79    }
80
81    return &private->format;
82 }
83
84 /*****************************************************************************/
85 void vc_container_format_delete(VC_CONTAINER_ES_FORMAT_T *format)
86 {
87    VC_CONTAINER_ES_FORMAT_PRIVATE_T *private = (VC_CONTAINER_ES_FORMAT_PRIVATE_T *)format;
88    vc_container_assert(private->magic == VC_CONTAINER_ES_FORMAT_MAGIC);
89    if(private->extradata) free(private->extradata);
90    free(private);
91 }
92
93 /*****************************************************************************/
94 VC_CONTAINER_STATUS_T vc_container_format_extradata_alloc(
95    VC_CONTAINER_ES_FORMAT_T *format, unsigned int size)
96 {
97    VC_CONTAINER_ES_FORMAT_PRIVATE_T *private = (VC_CONTAINER_ES_FORMAT_PRIVATE_T *)format;
98    vc_container_assert(private->magic == VC_CONTAINER_ES_FORMAT_MAGIC);
99
100    /* Sanity check the size requested */
101    if(size > EXTRADATA_SIZE_MAX)
102       return VC_CONTAINER_ERROR_CORRUPTED;
103
104    /* Allocate memory if needed */
105    if(private->extradata_size < size)
106    {
107       if(private->extradata) free(private->extradata);
108       private->extradata = malloc(size);
109       if(!private->extradata)
110          return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
111       private->extradata_size = size;
112    }
113
114    /* Set the fields in the actual format structure */
115    if(private->extradata) private->format.extradata = private->extradata;
116    else private->format.extradata = private->buffer;
117
118    return VC_CONTAINER_SUCCESS;
119 }
120
121 /*****************************************************************************/
122 VC_CONTAINER_STATUS_T vc_container_format_copy( VC_CONTAINER_ES_FORMAT_T *p_out,
123                                                 VC_CONTAINER_ES_FORMAT_T *p_in,
124                                                 unsigned int extra_buffer_size)
125 {
126    void *type = p_out->type;
127    uint8_t *extradata = p_out->extradata;
128
129    /* Check we have a sufficient buffer to copy the extra data */
130    if(p_in->extradata_size > extra_buffer_size ||
131       (p_in->extradata_size && !p_out->extradata))
132       return VC_CONTAINER_ERROR_BUFFER_TOO_SMALL;
133
134    *p_out->type = *p_in->type;
135    *p_out = *p_in;
136    p_out->type = type;
137    p_out->extradata = extradata;
138    if(p_in->extradata_size)
139       memcpy(p_out->extradata, p_in->extradata, p_in->extradata_size);
140
141    return VC_CONTAINER_SUCCESS;
142 }
143
144 /*****************************************************************************/
145 int utf8_from_charset(const char *charset, char *out, unsigned int out_size,
146                       const void *in, unsigned int in_size)
147 {
148    unsigned int i;
149    const uint16_t *in16 = (const uint16_t *)in;
150    const uint8_t *in8 = (const uint8_t *)in;
151
152    if(out_size < 1) return 1;
153    if(!strcmp(charset, "UTF16-LE")) goto utf16le;
154    if(!strcmp(charset, "UTF8")) goto utf8;
155    else return 1;
156
157  utf16le:
158    for(i = 0; i < in_size / 2 && in16[i] && i < out_size - 1; i++)
159    {
160       out[i] = in16[i];
161    }
162    out[i] = 0;
163    return 0;
164
165  utf8:
166    for(i = 0; i < in_size && in8[i] && i < out_size - 1; i++)
167    {
168       out[i] = in8[i];
169    }
170    out[i] = 0;
171    return 0;
172 }
173
174 /*****************************************************************************/
175 unsigned int vc_container_es_format_to_waveformatex(VC_CONTAINER_ES_FORMAT_T *format,
176                                                     uint8_t *buffer, unsigned int buffer_size)
177 {
178    uint16_t waveformat = codec_to_waveformat(format->codec);
179
180    if(format->es_type != VC_CONTAINER_ES_TYPE_AUDIO ||
181       waveformat == WAVE_FORMAT_UNKNOWN) return 0;
182
183    if(!buffer) return format->extradata_size + 18;
184
185    if(buffer_size < format->extradata_size + 18) return 0;
186
187    /* Build a waveformatex header */
188    buffer[0] = waveformat;
189    buffer[1] = waveformat >> 8;
190    buffer[2] = format->type->audio.channels;
191    buffer[3] = 0;
192    buffer[4] = (format->type->audio.sample_rate >> 0) & 0xFF;
193    buffer[5] = (format->type->audio.sample_rate >> 8) & 0xFF;
194    buffer[6] = (format->type->audio.sample_rate >> 16) & 0xFF;
195    buffer[7] = (format->type->audio.sample_rate >> 24) & 0xFF;
196    buffer[8] = (format->bitrate >> 3) & 0xFF;
197    buffer[9] = (format->bitrate >> 11) & 0xFF;
198    buffer[10] = (format->bitrate >> 19) & 0xFF;
199    buffer[11] = (format->bitrate >> 27) & 0xFF;
200    buffer[12] = (format->type->audio.block_align >> 0) & 0xFF;
201    buffer[13] = (format->type->audio.block_align >> 8) & 0xFF;
202    buffer[14] = (format->type->audio.bits_per_sample >> 0) & 0xFF;
203    buffer[15] = (format->type->audio.bits_per_sample >> 8) & 0xFF;
204    buffer[16] = (format->extradata_size >> 0) & 0xFF;
205    buffer[17] = (format->extradata_size >> 8) & 0xFF;
206    memcpy(buffer+18, format->extradata, format->extradata_size);
207    return format->extradata_size + 18;
208 }
209
210 /*****************************************************************************/
211 VC_CONTAINER_STATUS_T vc_container_waveformatex_to_es_format(uint8_t *p,
212    unsigned int buffer_size, unsigned int *extra_offset, unsigned int *extra_size,
213    VC_CONTAINER_ES_FORMAT_T *format)
214 {
215    VC_CONTAINER_FOURCC_T fourcc;
216    uint32_t waveformat_id;
217
218    if(!p || buffer_size < 16) return VC_CONTAINER_ERROR_INVALID_ARGUMENT;
219    waveformat_id = (p[1] << 8) | p[0];
220    fourcc = waveformat_to_codec(waveformat_id);
221
222    /* Read the waveformatex header */
223    if(extra_offset) *extra_offset = 16;
224    if(extra_size) *extra_size = 0;
225    format->type->audio.channels = p[2];
226    format->type->audio.sample_rate = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
227    format->bitrate = ((p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]) * 8;
228    format->type->audio.block_align = (p[13] << 8) | p[12];
229    format->type->audio.bits_per_sample = (p[15] << 8) | p[14];
230
231    if(waveformat_id == WAVE_FORMAT_PCM && format->type->audio.bits_per_sample == 8)
232       fourcc = VC_CONTAINER_CODEC_PCM_UNSIGNED_LE;
233
234    if(buffer_size >= 18)
235    {
236       if(extra_size)
237       {
238          *extra_size = (p[17] << 8) | p[16];
239          if(*extra_size + 18 > buffer_size) *extra_size = buffer_size - 18;
240       }
241       if(extra_offset) *extra_offset = 18;
242    }
243
244    /* Skip the MPEGLAYER3WAVEFORMAT structure */
245    if(waveformat_id == WAVE_FORMAT_MPEGLAYER3 && extra_size)
246    {
247       if(extra_offset) *extra_offset += *extra_size;
248       *extra_size = 0;
249    }
250
251    format->es_type = VC_CONTAINER_ES_TYPE_AUDIO;
252    format->codec = fourcc;
253
254    return VC_CONTAINER_SUCCESS;
255 }
256
257 /*****************************************************************************/
258 unsigned int vc_container_es_format_to_bitmapinfoheader(VC_CONTAINER_ES_FORMAT_T *format,
259                                                         uint8_t *buffer, unsigned int buffer_size)
260 {
261    uint32_t fourcc = codec_to_vfw_fourcc(format->codec);
262    uint32_t size = BITMAPINFOHEADER_SIZE_MAX + format->extradata_size;
263
264    if(format->es_type != VC_CONTAINER_ES_TYPE_VIDEO ||
265       fourcc == VC_CONTAINER_CODEC_UNKNOWN) return 0;
266
267    if(!buffer) return size;
268    if(buffer_size < size) return 0;
269
270    /* Build a bitmapinfoheader header */
271    memset(buffer, 0, BITMAPINFOHEADER_SIZE_MAX);
272    buffer[0] = (size >> 0) & 0xFF;
273    buffer[1] = (size >> 8) & 0xFF;
274    buffer[2] = (size >> 16) & 0xFF;
275    buffer[3] = (size >> 24) & 0xFF;
276    buffer[4] = (format->type->video.width >> 0) & 0xFF;
277    buffer[5] = (format->type->video.width >> 8) & 0xFF;
278    buffer[6] = (format->type->video.width >> 16) & 0xFF;
279    buffer[7] = (format->type->video.width >> 24) & 0xFF;
280    buffer[8] = (format->type->video.height >> 0) & 0xFF;
281    buffer[9] = (format->type->video.height >> 8) & 0xFF;
282    buffer[10] = (format->type->video.height >> 16) & 0xFF;
283    buffer[11] = (format->type->video.height >> 24) & 0xFF;
284    memcpy(buffer + 16, &fourcc, 4);
285    memcpy(buffer + BITMAPINFOHEADER_SIZE_MAX, format->extradata, format->extradata_size);
286    return size;
287 }
288
289 /*****************************************************************************/
290 VC_CONTAINER_STATUS_T vc_container_bitmapinfoheader_to_es_format(uint8_t *p,
291    unsigned int buffer_size, unsigned int *extra_offset, unsigned int *extra_size, 
292    VC_CONTAINER_ES_FORMAT_T *format)
293 {
294    VC_CONTAINER_FOURCC_T fourcc;
295    
296    if(!p || buffer_size < BITMAPINFOHEADER_SIZE_MAX) return VC_CONTAINER_ERROR_INVALID_ARGUMENT;
297    /* size = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; */
298    format->type->video.width = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
299    format->type->video.height = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
300    memcpy(&fourcc, p + 16, 4);
301   
302    format->es_type = VC_CONTAINER_ES_TYPE_VIDEO;
303    format->codec = vfw_fourcc_to_codec(fourcc);
304    
305    /* If no mapping is found from vfw, try a more generic one */
306    if (format->codec == fourcc && (fourcc = fourcc_to_codec(fourcc)) != VC_CONTAINER_CODEC_UNKNOWN)
307       format->codec = fourcc;
308
309    if(extra_offset) *extra_offset = BITMAPINFOHEADER_SIZE_MAX;
310    if(extra_size) 
311    {
312       if (buffer_size > BITMAPINFOHEADER_SIZE_MAX)
313          *extra_size = buffer_size - BITMAPINFOHEADER_SIZE_MAX;
314       else
315          *extra_size = 0;
316    }
317
318    return VC_CONTAINER_SUCCESS;   
319 }
320
321 /*****************************************************************************/
322 static struct {
323    VC_CONTAINER_METADATA_KEY_T key;
324    const char *name;
325 } meta_key_conv[] =
326 {  {VC_CONTAINER_METADATA_KEY_TITLE, "title"},
327    {VC_CONTAINER_METADATA_KEY_ARTIST, "artist"},
328    {VC_CONTAINER_METADATA_KEY_ALBUM, "album"},
329    {VC_CONTAINER_METADATA_KEY_DESCRIPTION, "description"},
330    {VC_CONTAINER_METADATA_KEY_YEAR, "year"},
331    {VC_CONTAINER_METADATA_KEY_GENRE, "genre"},
332    {VC_CONTAINER_METADATA_KEY_TRACK, "track"},
333    {VC_CONTAINER_METADATA_KEY_LYRICS, "lyrics"},
334    {VC_CONTAINER_METADATA_KEY_UNKNOWN, 0} };
335
336 /*****************************************************************************/
337 const char *vc_container_metadata_id_to_string(VC_CONTAINER_METADATA_KEY_T key)
338 {
339    int i;
340    for(i = 0; meta_key_conv[i].key != VC_CONTAINER_METADATA_KEY_UNKNOWN; i++ )
341       if(meta_key_conv[i].key == key) break;
342    return meta_key_conv[i].name;
343 }
344
345 /*****************************************************************************/
346 int64_t vc_container_maths_gcd(int64_t a, int64_t b)
347 {
348    while(b != 0)
349    {
350       int64_t t = b;
351       b = a % b;
352       a = t;
353    }
354    return a;
355 }
356
357 /*****************************************************************************/
358 void vc_container_maths_rational_simplify(uint32_t *num, uint32_t *den)
359 {
360    int64_t div = vc_container_maths_gcd((int64_t)*num, (int64_t)*den);
361    if(div)
362    {
363       *num /= div;
364       *den /= div;
365    }
366 }