Tag Parser 12.5.3
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Loading...
Searching...
No Matches
matroskaattachment.cpp
Go to the documentation of this file.
2#include "./ebmlelement.h"
4#include "./matroskaid.h"
5
6#include "../mediafileinfo.h"
7
8#include <c++utilities/conversion/binaryconversion.h>
9#include <c++utilities/conversion/stringbuilder.h>
10
11#include <memory>
12
13using namespace std;
14using namespace CppUtilities;
15
16namespace TagParser {
17
22
31{
32 clear();
33 static const string context("parsing \"AttachedFile\"-element");
34 m_attachedFileElement = attachedFileElement;
36 while (subElement) {
37 subElement->parse(diag);
38 switch (subElement->id()) {
40 if (description().empty()) {
41 setDescription(subElement->readString());
42 } else {
43 diag.emplace_back(DiagLevel::Warning, "Multiple \"FileDescription\"-elements found. Surplus elements will be ignored.", context);
44 }
45 break;
47 if (name().empty()) {
48 setName(subElement->readString());
49 } else {
50 diag.emplace_back(DiagLevel::Warning, "Multiple \"FileName\"-elements found. Surplus elements will be ignored.", context);
51 }
52 break;
54 if (mimeType().empty()) {
55 setMimeType(subElement->readString());
56 } else {
57 diag.emplace_back(DiagLevel::Warning, "Multiple \"FileMimeType\"-elements found. Surplus elements will be ignored.", context);
58 }
59 break;
61 if (data()) {
62 diag.emplace_back(DiagLevel::Warning, "Multiple \"FileData\"-elements found. Surplus elements will be ignored.", context);
63 } else {
64 setData(make_unique<StreamDataBlock>(std::bind(&EbmlElement::stream, subElement), subElement->dataOffset(), ios_base::beg,
65 subElement->startOffset() + subElement->totalSize(), ios_base::beg));
66 }
67 break;
69 if (id()) {
70 diag.emplace_back(DiagLevel::Warning, "Multiple \"FileUID\"-elements found. Surplus elements will be ignored.", context);
71 } else {
72 setId(subElement->readUInteger());
73 }
74 break;
78 case EbmlIds::Crc32:
79 case EbmlIds::Void:
80 break;
81 default:
82 diag.emplace_back(DiagLevel::Warning, "Unknown child element \"" % subElement->idToString() + "\" found.", context);
83 }
84 subElement = subElement->nextSibling();
85 }
86}
87
95void MatroskaAttachment::make(std::ostream &stream, Diagnostics &diag)
96{
97 if (!data() || !data()->size()) {
98 diag.emplace_back(DiagLevel::Critical, "There is no data assigned.", "making Matroska attachment");
100 }
101 prepareMaking(diag).make(stream, diag);
102}
103
110
115MatroskaAttachmentMaker::MatroskaAttachmentMaker(MatroskaAttachment &attachment, Diagnostics &diag)
116 : m_attachment(attachment)
117{
118 m_attachedFileElementSize = 2 + EbmlElement::calculateSizeDenotationLength(attachment.name().size()) + attachment.name().size() + 2
119 + EbmlElement::calculateSizeDenotationLength(attachment.mimeType().size()) + attachment.mimeType().size() + 2 + 1
121 if (auto dataSize = attachment.data() ? attachment.data()->size() : static_cast<std::uint64_t>(0)) {
122 m_attachedFileElementSize += 2 + EbmlElement::calculateSizeDenotationLength(dataSize) + dataSize;
123 }
124 if (!attachment.description().empty()) {
125 m_attachedFileElementSize
126 += 2 + EbmlElement::calculateSizeDenotationLength(attachment.description().size()) + attachment.description().size();
127 }
128 if (attachment.attachedFileElement()) {
129 EbmlElement *child;
130 for (auto id : initializer_list<EbmlElement::IdentifierType>{
132 if ((child = attachment.attachedFileElement()->childById(id, diag))) {
133 m_attachedFileElementSize += child->totalSize();
134 }
135 }
136 }
137 m_totalSize = 2 + EbmlElement::calculateSizeDenotationLength(m_attachedFileElementSize) + m_attachedFileElementSize;
138}
139
147void MatroskaAttachmentMaker::make(ostream &stream, Diagnostics &diag) const
148{
149 char buff[8];
150 BE::getBytes(static_cast<std::uint16_t>(MatroskaIds::AttachedFile), buff);
151 stream.write(buff, 2);
152 std::uint8_t len = EbmlElement::makeSizeDenotation(m_attachedFileElementSize, buff);
153 stream.write(buff, len);
154 // make elements
156 if (!attachment().description().empty()) {
158 }
161 if (attachment().attachedFileElement()) {
162 EbmlElement *child;
163 for (auto id : initializer_list<EbmlElement::IdentifierType>{
165 if ((child = attachment().attachedFileElement()->childById(id, diag))) {
166 if (child->buffer()) {
167 child->copyBuffer(stream);
168 } else {
169 child->copyEntirely(stream, diag, nullptr);
170 }
171 }
172 }
173 }
174 if (attachment().data() && attachment().data()->size()) {
175 BE::getBytes(static_cast<std::uint16_t>(MatroskaIds::FileData), buff);
176 stream.write(buff, 2);
177 len = EbmlElement::makeSizeDenotation(static_cast<std::uint64_t>(attachment().data()->size()), buff);
178 stream.write(buff, len);
179 attachment().data()->copyTo(stream);
180 }
181}
182
184{
185 EbmlElement *child;
186 if (attachment().attachedFileElement()) {
187 for (auto id : initializer_list<EbmlElement::IdentifierType>{
189 if ((child = attachment().attachedFileElement()->childById(id, diag))) {
190 child->makeBuffer();
191 }
192 }
193 }
194 if (attachment().data() && attachment().data()->size() && !attachment().isDataFromFile()) {
196 }
197}
198
199} // namespace TagParser
void setDescription(std::string_view description)
Sets a description of the attachment.
void clear()
Resets the object to its initial state.
const std::string & mimeType() const
Returns the MIME-type of the attachment.
const std::string & description() const
Returns a description of the attachment.
void setData(std::unique_ptr< StreamDataBlock > &&data)
Sets the data for the attachment.
const std::string & name() const
Returns the (file) name of the attachment.
std::uint64_t id() const
Returns the ID of the attachment.
void setName(std::string_view name)
Sets the (file) name of the attachment.
void setId(std::uint64_t id)
Sets the ID of the attachment.
const StreamDataBlock * data() const
Returns a reference to the data of the attachment.
void setMimeType(std::string_view mimeType)
Sets the MIME-type of the attachment.
The Diagnostics class is a container for DiagMessage.
The EbmlElement class helps to parse EBML files such as Matroska files.
Definition ebmlelement.h:32
static void makeSimpleElement(std::ostream &stream, IdentifierType id, std::uint64_t content)
Makes a simple EBML element.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
std::string idToString() const
Converts the specified EBML ID to a printable string.
Definition ebmlelement.h:71
std::string readString()
Reads the content of the element as string.
std::uint64_t readUInteger()
Reads the content of the element as unsigned integer.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
void copyEntirely(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
void copyBuffer(TargetStream &targetStream)
Copies buffered data to targetStream.
std::uint64_t startOffset() const
Returns the start offset in the related stream.
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
const IdentifierType & id() const
Returns the element ID.
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
std::uint64_t totalSize() const
Returns the total size of the element.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
void makeBuffer()
Buffers the element (header and data).
InvalidDataException() noexcept
Constructs a new exception.
const MatroskaAttachment & attachment() const
Returns the associated attachment.
void make(std::ostream &stream, Diagnostics &diag) const
Saves the attachment (specified when constructing the object) to the specified stream (makes an "Atta...
void bufferCurrentAttachments(Diagnostics &diag)
Implementation of TagParser::AbstractAttachment for the Matroska container.
EbmlElement * attachedFileElement() const
Returns the "AttachedFile"-element which has been specified when the parse() method has been called.
void make(std::ostream &stream, Diagnostics &diag)
Writes the attachment to the specified stream (makes an "AttachedFile"-element).
MatroskaAttachmentMaker prepareMaking(Diagnostics &diag)
Prepares making.
void parse(EbmlElement *attachedFileElement, Diagnostics &diag)
Parses attachment from the specified attachedFileElement.
void makeBuffer() const
Buffers the data block.
std::uint64_t size() const
Returns the size of the data block.
void copyTo(std::ostream &stream) const
Copies the data to the specified stream.
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10