Tag Parser: matroska/matroskaattachment.cpp Source File

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.
1#include "./matroskaattachment.h"
2#include "./ebmlelement.h"
3#include "./matroskacontainer.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
30 void MatroskaAttachment::parse(EbmlElement *attachedFileElement, Diagnostics &diag)
31{
32 clear();
33 static const string context("parsing \"AttachedFile\"-element");
34 m_attachedFileElement = attachedFileElement;
35 EbmlElement *subElement = attachedFileElement->firstChild();
36 while (subElement) {
37 subElement->parse(diag);
38 switch (subElement->id()) {
39 case MatroskaIds::FileDescription:
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;
46 case MatroskaIds::FileName:
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;
53 case MatroskaIds::FileMimeType:
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;
60 case MatroskaIds::FileData:
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;
68 case MatroskaIds::FileUID:
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;
75 case MatroskaIds::FileReferral:
76 case MatroskaIds::FileUsedStartTime:
77 case MatroskaIds::FileUsedEndTime:
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
95 void 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");
99 throw InvalidDataException();
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
120 + EbmlElement::calculateUIntegerLength(attachment.id());
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>{
131 MatroskaIds::FileReferral, MatroskaIds::FileUsedStartTime, MatroskaIds::FileUsedEndTime }) {
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
147 void 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
155 EbmlElement::makeSimpleElement(stream, MatroskaIds::FileName, attachment().name());
156 if (!attachment().description().empty()) {
157 EbmlElement::makeSimpleElement(stream, MatroskaIds::FileDescription, attachment().description());
158 }
159 EbmlElement::makeSimpleElement(stream, MatroskaIds::FileMimeType, attachment().mimeType());
160 EbmlElement::makeSimpleElement(stream, MatroskaIds::FileUID, attachment().id());
161 if (attachment().attachedFileElement()) {
162 EbmlElement *child;
163 for (auto id : initializer_list<EbmlElement::IdentifierType>{
164 MatroskaIds::FileReferral, MatroskaIds::FileUsedStartTime, MatroskaIds::FileUsedEndTime }) {
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
183 void MatroskaAttachmentMaker::bufferCurrentAttachments(Diagnostics &diag)
184{
185 EbmlElement *child;
186 if (attachment().attachedFileElement()) {
187 for (auto id : initializer_list<EbmlElement::IdentifierType>{
188 MatroskaIds::FileReferral, MatroskaIds::FileUsedStartTime, MatroskaIds::FileUsedEndTime }) {
189 if ((child = attachment().attachedFileElement()->childById(id, diag))) {
190 child->makeBuffer();
191 }
192 }
193 }
194 if (attachment().data() && attachment().data()->size() && !attachment().isDataFromFile()) {
195 attachment().data()->makeBuffer();
196 }
197}
198
199} // namespace TagParser
TagParser::AbstractAttachment::setDescription
void setDescription(std::string_view description)
Sets a description of the attachment.
Definition abstractattachment.h:153
TagParser::AbstractAttachment::clear
void clear()
Resets the object to its initial state.
Definition abstractattachment.cpp:169
TagParser::AbstractAttachment::mimeType
const std::string & mimeType() const
Returns the MIME-type of the attachment.
Definition abstractattachment.h:177
TagParser::AbstractAttachment::description
const std::string & description() const
Returns a description of the attachment.
Definition abstractattachment.h:145
TagParser::AbstractAttachment::setData
void setData(std::unique_ptr< StreamDataBlock > &&data)
Sets the data for the attachment.
Definition abstractattachment.h:223
TagParser::AbstractAttachment::name
const std::string & name() const
Returns the (file) name of the attachment.
Definition abstractattachment.h:161
TagParser::AbstractAttachment::id
std::uint64_t id() const
Returns the ID of the attachment.
Definition abstractattachment.h:193
TagParser::AbstractAttachment::setName
void setName(std::string_view name)
Sets the (file) name of the attachment.
Definition abstractattachment.h:169
TagParser::AbstractAttachment::setId
void setId(std::uint64_t id)
Sets the ID of the attachment.
Definition abstractattachment.h:201
TagParser::AbstractAttachment::data
const StreamDataBlock * data() const
Returns a reference to the data of the attachment.
Definition abstractattachment.h:213
TagParser::AbstractAttachment::setMimeType
void setMimeType(std::string_view mimeType)
Sets the MIME-type of the attachment.
Definition abstractattachment.h:185
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition diagnostics.h:156
TagParser::EbmlElement
The EbmlElement class helps to parse EBML files such as Matroska files.
Definition ebmlelement.h:32
TagParser::EbmlElement::makeSimpleElement
static void makeSimpleElement(std::ostream &stream, IdentifierType id, std::uint64_t content)
Makes a simple EBML element.
Definition ebmlelement.cpp:514
TagParser::EbmlElement::calculateSizeDenotationLength
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
Definition ebmlelement.cpp:288
TagParser::EbmlElement::idToString
std::string idToString() const
Converts the specified EBML ID to a printable string.
Definition ebmlelement.h:71
TagParser::EbmlElement::readString
std::string readString()
Reads the content of the element as string.
Definition ebmlelement.cpp:226
TagParser::EbmlElement::readUInteger
std::uint64_t readUInteger()
Reads the content of the element as unsigned integer.
Definition ebmlelement.cpp:238
TagParser::EbmlElement::makeSizeDenotation
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
Definition ebmlelement.cpp:343
TagParser::EbmlElement::calculateUIntegerLength
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
Definition ebmlelement.cpp:416
TagParser::GenericFileElement::copyEntirely
void copyEntirely(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
Definition genericfileelement.h:877
TagParser::GenericFileElement::copyBuffer
void copyBuffer(TargetStream &targetStream)
Copies buffered data to targetStream.
Definition genericfileelement.h:907
TagParser::GenericFileElement::startOffset
std::uint64_t startOffset() const
Returns the start offset in the related stream.
Definition genericfileelement.h:266
TagParser::GenericFileElement::buffer
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
Definition genericfileelement.h:928
TagParser::GenericFileElement::id
const IdentifierType & id() const
Returns the element ID.
Definition genericfileelement.h:283
TagParser::GenericFileElement< EbmlElement >::stream
std::iostream & stream()
Definition genericfileelement.h:242
TagParser::GenericFileElement::childById
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
Definition genericfileelement.h:610
TagParser::GenericFileElement::nextSibling
ImplementationType * nextSibling()
Returns the next sibling of the element.
Definition genericfileelement.h:439
TagParser::GenericFileElement::totalSize
std::uint64_t totalSize() const
Returns the total size of the element.
Definition genericfileelement.h:348
TagParser::GenericFileElement::parse
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
Definition genericfileelement.h:779
TagParser::GenericFileElement::dataOffset
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
Definition genericfileelement.h:338
TagParser::GenericFileElement::makeBuffer
void makeBuffer()
Buffers the element (header and data).
Definition genericfileelement.h:886
TagParser::InvalidDataException
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
Definition exceptions.h:25
TagParser::MatroskaAttachmentMaker::attachment
const MatroskaAttachment & attachment() const
Returns the associated attachment.
Definition matroskaattachment.h:31
TagParser::MatroskaAttachmentMaker::make
void make(std::ostream &stream, Diagnostics &diag) const
Saves the attachment (specified when constructing the object) to the specified stream (makes an "Atta...
Definition matroskaattachment.cpp:147
TagParser::MatroskaAttachmentMaker::bufferCurrentAttachments
void bufferCurrentAttachments(Diagnostics &diag)
Definition matroskaattachment.cpp:183
TagParser::MatroskaAttachment
Implementation of TagParser::AbstractAttachment for the Matroska container.
Definition matroskaattachment.h:44
TagParser::MatroskaAttachment::attachedFileElement
EbmlElement * attachedFileElement() const
Returns the "AttachedFile"-element which has been specified when the parse() method has been called.
Definition matroskaattachment.h:69
TagParser::MatroskaAttachment::make
void make(std::ostream &stream, Diagnostics &diag)
Writes the attachment to the specified stream (makes an "AttachedFile"-element).
Definition matroskaattachment.cpp:95
TagParser::MatroskaAttachment::prepareMaking
MatroskaAttachmentMaker prepareMaking(Diagnostics &diag)
Prepares making.
Definition matroskaattachment.h:84
TagParser::MatroskaAttachment::parse
void parse(EbmlElement *attachedFileElement, Diagnostics &diag)
Parses attachment from the specified attachedFileElement.
Definition matroskaattachment.cpp:30
TagParser::StreamDataBlock::makeBuffer
void makeBuffer() const
Buffers the data block.
Definition abstractattachment.cpp:73
TagParser::StreamDataBlock::size
std::uint64_t size() const
Returns the size of the data block.
Definition abstractattachment.h:69
TagParser::StreamDataBlock::copyTo
void copyTo(std::ostream &stream) const
Copies the data to the specified stream.
Definition abstractattachment.cpp:84
ebmlelement.h
matroskaattachment.h
matroskacontainer.h
matroskaid.h
mediafileinfo.h
CppUtilities
Definition abstractcontainer.h:16
TagParser::EbmlIds::Void
@ Void
Definition ebmlid.h:28
TagParser::EbmlIds::Crc32
@ Crc32
Definition ebmlid.h:28
TagParser::MatroskaIds::FileDescription
@ FileDescription
Definition matroskaid.h:283
TagParser::MatroskaIds::FileUsedStartTime
@ FileUsedStartTime
Definition matroskaid.h:289
TagParser::MatroskaIds::FileReferral
@ FileReferral
Definition matroskaid.h:288
TagParser::MatroskaIds::FileName
@ FileName
Definition matroskaid.h:284
TagParser::MatroskaIds::FileMimeType
@ FileMimeType
Definition matroskaid.h:285
TagParser::MatroskaIds::FileUsedEndTime
@ FileUsedEndTime
Definition matroskaid.h:290
TagParser::MatroskaIds::FileUID
@ FileUID
Definition matroskaid.h:287
TagParser::MatroskaIds::FileData
@ FileData
Definition matroskaid.h:286
TagParser::MatroskaIds::AttachedFile
@ AttachedFile
Definition matroskaid.h:277
TagParser
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TagParser::DiagLevel::Warning
@ Warning
Definition diagnostics.h:20
TagParser::DiagLevel::Critical
@ Critical
Definition diagnostics.h:21