1
0
Fork 0
forked from len0rd/rockbox

Move encoder CPU boost control to the core. Allow CPU to sleep a bit when PCM buffer is empty and save some power. Codec API becomes incompatible so full updates! :)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15854 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2007-11-30 05:16:56 +00:00
parent b0dd9eb5bc
commit 5323fe996b
8 changed files with 20 additions and 165 deletions

View file

@ -131,7 +131,6 @@ struct codec_api ci = {
enc_set_parameters, enc_set_parameters,
enc_get_chunk, enc_get_chunk,
enc_finish_chunk, enc_finish_chunk,
enc_pcm_buf_near_empty,
enc_get_pcm_data, enc_get_pcm_data,
enc_unget_pcm_data, enc_unget_pcm_data,
@ -141,15 +140,6 @@ struct codec_api ci = {
(read_func)read, (read_func)read,
PREFIX(lseek), PREFIX(lseek),
(write_func)write, (write_func)write,
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#ifdef CPU_BOOST_LOGGING
cpu_boost_,
#else
cpu_boost,
#endif
#endif
round_value_to_list32, round_value_to_list32,
#endif #endif

View file

@ -80,12 +80,12 @@
#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define CODEC_API_VERSION 21 #define CODEC_API_VERSION 22
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define CODEC_MIN_API_VERSION 18 #define CODEC_MIN_API_VERSION 22
/* codec return codes */ /* codec return codes */
enum codec_status { enum codec_status {
@ -200,7 +200,6 @@ struct codec_api {
void (*enc_set_parameters)(struct enc_parameters *params); void (*enc_set_parameters)(struct enc_parameters *params);
struct enc_chunk_hdr * (*enc_get_chunk)(void); struct enc_chunk_hdr * (*enc_get_chunk)(void);
void (*enc_finish_chunk)(void); void (*enc_finish_chunk)(void);
int (*enc_pcm_buf_near_empty)(void);
unsigned char * (*enc_get_pcm_data)(size_t size); unsigned char * (*enc_get_pcm_data)(size_t size);
size_t (*enc_unget_pcm_data)(size_t size); size_t (*enc_unget_pcm_data)(size_t size);
@ -210,21 +209,10 @@ struct codec_api {
ssize_t (*read)(int fd, void* buf, size_t count); ssize_t (*read)(int fd, void* buf, size_t count);
off_t (*PREFIX(lseek))(int fd, off_t offset, int whence); off_t (*PREFIX(lseek))(int fd, off_t offset, int whence);
ssize_t (*write)(int fd, const void* buf, size_t count); ssize_t (*write)(int fd, const void* buf, size_t count);
/* Encoder codecs adjust CPU boost themselves */
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#ifdef CPU_BOOST_LOGGING
void (*cpu_boost_)(bool on_off,char*location,int line);
#else
void (*cpu_boost)(bool on_off);
#endif
#endif
int (*round_value_to_list32)(unsigned long value, int (*round_value_to_list32)(unsigned long value,
const unsigned long list[], const unsigned long list[],
int count, int count,
bool signd); bool signd);
#endif #endif
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time

View file

@ -304,9 +304,6 @@ static bool init_encoder(void)
ci->enc_set_parameters == NULL || ci->enc_set_parameters == NULL ||
ci->enc_get_chunk == NULL || ci->enc_get_chunk == NULL ||
ci->enc_finish_chunk == NULL || ci->enc_finish_chunk == NULL ||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->enc_pcm_buf_near_empty == NULL ||
#endif
ci->enc_get_pcm_data == NULL ) ci->enc_get_pcm_data == NULL )
return false; return false;
@ -334,10 +331,6 @@ static bool init_encoder(void)
/* main codec entry point */ /* main codec entry point */
enum codec_status codec_main(void) enum codec_status codec_main(void)
{ {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
bool cpu_boosted;
#endif
if (!init_encoder()) if (!init_encoder())
{ {
ci->enc_codec_loaded = -1; ci->enc_codec_loaded = -1;
@ -347,11 +340,6 @@ enum codec_status codec_main(void)
/* main application waits for this flag during encoder loading */ /* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = 1; ci->enc_codec_loaded = 1;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->cpu_boost(true);
cpu_boosted = true;
#endif
/* main encoding loop */ /* main encoding loop */
while(!ci->stop_encoder) while(!ci->stop_encoder)
{ {
@ -364,13 +352,6 @@ enum codec_status codec_main(void)
if (ci->stop_encoder) if (ci->stop_encoder)
break; break;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
#endif
chunk = ci->enc_get_chunk(); chunk = ci->enc_get_chunk();
chunk->enc_size = enc_size; chunk->enc_size = enc_size;
chunk->num_pcm = PCM_SAMP_PER_CHUNK; chunk->num_pcm = PCM_SAMP_PER_CHUNK;
@ -382,21 +363,9 @@ enum codec_status codec_main(void)
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
#endif
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
#endif
/* reset parameters to initial state */ /* reset parameters to initial state */
ci->enc_set_parameters(NULL); ci->enc_set_parameters(NULL);

View file

@ -2423,9 +2423,6 @@ static bool enc_init(void)
ci->enc_set_parameters == NULL || ci->enc_set_parameters == NULL ||
ci->enc_get_chunk == NULL || ci->enc_get_chunk == NULL ||
ci->enc_finish_chunk == NULL || ci->enc_finish_chunk == NULL ||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->enc_pcm_buf_near_empty == NULL ||
#endif
ci->enc_get_pcm_data == NULL || ci->enc_get_pcm_data == NULL ||
ci->enc_unget_pcm_data == NULL ) ci->enc_unget_pcm_data == NULL )
return false; return false;
@ -2461,10 +2458,6 @@ static bool enc_init(void)
enum codec_status codec_main(void) enum codec_status codec_main(void)
{ {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
bool cpu_boosted;
#endif
/* Generic codec initialisation */ /* Generic codec initialisation */
if (!enc_init()) if (!enc_init())
{ {
@ -2475,11 +2468,6 @@ enum codec_status codec_main(void)
/* main application waits for this flag during encoder loading */ /* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = 1; ci->enc_codec_loaded = 1;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->cpu_boost(true);
cpu_boosted = true;
#endif
/* main encoding loop */ /* main encoding loop */
while (!ci->stop_encoder) while (!ci->stop_encoder)
{ {
@ -2492,13 +2480,6 @@ enum codec_status codec_main(void)
if (ci->stop_encoder) if (ci->stop_encoder)
break; break;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
#endif
chunk = ci->enc_get_chunk(); chunk = ci->enc_get_chunk();
chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
@ -2515,21 +2496,9 @@ enum codec_status codec_main(void)
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted && ci->enc_pcm_buf_near_empty())
{
ci->cpu_boost(false);
cpu_boosted = false;
}
#endif
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
#endif
/* reset parameters to initial state */ /* reset parameters to initial state */
ci->enc_set_parameters(NULL); ci->enc_set_parameters(NULL);

View file

@ -291,9 +291,6 @@ static bool init_encoder(void)
ci->enc_set_parameters == NULL || ci->enc_set_parameters == NULL ||
ci->enc_get_chunk == NULL || ci->enc_get_chunk == NULL ||
ci->enc_finish_chunk == NULL || ci->enc_finish_chunk == NULL ||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->enc_pcm_buf_near_empty == NULL ||
#endif
ci->enc_get_pcm_data == NULL ) ci->enc_get_pcm_data == NULL )
return false; return false;
@ -321,10 +318,6 @@ static bool init_encoder(void)
/* main codec entry point */ /* main codec entry point */
enum codec_status codec_main(void) enum codec_status codec_main(void)
{ {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
bool cpu_boosted;
#endif
if (!init_encoder()) if (!init_encoder())
{ {
ci->enc_codec_loaded = -1; ci->enc_codec_loaded = -1;
@ -334,11 +327,6 @@ enum codec_status codec_main(void)
/* main application waits for this flag during encoder loading */ /* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = 1; ci->enc_codec_loaded = 1;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->cpu_boost(true);
cpu_boosted = true;
#endif
/* main encoding loop */ /* main encoding loop */
while(!ci->stop_encoder) while(!ci->stop_encoder)
{ {
@ -351,13 +339,6 @@ enum codec_status codec_main(void)
if (ci->stop_encoder) if (ci->stop_encoder)
break; break;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
#endif
chunk = ci->enc_get_chunk(); chunk = ci->enc_get_chunk();
chunk->enc_size = enc_size; chunk->enc_size = enc_size;
chunk->num_pcm = PCM_SAMP_PER_CHUNK; chunk->num_pcm = PCM_SAMP_PER_CHUNK;
@ -369,21 +350,9 @@ enum codec_status codec_main(void)
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
#endif
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
#endif
/* reset parameters to initial state */ /* reset parameters to initial state */
ci->enc_set_parameters(NULL); ci->enc_set_parameters(NULL);

View file

@ -343,9 +343,6 @@ static bool init_encoder(void)
ci->enc_set_parameters == NULL || ci->enc_set_parameters == NULL ||
ci->enc_get_chunk == NULL || ci->enc_get_chunk == NULL ||
ci->enc_finish_chunk == NULL || ci->enc_finish_chunk == NULL ||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->enc_pcm_buf_near_empty == NULL ||
#endif
ci->enc_get_pcm_data == NULL || ci->enc_get_pcm_data == NULL ||
ci->enc_unget_pcm_data == NULL ) ci->enc_unget_pcm_data == NULL )
return false; return false;
@ -386,10 +383,6 @@ static bool init_encoder(void)
enum codec_status codec_main(void) enum codec_status codec_main(void)
{ {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
bool cpu_boosted;
#endif
/* initialize params and config */ /* initialize params and config */
if (!init_encoder()) if (!init_encoder())
{ {
@ -400,11 +393,6 @@ enum codec_status codec_main(void)
/* main application waits for this flag during encoder loading */ /* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = 1; ci->enc_codec_loaded = 1;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
ci->cpu_boost(true);
cpu_boosted = true;
#endif
/* main encoding loop */ /* main encoding loop */
while(!ci->stop_encoder) while(!ci->stop_encoder)
{ {
@ -422,13 +410,6 @@ enum codec_status codec_main(void)
abort_chunk = true; abort_chunk = true;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
#endif
chunk = ci->enc_get_chunk(); chunk = ci->enc_get_chunk();
/* reset counts and pointer */ /* reset counts and pointer */
@ -472,21 +453,9 @@ enum codec_status codec_main(void)
} }
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
#endif
ci->yield(); ci->yield();
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
if (cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
#endif
/* reset parameters to initial state */ /* reset parameters to initial state */
ci->enc_set_parameters(NULL); ci->enc_set_parameters(NULL);

View file

@ -275,8 +275,6 @@ void enc_set_parameters(struct enc_parameters *params);
struct enc_chunk_hdr * enc_get_chunk(void); struct enc_chunk_hdr * enc_get_chunk(void);
/* releases the current chunk into the available chunks */ /* releases the current chunk into the available chunks */
void enc_finish_chunk(void); void enc_finish_chunk(void);
/* checks near empty state on pcm input buffer */
int enc_pcm_buf_near_empty(void);
#define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */ #define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */

View file

@ -108,17 +108,16 @@ static unsigned long pre_record_ticks; /* pre-record time in ticks */
3.encoder: enc_set_parameters(); set the encoder parameters 3.encoder: enc_set_parameters(); set the encoder parameters
4.encoder: enc_get_pcm_data(); get n bytes of unprocessed pcm data 4.encoder: enc_get_pcm_data(); get n bytes of unprocessed pcm data
5.encoder: enc_unget_pcm_data(); put n bytes of data back (optional) 5.encoder: enc_unget_pcm_data(); put n bytes of data back (optional)
6.encoder: enc_pcm_buf_near_empty(); if !0: reduce cpu_boost 6.encoder: enc_get_chunk(); get a ptr to next enc chunk
7.encoder: enc_get_chunk(); get a ptr to next enc chunk 7.encoder: <process enc chunk> compress and store data to enc chunk
8.encoder: <process enc chunk> compress and store data to enc chunk 8.encoder: enc_finish_chunk(); inform main about chunk processed and
9.encoder: enc_finish_chunk(); inform main about chunk processed and
is available to be written to a file. is available to be written to a file.
Encoder can place any number of chunks Encoder can place any number of chunks
of PCM data in a single output chunk of PCM data in a single output chunk
but must stay within its output chunk but must stay within its output chunk
size size
A.encoder: repeat 4. to 9. 9.encoder: repeat 4. to 8.
B.pcmrec: enc_events_callback(); called for certain events A.pcmrec: enc_events_callback(); called for certain events
(*) Optional step (*) Optional step
****************************************************************************/ ****************************************************************************/
@ -1541,6 +1540,7 @@ void enc_set_parameters(struct enc_parameters *params)
/* Encoder is terminating */ /* Encoder is terminating */
memset(&enc_config, 0, sizeof (enc_config)); memset(&enc_config, 0, sizeof (enc_config));
enc_sample_rate = 0; enc_sample_rate = 0;
cancel_cpu_boost(); /* Make sure no boost remains */
return; return;
} }
@ -1709,15 +1709,6 @@ void enc_finish_chunk(void)
} }
} /* enc_finish_chunk */ } /* enc_finish_chunk */
/* checks near empty state on pcm input buffer */
int enc_pcm_buf_near_empty(void)
{
/* less than 1sec raw data? => unboost encoder */
int wp = dma_wr_pos;
size_t avail = (wp - pcm_rd_pos) & PCM_CHUNK_MASK;
return avail < (sample_rate << 2) ? 1 : 0;
} /* enc_pcm_buf_near_empty */
/* passes a pointer to next chunk of unprocessed wav data */ /* passes a pointer to next chunk of unprocessed wav data */
/* TODO: this really should give the actual size returned */ /* TODO: this really should give the actual size returned */
unsigned char * enc_get_pcm_data(size_t size) unsigned char * enc_get_pcm_data(size_t size)
@ -1744,12 +1735,24 @@ unsigned char * enc_get_pcm_data(size_t size)
pcm_buffer, pcm_rd_pos); pcm_buffer, pcm_rd_pos);
} }
if (avail >= (sample_rate << 2))
{
/* Filling up - boost codec */
trigger_cpu_boost();
}
pcm_buffer_empty = false; pcm_buffer_empty = false;
return ptr; return ptr;
} }
/* not enough data available - encoder should idle */ /* not enough data available - encoder should idle */
pcm_buffer_empty = true; pcm_buffer_empty = true;
cancel_cpu_boost();
/* Sleep long enough to allow one frame on average */
sleep(0);
return NULL; return NULL;
} /* enc_get_pcm_data */ } /* enc_get_pcm_data */