/*---------------------------------------------------------------------------*/ static void *decode_thread(struct thread_ctx_s *ctx) { while (ctx->decode_running) { size_t bytes, space, min_space; bool toend; bool ran = false; LOCK_S; bytes = _buf_used(ctx->streambuf); toend = (ctx->stream.state <= DISCONNECT); UNLOCK_S; LOCK_O; space = _buf_space(ctx->outputbuf); UNLOCK_O; LOCK_D; if (ctx->decode.state == DECODE_RUNNING && ctx->codec) { LOG_SDEBUG("streambuf bytes: %u outputbuf space: %u", bytes, space); IF_DIRECT( min_space = ctx->codec->min_space; ); IF_PROCESS( min_space = ctx->process.max_out_frames * BYTES_PER_FRAME; );
static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { size_t frames = frame->header.blocksize; unsigned bits_per_sample = frame->header.bits_per_sample; unsigned channels = frame->header.channels; FLAC__int32 *lptr = (FLAC__int32 *)buffer[0]; FLAC__int32 *rptr = (FLAC__int32 *)buffer[channels > 1 ? 1 : 0]; if (decode.new_stream) { LOCK_O; LOG_INFO("setting track_start"); output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.max_sample_rate); output.track_start = outputbuf->writep; if (output.fade_mode) _checkfade(true); decode.new_stream = false; UNLOCK_O; } LOCK_O_direct; while (frames > 0) { frames_t f; frames_t count; s32_t *optr; IF_DIRECT( optr = (s32_t *)outputbuf->writep; f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME; ); IF_PROCESS( optr = (s32_t *)process.inbuf; f = process.max_in_frames; );
static decode_state mpg_decode(void) { size_t bytes, space, size; int ret; u8_t *write_buf; LOCK_S; LOCK_O_direct; bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf)); IF_DIRECT( space = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)); write_buf = outputbuf->writep; );
static decode_state vorbis_decode(void) { static int channels; bool end; frames_t frames; int bytes, s, n; u8_t *write_buf; LOCK_S; LOCK_O_direct; end = (stream.state <= DISCONNECT); IF_DIRECT( frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME; );
static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { size_t frames = frame->header.blocksize; unsigned bits_per_sample = frame->header.bits_per_sample; unsigned channels = frame->header.channels; FLAC__int32 *lptr = (FLAC__int32 *)buffer[0]; FLAC__int32 *rptr = (FLAC__int32 *)buffer[channels > 1 ? 1 : 0]; if (decode.new_stream) { LOCK_O; LOG_INFO("setting track_start"); output.track_start = outputbuf->writep; decode.new_stream = false; #if DSD if (output.has_dop && bits_per_sample == 24 && is_flac_dop((u32_t *)lptr, (u32_t *)rptr, frames)) { LOG_INFO("file contains DOP"); output.next_dop = true; output.next_sample_rate = frame->header.sample_rate; output.fade = FADE_INACTIVE; } else { output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates); output.next_dop = false; if (output.fade_mode) _checkfade(true); } #else output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates); if (output.fade_mode) _checkfade(true); #endif UNLOCK_O; } LOCK_O_direct; while (frames > 0) { frames_t f; frames_t count; s32_t *optr; IF_DIRECT( optr = (s32_t *)outputbuf->writep; f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME; ); IF_PROCESS( optr = (s32_t *)process.inbuf; f = process.max_in_frames; );
static void *decode_thread() { while (running) { size_t bytes, space; bool toend; bool ran = false; LOCK_S; bytes = _buf_used(streambuf); toend = (stream.state <= DISCONNECT); UNLOCK_S; LOCK_O; space = _buf_space(outputbuf); UNLOCK_O; LOCK_D; if (decode.state == DECODE_RUNNING && codec) { LOG_SDEBUG("streambuf bytes: %u outputbuf space: %u", bytes, space); if (space > codec->min_space && (bytes > codec->min_read_bytes || toend)) { decode.state = codec->decode(); if (decode.state != DECODE_RUNNING) { LOG_INFO("decode %s", decode.state == DECODE_COMPLETE ? "complete" : "error"); LOCK_O; if (output.fade_mode) _checkfade(false); UNLOCK_O; wake_controller(); } ran = true; } } UNLOCK_D; if (!ran) { usleep(100000); } } return 0; }
static decode_state mpg_decode(void) { size_t bytes, space, size; int ret; LOCK_S; LOCK_O; bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf)); space = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)); bytes = min(bytes, READ_SIZE); space = min(space, WRITE_SIZE); if (stream.state <= DISCONNECT && bytes == 0) { UNLOCK_O; UNLOCK_S; return DECODE_COMPLETE; } if (m->use16bit) { space = (space / BYTES_PER_FRAME) * 4; } ret = m->mpg123_decode(m->h, streambuf->readp, bytes, outputbuf->writep, space, &size); if (ret == MPG123_NEW_FORMAT) { if (decode.new_stream) { long rate; int channels, enc; m->mpg123_getformat(m->h, &rate, &channels, &enc); LOG_INFO("setting track_start"); output.next_sample_rate = rate; output.track_start = outputbuf->writep; if (output.fade_mode) _checkfade(true); decode.new_stream = false; } else { LOG_WARN("format change mid stream - not supported"); } } // expand 16bit output to 32bit samples if (m->use16bit) { s16_t *iptr; s32_t *optr; size_t count = size / 2; size = count * 4; iptr = (s16_t *)outputbuf->writep + count; optr = (s32_t *)outputbuf->writep + count; while (count--) { *--optr = *--iptr << 16; } } _buf_inc_readp(streambuf, bytes); _buf_inc_writep(outputbuf, size); UNLOCK_O; UNLOCK_S; LOG_SDEBUG("write %u frames", size / BYTES_PER_FRAME); if (ret == MPG123_DONE) { LOG_INFO("stream complete"); return DECODE_COMPLETE; } if (ret == MPG123_ERR) { LOG_WARN("Error"); return DECODE_COMPLETE; } // OK and NEED_MORE keep running return DECODE_RUNNING; }