From 39b068fc5214ecfeff3e25481bed834837f9fc70 Mon Sep 17 00:00:00 2001 From: casey langen Date: Thu, 27 Dec 2018 13:40:27 -0800 Subject: [PATCH] A couple more ffmpeg decoder bug fixes -- wma files seem to be decoding properly on macOS (and likely Linux) now. --- src/core/plugin/Plugins.cpp | 20 +++---- src/core/plugin/Plugins.h | 6 ++- src/musikcube/Main.cpp | 5 +- src/musikcubed/main.cpp | 5 +- src/plugins/ffmpegdecoder/FfmpegDecoder.cpp | 59 ++++++++++++++++----- 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/core/plugin/Plugins.cpp b/src/core/plugin/Plugins.cpp index 0660650ce..6d4eceda1 100644 --- a/src/core/plugin/Plugins.cpp +++ b/src/core/plugin/Plugins.cpp @@ -258,7 +258,16 @@ static class Environment: public IEnvironment { namespace musik { namespace core { namespace plugin { - void InstallDependencies(IMessageQueue* messageQueue, IPlaybackService* playback, ILibraryPtr library) { + void InitDebug() { + /* debug */ + PluginFactory::Instance().QueryFunction( + "SetDebug", + [](musik::core::sdk::IPlugin* plugin, SetDebug func) { + func(&debugger); + }); + } + + void InitPlayback(IMessageQueue* messageQueue, IPlaybackService* playback, ILibraryPtr library) { /* preferences */ Preferences::LoadPluginPreferences(); @@ -292,16 +301,9 @@ namespace musik { namespace core { namespace plugin { [](musik::core::sdk::IPlugin* plugin, SetEnvironment func) { func(&environment); }); - - /* debug */ - PluginFactory::Instance().QueryFunction( - "SetDebug", - [](musik::core::sdk::IPlugin* plugin, SetDebug func) { - func(&debugger); - }); } - void UninstallDependencies() { + void Deinit() { /* preferences */ Preferences::SavePluginPreferences(); diff --git a/src/core/plugin/Plugins.h b/src/core/plugin/Plugins.h index 8827b440c..f1e86d2fe 100644 --- a/src/core/plugin/Plugins.h +++ b/src/core/plugin/Plugins.h @@ -40,11 +40,13 @@ namespace musik { namespace core { namespace plugin { - void InstallDependencies( + void InitDebug(); + + void InitPlayback( musik::core::runtime::IMessageQueue* messageQueue, musik::core::sdk::IPlaybackService* playback, musik::core::ILibraryPtr library); - void UninstallDependencies(); + void Deinit(); } } } diff --git a/src/musikcube/Main.cpp b/src/musikcube/Main.cpp index f64829ff5..ca08bfeb1 100644 --- a/src/musikcube/Main.cpp +++ b/src/musikcube/Main.cpp @@ -124,6 +124,7 @@ int main(int argc, char* argv[]) { auto fileLogger = new musik::debug::SimpleFileBackend(); auto consoleLogger = new ConsoleLogger(Window::MessageQueue()); musik::debug::Start({ fileLogger, consoleLogger }); + musik::core::plugin::InitDebug(); ILibraryPtr library = LibraryFactory::Default(); library->SetMessageQueue(Window::MessageQueue()); @@ -137,7 +138,7 @@ int main(int argc, char* argv[]) { GlobalHotkeys globalHotkeys(playback, library); Window::SetNavigationKeys(Hotkeys::NavigationKeys()); - musik::core::plugin::InstallDependencies( + musik::core::plugin::InitPlayback( &Window::MessageQueue(), &playback, library); #ifdef WIN32 @@ -223,7 +224,7 @@ int main(int argc, char* argv[]) { } musik::core::audio::vis::HideSelectedVisualizer(); - musik::core::plugin::UninstallDependencies(); + musik::core::plugin::Deinit(); LibraryFactory::Instance().Shutdown(); diff --git a/src/musikcubed/main.cpp b/src/musikcubed/main.cpp index e68b213af..f167dd269 100644 --- a/src/musikcubed/main.cpp +++ b/src/musikcubed/main.cpp @@ -238,6 +238,7 @@ int main(int argc, char** argv) { srand((unsigned int) time(0)); debug::Start(); + plugin::InitDebug(); EvMessageQueue messageQueue; auto library = LibraryFactory::Default(); @@ -246,7 +247,7 @@ int main(int argc, char** argv) { { PlaybackService playback(messageQueue, library); - plugin::InstallDependencies(&messageQueue, &playback, library); + plugin::InitPlayback(&messageQueue, &playback, library); auto prefs = Preferences::ForComponent(prefs::components::Settings); if (prefs->GetBool(prefs::keys::SyncOnStartup, true)) { @@ -258,5 +259,7 @@ int main(int argc, char** argv) { library->Indexer()->Stop(); } + plugin::Deinit(); + remove(LOCKFILE); } diff --git a/src/plugins/ffmpegdecoder/FfmpegDecoder.cpp b/src/plugins/ffmpegdecoder/FfmpegDecoder.cpp index bf3f46953..343611045 100644 --- a/src/plugins/ffmpegdecoder/FfmpegDecoder.cpp +++ b/src/plugins/ffmpegdecoder/FfmpegDecoder.cpp @@ -62,6 +62,13 @@ static std::string getAvError(int errnum) { return std::string(buffer); } +static void logAvError(const std::string& method, int errnum) { + if (errnum != 0) { + std::string err = method + "() failed: " + getAvError(errnum); + ::debug->Warning(TAG, err.c_str()); + } +} + static int readCallback(void* opaque, uint8_t* buffer, int bufferSize) { FfmpegDecoder* decoder = static_cast(opaque); if (decoder && decoder->Stream()) { @@ -92,6 +99,13 @@ static int64_t seekCallback(void* opaque, int64_t offset, int whence) { case SEEK_END: stream->SetPosition(stream->Length() - 1); break; + default: + debug->Error(TAG, "unknown seek type!"); + break; + } + + if (stream->Position() >= stream->Length()) { + return -1; } return stream->Position(); @@ -152,9 +166,9 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) { buffer->SetChannels((long) this->channels); buffer->SetSamples(0); - int readFrameResult = av_read_frame(this->formatContext, &this->packet); + int errnum = av_read_frame(this->formatContext, &this->packet); - if (!readFrameResult) { + if (!errnum) { int frameDecoded = 0; avcodec_decode_audio4( @@ -171,6 +185,20 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) { auto inFormat = this->codecContext->sample_fmt; auto inLayout = this->codecContext->channel_layout; + if (inLayout == 0) { + /* in some cases it seems the input channel layout cannot be detected. + for this case, we configure it manually so the resampler is happy. */ + switch (channels) { + case 1: inLayout = AV_CH_LAYOUT_MONO; break; + case 2: inLayout = AV_CH_LAYOUT_STEREO; break; + case 3: inLayout = AV_CH_LAYOUT_2POINT1; break; + case 4: inLayout = AV_CH_LAYOUT_3POINT1; break; + case 5: inLayout = AV_CH_LAYOUT_4POINT1; break; + case 6: inLayout = AV_CH_LAYOUT_5POINT1; break; + default: inLayout = AV_CH_LAYOUT_STEREO_DOWNMIX; break; + } + } + int decodedSize = av_samples_get_buffer_size( nullptr, channels, samples, inFormat, 1); @@ -192,7 +220,9 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) { 0, nullptr); - swr_init(this->resampler); + if ((errnum = swr_init(this->resampler)) != 0) { + logAvError("swr_init", errnum); + } } uint8_t* outData = (uint8_t*) buffer->BufferPointer(); @@ -201,9 +231,15 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) { int convertedSamplesPerChannel = swr_convert( this->resampler, &outData, samples, inData, samples); - /* actual buffer size, based on resampler output. should be the same - as the preferred size... */ - buffer->SetSamples(convertedSamplesPerChannel * this->channels); + if (convertedSamplesPerChannel < 0) { + logAvError("swr_convert", convertedSamplesPerChannel); + buffer->SetSamples(0); + } + else { + /* actual buffer size, based on resampler output. should be the same + as the preferred size... */ + buffer->SetSamples(convertedSamplesPerChannel * this->channels); + } } } else { @@ -214,11 +250,7 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) { return true; } else { - std::string err = - "av_read_frame() failed: " + - getAvError(readFrameResult); - - ::debug->Warning(TAG, err.c_str()); + logAvError("av_read_frame", errnum); } } @@ -276,7 +308,8 @@ bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) { this->formatContext->flags = AVFMT_FLAG_CUSTOM_IO; unsigned char probe[PROBE_SIZE]; - size_t count = stream->Read(probe, PROBE_SIZE); + memset(probe, 0, PROBE_SIZE); + size_t count = stream->Read(probe, PROBE_SIZE - AVPROBE_PADDING_SIZE); stream->SetPosition(0); AVProbeData probeData = { 0 }; @@ -298,7 +331,7 @@ bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) { } if (this->streamId != -1) { - ::debug->Info(TAG, "found audio!"); + ::debug->Info(TAG, "found audio stream!"); this->codecContext = this->formatContext->streams[this->streamId]->codec; if (codecContext) { this->codecContext->request_sample_fmt = AV_SAMPLE_FMT_FLT;