A couple more ffmpeg decoder bug fixes -- wma files seem to be decoding properly on macOS (and likely Linux) now.

This commit is contained in:
casey langen 2018-12-27 13:40:27 -08:00
parent e3a3da754e
commit 39b068fc52
5 changed files with 68 additions and 27 deletions

View File

@ -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>(
"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>(
"SetDebug",
[](musik::core::sdk::IPlugin* plugin, SetDebug func) {
func(&debugger);
});
}
void UninstallDependencies() {
void Deinit() {
/* preferences */
Preferences::SavePluginPreferences();

View File

@ -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();
} } }

View File

@ -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();

View File

@ -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);
}

View File

@ -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<FfmpegDecoder*>(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;