diff options
Diffstat (limited to 'lib/rbcodec/codecs/opus.c')
-rw-r--r-- | lib/rbcodec/codecs/opus.c | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/lib/rbcodec/codecs/opus.c b/lib/rbcodec/codecs/opus.c index 6f4a5644fb..d30a9cf714 100644 --- a/lib/rbcodec/codecs/opus.c +++ b/lib/rbcodec/codecs/opus.c | |||
@@ -216,7 +216,7 @@ static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og, | |||
216 | offset = ret; | 216 | offset = ret; |
217 | continue; | 217 | continue; |
218 | } | 218 | } |
219 | } else if (ret == -3) | 219 | } else if (ret == -3) |
220 | return(-3); | 220 | return(-3); |
221 | else if (ret<=0) | 221 | else if (ret<=0) |
222 | break; | 222 | break; |
@@ -235,8 +235,8 @@ static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og, | |||
235 | static int opus_seek_page_granule(int64_t pos, int64_t curpos, | 235 | static int opus_seek_page_granule(int64_t pos, int64_t curpos, |
236 | ogg_sync_state *oy, ogg_stream_state *os) | 236 | ogg_sync_state *oy, ogg_stream_state *os) |
237 | { | 237 | { |
238 | /* TODO: Someone may want to try to implement seek to packet, | 238 | /* TODO: Someone may want to try to implement seek to packet, |
239 | instead of just to page (should be more accurate, not be any | 239 | instead of just to page (should be more accurate, not be any |
240 | faster) */ | 240 | faster) */ |
241 | 241 | ||
242 | int64_t crofs; | 242 | int64_t crofs; |
@@ -253,7 +253,7 @@ static int opus_seek_page_granule(int64_t pos, int64_t curpos, | |||
253 | /* if seeking for more that 10sec, | 253 | /* if seeking for more that 10sec, |
254 | headersize is known & more than 10kb is played, | 254 | headersize is known & more than 10kb is played, |
255 | try to guess a place to seek from the number of | 255 | try to guess a place to seek from the number of |
256 | bytes playe for this position, this works best when | 256 | bytes playe for this position, this works best when |
257 | the bitrate is relativly constant. | 257 | the bitrate is relativly constant. |
258 | */ | 258 | */ |
259 | 259 | ||
@@ -324,7 +324,7 @@ static int opus_seek_page_granule(int64_t pos, int64_t curpos, | |||
324 | 324 | ||
325 | lastgranule = ogg_page_granulepos(&og); | 325 | lastgranule = ogg_page_granulepos(&og); |
326 | 326 | ||
327 | if ( ((lastgranule - (avgpagelen/4)) < pos && ( lastgranule + | 327 | if ( ((lastgranule - (avgpagelen/4)) < pos && ( lastgranule + |
328 | avgpagelen + (avgpagelen / 4)) > pos) || | 328 | avgpagelen + (avgpagelen / 4)) > pos) || |
329 | lastgranule > pos) { | 329 | lastgranule > pos) { |
330 | 330 | ||
@@ -360,15 +360,15 @@ enum codec_status codec_run(void) | |||
360 | int error = CODEC_ERROR; | 360 | int error = CODEC_ERROR; |
361 | long action; | 361 | long action; |
362 | intptr_t param; | 362 | intptr_t param; |
363 | ogg_sync_state oy; | 363 | ogg_sync_state *oy; |
364 | ogg_stream_state *os; | ||
364 | ogg_page og; | 365 | ogg_page og; |
365 | ogg_packet op; | 366 | ogg_packet op; |
366 | ogg_stream_state os; | ||
367 | int64_t page_granule = 0; | 367 | int64_t page_granule = 0; |
368 | int stream_init = -1; | 368 | int stream_init = -1; |
369 | int sample_rate = 48000; | 369 | int sample_rate = 48000; |
370 | OpusDecoder *st = NULL; | 370 | OpusDecoder *st = NULL; |
371 | OpusHeader header; | 371 | OpusHeader *header; |
372 | int ret; | 372 | int ret; |
373 | unsigned long strtoffset; | 373 | unsigned long strtoffset; |
374 | int skip = 0; | 374 | int skip = 0; |
@@ -387,10 +387,15 @@ enum codec_status codec_run(void) | |||
387 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); | 387 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); |
388 | #endif | 388 | #endif |
389 | 389 | ||
390 | /* Allocate some stuff off the heap */ | ||
391 | header = _ogg_malloc(sizeof(*header)); | ||
392 | os = _ogg_malloc(sizeof(*os)); | ||
393 | oy = _ogg_malloc(sizeof(*oy)); | ||
394 | |||
390 | /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */ | 395 | /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */ |
391 | ogg_sync_init(&oy); | 396 | ogg_sync_init(oy); |
392 | oy.storage = 64*1024; | 397 | oy->storage = 64*1024; |
393 | oy.data = _ogg_malloc(oy.storage); | 398 | oy->data = _ogg_malloc(oy->storage); |
394 | 399 | ||
395 | /* allocate output buffer */ | 400 | /* allocate output buffer */ |
396 | uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t)); | 401 | uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t)); |
@@ -407,13 +412,13 @@ enum codec_status codec_run(void) | |||
407 | if (action == CODEC_ACTION_SEEK_TIME) { | 412 | if (action == CODEC_ACTION_SEEK_TIME) { |
408 | if (st != NULL) { | 413 | if (st != NULL) { |
409 | /* calculate granule to seek to (including seek rewind) */ | 414 | /* calculate granule to seek to (including seek rewind) */ |
410 | seek_target = (48LL * param) + header.preskip; | 415 | seek_target = (48LL * param) + header->preskip; |
411 | skip = MIN(seek_target, SEEK_REWIND); | 416 | skip = MIN(seek_target, SEEK_REWIND); |
412 | seek_target -= skip; | 417 | seek_target -= skip; |
413 | 418 | ||
414 | LOGF("Opus seek page:%lld,%lld,%ld\n", (long long int)seek_target, | 419 | LOGF("Opus seek page:%lld,%lld,%ld\n", (long long int)seek_target, |
415 | (long long int)page_granule, (long)param); | 420 | (long long int)page_granule, (long)param); |
416 | opus_seek_page_granule(seek_target, page_granule, &oy, &os); | 421 | opus_seek_page_granule(seek_target, page_granule, oy, os); |
417 | /* reset the state to help ensure that subsequent packets won't | 422 | /* reset the state to help ensure that subsequent packets won't |
418 | use state set by unrelated packets processed before seek */ | 423 | use state set by unrelated packets processed before seek */ |
419 | opus_decoder_ctl(st, OPUS_RESET_STATE); | 424 | opus_decoder_ctl(st, OPUS_RESET_STATE); |
@@ -427,14 +432,14 @@ enum codec_status codec_run(void) | |||
427 | 432 | ||
428 | next_page: | 433 | next_page: |
429 | /*Get the ogg buffer for writing*/ | 434 | /*Get the ogg buffer for writing*/ |
430 | if (get_more_data(&oy) < 1) { | 435 | if (get_more_data(oy) < 1) { |
431 | goto done; | 436 | goto done; |
432 | } | 437 | } |
433 | 438 | ||
434 | /* Loop for all complete pages we got (most likely only one) */ | 439 | /* Loop for all complete pages we got (most likely only one) */ |
435 | while (ogg_sync_pageout(&oy, &og) == 1) { | 440 | while (ogg_sync_pageout(oy, &og) == 1) { |
436 | if (stream_init != 0) { | 441 | if (stream_init != 0) { |
437 | stream_init = ogg_stream_init(&os, ogg_page_serialno(&og)); | 442 | stream_init = ogg_stream_init(os, ogg_page_serialno(&og)); |
438 | if (stream_init != 0) { | 443 | if (stream_init != 0) { |
439 | LOGF("Stream init failed"); | 444 | LOGF("Stream init failed"); |
440 | goto done; | 445 | goto done; |
@@ -442,22 +447,22 @@ enum codec_status codec_run(void) | |||
442 | } | 447 | } |
443 | 448 | ||
444 | /* Add page to the bitstream */ | 449 | /* Add page to the bitstream */ |
445 | ogg_stream_pagein(&os, &og); | 450 | ogg_stream_pagein(os, &og); |
446 | 451 | ||
447 | page_granule = ogg_page_granulepos(&og); | 452 | page_granule = ogg_page_granulepos(&og); |
448 | granule_pos = page_granule; | 453 | granule_pos = page_granule; |
449 | 454 | ||
450 | while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) { | 455 | while ((ogg_stream_packetout(os, &op) == 1) && !op.e_o_s) { |
451 | if (op.packetno == 0){ | 456 | if (op.packetno == 0){ |
452 | /* identification header */ | 457 | /* identification header */ |
453 | 458 | ||
454 | if (opus_header_parse(op.packet, op.bytes, &header) == 0) { | 459 | if (opus_header_parse(op.packet, op.bytes, header) == 0) { |
455 | LOGF("Could not parse header"); | 460 | LOGF("Could not parse header"); |
456 | goto done; | 461 | goto done; |
457 | } | 462 | } |
458 | skip = header.preskip; | 463 | skip = header->preskip; |
459 | 464 | ||
460 | st = opus_decoder_create(sample_rate, header.channels, &ret); | 465 | st = opus_decoder_create(sample_rate, header->channels, &ret); |
461 | if (ret != OPUS_OK) { | 466 | if (ret != OPUS_OK) { |
462 | LOGF("opus_decoder_create failed %d", ret); | 467 | LOGF("opus_decoder_create failed %d", ret); |
463 | goto done; | 468 | goto done; |
@@ -466,11 +471,11 @@ enum codec_status codec_run(void) | |||
466 | 471 | ||
467 | codec_set_replaygain(ci->id3); | 472 | codec_set_replaygain(ci->id3); |
468 | 473 | ||
469 | opus_decoder_ctl(st, OPUS_SET_GAIN(header.gain)); | 474 | opus_decoder_ctl(st, OPUS_SET_GAIN(header->gain)); |
470 | 475 | ||
471 | ci->configure(DSP_SET_FREQUENCY, sample_rate); | 476 | ci->configure(DSP_SET_FREQUENCY, sample_rate); |
472 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | 477 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); |
473 | ci->configure(DSP_SET_STEREO_MODE, (header.channels == 2) ? | 478 | ci->configure(DSP_SET_STEREO_MODE, (header->channels == 2) ? |
474 | STEREO_INTERLEAVED : STEREO_MONO); | 479 | STEREO_INTERLEAVED : STEREO_MONO); |
475 | 480 | ||
476 | if (strtoffset) | 481 | if (strtoffset) |
@@ -479,7 +484,7 @@ enum codec_status codec_run(void) | |||
479 | action = CODEC_ACTION_SEEK_TIME; | 484 | action = CODEC_ACTION_SEEK_TIME; |
480 | goto process_action; | 485 | goto process_action; |
481 | } else { | 486 | } else { |
482 | /* seek buffer directly to the first audio packet to avoid | 487 | /* seek buffer directly to the first audio packet to avoid |
483 | allocating space for huge comment packets | 488 | allocating space for huge comment packets |
484 | (embedded Album Art) */ | 489 | (embedded Album Art) */ |
485 | if (seek_opus_tags()) | 490 | if (seek_opus_tags()) |
@@ -490,12 +495,12 @@ enum codec_status codec_run(void) | |||
490 | } | 495 | } |
491 | } | 496 | } |
492 | LOGF("sync reset"); | 497 | LOGF("sync reset"); |
493 | ogg_sync_reset(&oy); /* next page */ | 498 | ogg_sync_reset(oy); /* next page */ |
494 | break; | 499 | break; |
495 | } else { | 500 | } else { |
496 | /* report progress */ | 501 | /* report progress */ |
497 | ci->set_offset((size_t) ci->curpos); | 502 | ci->set_offset((size_t) ci->curpos); |
498 | ci->set_elapsed((granule_pos - header.preskip) / 48); | 503 | ci->set_elapsed((granule_pos - header->preskip) / 48); |
499 | 504 | ||
500 | /* Decode audio packets */ | 505 | /* Decode audio packets */ |
501 | ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0); | 506 | ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0); |
@@ -503,7 +508,7 @@ enum codec_status codec_run(void) | |||
503 | if (ret > skip) { | 508 | if (ret > skip) { |
504 | /* part of or entire output buffer is played */ | 509 | /* part of or entire output buffer is played */ |
505 | ret -= skip; | 510 | ret -= skip; |
506 | ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret); | 511 | ci->pcmbuf_insert(&output[skip * header->channels], NULL, ret); |
507 | skip = 0; | 512 | skip = 0; |
508 | } else { | 513 | } else { |
509 | if (ret < 0) { | 514 | if (ret < 0) { |