Skip to content

Commit 4810495

Browse files
committed
Integrate cues, fix element rendering and resizing
1 parent c817cc0 commit 4810495

21 files changed

Lines changed: 316 additions & 125 deletions

taglib/matroska/ebml/ebmlelement.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ namespace TagLib::EBML {
130130
class MkTags;
131131
class MkAttachments;
132132
class MkSeekHead;
133+
class MkCues;
133134
class VoidElement;
134135

135136
template <String::Type t>
@@ -157,7 +158,7 @@ namespace TagLib::EBML {
157158
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
158159
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
159160
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
160-
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MasterElement; };
161+
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
161162
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
162163
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
163164
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };

taglib/matroska/ebml/ebmlmkcues.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424

2525
using namespace TagLib;
2626

27-
Matroska::Cues *EBML::MkCues::parse()
27+
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
2828
{
29-
auto cues = new Matroska::Cues();
29+
auto cues = std::make_unique<Matroska::Cues>(segmentDataOffset);
3030
cues->setOffset(offset);
3131
cues->setSize(getSize());
3232
cues->setID(static_cast<Matroska::Element::ID>(id));

taglib/matroska/ebml/ebmlmkcues.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ namespace TagLib {
3939
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
4040
{
4141
}
42+
MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset) :
43+
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
44+
{
45+
}
4246
MkCues() :
4347
MasterElement(Id::MkCues, 0, 0, 0)
4448
{
4549
}
4650

47-
Matroska::Cues *parse();
51+
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset);
4852
};
4953
}
5054
}

taglib/matroska/ebml/ebmlmkseekhead.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525

2626
using namespace TagLib;
2727

28-
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse()
28+
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset)
2929
{
30-
auto seekHead = std::make_unique<Matroska::SeekHead>();
30+
auto seekHead = std::make_unique<Matroska::SeekHead>(segmentDataOffset);
3131
seekHead->setOffset(offset);
3232
seekHead->setSize(getSize() + padding);
3333

taglib/matroska/ebml/ebmlmkseekhead.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace TagLib {
4646
{
4747
}
4848

49-
std::unique_ptr<Matroska::SeekHead> parse();
49+
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset);
5050
};
5151
}
5252
}

taglib/matroska/ebml/ebmlmksegment.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@
2828
#include "matroskafile.h"
2929
#include "matroskatag.h"
3030
#include "matroskaattachments.h"
31+
#include "matroskacues.h"
3132
#include "matroskaseekhead.h"
3233
#include "matroskasegment.h"
3334

3435
using namespace TagLib;
3536

3637
EBML::MkSegment::~MkSegment() = default;
3738

39+
offset_t EBML::MkSegment::segmentDataOffset() const
40+
{
41+
return offset + idSize(id) + sizeLength;
42+
}
43+
3844
bool EBML::MkSegment::read(File &file)
3945
{
4046
offset_t maxOffset = file.tell() + dataSize;
@@ -49,6 +55,11 @@ bool EBML::MkSegment::read(File &file)
4955
if(!seekHead->read(file))
5056
return false;
5157
}
58+
else if(id == Id::MkCues) {
59+
cues = element_cast<Id::MkCues>(std::move(element));
60+
if(!cues->read(file))
61+
return false;
62+
}
5263
else if(id == Id::MkInfo) {
5364
info = element_cast<Id::MkInfo>(std::move(element));
5465
if(!info->read(file))
@@ -94,7 +105,12 @@ std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments()
94105

95106
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead()
96107
{
97-
return seekHead ? seekHead->parse() : nullptr;
108+
return seekHead ? seekHead->parse(segmentDataOffset()) : nullptr;
109+
}
110+
111+
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues()
112+
{
113+
return cues ? cues->parse(segmentDataOffset()) : nullptr;
98114
}
99115

100116
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment()

taglib/matroska/ebml/ebmlmksegment.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "ebmlmktags.h"
2727
#include "ebmlmkattachments.h"
2828
#include "ebmlmkseekhead.h"
29+
#include "ebmlmkcues.h"
2930
#include "ebmlmkinfo.h"
3031
#include "ebmlmktracks.h"
3132
#include "taglib.h"
@@ -50,10 +51,12 @@ namespace TagLib {
5051
{
5152
}
5253
~MkSegment() override;
54+
offset_t segmentDataOffset() const;
5355
bool read(File &file) override;
5456
std::unique_ptr<Matroska::Tag> parseTag();
5557
std::unique_ptr<Matroska::Attachments> parseAttachments();
5658
std::unique_ptr<Matroska::SeekHead> parseSeekHead();
59+
std::unique_ptr<Matroska::Cues> parseCues();
5760
std::unique_ptr<Matroska::Segment> parseSegment();
5861
void parseInfo(Matroska::Properties *properties);
5962
void parseTracks(Matroska::Properties *properties);
@@ -62,6 +65,7 @@ namespace TagLib {
6265
std::unique_ptr<MkTags> tags;
6366
std::unique_ptr<MkAttachments> attachments;
6467
std::unique_ptr<MkSeekHead> seekHead;
68+
std::unique_ptr<MkCues> cues;
6569
std::unique_ptr<MkInfo> info;
6670
std::unique_ptr<MkTracks> tracks;
6771
};

taglib/matroska/matroskaattachments.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Matroska::Attachments::~Attachments() = default;
5656
void Matroska::Attachments::addAttachedFile(const AttachedFile& file)
5757
{
5858
d->files.append(file);
59+
setNeedsRender(true);
5960
}
6061

6162
void Matroska::Attachments::removeAttachedFile(unsigned long long uid)
@@ -66,12 +67,14 @@ void Matroska::Attachments::removeAttachedFile(unsigned long long uid)
6667
});
6768
if(it != d->files.end()) {
6869
d->files.erase(it);
70+
setNeedsRender(true);
6971
}
7072
}
7173

7274
void Matroska::Attachments::clear()
7375
{
7476
d->files.clear();
77+
setNeedsRender(true);
7578
}
7679

7780
const Matroska::Attachments::AttachedFileList &Matroska::Attachments::attachedFileList() const
@@ -85,11 +88,17 @@ const Matroska::Attachments::AttachedFileList &Matroska::Attachments::attachedFi
8588

8689
Matroska::Attachments::AttachedFileList &Matroska::Attachments::attachedFiles()
8790
{
91+
setNeedsRender(true);
8892
return d->files;
8993
}
9094

91-
bool Matroska::Attachments::render()
95+
ByteVector Matroska::Attachments::renderInternal()
9296
{
97+
if(d->files.isEmpty()) {
98+
// Avoid writing an Attachments element without AttachedFile element.
99+
return {};
100+
}
101+
93102
EBML::MkAttachments attachments;
94103
for(const auto &attachedFile : std::as_const(d->files)) {
95104
auto attachedFileElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFile>();
@@ -127,14 +136,5 @@ bool Matroska::Attachments::render()
127136

128137
attachments.appendElement(std::move(attachedFileElement));
129138
}
130-
131-
auto beforeSize = size();
132-
auto data = attachments.render();
133-
auto afterSize = data.size();
134-
if(beforeSize != afterSize) {
135-
if(!emitSizeChanged(afterSize - beforeSize))
136-
return false;
137-
}
138-
setData(data);
139-
return true;
139+
return attachments.render();
140140
}

taglib/matroska/matroskaattachments.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace TagLib {
4747
Attachments();
4848

4949
//! Destroy attachements.
50-
~Attachments();
50+
virtual ~Attachments();
5151

5252
//! Add an attached file.
5353
void addAttachedFile(const AttachedFile &file);
@@ -67,7 +67,7 @@ namespace TagLib {
6767
class AttachmentsPrivate;
6868

6969
// private Element implementation
70-
bool render() override;
70+
ByteVector renderInternal() override;
7171
AttachedFileList &attachedFiles();
7272

7373
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE

taglib/matroska/matroskacues.cpp

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@
2929

3030
using namespace TagLib;
3131

32-
Matroska::Cues::Cues() :
33-
Element(static_cast<ID>(EBML::Element::Id::MkCues))
32+
Matroska::Cues::Cues(offset_t segmentDataOffset) :
33+
Element(static_cast<ID>(EBML::Element::Id::MkCues)),
34+
segmentDataOffset(segmentDataOffset)
3435
{
36+
setNeedsRender(false);
3537
}
3638

3739
ByteVector Matroska::Cues::renderInternal()
3840
{
41+
auto beforeSize = sizeRenderedOrWritten();
3942
EBML::MkCues cues;
43+
cues.setMinRenderSize(beforeSize);
4044
for(const auto &cuePoint : cuePoints) {
4145
auto cuePointElement = EBML::make_unique_element<EBML::Element::Id::MkCuePoint>();
4246
auto timestamp = EBML::make_unique_element<EBML::Element::Id::MkCueTime>();
@@ -57,7 +61,33 @@ ByteVector Matroska::Cues::renderInternal()
5761
clusterPosition->setValue(cueTrack->getClusterPosition());
5862
cueTrackElement->appendElement(std::move(clusterPosition));
5963

60-
// Todo - other elements
64+
// Relative position, optional
65+
if(cueTrack->getRelativePosition().has_value()) {
66+
auto relativePosition = EBML::make_unique_element<EBML::Element::Id::MkCueRelativePosition>();
67+
relativePosition->setValue(cueTrack->getRelativePosition().value());
68+
cueTrackElement->appendElement(std::move(relativePosition));
69+
}
70+
71+
// Duration, optional
72+
if(cueTrack->getDuration().has_value()) {
73+
auto duration = EBML::make_unique_element<EBML::Element::Id::MkCueDuration>();
74+
duration->setValue(cueTrack->getDuration().value());
75+
cueTrackElement->appendElement(std::move(duration));
76+
}
77+
78+
// Block number, optional
79+
if(cueTrack->getBlockNumber().has_value()) {
80+
auto blockNumber = EBML::make_unique_element<EBML::Element::Id::MkCueBlockNumber>();
81+
blockNumber->setValue(cueTrack->getBlockNumber().value());
82+
cueTrackElement->appendElement(std::move(blockNumber));
83+
}
84+
85+
// Codec state, not in version 1
86+
if(cueTrack->getCodecState().has_value()) {
87+
auto codecState = EBML::make_unique_element<EBML::Element::Id::MkCueCodecState>();
88+
codecState->setValue(cueTrack->getCodecState().value());
89+
cueTrackElement->appendElement(std::move(codecState));
90+
}
6191

6292
// Reference times
6393
auto referenceTimes = cueTrack->referenceTimes();
@@ -72,29 +102,33 @@ ByteVector Matroska::Cues::renderInternal()
72102
}
73103
cuePointElement->appendElement(std::move(cueTrackElement));
74104
}
105+
cues.appendElement(std::move(cuePointElement));
75106
}
76107
return cues.render();
77108
}
78109

79-
bool Matroska::Cues::render()
110+
void Matroska::Cues::write(TagLib::File& file)
80111
{
81-
if(!needsRender)
82-
return true;
83-
84-
setData(renderInternal());
85-
needsRender = false;
86-
return true;
112+
if(!data().isEmpty())
113+
Element::write(file);
87114
}
88115

89116
bool Matroska::Cues::sizeChanged(Element &caller, offset_t delta)
90117
{
91-
offset_t offset = caller.offset();
92-
for(auto &cuePoint : cuePoints)
93-
needsRender |= cuePoint->adjustOffset(offset, delta);
118+
// Adjust own offset
119+
if(!Element::sizeChanged(caller, delta))
120+
return false;
121+
122+
offset_t offset = caller.offset() - segmentDataOffset;
123+
for(auto &cuePoint : cuePoints) {
124+
if(cuePoint->adjustOffset(offset, delta)) {
125+
setNeedsRender(true);
126+
}
127+
}
94128
return true;
95129
}
96130

97-
bool Matroska::Cues::isValid(TagLib::File &file, offset_t segmentDataOffset) const
131+
bool Matroska::Cues::isValid(TagLib::File &file) const
98132
{
99133
for(const auto &cuePoint : cuePoints) {
100134
if(!cuePoint->isValid(file, segmentDataOffset))
@@ -150,8 +184,8 @@ bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset)
150184
debug("No cluster found at position");
151185
return false;
152186
}
153-
if(codecState) {
154-
file.seek(segmentDataOffset + codecState);
187+
if(codecState.has_value() && codecState.value() != 0) {
188+
file.seek(segmentDataOffset + codecState.value());
155189
if(EBML::Element::readId(file) != static_cast<unsigned int>(EBML::Element::Id::MkCodecState)) {
156190
debug("No codec state found at position");
157191
return false;
@@ -160,8 +194,18 @@ bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset)
160194
return true;
161195
}
162196

163-
bool Matroska::CueTrack::adjustOffset(offset_t, offset_t)
197+
bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta)
164198
{
165-
// TODO implement
166-
return false;
199+
bool ret = false;
200+
if(clusterPosition > offset) {
201+
clusterPosition += delta;
202+
ret = true;
203+
}
204+
offset_t codecStateValue;
205+
if(codecState.has_value() && (codecStateValue = codecState.value()) != 0 &&
206+
codecStateValue > offset) {
207+
codecState = codecStateValue + delta;
208+
ret = true;
209+
}
210+
return ret;
167211
}

0 commit comments

Comments
 (0)