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



Wiki > Main > HowToWriteCodecs (compare)

Difference: HowToWriteCodecs (r11 vs. r10)

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(void) codec_main(enum codec_entry_call_reason reason) { next_track: /* 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; } while (!*ci->taginfo_ready && !ci->stop_codec) ci->sleep(1); 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 */ ci->set_elapsed(0); /* The main decoder loop */ while (1) { ci->yield(); enum codec_command_action action = ci->get_command(¶m); if (ci->stop_codec || ci->new_track) (action == CODEC_ACTION_HALT) { /* Playback said codec should stop */ break; } if (ci->seek_time) (action == CODEC_ACTION_SEEK_TIME) { /* New time is ready in ci->seek_time param */ /* absolute position in ms */ /* seek to pos */ /* update elapsed */ ci->set_elapsed(ci->seek_time); 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 Update elapsed in ms */ ci->set_elapsed(current_Pos); if( EndOfFile ) break; } if (ci->request_next_track()) goto next_track; 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/ 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

Revision r11 - 01 May 2011 - 21:53 - MichaelSevakis
Revision r10 - 12 Nov 2010 - 21:12 - MichaelGiacomelli
Copyright by the contributing authors.