1 /*
2 rmff.c
3
4 Copyright (C) Moritz Bunkus - March 2004
5
6 librmff is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1, or (at your option)
9 any later version.
10
11 librmff is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 */
21
22 #include "common/os.h"
23
24 #include <errno.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "librmff.h"
31
32 #if defined(COMP_MSC)
33 #define inline __inline
34 #endif
35
36 typedef struct rmff_video_segment_t {
37 uint32_t size;
38 uint32_t offset;
39 unsigned char *data;
40 } rmff_video_segment_t;
41
42 typedef struct rmff_bitrate_t {
43 uint32_t *timecodes;
44 uint32_t *frame_sizes;
45 uint32_t num_entries;
46 } rmff_bitrate_t;
47
48 typedef struct rmff_file_internal_t {
49 uint32_t max_bit_rate;
50 uint32_t avg_bit_rate;
51 uint32_t max_packet_size;
52 uint32_t avg_packet_size;
53 uint32_t highest_timecode;
54 uint32_t num_packets;
55 uint32_t data_offset;
56 uint32_t next_data_offset;
57 uint32_t data_contents_size;
58 uint32_t index_offset;
59 int num_index_chunks;
60 uint32_t total_bytes;
61 rmff_bitrate_t bitrate;
62 } rmff_file_internal_t;
63
64 typedef struct rmff_track_internal_t {
65 uint32_t max_bit_rate;
66 uint32_t avg_bit_rate;
67 uint32_t max_packet_size;
68 uint32_t avg_packet_size;
69 uint32_t highest_timecode;
70 uint32_t num_packets;
71 uint32_t num_packed_frames;
72 int index_this;
73 uint32_t total_bytes;
74 rmff_bitrate_t bitrate;
75
76 /* Used for video packet assembly. */
77 uint32_t c_timecode;
78 int f_merged;
79 int c_keyframe;
80 rmff_video_segment_t *segments;
81 int num_segments;
82 rmff_frame_t **assembled_frames;
83 int num_assembled_frames;
84 } rmff_track_internal_t;
85
86 int rmff_last_error = RMFF_ERR_OK;
87 const char *rmff_last_error_msg = NULL;
88 static char error_msg_buffer[1000];
89 static const char *rmff_std_error_messages[] = {
90 "No error",
91 "File is not a RealMedia file",
92 "Inconsistent data found in file",
93 "End of file reached",
94 "Input/output error",
95 "Invalid parameters"
96 };
97
98 const char *
rmff_get_error_str(int code)99 rmff_get_error_str(int code) {
100 code *= -1;
101 if ((code >= 0) && (code <= 5))
102 return rmff_std_error_messages[code];
103 else
104 return "Unknown error";
105 }
106
107 static void
set_error(int error_number,const char * error_msg)108 set_error(int error_number,
109 const char *error_msg) {
110 rmff_last_error = error_number;
111 if (error_msg == NULL)
112 rmff_last_error_msg = rmff_get_error_str(error_number);
113 else
114 rmff_last_error_msg = error_msg;
115 }
116
117 #define clear_error() set_error(RMFF_ERR_OK, NULL)
118
119 uint16_t
rmff_get_uint16_be(const void * buf)120 rmff_get_uint16_be(const void *buf) {
121 uint16_t ret;
122 unsigned char *tmp;
123
124 tmp = (unsigned char *) buf;
125
126 ret = tmp[0] & 0xff;
127 ret = (ret << 8) + (tmp[1] & 0xff);
128
129 return ret;
130 }
131
132 uint32_t
rmff_get_uint32_be(const void * buf)133 rmff_get_uint32_be(const void *buf) {
134 uint32_t ret;
135 unsigned char *tmp;
136
137 tmp = (unsigned char *) buf;
138
139 ret = tmp[0] & 0xff;
140 ret = (ret << 8) + (tmp[1] & 0xff);
141 ret = (ret << 8) + (tmp[2] & 0xff);
142 ret = (ret << 8) + (tmp[3] & 0xff);
143
144 return ret;
145 }
146
147 uint32_t
rmff_get_uint32_le(const void * buf)148 rmff_get_uint32_le(const void *buf) {
149 uint32_t ret;
150 unsigned char *tmp;
151
152 tmp = (unsigned char *) buf;
153
154 ret = tmp[3] & 0xff;
155 ret = (ret << 8) + (tmp[2] & 0xff);
156 ret = (ret << 8) + (tmp[1] & 0xff);
157 ret = (ret << 8) + (tmp[0] & 0xff);
158
159 return ret;
160 }
161
162 void
rmff_put_uint16_be(void * buf,uint16_t value)163 rmff_put_uint16_be(void *buf,
164 uint16_t value) {
165 unsigned char *tmp;
166
167 tmp = (unsigned char *) buf;
168
169 tmp[1] = value & 0xff;
170 tmp[0] = (value >>= 8) & 0xff;
171 }
172
173 void
rmff_put_uint32_be(void * buf,uint32_t value)174 rmff_put_uint32_be(void *buf,
175 uint32_t value) {
176 unsigned char *tmp;
177
178 tmp = (unsigned char *) buf;
179
180 tmp[3] = value & 0xff;
181 tmp[2] = (value >>= 8) & 0xff;
182 tmp[1] = (value >>= 8) & 0xff;
183 tmp[0] = (value >>= 8) & 0xff;
184 }
185
186 void
rmff_put_uint32_le(void * buf,uint32_t value)187 rmff_put_uint32_le(void *buf,
188 uint32_t value) {
189 unsigned char *tmp;
190
191 tmp = (unsigned char *) buf;
192
193 tmp[0] = value & 0xff;
194 tmp[1] = (value >>= 8) & 0xff;
195 tmp[2] = (value >>= 8) & 0xff;
196 tmp[3] = (value >>= 8) & 0xff;
197 }
198
199 #define read_uint8() file_read_uint8(io, fh)
200 #define read_uint16_be() file_read_uint16_be(io, fh)
201 #define read_uint32_be() file_read_uint32_be(io, fh)
202 #define read_uint16_be_to(addr) rmff_put_uint16_be(addr, read_uint16_be())
203 #define read_uint32_be_to(addr) rmff_put_uint32_be(addr, read_uint32_be())
204 #define write_uint8(v) file_write_uint8(io, fh, v)
205 #define write_uint16_be(v) file_write_uint16_be(io, fh, v)
206 #define write_uint32_be(v) file_write_uint32_be(io, fh, v)
207 #define write_uint16_be_from(addr) write_uint16_be(rmff_get_uint16_be(addr))
208 #define write_uint32_be_from(addr) write_uint32_be(rmff_get_uint32_be(addr))
209 #define get_fourcc(b) rmff_get_uint32_be(b)
210
211 static uint8_t
file_read_uint8(mb_file_io_t * io,void * fh)212 file_read_uint8(mb_file_io_t *io,
213 void *fh) {
214 unsigned char tmp;
215
216 if (io->read(fh, &tmp, 1) != 1) {
217 set_error(RMFF_ERR_IO, NULL);
218 return 0;
219 }
220 return tmp;
221 }
222
223 static uint16_t
file_read_uint16_be(mb_file_io_t * io,void * fh)224 file_read_uint16_be(mb_file_io_t *io,
225 void *fh) {
226 unsigned char tmp[2];
227
228 if (io->read(fh, tmp, 2) != 2) {
229 set_error(RMFF_ERR_IO, NULL);
230 return 0;
231 }
232 return rmff_get_uint16_be(tmp);
233 }
234
235 static uint32_t
file_read_uint32_be(mb_file_io_t * io,void * fh)236 file_read_uint32_be(mb_file_io_t *io,
237 void *fh) {
238 unsigned char tmp[4];
239
240 if (io->read(fh, tmp, 4) != 4) {
241 set_error(RMFF_ERR_IO, NULL);
242 return 0;
243 }
244 return rmff_get_uint32_be(tmp);
245 }
246
247 static int
file_write_uint8(mb_file_io_t * io,void * fh,uint8_t value)248 file_write_uint8(mb_file_io_t *io,
249 void *fh,
250 uint8_t value) {
251 return io->write(fh, &value, 1);
252 }
253
254 static int
file_write_uint16_be(mb_file_io_t * io,void * fh,uint16_t value)255 file_write_uint16_be(mb_file_io_t *io,
256 void *fh,
257 uint16_t value) {
258 unsigned char tmp[2];
259
260 rmff_put_uint16_be(tmp, value);
261 return io->write(fh, &tmp, 2);
262 }
263
264 static int
file_write_uint32_be(mb_file_io_t * io,void * fh,uint32_t value)265 file_write_uint32_be(mb_file_io_t *io,
266 void *fh,
267 uint32_t value) {
268 unsigned char tmp[4];
269
270 rmff_put_uint32_be(tmp, value);
271 return io->write(fh, &tmp, 4);
272 }
273
274 void
die(const char * fmt,...)275 die(const char *fmt,
276 ...) {
277 va_list ap;
278
279 fprintf(stderr, "'die' called: ");
280 va_start(ap, fmt);
281 vfprintf(stderr, fmt, ap);
282 va_end(ap);
283 fprintf(stderr, "\n");
284 exit(1);
285 }
286
287 #define safestrdup(s) _safestrdup(s, __FILE__, __LINE__)
288 #define safememdup(s, b) _safememdup(s, b, __FILE__, __LINE__)
289 #define safemalloc(s) _safemalloc(s, __FILE__, __LINE__)
290 #define safecalloc(s) _safecalloc(s, __FILE__, __LINE__)
291 #define saferealloc(s, b) _saferealloc(s, b, __FILE__, __LINE__)
292 #define safefree(s) { if ((s) != NULL) free(s); }
293
294 static char *
_safestrdup(const char * s,const char * file,int line)295 _safestrdup(const char *s,
296 const char *file,
297 int line) {
298 char *copy;
299
300 if (s == NULL)
301 return NULL;
302
303 copy = strdup(s);
304 if (copy == NULL)
305 die("safestrdup() called from file %s, line %d: strdup() "
306 "returned NULL for '%s'.", file, line, s);
307
308 return copy;
309 }
310
311 static void *
_safememdup(const void * s,size_t size,const char * file,int line)312 _safememdup(const void *s,
313 size_t size,
314 const char *file,
315 int line) {
316 void *copy;
317
318 if (s == NULL)
319 return NULL;
320
321 copy = malloc(size);
322 if (copy == NULL)
323 die("safememdup() called from file %s, line %d: malloc() "
324 "returned NULL for a size of %d bytes.", file, line, size);
325 memcpy(copy, s, size);
326
327 return copy;
328 }
329
330 static void *
_safemalloc(size_t size,const char * file,int line)331 _safemalloc(size_t size,
332 const char *file,
333 int line) {
334 void *mem;
335
336 mem = malloc(size);
337 if (mem == NULL)
338 die("safemalloc() called from file %s, line %d: malloc() "
339 "returned NULL for a size of %d bytes.", file, line, size);
340
341 return mem;
342 }
343
_safecalloc(size_t size,const char * file,int line)344 static void *_safecalloc(size_t size,
345 const char *file,
346 int line) {
347 void *mem;
348
349 mem = calloc(size, 1);
350 if (mem == NULL)
351 die("safemalloc() called from file %s, line %d: malloc() "
352 "returned NULL for a size of %d bytes.", file, line, size);
353
354 return mem;
355 }
356
357 static void *
_saferealloc(void * mem,size_t size,const char * file,int line)358 _saferealloc(void *mem,
359 size_t size,
360 const char *file,
361 int line) {
362 mem = realloc(mem, size);
363 if (mem == NULL)
364 die("saferealloc() called from file %s, line %d: realloc() "
365 "returned NULL for a size of %d bytes.", file, line, size);
366
367 return mem;
368 }
369
370 static rmff_file_t *
open_file_for_reading(const char * path,mb_file_io_t * io)371 open_file_for_reading(const char *path,
372 mb_file_io_t *io) {
373 rmff_file_t *file;
374 void *file_h;
375 char signature[5];
376
377 file_h = io->open(path, MB_OPEN_MODE_READING);
378 if (file_h == NULL)
379 return NULL;
380
381 signature[4] = 0;
382 if ((io->read(file_h, signature, 4) != 4) ||
383 strcmp(signature, ".RMF")) {
384 io->close(file_h);
385 set_error(RMFF_ERR_NOT_RMFF, NULL);
386 return NULL;
387 }
388
389 file = (rmff_file_t *)safecalloc(sizeof(rmff_file_t));
390 file->handle = file_h;
391 file->name = safestrdup(path);
392 file->io = io;
393 io->seek(file_h, 0, SEEK_END);
394 file->size = io->tell(file_h);
395 io->seek(file_h, 4, SEEK_SET);
396 file->open_mode = RMFF_OPEN_MODE_READING;
397 file->internal = safecalloc(sizeof(rmff_file_internal_t));
398
399 clear_error();
400 return file;
401 }
402
403 static rmff_file_t *
open_file_for_writing(const char * path,mb_file_io_t * io)404 open_file_for_writing(const char *path,
405 mb_file_io_t *io) {
406 rmff_file_t *file;
407 void *file_h;
408 const char *signature = ".RMF";
409
410 file_h = io->open(path, MB_OPEN_MODE_WRITING);
411 if (file_h == NULL)
412 return NULL;
413
414 if (io->write(file_h, signature, 4) != 4) {
415 io->close(file_h);
416 set_error(RMFF_ERR_IO, NULL);
417 return NULL;
418 }
419
420 file = (rmff_file_t *)safecalloc(sizeof(rmff_file_t));
421 file->handle = file_h;
422 file->name = safestrdup(path);
423 file->io = io;
424 file->size = -1;
425 file->open_mode = RMFF_OPEN_MODE_WRITING;
426 file->internal = safecalloc(sizeof(rmff_file_internal_t));
427
428 /* save allowed & perfect play */
429 rmff_put_uint16_be(&file->prop_header.flags,
430 RMFF_FILE_FLAG_SAVE_ENABLED |
431 RMFF_FILE_FLAG_DOWNLOAD_ENABLED);
432
433 clear_error();
434 return file;
435 }
436
437 rmff_file_t *
rmff_open_file(const char * path,int mode)438 rmff_open_file(const char *path,
439 int mode) {
440 return rmff_open_file_with_io(path, mode, &std_mb_file_io);
441 }
442
443 rmff_file_t *
rmff_open_file_with_io(const char * path,int mode,mb_file_io_t * io)444 rmff_open_file_with_io(const char *path,
445 int mode,
446 mb_file_io_t *io) {
447 if ((path == NULL) || (io == NULL) ||
448 ((mode != RMFF_OPEN_MODE_READING) && (mode != RMFF_OPEN_MODE_WRITING))) {
449 set_error(RMFF_ERR_PARAMETERS, NULL);
450 return NULL;
451 }
452
453 if (mode == RMFF_OPEN_MODE_READING)
454 return open_file_for_reading(path, io);
455 else
456 return open_file_for_writing(path, io);
457 }
458
459 void
rmff_free_track_data(rmff_track_t * track)460 rmff_free_track_data(rmff_track_t *track) {
461 rmff_track_internal_t *tint;
462 int i;
463
464 if (track == NULL)
465 return;
466 safefree(track->index);
467 safefree(track->mdpr_header.name);
468 safefree(track->mdpr_header.mime_type);
469 safefree(track->mdpr_header.type_specific_data);
470 tint = (rmff_track_internal_t *)track->internal;
471 for (i = 0; i < tint->num_segments; i++)
472 safefree(tint->segments[i].data);
473 safefree(tint->segments);
474 for (i = 0; i < tint->num_assembled_frames; i++)
475 rmff_release_frame(tint->assembled_frames[i]);
476 safefree(tint->assembled_frames);
477 safefree(track->internal);
478 }
479
480 void
rmff_close_file(rmff_file_t * file)481 rmff_close_file(rmff_file_t *file) {
482 int i;
483
484 if (file == NULL)
485 return;
486
487 safefree(file->name);
488 for (i = 0; i < file->num_tracks; i++) {
489 rmff_free_track_data(file->tracks[i]);
490 safefree(file->tracks[i]);
491 }
492 safefree(file->tracks);
493 safefree(file->cont_header.title);
494 safefree(file->cont_header.author);
495 safefree(file->cont_header.copyright);
496 safefree(file->cont_header.comment);
497 safefree(file->internal);
498 file->io->close(file->handle);
499 safefree(file);
500 }
501
502 #define skip(num) \
503 { \
504 if (io->seek(fh, num, SEEK_CUR) != 0) {\
505 set_error(RMFF_ERR_IO, NULL); \
506 return -1; \
507 } \
508 }
509
510 static void
add_to_index(rmff_track_t * track,int64_t pos,uint32_t timecode,uint32_t packet_number)511 add_to_index(rmff_track_t *track,
512 int64_t pos,
513 uint32_t timecode,
514 uint32_t packet_number) {
515 if ((track->index != NULL) &&
516 (track->index[track->num_index_entries - 1].timecode == timecode))
517 return;
518 track->index = (rmff_index_entry_t *)
519 saferealloc(track->index, (track->num_index_entries + 1) *
520 sizeof(rmff_index_entry_t));
521 track->index[track->num_index_entries].pos = pos;
522 track->index[track->num_index_entries].timecode = timecode;
523 track->index[track->num_index_entries].packet_number = packet_number;
524 track->num_index_entries++;
525 }
526
527 static void
read_index(rmff_file_t * file,int64_t pos)528 read_index(rmff_file_t *file,
529 int64_t pos) {
530 void *fh;
531 mb_file_io_t *io;
532 rmff_track_t *track;
533 uint32_t object_id, num_entries;
534 uint32_t next_header_offset, i, timecode, offset, packet_number;
535 uint16_t id;
536
537 fh = file->handle;
538 io = file->io;
539
540 rmff_last_error = RMFF_ERR_OK;
541 io->seek(fh, pos, SEEK_SET);
542 object_id = read_uint32_be();
543 read_uint32_be(); /* object_size */
544 read_uint16_be(); /* object_version (2) */
545 if (rmff_last_error != RMFF_ERR_OK)
546 return;
547
548 if (object_id != rmffFOURCC('I', 'N', 'D', 'X'))
549 return;
550
551 num_entries = read_uint32_be();
552 id = read_uint16_be();
553 track = rmff_find_track_with_id(file, id);
554 if (track == NULL)
555 return;
556 next_header_offset = read_uint32_be();
557 track->num_index_entries = 0;
558 safefree(track->index);
559 track->index = NULL;
560
561 for (i = 0; i < num_entries; i++) {
562 if (read_uint16_be() != 0) /* version */
563 return;
564 timecode = read_uint32_be();
565 offset = read_uint32_be();
566 packet_number = read_uint32_be();
567 add_to_index(track, timecode, offset, packet_number);
568 }
569
570 if (next_header_offset > 0)
571 read_index(file, next_header_offset);
572 }
573
574 int
rmff_read_headers(rmff_file_t * file)575 rmff_read_headers(rmff_file_t *file) {
576 mb_file_io_t *io;
577 void *fh;
578 uint32_t object_id, object_size, size;
579 uint16_t object_version;
580 rmff_rmf_t *rmf;
581 rmff_prop_t *prop;
582 rmff_cont_t *cont;
583 rmff_mdpr_t *mdpr;
584 rmff_track_t *track;
585 real_video_props_t *rvp;
586 real_audio_v4_props_t *ra4p;
587 rmff_file_internal_t *fint;
588 int prop_header_found;
589 int64_t old_pos;
590
591 if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING)) {
592 set_error(RMFF_ERR_PARAMETERS, NULL);
593 return RMFF_ERR_PARAMETERS;
594 }
595 if (file->headers_read)
596 return 0;
597
598 io = file->io;
599 fh = file->handle;
600 fint = (rmff_file_internal_t *)file->internal;
601 if (io->seek(fh, 0, SEEK_SET)) {
602 set_error(RMFF_ERR_IO, NULL);
603 return RMFF_ERR_IO;
604 }
605
606 rmf = &file->rmf_header;
607
608 rmff_last_error = RMFF_ERR_OK;
609 read_uint32_be_to(&rmf->obj.id);
610 read_uint32_be_to(&rmf->obj.size);
611 read_uint16_be_to(&rmf->obj.version);
612 read_uint32_be_to(&rmf->format_version);
613 read_uint32_be_to(&rmf->num_headers);
614 if (rmff_last_error != RMFF_ERR_OK)
615 return rmff_last_error;
616
617 prop = &file->prop_header;
618 prop_header_found = 0;
619 cont = &file->cont_header;
620 while (1) {
621 rmff_last_error = RMFF_ERR_OK;
622 object_id = read_uint32_be();
623 object_size = read_uint32_be();
624 object_version = read_uint16_be();
625 if (rmff_last_error != RMFF_ERR_OK)
626 break;
627
628 if (object_id == rmffFOURCC('P', 'R', 'O', 'P')) {
629 rmff_put_uint32_be(&prop->obj.id, object_id);
630 rmff_put_uint32_be(&prop->obj.size, object_size);
631 rmff_put_uint16_be(&prop->obj.version, object_version);
632 read_uint32_be_to(&prop->max_bit_rate);
633 read_uint32_be_to(&prop->avg_bit_rate);
634 read_uint32_be_to(&prop->max_packet_size);
635 read_uint32_be_to(&prop->avg_packet_size);
636 read_uint32_be_to(&prop->num_packets);
637 read_uint32_be_to(&prop->duration);
638 read_uint32_be_to(&prop->preroll);
639 read_uint32_be_to(&prop->index_offset);
640 read_uint32_be_to(&prop->data_offset);
641 read_uint16_be_to(&prop->num_streams);
642 read_uint16_be_to(&prop->flags);
643 prop_header_found = 1;
644
645 } else if (object_id == rmffFOURCC('C', 'O', 'N', 'T')) {
646 if (file->cont_header_present) {
647 safefree(cont->title);
648 safefree(cont->author);
649 safefree(cont->copyright);
650 safefree(cont->comment);
651 }
652 memset(cont, 0, sizeof(rmff_cont_t));
653 rmff_put_uint32_be(&cont->obj.id, object_id);
654 rmff_put_uint32_be(&cont->obj.size, object_size);
655 rmff_put_uint16_be(&cont->obj.version, object_version);
656
657 size = read_uint16_be(); /* title_len */
658 if (size > 0) {
659 cont->title = (char *)safecalloc(size + 1);
660 io->read(fh, cont->title, size);
661 }
662 size = read_uint16_be(); /* author_len */
663 if (size > 0) {
664 cont->author = (char *)safecalloc(size + 1);
665 io->read(fh, cont->author, size);
666 }
667 size = read_uint16_be(); /* copyright_len */
668 if (size > 0) {
669 cont->copyright = (char *)safecalloc(size + 1);
670 io->read(fh, cont->copyright, size);
671 }
672 size = read_uint16_be(); /* comment_len */
673 if (size > 0) {
674 cont->comment = (char *)safecalloc(size + 1);
675 io->read(fh, cont->comment, size);
676 }
677 file->cont_header_present = 1;
678
679 } else if (object_id == rmffFOURCC('M', 'D', 'P', 'R')) {
680 track = (rmff_track_t *)safecalloc(sizeof(rmff_track_t));
681 track->file = (struct rmff_file_t *)file;
682 mdpr = &track->mdpr_header;
683 rmff_put_uint32_be(&mdpr->obj.id, object_id);
684 rmff_put_uint32_be(&mdpr->obj.size, object_size);
685 rmff_put_uint16_be(&mdpr->obj.version, object_version);
686 read_uint16_be_to(&mdpr->id);
687 track->id = rmff_get_uint16_be(&mdpr->id);
688 read_uint32_be_to(&mdpr->max_bit_rate);
689 read_uint32_be_to(&mdpr->avg_bit_rate);
690 read_uint32_be_to(&mdpr->max_packet_size);
691 read_uint32_be_to(&mdpr->avg_packet_size);
692 read_uint32_be_to(&mdpr->start_time);
693 read_uint32_be_to(&mdpr->preroll);
694 read_uint32_be_to(&mdpr->duration);
695 size = read_uint8(); /* stream_name_len */
696 if (size > 0) {
697 mdpr->name = (char *)safemalloc(size + 1);
698 io->read(fh, mdpr->name, size);
699 mdpr->name[size] = 0;
700 }
701 size = read_uint8(); /* mime_type_len */
702 if (size > 0) {
703 mdpr->mime_type = (char *)safemalloc(size + 1);
704 io->read(fh, mdpr->mime_type, size);
705 mdpr->mime_type[size] = 0;
706 }
707 size = read_uint32_be(); /* type_specific_size */
708 rmff_put_uint32_be(&mdpr->type_specific_size, size);
709 if (size > 0) {
710 mdpr->type_specific_data = (unsigned char *)safemalloc(size);
711 io->read(fh, mdpr->type_specific_data, size);
712 }
713
714 rvp = (real_video_props_t *)mdpr->type_specific_data;
715 ra4p = (real_audio_v4_props_t *)mdpr->type_specific_data;
716 if ((size >= sizeof(real_video_props_t)) &&
717 (get_fourcc(&rvp->fourcc1) == rmffFOURCC('V', 'I', 'D', 'O')))
718 track->type = RMFF_TRACK_TYPE_VIDEO;
719 else if ((size >= sizeof(real_audio_v4_props_t)) &&
720 (get_fourcc(&ra4p->fourcc1) ==
721 rmffFOURCC('.', 'r', 'a', 0xfd))) {
722 track->type = RMFF_TRACK_TYPE_AUDIO;
723 if ((rmff_get_uint16_be(&ra4p->version1) == 5) &&
724 (size < sizeof(real_audio_v5_props_t))) {
725 set_error(RMFF_ERR_DATA, "RealAudio v5 data indicated but "
726 "data too small");
727 return RMFF_ERR_DATA;
728 }
729 }
730
731 track->internal = safecalloc(sizeof(rmff_track_internal_t));
732 file->tracks =
733 (rmff_track_t **)saferealloc(file->tracks, (file->num_tracks + 1) *
734 sizeof(rmff_track_t *));
735 file->tracks[file->num_tracks] = track;
736 file->num_tracks++;
737
738 } else if (object_id == rmffFOURCC('D', 'A', 'T', 'A')) {
739 fint->data_offset = io->tell(fh) - (4 + 4 + 2);
740 file->num_packets_in_chunk = read_uint32_be();
741 fint->next_data_offset = read_uint32_be();
742 break;
743
744 } else {
745 /* Unknown header type */
746 set_error(RMFF_ERR_DATA, NULL);
747 return RMFF_ERR_DATA;
748 }
749 }
750
751 if (prop_header_found && (fint->data_offset > 0)) {
752 if (rmff_get_uint32_be(&file->prop_header.index_offset) > 0) {
753 old_pos = io->tell(fh);
754 read_index(file, rmff_get_uint32_be(&file->prop_header.index_offset));
755 io->seek(fh, old_pos, SEEK_SET);
756 }
757 file->headers_read = 1;
758 return 0;
759 }
760 set_error(RMFF_ERR_DATA, NULL);
761 return RMFF_ERR_DATA;
762 }
763
764 int
rmff_get_next_frame_size(rmff_file_t * file)765 rmff_get_next_frame_size(rmff_file_t *file) {
766 uint16_t object_version, length;
767 uint32_t object_id;
768 mb_file_io_t *io;
769 void *fh;
770 int result;
771 int64_t old_pos;
772
773 if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
774 (file->handle == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING)) {
775 set_error(RMFF_ERR_PARAMETERS, NULL);
776 return RMFF_ERR_PARAMETERS;
777 }
778 io = file->io;
779 fh = file->handle;
780 old_pos = io->tell(fh);
781 if ((file->size - old_pos) < 12) {
782 set_error(RMFF_ERR_EOF, NULL);
783 return RMFF_ERR_EOF;
784 }
785
786 object_version = read_uint16_be();
787 length = read_uint16_be();
788 object_id = ((uint32_t)object_version) << 16 | length;
789 if (object_id == rmffFOURCC('D', 'A', 'T', 'A')) {
790 skip(4 + 4); /* packets_in_chunk, next_data_header */
791 result = rmff_get_next_frame_size(file);
792 io->seek(fh, old_pos, SEEK_SET);
793 return result;
794 }
795 io->seek(fh, old_pos, SEEK_SET);
796 if (object_id == rmffFOURCC('I', 'N', 'D', 'X')) {
797 set_error(RMFF_ERR_EOF, NULL);
798 return RMFF_ERR_EOF;
799 }
800 return length - 12;
801 }
802
803 rmff_frame_t *
rmff_read_next_frame(rmff_file_t * file,void * buffer)804 rmff_read_next_frame(rmff_file_t *file,
805 void *buffer) {
806 rmff_frame_t *frame;
807 rmff_file_internal_t *fint;
808 uint16_t object_version, length;
809 uint32_t object_id;
810 mb_file_io_t *io;
811 void *fh;
812
813 if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
814 (file->handle == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING)) {
815 set_error(RMFF_ERR_PARAMETERS, NULL);
816 return NULL;
817 }
818 io = file->io;
819 fh = file->handle;
820 fint = (rmff_file_internal_t *)file->internal;
821 if ((file->size - io->tell(fh)) < 12) {
822 set_error(RMFF_ERR_EOF, NULL);
823 return NULL;
824 }
825
826 object_version = read_uint16_be();
827 length = read_uint16_be();
828 object_id = ((uint32_t)object_version) << 16 | length;
829 if (object_id == rmffFOURCC('D', 'A', 'T', 'A')) {
830 file->num_packets_in_chunk = read_uint32_be();
831 fint->next_data_offset = read_uint32_be();
832 file->num_packets_read = 0;
833 return rmff_read_next_frame(file, buffer);
834 }
835 if ((file->num_packets_read >= file->num_packets_in_chunk) ||
836 (object_id == rmffFOURCC('I', 'N', 'D', 'X'))) {
837 set_error(RMFF_ERR_EOF, NULL);
838 return NULL;
839 }
840
841 frame = (rmff_frame_t *)safecalloc(sizeof(rmff_frame_t));
842 if (buffer == NULL) {
843 buffer = safemalloc(length);
844 frame->allocated_by_rmff = 1;
845 }
846 frame->data = (unsigned char *)buffer;
847 frame->size = length - 12;
848 frame->id = read_uint16_be();
849 frame->timecode = read_uint32_be();
850 frame->reserved = read_uint8();
851 frame->flags = read_uint8();
852 if (io->read(fh, frame->data, frame->size) != frame->size) {
853 rmff_release_frame(frame);
854 set_error(RMFF_ERR_EOF, NULL);
855 return NULL;
856 }
857 file->num_packets_read++;
858
859 return frame;
860 }
861
862 rmff_frame_t *
rmff_allocate_frame(uint32_t size,void * buffer)863 rmff_allocate_frame(uint32_t size,
864 void *buffer) {
865 rmff_frame_t *frame;
866
867 if (size == 0) {
868 set_error(RMFF_ERR_PARAMETERS, NULL);
869 return NULL;
870 }
871 frame = (rmff_frame_t *)safecalloc(sizeof(rmff_frame_t));
872 if (buffer == NULL) {
873 buffer = safemalloc(size);
874 frame->allocated_by_rmff = 1;
875 }
876 frame->size = size;
877 frame->data = (unsigned char *)buffer;
878
879 return frame;
880 }
881
882 void
rmff_release_frame(rmff_frame_t * frame)883 rmff_release_frame(rmff_frame_t *frame) {
884 if (frame == NULL)
885 return;
886 if (frame->allocated_by_rmff)
887 safefree(frame->data);
888 safefree(frame);
889 }
890
891 void
rmff_set_cont_header(rmff_file_t * file,const char * title,const char * author,const char * copyright,const char * comment)892 rmff_set_cont_header(rmff_file_t *file,
893 const char *title,
894 const char *author,
895 const char *copyright,
896 const char *comment) {
897 if (file == NULL)
898 return;
899
900 safefree(file->cont_header.title);
901 safefree(file->cont_header.author);
902 safefree(file->cont_header.copyright);
903 safefree(file->cont_header.comment);
904 file->cont_header.title = safestrdup(title);
905 file->cont_header.author = safestrdup(author);
906 file->cont_header.copyright = safestrdup(copyright);
907 file->cont_header.comment = safestrdup(comment);
908 }
909
910 void
rmff_set_track_data(rmff_track_t * track,const char * name,const char * mime_type)911 rmff_set_track_data(rmff_track_t *track,
912 const char *name,
913 const char *mime_type) {
914 if (track == NULL)
915 return;
916 if (name != track->mdpr_header.name) {
917 safefree(track->mdpr_header.name);
918 track->mdpr_header.name = safestrdup(name);
919 }
920 if (mime_type != track->mdpr_header.mime_type) {
921 safefree(track->mdpr_header.mime_type);
922 track->mdpr_header.mime_type = safestrdup(mime_type);
923 }
924 }
925
926 void
rmff_set_type_specific_data(rmff_track_t * track,const unsigned char * data,uint32_t size)927 rmff_set_type_specific_data(rmff_track_t *track,
928 const unsigned char *data,
929 uint32_t size) {
930 if (track == NULL)
931 return;
932 if (data != track->mdpr_header.type_specific_data) {
933 safefree(track->mdpr_header.type_specific_data);
934 track->mdpr_header.type_specific_data =
935 (unsigned char *)safememdup(data, size);
936 rmff_put_uint32_be(&track->mdpr_header.type_specific_size, size);
937 }
938 }
939
940 rmff_track_t *
rmff_add_track(rmff_file_t * file,int create_index)941 rmff_add_track(rmff_file_t *file,
942 int create_index) {
943 rmff_track_t *track;
944 rmff_track_internal_t *tint;
945 int i, id, found;
946
947 if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_WRITING)) {
948 set_error(RMFF_ERR_PARAMETERS, NULL);
949 return NULL;
950 }
951
952 id = 0;
953 do {
954 found = 0;
955 for (i = 0; i < file->num_tracks; i++)
956 if (file->tracks[i]->id == id) {
957 found = 1;
958 id++;
959 break;
960 }
961 } while (found);
962
963 track = (rmff_track_t *)safecalloc(sizeof(rmff_track_t));
964 track->id = id;
965 track->file = file;
966 tint = (rmff_track_internal_t *)safecalloc(sizeof(rmff_track_internal_t));
967 tint->index_this = create_index;
968 track->internal = tint;
969
970 file->tracks =
971 (rmff_track_t **)saferealloc(file->tracks, (file->num_tracks + 1) *
972 sizeof(rmff_track_t *));
973 file->tracks[file->num_tracks] = track;
974 file->num_tracks++;
975
976 return track;
977 }
978
979 void
rmff_set_std_audio_v4_values(real_audio_v4_props_t * props)980 rmff_set_std_audio_v4_values(real_audio_v4_props_t *props) {
981 if (props == NULL)
982 return;
983
984 memset(props, 0, sizeof(real_audio_v4_props_t));
985 rmff_put_uint32_be(&props->fourcc1, rmffFOURCC('.', 'r', 'a', 0xfd));
986 rmff_put_uint16_be(&props->version1, 4);
987 rmff_put_uint32_be(&props->fourcc2, rmffFOURCC('.', 'r', 'a', '4'));
988 rmff_put_uint32_be(&props->stream_length, 0x10000000);
989 rmff_put_uint16_be(&props->version2, 4);
990 rmff_put_uint16_be(&props->header_size, 0x4e);
991
992 }
993
994 void
rmff_set_std_audio_v5_values(real_audio_v5_props_t * props)995 rmff_set_std_audio_v5_values(real_audio_v5_props_t *props) {
996 }
997
998 void
rmff_set_std_video_values(real_video_props_t * props)999 rmff_set_std_video_values(real_video_props_t *props) {
1000 }
1001
1002 static int
write_prop_header(rmff_file_t * file)1003 write_prop_header(rmff_file_t *file) {
1004 void *fh;
1005 mb_file_io_t *io;
1006 int bw;
1007
1008 io = file->io;
1009 fh = file->handle;
1010
1011 /* Write the PROP header. */
1012 bw = write_uint32_be(rmffFOURCC('P', 'R', 'O', 'P'));
1013 bw += write_uint32_be(0x32); /* object_size */
1014 bw += write_uint16_be(0); /* object_version */
1015
1016 bw += write_uint32_be_from(&file->prop_header.max_bit_rate);
1017 bw += write_uint32_be_from(&file->prop_header.avg_bit_rate);
1018 bw += write_uint32_be_from(&file->prop_header.max_packet_size);
1019 bw += write_uint32_be_from(&file->prop_header.avg_packet_size);
1020 bw += write_uint32_be_from(&file->prop_header.num_packets);
1021 bw += write_uint32_be_from(&file->prop_header.duration);
1022 bw += write_uint32_be_from(&file->prop_header.preroll);
1023 bw += write_uint32_be_from(&file->prop_header.index_offset);
1024 bw += write_uint32_be_from(&file->prop_header.data_offset);
1025 bw += write_uint16_be_from(&file->prop_header.num_streams);
1026 bw += write_uint16_be_from(&file->prop_header.flags);
1027
1028 return bw;
1029 }
1030
1031 static int
write_cont_header(rmff_file_t * file)1032 write_cont_header(rmff_file_t *file) {
1033 void *fh;
1034 mb_file_io_t *io;
1035 int bw, wanted_len, title_len, author_len, copyright_len, comment_len;
1036
1037 io = file->io;
1038 fh = file->handle;
1039
1040 if (file->cont_header.title == NULL)
1041 title_len = 0;
1042 else
1043 title_len = strlen(file->cont_header.title);
1044 if (file->cont_header.author == NULL)
1045 author_len = 0;
1046 else
1047 author_len = strlen(file->cont_header.author);
1048 if (file->cont_header.copyright == NULL)
1049 copyright_len = 0;
1050 else
1051 copyright_len = strlen(file->cont_header.copyright);
1052 if (file->cont_header.comment == NULL)
1053 comment_len = 0;
1054 else
1055 comment_len = strlen(file->cont_header.comment);
1056
1057 wanted_len = 4 + 4 + 2 + 4 * 2 + title_len + author_len + copyright_len +
1058 comment_len;
1059
1060 /* Write the CONT header. */
1061 bw = write_uint32_be(rmffFOURCC('C', 'O', 'N', 'T'));
1062 bw += write_uint32_be(wanted_len); /* object_size */
1063 bw += write_uint16_be(0); /* object_version */
1064 bw += write_uint16_be(title_len);
1065 if (file->cont_header.title != NULL)
1066 bw += io->write(fh, file->cont_header.title, title_len);
1067 bw += write_uint16_be(author_len);
1068 if (file->cont_header.author != NULL)
1069 bw += io->write(fh, file->cont_header.author, author_len);
1070 bw += write_uint16_be(copyright_len);
1071 if (file->cont_header.copyright != NULL)
1072 bw += io->write(fh, file->cont_header.copyright, copyright_len);
1073 bw += write_uint16_be(comment_len);
1074 if (file->cont_header.comment != NULL)
1075 bw += io->write(fh, file->cont_header.comment, comment_len);
1076
1077 if (bw == wanted_len)
1078 return 0;
1079 set_error(RMFF_ERR_IO, "Could not write the CONT header");
1080 return RMFF_ERR_IO;
1081 }
1082
1083 static int
write_mdpr_header(rmff_track_t * track)1084 write_mdpr_header(rmff_track_t *track) {
1085 void *fh;
1086 mb_file_io_t *io;
1087 int bw, wanted_len, name_len, mime_type_len;
1088
1089 io = track->file->io;
1090 fh = track->file->handle;
1091
1092 rmff_put_uint16_be(&track->mdpr_header.id, track->id);
1093 if (track->mdpr_header.name == NULL)
1094 name_len = 0;
1095 else
1096 name_len = strlen(track->mdpr_header.name);
1097 if (track->mdpr_header.mime_type == NULL)
1098 mime_type_len = 0;
1099 else
1100 mime_type_len = strlen(track->mdpr_header.mime_type);
1101
1102 wanted_len = 4 + 4 + 2 + 2 + 7 * 4 + 1 + name_len + 1 + mime_type_len +
1103 4 + rmff_get_uint32_be(&track->mdpr_header.type_specific_size);
1104
1105 /* Write the MDPR header. */
1106 bw = write_uint32_be(rmffFOURCC('M', 'D', 'P', 'R'));
1107 bw += write_uint32_be(wanted_len); /* object_size */
1108 bw += write_uint16_be(0); /* object_version */
1109
1110 bw += write_uint16_be_from(&track->mdpr_header.id);
1111 bw += write_uint32_be_from(&track->mdpr_header.max_bit_rate);
1112 bw += write_uint32_be_from(&track->mdpr_header.avg_bit_rate);
1113 bw += write_uint32_be_from(&track->mdpr_header.max_packet_size);
1114 bw += write_uint32_be_from(&track->mdpr_header.avg_packet_size);
1115 bw += write_uint32_be_from(&track->mdpr_header.start_time);
1116 bw += write_uint32_be_from(&track->mdpr_header.preroll);
1117 bw += write_uint32_be_from(&track->mdpr_header.duration);
1118 bw += write_uint8(name_len);
1119 if (track->mdpr_header.name != NULL)
1120 bw += io->write(fh, track->mdpr_header.name, name_len);
1121 bw += write_uint8(mime_type_len);
1122 if (track->mdpr_header.mime_type != NULL)
1123 bw += io->write(fh, track->mdpr_header.mime_type, mime_type_len);
1124 bw += write_uint32_be_from(&track->mdpr_header.type_specific_size);
1125 if (track->mdpr_header.type_specific_data != NULL)
1126 bw +=
1127 io->write(fh, track->mdpr_header.type_specific_data,
1128 rmff_get_uint32_be(&track->mdpr_header.type_specific_size));
1129
1130 if (wanted_len != bw) {
1131 set_error(RMFF_ERR_IO, "Could not write the MDPR header");
1132 return RMFF_ERR_IO;
1133 }
1134 clear_error();
1135 return RMFF_ERR_OK;
1136 }
1137
1138 static int
write_data_header(rmff_file_t * file)1139 write_data_header(rmff_file_t *file) {
1140 void *fh;
1141 mb_file_io_t *io;
1142 rmff_file_internal_t *fint;
1143 int bw;
1144
1145 io = file->io;
1146 fh = file->handle;
1147 fint = (rmff_file_internal_t *)file->internal;
1148
1149 bw = write_uint32_be(rmffFOURCC('D', 'A', 'T', 'A'));
1150 bw += write_uint32_be(fint->data_contents_size + 4 + 4 + 2 + 4 + 4);
1151 bw += write_uint16_be(0); /* object_version */
1152 bw += write_uint32_be(fint->num_packets); /* num_packets_in_chunk */
1153 bw += write_uint32_be(0); /* next_data_header_offset */
1154
1155 if (bw != 18) {
1156 set_error(RMFF_ERR_IO, "Could not write the DATA header");
1157 return RMFF_ERR_IO;
1158 }
1159 clear_error();
1160 return RMFF_ERR_OK;
1161 }
1162
1163 int
rmff_write_headers(rmff_file_t * file)1164 rmff_write_headers(rmff_file_t *file) {
1165 void *fh;
1166 mb_file_io_t *io;
1167 int i, bw, num_headers;
1168 rmff_file_internal_t *fint;
1169 const char *signature = ".RMF";
1170
1171 if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_WRITING)) {
1172 set_error(RMFF_ERR_PARAMETERS, NULL);
1173 return RMFF_ERR_PARAMETERS;
1174 }
1175
1176 io = file->io;
1177 fh = file->handle;
1178 io->seek(fh, 0, SEEK_SET);
1179 fint = (rmff_file_internal_t *)file->internal;
1180
1181 num_headers = 1 + /* PROP */
1182 1 + /* DATA */
1183 file->num_tracks + /* MDPR */
1184 fint->num_index_chunks; /* INDX */
1185 if (file->cont_header_present)
1186 num_headers++;
1187
1188 /* Write the file header. */
1189 bw = io->write(fh, signature, 4);
1190 bw += write_uint32_be(0x12); /* header_size */
1191 bw += write_uint16_be(0); /* object_version */
1192 bw += write_uint32_be(0); /* file_version */
1193 bw += write_uint32_be(num_headers);
1194
1195 if (bw != 18) {
1196 set_error(RMFF_ERR_IO, "Could not write the file header");
1197 return RMFF_ERR_IO;
1198 }
1199
1200 bw = write_prop_header(file);
1201 if (bw != 0x32) {
1202 set_error(RMFF_ERR_IO, "Could not write the PROP header");
1203 return RMFF_ERR_IO;
1204 }
1205
1206 if (file->cont_header_present) {
1207 bw = write_cont_header(file);
1208 if (bw != RMFF_ERR_OK)
1209 return bw;
1210 }
1211
1212 for (i = 0; i < file->num_tracks; i++) {
1213 bw = write_mdpr_header(file->tracks[i]);
1214 if (bw < RMFF_ERR_OK)
1215 return bw;
1216 }
1217
1218 fint->data_offset = io->tell(fh);
1219
1220 bw = write_data_header(file);
1221 if (bw < RMFF_ERR_OK)
1222 return bw;
1223
1224 clear_error();
1225 return RMFF_ERR_OK;
1226 }
1227
1228 int
rmff_fix_headers(rmff_file_t * file)1229 rmff_fix_headers(rmff_file_t *file) {
1230 rmff_prop_t *prop;
1231 rmff_mdpr_t *mdpr;
1232 rmff_track_t *track;
1233 rmff_file_internal_t *fint;
1234 rmff_track_internal_t *tint;
1235 int i;
1236
1237 if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_WRITING)) {
1238 set_error(RMFF_ERR_PARAMETERS, NULL);
1239 return RMFF_ERR_PARAMETERS;
1240 }
1241
1242 fint = (rmff_file_internal_t *)file->internal;
1243
1244 if (fint->highest_timecode > 0)
1245 fint->avg_bit_rate = (int64_t)fint->total_bytes * 8 * 1000 /
1246 fint->highest_timecode;
1247
1248 prop = &file->prop_header;
1249 rmff_put_uint32_be(&prop->max_bit_rate, fint->max_bit_rate);
1250 rmff_put_uint32_be(&prop->avg_bit_rate, fint->avg_bit_rate);
1251 rmff_put_uint32_be(&prop->max_packet_size, fint->max_packet_size);
1252 rmff_put_uint32_be(&prop->avg_packet_size, fint->avg_packet_size);
1253 rmff_put_uint32_be(&prop->num_packets, fint->num_packets);
1254 rmff_put_uint32_be(&prop->duration, fint->highest_timecode);
1255 rmff_put_uint32_be(&prop->index_offset, fint->index_offset);
1256 rmff_put_uint32_be(&prop->data_offset, fint->data_offset);
1257 rmff_put_uint16_be(&prop->num_streams, file->num_tracks);
1258
1259 for (i = 0; i < file->num_tracks; i++) {
1260 track = file->tracks[i];
1261 mdpr = &track->mdpr_header;
1262 tint = (rmff_track_internal_t *)track->internal;
1263
1264 if (tint->highest_timecode > 0)
1265 tint->avg_bit_rate = (int64_t)tint->total_bytes * 8 * 1000 /
1266 tint->highest_timecode;
1267
1268 rmff_put_uint16_be(&mdpr->id, track->id);
1269 rmff_put_uint32_be(&mdpr->max_bit_rate, tint->max_bit_rate);
1270 rmff_put_uint32_be(&mdpr->avg_bit_rate, tint->avg_bit_rate);
1271 rmff_put_uint32_be(&mdpr->max_packet_size, tint->max_packet_size);
1272 rmff_put_uint32_be(&mdpr->avg_packet_size, tint->avg_packet_size);
1273 rmff_put_uint32_be(&mdpr->duration, tint->highest_timecode);
1274 }
1275
1276 return rmff_write_headers(file);
1277 }
1278
1279 void
rmff_copy_track_headers(rmff_track_t * dst,rmff_track_t * src)1280 rmff_copy_track_headers(rmff_track_t *dst,
1281 rmff_track_t *src) {
1282 if ((dst == NULL) || (src == NULL))
1283 return;
1284
1285 safefree(dst->mdpr_header.name);
1286 safefree(dst->mdpr_header.mime_type);
1287 safefree(dst->mdpr_header.type_specific_data);
1288 memcpy(&dst->mdpr_header, &src->mdpr_header, sizeof(rmff_mdpr_t));
1289 dst->mdpr_header.name = safestrdup(src->mdpr_header.name);
1290 dst->mdpr_header.mime_type = safestrdup(src->mdpr_header.mime_type);
1291 dst->mdpr_header.type_specific_data = (unsigned char *)
1292 safememdup(src->mdpr_header.type_specific_data,
1293 rmff_get_uint32_be(&src->mdpr_header.type_specific_size));
1294 dst->type = src->type;
1295 }
1296
1297 static uint32_t
rmff_update_max_bitrate(rmff_bitrate_t * bitrate,uint32_t timecode,uint32_t frame_size)1298 rmff_update_max_bitrate(rmff_bitrate_t *bitrate,
1299 uint32_t timecode,
1300 uint32_t frame_size) {
1301 uint32_t i, max_bit_rate, total_size;
1302
1303 bitrate->timecodes = (uint32_t *)saferealloc(bitrate->timecodes,
1304 (bitrate->num_entries + 1) *
1305 sizeof(uint32_t));
1306 bitrate->timecodes[bitrate->num_entries] = timecode;
1307 bitrate->frame_sizes = (uint32_t *)saferealloc(bitrate->frame_sizes,
1308 (bitrate->num_entries + 1) *
1309 sizeof(uint32_t));
1310 bitrate->frame_sizes[bitrate->num_entries] = frame_size;
1311 bitrate->num_entries++;
1312
1313 if ((bitrate->timecodes[bitrate->num_entries - 1] -
1314 bitrate->timecodes[0]) < 1000)
1315 return 0;
1316
1317 total_size = 0;
1318 for (i = 0; i < bitrate->num_entries; i++)
1319 total_size += bitrate->frame_sizes[i];
1320 max_bit_rate = (uint32_t)
1321 ((int64_t)total_size * 8 * 1000 /
1322 (bitrate->timecodes[bitrate->num_entries - 1] -
1323 bitrate->timecodes[0]));
1324 i = 0;
1325 while ((i < bitrate->num_entries) &&
1326 ((bitrate->timecodes[bitrate->num_entries - 1] -
1327 bitrate->timecodes[i]) >= 1000))
1328 i++;
1329 memmove(&bitrate->timecodes[0], &bitrate->timecodes[i],
1330 (bitrate->num_entries - i) * sizeof(uint32_t));
1331 bitrate->timecodes = (uint32_t *)saferealloc(bitrate->timecodes,
1332 (bitrate->num_entries - i) *
1333 sizeof(uint32_t));
1334 memmove(&bitrate->frame_sizes[0], &bitrate->frame_sizes[i],
1335 (bitrate->num_entries - i) * sizeof(uint32_t));
1336 bitrate->frame_sizes = (uint32_t *)saferealloc(bitrate->frame_sizes,
1337 (bitrate->num_entries - i) *
1338 sizeof(uint32_t));
1339 bitrate->num_entries -= i;
1340
1341 return max_bit_rate;
1342 }
1343
1344 int
rmff_write_frame(rmff_track_t * track,rmff_frame_t * frame)1345 rmff_write_frame(rmff_track_t *track,
1346 rmff_frame_t *frame) {
1347 void *fh;
1348 mb_file_io_t *io;
1349 rmff_file_internal_t *fint;
1350 rmff_track_internal_t *tint;
1351 int bw, wanted_len;
1352 uint32_t bit_rate;
1353 int64_t pos;
1354
1355 if ((track == NULL) || (frame == NULL) || (frame->data == NULL) ||
1356 (track->file->open_mode != RMFF_OPEN_MODE_WRITING)) {
1357 set_error(RMFF_ERR_PARAMETERS, NULL);
1358 return RMFF_ERR_PARAMETERS;
1359 }
1360
1361 io = track->file->io;
1362 fh = track->file->handle;
1363 fint = (rmff_file_internal_t *)track->file->internal;
1364 tint = (rmff_track_internal_t *)track->internal;
1365
1366 pos = io->tell(fh);
1367 if (tint->index_this && ((frame->flags & 2) == 2))
1368 add_to_index(track, pos, frame->timecode, fint->num_packets);
1369 wanted_len = 2 + 2 + 2 + 4 + 1 + 1 + frame->size;
1370
1371 bw = write_uint16_be(0); /* object_version */
1372 bw += write_uint16_be(wanted_len);
1373 bw += write_uint16_be(track->id);
1374 bw += write_uint32_be(frame->timecode);
1375 bw += write_uint8(0); /* reserved */
1376 bw += write_uint8(frame->flags);
1377 bw += io->write(fh, frame->data, frame->size);
1378
1379 if (bw != wanted_len) {
1380 set_error(RMFF_ERR_IO, "Could not write the frame");
1381 return RMFF_ERR_IO;
1382 }
1383
1384 if (frame->size > fint->max_packet_size)
1385 fint->max_packet_size = frame->size;
1386 fint->avg_packet_size = (fint->avg_packet_size * fint->num_packets +
1387 frame->size) / (fint->num_packets + 1);
1388 fint->num_packets++;
1389 fint->total_bytes += frame->size;
1390 if (frame->timecode > fint->highest_timecode)
1391 fint->highest_timecode = frame->timecode;
1392 fint->data_contents_size += wanted_len;
1393
1394 if (frame->size > tint->max_packet_size)
1395 tint->max_packet_size = frame->size;
1396 tint->avg_packet_size = (tint->avg_packet_size * tint->num_packets +
1397 frame->size) / (tint->num_packets + 1);
1398 tint->num_packets++;
1399 tint->total_bytes += frame->size;
1400 if (frame->timecode > tint->highest_timecode)
1401 tint->highest_timecode = frame->timecode;
1402
1403 bit_rate = rmff_update_max_bitrate(&fint->bitrate, frame->timecode,
1404 frame->size);
1405 if (bit_rate > fint->max_bit_rate)
1406 fint->max_bit_rate = bit_rate;
1407 bit_rate = rmff_update_max_bitrate(&tint->bitrate, frame->timecode,
1408 frame->size);
1409 if (bit_rate > tint->max_bit_rate)
1410 tint->max_bit_rate = bit_rate;
1411
1412 clear_error();
1413 return RMFF_ERR_OK;
1414 }
1415
1416 rmff_track_t *
rmff_find_track_with_id(rmff_file_t * file,uint16_t id)1417 rmff_find_track_with_id(rmff_file_t *file,
1418 uint16_t id) {
1419 int i;
1420
1421 clear_error();
1422 if (file == 0) {
1423 set_error(RMFF_ERR_PARAMETERS, NULL);
1424 return NULL;
1425 }
1426 for (i = 0; i < file->num_tracks; i++)
1427 if (file->tracks[i]->id == id)
1428 return file->tracks[i];
1429 return NULL;
1430 }
1431
1432 int
rmff_write_index(rmff_file_t * file)1433 rmff_write_index(rmff_file_t *file) {
1434 void *fh;
1435 mb_file_io_t *io;
1436 rmff_file_internal_t *fint;
1437 rmff_track_t *track;
1438 int i, j, bw, wanted_len;
1439 int64_t pos;
1440
1441 if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_WRITING)) {
1442 set_error(RMFF_ERR_PARAMETERS, NULL);
1443 return RMFF_ERR_PARAMETERS;
1444 }
1445
1446 fh = file->handle;
1447 io = file->io;
1448 fint = (rmff_file_internal_t *)file->internal;
1449
1450 fint->num_index_chunks = 0;
1451 for (i = 0; i < file->num_tracks; i++)
1452 if (file->tracks[i]->num_index_entries > 0)
1453 fint->num_index_chunks++;
1454
1455 if (fint->num_index_chunks == 0) {
1456 clear_error();
1457 return RMFF_ERR_OK;
1458 }
1459
1460 io->seek(fh, 0, SEEK_END);
1461
1462 for (i = 0; i < file->num_tracks; i++) {
1463 track = file->tracks[i];
1464 if (track->num_index_entries > 0) {
1465 pos = io->tell(fh);
1466 if (fint->index_offset == 0)
1467 fint->index_offset = pos;
1468 wanted_len = 4 + 4 + 2 + /* normal chunk header */
1469 4 + /* num_entries */
1470 2 + /* track_id */
1471 4 + /* next_header_pos */
1472 (2 + /* version */
1473 4 + /* timecode */
1474 4 + /* offset */
1475 4) * /* packet_number */
1476 track->num_index_entries;
1477 bw = write_uint32_be(rmffFOURCC('I', 'N', 'D', 'X'));
1478 bw += write_uint32_be(wanted_len);
1479 bw += write_uint16_be(0); /* object_version */
1480 bw += write_uint32_be(track->num_index_entries);
1481 bw += write_uint16_be(track->id);
1482 if ((i + 1) < fint->num_index_chunks)
1483 bw += write_uint32_be(pos + wanted_len); /* next_indx_offset */
1484 else
1485 bw += write_uint32_be(0); /* no next_indx_chunk */
1486 for (j = 0; j < track->num_index_entries; j++) {
1487 bw += write_uint16_be(0); /* version */
1488 bw += write_uint32_be(track->index[j].timecode);
1489 bw += write_uint32_be(track->index[j].pos);
1490 bw += write_uint32_be(track->index[j].packet_number);
1491 }
1492 if (bw != wanted_len) {
1493 set_error(RMFF_ERR_IO, "Could not write the INDX chunk");
1494 return RMFF_ERR_IO;
1495 }
1496 }
1497 }
1498
1499 clear_error();
1500 return RMFF_ERR_OK;
1501 }
1502
1503 int
rmff_write_packed_video_frame(rmff_track_t * track,rmff_frame_t * frame)1504 rmff_write_packed_video_frame(rmff_track_t *track,
1505 rmff_frame_t *frame) {
1506 unsigned char *src_ptr, *ptr, *dst;
1507 int num_subpackets, i, offset, total_len;
1508 uint32_t *offsets, *lengths;
1509 rmff_frame_t *spframe;
1510 rmff_track_internal_t *tint;
1511
1512 if ((track == NULL) || (frame == NULL) ||
1513 (track->file == NULL) ||
1514 (track->file->open_mode != RMFF_OPEN_MODE_WRITING)) {
1515 set_error(RMFF_ERR_PARAMETERS, NULL);
1516 return RMFF_ERR_PARAMETERS;
1517 }
1518
1519 tint = (rmff_track_internal_t *)track->internal;
1520 src_ptr = frame->data;
1521 num_subpackets = *src_ptr + 1;
1522 src_ptr++;
1523 if (frame->size < (num_subpackets * 8 + 1)) {
1524 set_error(RMFF_ERR_DATA, "RealVideo unpacking failed: frame size "
1525 "too small. Could not extract sub packet offsets.");
1526 return RMFF_ERR_DATA;
1527 }
1528
1529 offsets = (uint32_t *)safemalloc(num_subpackets * sizeof(uint32_t));
1530 for (i = 0; i < num_subpackets; i++) {
1531 src_ptr += 4;
1532 offsets[i] = rmff_get_uint32_le(src_ptr);
1533 src_ptr += 4;
1534 }
1535 if ((offsets[num_subpackets - 1] + (src_ptr - frame->data)) >= frame->size) {
1536 safefree(offsets);
1537 set_error(RMFF_ERR_DATA, "RealVideo unpacking failed: frame size "
1538 "too small. The sub packet offsets indicate a size "
1539 "larger than the actual size.");
1540 return RMFF_ERR_DATA;
1541 }
1542 total_len = frame->size - (src_ptr - frame->data);
1543 lengths = (uint32_t *)safemalloc(num_subpackets * sizeof(uint32_t));
1544 for (i = 0; i < (num_subpackets - 1); i++)
1545 lengths[i] = offsets[i + 1] - offsets[i];
1546 lengths[num_subpackets - 1] = total_len - offsets[num_subpackets - 1];
1547
1548 dst = (unsigned char *)safemalloc(frame->size * 2);
1549 for (i = 0; i < num_subpackets; i++) {
1550 ptr = dst;
1551 if (num_subpackets == 1) {
1552 /* BROKEN! */
1553 *ptr = 0xc0; /* complete frame */
1554 ptr++;
1555
1556 } else {
1557 *ptr = (num_subpackets >> 1) & 0x7f; /* number of subpackets */
1558 if (i == (num_subpackets - 1)) /* last fragment? */
1559 *ptr |= 0x80;
1560 ptr++;
1561
1562 *ptr = i + 1; /* fragment number */
1563 *ptr |= ((num_subpackets & 0x01) << 7); /* number of subpackets */
1564 ptr++;
1565 }
1566
1567 /* total packet length: */
1568 if (total_len > 0x3fff) {
1569 rmff_put_uint16_be(ptr, ((total_len & 0x3fff0000) >> 16));
1570 ptr += 2;
1571 rmff_put_uint16_be(ptr, total_len & 0x0000ffff);
1572 } else
1573 rmff_put_uint16_be(ptr, 0x4000 | total_len);
1574 ptr += 2;
1575
1576 /* fragment offset from beginning/end: */
1577 if (num_subpackets == 1)
1578 offset = frame->timecode;
1579 else if (i < (num_subpackets - 1))
1580 offset = offsets[i];
1581 else
1582 /* If it's the last packet then the 'offset' is the fragment's length. */
1583 offset = lengths[i];
1584
1585 if (offset > 0x3fff) {
1586 rmff_put_uint16_be(ptr, ((offset & 0x3fff0000) >> 16));
1587 ptr += 2;
1588 rmff_put_uint16_be(ptr, offset & 0x0000ffff);
1589 } else
1590 rmff_put_uint16_be(ptr, 0x4000 | offset);
1591 ptr += 2;
1592
1593 /* sequence number = frame number & 0xff */
1594 *ptr = tint->num_packed_frames & 0xff;
1595 ptr++;
1596
1597 memcpy(ptr, src_ptr, lengths[i]);
1598 src_ptr += lengths[i];
1599 ptr += lengths[i];
1600
1601 spframe = rmff_allocate_frame(ptr - dst, dst);
1602 if (spframe == NULL) {
1603 safefree(offsets);
1604 safefree(lengths);
1605 safefree(dst);
1606 set_error(RMFF_ERR_IO, "Memory allocation error: Could not get a "
1607 "rmff_frame_t");
1608 return RMFF_ERR_IO;
1609 }
1610 spframe->timecode = frame->timecode;
1611 spframe->flags = frame->flags;
1612 if (rmff_write_frame(track, spframe) != RMFF_ERR_OK) {
1613 safefree(offsets);
1614 safefree(lengths);
1615 safefree(dst);
1616 return rmff_last_error;
1617 }
1618 rmff_release_frame(spframe);
1619 }
1620 safefree(offsets);
1621 safefree(lengths);
1622 safefree(dst);
1623
1624 tint->num_packed_frames++;
1625
1626 clear_error();
1627 return RMFF_ERR_OK;
1628 }
1629
1630 static inline uint16_t
data_get_uint16_be(unsigned char ** data,int * len)1631 data_get_uint16_be(unsigned char **data,
1632 int *len) {
1633 (*data) += 2;
1634 (*len) -= 2;
1635 return rmff_get_uint16_be((*data) - 2);
1636 }
1637
1638 static inline unsigned char
data_get_uint8(unsigned char ** data,int * len)1639 data_get_uint8(unsigned char **data,
1640 int *len) {
1641 (*data)++;
1642 (*len)--;
1643 return *((*data) - 1);
1644 }
1645
1646 static int
deliver_segments(rmff_track_t * track,uint32_t timecode)1647 deliver_segments(rmff_track_t *track,
1648 uint32_t timecode) {
1649 uint32_t len, total;
1650 int i;
1651 unsigned char *buffer, *ptr;
1652 rmff_video_segment_t *segment;
1653 rmff_track_internal_t *tint;
1654 rmff_frame_t *frame;
1655
1656 tint = (rmff_track_internal_t *)track->internal;
1657 if (tint->num_segments == 0)
1658 return tint->num_assembled_frames;
1659
1660 len = 0;
1661 total = 0;
1662
1663 for (i = 0; i < tint->num_segments; i++) {
1664 segment = &tint->segments[i];
1665 if (len < (segment->offset + segment->size))
1666 len = segment->offset + segment->size;
1667 total += segment->size;
1668 }
1669
1670 if (len != total) {
1671 sprintf(error_msg_buffer, "Packet assembly failed. "
1672 "Expected packet length was %d but found only %d sub packets "
1673 "containing %d bytes.", len, tint->num_segments, total);
1674 set_error(RMFF_ERR_DATA, error_msg_buffer);
1675 return RMFF_ERR_DATA;
1676 }
1677
1678 len += 1 + 2 * 4 * (tint->f_merged ? 1: tint->num_segments);
1679 buffer = (unsigned char *)safemalloc(len);
1680 ptr = buffer;
1681
1682 *ptr = tint->f_merged ? 0 : tint->num_segments - 1;
1683 ptr++;
1684
1685 if (tint->f_merged) {
1686 rmff_put_uint32_le(ptr, 1);
1687 ptr += 4;
1688 rmff_put_uint32_le(ptr, 0);
1689 ptr += 4;
1690 } else {
1691 for (i = 0; i < tint->num_segments; i++) {
1692 rmff_put_uint32_le(ptr, 1);
1693 ptr += 4;
1694 rmff_put_uint32_le(ptr, tint->segments[i].offset);
1695 ptr += 4;
1696 }
1697 }
1698
1699 for (i = 0; i < tint->num_segments; i++) {
1700 segment = &tint->segments[i];
1701 memcpy(ptr, segment->data, segment->size);
1702 ptr += segment->size;
1703 }
1704
1705 frame = rmff_allocate_frame(len, buffer);
1706 frame->timecode = timecode;
1707 frame->flags = tint->c_keyframe ? RMFF_FRAME_FLAG_KEYFRAME : 0;
1708 tint->assembled_frames = (rmff_frame_t **)
1709 saferealloc(tint->assembled_frames, (tint->num_assembled_frames + 1) *
1710 sizeof(rmff_frame_t *));
1711 tint->assembled_frames[tint->num_assembled_frames] = frame;
1712 tint->num_assembled_frames++;
1713
1714 for (i = 0; i < tint->num_segments; i++)
1715 safefree(tint->segments[i].data);
1716 safefree(tint->segments);
1717 tint->segments = NULL;
1718 tint->num_segments = 0;
1719
1720 return tint->num_assembled_frames;
1721 }
1722
1723 int
rmff_assemble_packed_video_frame(rmff_track_t * track,rmff_frame_t * frame)1724 rmff_assemble_packed_video_frame(rmff_track_t *track,
1725 rmff_frame_t *frame) {
1726 uint32_t vpkg_header, vpkg_length, vpkg_offset;
1727 uint32_t len, this_timecode;
1728 int data_len, result;
1729 unsigned char *data;
1730 rmff_track_internal_t *tint;
1731 rmff_video_segment_t *segment;
1732
1733 if ((track == NULL) || (frame == NULL) || (frame->data == NULL) ||
1734 (frame->size == 0)) {
1735 set_error(RMFF_ERR_PARAMETERS, NULL);
1736 return RMFF_ERR_PARAMETERS;
1737 }
1738
1739 tint = (rmff_track_internal_t *)track->internal;
1740 if (tint->num_segments == 0) {
1741 tint->c_keyframe = (frame->flags & RMFF_FRAME_FLAG_KEYFRAME) ==
1742 RMFF_FRAME_FLAG_KEYFRAME ? 1 : 0;
1743 tint->f_merged = 0;
1744 }
1745
1746 if (frame->timecode != tint->c_timecode)
1747 deliver_segments(track, tint->c_timecode);
1748
1749 data = frame->data;
1750 data_len = frame->size;
1751
1752 while (data_len > 2) {
1753 vpkg_length = 0;
1754 vpkg_offset = 0;
1755 this_timecode = frame->timecode;
1756
1757 // bit 7: 1=last block in block chain
1758 // bit 6: 1=short header (only one block?)
1759 vpkg_header = data_get_uint8(&data, &data_len);
1760
1761 if ((vpkg_header & 0xc0) == 0x40) {
1762 // seems to be a very short header
1763 // 2 bytes, purpose of the second byte yet unknown
1764 data_get_uint8(&data, &data_len);
1765 vpkg_length = data_len;
1766
1767 } else {
1768 if ((vpkg_header & 0x40) == 0) {
1769 if (data_len < 1) {
1770 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1771 "data available");
1772 return RMFF_ERR_DATA;
1773 }
1774 // sub-seqnum (bits 0-6: number of fragment. bit 7: ???)
1775 data_get_uint8(&data, &data_len);
1776 }
1777
1778 // size of the complete packet
1779 // bit 14 is always one (same applies to the offset)
1780 if (data_len < 2) {
1781 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1782 "data available");
1783 return RMFF_ERR_DATA;
1784 }
1785 vpkg_length = data_get_uint16_be(&data, &data_len);
1786
1787 if ((vpkg_length & 0x8000) == 0x8000)
1788 tint->f_merged = 1;
1789
1790 if ((vpkg_length & 0x4000) == 0) {
1791 if (data_len < 2) {
1792 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1793 "data available");
1794 return RMFF_ERR_DATA;
1795 }
1796 vpkg_length <<= 16;
1797 vpkg_length |= data_get_uint16_be(&data, &data_len);
1798 vpkg_length &= 0x3fffffff;
1799
1800 } else
1801 vpkg_length &= 0x3fff;
1802
1803 // offset of the following data inside the complete packet
1804 // Note: if (hdr&0xC0)==0x80 then offset is relative to the
1805 // _end_ of the packet, so it's equal to fragment size!!!
1806 if (data_len < 2) {
1807 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1808 "data available");
1809 return RMFF_ERR_DATA;
1810 }
1811 vpkg_offset = data_get_uint16_be(&data, &data_len);
1812
1813 if ((vpkg_offset & 0x4000) == 0) {
1814 if (data_len < 2) {
1815 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1816 "data available");
1817 return RMFF_ERR_DATA;
1818 }
1819 vpkg_offset <<= 16;
1820 vpkg_offset |= data_get_uint16_be(&data, &data_len);
1821 vpkg_offset &= 0x3fffffff;
1822
1823 } else
1824 vpkg_offset &= 0x3fff;
1825
1826 if (data_len < 1) {
1827 set_error(RMFF_ERR_DATA, "Assembly failed: not enough frame "
1828 "data available");
1829 return RMFF_ERR_DATA;
1830 }
1831 data_get_uint8(&data, &data_len);
1832
1833 if ((vpkg_header & 0xc0) == 0xc0) {
1834 this_timecode = vpkg_offset;
1835 vpkg_offset = 0;
1836 } else if ((vpkg_header & 0xc0) == 0x80)
1837 vpkg_offset = vpkg_length - vpkg_offset;
1838 }
1839
1840 if (vpkg_offset > vpkg_length)
1841 return RMFF_ERR_DATA;
1842
1843 if (data_len < (int)(vpkg_length - vpkg_offset))
1844 len = data_len;
1845 else
1846 len = (int)(vpkg_length - vpkg_offset);
1847
1848 tint->segments = (rmff_video_segment_t *)
1849 saferealloc(tint->segments, (tint->num_segments + 1) *
1850 sizeof(rmff_video_segment_t));
1851 segment = &tint->segments[tint->num_segments];
1852 tint->num_segments++;
1853
1854 segment->offset = vpkg_offset;
1855 segment->data = (unsigned char *)safemalloc(len);
1856 segment->size = len;
1857 memcpy(segment->data, data, len);
1858 data += len;
1859 data_len -= len;
1860
1861 tint->c_timecode = this_timecode;
1862
1863 if (((vpkg_header & 0x80) == 0x80) ||
1864 ((vpkg_offset + len) >= vpkg_length)) {
1865 result = deliver_segments(track, this_timecode);
1866 tint->c_keyframe = 0;
1867 if (result < 0)
1868 return result;
1869 }
1870 }
1871
1872 return tint->num_assembled_frames;
1873 }
1874
1875 rmff_frame_t *
rmff_get_packed_video_frame(rmff_track_t * track)1876 rmff_get_packed_video_frame(rmff_track_t *track) {
1877 rmff_track_internal_t *tint;
1878 rmff_frame_t *frame;
1879
1880 if (track == NULL) {
1881 set_error(RMFF_ERR_PARAMETERS, NULL);
1882 return NULL;
1883 }
1884
1885 tint = (rmff_track_internal_t *)track->internal;
1886 if (tint->num_assembled_frames == 0) {
1887 clear_error();
1888 return NULL;
1889 }
1890
1891 frame = tint->assembled_frames[0];
1892 tint->num_assembled_frames--;
1893 if (tint->num_assembled_frames == 0) {
1894 safefree(tint->assembled_frames);
1895 tint->assembled_frames = NULL;
1896 } else {
1897 memmove(&tint->assembled_frames[0], &tint->assembled_frames[1],
1898 tint->num_assembled_frames * sizeof(rmff_frame_t *));
1899 tint->assembled_frames = (rmff_frame_t **)
1900 saferealloc(tint->assembled_frames, tint->num_assembled_frames *
1901 sizeof(rmff_frame_t *));
1902 }
1903
1904 clear_error();
1905 return frame;
1906 }
1907