release
dev builds
extras
themes manual
wiki
device status forums
mailing lists
IRC bugs
patches
dev guide



Search | Go
Wiki > Main > DocsIndex > HowToWriteCodecs

How to write a codec for Rockbox

Codec structure

The entry point for a codec is in apps/codecs/codec_name.c (e.g. flac.c). This code handles control of the codec using the API as in the example below. Decoding itself is usually handled one level further down (e.g. apps/codecs/libcodec_name/).

  • a minimal Codec structure looks like this:

#include "codeclib.h"

CODEC_HEADER

/* this is the codec entry point */
enum codec_status codec_main(enum codec_entry_call_reason reason)
{
    /* Check reason if actually doing something useful with it */
    if (reason == CODEC_LOAD)
    {
        /* Codec is being loaded and initialized; do load-time inits here */
        /* May include creating threads or setting DSP parameters that do not
           change on a per-track basis */
        return CODEC_OK; /* OR return CODEC_ERROR if init fails */
        
    }
    else if (reason == CODEC_UNLOAD)
    {
        /* Codec is about to be removed from memory; clean up any resouces
           allocated */
        return CODEC_OK; /* Return value ignored */
    }
    else
    {
        /* Default response in cases where codec has nothing to do when
           codec_main is called for a particular reason */
        return CODEC_OK;
    }
}

/* this is called for each file to process */
enum codec_status codec_run(void)
{
    /* param that receives data for a command */
    intptr_t param;

    if (codec_init()) {
        DEBUGF("codec init failed\n");
        return CODEC_ERROR;
    }

    codec_set_replaygain(ci->id3);

    /* Init Codec for Track */ 

    /* Make use of 44.1khz */
    ci->configure(DSP_SET_FREQUENCY, 44100);
    /* Sample depth is 16 bit little endian */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
    /* Stereo or Mono output ? */
    ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
   
    /* reset eleapsed or (see below)... */
    ci->set_elapsed(0);

    /* ...check ci->id3->elapsed and ci->id3->offset if playback is starting
     * for a mid-track resume. Either or both fields will be non-zero if playback
     * is to start at some point other than the beginning of the track. If only one
     * field is non-zero, that one should have priority. If both are non-zero, your
     * codec may choose the appropriate (eg., the most accurate) way to seek
     * to the resume point for the track and decides which has priority. If only
     * one of them is meaningful in your particular case, it is safe to ignore the
     * other (eg., can only seek/resume by elapsed time because it is an
     * emulator format and the offset is never changed). */
   
    /* The main decoder loop */    
    while (1)
    {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
        {
            /* Playback said codec should stop */
            break;
        }

        if (action == CODEC_ACTION_SEEK_TIME) {
            /* New time is ready in param */
            /* absolute position in ms */
           
            /* seek to pos */
            
            /* update elapsed */
            ci->set_elapsed(param);

            /* seek ready */    
            ci->seek_complete();            
        }

         /* Generate a buffer full of Audio */

        /* Insert a buffer full of samples */
        ci->pcmbuf_insert(sample_buffer, NULL, numberOfSamples);
        
        /* Update elapsed in ms */
        ci->set_elapsed(current_Pos);
        
        if( EndOfFile )
            break;
    }
 
    return CODEC_OK;    
}

Adding a decoder to Rockbox

This is of course subject to change as things move around in the source.

  • Put your source in apps/codecs

  • apps/codecs/SOURCES
    • Add the file name.

  • apps/codecs/Makefile
    • Add a rule like ${OBJDIR}/wav.elf : $(OBJDIR)/wav.o

  • apps/metadata.h
    • Add a value to the Audio file types enum.

  • apps/metadata.c
    • Add a case to the switch in get_metadata()
    • Add an entry or entries to audio_formats[]
    • If one codec supports multiple formats, add a case to get_audio_base_codec_type().
    • If the format is atomic audio (must be completely loaded onto the buffer), add a case to get_audio_base_data_type().
    • If file can be resumed without loading it from the beginning, add a case to format_buffers_with_offset().

  • apps/metadata
    • Add your metadata detection here.

  • apps/filetypes.c
    • Add an element to inbuilt_filetypes struct.

Finally, optimize your codec for your player to maximize battery life: TargetSpecificOptimization
r12 - 13 Mar 2014 - 11:27:59 - MichaelSevakis

Parents: DocsIndex
Copyright by the contributing authors.