FFmpeg parser: better fallback for streams that do not expose bitrate
This commit is contained in:
@@ -32,6 +32,7 @@ extern "C"
|
||||
}
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
#include "core/String.hpp"
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
@@ -189,7 +190,7 @@ namespace lms::audio::ffmpeg
|
||||
std::array<char, 256> buffer{ 0 };
|
||||
std::vsnprintf(buffer.data(), buffer.size(), fmt, vl);
|
||||
|
||||
LMS_LOG(AUDIO, DEBUG, "ffmpeg [" << avLogLevelToStr(level) << "] " << buffer.data());
|
||||
LMS_LOG(AUDIO, DEBUG, "FFmpeg [" << avLogLevelToStr(level) << "] " << buffer.data());
|
||||
}
|
||||
|
||||
class AvInitializer
|
||||
@@ -205,6 +206,8 @@ namespace lms::audio::ffmpeg
|
||||
AudioFile::AudioFile(const std::filesystem::path& p)
|
||||
: _p{ p }
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("MetaData", "FFmpegParseFile");
|
||||
|
||||
static AvInitializer init;
|
||||
|
||||
int error{ avformat_open_input(&_context, _p.c_str(), nullptr, nullptr) };
|
||||
@@ -240,7 +243,8 @@ namespace lms::audio::ffmpeg
|
||||
info.container = avdemuxerToContainerType(_context->iformat->name);
|
||||
info.containerName = _context->iformat->name;
|
||||
|
||||
info.bitrate = _context->bit_rate;
|
||||
if (_context->bit_rate > 0)
|
||||
info.bitrate = _context->bit_rate;
|
||||
info.duration = std::chrono::milliseconds{ _context->duration == AV_NOPTS_VALUE ? 0 : _context->duration / AV_TIME_BASE * 1'000 };
|
||||
|
||||
return info;
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace lms::audio::ffmpeg
|
||||
std::optional<ContainerType> container;
|
||||
std::string containerName;
|
||||
|
||||
std::size_t bitrate{};
|
||||
std::optional<std::size_t> bitrate;
|
||||
std::chrono::milliseconds duration{};
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
#include "AudioFileInfo.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <system_error>
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
@@ -44,6 +47,12 @@ namespace lms::audio::ffmpeg
|
||||
return audioProperties;
|
||||
}
|
||||
|
||||
if (containerInfo.duration.count() == 0)
|
||||
{
|
||||
LMS_LOG(AUDIO, DEBUG, "Cannot determine duration in " << audioFile.getPath());
|
||||
return audioProperties;
|
||||
}
|
||||
|
||||
if (!containerInfo.container)
|
||||
{
|
||||
LMS_LOG(AUDIO, DEBUG, "Unhandled container '" << containerInfo.containerName << "' in " << audioFile.getPath());
|
||||
@@ -56,12 +65,6 @@ namespace lms::audio::ffmpeg
|
||||
return audioProperties;
|
||||
}
|
||||
|
||||
if (!bestStreamInfo->bitrate || *bestStreamInfo->bitrate == 0)
|
||||
{
|
||||
LMS_LOG(AUDIO, DEBUG, "Cannot determine bitrate in " << audioFile.getPath());
|
||||
return audioProperties;
|
||||
}
|
||||
|
||||
if (!bestStreamInfo->channelCount || *bestStreamInfo->channelCount == 0)
|
||||
{
|
||||
LMS_LOG(AUDIO, DEBUG, "Cannot determine channel count in " << audioFile.getPath());
|
||||
@@ -79,7 +82,27 @@ namespace lms::audio::ffmpeg
|
||||
audioProperties->container = *containerInfo.container;
|
||||
audioProperties->duration = containerInfo.duration;
|
||||
audioProperties->codec = *bestStreamInfo->codec;
|
||||
audioProperties->bitrate = *bestStreamInfo->bitrate;
|
||||
|
||||
if (bestStreamInfo->bitrate)
|
||||
audioProperties->bitrate = *bestStreamInfo->bitrate;
|
||||
else if (containerInfo.bitrate)
|
||||
audioProperties->bitrate = *containerInfo.bitrate;
|
||||
else // Fallback on a bitrate based on duration/size
|
||||
{
|
||||
std::error_code ec;
|
||||
const auto fileSize{ std::filesystem::file_size(audioFile.getPath(), ec) };
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(AUDIO, DEBUG, "Cannot determine file size for " << audioFile.getPath() << ": " << ec.message());
|
||||
audioProperties.reset();
|
||||
return audioProperties;
|
||||
}
|
||||
|
||||
audioProperties->bitrate = static_cast<std::size_t>(std::chrono::duration_cast<std::chrono::duration<double>>(containerInfo.duration).count() / fileSize);
|
||||
LMS_LOG(AUDIO, DEBUG, "Estimated bitrate from duration/size: " << audioProperties->bitrate << " bps in " << audioFile.getPath());
|
||||
}
|
||||
assert(audioProperties->bitrate > 0);
|
||||
|
||||
audioProperties->channelCount = *bestStreamInfo->channelCount;
|
||||
audioProperties->sampleRate = *bestStreamInfo->sampleRate;
|
||||
audioProperties->bitsPerSample = bestStreamInfo->bitsPerSample;
|
||||
|
||||
Reference in New Issue
Block a user