diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-04-01 13:22:21 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-04-19 10:29:38 +1000 |
| commit | 7c6fd654f50e6665efa4226c6b927f9762734182 (patch) | |
| tree | 58ccb69068c550e9c2223c1b510cfa525690b731 /src/audio/audio_decoder.cpp | |
| parent | 3817ec0c77b8d44e54b35ea9f76e7bb4666c6c08 (diff) | |
| download | tangara-fw-7c6fd654f50e6665efa4226c6b927f9762734182.tar.gz | |
New pipeline building, still needs proper control
Diffstat (limited to 'src/audio/audio_decoder.cpp')
| -rw-r--r-- | src/audio/audio_decoder.cpp | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp index f8614478..ada1f8f7 100644 --- a/src/audio/audio_decoder.cpp +++ b/src/audio/audio_decoder.cpp @@ -26,22 +26,22 @@ static const char* kTag = "DEC"; AudioDecoder::AudioDecoder() : IAudioElement(), - stream_info_({}), - has_samples_to_send_(false), - needs_more_input_(true) {} + current_codec_(), + current_input_format_(), + current_output_format_(), + has_samples_to_send_(false) {} AudioDecoder::~AudioDecoder() {} auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info) -> bool { - if (!std::holds_alternative<StreamInfo::Encoded>(info.data)) { + if (!std::holds_alternative<StreamInfo::Encoded>(info.format)) { return false; } - const auto& encoded = std::get<StreamInfo::Encoded>(info.data); + const auto& encoded = std::get<StreamInfo::Encoded>(info.format); // Reuse the existing codec if we can. This will help with gapless playback, // since we can potentially just continue to decode as we were before, // without any setup overhead. - // TODO: use audio type from stream if (current_codec_ != nullptr && current_codec_->CanHandleType(encoded.type)) { current_codec_->ResetForNewStream(); @@ -60,43 +60,47 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info) -> bool { return true; } -auto AudioDecoder::Process(std::vector<Stream>* inputs, MutableStream* output) - -> void { +auto AudioDecoder::Process(const std::vector<InputStream>& inputs, + OutputStream* output) -> void { // We don't really expect multiple inputs, so just pick the first that // contains data. If none of them contain data, then we can still flush // pending samples. - auto input = - std::find_if(inputs->begin(), inputs->end(), - [](const Stream& s) { return s.data.size_bytes() > 0; }); - - if (input != inputs->end()) { - const StreamInfo* info = input->info; - if (!stream_info_ || *stream_info_ != *info) { - // The input stream has changed! Immediately throw everything away and - // start from scratch. - // TODO: special case gapless playback? needs thought. - stream_info_ = *info; - has_samples_to_send_ = false; - has_set_stream_info_ = false; - - ProcessStreamInfo(*info); - } + auto input = std::find_if( + inputs.begin(), inputs.end(), + [](const InputStream& s) { return s.data().size_bytes() > 0; }); + if (input == inputs.end()) { + input = inputs.begin(); + } + + const StreamInfo& info = input->info(); + if (!current_input_format_ || *current_input_format_ != info.format) { + // The input stream has changed! Immediately throw everything away and + // start from scratch. + current_input_format_ = info.format; + has_samples_to_send_ = false; - current_codec_->SetInput(input->data); + ProcessStreamInfo(info); } + current_codec_->SetInput(input->data()); + while (true) { if (has_samples_to_send_) { - if (!has_set_stream_info_) { - has_set_stream_info_ = true; + if (!current_output_format_) { auto format = current_codec_->GetOutputFormat(); - output->info->data.emplace<StreamInfo::Pcm>( - format.bits_per_sample, format.sample_rate_hz, format.num_channels); + current_output_format_ = StreamInfo::Pcm{ + .channels = format.num_channels, + .bits_per_sample = format.bits_per_sample, + .sample_rate = format.sample_rate_hz, + }; + } + + if (!output->prepare(*current_output_format_)) { + break; } - auto write_res = current_codec_->WriteOutputSamples( - output->data.subspan(output->info->bytes_in_stream)); - output->info->bytes_in_stream += write_res.first; + auto write_res = current_codec_->WriteOutputSamples(output->data()); + output->add(write_res.first); has_samples_to_send_ = !write_res.second; if (has_samples_to_send_) { @@ -106,26 +110,23 @@ auto AudioDecoder::Process(std::vector<Stream>* inputs, MutableStream* output) } } - if (input != inputs->end()) { - auto res = current_codec_->ProcessNextFrame(); - if (res.has_error()) { - // TODO(jacqueline): Handle errors. - return; - } - input->data = input->data.subspan(current_codec_->GetInputPosition()); + auto res = current_codec_->ProcessNextFrame(); + if (res.has_error()) { + // TODO(jacqueline): Handle errors. + return; + } - if (res.value()) { - // We're out of data in this buffer. Finish immediately; there's nothing - // to send. - break; - } else { - has_samples_to_send_ = true; - } - } else { - // No input; nothing to do. + if (res.value()) { + // We're out of useable data in this buffer. Finish immediately; there's + // nothing to send. + input->mark_incomplete(); break; + } else { + has_samples_to_send_ = true; } } + + input->consume(current_codec_->GetInputPosition()); } } // namespace audio |
