Exposed metadata for each embedded picture
This commit is contained in:
@@ -34,6 +34,8 @@ extern "C"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/String.hpp"
|
||||
|
||||
#include "av/Types.hpp"
|
||||
|
||||
namespace lms::av
|
||||
{
|
||||
namespace
|
||||
@@ -43,9 +45,9 @@ namespace lms::av
|
||||
std::array<char, 128> buf = { 0 };
|
||||
|
||||
if (::av_strerror(error, buf.data(), buf.size()) == 0)
|
||||
return &buf[0];
|
||||
else
|
||||
return "Unknown error";
|
||||
return buf.data();
|
||||
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
class AudioFileException : public Exception
|
||||
@@ -158,7 +160,7 @@ namespace lms::av
|
||||
{
|
||||
ContainerInfo info;
|
||||
info.bitrate = _context->bit_rate;
|
||||
info.duration = std::chrono::milliseconds{ _context->duration == AV_NOPTS_VALUE ? 0 : _context->duration / AV_TIME_BASE * 1000 };
|
||||
info.duration = std::chrono::milliseconds{ _context->duration == AV_NOPTS_VALUE ? 0 : _context->duration / AV_TIME_BASE * 1'000 };
|
||||
info.name = _context->iformat->name;
|
||||
|
||||
return info;
|
||||
@@ -237,7 +239,7 @@ namespace lms::av
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioFile::visitAttachedPictures(std::function<void(const Picture&)> func) const
|
||||
void AudioFile::visitAttachedPictures(std::function<void(const Picture&, const MetadataMap&)> func) const
|
||||
{
|
||||
static const std::unordered_map<int, std::string> codecMimeMap{
|
||||
{ AV_CODEC_ID_BMP, "image/x-bmp" },
|
||||
@@ -262,6 +264,9 @@ namespace lms::av
|
||||
continue;
|
||||
}
|
||||
|
||||
MetadataMap metadata;
|
||||
getMetaDataFromDictionnary(avstream->metadata, metadata);
|
||||
|
||||
Picture picture;
|
||||
|
||||
auto itMime = codecMimeMap.find(avstream->codecpar->codec_id);
|
||||
@@ -280,7 +285,7 @@ namespace lms::av
|
||||
picture.data = reinterpret_cast<const std::byte*>(pkt.data);
|
||||
picture.dataSize = pkt.size;
|
||||
|
||||
func(picture);
|
||||
func(picture, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,13 @@ struct AVFormatContext;
|
||||
|
||||
namespace lms::av
|
||||
{
|
||||
|
||||
class AudioFile final : public IAudioFile
|
||||
{
|
||||
public:
|
||||
AudioFile(const std::filesystem::path& p);
|
||||
~AudioFile();
|
||||
~AudioFile() override;
|
||||
AudioFile(const AudioFile&) = delete;
|
||||
AudioFile& operator=(const AudioFile&) = delete;
|
||||
|
||||
const std::filesystem::path& getPath() const override;
|
||||
ContainerInfo getContainerInfo() const override;
|
||||
@@ -39,16 +40,12 @@ namespace lms::av
|
||||
std::optional<StreamInfo> getBestStreamInfo() const override;
|
||||
std::optional<std::size_t> getBestStreamIndex() const override;
|
||||
bool hasAttachedPictures() const override;
|
||||
void visitAttachedPictures(std::function<void(const Picture&)> func) const override;
|
||||
void visitAttachedPictures(std::function<void(const Picture&, const MetadataMap&)> func) const override;
|
||||
|
||||
private:
|
||||
AudioFile(const AudioFile&) = delete;
|
||||
AudioFile& operator=(const AudioFile&) = delete;
|
||||
|
||||
std::optional<StreamInfo> getStreamInfo(std::size_t streamIndex) const;
|
||||
|
||||
const std::filesystem::path _p;
|
||||
AVFormatContext* _context{};
|
||||
};
|
||||
|
||||
} // namespace lms::av
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
namespace lms::av
|
||||
{
|
||||
// List should be sync with the codecs shipped in the lms's docker version
|
||||
@@ -62,14 +60,14 @@ namespace lms::av
|
||||
struct Picture
|
||||
{
|
||||
std::string mimeType;
|
||||
const std::byte* data{};
|
||||
const std::byte* data{}; // valid as long as IAudioFile exists
|
||||
std::size_t dataSize{};
|
||||
};
|
||||
|
||||
struct ContainerInfo
|
||||
{
|
||||
std::size_t bitrate{};
|
||||
std::string name{};
|
||||
std::string name;
|
||||
std::chrono::milliseconds duration{};
|
||||
};
|
||||
|
||||
@@ -99,7 +97,7 @@ namespace lms::av
|
||||
virtual std::optional<StreamInfo> getBestStreamInfo() const = 0; // none if failure/unknown
|
||||
virtual std::optional<std::size_t> getBestStreamIndex() const = 0; // none if failure/unknown
|
||||
virtual bool hasAttachedPictures() const = 0;
|
||||
virtual void visitAttachedPictures(std::function<void(const Picture&)> func) const = 0;
|
||||
virtual void visitAttachedPictures(std::function<void(const Picture&, const MetadataMap& metadata)> func) const = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IAudioFile> parseAudioFile(const std::filesystem::path& p);
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
#include "ArtworkService.hpp"
|
||||
|
||||
#include "av/IAudioFile.hpp"
|
||||
#include "av/Types.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Path.hpp"
|
||||
#include "core/Random.hpp"
|
||||
#include "core/String.hpp"
|
||||
#include "core/Utils.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Db.hpp"
|
||||
@@ -71,7 +69,7 @@ namespace lms::cover
|
||||
{
|
||||
std::unique_ptr<IEncodedImage> image;
|
||||
|
||||
input.visitAttachedPictures([&](const av::Picture& picture) {
|
||||
input.visitAttachedPictures([&](const av::Picture& picture, const av::IAudioFile::MetadataMap& /* metadata */) {
|
||||
if (image)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user