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