summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/wavpack_enc.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2013-07-04 05:27:29 -0400
committerMichael Sevakis <jethead71@rockbox.org>2013-07-09 06:28:33 -0400
commit95bc93194e18d1f5c7bf49683bcbe1b6ecc2a073 (patch)
tree58e0c3b1063191ebf7246b8361ad484ef9aaaaf5 /lib/rbcodec/codecs/wavpack_enc.c
parent08e466ff92a367bc54b0cf13585ca0b5d94ddd6c (diff)
downloadrockbox-95bc93194e18d1f5c7bf49683bcbe1b6ecc2a073.tar.gz
rockbox-95bc93194e18d1f5c7bf49683bcbe1b6ecc2a073.zip
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
Diffstat (limited to 'lib/rbcodec/codecs/wavpack_enc.c')
-rw-r--r--lib/rbcodec/codecs/wavpack_enc.c125
1 files changed, 116 insertions, 9 deletions
diff --git a/lib/rbcodec/codecs/wavpack_enc.c b/lib/rbcodec/codecs/wavpack_enc.c
index 864012b4cd..ffb090f6ec 100644
--- a/lib/rbcodec/codecs/wavpack_enc.c
+++ b/lib/rbcodec/codecs/wavpack_enc.c
@@ -25,6 +25,10 @@
25 25
26CODEC_ENC_HEADER 26CODEC_ENC_HEADER
27 27
28#if NUM_CORES > 1
29#define WAVPACK_ENC_COP
30#endif
31
28/** Types **/ 32/** Types **/
29typedef struct 33typedef struct
30{ 34{
@@ -74,13 +78,24 @@ struct wvpk_chunk_data
74/** Data **/ 78/** Data **/
75static int32_t input_buffer[PCM_SAMP_PER_CHUNK*2] IBSS_ATTR; 79static int32_t input_buffer[PCM_SAMP_PER_CHUNK*2] IBSS_ATTR;
76 80
81#ifdef WAVPACK_ENC_COP
82#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
83/* Not enough for IRAM */
84static uint8_t output_buffer[PCM_SAMP_PER_CHUNK*PCM_DEPTH_BYTES*2*110/100]
85 SHAREDBSS_ATTR MEM_ALIGN_ATTR;
86#else
87static uint8_t output_buffer[PCM_SAMP_PER_CHUNK*PCM_DEPTH_BYTES*2*110/100]
88 IBSS_ATTR MEM_ALIGN_ATTR;
89#endif
90#endif /* WAVPACK_ENC_COP */
91
77static WavpackConfig config IBSS_ATTR; 92static WavpackConfig config IBSS_ATTR;
78static WavpackContext *wpc; 93static WavpackContext *wpc IBSS_ATTR;
79static uint32_t sample_rate; 94static uint32_t sample_rate IBSS_ATTR;
80static int num_channels; 95static int num_channels IBSS_ATTR;
81static uint32_t total_samples; 96static uint32_t total_samples IBSS_ATTR;
82static size_t out_reqsize; 97static size_t out_reqsize IBSS_ATTR;
83static size_t frame_size; 98static size_t frame_size IBSS_ATTR;
84 99
85static const WavpackMetadataHeader wvpk_mdh = 100static const WavpackMetadataHeader wvpk_mdh =
86{ 101{
@@ -230,6 +245,89 @@ static int on_stream_end(void)
230 return 0; 245 return 0;
231} 246}
232 247
248static inline uint32_t encode_block_(uint8_t *outbuf)
249{
250 if (WavpackStartBlock(wpc, outbuf, outbuf + out_reqsize) &&
251 WavpackPackSamples(wpc, input_buffer, PCM_SAMP_PER_CHUNK))
252 return WavpackFinishBlock(wpc);
253
254 return 0;
255}
256
257#ifdef WAVPACK_ENC_COP
258/* This is to relieve CPU of encoder load since it has other significant tasks
259 to perform when recording. It is not written to provide parallelism within
260 the codec. */
261static const char enc_thread_name[] = { "Wavpack enc" };
262static bool quit IBSS_ATTR;
263static uint32_t out_size IBSS_ATTR;
264static struct semaphore enc_sema IBSS_ATTR;
265static struct semaphore cod_sema IBSS_ATTR;
266static unsigned int enc_thread_id;
267
268static void ICODE_ATTR enc_thread(void)
269{
270 while (1)
271 {
272 ci->semaphore_wait(&enc_sema, TIMEOUT_BLOCK);
273
274 if (quit)
275 break;
276
277 out_size = encode_block_(output_buffer);
278
279 ci->semaphore_release(&cod_sema);
280 }
281}
282
283static inline bool enc_thread_init(void *stack, size_t stack_size)
284{
285 quit = false;
286 ci->semaphore_init(&enc_sema, 1, 0);
287 ci->semaphore_init(&cod_sema, 1, 0);
288
289 enc_thread_id = ci->create_thread(enc_thread, stack, stack_size,
290 0, enc_thread_name
291 IF_PRIO(, PRIORITY_PLAYBACK)
292 IF_COP(, COP));
293
294 return enc_thread_id != 0;
295}
296
297static inline void enc_thread_stop(void)
298{
299 quit = true;
300 ci->semaphore_release(&enc_sema);
301 ci->thread_wait(enc_thread_id);
302}
303
304static inline uint32_t encode_block(uint8_t *outbuf)
305{
306 ci->semaphore_release(&enc_sema);
307 ci->semaphore_wait(&cod_sema, TIMEOUT_BLOCK);
308 ci->memcpy(outbuf, output_buffer, out_size);
309 return out_size;
310}
311
312#else /* !WAVPACK_ENC_COP */
313
314static inline uint32_t encode_block(uint8_t *outbuf)
315{
316 return encode_block_(outbuf);
317}
318
319static inline bool enc_thread_init(void *stack, size_t stack_size)
320{
321 return true;
322 (void)stack; (void)stack_size;
323}
324
325static inline void enc_thread_stop(void)
326{
327}
328
329#endif /* WAVPACK_ENC_COP */
330
233/* this is the codec entry point */ 331/* this is the codec entry point */
234enum codec_status codec_main(enum codec_entry_call_reason reason) 332enum codec_status codec_main(enum codec_entry_call_reason reason)
235{ 333{
@@ -242,6 +340,13 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
242/* this is called for each file to process */ 340/* this is called for each file to process */
243enum codec_status codec_run(void) 341enum codec_status codec_run(void)
244{ 342{
343 /* Encoder thread stack goes on our stack - leave 4k for us
344 Will be optimized away when single-threaded */
345 uint32_t enc_stack[(DEFAULT_STACK_SIZE+0x1000) / sizeof(uint32_t)];
346
347 if (!enc_thread_init(enc_stack, sizeof (enc_stack)))
348 return CODEC_ERROR;
349
245 enum { GETBUF_ENC, GETBUF_PCM } getbuf = GETBUF_ENC; 350 enum { GETBUF_ENC, GETBUF_PCM } getbuf = GETBUF_ENC;
246 struct enc_chunk_data *data = NULL; 351 struct enc_chunk_data *data = NULL;
247 352
@@ -269,11 +374,12 @@ enum codec_status codec_run(void)
269 374
270 input_buffer_to_int32(frame_size); 375 input_buffer_to_int32(frame_size);
271 376
272 if (WavpackStartBlock(wpc, data->data, data->data + out_reqsize) && 377 uint32_t size = encode_block(data->data);
273 WavpackPackSamples(wpc, input_buffer, PCM_SAMP_PER_CHUNK)) 378
379 if (size)
274 { 380 {
275 /* finish the chunk and store chunk size info */ 381 /* finish the chunk and store chunk size info */
276 data->hdr.size = WavpackFinishBlock(wpc); 382 data->hdr.size = size;
277 data->pcm_count = PCM_SAMP_PER_CHUNK; 383 data->pcm_count = PCM_SAMP_PER_CHUNK;
278 } 384 }
279 else 385 else
@@ -285,6 +391,7 @@ enum codec_status codec_run(void)
285 ci->enc_encbuf_finish_buffer(); 391 ci->enc_encbuf_finish_buffer();
286 } 392 }
287 393
394 enc_thread_stop();
288 return CODEC_OK; 395 return CODEC_OK;
289} 396}
290 397