forked from len0rd/rockbox
Multithread compressing encoders on multicore targets.
For mp3_enc, split encoding duties between COP and CPU. For wavpack_enc, simply run the encoding on COP (splitting that one needs more consideration) which keeps the it and the UI from running on the same core. As a result, at least they are now useable on PP at "normal" sample rates. mp3_enc in all this gets an extensive renovation and some optimizations for speed, to reduce IRAM requirements and remove unneeded stuff. Change-Id: I215578dbe36f14e516b05a5ca70880eb01ca0ec2
This commit is contained in:
parent
08e466ff92
commit
95bc93194e
2 changed files with 2272 additions and 1776 deletions
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
CODEC_ENC_HEADER
|
CODEC_ENC_HEADER
|
||||||
|
|
||||||
|
#if NUM_CORES > 1
|
||||||
|
#define WAVPACK_ENC_COP
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Types **/
|
/** Types **/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -74,13 +78,24 @@ struct wvpk_chunk_data
|
||||||
/** Data **/
|
/** Data **/
|
||||||
static int32_t input_buffer[PCM_SAMP_PER_CHUNK*2] IBSS_ATTR;
|
static int32_t input_buffer[PCM_SAMP_PER_CHUNK*2] IBSS_ATTR;
|
||||||
|
|
||||||
|
#ifdef WAVPACK_ENC_COP
|
||||||
|
#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
|
||||||
|
/* Not enough for IRAM */
|
||||||
|
static uint8_t output_buffer[PCM_SAMP_PER_CHUNK*PCM_DEPTH_BYTES*2*110/100]
|
||||||
|
SHAREDBSS_ATTR MEM_ALIGN_ATTR;
|
||||||
|
#else
|
||||||
|
static uint8_t output_buffer[PCM_SAMP_PER_CHUNK*PCM_DEPTH_BYTES*2*110/100]
|
||||||
|
IBSS_ATTR MEM_ALIGN_ATTR;
|
||||||
|
#endif
|
||||||
|
#endif /* WAVPACK_ENC_COP */
|
||||||
|
|
||||||
static WavpackConfig config IBSS_ATTR;
|
static WavpackConfig config IBSS_ATTR;
|
||||||
static WavpackContext *wpc;
|
static WavpackContext *wpc IBSS_ATTR;
|
||||||
static uint32_t sample_rate;
|
static uint32_t sample_rate IBSS_ATTR;
|
||||||
static int num_channels;
|
static int num_channels IBSS_ATTR;
|
||||||
static uint32_t total_samples;
|
static uint32_t total_samples IBSS_ATTR;
|
||||||
static size_t out_reqsize;
|
static size_t out_reqsize IBSS_ATTR;
|
||||||
static size_t frame_size;
|
static size_t frame_size IBSS_ATTR;
|
||||||
|
|
||||||
static const WavpackMetadataHeader wvpk_mdh =
|
static const WavpackMetadataHeader wvpk_mdh =
|
||||||
{
|
{
|
||||||
|
@ -230,6 +245,89 @@ static int on_stream_end(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t encode_block_(uint8_t *outbuf)
|
||||||
|
{
|
||||||
|
if (WavpackStartBlock(wpc, outbuf, outbuf + out_reqsize) &&
|
||||||
|
WavpackPackSamples(wpc, input_buffer, PCM_SAMP_PER_CHUNK))
|
||||||
|
return WavpackFinishBlock(wpc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WAVPACK_ENC_COP
|
||||||
|
/* This is to relieve CPU of encoder load since it has other significant tasks
|
||||||
|
to perform when recording. It is not written to provide parallelism within
|
||||||
|
the codec. */
|
||||||
|
static const char enc_thread_name[] = { "Wavpack enc" };
|
||||||
|
static bool quit IBSS_ATTR;
|
||||||
|
static uint32_t out_size IBSS_ATTR;
|
||||||
|
static struct semaphore enc_sema IBSS_ATTR;
|
||||||
|
static struct semaphore cod_sema IBSS_ATTR;
|
||||||
|
static unsigned int enc_thread_id;
|
||||||
|
|
||||||
|
static void ICODE_ATTR enc_thread(void)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ci->semaphore_wait(&enc_sema, TIMEOUT_BLOCK);
|
||||||
|
|
||||||
|
if (quit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
out_size = encode_block_(output_buffer);
|
||||||
|
|
||||||
|
ci->semaphore_release(&cod_sema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool enc_thread_init(void *stack, size_t stack_size)
|
||||||
|
{
|
||||||
|
quit = false;
|
||||||
|
ci->semaphore_init(&enc_sema, 1, 0);
|
||||||
|
ci->semaphore_init(&cod_sema, 1, 0);
|
||||||
|
|
||||||
|
enc_thread_id = ci->create_thread(enc_thread, stack, stack_size,
|
||||||
|
0, enc_thread_name
|
||||||
|
IF_PRIO(, PRIORITY_PLAYBACK)
|
||||||
|
IF_COP(, COP));
|
||||||
|
|
||||||
|
return enc_thread_id != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void enc_thread_stop(void)
|
||||||
|
{
|
||||||
|
quit = true;
|
||||||
|
ci->semaphore_release(&enc_sema);
|
||||||
|
ci->thread_wait(enc_thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t encode_block(uint8_t *outbuf)
|
||||||
|
{
|
||||||
|
ci->semaphore_release(&enc_sema);
|
||||||
|
ci->semaphore_wait(&cod_sema, TIMEOUT_BLOCK);
|
||||||
|
ci->memcpy(outbuf, output_buffer, out_size);
|
||||||
|
return out_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !WAVPACK_ENC_COP */
|
||||||
|
|
||||||
|
static inline uint32_t encode_block(uint8_t *outbuf)
|
||||||
|
{
|
||||||
|
return encode_block_(outbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool enc_thread_init(void *stack, size_t stack_size)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
(void)stack; (void)stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void enc_thread_stop(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WAVPACK_ENC_COP */
|
||||||
|
|
||||||
/* this is the codec entry point */
|
/* this is the codec entry point */
|
||||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||||
{
|
{
|
||||||
|
@ -242,6 +340,13 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||||
/* this is called for each file to process */
|
/* this is called for each file to process */
|
||||||
enum codec_status codec_run(void)
|
enum codec_status codec_run(void)
|
||||||
{
|
{
|
||||||
|
/* Encoder thread stack goes on our stack - leave 4k for us
|
||||||
|
Will be optimized away when single-threaded */
|
||||||
|
uint32_t enc_stack[(DEFAULT_STACK_SIZE+0x1000) / sizeof(uint32_t)];
|
||||||
|
|
||||||
|
if (!enc_thread_init(enc_stack, sizeof (enc_stack)))
|
||||||
|
return CODEC_ERROR;
|
||||||
|
|
||||||
enum { GETBUF_ENC, GETBUF_PCM } getbuf = GETBUF_ENC;
|
enum { GETBUF_ENC, GETBUF_PCM } getbuf = GETBUF_ENC;
|
||||||
struct enc_chunk_data *data = NULL;
|
struct enc_chunk_data *data = NULL;
|
||||||
|
|
||||||
|
@ -269,11 +374,12 @@ enum codec_status codec_run(void)
|
||||||
|
|
||||||
input_buffer_to_int32(frame_size);
|
input_buffer_to_int32(frame_size);
|
||||||
|
|
||||||
if (WavpackStartBlock(wpc, data->data, data->data + out_reqsize) &&
|
uint32_t size = encode_block(data->data);
|
||||||
WavpackPackSamples(wpc, input_buffer, PCM_SAMP_PER_CHUNK))
|
|
||||||
|
if (size)
|
||||||
{
|
{
|
||||||
/* finish the chunk and store chunk size info */
|
/* finish the chunk and store chunk size info */
|
||||||
data->hdr.size = WavpackFinishBlock(wpc);
|
data->hdr.size = size;
|
||||||
data->pcm_count = PCM_SAMP_PER_CHUNK;
|
data->pcm_count = PCM_SAMP_PER_CHUNK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -285,6 +391,7 @@ enum codec_status codec_run(void)
|
||||||
ci->enc_encbuf_finish_buffer();
|
ci->enc_encbuf_finish_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enc_thread_stop();
|
||||||
return CODEC_OK;
|
return CODEC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue