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
29 #include <libavutil/intreadwrite.h>
39 static void hexdump (const char *buf
, int length
) {
43 printf ("rmff: ascii>");
44 for (i
= 0; i
< length
; i
++) {
45 unsigned char c
= buf
[i
];
47 if ((c
>= 32) && (c
<= 128))
54 printf ("rmff: hexdump> ");
55 for (i
= 0; i
< length
; i
++) {
56 unsigned char c
= buf
[i
];
71 * writes header data to a buffer
74 static int rmff_dump_fileheader(rmff_fileheader_t
*fileheader
, char *buffer
, int bufsize
) {
76 if (!fileheader
) return 0;
78 if (bufsize
< RMFF_FILEHEADER_SIZE
)
81 AV_WB32(buffer
, fileheader
->object_id
);
82 AV_WB32(buffer
+4, fileheader
->size
);
83 AV_WB16(buffer
+8, fileheader
->object_version
);
84 AV_WB32(buffer
+10, fileheader
->file_version
);
85 AV_WB32(buffer
+14, fileheader
->num_headers
);
87 return RMFF_FILEHEADER_SIZE
;
90 static int rmff_dump_prop(rmff_prop_t
*prop
, char *buffer
, int bufsize
) {
94 if (bufsize
< RMFF_PROPHEADER_SIZE
)
97 AV_WB32(buffer
, prop
->object_id
);
98 AV_WB32(buffer
+4, prop
->size
);
99 AV_WB16(buffer
+8, prop
->object_version
);
100 AV_WB32(buffer
+10, prop
->max_bit_rate
);
101 AV_WB32(buffer
+14, prop
->avg_bit_rate
);
102 AV_WB32(buffer
+18, prop
->max_packet_size
);
103 AV_WB32(buffer
+22, prop
->avg_packet_size
);
104 AV_WB32(buffer
+26, prop
->num_packets
);
105 AV_WB32(buffer
+30, prop
->duration
);
106 AV_WB32(buffer
+34, prop
->preroll
);
107 AV_WB32(buffer
+38, prop
->index_offset
);
108 AV_WB32(buffer
+42, prop
->data_offset
);
109 AV_WB16(buffer
+46, prop
->num_streams
);
110 AV_WB16(buffer
+48, prop
->flags
);
112 return RMFF_PROPHEADER_SIZE
;
115 static int rmff_dump_mdpr(rmff_mdpr_t
*mdpr
, char *buffer
, int bufsize
) {
121 if (!(bufsize
> RMFF_MDPRHEADER_SIZE
+ mdpr
->stream_name_size
+ mdpr
->mime_type_size
&&
122 (unsigned)bufsize
- RMFF_MDPRHEADER_SIZE
- mdpr
->stream_name_size
- mdpr
->mime_type_size
> mdpr
->type_specific_len
))
125 AV_WB32(buffer
, mdpr
->object_id
);
126 AV_WB32(buffer
+4, mdpr
->size
);
127 AV_WB16(buffer
+8, mdpr
->object_version
);
128 AV_WB16(buffer
+10, mdpr
->stream_number
);
129 AV_WB32(buffer
+12, mdpr
->max_bit_rate
);
130 AV_WB32(buffer
+16, mdpr
->avg_bit_rate
);
131 AV_WB32(buffer
+20, mdpr
->max_packet_size
);
132 AV_WB32(buffer
+24, mdpr
->avg_packet_size
);
133 AV_WB32(buffer
+28, mdpr
->start_time
);
134 AV_WB32(buffer
+32, mdpr
->preroll
);
135 AV_WB32(buffer
+36, mdpr
->duration
);
137 buffer
[40] = mdpr
->stream_name_size
;
138 s1
=mdpr
->stream_name_size
;
139 memcpy(&buffer
[41], mdpr
->stream_name
, s1
);
141 buffer
[41+s1
] = mdpr
->mime_type_size
;
142 s2
=mdpr
->mime_type_size
;
143 memcpy(&buffer
[42+s1
], mdpr
->mime_type
, s2
);
145 AV_WB32(buffer
+42+s1
+s2
, mdpr
->type_specific_len
);
146 s3
=mdpr
->type_specific_len
;
147 memcpy(&buffer
[46+s1
+s2
], mdpr
->type_specific_data
, s3
);
149 return RMFF_MDPRHEADER_SIZE
+ s1
+ s2
+ s3
;
152 static int rmff_dump_cont(rmff_cont_t
*cont
, char *buffer
, int bufsize
) {
158 if (bufsize
< RMFF_CONTHEADER_SIZE
+ cont
->title_len
+ cont
->author_len
+
159 cont
->copyright_len
+ cont
->comment_len
)
162 AV_WB32(buffer
, cont
->object_id
);
163 AV_WB32(buffer
+4, cont
->size
);
164 AV_WB16(buffer
+8, cont
->object_version
);
166 AV_WB16(buffer
+10, cont
->title_len
);
167 memcpy(&buffer
[12], cont
->title
, cont
->title_len
);
168 p
=12+cont
->title_len
;
170 AV_WB16(buffer
+p
, cont
->author_len
);
171 memcpy(&buffer
[p
+2], cont
->author
, cont
->author_len
);
172 p
+=2+cont
->author_len
;
174 AV_WB16(buffer
+p
, cont
->copyright_len
);
175 memcpy(&buffer
[p
+2], cont
->copyright
, cont
->copyright_len
);
176 p
+=2+cont
->copyright_len
;
178 AV_WB16(buffer
+p
, cont
->comment_len
);
179 memcpy(&buffer
[p
+2], cont
->comment
, cont
->comment_len
);
181 return RMFF_CONTHEADER_SIZE
+ cont
->title_len
+ cont
->author_len
+
182 cont
->copyright_len
+ cont
->comment_len
;
185 static int rmff_dump_dataheader(rmff_data_t
*data
, char *buffer
, int bufsize
) {
189 if (bufsize
< RMFF_DATAHEADER_SIZE
)
192 AV_WB32(buffer
, data
->object_id
);
193 AV_WB32(buffer
+4, data
->size
);
194 AV_WB16(buffer
+8, data
->object_version
);
195 AV_WB32(buffer
+10, data
->num_packets
);
196 AV_WB32(buffer
+14, data
->next_data_header
);
198 return RMFF_DATAHEADER_SIZE
;
201 int rmff_dump_header(rmff_header_t
*h
, char *buffer
, int max
) {
204 rmff_mdpr_t
**stream
=h
->streams
;
206 if ((size
=rmff_dump_fileheader(h
->fileheader
, &buffer
[written
], max
)) < 0)
210 if ((size
=rmff_dump_prop(h
->prop
, &buffer
[written
], max
)) < 0)
214 if ((size
=rmff_dump_cont(h
->cont
, &buffer
[written
], max
)) < 0)
222 if ((size
=rmff_dump_mdpr(*stream
, &buffer
[written
], max
)) < 0)
230 if ((size
=rmff_dump_dataheader(h
->data
, &buffer
[written
], max
)) < 0)
237 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff_dumpheader: buffer too small, aborting. Please report\n");
241 void rmff_dump_pheader(rmff_pheader_t
*h
, char *data
) {
243 data
[0]=(h
->object_version
>>8) & 0xff;
244 data
[1]=h
->object_version
& 0xff;
245 data
[2]=(h
->length
>>8) & 0xff;
246 data
[3]=h
->length
& 0xff;
247 data
[4]=(h
->stream_number
>>8) & 0xff;
248 data
[5]=h
->stream_number
& 0xff;
249 data
[6]=(h
->timestamp
>>24) & 0xff;
250 data
[7]=(h
->timestamp
>>16) & 0xff;
251 data
[8]=(h
->timestamp
>>8) & 0xff;
252 data
[9]=h
->timestamp
& 0xff;
253 data
[10]=h
->reserved
;
257 static rmff_fileheader_t
*rmff_scan_fileheader(const char *data
) {
259 rmff_fileheader_t
*fileheader
=malloc(sizeof(rmff_fileheader_t
));
261 fileheader
->object_id
=AV_RB32(data
);
262 fileheader
->size
=AV_RB32(&data
[4]);
263 fileheader
->object_version
=AV_RB16(&data
[8]);
264 if (fileheader
->object_version
!= 0)
266 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in .RMF: 0x%04x\n",
267 fileheader
->object_version
);
269 fileheader
->file_version
=AV_RB32(&data
[10]);
270 fileheader
->num_headers
=AV_RB32(&data
[14]);
275 static rmff_prop_t
*rmff_scan_prop(const char *data
) {
277 rmff_prop_t
*prop
=malloc(sizeof(rmff_prop_t
));
279 prop
->object_id
=AV_RB32(data
);
280 prop
->size
=AV_RB32(&data
[4]);
281 prop
->object_version
=AV_RB16(&data
[8]);
282 if (prop
->object_version
!= 0)
284 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in PROP: 0x%04x\n",
285 prop
->object_version
);
287 prop
->max_bit_rate
=AV_RB32(&data
[10]);
288 prop
->avg_bit_rate
=AV_RB32(&data
[14]);
289 prop
->max_packet_size
=AV_RB32(&data
[18]);
290 prop
->avg_packet_size
=AV_RB32(&data
[22]);
291 prop
->num_packets
=AV_RB32(&data
[26]);
292 prop
->duration
=AV_RB32(&data
[30]);
293 prop
->preroll
=AV_RB32(&data
[34]);
294 prop
->index_offset
=AV_RB32(&data
[38]);
295 prop
->data_offset
=AV_RB32(&data
[42]);
296 prop
->num_streams
=AV_RB16(&data
[46]);
297 prop
->flags
=AV_RB16(&data
[48]);
302 static rmff_mdpr_t
*rmff_scan_mdpr(const char *data
) {
304 rmff_mdpr_t
*mdpr
=malloc(sizeof(rmff_mdpr_t
));
306 mdpr
->object_id
=AV_RB32(data
);
307 mdpr
->size
=AV_RB32(&data
[4]);
308 mdpr
->object_version
=AV_RB16(&data
[8]);
309 if (mdpr
->object_version
!= 0)
311 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in MDPR: 0x%04x\n",
312 mdpr
->object_version
);
314 mdpr
->stream_number
=AV_RB16(&data
[10]);
315 mdpr
->max_bit_rate
=AV_RB32(&data
[12]);
316 mdpr
->avg_bit_rate
=AV_RB32(&data
[16]);
317 mdpr
->max_packet_size
=AV_RB32(&data
[20]);
318 mdpr
->avg_packet_size
=AV_RB32(&data
[24]);
319 mdpr
->start_time
=AV_RB32(&data
[28]);
320 mdpr
->preroll
=AV_RB32(&data
[32]);
321 mdpr
->duration
=AV_RB32(&data
[36]);
323 mdpr
->stream_name_size
=data
[40];
324 mdpr
->stream_name
=malloc(mdpr
->stream_name_size
+1);
325 memcpy(mdpr
->stream_name
, &data
[41], mdpr
->stream_name_size
);
326 mdpr
->stream_name
[mdpr
->stream_name_size
]=0;
328 mdpr
->mime_type_size
=data
[41+mdpr
->stream_name_size
];
329 mdpr
->mime_type
=malloc(mdpr
->mime_type_size
+1);
330 memcpy(mdpr
->mime_type
, &data
[42+mdpr
->stream_name_size
], mdpr
->mime_type_size
);
331 mdpr
->mime_type
[mdpr
->mime_type_size
]=0;
333 mdpr
->type_specific_len
=AV_RB32(&data
[42+mdpr
->stream_name_size
+mdpr
->mime_type_size
]);
334 mdpr
->type_specific_data
=malloc(mdpr
->type_specific_len
);
335 memcpy(mdpr
->type_specific_data
,
336 &data
[46+mdpr
->stream_name_size
+mdpr
->mime_type_size
], mdpr
->type_specific_len
);
341 static rmff_cont_t
*rmff_scan_cont(const char *data
) {
343 rmff_cont_t
*cont
=malloc(sizeof(rmff_cont_t
));
346 cont
->object_id
=AV_RB32(data
);
347 cont
->size
=AV_RB32(&data
[4]);
348 cont
->object_version
=AV_RB16(&data
[8]);
349 if (cont
->object_version
!= 0)
351 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in CONT: 0x%04x\n",
352 cont
->object_version
);
354 cont
->title_len
=AV_RB16(&data
[10]);
355 cont
->title
=malloc(cont
->title_len
+1);
356 memcpy(cont
->title
, &data
[12], cont
->title_len
);
357 cont
->title
[cont
->title_len
]=0;
358 pos
=cont
->title_len
+12;
359 cont
->author_len
=AV_RB16(&data
[pos
]);
360 cont
->author
=malloc(cont
->author_len
+1);
361 memcpy(cont
->author
, &data
[pos
+2], cont
->author_len
);
362 cont
->author
[cont
->author_len
]=0;
363 pos
=pos
+2+cont
->author_len
;
364 cont
->copyright_len
=AV_RB16(&data
[pos
]);
365 cont
->copyright
=malloc(cont
->copyright_len
+1);
366 memcpy(cont
->copyright
, &data
[pos
+2], cont
->copyright_len
);
367 cont
->copyright
[cont
->copyright_len
]=0;
368 pos
=pos
+2+cont
->copyright_len
;
369 cont
->comment_len
=AV_RB16(&data
[pos
]);
370 cont
->comment
=malloc(cont
->comment_len
+1);
371 memcpy(cont
->comment
, &data
[pos
+2], cont
->comment_len
);
372 cont
->comment
[cont
->comment_len
]=0;
377 static rmff_data_t
*rmff_scan_dataheader(const char *data
) {
379 rmff_data_t
*dh
=malloc(sizeof(rmff_data_t
));
381 dh
->object_id
=AV_RB32(data
);
382 dh
->size
=AV_RB32(&data
[4]);
383 dh
->object_version
=AV_RB16(&data
[8]);
384 if (dh
->object_version
!= 0)
386 mp_msg(MSGT_STREAM
, MSGL_WARN
, "warning: unknown object version in DATA: 0x%04x\n",
389 dh
->num_packets
=AV_RB32(&data
[10]);
390 dh
->next_data_header
=AV_RB32(&data
[14]);
395 rmff_header_t
*rmff_scan_header(const char *data
) {
397 rmff_header_t
*header
=malloc(sizeof(rmff_header_t
));
398 rmff_mdpr_t
*mdpr
=NULL
;
401 const char *ptr
=data
;
404 header
->fileheader
=NULL
;
409 chunk_type
= AV_RB32(ptr
);
410 if (chunk_type
!= RMF_TAG
)
412 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff: not an real media file header (.RMF tag not found).\n");
416 header
->fileheader
=rmff_scan_fileheader(ptr
);
417 ptr
+= header
->fileheader
->size
;
419 header
->streams
=malloc(sizeof(rmff_mdpr_t
*)*(header
->fileheader
->num_headers
));
420 for (i
=0; i
<header
->fileheader
->num_headers
; i
++) {
421 header
->streams
[i
]=NULL
;
424 for (i
=1; i
<header
->fileheader
->num_headers
; i
++) {
425 chunk_type
= AV_RB32(ptr
);
429 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff: warning: only %d of %d header found.\n", i
, header
->fileheader
->num_headers
);
434 switch (chunk_type
) {
436 header
->prop
=rmff_scan_prop(ptr
);
437 chunk_size
=header
->prop
->size
;
440 mdpr
=rmff_scan_mdpr(ptr
);
441 chunk_size
=mdpr
->size
;
442 header
->streams
[mdpr
->stream_number
]=mdpr
;
445 header
->cont
=rmff_scan_cont(ptr
);
446 chunk_size
=header
->cont
->size
;
449 header
->data
=rmff_scan_dataheader(ptr
);
450 chunk_size
=34; /* hard coded header size */
453 mp_msg(MSGT_STREAM
, MSGL_WARN
, "unknown chunk\n");
464 rmff_header_t
*rmff_scan_header_stream(int fd
) {
466 rmff_header_t
*header
;
467 char *buf
=xbuffer_init(1024);
473 buf
= xbuffer_ensure_size(buf
, index
+8);
474 recv(fd
, buf
+index
, 8, 0);
475 chunk_type
=AV_RB32(buf
+index
); index
+=4;
476 chunk_size
=AV_RB32(buf
+index
); index
+=4;
478 switch (chunk_type
) {
485 buf
= xbuffer_ensure_size(buf
, index
+chunk_size
-8);
486 recv(fd
, buf
+index
, (chunk_size
-8), 0);
487 index
+=(chunk_size
-8);
490 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_scan_header_stream: unknown chunk");
491 hexdump(buf
+index
-8, 8);
494 } while (chunk_type
!= DATA_TAG
);
496 header
= rmff_scan_header(buf
);
503 void rmff_scan_pheader(rmff_pheader_t
*h
, char *data
) {
505 h
->object_version
=AV_RB16(data
);
506 h
->length
=AV_RB16(data
+2);
507 h
->stream_number
=AV_RB16(data
+4);
508 h
->timestamp
=AV_RB32(data
+6);
509 h
->reserved
=(uint8_t)data
[10];
510 h
->flags
=(uint8_t)data
[11];
513 rmff_fileheader_t
*rmff_new_fileheader(uint32_t num_headers
) {
515 rmff_fileheader_t
*fileheader
=malloc(sizeof(rmff_fileheader_t
));
517 fileheader
->object_id
=RMF_TAG
;
519 fileheader
->object_version
=0;
520 fileheader
->file_version
=0;
521 fileheader
->num_headers
=num_headers
;
526 rmff_prop_t
*rmff_new_prop (
527 uint32_t max_bit_rate
,
528 uint32_t avg_bit_rate
,
529 uint32_t max_packet_size
,
530 uint32_t avg_packet_size
,
531 uint32_t num_packets
,
534 uint32_t index_offset
,
535 uint32_t data_offset
,
536 uint16_t num_streams
,
539 rmff_prop_t
*prop
=malloc(sizeof(rmff_prop_t
));
541 prop
->object_id
=PROP_TAG
;
543 prop
->object_version
=0;
545 prop
->max_bit_rate
=max_bit_rate
;
546 prop
->avg_bit_rate
=avg_bit_rate
;
547 prop
->max_packet_size
=max_packet_size
;
548 prop
->avg_packet_size
=avg_packet_size
;
549 prop
->num_packets
=num_packets
;
550 prop
->duration
=duration
;
551 prop
->preroll
=preroll
;
552 prop
->index_offset
=index_offset
;
553 prop
->data_offset
=data_offset
;
554 prop
->num_streams
=num_streams
;
560 rmff_mdpr_t
*rmff_new_mdpr(
561 uint16_t stream_number
,
562 uint32_t max_bit_rate
,
563 uint32_t avg_bit_rate
,
564 uint32_t max_packet_size
,
565 uint32_t avg_packet_size
,
569 const char *stream_name
,
570 const char *mime_type
,
571 uint32_t type_specific_len
,
572 const char *type_specific_data
) {
574 rmff_mdpr_t
*mdpr
=calloc(sizeof(rmff_mdpr_t
),1);
576 mdpr
->object_id
=MDPR_TAG
;
577 mdpr
->object_version
=0;
579 mdpr
->stream_number
=stream_number
;
580 mdpr
->max_bit_rate
=max_bit_rate
;
581 mdpr
->avg_bit_rate
=avg_bit_rate
;
582 mdpr
->max_packet_size
=max_packet_size
;
583 mdpr
->avg_packet_size
=avg_packet_size
;
584 mdpr
->start_time
=start_time
;
585 mdpr
->preroll
=preroll
;
586 mdpr
->duration
=duration
;
587 mdpr
->stream_name_size
=0;
589 mdpr
->stream_name
=strdup(stream_name
);
590 mdpr
->stream_name_size
=strlen(stream_name
);
592 mdpr
->mime_type_size
=0;
594 mdpr
->mime_type
=strdup(mime_type
);
595 mdpr
->mime_type_size
=strlen(mime_type
);
597 mdpr
->type_specific_len
=type_specific_len
;
598 mdpr
->type_specific_data
=malloc(type_specific_len
);
599 memcpy(mdpr
->type_specific_data
,type_specific_data
,type_specific_len
);
600 mdpr
->mlti_data
=NULL
;
602 mdpr
->size
=mdpr
->stream_name_size
+mdpr
->mime_type_size
+mdpr
->type_specific_len
+46;
607 rmff_cont_t
*rmff_new_cont(const char *title
, const char *author
, const char *copyright
, const char *comment
) {
609 rmff_cont_t
*cont
=malloc(sizeof(rmff_cont_t
));
611 cont
->object_id
=CONT_TAG
;
612 cont
->object_version
=0;
616 cont
->copyright
=NULL
;
621 cont
->copyright_len
=0;
625 cont
->title_len
=strlen(title
);
626 cont
->title
=strdup(title
);
629 cont
->author_len
=strlen(author
);
630 cont
->author
=strdup(author
);
633 cont
->copyright_len
=strlen(copyright
);
634 cont
->copyright
=strdup(copyright
);
637 cont
->comment_len
=strlen(comment
);
638 cont
->comment
=strdup(comment
);
640 cont
->size
=cont
->title_len
+cont
->author_len
+cont
->copyright_len
+cont
->comment_len
+18;
645 rmff_data_t
*rmff_new_dataheader(uint32_t num_packets
, uint32_t next_data_header
) {
647 rmff_data_t
*data
=malloc(sizeof(rmff_data_t
));
649 data
->object_id
=DATA_TAG
;
651 data
->object_version
=0;
652 data
->num_packets
=num_packets
;
653 data
->next_data_header
=next_data_header
;
658 void rmff_print_header(rmff_header_t
*h
) {
660 rmff_mdpr_t
**stream
;
663 printf("rmff_print_header: NULL given\n");
669 printf("file version : %d\n", h
->fileheader
->file_version
);
670 printf("number of headers : %d\n", h
->fileheader
->num_headers
);
674 printf("\nCONTENT:\n");
675 printf("title : %s\n", h
->cont
->title
);
676 printf("author : %s\n", h
->cont
->author
);
677 printf("copyright : %s\n", h
->cont
->copyright
);
678 printf("comment : %s\n", h
->cont
->comment
);
682 printf("\nSTREAM PROPERTIES:\n");
683 printf("bit rate (max/avg) : %i/%i\n", h
->prop
->max_bit_rate
, h
->prop
->avg_bit_rate
);
684 printf("packet size (max/avg) : %i/%i bytes\n", h
->prop
->max_packet_size
, h
->prop
->avg_packet_size
);
685 printf("packets : %i\n", h
->prop
->num_packets
);
686 printf("duration : %i ms\n", h
->prop
->duration
);
687 printf("pre-buffer : %i ms\n", h
->prop
->preroll
);
688 printf("index offset : %i bytes\n", h
->prop
->index_offset
);
689 printf("data offset : %i bytes\n", h
->prop
->data_offset
);
690 printf("media streams : %i\n", h
->prop
->num_streams
);
692 if (h
->prop
->flags
& PN_SAVE_ENABLED
) printf("save_enabled ");
693 if (h
->prop
->flags
& PN_PERFECT_PLAY_ENABLED
) printf("perfect_play_enabled ");
694 if (h
->prop
->flags
& PN_LIVE_BROADCAST
) printf("live_broadcast ");
702 printf("\nSTREAM %i:\n", (*stream
)->stream_number
);
703 printf("stream name [mime type] : %s [%s]\n", (*stream
)->stream_name
, (*stream
)->mime_type
);
704 printf("bit rate (max/avg) : %i/%i\n", (*stream
)->max_bit_rate
, (*stream
)->avg_bit_rate
);
705 printf("packet size (max/avg) : %i/%i bytes\n", (*stream
)->max_packet_size
, (*stream
)->avg_packet_size
);
706 printf("start time : %i\n", (*stream
)->start_time
);
707 printf("pre-buffer : %i ms\n", (*stream
)->preroll
);
708 printf("duration : %i ms\n", (*stream
)->duration
);
709 printf("type specific data:\n");
710 hexdump((*stream
)->type_specific_data
, (*stream
)->type_specific_len
);
717 printf("size : %i\n", h
->data
->size
);
718 printf("packets : %i\n", h
->data
->num_packets
);
719 printf("next DATA : 0x%08x\n", h
->data
->next_data_header
);
723 void rmff_fix_header(rmff_header_t
*h
) {
727 rmff_mdpr_t
**streams
;
731 mp_msg(MSGT_STREAM
, MSGL_ERR
, "rmff_fix_header: fatal: no header given.\n");
736 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no MDPR chunks\n");
744 header_size
+=(*streams
)->size
;
750 if (h
->prop
->size
!= 50)
753 printf("rmff_fix_header: correcting prop.size from %i to %i\n", h
->prop
->size
, 50);
757 if (h
->prop
->num_streams
!= num_streams
)
760 printf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h
->prop
->num_streams
, num_streams
);
762 h
->prop
->num_streams
=num_streams
;
767 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no PROP chunk.\n");
771 header_size
+=h
->cont
->size
;
773 mp_msg(MSGT_STREAM
, MSGL_WARN
, "rmff_fix_header: warning: no CONT chunk.\n");
777 printf("rmff_fix_header: no DATA chunk, creating one\n");
779 h
->data
=malloc(sizeof(rmff_data_t
));
780 h
->data
->object_id
=DATA_TAG
;
781 h
->data
->object_version
=0;
783 h
->data
->num_packets
=0;
784 h
->data
->next_data_header
=0;
789 if (!h
->fileheader
) {
791 printf("rmff_fix_header: no fileheader, creating one");
793 h
->fileheader
=malloc(sizeof(rmff_fileheader_t
));
794 h
->fileheader
->object_id
=RMF_TAG
;
795 h
->fileheader
->size
=34;
796 h
->fileheader
->object_version
=0;
797 h
->fileheader
->file_version
=0;
798 h
->fileheader
->num_headers
=num_headers
+1;
800 header_size
+=h
->fileheader
->size
;
803 if(h
->fileheader
->num_headers
!= num_headers
) {
805 printf("rmff_fix_header: setting num_headers from %i to %i\n", h
->fileheader
->num_headers
, num_headers
);
807 h
->fileheader
->num_headers
=num_headers
;
811 if (h
->prop
->data_offset
!= header_size
) {
813 printf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h
->prop
->data_offset
, header_size
);
815 h
->prop
->data_offset
=header_size
;
817 if (h
->prop
->num_packets
== 0) {
818 int p
=(int)(h
->prop
->avg_bit_rate
/8.0*(h
->prop
->duration
/1000.0)/h
->prop
->avg_packet_size
);
820 printf("rmff_fix_header: assuming prop.num_packets=%i\n", p
);
822 h
->prop
->num_packets
=p
;
824 if (h
->data
->num_packets
== 0) {
826 printf("rmff_fix_header: assuming data.num_packets=%i\n", h
->prop
->num_packets
);
828 h
->data
->num_packets
=h
->prop
->num_packets
;
832 printf("rmff_fix_header: assuming data.size=%i\n", h
->prop
->num_packets
*h
->prop
->avg_packet_size
);
834 h
->data
->size
=h
->prop
->num_packets
*h
->prop
->avg_packet_size
;
838 int rmff_get_header_size(rmff_header_t
*h
) {
841 if (!h
->prop
) return -1;
843 return h
->prop
->data_offset
+18;
847 void rmff_free_header(rmff_header_t
*h
) {
856 free(h
->cont
->title
);
857 free(h
->cont
->author
);
858 free(h
->cont
->copyright
);
859 free(h
->cont
->comment
);
864 rmff_mdpr_t
**s
=h
->streams
;
867 free((*s
)->stream_name
);
868 free((*s
)->mime_type
);
869 free((*s
)->type_specific_data
);