LibMedia: Set the AVCodecContext's sample rate and channel layout

This is required in order for our audio block output function to create
a sample specification for WAV files.
This commit is contained in:
Zaggy1024 2025-12-15 17:03:19 -06:00 committed by Gregory Bertilson
parent b4ca17fd29
commit fa3cda8e4a
3 changed files with 15 additions and 3 deletions

View file

@ -12,7 +12,7 @@
namespace Media::FFmpeg {
DecoderErrorOr<NonnullOwnPtr<FFmpegAudioDecoder>> FFmpegAudioDecoder::try_create(CodecID codec_id, ReadonlyBytes codec_initialization_data)
DecoderErrorOr<NonnullOwnPtr<FFmpegAudioDecoder>> FFmpegAudioDecoder::try_create(CodecID codec_id, Audio::SampleSpecification const& sample_specification, ReadonlyBytes codec_initialization_data)
{
AVCodecContext* codec_context = nullptr;
AVPacket* packet = nullptr;
@ -37,6 +37,17 @@ DecoderErrorOr<NonnullOwnPtr<FFmpegAudioDecoder>> FFmpegAudioDecoder::try_create
codec_context->time_base = { 1, 1'000'000 };
codec_context->thread_count = static_cast<int>(min(Core::System::hardware_concurrency(), 4));
if (sample_specification.sample_rate() > NumericLimits<int>::max())
return DecoderError::with_description(DecoderErrorCategory::Corrupted, "Sample rate is too large"sv);
codec_context->sample_rate = static_cast<int>(sample_specification.sample_rate());
if (sample_specification.channel_map().is_valid()) {
auto channel_layout_result = channel_map_to_av_channel_layout(sample_specification.channel_map());
if (channel_layout_result.is_error())
return DecoderError::format(DecoderErrorCategory::Invalid, channel_layout_result.error().string_literal());
codec_context->ch_layout = channel_layout_result.release_value();
}
if (!codec_initialization_data.is_empty()) {
if (codec_initialization_data.size() > NumericLimits<int>::max())
return DecoderError::corrupted("Codec initialization data is too large"sv);

View file

@ -15,7 +15,7 @@ namespace Media::FFmpeg {
class MEDIA_API FFmpegAudioDecoder final : public AudioDecoder {
public:
static DecoderErrorOr<NonnullOwnPtr<FFmpegAudioDecoder>> try_create(CodecID, ReadonlyBytes codec_initialization_data);
static DecoderErrorOr<NonnullOwnPtr<FFmpegAudioDecoder>> try_create(CodecID, Audio::SampleSpecification const&, ReadonlyBytes codec_initialization_data);
FFmpegAudioDecoder(AVCodecContext* codec_context, AVPacket* packet, AVFrame* frame);
virtual ~FFmpegAudioDecoder() override;

View file

@ -21,8 +21,9 @@ namespace Media {
DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> AudioDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, Track const& track)
{
auto codec_id = TRY(demuxer->get_codec_id_for_track(track));
auto const& sample_specification = track.audio_data().sample_specification;
auto codec_initialization_data = TRY(demuxer->get_codec_initialization_data_for_track(track));
auto decoder = DECODER_TRY_ALLOC(FFmpeg::FFmpegAudioDecoder::try_create(codec_id, codec_initialization_data));
auto decoder = DECODER_TRY_ALLOC(FFmpeg::FFmpegAudioDecoder::try_create(codec_id, sample_specification, codec_initialization_data));
auto converter = DECODER_TRY_ALLOC(FFmpeg::FFmpegAudioConverter::try_create());
auto thread_data = DECODER_TRY_ALLOC(try_make_ref_counted<AudioDataProvider::ThreadData>(main_thread_event_loop, demuxer, track, move(decoder), move(converter)));