forked from mirror/openmw-tes3mp
Restore exception throwing to the decoder
This commit is contained in:
parent
06ae61479a
commit
08e947319a
5 changed files with 56 additions and 73 deletions
|
@ -176,16 +176,16 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length)
|
||||||
return dec;
|
return dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FFmpeg_Decoder::open(const std::string &fname)
|
void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
mDataStream = mResourceMgr->get(fname);
|
||||||
|
|
||||||
|
if((mFormatCtx=avformat_alloc_context()) == NULL)
|
||||||
|
throw std::runtime_error("Failed to allocate context");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mDataStream = mResourceMgr->get(fname);
|
|
||||||
|
|
||||||
if((mFormatCtx=avformat_alloc_context()) == NULL)
|
|
||||||
throw std::runtime_error("Failed to allocate context");
|
|
||||||
|
|
||||||
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
||||||
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
||||||
{
|
{
|
||||||
|
@ -250,16 +250,8 @@ bool FFmpeg_Decoder::open(const std::string &fname)
|
||||||
mOutputChannelLayout = (*mStream)->codec->channel_layout;
|
mOutputChannelLayout = (*mStream)->codec->channel_layout;
|
||||||
if(mOutputChannelLayout == 0)
|
if(mOutputChannelLayout == 0)
|
||||||
mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels);
|
mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(...) {
|
||||||
{
|
|
||||||
std::cerr<< "Could not open audio file: "<<e.what() <<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mFormatCtx)
|
|
||||||
{
|
|
||||||
if(mStream)
|
if(mStream)
|
||||||
avcodec_close((*mStream)->codec);
|
avcodec_close((*mStream)->codec);
|
||||||
mStream = NULL;
|
mStream = NULL;
|
||||||
|
@ -273,8 +265,8 @@ bool FFmpeg_Decoder::open(const std::string &fname)
|
||||||
mFormatCtx->pb = NULL;
|
mFormatCtx->pb = NULL;
|
||||||
|
|
||||||
avformat_close_input(&mFormatCtx);
|
avformat_close_input(&mFormatCtx);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::close()
|
void FFmpeg_Decoder::close()
|
||||||
|
@ -316,13 +308,10 @@ std::string FFmpeg_Decoder::getName()
|
||||||
return mFormatCtx->filename;
|
return mFormatCtx->filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
{
|
{
|
||||||
if(!mStream)
|
if(!mStream)
|
||||||
{
|
throw std::runtime_error("No audio stream info");
|
||||||
std::cerr<< "No audio stream info" <<std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mOutputSampleFormat == AV_SAMPLE_FMT_U8)
|
if(mOutputSampleFormat == AV_SAMPLE_FMT_U8)
|
||||||
*type = SampleType_UInt8;
|
*type = SampleType_UInt8;
|
||||||
|
@ -330,6 +319,11 @@ bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
||||||
*type = SampleType_Int16;
|
*type = SampleType_Int16;
|
||||||
else if(mOutputSampleFormat == AV_SAMPLE_FMT_FLT)
|
else if(mOutputSampleFormat == AV_SAMPLE_FMT_FLT)
|
||||||
*type = SampleType_Float32;
|
*type = SampleType_Float32;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
|
*type = SampleType_Int16;
|
||||||
|
}
|
||||||
|
|
||||||
if(mOutputChannelLayout == AV_CH_LAYOUT_MONO)
|
if(mOutputChannelLayout == AV_CH_LAYOUT_MONO)
|
||||||
*chans = ChannelConfig_Mono;
|
*chans = ChannelConfig_Mono;
|
||||||
|
@ -378,18 +372,10 @@ bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
||||||
0, // logging level offset
|
0, // logging level offset
|
||||||
NULL); // log context
|
NULL); // log context
|
||||||
if(!mSwr)
|
if(!mSwr)
|
||||||
{
|
throw std::runtime_error("Couldn't allocate SwrContext");
|
||||||
std::cerr<< "Couldn't allocate SwrContext" <<std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(swr_init(mSwr) < 0)
|
if(swr_init(mSwr) < 0)
|
||||||
{
|
throw std::runtime_error("Couldn't initialize SwrContext");
|
||||||
std::cerr<< "Couldn't initialize SwrContext" <<std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
||||||
|
|
|
@ -66,11 +66,11 @@ namespace MWSound
|
||||||
bool getAVAudioData();
|
bool getAVAudioData();
|
||||||
size_t readAVAudioData(void *data, size_t length);
|
size_t readAVAudioData(void *data, size_t length);
|
||||||
|
|
||||||
bool open(const std::string &fname) override;
|
void open(const std::string &fname) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
std::string getName() override;
|
std::string getName() override;
|
||||||
bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override;
|
void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override;
|
||||||
|
|
||||||
size_t read(char *buffer, size_t bytes) override;
|
size_t read(char *buffer, size_t bytes) override;
|
||||||
void readAll(std::vector<char> &output) override;
|
void readAll(std::vector<char> &output) override;
|
||||||
|
|
|
@ -27,10 +27,10 @@ namespace MWSound
|
||||||
private:
|
private:
|
||||||
MWSound::MovieAudioDecoder* mDecoder;
|
MWSound::MovieAudioDecoder* mDecoder;
|
||||||
|
|
||||||
bool open(const std::string &fname) override;
|
void open(const std::string &fname) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
std::string getName() override;
|
std::string getName() override;
|
||||||
bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override;
|
void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override;
|
||||||
size_t read(char *buffer, size_t bytes) override;
|
size_t read(char *buffer, size_t bytes) override;
|
||||||
size_t getSampleOffset() override;
|
size_t getSampleOffset() override;
|
||||||
};
|
};
|
||||||
|
@ -98,9 +98,9 @@ namespace MWSound
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool MWSoundDecoderBridge::open(const std::string &fname)
|
void MWSoundDecoderBridge::open(const std::string &fname)
|
||||||
{
|
{
|
||||||
return false;
|
throw std::runtime_error("Method not implemented");
|
||||||
}
|
}
|
||||||
void MWSoundDecoderBridge::close() {}
|
void MWSoundDecoderBridge::close() {}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ namespace MWSound
|
||||||
return mDecoder->getStreamName();
|
return mDecoder->getStreamName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
{
|
{
|
||||||
*samplerate = mDecoder->getOutputSampleRate();
|
*samplerate = mDecoder->getOutputSampleRate();
|
||||||
|
|
||||||
|
@ -125,10 +125,8 @@ namespace MWSound
|
||||||
else if (outputChannelLayout == AV_CH_LAYOUT_QUAD)
|
else if (outputChannelLayout == AV_CH_LAYOUT_QUAD)
|
||||||
*chans = ChannelConfig_Quad;
|
*chans = ChannelConfig_Quad;
|
||||||
else
|
else
|
||||||
{
|
throw std::runtime_error("Unsupported channel layout: "+
|
||||||
std::cerr<< "Unsupported channel layout: "<<outputChannelLayout <<std::endl;
|
std::to_string(outputChannelLayout));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AVSampleFormat outputSampleFormat = mDecoder->getOutputSampleFormat();
|
AVSampleFormat outputSampleFormat = mDecoder->getOutputSampleFormat();
|
||||||
if (outputSampleFormat == AV_SAMPLE_FMT_U8)
|
if (outputSampleFormat == AV_SAMPLE_FMT_U8)
|
||||||
|
@ -141,11 +139,8 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
char str[1024];
|
char str[1024];
|
||||||
av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat);
|
av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat);
|
||||||
std::cerr<< "Unsupported sample format: "<<str <<std::endl;
|
throw std::runtime_error(std::string("Unsupported sample format: ")+str);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MWSoundDecoderBridge::read(char *buffer, size_t bytes)
|
size_t MWSoundDecoderBridge::read(char *buffer, size_t bytes)
|
||||||
|
|
|
@ -411,10 +411,14 @@ bool OpenAL_SoundStream::init(bool getLoudnessData)
|
||||||
ChannelConfig chans;
|
ChannelConfig chans;
|
||||||
SampleType type;
|
SampleType type;
|
||||||
|
|
||||||
if(!mDecoder->getInfo(&mSampleRate, &chans, &type))
|
try {
|
||||||
|
mDecoder->getInfo(&mSampleRate, &chans, &type);
|
||||||
|
mFormat = getALFormat(chans, type);
|
||||||
|
}
|
||||||
|
catch(std::exception &e) {
|
||||||
|
std::cerr<< "Failed to get stream info: "<<e.what() <<std::endl;
|
||||||
return false;
|
return false;
|
||||||
mFormat = getALFormat(chans, type);
|
}
|
||||||
if(!mFormat) return false;
|
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -946,35 +950,33 @@ std::pair<Sound_Handle,size_t> OpenAL_Output::loadSound(const std::string &fname
|
||||||
{
|
{
|
||||||
getALError();
|
getALError();
|
||||||
|
|
||||||
DecoderPtr decoder = mManager.getDecoder();
|
|
||||||
// Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav.
|
|
||||||
bool succeeded;
|
|
||||||
if(decoder->mResourceMgr->exists(fname))
|
|
||||||
succeeded = decoder->open(fname);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string file = fname;
|
|
||||||
std::string::size_type pos = file.rfind('.');
|
|
||||||
if(pos != std::string::npos)
|
|
||||||
file = file.substr(0, pos)+".mp3";
|
|
||||||
succeeded = decoder->open(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
ALenum format;
|
ALenum format;
|
||||||
int srate;
|
int srate;
|
||||||
|
|
||||||
if(succeeded)
|
try {
|
||||||
{
|
DecoderPtr decoder = mManager.getDecoder();
|
||||||
|
// Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav.
|
||||||
|
if(decoder->mResourceMgr->exists(fname))
|
||||||
|
decoder->open(fname);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string file = fname;
|
||||||
|
std::string::size_type pos = file.rfind('.');
|
||||||
|
if(pos != std::string::npos)
|
||||||
|
file = file.substr(0, pos)+".mp3";
|
||||||
|
decoder->open(file);
|
||||||
|
}
|
||||||
|
|
||||||
ChannelConfig chans;
|
ChannelConfig chans;
|
||||||
SampleType type;
|
SampleType type;
|
||||||
if(decoder->getInfo(&srate, &chans, &type))
|
decoder->getInfo(&srate, &chans, &type);
|
||||||
{
|
format = getALFormat(chans, type);
|
||||||
format = getALFormat(chans, type);
|
if(format) decoder->readAll(data);
|
||||||
if(format) decoder->readAll(data);
|
}
|
||||||
}
|
catch(std::exception &e) {
|
||||||
|
std::cerr<< "Failed to load audio from "<<fname<<": "<<e.what() <<std::endl;
|
||||||
}
|
}
|
||||||
decoder->close();
|
|
||||||
|
|
||||||
if(data.empty())
|
if(data.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,11 +34,11 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
const VFS::Manager* mResourceMgr;
|
const VFS::Manager* mResourceMgr;
|
||||||
|
|
||||||
virtual bool open(const std::string &fname) = 0;
|
virtual void open(const std::string &fname) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
|
|
||||||
virtual std::string getName() = 0;
|
virtual std::string getName() = 0;
|
||||||
virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
||||||
|
|
||||||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||||
virtual void readAll(std::vector<char> &output);
|
virtual void readAll(std::vector<char> &output);
|
||||||
|
|
Loading…
Reference in a new issue