Main Page | Data Structures | File List | Data Fields | Globals

librmff Documentation

0.6.2

Introduction

librmff is short for 'RealMedia file format access library'. It aims at providing the programmer an easy way to read and write RealMedia files. It does not contain any codecs for audio/video handling.

You can find a description of the RealMedia file format at http://www.pcisys.net/~melanson/codecs/rmff.htm

License

The library was written by Moritz Bunkus <moritz@bunkus.org>. It is licensed under the terms of the GNU Lesser General Public License (GNU LGPL) which can be found in the file COPYING.

Usage

Here are very short samples of how to use the library.

Reading an existing file

Reading an existing file requires four steps: Opening the file, reading the headers, reading all the frames and closing the file.

Example:

rmff_file_t *file; rmff_frame_t *frame; file = rmff_open_file("sample_file.rm", RMFF_OPEN_MODE_READING); if (file == NULL) { // Handle the error. return; } if (rmff_read_headers(file) == RMFF_ERR_OK) { // Output some general information about the tracks in the file. // Now read all the frames. while ((frame = rmff_read_next_frame(file, NULL)) != NULL) { // Do something with the frame and release it afterwards. rmff_release_frame(frame); } } rmff_close_file(file);

Creating a new file

Creating a new file is a bit more complex. This library only provides a low level codec independant layer to the RealMedia file format.

Creating a new file involves the following step in this particular order:

  1. open a new file with RMFF_OPEN_MODR_WRITING,
  2. add track entries with rmff_add_track,
  3. write the headers with rmff_write_headers,
  4. write all the frames with rmff_write_frame,
  5. optionally write the indexes with rmff_write_index,
  6. fix all the headers with rmff_fix_headers and
  7. close the file with rmff_close_file.

Please note that the error handling is not shown in the following example:

rmff_file_t *file; rmff_track_t *track; rmff_frame_t *frame; file = rmff_open_file("new_file.rm", RMFF_OPEN_MODE_WRITING); track = rmff_add_track(file, 1); // Also create an index for this track. // The track types etc are stored in the ::rmff_mdpr_t#type_specific_data // It usually contains a ::real_audio_v4_props_t, ::real_audio_v5_props_t // or ::real_video_props_t structures which have to be set by the // calling application. // After setting the structures: rmff_write_headers(file); while (!done) { // Generate frames. ... frame = rmff_allocate_frame(size, NULL); rmff_write_frame(track, frame); rmff_release_frame(frame); } rmff_write_index(file); rmff_fix_headers(file); rmff_close_file(file);

Memory handling

Generally librmff allocates and frees memory itself. You should never mess with pointers inside the structures directly but use the provided functions for manipulating it. There are two exceptions to this rule: the frame handling and the app_data pointers.

The app_data members in ::rmff_file_t and ::rmff_track_t are never touched by librmff and can be used by the application to store its own data.

The functions rmff_read_next_frame, rmff_release_frame and rmff_allocate_frame allow the application to provide its own buffers for storing the frame contents. librmff will not copy this memory further. It will read directly into the buffer or write directly from the buffer into the file.

Example:

rmff_frame_t *frame; unsigned char *buffer, int size; while (1) { // Get the next frame's size. size = rmff_get_next_frame_size(file); // Have we reached the end of the file? if (size == -1) break; // Allocate enough space for this frame and let librmff read directly // into it. buffer = (unsigned char *)malloc(size); frame = rmff_read_next_frame(file, buffer); // Now do something with the buffer. Afterwards release the frame. rmff_release_frame(frame); // The buffer is still allocated. So free it now. free(buffer); }

Packed video frames

The RealVideo frames are not stored one-complete-frame in one packet (packet meaning one 'frame' used by rmff_write_frame and returned by rmff_read_next_frame). They are split up into several sub packets. However, the Real decoder libraries usually need a completely assembled frame that contains all sub packets along with the offsets to each sub packet in the complete frame.

librmff can make the developper's life easier because it provides the function rmff_write_packed_video_frame that will split up such an assembled packet into all the sub packets and write those automatically, and two functions that assemble sub packets into such a packed frame (rmff_assemble_packed_video_frame and rmff_get_packed_video_frame).

Bitstream format

There are three layouts for how the bitstream for such a sub packet looks like which depends on the first two bits.

  1. For AA = 00 and AA = 10:
    AABBBBBB BCCCCCCC DEFFFFFF FFFFFFFF (GGGGGGGG GGGGGGGG) HIJJJJJJ JJJJJJJJ (KKKKKKKK KKKKKKKK) LLLLLLLL
  2. For AA = 01:
    AABBBBBB BCCCCCCC
  3. For AA = 11:
    AABBBBBB DEFFFFFF FFFFFFFF (GGGGGGGG GGGGGGGG) HIJJJJJJ JJJJJJJJ (KKKKKKKK KKKKKKKK) LLLLLLLL

Packed frame assembly example

Here's a short example how to use the packet assembly:
rmff_frame_t *raw_frame, *packed_frame; rmff_track_t *track; int result; // Open the file, check the tracks. while ((raw_frame = rmff_read_next_frame(file, NULL)) != NULL) { track = rmff_find_track_with_id(file, raw_frame->id); if (track->type != RMFF_TRACK_TYPE_VIDEO) { // Handle audio etc. } else { if ((result = rmff_assemble_packed_video_frame(track, raw_frame)) < 0) { // Handle the error. } else { while ((packed_frame = rmff_get_packed_video_frame(track)) != NULL) { // Do something with the assembled frame and release it afterwards. rmff_release_frame(packed_frame); } } } rmff_release_frame(raw_frame); }

Generated on Thu Jun 24 16:21:13 2004 for librmff by doxygen 1.3.6-20040222