mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-30 07:21:12 +00:00
Audio resampling fixes
- Don't try to use float audio or extended channel layouts if the hardware does not support them - Add channel layout resampling support to ffmpeg_decoder
This commit is contained in:
parent
dbe30e31b9
commit
55c9c0a266
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "al.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifndef HAVE_LIBSWRESAMPLE
|
#ifndef HAVE_LIBSWRESAMPLE
|
||||||
// FIXME: remove this section once libswresample is packaged for Debian
|
// FIXME: remove this section once libswresample is packaged for Debian
|
||||||
@ -112,7 +114,7 @@ bool FFmpeg_Decoder::getAVAudioData()
|
|||||||
if(!mDataBuf || mDataBufLen < mFrame->nb_samples)
|
if(!mDataBuf || mDataBufLen < mFrame->nb_samples)
|
||||||
{
|
{
|
||||||
av_freep(&mDataBuf);
|
av_freep(&mDataBuf);
|
||||||
if(av_samples_alloc(&mDataBuf, NULL, (*mStream)->codec->channels,
|
if(av_samples_alloc(&mDataBuf, NULL, av_get_channel_layout_nb_channels(mOutputChannelLayout),
|
||||||
mFrame->nb_samples, mOutputSampleFormat, 0) < 0)
|
mFrame->nb_samples, mOutputSampleFormat, 0) < 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@ -147,7 +149,7 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length)
|
|||||||
if(!getAVAudioData())
|
if(!getAVAudioData())
|
||||||
break;
|
break;
|
||||||
mFramePos = 0;
|
mFramePos = 0;
|
||||||
mFrameSize = mFrame->nb_samples * (*mStream)->codec->channels *
|
mFrameSize = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
|
||||||
av_get_bytes_per_sample(mOutputSampleFormat);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,47 +287,32 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
if(!mStream)
|
if(!mStream)
|
||||||
fail("No audio stream info");
|
fail("No audio stream info");
|
||||||
|
|
||||||
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8)
|
if(((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
||||||
*type = SampleType_UInt8;
|
&& alIsExtensionPresent("AL_EXT_FLOAT32"))
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16)
|
mOutputSampleFormat = AV_SAMPLE_FMT_FLT;
|
||||||
*type = SampleType_Int16;
|
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT)
|
|
||||||
*type = SampleType_Float32;
|
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
|
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
|
||||||
*type = SampleType_UInt8;
|
mOutputSampleFormat = AV_SAMPLE_FMT_U8;
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P)
|
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P)
|
||||||
*type = SampleType_Int16;
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
|
||||||
*type = SampleType_Float32;
|
|
||||||
else
|
else
|
||||||
fail(std::string("Unsupported sample format: ")+
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
av_get_sample_fmt_name((*mStream)->codec->sample_fmt));
|
|
||||||
|
if(mOutputSampleFormat == AV_SAMPLE_FMT_U8)
|
||||||
|
*type = SampleType_UInt8;
|
||||||
|
else if(mOutputSampleFormat == AV_SAMPLE_FMT_S16)
|
||||||
|
*type = SampleType_Int16;
|
||||||
|
else if(mOutputSampleFormat == AV_SAMPLE_FMT_FLT)
|
||||||
|
*type = SampleType_Float32;
|
||||||
|
|
||||||
int64_t ch_layout = (*mStream)->codec->channel_layout;
|
int64_t ch_layout = (*mStream)->codec->channel_layout;
|
||||||
|
|
||||||
if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_MONO)
|
if(ch_layout == 0)
|
||||||
*chans = ChannelConfig_Mono;
|
|
||||||
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_STEREO)
|
|
||||||
*chans = ChannelConfig_Stereo;
|
|
||||||
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_QUAD)
|
|
||||||
*chans = ChannelConfig_Quad;
|
|
||||||
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_5POINT1)
|
|
||||||
*chans = ChannelConfig_5point1;
|
|
||||||
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_7POINT1)
|
|
||||||
*chans = ChannelConfig_7point1;
|
|
||||||
else if((*mStream)->codec->channel_layout == 0)
|
|
||||||
{
|
{
|
||||||
/* Unknown channel layout. Try to guess. */
|
/* Unknown channel layout. Try to guess. */
|
||||||
if((*mStream)->codec->channels == 1)
|
if((*mStream)->codec->channels == 1)
|
||||||
{
|
|
||||||
*chans = ChannelConfig_Mono;
|
|
||||||
ch_layout = AV_CH_LAYOUT_MONO;
|
ch_layout = AV_CH_LAYOUT_MONO;
|
||||||
}
|
|
||||||
else if((*mStream)->codec->channels == 2)
|
else if((*mStream)->codec->channels == 2)
|
||||||
{
|
|
||||||
*chans = ChannelConfig_Stereo;
|
|
||||||
ch_layout = AV_CH_LAYOUT_STEREO;
|
ch_layout = AV_CH_LAYOUT_STEREO;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream sstr("Unsupported raw channel count: ");
|
std::stringstream sstr("Unsupported raw channel count: ");
|
||||||
@ -333,6 +320,25 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
fail(sstr.str());
|
fail(sstr.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mOutputChannelLayout = ch_layout;
|
||||||
|
if ((ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1
|
||||||
|
|| ch_layout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
|
mOutputChannelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
|
else if (ch_layout != AV_CH_LAYOUT_MONO
|
||||||
|
&& ch_layout != AV_CH_LAYOUT_STEREO)
|
||||||
|
mOutputChannelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
|
|
||||||
|
if(mOutputChannelLayout == AV_CH_LAYOUT_MONO)
|
||||||
|
*chans = ChannelConfig_Mono;
|
||||||
|
else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO)
|
||||||
|
*chans = ChannelConfig_Stereo;
|
||||||
|
else if(mOutputChannelLayout == AV_CH_LAYOUT_QUAD)
|
||||||
|
*chans = ChannelConfig_Quad;
|
||||||
|
else if(mOutputChannelLayout == AV_CH_LAYOUT_5POINT1)
|
||||||
|
*chans = ChannelConfig_5point1;
|
||||||
|
else if(mOutputChannelLayout == AV_CH_LAYOUT_7POINT1)
|
||||||
|
*chans = ChannelConfig_7point1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char str[1024];
|
char str[1024];
|
||||||
@ -343,17 +349,11 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
|
|
||||||
*samplerate = (*mStream)->codec->sample_rate;
|
*samplerate = (*mStream)->codec->sample_rate;
|
||||||
|
|
||||||
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
|
if(mOutputSampleFormat != (*mStream)->codec->sample_fmt
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_U8;
|
|| mOutputChannelLayout != ch_layout)
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P)
|
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_FLT;
|
|
||||||
|
|
||||||
if(mOutputSampleFormat != AV_SAMPLE_FMT_NONE)
|
|
||||||
{
|
{
|
||||||
mSwr = swr_alloc_set_opts(mSwr, // SwrContext
|
mSwr = swr_alloc_set_opts(mSwr, // SwrContext
|
||||||
ch_layout, // output ch layout
|
mOutputChannelLayout, // output ch layout
|
||||||
mOutputSampleFormat, // output sample format
|
mOutputSampleFormat, // output sample format
|
||||||
(*mStream)->codec->sample_rate, // output sample rate
|
(*mStream)->codec->sample_rate, // output sample rate
|
||||||
ch_layout, // input ch layout
|
ch_layout, // input ch layout
|
||||||
@ -383,7 +383,7 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
|||||||
|
|
||||||
while(getAVAudioData())
|
while(getAVAudioData())
|
||||||
{
|
{
|
||||||
size_t got = mFrame->nb_samples * (*mStream)->codec->channels *
|
size_t got = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
|
||||||
av_get_bytes_per_sample(mOutputSampleFormat);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
const char *inbuf = reinterpret_cast<char*>(mFrameData[0]);
|
const char *inbuf = reinterpret_cast<char*>(mFrameData[0]);
|
||||||
output.insert(output.end(), inbuf, inbuf+got);
|
output.insert(output.end(), inbuf, inbuf+got);
|
||||||
@ -402,7 +402,7 @@ void FFmpeg_Decoder::rewind()
|
|||||||
|
|
||||||
size_t FFmpeg_Decoder::getSampleOffset()
|
size_t FFmpeg_Decoder::getSampleOffset()
|
||||||
{
|
{
|
||||||
int delay = (mFrameSize-mFramePos) / (*mStream)->codec->channels /
|
int delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) /
|
||||||
av_get_bytes_per_sample(mOutputSampleFormat);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay;
|
return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay;
|
||||||
}
|
}
|
||||||
@ -416,6 +416,7 @@ FFmpeg_Decoder::FFmpeg_Decoder()
|
|||||||
, mNextPts(0.0)
|
, mNextPts(0.0)
|
||||||
, mSwr(0)
|
, mSwr(0)
|
||||||
, mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
|
, mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
|
||||||
|
, mOutputChannelLayout(0)
|
||||||
, mDataBuf(NULL)
|
, mDataBuf(NULL)
|
||||||
, mFrameData(NULL)
|
, mFrameData(NULL)
|
||||||
, mDataBufLen(0)
|
, mDataBufLen(0)
|
||||||
|
@ -59,6 +59,7 @@ namespace MWSound
|
|||||||
|
|
||||||
SwrContext *mSwr;
|
SwrContext *mSwr;
|
||||||
enum AVSampleFormat mOutputSampleFormat;
|
enum AVSampleFormat mOutputSampleFormat;
|
||||||
|
int64_t mOutputChannelLayout;
|
||||||
uint8_t *mDataBuf;
|
uint8_t *mDataBuf;
|
||||||
uint8_t **mFrameData;
|
uint8_t **mFrameData;
|
||||||
int mDataBufLen;
|
int mDataBufLen;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
|
||||||
|
#include "al.h"
|
||||||
|
|
||||||
#include "sound_decoder.hpp"
|
#include "sound_decoder.hpp"
|
||||||
#include "sound.hpp"
|
#include "sound.hpp"
|
||||||
|
|
||||||
@ -64,20 +66,21 @@ namespace MWSound
|
|||||||
|
|
||||||
virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate)
|
virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate)
|
||||||
{
|
{
|
||||||
if (sampleFormat == AV_SAMPLE_FMT_U8P)
|
if (sampleFormat == AV_SAMPLE_FMT_U8P || sampleFormat == AV_SAMPLE_FMT_U8)
|
||||||
sampleFormat = AV_SAMPLE_FMT_U8;
|
sampleFormat = AV_SAMPLE_FMT_U8;
|
||||||
else if (sampleFormat == AV_SAMPLE_FMT_S16P)
|
else if (sampleFormat == AV_SAMPLE_FMT_S16P || sampleFormat == AV_SAMPLE_FMT_S16)
|
||||||
sampleFormat = AV_SAMPLE_FMT_S16;
|
sampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
else if (sampleFormat == AV_SAMPLE_FMT_FLTP)
|
else if ((sampleFormat == AV_SAMPLE_FMT_FLTP || sampleFormat == AV_SAMPLE_FMT_FLT)
|
||||||
|
&& alIsExtensionPresent("AL_EXT_FLOAT32"))
|
||||||
sampleFormat = AV_SAMPLE_FMT_FLT;
|
sampleFormat = AV_SAMPLE_FMT_FLT;
|
||||||
else
|
else
|
||||||
sampleFormat = AV_SAMPLE_FMT_FLT;
|
sampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
|
|
||||||
if (channelLayout != AV_CH_LAYOUT_MONO
|
if ((channelLayout == AV_CH_LAYOUT_5POINT1 || channelLayout == AV_CH_LAYOUT_7POINT1
|
||||||
&& channelLayout != AV_CH_LAYOUT_5POINT1
|
|| channelLayout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
&& channelLayout != AV_CH_LAYOUT_7POINT1
|
channelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
&& channelLayout != AV_CH_LAYOUT_STEREO
|
else if (channelLayout != AV_CH_LAYOUT_MONO
|
||||||
&& channelLayout != AV_CH_LAYOUT_QUAD)
|
&& channelLayout != AV_CH_LAYOUT_STEREO)
|
||||||
channelLayout = AV_CH_LAYOUT_STEREO;
|
channelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user