Mercurial > mplayer.hg
annotate stream/realrtsp/rmff.c @ 21460:62bd8e0d3a0f
Open embedded fonts directly from memory.
FontConfig 2.4.2 (released yesterday) supports scanning fonts with
FcFreeTypeQueryFace without writing them to disk. With earlier FontConfig
versions, the old mechanism is used.
author | eugeni |
---|---|
date | Sun, 03 Dec 2006 18:24:11 +0000 |
parents | de8bbed6c79e |
children | 6c1fe779b704 |
rev | line source |
---|---|
9922 | 1 /* |
2 * This file was ported to MPlayer from xine CVS rmff.c,v 1.3 2002/12/24 01:30:22 | |
3 */ | |
4 | |
5 /* | |
6 * Copyright (C) 2002 the xine project | |
7 * | |
8 * This file is part of xine, a free video player. | |
9 * | |
10 * xine 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. | |
14 * | |
15 * xine 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. | |
19 * | |
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-1307, USA | |
23 * | |
24 * | |
25 * functions for real media file format | |
26 * adopted from joschkas real tools | |
27 */ | |
28 | |
29 #include "rmff.h" | |
30 #include "xbuffer.h" | |
20711 | 31 #include "mp_msg.h" |
9922 | 32 |
33 /* | |
34 #define LOG | |
35 */ | |
36 | |
37 #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) | |
38 #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ | |
39 (((uint8_t*)(x))[1] << 16) | \ | |
40 (((uint8_t*)(x))[2] << 8) | \ | |
41 ((uint8_t*)(x))[3]) | |
42 | |
43 static void hexdump (const char *buf, int length) { | |
44 | |
45 int i; | |
46 | |
47 printf ("rmff: ascii>"); | |
48 for (i = 0; i < length; i++) { | |
49 unsigned char c = buf[i]; | |
50 | |
51 if ((c >= 32) && (c <= 128)) | |
52 printf ("%c", c); | |
53 else | |
54 printf ("."); | |
55 } | |
56 printf ("\n"); | |
57 | |
58 printf ("rmff: hexdump> "); | |
59 for (i = 0; i < length; i++) { | |
60 unsigned char c = buf[i]; | |
61 | |
62 printf ("%02x", c); | |
63 | |
64 if ((i % 16) == 15) | |
65 printf ("\nrmff: "); | |
66 | |
67 if ((i % 2) == 1) | |
68 printf (" "); | |
69 | |
70 } | |
71 printf ("\n"); | |
72 } | |
73 | |
74 /* | |
75 * writes header data to a buffer | |
76 */ | |
77 | |
78 static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) { | |
79 | |
80 if (!fileheader) return; | |
81 fileheader->object_id=BE_32(&fileheader->object_id); | |
82 fileheader->size=BE_32(&fileheader->size); | |
83 fileheader->object_version=BE_16(&fileheader->object_version); | |
84 fileheader->file_version=BE_32(&fileheader->file_version); | |
85 fileheader->num_headers=BE_32(&fileheader->num_headers); | |
86 | |
87 memcpy(buffer, fileheader, 8); | |
88 memcpy(&buffer[8], &fileheader->object_version, 2); | |
89 memcpy(&buffer[10], &fileheader->file_version, 8); | |
90 | |
91 fileheader->size=BE_32(&fileheader->size); | |
92 fileheader->object_version=BE_16(&fileheader->object_version); | |
93 fileheader->file_version=BE_32(&fileheader->file_version); | |
94 fileheader->num_headers=BE_32(&fileheader->num_headers); | |
95 fileheader->object_id=BE_32(&fileheader->object_id); | |
96 } | |
97 | |
98 static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) { | |
99 | |
100 if (!prop) return; | |
101 prop->object_id=BE_32(&prop->object_id); | |
102 prop->size=BE_32(&prop->size); | |
103 prop->object_version=BE_16(&prop->object_version); | |
104 prop->max_bit_rate=BE_32(&prop->max_bit_rate); | |
105 prop->avg_bit_rate=BE_32(&prop->avg_bit_rate); | |
106 prop->max_packet_size=BE_32(&prop->max_packet_size); | |
107 prop->avg_packet_size=BE_32(&prop->avg_packet_size); | |
108 prop->num_packets=BE_32(&prop->num_packets); | |
109 prop->duration=BE_32(&prop->duration); | |
110 prop->preroll=BE_32(&prop->preroll); | |
111 prop->index_offset=BE_32(&prop->index_offset); | |
112 prop->data_offset=BE_32(&prop->data_offset); | |
113 prop->num_streams=BE_16(&prop->num_streams); | |
114 prop->flags=BE_16(&prop->flags); | |
115 | |
116 memcpy(buffer, prop, 8); | |
117 memcpy(&buffer[8], &prop->object_version, 2); | |
118 memcpy(&buffer[10], &prop->max_bit_rate, 36); | |
119 memcpy(&buffer[46], &prop->num_streams, 2); | |
120 memcpy(&buffer[48], &prop->flags, 2); | |
121 | |
122 prop->size=BE_32(&prop->size); | |
123 prop->object_version=BE_16(&prop->object_version); | |
124 prop->max_bit_rate=BE_32(&prop->max_bit_rate); | |
125 prop->avg_bit_rate=BE_32(&prop->avg_bit_rate); | |
126 prop->max_packet_size=BE_32(&prop->max_packet_size); | |
127 prop->avg_packet_size=BE_32(&prop->avg_packet_size); | |
128 prop->num_packets=BE_32(&prop->num_packets); | |
129 prop->duration=BE_32(&prop->duration); | |
130 prop->preroll=BE_32(&prop->preroll); | |
131 prop->index_offset=BE_32(&prop->index_offset); | |
132 prop->data_offset=BE_32(&prop->data_offset); | |
133 prop->num_streams=BE_16(&prop->num_streams); | |
134 prop->flags=BE_16(&prop->flags); | |
135 prop->object_id=BE_32(&prop->object_id); | |
136 } | |
137 | |
138 static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) { | |
139 | |
140 int s1, s2, s3; | |
141 | |
142 if (!mdpr) return; | |
143 mdpr->object_id=BE_32(&mdpr->object_id); | |
144 mdpr->size=BE_32(&mdpr->size); | |
145 mdpr->object_version=BE_16(&mdpr->object_version); | |
146 mdpr->stream_number=BE_16(&mdpr->stream_number); | |
147 mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate); | |
148 mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate); | |
149 mdpr->max_packet_size=BE_32(&mdpr->max_packet_size); | |
150 mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size); | |
151 mdpr->start_time=BE_32(&mdpr->start_time); | |
152 mdpr->preroll=BE_32(&mdpr->preroll); | |
153 mdpr->duration=BE_32(&mdpr->duration); | |
154 | |
155 memcpy(buffer, mdpr, 8); | |
156 memcpy(&buffer[8], &mdpr->object_version, 2); | |
157 memcpy(&buffer[10], &mdpr->stream_number, 2); | |
158 memcpy(&buffer[12], &mdpr->max_bit_rate, 28); | |
159 memcpy(&buffer[40], &mdpr->stream_name_size, 1); | |
160 s1=mdpr->stream_name_size; | |
161 memcpy(&buffer[41], mdpr->stream_name, s1); | |
162 | |
163 memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1); | |
164 s2=mdpr->mime_type_size; | |
165 memcpy(&buffer[42+s1], mdpr->mime_type, s2); | |
166 | |
167 mdpr->type_specific_len=BE_32(&mdpr->type_specific_len); | |
168 memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4); | |
169 mdpr->type_specific_len=BE_32(&mdpr->type_specific_len); | |
170 s3=mdpr->type_specific_len; | |
171 memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3); | |
172 | |
173 mdpr->size=BE_32(&mdpr->size); | |
174 mdpr->stream_number=BE_16(&mdpr->stream_number); | |
175 mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate); | |
176 mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate); | |
177 mdpr->max_packet_size=BE_32(&mdpr->max_packet_size); | |
178 mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size); | |
179 mdpr->start_time=BE_32(&mdpr->start_time); | |
180 mdpr->preroll=BE_32(&mdpr->preroll); | |
181 mdpr->duration=BE_32(&mdpr->duration); | |
182 mdpr->object_id=BE_32(&mdpr->object_id); | |
183 | |
184 } | |
185 | |
186 static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) { | |
187 | |
188 int p; | |
189 | |
190 if (!cont) return; | |
191 cont->object_id=BE_32(&cont->object_id); | |
192 cont->size=BE_32(&cont->size); | |
193 cont->object_version=BE_16(&cont->object_version); | |
194 | |
195 memcpy(buffer, cont, 8); | |
196 memcpy(&buffer[8], &cont->object_version, 2); | |
197 | |
198 cont->title_len=BE_16(&cont->title_len); | |
199 memcpy(&buffer[10], &cont->title_len, 2); | |
200 cont->title_len=BE_16(&cont->title_len); | |
201 memcpy(&buffer[12], cont->title, cont->title_len); | |
202 p=12+cont->title_len; | |
203 | |
204 cont->author_len=BE_16(&cont->author_len); | |
205 memcpy(&buffer[p], &cont->author_len, 2); | |
206 cont->author_len=BE_16(&cont->author_len); | |
207 memcpy(&buffer[p+2], cont->author, cont->author_len); | |
208 p+=2+cont->author_len; | |
209 | |
210 cont->copyright_len=BE_16(&cont->copyright_len); | |
211 memcpy(&buffer[p], &cont->copyright_len, 2); | |
212 cont->copyright_len=BE_16(&cont->copyright_len); | |
213 memcpy(&buffer[p+2], cont->copyright, cont->copyright_len); | |
214 p+=2+cont->copyright_len; | |
215 | |
216 cont->comment_len=BE_16(&cont->comment_len); | |
217 memcpy(&buffer[p], &cont->comment_len, 2); | |
218 cont->comment_len=BE_16(&cont->comment_len); | |
219 memcpy(&buffer[p+2], cont->comment, cont->comment_len); | |
220 | |
221 cont->size=BE_32(&cont->size); | |
222 cont->object_version=BE_16(&cont->object_version); | |
223 cont->object_id=BE_32(&cont->object_id); | |
224 } | |
225 | |
226 static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) { | |
227 | |
228 if (!data) return; | |
229 data->object_id=BE_32(&data->object_id); | |
230 data->size=BE_32(&data->size); | |
231 data->object_version=BE_16(&data->object_version); | |
232 data->num_packets=BE_32(&data->num_packets); | |
233 data->next_data_header=BE_32(&data->next_data_header); | |
234 | |
235 memcpy(buffer, data, 8); | |
236 memcpy(&buffer[8], &data->object_version, 2); | |
237 memcpy(&buffer[10], &data->num_packets, 8); | |
238 | |
239 data->num_packets=BE_32(&data->num_packets); | |
240 data->next_data_header=BE_32(&data->next_data_header); | |
241 data->size=BE_32(&data->size); | |
242 data->object_version=BE_16(&data->object_version); | |
243 data->object_id=BE_32(&data->object_id); | |
244 } | |
245 | |
246 int rmff_dump_header(rmff_header_t *h, char *buffer, int max) { | |
247 | |
248 int written=0; | |
249 rmff_mdpr_t **stream=h->streams; | |
250 | |
251 rmff_dump_fileheader(h->fileheader, &buffer[written]); | |
252 written+=h->fileheader->size; | |
253 rmff_dump_prop(h->prop, &buffer[written]); | |
254 written+=h->prop->size; | |
255 rmff_dump_cont(h->cont, &buffer[written]); | |
256 written+=h->cont->size; | |
257 if (stream) | |
258 { | |
259 while(*stream) | |
260 { | |
261 rmff_dump_mdpr(*stream, &buffer[written]); | |
262 written+=(*stream)->size; | |
263 stream++; | |
264 } | |
265 } | |
266 | |
267 rmff_dump_dataheader(h->data, &buffer[written]); | |
268 written+=18; | |
269 | |
270 return written; | |
271 } | |
272 | |
273 void rmff_dump_pheader(rmff_pheader_t *h, char *data) { | |
274 | |
275 data[0]=(h->object_version>>8) & 0xff; | |
276 data[1]=h->object_version & 0xff; | |
277 data[2]=(h->length>>8) & 0xff; | |
278 data[3]=h->length & 0xff; | |
279 data[4]=(h->stream_number>>8) & 0xff; | |
280 data[5]=h->stream_number & 0xff; | |
281 data[6]=(h->timestamp>>24) & 0xff; | |
282 data[7]=(h->timestamp>>16) & 0xff; | |
283 data[8]=(h->timestamp>>8) & 0xff; | |
284 data[9]=h->timestamp & 0xff; | |
285 data[10]=h->reserved; | |
286 data[11]=h->flags; | |
287 } | |
288 | |
289 static rmff_fileheader_t *rmff_scan_fileheader(const char *data) { | |
290 | |
291 rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t)); | |
292 | |
293 fileheader->object_id=BE_32(data); | |
294 fileheader->size=BE_32(&data[4]); | |
295 fileheader->object_version=BE_16(&data[8]); | |
296 if (fileheader->object_version != 0) | |
297 { | |
20711 | 298 mp_msg(MSGT_STREAM, MSGL_WARN, "warning: unknown object version in .RMF: 0x%04x\n", |
9922 | 299 fileheader->object_version); |
300 } | |
301 fileheader->file_version=BE_32(&data[10]); | |
302 fileheader->num_headers=BE_32(&data[14]); | |
303 | |
304 return fileheader; | |
305 } | |
306 | |
307 static rmff_prop_t *rmff_scan_prop(const char *data) { | |
308 | |
309 rmff_prop_t *prop=malloc(sizeof(rmff_prop_t)); | |
310 | |
311 prop->object_id=BE_32(data); | |
312 prop->size=BE_32(&data[4]); | |
313 prop->object_version=BE_16(&data[8]); | |
314 if (prop->object_version != 0) | |
315 { | |
20711 | 316 mp_msg(MSGT_STREAM, MSGL_WARN, "warning: unknown object version in PROP: 0x%04x\n", |
9922 | 317 prop->object_version); |
318 } | |
319 prop->max_bit_rate=BE_32(&data[10]); | |
320 prop->avg_bit_rate=BE_32(&data[14]); | |
321 prop->max_packet_size=BE_32(&data[18]); | |
322 prop->avg_packet_size=BE_32(&data[22]); | |
323 prop->num_packets=BE_32(&data[26]); | |
324 prop->duration=BE_32(&data[30]); | |
325 prop->preroll=BE_32(&data[34]); | |
326 prop->index_offset=BE_32(&data[38]); | |
327 prop->data_offset=BE_32(&data[42]); | |
328 prop->num_streams=BE_16(&data[46]); | |
329 prop->flags=BE_16(&data[48]); | |
330 | |
331 return prop; | |
332 } | |
333 | |
334 static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { | |
335 | |
336 rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t)); | |
337 | |
338 mdpr->object_id=BE_32(data); | |
339 mdpr->size=BE_32(&data[4]); | |
340 mdpr->object_version=BE_16(&data[8]); | |
341 if (mdpr->object_version != 0) | |
342 { | |
20711 | 343 mp_msg(MSGT_STREAM, MSGL_WARN, "warning: unknown object version in MDPR: 0x%04x\n", |
9922 | 344 mdpr->object_version); |
345 } | |
346 mdpr->stream_number=BE_16(&data[10]); | |
347 mdpr->max_bit_rate=BE_32(&data[12]); | |
348 mdpr->avg_bit_rate=BE_32(&data[16]); | |
349 mdpr->max_packet_size=BE_32(&data[20]); | |
350 mdpr->avg_packet_size=BE_32(&data[24]); | |
351 mdpr->start_time=BE_32(&data[28]); | |
352 mdpr->preroll=BE_32(&data[32]); | |
353 mdpr->duration=BE_32(&data[36]); | |
354 | |
355 mdpr->stream_name_size=data[40]; | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
356 mdpr->stream_name=malloc(mdpr->stream_name_size+1); |
9922 | 357 memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size); |
358 mdpr->stream_name[mdpr->stream_name_size]=0; | |
359 | |
360 mdpr->mime_type_size=data[41+mdpr->stream_name_size]; | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
361 mdpr->mime_type=malloc(mdpr->mime_type_size+1); |
9922 | 362 memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size); |
363 mdpr->mime_type[mdpr->mime_type_size]=0; | |
364 | |
365 mdpr->type_specific_len=BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]); | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
366 mdpr->type_specific_data=malloc(mdpr->type_specific_len); |
9922 | 367 memcpy(mdpr->type_specific_data, |
368 &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); | |
369 | |
370 return mdpr; | |
371 } | |
372 | |
373 static rmff_cont_t *rmff_scan_cont(const char *data) { | |
374 | |
375 rmff_cont_t *cont=malloc(sizeof(rmff_cont_t)); | |
376 int pos; | |
377 | |
378 cont->object_id=BE_32(data); | |
379 cont->size=BE_32(&data[4]); | |
380 cont->object_version=BE_16(&data[8]); | |
381 if (cont->object_version != 0) | |
382 { | |
20711 | 383 mp_msg(MSGT_STREAM, MSGL_WARN, "warning: unknown object version in CONT: 0x%04x\n", |
9922 | 384 cont->object_version); |
385 } | |
386 cont->title_len=BE_16(&data[10]); | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
387 cont->title=malloc(cont->title_len+1); |
9922 | 388 memcpy(cont->title, &data[12], cont->title_len); |
389 cont->title[cont->title_len]=0; | |
390 pos=cont->title_len+12; | |
391 cont->author_len=BE_16(&data[pos]); | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
392 cont->author=malloc(cont->author_len+1); |
9922 | 393 memcpy(cont->author, &data[pos+2], cont->author_len); |
394 cont->author[cont->author_len]=0; | |
395 pos=pos+2+cont->author_len; | |
396 cont->copyright_len=BE_16(&data[pos]); | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
397 cont->copyright=malloc(cont->copyright_len+1); |
9922 | 398 memcpy(cont->copyright, &data[pos+2], cont->copyright_len); |
399 cont->copyright[cont->copyright_len]=0; | |
400 pos=pos+2+cont->copyright_len; | |
401 cont->comment_len=BE_16(&data[pos]); | |
19074
d385666efa27
removes unused parentheses lefted behind in the r19075 sizeof(char) cleanups, noticed by dalias
reynaldo
parents:
19070
diff
changeset
|
402 cont->comment=malloc(cont->comment_len+1); |
9922 | 403 memcpy(cont->comment, &data[pos+2], cont->comment_len); |
404 cont->comment[cont->comment_len]=0; | |
405 | |
406 return cont; | |
407 } | |
408 | |
409 static rmff_data_t *rmff_scan_dataheader(const char *data) { | |
410 | |
411 rmff_data_t *dh=malloc(sizeof(rmff_data_t)); | |
412 | |
413 dh->object_id=BE_32(data); | |
414 dh->size=BE_32(&data[4]); | |
415 dh->object_version=BE_16(&data[8]); | |
416 if (dh->object_version != 0) | |
417 { | |
20711 | 418 mp_msg(MSGT_STREAM, MSGL_WARN, "warning: unknown object version in DATA: 0x%04x\n", |
9922 | 419 dh->object_version); |
420 } | |
421 dh->num_packets=BE_32(&data[10]); | |
422 dh->next_data_header=BE_32(&data[14]); | |
423 | |
424 return dh; | |
425 } | |
426 | |
427 rmff_header_t *rmff_scan_header(const char *data) { | |
428 | |
429 rmff_header_t *header=malloc(sizeof(rmff_header_t)); | |
430 rmff_mdpr_t *mdpr=NULL; | |
431 int chunk_size; | |
432 uint32_t chunk_type; | |
433 const char *ptr=data; | |
434 int i; | |
435 | |
436 header->fileheader=NULL; | |
437 header->prop=NULL; | |
438 header->cont=NULL; | |
439 header->data=NULL; | |
440 | |
441 chunk_type = BE_32(ptr); | |
442 if (chunk_type != RMF_TAG) | |
443 { | |
20711 | 444 mp_msg(MSGT_STREAM, MSGL_ERR, "rmff: not an real media file header (.RMF tag not found).\n"); |
9922 | 445 free(header); |
446 return NULL; | |
447 } | |
448 header->fileheader=rmff_scan_fileheader(ptr); | |
449 ptr += header->fileheader->size; | |
450 | |
451 header->streams=malloc(sizeof(rmff_mdpr_t*)*(header->fileheader->num_headers)); | |
452 for (i=0; i<header->fileheader->num_headers; i++) { | |
453 header->streams[i]=NULL; | |
454 } | |
455 | |
456 for (i=1; i<header->fileheader->num_headers; i++) { | |
457 chunk_type = BE_32(ptr); | |
458 | |
459 if (ptr[0] == 0) | |
460 { | |
20711 | 461 mp_msg(MSGT_STREAM, MSGL_WARN, "rmff: warning: only %d of %d header found.\n", i, header->fileheader->num_headers); |
9922 | 462 break; |
463 } | |
464 | |
465 chunk_size=1; | |
466 switch (chunk_type) { | |
467 case PROP_TAG: | |
468 header->prop=rmff_scan_prop(ptr); | |
469 chunk_size=header->prop->size; | |
470 break; | |
471 case MDPR_TAG: | |
472 mdpr=rmff_scan_mdpr(ptr); | |
473 chunk_size=mdpr->size; | |
474 header->streams[mdpr->stream_number]=mdpr; | |
475 break; | |
476 case CONT_TAG: | |
477 header->cont=rmff_scan_cont(ptr); | |
478 chunk_size=header->cont->size; | |
479 break; | |
480 case DATA_TAG: | |
481 header->data=rmff_scan_dataheader(ptr); | |
482 chunk_size=34; /* hard coded header size */ | |
483 break; | |
484 default: | |
20711 | 485 mp_msg(MSGT_STREAM, MSGL_WARN, "unknown chunk\n"); |
9922 | 486 hexdump(ptr,10); |
487 chunk_size=1; | |
488 break; | |
489 } | |
490 ptr+=chunk_size; | |
491 } | |
492 | |
493 return header; | |
494 } | |
495 | |
496 rmff_header_t *rmff_scan_header_stream(int fd) { | |
497 | |
498 rmff_header_t *header; | |
499 char *buf=xbuffer_init(1024); | |
500 int index=0; | |
501 uint32_t chunk_type; | |
502 uint32_t chunk_size; | |
503 | |
504 do { | |
505 buf = xbuffer_ensure_size(buf, index+8); | |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
9922
diff
changeset
|
506 recv(fd, buf+index, 8, 0); |
9922 | 507 chunk_type=BE_32(buf+index); index+=4; |
508 chunk_size=BE_32(buf+index); index+=4; | |
509 | |
510 switch (chunk_type) { | |
511 case DATA_TAG: | |
512 chunk_size=18; | |
513 case MDPR_TAG: | |
514 case CONT_TAG: | |
515 case RMF_TAG: | |
516 case PROP_TAG: | |
517 buf = xbuffer_ensure_size(buf, index+chunk_size-8); | |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
9922
diff
changeset
|
518 recv(fd, buf+index, (chunk_size-8), 0); |
9922 | 519 index+=(chunk_size-8); |
520 break; | |
521 default: | |
20711 | 522 mp_msg(MSGT_STREAM, MSGL_WARN, "rmff_scan_header_stream: unknown chunk"); |
9922 | 523 hexdump(buf+index-8, 8); |
524 chunk_type=DATA_TAG; | |
525 } | |
526 } while (chunk_type != DATA_TAG); | |
527 | |
528 header = rmff_scan_header(buf); | |
529 | |
530 xbuffer_free(buf); | |
531 | |
532 return header; | |
533 } | |
534 | |
535 void rmff_scan_pheader(rmff_pheader_t *h, char *data) { | |
536 | |
537 h->object_version=BE_16(data); | |
538 h->length=BE_16(data+2); | |
539 h->stream_number=BE_16(data+4); | |
540 h->timestamp=BE_32(data+6); | |
541 h->reserved=(uint8_t)data[10]; | |
542 h->flags=(uint8_t)data[11]; | |
543 } | |
544 | |
545 rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) { | |
546 | |
547 rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t)); | |
548 | |
549 fileheader->object_id=RMF_TAG; | |
550 fileheader->size=18; | |
551 fileheader->object_version=0; | |
552 fileheader->file_version=0; | |
553 fileheader->num_headers=num_headers; | |
554 | |
555 return fileheader; | |
556 } | |
557 | |
558 rmff_prop_t *rmff_new_prop ( | |
559 uint32_t max_bit_rate, | |
560 uint32_t avg_bit_rate, | |
561 uint32_t max_packet_size, | |
562 uint32_t avg_packet_size, | |
563 uint32_t num_packets, | |
564 uint32_t duration, | |
565 uint32_t preroll, | |
566 uint32_t index_offset, | |
567 uint32_t data_offset, | |
568 uint16_t num_streams, | |
569 uint16_t flags ) { | |
570 | |
571 rmff_prop_t *prop=malloc(sizeof(rmff_prop_t)); | |
572 | |
573 prop->object_id=PROP_TAG; | |
574 prop->size=50; | |
575 prop->object_version=0; | |
576 | |
577 prop->max_bit_rate=max_bit_rate; | |
578 prop->avg_bit_rate=avg_bit_rate; | |
579 prop->max_packet_size=max_packet_size; | |
580 prop->avg_packet_size=avg_packet_size; | |
581 prop->num_packets=num_packets; | |
582 prop->duration=duration; | |
583 prop->preroll=preroll; | |
584 prop->index_offset=index_offset; | |
585 prop->data_offset=data_offset; | |
586 prop->num_streams=num_streams; | |
587 prop->flags=flags; | |
588 | |
589 return prop; | |
590 } | |
591 | |
592 rmff_mdpr_t *rmff_new_mdpr( | |
593 uint16_t stream_number, | |
594 uint32_t max_bit_rate, | |
595 uint32_t avg_bit_rate, | |
596 uint32_t max_packet_size, | |
597 uint32_t avg_packet_size, | |
598 uint32_t start_time, | |
599 uint32_t preroll, | |
600 uint32_t duration, | |
601 const char *stream_name, | |
602 const char *mime_type, | |
603 uint32_t type_specific_len, | |
604 const char *type_specific_data ) { | |
605 | |
606 rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t)); | |
607 | |
608 mdpr->object_id=MDPR_TAG; | |
609 mdpr->object_version=0; | |
610 | |
611 mdpr->stream_number=stream_number; | |
612 mdpr->max_bit_rate=max_bit_rate; | |
613 mdpr->avg_bit_rate=avg_bit_rate; | |
614 mdpr->max_packet_size=max_packet_size; | |
615 mdpr->avg_packet_size=avg_packet_size; | |
616 mdpr->start_time=start_time; | |
617 mdpr->preroll=preroll; | |
618 mdpr->duration=duration; | |
619 mdpr->stream_name_size=0; | |
620 if (stream_name) { | |
621 mdpr->stream_name=strdup(stream_name); | |
622 mdpr->stream_name_size=strlen(stream_name); | |
623 } | |
624 mdpr->mime_type_size=0; | |
625 if (mime_type) { | |
626 mdpr->mime_type=strdup(mime_type); | |
627 mdpr->mime_type_size=strlen(mime_type); | |
628 } | |
629 mdpr->type_specific_len=type_specific_len; | |
19070 | 630 mdpr->type_specific_data=malloc(type_specific_len); |
9922 | 631 memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len); |
632 mdpr->mlti_data=NULL; | |
633 | |
634 mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46; | |
635 | |
636 return mdpr; | |
637 } | |
638 | |
639 rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) { | |
640 | |
641 rmff_cont_t *cont=malloc(sizeof(rmff_cont_t)); | |
642 | |
643 cont->object_id=CONT_TAG; | |
644 cont->object_version=0; | |
645 | |
646 cont->title=NULL; | |
647 cont->author=NULL; | |
648 cont->copyright=NULL; | |
649 cont->comment=NULL; | |
650 | |
651 cont->title_len=0; | |
652 cont->author_len=0; | |
653 cont->copyright_len=0; | |
654 cont->comment_len=0; | |
655 | |
656 if (title) { | |
657 cont->title_len=strlen(title); | |
658 cont->title=strdup(title); | |
659 } | |
660 if (author) { | |
661 cont->author_len=strlen(author); | |
662 cont->author=strdup(author); | |
663 } | |
664 if (copyright) { | |
665 cont->copyright_len=strlen(copyright); | |
666 cont->copyright=strdup(copyright); | |
667 } | |
668 if (comment) { | |
669 cont->comment_len=strlen(comment); | |
670 cont->comment=strdup(comment); | |
671 } | |
672 cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18; | |
673 | |
674 return cont; | |
675 } | |
676 | |
677 rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) { | |
678 | |
679 rmff_data_t *data=malloc(sizeof(rmff_data_t)); | |
680 | |
681 data->object_id=DATA_TAG; | |
682 data->size=18; | |
683 data->object_version=0; | |
684 data->num_packets=num_packets; | |
685 data->next_data_header=next_data_header; | |
686 | |
687 return data; | |
688 } | |
689 | |
690 void rmff_print_header(rmff_header_t *h) { | |
691 | |
692 rmff_mdpr_t **stream; | |
693 | |
694 if(!h) { | |
695 printf("rmff_print_header: NULL given\n"); | |
696 return; | |
697 } | |
698 if(h->fileheader) | |
699 { | |
700 printf("\nFILE:\n"); | |
701 printf("file version : %d\n", h->fileheader->file_version); | |
702 printf("number of headers : %d\n", h->fileheader->num_headers); | |
703 } | |
704 if(h->cont) | |
705 { | |
706 printf("\nCONTENT:\n"); | |
707 printf("title : %s\n", h->cont->title); | |
708 printf("author : %s\n", h->cont->author); | |
709 printf("copyright : %s\n", h->cont->copyright); | |
710 printf("comment : %s\n", h->cont->comment); | |
711 } | |
712 if(h->prop) | |
713 { | |
714 printf("\nSTREAM PROPERTIES:\n"); | |
715 printf("bit rate (max/avg) : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate); | |
716 printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size); | |
717 printf("packets : %i\n", h->prop->num_packets); | |
718 printf("duration : %i ms\n", h->prop->duration); | |
719 printf("pre-buffer : %i ms\n", h->prop->preroll); | |
720 printf("index offset : %i bytes\n", h->prop->index_offset); | |
721 printf("data offset : %i bytes\n", h->prop->data_offset); | |
722 printf("media streams : %i\n", h->prop->num_streams); | |
723 printf("flags : "); | |
724 if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled "); | |
725 if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled "); | |
726 if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast "); | |
727 printf("\n"); | |
728 } | |
729 stream=h->streams; | |
730 if(stream) | |
731 { | |
732 while (*stream) | |
733 { | |
734 printf("\nSTREAM %i:\n", (*stream)->stream_number); | |
735 printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type); | |
736 printf("bit rate (max/avg) : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate); | |
737 printf("packet size (max/avg) : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size); | |
738 printf("start time : %i\n", (*stream)->start_time); | |
739 printf("pre-buffer : %i ms\n", (*stream)->preroll); | |
740 printf("duration : %i ms\n", (*stream)->duration); | |
741 printf("type specific data:\n"); | |
742 hexdump((*stream)->type_specific_data, (*stream)->type_specific_len); | |
743 stream++; | |
744 } | |
745 } | |
746 if(h->data) | |
747 { | |
748 printf("\nDATA:\n"); | |
749 printf("size : %i\n", h->data->size); | |
750 printf("packets : %i\n", h->data->num_packets); | |
751 printf("next DATA : 0x%08x\n", h->data->next_data_header); | |
752 } | |
753 } | |
754 | |
755 void rmff_fix_header(rmff_header_t *h) { | |
756 | |
757 int num_headers=0; | |
758 int header_size=0; | |
759 rmff_mdpr_t **streams; | |
760 int num_streams=0; | |
761 | |
762 if (!h) { | |
20711 | 763 mp_msg(MSGT_STREAM, MSGL_ERR, "rmff_fix_header: fatal: no header given.\n"); |
9922 | 764 return; |
765 } | |
766 | |
767 if (!h->streams) { | |
20711 | 768 mp_msg(MSGT_STREAM, MSGL_WARN, "rmff_fix_header: warning: no MDPR chunks\n"); |
9922 | 769 } else |
770 { | |
771 streams=h->streams; | |
772 while (*streams) | |
773 { | |
774 num_streams++; | |
775 num_headers++; | |
776 header_size+=(*streams)->size; | |
777 streams++; | |
778 } | |
779 } | |
780 | |
781 if (h->prop) { | |
782 if (h->prop->size != 50) | |
783 { | |
784 #ifdef LOG | |
785 printf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50); | |
786 #endif | |
787 h->prop->size=50; | |
788 } | |
789 if (h->prop->num_streams != num_streams) | |
790 { | |
791 #ifdef LOG | |
792 printf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams); | |
793 #endif | |
794 h->prop->num_streams=num_streams; | |
795 } | |
796 num_headers++; | |
797 header_size+=50; | |
798 } else | |
20711 | 799 mp_msg(MSGT_STREAM, MSGL_WARN, "rmff_fix_header: warning: no PROP chunk.\n"); |
9922 | 800 |
801 if (h->cont) { | |
802 num_headers++; | |
803 header_size+=h->cont->size; | |
804 } else | |
20711 | 805 mp_msg(MSGT_STREAM, MSGL_WARN, "rmff_fix_header: warning: no CONT chunk.\n"); |
9922 | 806 |
807 if (!h->data) { | |
808 #ifdef LOG | |
809 printf("rmff_fix_header: no DATA chunk, creating one\n"); | |
810 #endif | |
811 h->data=malloc(sizeof(rmff_data_t)); | |
812 h->data->object_id=DATA_TAG; | |
813 h->data->object_version=0; | |
814 h->data->size=34; | |
815 h->data->num_packets=0; | |
816 h->data->next_data_header=0; | |
817 } | |
818 num_headers++; | |
819 | |
820 | |
821 if (!h->fileheader) { | |
822 #ifdef LOG | |
823 printf("rmff_fix_header: no fileheader, creating one"); | |
824 #endif | |
825 h->fileheader=malloc(sizeof(rmff_fileheader_t)); | |
826 h->fileheader->object_id=RMF_TAG; | |
827 h->fileheader->size=34; | |
828 h->fileheader->object_version=0; | |
829 h->fileheader->file_version=0; | |
830 h->fileheader->num_headers=num_headers+1; | |
831 } | |
832 header_size+=h->fileheader->size; | |
833 num_headers++; | |
834 | |
835 if(h->fileheader->num_headers != num_headers) { | |
836 #ifdef LOG | |
837 printf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers); | |
838 #endif | |
839 h->fileheader->num_headers=num_headers; | |
840 } | |
841 | |
842 if(h->prop) { | |
843 if (h->prop->data_offset != header_size) { | |
844 #ifdef LOG | |
845 printf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size); | |
846 #endif | |
847 h->prop->data_offset=header_size; | |
848 } | |
849 if (h->prop->num_packets == 0) { | |
850 int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size); | |
851 #ifdef LOG | |
852 printf("rmff_fix_header: assuming prop.num_packets=%i\n", p); | |
853 #endif | |
854 h->prop->num_packets=p; | |
855 } | |
856 if (h->data->num_packets == 0) { | |
857 #ifdef LOG | |
858 printf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets); | |
859 #endif | |
860 h->data->num_packets=h->prop->num_packets; | |
861 } | |
862 | |
863 #ifdef LOG | |
864 printf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size); | |
865 #endif | |
866 h->data->size=h->prop->num_packets*h->prop->avg_packet_size; | |
867 } | |
868 } | |
869 | |
870 int rmff_get_header_size(rmff_header_t *h) { | |
871 | |
872 if (!h) return 0; | |
873 if (!h->prop) return -1; | |
874 | |
875 return h->prop->data_offset+18; | |
876 | |
877 } | |
878 | |
879 void rmff_free_header(rmff_header_t *h) { | |
880 | |
881 if (!h) return; | |
882 | |
883 if (h->fileheader) free(h->fileheader); | |
884 if (h->prop) free(h->prop); | |
885 if (h->data) free(h->data); | |
886 if (h->cont) | |
887 { | |
888 free(h->cont->title); | |
889 free(h->cont->author); | |
890 free(h->cont->copyright); | |
891 free(h->cont->comment); | |
892 free(h->cont); | |
893 } | |
894 if (h->streams) | |
895 { | |
896 rmff_mdpr_t **s=h->streams; | |
897 | |
898 while(*s) { | |
899 free((*s)->stream_name); | |
900 free((*s)->mime_type); | |
901 free((*s)->type_specific_data); | |
902 free(*s); | |
903 s++; | |
904 } | |
905 free(h->streams); | |
906 } | |
907 free(h); | |
908 } |