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