2018-03-06 23:09:15 +01:00
|
|
|
#ifndef TAG_PARSER_MP4TAGATOM_H
|
|
|
|
#define TAG_PARSER_MP4TAGATOM_H
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-09-06 19:57:33 +02:00
|
|
|
#include "../generictagfield.h"
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2017-01-23 00:25:53 +01:00
|
|
|
#include <c++utilities/conversion/stringconversion.h>
|
2018-03-07 01:17:50 +01:00
|
|
|
#include <c++utilities/io/binarywriter.h>
|
2015-12-10 13:50:46 +01:00
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
#include <cstdint>
|
2016-02-05 20:25:38 +01:00
|
|
|
#include <sstream>
|
2018-03-07 01:17:50 +01:00
|
|
|
#include <vector>
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
namespace TagParser {
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Encapsulates the most common data type IDs of MP4 tag fields.
|
|
|
|
*/
|
|
|
|
namespace RawDataType {
|
2019-03-13 19:06:42 +01:00
|
|
|
enum KnownValue : std::uint32_t {
|
2015-04-22 19:22:01 +02:00
|
|
|
Reserved = 0, /**< reserved for use where no type needs to be indicated */
|
|
|
|
Utf8 = 1, /**< without any count or NULL terminator */
|
|
|
|
Utf16 = 2, /**< also known as UTF-16BE */
|
|
|
|
Sjis = 3, /**< S/JIS: deprecated unless it is needed for special Japanese characters */
|
|
|
|
Utf8Sort = 4, /**< variant storage of a string for sorting only */
|
|
|
|
Utf16Sort = 5, /**< variant storage of a string for sorting only */
|
|
|
|
Html = 6, /**< the HTML file header specifies which HTML version */
|
|
|
|
Xml = 7, /**< the XML header must identify the DTD or schemas */
|
|
|
|
Uuid = 8, /**< also known as GUID; stored as 16 bytes in binary (valid as an ID) */
|
|
|
|
Isrc = 9, /**< stored as UTF-8 text (valid as an ID) */
|
|
|
|
Mi3p = 10, /**< stored as UTF-8 text (valid as an ID) */
|
|
|
|
Gif = 12, /**< (deprecated) a GIF image */
|
|
|
|
Jpeg = 13, /**< in a JFIF wrapper */
|
|
|
|
Png = 14, /**< in a PNG wrapper */
|
|
|
|
Url = 15, /**< absolute, in UTF-8 characters */
|
|
|
|
Duration = 16, /**< in milliseconds, 32-bit integer */
|
|
|
|
DateTime = 17, /**< in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits */
|
|
|
|
Genred = 18, /**< a list of enumerated values */
|
|
|
|
BeSignedInt = 21, /**< the size of the integer is derived from the container size (max 4 byte assumed) */
|
|
|
|
BeUnsignedInt = 22, /**< the size of the integer is derived from the container size (max 4 byte assumed) */
|
|
|
|
BeFloat32 = 23, /**< IEEE754 */
|
|
|
|
BeFloat64 = 24, /**< IEEE754 */
|
|
|
|
Upc = 25, /**< Universal Product Code, in text UTF-8 format (valid as an ID) */
|
|
|
|
Bmp = 27, /**< windows bitmap format graphics */
|
|
|
|
QuickTimeMetadataAtom = 28, /**< a block of data having the structure of the Metadata atom defined in this specification */
|
|
|
|
Undefined = 255 /**< a undefined */
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
class Mp4TagField;
|
2018-03-05 17:49:29 +01:00
|
|
|
class Diagnostics;
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Defines traits for the TagField implementation of the Mp4TagField class.
|
|
|
|
*/
|
2018-03-07 01:17:50 +01:00
|
|
|
template <> class TAG_PARSER_EXPORT TagFieldTraits<Mp4TagField> {
|
2015-04-22 19:22:01 +02:00
|
|
|
public:
|
2019-03-13 19:06:42 +01:00
|
|
|
using IdentifierType = std::uint32_t;
|
|
|
|
using TypeInfoType = std::uint32_t;
|
2015-04-22 19:22:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class Mp4Atom;
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT Mp4TagFieldMaker {
|
2015-12-10 13:50:46 +01:00
|
|
|
friend class Mp4TagField;
|
|
|
|
|
|
|
|
public:
|
2021-01-29 23:21:38 +01:00
|
|
|
Mp4TagFieldMaker(Mp4TagFieldMaker &&) = default;
|
2015-12-10 13:50:46 +01:00
|
|
|
void make(std::ostream &stream);
|
|
|
|
const Mp4TagField &field() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t requiredSize() const;
|
2015-12-10 13:50:46 +01:00
|
|
|
|
|
|
|
private:
|
2021-01-29 23:21:38 +01:00
|
|
|
/// \cond
|
|
|
|
struct Data {
|
|
|
|
Data();
|
|
|
|
Data(Data &&) = default;
|
|
|
|
std::string_view rawData;
|
|
|
|
std::stringstream convertedData;
|
|
|
|
std::uint64_t size = 0;
|
|
|
|
std::uint32_t rawType = 0;
|
|
|
|
std::uint16_t countryIndicator = 0;
|
|
|
|
std::uint16_t languageIndicator = 0;
|
|
|
|
};
|
|
|
|
/// \endcond
|
|
|
|
|
2018-03-05 17:49:29 +01:00
|
|
|
Mp4TagFieldMaker(Mp4TagField &field, Diagnostics &diag);
|
2021-01-29 23:21:38 +01:00
|
|
|
std::uint64_t prepareDataAtom(
|
|
|
|
const TagValue &value, std::uint16_t countryIndicator, std::uint16_t languageIndicator, const std::string &context, Diagnostics &diag);
|
2015-12-10 13:50:46 +01:00
|
|
|
|
|
|
|
Mp4TagField &m_field;
|
2019-06-10 22:49:11 +02:00
|
|
|
CppUtilities::BinaryWriter m_writer;
|
2021-01-29 23:21:38 +01:00
|
|
|
std::vector<Data> m_data;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t m_totalSize;
|
2015-12-10 13:50:46 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the associated field.
|
|
|
|
*/
|
|
|
|
inline const Mp4TagField &Mp4TagFieldMaker::field() const
|
|
|
|
{
|
|
|
|
return m_field;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns number of bytes which will be written when making the field.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t Mp4TagFieldMaker::requiredSize() const
|
2015-12-10 13:50:46 +01:00
|
|
|
{
|
2018-03-07 01:17:50 +01:00
|
|
|
return m_totalSize;
|
2015-12-10 13:50:46 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT Mp4TagField : public TagField<Mp4TagField> {
|
2015-04-22 19:22:01 +02:00
|
|
|
friend class TagField<Mp4TagField>;
|
|
|
|
|
|
|
|
public:
|
2021-01-29 23:21:38 +01:00
|
|
|
struct AdditionalData {
|
|
|
|
TagValue value;
|
|
|
|
std::uint32_t rawDataType = 0;
|
|
|
|
std::uint16_t countryIndicator = 0;
|
|
|
|
std::uint16_t languageIndicator = 0;
|
|
|
|
};
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
Mp4TagField();
|
2017-03-07 17:16:17 +01:00
|
|
|
Mp4TagField(IdentifierType id, const TagValue &value);
|
2021-01-30 21:53:06 +01:00
|
|
|
Mp4TagField(std::string_view mean, std::string_view name, const TagValue &value);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-05 17:49:29 +01:00
|
|
|
void reparse(Mp4Atom &ilstChild, Diagnostics &diag);
|
|
|
|
Mp4TagFieldMaker prepareMaking(Diagnostics &diag);
|
|
|
|
void make(std::ostream &stream, Diagnostics &diag);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2021-01-29 23:21:38 +01:00
|
|
|
const std::vector<AdditionalData> &additionalData() const;
|
|
|
|
std::vector<AdditionalData> &additionalData();
|
2015-04-22 19:22:01 +02:00
|
|
|
bool isAdditionalTypeInfoUsed() const;
|
|
|
|
const std::string &name() const;
|
|
|
|
void setName(const std::string &name);
|
|
|
|
const std::string &mean() const;
|
|
|
|
void setMean(const std::string &mean);
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint32_t parsedRawDataType() const;
|
|
|
|
std::uint16_t countryIndicator() const;
|
|
|
|
std::uint16_t languageIndicator() const;
|
2015-04-22 19:22:01 +02:00
|
|
|
bool supportsNestedFields() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::vector<std::uint32_t> expectedRawDataTypes() const;
|
|
|
|
std::uint32_t appropriateRawDataType() const;
|
2021-01-29 23:21:38 +01:00
|
|
|
std::uint32_t appropriateRawDataTypeForValue(const TagValue &value) const;
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2021-01-30 21:53:06 +01:00
|
|
|
static IdentifierType fieldIdFromString(std::string_view idString);
|
2017-03-07 17:16:17 +01:00
|
|
|
static std::string fieldIdToString(IdentifierType id);
|
2017-01-23 00:25:53 +01:00
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
private:
|
2021-01-30 18:25:46 +01:00
|
|
|
void internallyClearValue();
|
|
|
|
void internallyClearFurtherData();
|
2015-04-22 19:22:01 +02:00
|
|
|
std::string m_name;
|
|
|
|
std::string m_mean;
|
2021-01-29 23:21:38 +01:00
|
|
|
std::vector<AdditionalData> m_additionalData;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint32_t m_parsedRawDataType;
|
|
|
|
std::uint16_t m_countryIndicator;
|
|
|
|
std::uint16_t m_langIndicator;
|
2015-04-22 19:22:01 +02:00
|
|
|
};
|
|
|
|
|
2021-01-29 23:21:38 +01:00
|
|
|
/*!
|
|
|
|
* \brief Returns additional data (and the corresponding raw data type, country and language).
|
|
|
|
* \remarks Some files seen in the wild have multiple data atoms. This function allows to access the data from additional atoms.
|
|
|
|
*/
|
|
|
|
inline const std::vector<Mp4TagField::AdditionalData> &Mp4TagField::additionalData() const
|
|
|
|
{
|
|
|
|
return m_additionalData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns additional data (and the corresponding raw data type, country and language).
|
|
|
|
* \remarks Some files seen in the wild have multiple data atoms. This function allows to access the data from additional atoms.
|
|
|
|
*/
|
|
|
|
inline std::vector<Mp4TagField::AdditionalData> &Mp4TagField::additionalData()
|
|
|
|
{
|
|
|
|
return m_additionalData;
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns whether the additional type info is used.
|
|
|
|
*/
|
|
|
|
inline bool Mp4TagField::isAdditionalTypeInfoUsed() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the "name" for "extended" fields.
|
|
|
|
*/
|
|
|
|
inline const std::string &Mp4TagField::name() const
|
|
|
|
{
|
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets the "name" for the "extended" field.
|
|
|
|
*/
|
|
|
|
inline void Mp4TagField::setName(const std::string &name)
|
|
|
|
{
|
|
|
|
m_name = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the "mean" for "extended" fields.
|
|
|
|
*/
|
|
|
|
inline const std::string &Mp4TagField::mean() const
|
|
|
|
{
|
|
|
|
return m_mean;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets the "mean" for the "extended" field.
|
|
|
|
*/
|
|
|
|
inline void Mp4TagField::setMean(const std::string &mean)
|
|
|
|
{
|
|
|
|
m_mean = mean;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the raw data type which has been determined when parsing.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint32_t Mp4TagField::parsedRawDataType() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_parsedRawDataType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the country indicator.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint16_t Mp4TagField::countryIndicator() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_countryIndicator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the language indicator.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint16_t Mp4TagField::languageIndicator() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_langIndicator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns whether nested fields are supported.
|
|
|
|
*/
|
|
|
|
inline bool Mp4TagField::supportsNestedFields() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-23 00:25:53 +01:00
|
|
|
/*!
|
|
|
|
* \brief Converts the specified ID string representation to an actual ID.
|
|
|
|
* \remarks The specified \a idString is assumed to be UTF-8 encoded. In order to get the ©-sign
|
|
|
|
* correctly, it is converted to Latin-1.
|
|
|
|
*/
|
2021-01-30 21:53:06 +01:00
|
|
|
inline Mp4TagField::IdentifierType Mp4TagField::fieldIdFromString(std::string_view idString)
|
2017-01-23 00:25:53 +01:00
|
|
|
{
|
2021-01-30 21:53:06 +01:00
|
|
|
const auto latin1 = CppUtilities::convertUtf8ToLatin1(idString.data(), idString.size());
|
2018-03-07 01:17:50 +01:00
|
|
|
switch (latin1.second) {
|
2017-01-23 00:25:53 +01:00
|
|
|
case 4:
|
2019-06-10 22:49:11 +02:00
|
|
|
return CppUtilities::BE::toUInt32(latin1.first.get());
|
2017-01-23 00:25:53 +01:00
|
|
|
default:
|
2019-06-10 22:49:11 +02:00
|
|
|
throw CppUtilities::ConversionException("MP4 ID must be exactly 4 chars");
|
2017-01-23 00:25:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the string representation for the specified \a id.
|
|
|
|
* \remarks The specified \a id is considered Latin-1 encoded. In order to get the ©-sign
|
|
|
|
* correctly, it is converted to UTF-8.
|
|
|
|
*/
|
2017-03-07 17:16:17 +01:00
|
|
|
inline std::string Mp4TagField::fieldIdToString(Mp4TagField::IdentifierType id)
|
2017-01-23 00:25:53 +01:00
|
|
|
{
|
2019-06-10 22:49:11 +02:00
|
|
|
const auto utf8 = CppUtilities::convertLatin1ToUtf8(CppUtilities::interpretIntegerAsString<std::uint32_t>(id).data(), 4);
|
2017-01-23 00:25:53 +01:00
|
|
|
return std::string(utf8.first.get(), utf8.second);
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
} // namespace TagParser
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-06 23:09:15 +01:00
|
|
|
#endif // TAG_PARSER_MP4TAGATOM_H
|