2 * This file was ported to MPlayer from xine CVS rmff.c,v 1.3 2002/12/24 01:30:22
6 * Copyright (C) 2002 the xine project
8 * This file is part of xine, a free video player.
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.
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.
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
25 * functions for real media file format
26 * adopted from joschkas real tools
32 #include "libavutil/intreadwrite.h"
38 static void hexdump (const char *buf
, int length
) {
42 printf ("rmff: ascii>");
43 for (i
= 0; i
< length
; i
++) {
44 unsigned char c
= buf
[i
];
46 if ((c
>= 32) && (c
<= 128))
53 printf ("rmff: hexdump> ");
54 for (i
= 0; i
< length
; i
++) {
55 unsigned char c
= buf
[i
];
70 * writes header data to a buffer
73 static int rmff_dump_fileheader(rmff_fileheader_t
*fileheader
, char *buffer
, int bufsize
) {
75 if (!fileheader
) return 0;
77 if (bufsize
< RMFF_FILEHEADER_SIZE
)
80 AV_WB32(buffer
, fileheader
->object_id
);
81 AV_WB32(buffer
+4, fileheader
->size
);
82 AV_WB16(buffer
+8, fileheader
->object_version
);
83 AV_WB32(buffer
+10, fileheader
->file_version
);
84 AV_WB32(buffer
+14, fileheader
->num_headers
);
86 return RMFF_FILEHEADER_SIZE
;
89 static int rmff_dump_prop(rmff_prop_t
*prop
, char *buffer
, int bufsize
) {
93 if (bufsize
< RMFF_PROPHEADER_SIZE
)
96 AV_WB32(buffer
, prop
->object_id
);
97 AV_WB32(buffer
+4, prop
->size
);
98 AV_WB16(buffer
+8, prop
->object_version
);
99 AV_WB32(buffer
+10, prop
->max_bit_rate
);
100 AV_WB32(buffer
+14, prop
->avg_bit_rate
);
101 AV_WB32(buffer
+18, prop
->max_packet_size
);
102 AV_WB32(buffer
+22, prop
->avg_packet_size
);
103 AV_WB32(buffer
+26, prop
->num_packets
);
104 AV_WB32(buffer
+30, prop
->duration
);
105 AV_WB32(buffer
+34, prop
->preroll
);
106 AV_WB32(buffer
+38, prop
->index_offset
);
107 AV_WB32(buffer
+42, prop
->data_offset
);
108 AV_WB16(buffer
+46, prop
->num_streams
);
109 AV_WB16(buffer
+48, prop
->flags
);
111 return RMFF_PROPHEADER_SIZE
;
114 static int rmff_dump_mdpr(rmff_mdpr_t
*mdpr
, char *buffer
, int bufsize
) {
120 if (!(bufsize
> RMFF_MDPRHEADER_SIZE
+ mdpr
->stream_name_size
+ mdpr
->mime_type_size
&&
121 (unsigned)bufsize
- RMFF_MDPRHEADER_SIZE
- mdpr
->stream_name_size
- mdpr
->mime_type_size
> mdpr
->type_specific_len
))
124 AV_WB32(buffer
, mdpr
->object_id
);
125 AV_WB32(buffer
+4, mdpr
->size
);
126 AV_WB16(buffer
+8, mdpr
->object_version
);
127 AV_WB16(buffer
+10, mdpr
->stream_number
);
128 AV_WB32(buffer
+12, mdpr
->max_bit_rate
);
129 AV_WB32(buffer
+16, mdpr
->avg_bit_rate
);
130 AV_WB32(buffer
+20, mdpr
->max_packet_size
);
131 AV_WB32(buffer
+24, mdpr
->avg_packet_size
);
132 AV_WB32(buffer
+28, mdpr
->start_time
);
133 AV_WB32(buffer
+32, mdpr
->preroll
);
134 AV_WB32(buffer
+36, mdpr
->duration
);
136 buffer
[40] = mdpr
->stream_name_size
;
137 s1
=mdpr
->stream_name_size
;
138 memcpy(&buffer
[41], mdpr
->stream_name
, s1
);
140 buffer
[41+s1
] = mdpr
->mime_type_size
;
141 s2
=mdpr
->mime_type_size
;
142 memcpy(&buffer
[42+s1
], mdpr
->mime_type
, s2
);
144 AV_WB32(buffer
+42+s1
+s2
, mdpr
->type_specific_len
);
145 s3
=mdpr
->type_specific_len
;
146 memcpy(&buffer
[46+s1
+s2
], mdpr
->type_specific_data
, s3
);
148 return RMFF_MDPRHEADER_SIZE
+ s1
+ s2
+ s3
;
151 static int rmff_dump_cont(rmff_cont_t
*cont
, char *buffer
, int bufsize
) {
157 if (bufsize
< RMFF_CONTHEADER_SIZE
+ cont
->title_len
+ cont
->author_len
+
158 cont
->copyright_len
+ cont
->comment_len
)
161 AV_WB32(buffer
, cont
->object_id
);
162 AV_WB32(buffer
+4, cont
->size
);
163 AV_WB16(buffer
+8, cont
->object_version
);
165 AV_WB16(buffer
+10, cont
->title_len
);
166 memcpy(&buffer
[12], cont
->title
, cont
->title_len
);
167 p
=12+cont
->title_len
;
169 AV_WB16(buffer
+p
, cont
->author_len
);
170 memcpy(&buffer
[p
+2], cont
->author
, cont
->author_len
);
171 p
+=2+cont
->author_len
;
173 AV_WB16(buffer
+p
, cont
->copyright_len
);
174 memcpy(&buffer
[p
+2], cont
->copyright
, cont
->copyright_len
);
175 p
+=2+cont
->copyright_len
;
177 AV_WB16(buffer
+p
, cont
->comment_len
);
178 memcpy(&buffer
[p
+2], cont
->comment
, cont
->comment_len
);
180 return RMFF_CONTHEADER_SIZE
+ cont
->title_len
+ cont
->author_len
+
181 cont
->copyright_len
+ cont
->comment_len
;
184 static int rmff_dump_dataheader(rmff_data_t
*data
, char *buffer
, int bufsize
) {
188 if (bufsize
< RMFF_DATAHEADER_SIZE
)
191 AV_WB32(buffer
, data
->object_id
);
192 AV_WB32(buffer
+4, data
->size
);
193 AV_WB16(buffer
+8, data
->object_version
);
194 AV_WB32(buffer
+10, data
->num_packets
);
195 AV_WB32(buffer
+14, data
->next_data_header
);
197 return RMFF_DATAHEADER_SIZE
;
200 int rmff_dump_header(rmff_header_t
*h
, char *buffer
, int max
) {
203 rmff_mdpr_t
**stream
=h
->streams
;
205 if ((size
=rmff_dump_fileheader(h
->fileheader
, &buffer
[written
], max
)) < 0)
209 if ((size
=rmff_dump_prop(h
->prop
, &buffer
[written
], max
)) < 0)
213 if ((size
=rmff_dump_cont(h
->cont
, &buffer
[written
], max
)) < 0)
221 if ((size
=rmff_dump_mdpr(*stream
, &buffer
[written
], max
)) < 0)
229 if ((size
=rmff_dump_dataheader(h
->data
, &buffer
[written
], max
)) < 0)
236 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff_dumpheader: buffer too small, aborting. Please report\n");
240 void rmff_dump_pheader(rmff_pheader_t
*h
, char *data
) {
242 data
[0]=(h
->object_version
>>8) & 0xff;
243 data
[1]=h
->object_version
& 0xff;
244 data
[2]=(h
->length
>>8) & 0xff;
245 data
[3]=h
->length
& 0xff;
246 data
[4]=(h
->stream_number
>>8) & 0xff;
247 data
[5]=h
->stream_number
& 0xff;
248 data
[6]=(h
->timestamp
>>24) & 0xff;
249 data
[7]=(h
->timestamp
>>16) & 0xff;
250 data
[8]=(h
->timestamp
>>8) & 0xff;
251 data
[9]=h
->timestamp
& 0xff;
252 data
[10]=h
->reserved
;
256 static rmff_fileheader_t
*rmff_scan_fileheader(const char *data
) {
258 rmff_fileheader_t
*fileheader
=malloc(sizeof(rmff_fileheader_t
));
260 fileheader
->object_id
=AV_RB32(data
);
261 fileheader
->size
=AV_RB32(&data
[4]);
262 fileheader
->object_version
=AV_RB16(&data
[8]);
263 if (fileheader
->object_version
!= 0)
265 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in .RMF: 0x%04x\n",
266 fileheader
->object_version
);
268 fileheader
->file_version
=AV_RB32(&data
[10]);
269 fileheader
->num_headers
=AV_RB32(&data
[14]);
274 static rmff_prop_t
*rmff_scan_prop(const char *data
) {
276 rmff_prop_t
*prop
=malloc(sizeof(rmff_prop_t
));
278 prop
->object_id
=AV_RB32(data
);
279 prop
->size
=AV_RB32(&data
[4]);
280 prop
->object_version
=AV_RB16(&data
[8]);
281 if (prop
->object_version
!= 0)
283 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in PROP: 0x%04x\n",
284 prop
->object_version
);
286 prop
->max_bit_rate
=AV_RB32(&data
[10]);
287 prop
->avg_bit_rate
=AV_RB32(&data
[14]);
288 prop
->max_packet_size
=AV_RB32(&data
[18]);
289 prop
->avg_packet_size
=AV_RB32(&data
[22]);
290 prop
->num_packets
=AV_RB32(&data
[26]);
291 prop
->duration
=AV_RB32(&data
[30]);
292 prop
->preroll
=AV_RB32(&data
[34]);
293 prop
->index_offset
=AV_RB32(&data
[38]);
294 prop
->data_offset
=AV_RB32(&data
[42]);
295 prop
->num_streams
=AV_RB16(&data
[46]);
296 prop
->flags
=AV_RB16(&data
[48]);
301 static rmff_mdpr_t
*rmff_scan_mdpr(const char *data
) {
303 rmff_mdpr_t
*mdpr
=malloc(sizeof(rmff_mdpr_t
));
305 mdpr
->object_id
=AV_RB32(data
);
306 mdpr
->size
=AV_RB32(&data
[4]);
307 mdpr
->object_version
=AV_RB16(&data
[8]);
308 if (mdpr
->object_version
!= 0)
310 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in MDPR: 0x%04x\n",
311 mdpr
->object_version
);
313 mdpr
->stream_number
=AV_RB16(&data
[10]);
314 mdpr
->max_bit_rate
=AV_RB32(&data
[12]);
315 mdpr
->avg_bit_rate
=AV_RB32(&data
[16]);
316 mdpr
->max_packet_size
=AV_RB32(&data
[20]);
317 mdpr
->avg_packet_size
=AV_RB32(&data
[24]);
318 mdpr
->start_time
=AV_RB32(&data
[28]);
319 mdpr
->preroll
=AV_RB32(&data
[32]);
320 mdpr
->duration
=AV_RB32(&data
[36]);
322 mdpr
->stream_name_size
=data
[40];
323 mdpr
->stream_name
=malloc(mdpr
->stream_name_size
+1);
324 memcpy(mdpr
->stream_name
, &data
[41], mdpr
->stream_name_size
);
325 mdpr
->stream_name
[mdpr
->stream_name_size
]=0;
327 mdpr
->mime_type_size
=data
[41+mdpr
->stream_name_size
];
328 mdpr
->mime_type
=malloc(mdpr
->mime_type_size
+1);
329 memcpy(mdpr
->mime_type
, &data
[42+mdpr
->stream_name_size
], mdpr
->mime_type_size
);
330 mdpr
->mime_type
[mdpr
->mime_type_size
]=0;
332 mdpr
->type_specific_len
=AV_RB32(&data
[42+mdpr
->stream_name_size
+mdpr
->mime_type_size
]);
333 mdpr
->type_specific_data
=malloc(mdpr
->type_specific_len
);
334 memcpy(mdpr
->type_specific_data
,
335 &data
[46+mdpr
->stream_name_size
+mdpr
->mime_type_size
], mdpr
->type_specific_len
);
340 static rmff_cont_t
*rmff_scan_cont(const char *data
) {
342 rmff_cont_t
*cont
=malloc(sizeof(rmff_cont_t
));
345 cont
->object_id
=AV_RB32(data
);
346 cont
->size
=AV_RB32(&data
[4]);
347 cont
->object_version
=AV_RB16(&data
[8]);
348 if (cont
->object_version
!= 0)
350 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in CONT: 0x%04x\n",
351 cont
->object_version
);
353 cont
->title_len
=AV_RB16(&data
[10]);
354 cont
->title
=malloc(cont
->title_len
+1);
355 memcpy(cont
->title
, &data
[12], cont
->title_len
);
356 cont
->title
[cont
->title_len
]=0;
357 pos
=cont
->title_len
+12;
358 cont
->author_len
=AV_RB16(&data
[pos
]);
359 cont
->author
=malloc(cont
->author_len
+1);
360 memcpy(cont
->author
, &data
[pos
+2], cont
->author_len
);
361 cont
->author
[cont
->author_len
]=0;
362 pos
=pos
+2+cont
->author_len
;
363 cont
->copyright_len
=AV_RB16(&data
[pos
]);
364 cont
->copyright
=malloc(cont
->copyright_len
+1);
365 memcpy(cont
->copyright
, &data
[pos
+2], cont
->copyright_len
);
366 cont
->copyright
[cont
->copyright_len
]=0;
367 pos
=pos
+2+cont
->copyright_len
;
368 cont
->comment_len
=AV_RB16(&data
[pos
]);
369 cont
->comment
=malloc(cont
->comment_len
+1);
370 memcpy(cont
->comment
, &data
[pos
+2], cont
->comment_len
);
371 cont
->comment
[cont
->comment_len
]=0;
376 static rmff_data_t
*rmff_scan_dataheader(const char *data
) {
378 rmff_data_t
*dh
=malloc(sizeof(rmff_data_t
));
380 dh
->object_id
=AV_RB32(data
);
381 dh
->size
=AV_RB32(&data
[4]);
382 dh
->object_version
=AV_RB16(&data
[8]);
383 if (dh
->object_version
!= 0)
385 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in DATA: 0x%04x\n",
388 dh
->num_packets
=AV_RB32(&data
[10]);
389 dh
->next_data_header
=AV_RB32(&data
[14]);
394 rmff_header_t
*rmff_scan_header(const char *data
) {
396 rmff_header_t
*header
=malloc(sizeof(rmff_header_t
));
397 rmff_mdpr_t
*mdpr
=NULL
;
400 const char *ptr
=data
;
403 header
->fileheader
=NULL
;
408 chunk_type
= AV_RB32(ptr
);
409 if (chunk_type
!= RMF_TAG
)
411 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff: not an real media file header (.RMF tag not found).\n");
415 header
->fileheader
=rmff_scan_fileheader(ptr
);
416 ptr
+= header
->fileheader
->size
;
418 header
->streams
=malloc(sizeof(rmff_mdpr_t
*)*(header
->fileheader
->num_headers
));
419 for (i
=0; i
<header
->fileheader
->num_headers
; i
++) {
420 header
->streams
[i
]=NULL
;
423 for (i
=1; i
<header
->fileheader
->num_headers
; i
++) {
424 chunk_type
= AV_RB32(ptr
);
428 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff: warning: only %d of %d header found.\n", i
, header
->fileheader
->num_headers
);
433 switch (chunk_type
) {
435 header
->prop
=rmff_scan_prop(ptr
);
436 chunk_size
=header
->prop
->size
;
439 mdpr
=rmff_scan_mdpr(ptr
);
440 chunk_size
=mdpr
->size
;
441 header
->streams
[mdpr
->stream_number
]=mdpr
;
444 header
->cont
=rmff_scan_cont(ptr
);
445 chunk_size
=header
->cont
->size
;
448 header
->data
=rmff_scan_dataheader(ptr
);
449 chunk_size
=34; /* hard coded header size */
452 mp_msg(MSGT_STREAM
, MSGL_WARN
, "unknown chunk\n");
463 rmff_header_t
*rmff_scan_header_stream(int fd
) {
465 rmff_header_t
*header
;
466 char *buf
=xbuffer_init(1024);
472 buf
= xbuffer_ensure_size(buf
, index
+8);
473 recv(fd
, buf
+index
, 8, 0);
474 chunk_type
=AV_RB32(buf
+index
); index
+=4;
475 chunk_size
=AV_RB32(buf
+index
); index
+=4;
477 switch (chunk_type
) {
484 buf
= xbuffer_ensure_size(buf
, index
+chunk_size
-8);
485 recv(fd
, buf
+index
, (chunk_size
-8), 0);
486 index
+=(chunk_size
-8);
489 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_scan_header_stream: unknown chunk");
490 hexdump(buf
+index
-8, 8);
493 } while (chunk_type
!= DATA_TAG
);
495 header
= rmff_scan_header(buf
);
502 void rmff_scan_pheader(rmff_pheader_t
*h
, char *data
) {
504 h
->object_version
=AV_RB16(data
);
505 h
->length
=AV_RB16(data
+2);
506 h
->stream_number
=AV_RB16(data
+4);
507 h
->timestamp
=AV_RB32(data
+6);
508 h
->reserved
=(uint8_t)data
[10];
509 h
->flags
=(uint8_t)data
[11];
512 rmff_fileheader_t
*rmff_new_fileheader(uint32_t num_headers
) {
514 rmff_fileheader_t
*fileheader
=malloc(sizeof(rmff_fileheader_t
));
516 fileheader
->object_id
=RMF_TAG
;
518 fileheader
->object_version
=0;
519 fileheader
->file_version
=0;
520 fileheader
->num_headers
=num_headers
;
525 rmff_prop_t
*rmff_new_prop (
526 uint32_t max_bit_rate
,
527 uint32_t avg_bit_rate
,
528 uint32_t max_packet_size
,
529 uint32_t avg_packet_size
,
530 uint32_t num_packets
,
533 uint32_t index_offset
,
534 uint32_t data_offset
,
535 uint16_t num_streams
,
538 rmff_prop_t
*prop
=malloc(sizeof(rmff_prop_t
));
540 prop
->object_id
=PROP_TAG
;
542 prop
->object_version
=0;
544 prop
->max_bit_rate
=max_bit_rate
;
545 prop
->avg_bit_rate
=avg_bit_rate
;
546 prop
->max_packet_size
=max_packet_size
;
547 prop
->avg_packet_size
=avg_packet_size
;
548 prop
->num_packets
=num_packets
;
549 prop
->duration
=duration
;
550 prop
->preroll
=preroll
;
551 prop
->index_offset
=index_offset
;
552 prop
->data_offset
=data_offset
;
553 prop
->num_streams
=num_streams
;
559 rmff_mdpr_t
*rmff_new_mdpr(
560 uint16_t stream_number
,
561 uint32_t max_bit_rate
,
562 uint32_t avg_bit_rate
,
563 uint32_t max_packet_size
,
564 uint32_t avg_packet_size
,
568 const char *stream_name
,
569 const char *mime_type
,
570 uint32_t type_specific_len
,
571 const char *type_specific_data
) {
573 rmff_mdpr_t
*mdpr
=calloc(sizeof(rmff_mdpr_t
),1);
575 mdpr
->object_id
=MDPR_TAG
;
576 mdpr
->object_version
=0;
578 mdpr
->stream_number
=stream_number
;
579 mdpr
->max_bit_rate
=max_bit_rate
;
580 mdpr
->avg_bit_rate
=avg_bit_rate
;
581 mdpr
->max_packet_size
=max_packet_size
;
582 mdpr
->avg_packet_size
=avg_packet_size
;
583 mdpr
->start_time
=start_time
;
584 mdpr
->preroll
=preroll
;
585 mdpr
->duration
=duration
;
586 mdpr
->stream_name_size
=0;
588 mdpr
->stream_name
=strdup(stream_name
);
589 mdpr
->stream_name_size
=strlen(stream_name
);
591 mdpr
->mime_type_size
=0;
593 mdpr
->mime_type
=strdup(mime_type
);
594 mdpr
->mime_type_size
=strlen(mime_type
);
596 mdpr
->type_specific_len
=type_specific_len
;
597 mdpr
->type_specific_data
=malloc(type_specific_len
);
598 memcpy(mdpr
->type_specific_data
,type_specific_data
,type_specific_len
);
599 mdpr
->mlti_data
=NULL
;
601 mdpr
->size
=mdpr
->stream_name_size
+mdpr
->mime_type_size
+mdpr
->type_specific_len
+46;
606 rmff_cont_t
*rmff_new_cont(const char *title
, const char *author
, const char *copyright
, const char *comment
) {
608 rmff_cont_t
*cont
=malloc(sizeof(rmff_cont_t
));
610 cont
->object_id
=CONT_TAG
;
611 cont
->object_version
=0;
615 cont
->copyright
=NULL
;
620 cont
->copyright_len
=0;
624 cont
->title_len
=strlen(title
);
625 cont
->title
=strdup(title
);
628 cont
->author_len
=strlen(author
);
629 cont
->author
=strdup(author
);
632 cont
->copyright_len
=strlen(copyright
);
633 cont
->copyright
=strdup(copyright
);
636 cont
->comment_len
=strlen(comment
);
637 cont
->comment
=strdup(comment
);
639 cont
->size
=cont
->title_len
+cont
->author_len
+cont
->copyright_len
+cont
->comment_len
+18;
644 rmff_data_t
*rmff_new_dataheader(uint32_t num_packets
, uint32_t next_data_header
) {
646 rmff_data_t
*data
=malloc(sizeof(rmff_data_t
));
648 data
->object_id
=DATA_TAG
;
650 data
->object_version
=0;
651 data
->num_packets
=num_packets
;
652 data
->next_data_header
=next_data_header
;
657 void rmff_print_header(rmff_header_t
*h
) {
659 rmff_mdpr_t
**stream
;
662 printf("rmff_print_header: NULL given\n");
668 printf("file version : %d\n", h
->fileheader
->file_version
);
669 printf("number of headers : %d\n", h
->fileheader
->num_headers
);
673 printf("\nCONTENT:\n");
674 printf("title : %s\n", h
->cont
->title
);
675 printf("author : %s\n", h
->cont
->author
);
676 printf("copyright : %s\n", h
->cont
->copyright
);
677 printf("comment : %s\n", h
->cont
->comment
);
681 printf("\nSTREAM PROPERTIES:\n");
682 printf("bit rate (max/avg) : %i/%i\n", h
->prop
->max_bit_rate
, h
->prop
->avg_bit_rate
);
683 printf("packet size (max/avg) : %i/%i bytes\n", h
->prop
->max_packet_size
, h
->prop
->avg_packet_size
);
684 printf("packets : %i\n", h
->prop
->num_packets
);
685 printf("duration : %i ms\n", h
->prop
->duration
);
686 printf("pre-buffer : %i ms\n", h
->prop
->preroll
);
687 printf("index offset : %i bytes\n", h
->prop
->index_offset
);
688 printf("data offset : %i bytes\n", h
->prop
->data_offset
);
689 printf("media streams : %i\n", h
->prop
->num_streams
);
691 if (h
->prop
->flags
& PN_SAVE_ENABLED
) printf("save_enabled ");
692 if (h
->prop
->flags
& PN_PERFECT_PLAY_ENABLED
) printf("perfect_play_enabled ");
693 if (h
->prop
->flags
& PN_LIVE_BROADCAST
) printf("live_broadcast ");
701 printf("\nSTREAM %i:\n", (*stream
)->stream_number
);
702 printf("stream name [mime type] : %s [%s]\n", (*stream
)->stream_name
, (*stream
)->mime_type
);
703 printf("bit rate (max/avg) : %i/%i\n", (*stream
)->max_bit_rate
, (*stream
)->avg_bit_rate
);
704 printf("packet size (max/avg) : %i/%i bytes\n", (*stream
)->max_packet_size
, (*stream
)->avg_packet_size
);
705 printf("start time : %i\n", (*stream
)->start_time
);
706 printf("pre-buffer : %i ms\n", (*stream
)->preroll
);
707 printf("duration : %i ms\n", (*stream
)->duration
);
708 printf("type specific data:\n");
709 hexdump((*stream
)->type_specific_data
, (*stream
)->type_specific_len
);
716 printf("size : %i\n", h
->data
->size
);
717 printf("packets : %i\n", h
->data
->num_packets
);
718 printf("next DATA : 0x%08x\n", h
->data
->next_data_header
);
722 void rmff_fix_header(rmff_header_t
*h
) {
726 rmff_mdpr_t
**streams
;
730 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff_fix_header: fatal: no header given.\n");
735 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no MDPR chunks\n");
743 header_size
+=(*streams
)->size
;
749 if (h
->prop
->size
!= 50)
752 printf("rmff_fix_header: correcting prop.size from %i to %i\n", h
->prop
->size
, 50);
756 if (h
->prop
->num_streams
!= num_streams
)
759 printf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h
->prop
->num_streams
, num_streams
);
761 h
->prop
->num_streams
=num_streams
;
766 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no PROP chunk.\n");
770 header_size
+=h
->cont
->size
;
772 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no CONT chunk.\n");
776 printf("rmff_fix_header: no DATA chunk, creating one\n");
778 h
->data
=malloc(sizeof(rmff_data_t
));
779 h
->data
->object_id
=DATA_TAG
;
780 h
->data
->object_version
=0;
782 h
->data
->num_packets
=0;
783 h
->data
->next_data_header
=0;
788 if (!h
->fileheader
) {
790 printf("rmff_fix_header: no fileheader, creating one");
792 h
->fileheader
=malloc(sizeof(rmff_fileheader_t
));
793 h
->fileheader
->object_id
=RMF_TAG
;
794 h
->fileheader
->size
=34;
795 h
->fileheader
->object_version
=0;
796 h
->fileheader
->file_version
=0;
797 h
->fileheader
->num_headers
=num_headers
+1;
799 header_size
+=h
->fileheader
->size
;
802 if(h
->fileheader
->num_headers
!= num_headers
) {
804 printf("rmff_fix_header: setting num_headers from %i to %i\n", h
->fileheader
->num_headers
, num_headers
);
806 h
->fileheader
->num_headers
=num_headers
;
810 if (h
->prop
->data_offset
!= header_size
) {
812 printf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h
->prop
->data_offset
, header_size
);
814 h
->prop
->data_offset
=header_size
;
816 if (h
->prop
->num_packets
== 0) {
817 int p
=(int)(h
->prop
->avg_bit_rate
/8.0*(h
->prop
->duration
/1000.0)/h
->prop
->avg_packet_size
);
819 printf("rmff_fix_header: assuming prop.num_packets=%i\n", p
);
821 h
->prop
->num_packets
=p
;
823 if (h
->data
->num_packets
== 0) {
825 printf("rmff_fix_header: assuming data.num_packets=%i\n", h
->prop
->num_packets
);
827 h
->data
->num_packets
=h
->prop
->num_packets
;
831 printf("rmff_fix_header: assuming data.size=%i\n", h
->prop
->num_packets
*h
->prop
->avg_packet_size
);
833 h
->data
->size
=h
->prop
->num_packets
*h
->prop
->avg_packet_size
;
837 int rmff_get_header_size(rmff_header_t
*h
) {
840 if (!h
->prop
) return -1;
842 return h
->prop
->data_offset
+18;
846 void rmff_free_header(rmff_header_t
*h
) {
850 if (h
->fileheader
) free(h
->fileheader
);
851 if (h
->prop
) free(h
->prop
);
852 if (h
->data
) free(h
->data
);
855 free(h
->cont
->title
);
856 free(h
->cont
->author
);
857 free(h
->cont
->copyright
);
858 free(h
->cont
->comment
);
863 rmff_mdpr_t
**s
=h
->streams
;
866 free((*s
)->stream_name
);
867 free((*s
)->mime_type
);
868 free((*s
)->type_specific_data
);