1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2005 x264 project
7 * Authors: Mike Matsnev
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
28 mk_Context
*mk_createContext(mk_Writer
*w
, mk_Context
*parent
, unsigned id
) {
33 w
->freelist
= w
->freelist
->next
;
35 c
= malloc(sizeof(*c
));
36 memset(c
, 0, sizeof(*c
));
46 if (c
->owner
->actlist
)
47 c
->owner
->actlist
->prev
= &c
->next
;
48 c
->next
= c
->owner
->actlist
;
49 c
->prev
= &c
->owner
->actlist
;
54 int mk_appendContextData(mk_Context
*c
, const void *data
, uint64_t size
) {
55 uint64_t ns
= c
->d_cur
+ size
;
59 uint64_t dn
= c
->d_max
? c
->d_max
<< 1 : 16;
63 dp
= realloc(c
->data
, dn
);
71 memcpy((char*)c
->data
+ c
->d_cur
, data
, size
);
78 int mk_writeID(mk_Context
*c
, unsigned id
) {
79 unsigned char c_id
[4] = { id
>> 24, id
>> 16, id
>> 8, id
};
82 return mk_appendContextData(c
, c_id
, 4);
84 return mk_appendContextData(c
, c_id
+1, 3);
86 return mk_appendContextData(c
, c_id
+2, 2);
87 return mk_appendContextData(c
, c_id
+3, 1);
90 int mk_writeSize(mk_Context
*c
, uint64_t size
) {
91 unsigned char c_size
[8] = { 0x01, size
>> 48, size
>> 40, size
>> 32, size
>> 24, size
>> 16, size
>> 8, size
};
95 return mk_appendContextData(c
, c_size
+7, 1);
99 return mk_appendContextData(c
, c_size
+6, 2);
101 if (size
< 0x1fffff) {
103 return mk_appendContextData(c
, c_size
+5, 3);
105 if (size
< 0x0fffffff) {
107 return mk_appendContextData(c
, c_size
+4, 4);
109 if (size
< 0x07ffffffff) {
111 return mk_appendContextData(c
, c_size
+3, 5);
113 if (size
< 0x03ffffffffff) {
115 return mk_appendContextData(c
, c_size
+2, 6);
117 if (size
< 0x01ffffffffffff) {
119 return mk_appendContextData(c
, c_size
+1, 7);
121 return mk_appendContextData(c
, c_size
, 9);
124 int mk_writeSSize(mk_Context
*c
, int64_t size
) {
125 uint64_t u_size
= (uint64_t)llabs(size
);
126 unsigned size_size
= mk_ebmlSizeSize( u_size
<< 1 ); // We need to shift by one to get the correct size here.
143 size
+= 0x03ffffffff;
146 size
+= 0x01ffffffffff;
149 size
+= 0x00ffffffffffff;
151 default: // Matroska currently doesn't support any int > 56-bit.
155 return mk_writeSize(c
, size
);
158 int mk_flushContextID(mk_Context
*c
) {
159 unsigned char size_undf
[8] = {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
164 CHECK(mk_writeID(c
->parent
, c
->id
));
165 CHECK(mk_appendContextData(c
->parent
, &size_undf
, 8));
172 int mk_flushContextData(mk_Context
*c
) {
177 CHECK(mk_appendContextData(c
->parent
, c
->data
, c
->d_cur
));
179 if (fwrite(c
->data
, c
->d_cur
, 1, c
->owner
->fp
) != 1)
181 w
->f_pos
+= c
->d_cur
;
182 if (w
->f_pos
> w
->f_eof
)
191 int mk_closeContext(mk_Context
*c
, off_t
*off
) {
193 CHECK(mk_writeID(c
->parent
, c
->id
));
194 CHECK(mk_writeSize(c
->parent
, c
->d_cur
));
197 if (c
->parent
&& off
!= NULL
)
198 *off
+= c
->parent
->d_cur
;
200 CHECK(mk_flushContextData(c
));
203 c
->next
->prev
= c
->prev
;
204 *(c
->prev
) = c
->next
;
205 c
->next
= c
->owner
->freelist
;
206 c
->owner
->freelist
= c
;
211 void mk_destroyContexts(mk_Writer
*w
) {
212 mk_Context
*cur
, *next
;
214 for (cur
= w
->freelist
; cur
; cur
= next
) {
220 for (cur
= w
->actlist
; cur
; cur
= next
) {
226 w
->freelist
= w
->actlist
= w
->root
= NULL
;
229 int mk_writeStr(mk_Context
*c
, unsigned id
, const char *str
) {
230 size_t len
= strlen(str
);
232 CHECK(mk_writeID(c
, id
));
233 CHECK(mk_writeSize(c
, len
));
234 CHECK(mk_appendContextData(c
, str
, len
));
238 int mk_writeBin(mk_Context
*c
, unsigned id
, const void *data
, unsigned size
) {
239 CHECK(mk_writeID(c
, id
));
240 CHECK(mk_writeSize(c
, size
));
241 CHECK(mk_appendContextData(c
, data
, size
));
245 int mk_writeUInt(mk_Context
*c
, unsigned id
, uint64_t ui
) {
246 unsigned char c_ui
[8] = { ui
>> 56, ui
>> 48, ui
>> 40, ui
>> 32, ui
>> 24, ui
>> 16, ui
>> 8, ui
};
249 CHECK(mk_writeID(c
, id
));
250 while (i
< 7 && c_ui
[i
] == 0)
252 CHECK(mk_writeSize(c
, 8 - i
));
253 CHECK(mk_appendContextData(c
, c_ui
+i
, 8 - i
));
257 int mk_writeSInt(mk_Context
*c
, unsigned id
, int64_t si
) {
258 unsigned char c_si
[8] = { si
>> 56, si
>> 48, si
>> 40, si
>> 32, si
>> 24, si
>> 16, si
>> 8, si
};
261 CHECK(mk_writeID(c
, id
));
263 while (i
< 7 && c_si
[i
] == 0xff && c_si
[i
+1] & 0x80)
266 while (i
< 7 && c_si
[i
] == 0 && !(c_si
[i
+1] & 0x80))
268 CHECK(mk_writeSize(c
, 8 - i
));
269 CHECK(mk_appendContextData(c
, c_si
+i
, 8 - i
));
273 int mk_writeFloatRaw(mk_Context
*c
, float f
) {
278 unsigned char c_f
[4];
286 return mk_appendContextData(c
, c_f
, 4);
289 int mk_writeFloat(mk_Context
*c
, unsigned id
, float f
) {
290 CHECK(mk_writeID(c
, id
));
291 CHECK(mk_writeSize(c
, 4));
292 CHECK(mk_writeFloatRaw(c
, f
));
296 unsigned mk_ebmlSizeSize(uint64_t s
) {
305 if (s
< 0x07ffffffff)
307 if (s
< 0x03ffffffffff)
309 if (s
< 0x01ffffffffffff)
314 unsigned mk_ebmlSIntSize(int64_t si
) {
315 unsigned char c_si
[8] = { si
>> 56, si
>> 48, si
>> 40, si
>> 32, si
>> 24, si
>> 16, si
>> 8, si
};
319 while (i
< 7 && c_si
[i
] == 0xff && c_si
[i
+1] & 0x80)
322 while (i
< 7 && c_si
[i
] == 0 && !(c_si
[i
+1] & 0x80))