From 045274b2da982599cf987a59f6e10f4176f2f520 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 13 Sep 2026 16:12:53 +0000 Subject: [PATCH] 2026-09-13 16:12:52 Signed-off-by: lizzie --- .../adsp/apps/opus/opus_decoder.cpp | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/audio_core/adsp/apps/opus/opus_decoder.cpp b/src/audio_core/adsp/apps/opus/opus_decoder.cpp index 3bf215351e..50ef8ba0f9 100644 --- a/src/audio_core/adsp/apps/opus/opus_decoder.cpp +++ b/src/audio_core/adsp/apps/opus/opus_decoder.cpp @@ -96,10 +96,11 @@ public: if (avcodec_open2(avc, codec, nullptr) >= 0) { pkt = av_packet_alloc(); frame = av_frame_alloc(); + // opus fltp -> libopus s16 if (swr_alloc_set_opts2( &swr, &avc->ch_layout, AV_SAMPLE_FMT_S16, 48000, - &avc->ch_layout, (enum AVSampleFormat)frame->format, 48000, + &avc->ch_layout, AV_SAMPLE_FMT_FLTP, 48000, 0, nullptr) >= 0) { if (swr_init(swr) >= 0) { return ResultSuccess; @@ -132,46 +133,51 @@ public: Result Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, u64 input_data, u64 input_data_size) { out_sample_count = 0; + if (input_data_size == 0 || output_data_size == 0) + return ResultSuccess; if (avc) { - int rem_output_bytes = int(output_data_size); - while (rem_output_bytes > 0) { - int r = avcodec_receive_frame(avc, frame); - if (r == AVERROR(EAGAIN)) { + int r; + if ((r = av_new_packet(pkt, int(input_data_size))) >= 0) { + std::memcpy(pkt->data, reinterpret_cast(input_data), input_data_size); + if ((r = avcodec_send_packet(avc, pkt)) >= 0) { + int rem_output_bytes = int(output_data_size); av_frame_unref(frame); - av_packet_unref(pkt); - if ((r = av_new_packet(pkt, int(input_data_size))) < 0) - break; - std::memcpy(pkt->data, reinterpret_cast(input_data), input_data_size); - if ((r = avcodec_send_packet(avc, pkt)) < 0) - break; - } else if (r == AVERROR_EOF) { - av_frame_unref(frame); - break; - } else if (r >= 0) { - auto const input_bsize = av_samples_get_buffer_size(frame->linesize, frame->ch_layout.nb_channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 1); - if (frame->format == AV_SAMPLE_FMT_S16) { - // input_bsize == output_bsize - ASSERT(size_t(int(output_data_size) - rem_output_bytes + input_bsize) <= size_t(output_data_size)); - std::memcpy(reinterpret_cast(output_data + (int(output_data_size) - rem_output_bytes)), frame->data[0], size_t(input_bsize)); - } else { - int out_samples = int(av_rescale_rnd(swr_get_delay(swr, frame->sample_rate) + frame->nb_samples, frame->sample_rate, frame->sample_rate, AV_ROUND_UP)); - uint8_t *output = nullptr; - av_samples_alloc(&output, frame->linesize, frame->ch_layout.nb_channels, out_samples, AV_SAMPLE_FMT_S16, 0); - out_samples = swr_convert(swr, &output, out_samples, (const uint8_t **)frame->data, frame->nb_samples); - auto const output_bsize = av_samples_get_buffer_size(frame->linesize, frame->ch_layout.nb_channels, out_samples, AV_SAMPLE_FMT_S16, 1); - std::memcpy(reinterpret_cast(output_data + (int(output_data_size) - rem_output_bytes)), output, size_t(output_bsize)); - av_freep(&output); + while ((r = avcodec_receive_frame(avc, frame)) >= 0) { + auto const input_bsize = av_samples_get_buffer_size(frame->linesize, frame->ch_layout.nb_channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 1); + ASSERT(rem_output_bytes - input_bsize >= 0); + auto const dst_data = reinterpret_cast(output_data + (int(output_data_size) - rem_output_bytes)); + if (frame->format == AV_SAMPLE_FMT_S16) { + // input_bsize == output_bsize + ASSERT(size_t(int(output_data_size) - rem_output_bytes + input_bsize) <= size_t(output_data_size)); + std::memcpy(dst_data, frame->data[0], size_t(input_bsize)); + } else { + int out_samples = int(av_rescale_rnd(swr_get_delay(swr, frame->sample_rate) + frame->nb_samples, frame->sample_rate, frame->sample_rate, AV_ROUND_UP)); + uint8_t *output = nullptr; + av_samples_alloc(&output, frame->linesize, frame->ch_layout.nb_channels, out_samples, AV_SAMPLE_FMT_S16, 0); + out_samples = swr_convert(swr, &output, out_samples, (const uint8_t **)frame->data, frame->nb_samples); + auto const output_bsize = av_samples_get_buffer_size(frame->linesize, frame->ch_layout.nb_channels, out_samples, AV_SAMPLE_FMT_S16, 1); + std::memcpy(dst_data, output, size_t(output_bsize)); + av_freep(&output); + } + out_sample_count += frame->nb_samples; + rem_output_bytes -= input_bsize; + av_frame_unref(frame); } - out_sample_count += frame->nb_samples; - rem_output_bytes -= input_bsize; - av_frame_unref(frame); + if (r == AVERROR_EOF) { + LOG_WARNING(Audio_DSP, "eof"); + } else if (r < 0) { + LOG_ERROR(Audio_DSP, "{}", r); + } + ASSERT(rem_output_bytes == 0 && "remaining bytes!"); + av_packet_unref(pkt); + return ResultSuccess; } else { LOG_ERROR(Audio_DSP, "{}", r); - break; } + } else { + LOG_ERROR(Audio_DSP, "{}", r); } - ASSERT(rem_output_bytes == 0 && "remaining bytes!"); - return ResultSuccess; + av_packet_unref(pkt); } return Service::Audio::ResultLibOpusInvalidState; }