Restore exception throwing to the decoder

pull/359/head
Chris Robinson 7 years ago
parent 06ae61479a
commit 08e947319a

@ -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();
try mDataStream = mResourceMgr->get(fname);
{
mDataStream = mResourceMgr->get(fname);
if((mFormatCtx=avformat_alloc_context()) == NULL) if((mFormatCtx=avformat_alloc_context()) == NULL)
throw std::runtime_error("Failed to allocate context"); throw std::runtime_error("Failed to allocate context");
try
{
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)
{
std::cerr<< "Could not open audio file: "<<e.what() <<std::endl;
} }
catch(...) {
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();
ChannelConfig chans; // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav.
SampleType type; if(decoder->mResourceMgr->exists(fname))
if(decoder->getInfo(&srate, &chans, &type)) decoder->open(fname);
else
{ {
format = getALFormat(chans, type); std::string file = fname;
if(format) decoder->readAll(data); std::string::size_type pos = file.rfind('.');
if(pos != std::string::npos)
file = file.substr(0, pos)+".mp3";
decoder->open(file);
} }
ChannelConfig chans;
SampleType type;
decoder->getInfo(&srate, &chans, &type);
format = getALFormat(chans, type);
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…
Cancel
Save