Adding RM support to Rockbox
This project is part of the Google Summer of Code 2009 project
Rockbox already supports a wide range of codecs, it still, however, does not have support for RM. The main aim of the project, thus, is to add support for RM format, and to have enough fixed-point decoders to handle the commonly available RM files.
- Write a standalone rm-wav converter. DONE
- Fixed-point replacement for cook decoder. DONE
- Porting to Rockbox. DONE
- If time allows : Adding other codec(s).
Currently the following codecs are supported
All four codecs decode faster than real-time and support seeking.
- Isolated cook decoder from libffmpeg.
- Removed the need for AVCodecContext and AVPacket from the source by defining new structures RMContext and RMPacket that would carry the needed data.
- Produced properly constructed frames from the parser : Cook actually scrambles the audio frames using a very weird formula, so for the decoder to work properly, the frames have to be reconstructed first in one scrambling unit (see CookCodec ), and then sent frame by frame to the decoder.
- The program is now able to take in an rm file, with cook codec, and produce a decoded wav file. Latest code is available in svn.
- I found a bug with the converter. When a file had avg_packet_size ! = frame_size, the converter would produce an output which is shorter by a few seconds than ffmpeg's. This is due to the fact that it keeps constructing scrambling units containing sub_packet_h number of packets, so in this specific sample where packet_size ! = frame_size, the last decoding loop will leave away a few undecoded frames, because remaining number of frames would be less than sub_packet_h, i.e not enough to construct a scrambling unit. This bug was fixed by making the demuxer construct a partially filled scrambling unit whenever this situation is encountered.
- Patched cook.c with the aforementioned fixed-point patch. To use the patch, I had to check out a revision of cook.c that was actually older than the patch itself. Also, there were certain hunks that always failed in the patch, so I had to do those by hand by reading through them in the diff file and applying the required changes to cook.c. Also, I had to modify dsputil.h a little bit and get an old revision of fft.c . Changed : For consistency, fixed-point conversion was repeated one more time. I didn't check out an old revision of cook.c, instead, I examined the patch, how it changed the different functions, etc. and adapted those changes to the current revision of cook.c.
- The rm2wav program now produces the same output wav files using fixed-point arithmetic.
- Removed mallocs from the decoder - There's was only one malloc in the init function which has been replaced by a fixed size array.
- The decoder now consumes packets directly from the scrambling unit, this has been done to avoid memcpy-ing from the scrambling unit to an input buffer.
- Initialization of VLC tables used dynamic allocation - Resolved by hard-coding fixed size tables.
- Major modifications/clean-ups have been applied to the code and it's now mostly ready to be ported.
- Rockbox now recognizes a rm/ra file as an audio file, calls get_rm_metadata() which works fine for now and directs the playback engine to the correct codec as expected. get_rm_metadata() still needs some cleaning to be good enough to be committed.
- The test program was modified to read audio frames from a memory buffer instead of a file descriptor. This makes the decoding process as close as possible to how it's done in rockbox and eases debugging before the actual porting of cook to rockbox.
- Modified the metadata parser to read some more parameters needed by the codec.
- Ported cook codec, but cook/rm files still only work in the sim.
- Cook/RM files now play on target.
- Added seeking support. ffmpeg doesn't implement seeking in rm in a good way, and the rm parser is currently being rewritten, so I had to come up with an algorithm for seeking in rm. It basically depends on searching blocks (scrambling units) for the time stamp that's closest to the desired seek time, then that seek point will certainly be within that block. time offset is then measured between the seek time and the block's time stamp, and using the bit rate, the exact number of packet in the block could be determined.
Remaining work for current phase
Copyright © by the contributing authors.