1 /*****************************************************************************
2  * vlc_boxes.h : Boxes/Atoms handling helpers
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *          Gildas Bazin <gbazin at videolan dot org>
8  *          Rafaël Carré <funman at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program 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
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24 #ifndef VLC_BOXES_H
25 #define VLC_BOXES_H
26 
27 #include <vlc_common.h>
28 #include <vlc_block.h>
29 
30 /**
31  * \file
32  * This file defines functions, structures for handling boxes/atoms in vlc
33  */
34 
35 typedef struct bo_t
36 {
37     block_t     *b;
38     size_t      basesize;
39 } bo_t;
40 
bo_init(bo_t * p_bo,int i_size)41 static inline bool bo_init(bo_t *p_bo, int i_size)
42 {
43     p_bo->b = block_Alloc(i_size);
44     if (p_bo->b == NULL)
45         return false;
46 
47     p_bo->b->i_buffer = 0;
48     p_bo->basesize = i_size;
49 
50     return true;
51 }
52 
bo_deinit(bo_t * p_bo)53 static inline void bo_deinit(bo_t *p_bo)
54 {
55     if(p_bo->b)
56         block_Release(p_bo->b);
57 }
58 
bo_free(bo_t * p_bo)59 static inline void bo_free(bo_t *p_bo)
60 {
61     if(!p_bo)
62         return;
63     bo_deinit(p_bo);
64     free(p_bo);
65 }
66 
bo_extend(bo_t * p_bo,size_t i_total)67 static inline int bo_extend(bo_t *p_bo, size_t i_total)
68 {
69     if(!p_bo->b)
70         return false;
71     const size_t i_size = p_bo->b->i_size - (p_bo->b->p_buffer - p_bo->b->p_start);
72     if (i_total >= i_size)
73     {
74         int i_growth = p_bo->basesize;
75         while(i_total >= i_size + i_growth)
76             i_growth += p_bo->basesize;
77 
78         int i = p_bo->b->i_buffer; /* Realloc would set payload size == buffer size */
79         p_bo->b = block_Realloc(p_bo->b, 0, i_size + i_growth);
80         if (!p_bo->b)
81             return false;
82         p_bo->b->i_buffer = i;
83     }
84     return true;
85 }
86 
87 #define BO_SET_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, size_t i_offset, type val)\
88     {\
89         if (!bo_extend(p_bo, i_offset + sizeof(type)))\
90             return false;\
91         handler(&p_bo->b->p_buffer[i_offset], val);\
92         return true;\
93     }
94 
95 #define BO_ADD_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, type val)\
96     {\
97         if(!p_bo->b || !handler(p_bo, p_bo->b->i_buffer, val))\
98             return false;\
99         p_bo->b->i_buffer += sizeof(type);\
100         return true;\
101     }
102 
103 #define BO_FUNC_DECL(suffix, handler, type ) \
104     BO_SET_DECL_S( bo_set_ ## suffix ## be, handler ## BE, type )\
105     BO_SET_DECL_S( bo_set_ ## suffix ## le, handler ## LE, type )\
106     BO_ADD_DECL_S( bo_add_ ## suffix ## be, bo_set_ ## suffix ## be, type )\
107     BO_ADD_DECL_S( bo_add_ ## suffix ## le, bo_set_ ## suffix ## le, type )
108 
bo_set_8(bo_t * p_bo,size_t i_offset,uint8_t i)109 static inline bool bo_set_8(bo_t *p_bo, size_t i_offset, uint8_t i)
110 {
111     if (!bo_extend(p_bo, i_offset + 1))
112         return false;
113     p_bo->b->p_buffer[i_offset] = i;
114     return true;
115 }
116 
bo_add_8(bo_t * p_bo,uint8_t i)117 static inline bool bo_add_8(bo_t *p_bo, uint8_t i)
118 {
119     if(!p_bo->b || !bo_set_8( p_bo, p_bo->b->i_buffer, i ))
120         return false;
121     p_bo->b->i_buffer++;
122     return true;
123 }
124 
125 /* declares all bo_[set,add]_[16,32,64] */
126 BO_FUNC_DECL( 16, SetW,  uint16_t )
127 BO_FUNC_DECL( 32, SetDW, uint32_t )
128 BO_FUNC_DECL( 64, SetQW, uint64_t )
129 
130 #undef BO_FUNC_DECL
131 #undef BO_SET_DECL_S
132 #undef BO_ADD_DECL_S
133 
bo_add_24be(bo_t * p_bo,uint32_t i)134 static inline bool bo_add_24be(bo_t *p_bo, uint32_t i)
135 {
136     if(!p_bo->b || !bo_extend(p_bo, p_bo->b->i_buffer + 3))
137         return false;
138     p_bo->b->p_buffer[p_bo->b->i_buffer++] = ((i >> 16) & 0xff);
139     p_bo->b->p_buffer[p_bo->b->i_buffer++] = ((i >> 8) & 0xff);
140     p_bo->b->p_buffer[p_bo->b->i_buffer++] = (i & 0xff);
141     return true;
142 }
143 
bo_swap_32be(bo_t * p_bo,size_t i_pos,uint32_t i)144 static inline void bo_swap_32be (bo_t *p_bo, size_t i_pos, uint32_t i)
145 {
146     if (!p_bo->b || p_bo->b->i_buffer < i_pos + 4)
147         return;
148     p_bo->b->p_buffer[i_pos    ] = (i >> 24)&0xff;
149     p_bo->b->p_buffer[i_pos + 1] = (i >> 16)&0xff;
150     p_bo->b->p_buffer[i_pos + 2] = (i >>  8)&0xff;
151     p_bo->b->p_buffer[i_pos + 3] = (i      )&0xff;
152 }
153 
bo_add_mem(bo_t * p_bo,size_t i_size,const void * p_mem)154 static inline bool bo_add_mem(bo_t *p_bo, size_t i_size, const void *p_mem)
155 {
156     if(!p_bo->b || !bo_extend(p_bo, p_bo->b->i_buffer + i_size))
157         return false;
158     memcpy(&p_bo->b->p_buffer[p_bo->b->i_buffer], p_mem, i_size);
159     p_bo->b->i_buffer += i_size;
160     return true;
161 }
162 
163 #define bo_add_fourcc(p_bo, fcc) bo_add_mem(p_bo, 4, fcc)
164 
165 #endif // VLC_BOXES_H
166