mirror of
https://github.com/taglib/taglib.git
synced 2026-02-08 00:10:15 -05:00
Initial cues work
This commit is contained in:
committed by
Urs Fleisch
parent
975eaac3ca
commit
f94843614f
81
taglib/matroska/ebml/ebmlmkcues.cpp
Normal file
81
taglib/matroska/ebml/ebmlmkcues.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkcues.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "matroskafile.h"
|
||||
#include "matroskacues.h"
|
||||
#include "tdebug.h"
|
||||
#include "tutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
Matroska::Cues* EBML::MkCues::parse()
|
||||
{
|
||||
auto cues = new Matroska::Cues();
|
||||
cues->setOffset(offset);
|
||||
cues->setSize(getSize());
|
||||
cues->setID(id);
|
||||
|
||||
for (auto cuesChild : elements) {
|
||||
if (cuesChild->getId() != ElementIDs::MkCuePoint)
|
||||
continue;
|
||||
auto cuePointElement = static_cast<MasterElement*>(cuesChild);
|
||||
auto cuePoint = new Matroska::CuePoint();
|
||||
|
||||
for (auto cuePointChild : *cuePointElement) {
|
||||
Id id = cuePointChild->getId();
|
||||
if (id == ElementIDs::MkCueTime)
|
||||
cuePoint->setTime(static_cast<UIntElement*>(cuePointChild)->getValue());
|
||||
else if (id == ElementIDs::MkCueTrackPositions) {
|
||||
auto cueTrack = new Matroska::CueTrack();
|
||||
auto cueTrackElement = static_cast<MasterElement*>(cuePointChild);
|
||||
for (auto cueTrackChild : *cueTrackElement) {
|
||||
Id trackId = cueTrackChild->getId();
|
||||
if (trackId == ElementIDs::MkCueTrack)
|
||||
cueTrack->setTrackNumber(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueClusterPosition)
|
||||
cueTrack->setClusterPosition(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueRelativePosition)
|
||||
cueTrack->setRelativePosition(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueDuration)
|
||||
cueTrack->setDuration(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueBlockNumber)
|
||||
cueTrack->setBlockNumber(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueCodecState)
|
||||
cueTrack->setCodecState(static_cast<UIntElement*>(cueTrackChild)->getValue());
|
||||
else if (trackId == ElementIDs::MkCueReference) {
|
||||
auto cueReference = static_cast<MasterElement*>(cueTrackChild);
|
||||
for (auto cueReferenceChild : *cueReference) {
|
||||
if (cueReferenceChild->getId() != ElementIDs::MkCueReference)
|
||||
continue;
|
||||
cueTrack->addReferenceTime(static_cast<UIntElement*>(cueReferenceChild)->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
cuePoint->addCueTrack(cueTrack);
|
||||
}
|
||||
}
|
||||
cues->addCuePoint(cuePoint);
|
||||
}
|
||||
return cues;
|
||||
}
|
||||
51
taglib/matroska/ebml/ebmlmkcues.h
Normal file
51
taglib/matroska/ebml/ebmlmkcues.h
Normal file
@ -0,0 +1,51 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "taglib.h"
|
||||
|
||||
#ifndef TAGLIB_EBMLMKCUES_H
|
||||
#define TAGLIB_EBMLMKCUES_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Cues;
|
||||
}
|
||||
//class Matroska::Tag;
|
||||
namespace EBML {
|
||||
class MkCues : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkCues(int sizeLength, offset_t dataSize, offset_t offset)
|
||||
: MasterElement(ElementIDs::MkCues, sizeLength, dataSize, offset)
|
||||
{}
|
||||
MkCues()
|
||||
: MasterElement(ElementIDs::MkCues, 0, 0, 0)
|
||||
{}
|
||||
|
||||
Matroska::Cues* parse();
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
161
taglib/matroska/matroskacues.cpp
Normal file
161
taglib/matroska/matroskacues.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskacues.h"
|
||||
#include "ebmlelement.h"
|
||||
#include "ebmlmkcues.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "tlist.h"
|
||||
#include "tdebug.h"
|
||||
#include "tfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
Matroska::Cues::Cues()
|
||||
: Element(ElementIDs::MkCues)
|
||||
{
|
||||
cuePoints.setAutoDelete(true);
|
||||
}
|
||||
|
||||
ByteVector Matroska::Cues::renderInternal()
|
||||
{
|
||||
EBML::MkCues cues;
|
||||
for (auto &cuePoint : cuePoints) {
|
||||
auto cuePointElement = new EBML::MasterElement(EBML::ElementIDs::MkCuePoint);
|
||||
auto timestamp = new EBML::UIntElement(EBML::ElementIDs::MkCueTime);
|
||||
timestamp->setValue(cuePoint->getTime());
|
||||
cuePointElement->appendElement(timestamp);
|
||||
|
||||
auto trackList = cuePoint->cueTrackList();
|
||||
for (auto &cueTrack : trackList) {
|
||||
auto cueTrackElement = new EBML::MasterElement(EBML::ElementIDs::MkCueTrackPositions);
|
||||
|
||||
// Track number
|
||||
auto trackNumber = new EBML::UIntElement(EBML::ElementIDs::MkCueTrack);
|
||||
trackNumber->setValue(cueTrack->getTrackNumber());
|
||||
cueTrackElement->appendElement(trackNumber);
|
||||
|
||||
// Cluster position
|
||||
auto clusterPosition = new EBML::UIntElement(EBML::ElementIDs::MkCueClusterPosition);
|
||||
clusterPosition->setValue(cueTrack->getClusterPosition());
|
||||
cueTrackElement->appendElement(clusterPosition);
|
||||
|
||||
// Todo - other elements
|
||||
|
||||
|
||||
// Reference times
|
||||
auto referenceTimes = cueTrack->referenceTimes();
|
||||
if (!referenceTimes.isEmpty()) {
|
||||
auto cueReference = new EBML::MasterElement(EBML::ElementIDs::MkCueReference);
|
||||
for (auto reference : referenceTimes) {
|
||||
auto refTime = new EBML::UIntElement(EBML::ElementIDs::MkCueRefTime);
|
||||
refTime->setValue(reference);
|
||||
cueReference->appendElement(refTime);
|
||||
}
|
||||
cueTrackElement->appendElement(cueReference);
|
||||
}
|
||||
cuePointElement->appendElement(cueTrackElement);
|
||||
}
|
||||
}
|
||||
return cues.render();
|
||||
}
|
||||
|
||||
bool Matroska::Cues::render()
|
||||
{
|
||||
if (!needsRender)
|
||||
return true;
|
||||
|
||||
|
||||
setData(cues.render());
|
||||
needsRender = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matroska::Cues::sizeChanged(Element &caller, offset_t delta)
|
||||
{
|
||||
offset_t offset = caller.offset();
|
||||
for (auto cuePoint : cuePoints)
|
||||
needsRender |= cuePoint->adjustOffset(offset, delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matroska::Cues::isValid(TagLib::File &file, offset_t segmentDataOffset) const
|
||||
{
|
||||
for (const auto cuePoint : cuePoints) {
|
||||
if (!cuePoint->isValid(file, segmentDataOffset))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Matroska::CuePoint::CuePoint()
|
||||
{
|
||||
cueTracks.setAutoDelete(true);
|
||||
}
|
||||
|
||||
bool Matroska::CuePoint::isValid(TagLib::File &file, offset_t segmentDataOffset) const
|
||||
{
|
||||
for (const auto track : cueTracks) {
|
||||
if (!track->isValid(file, segmentDataOffset))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta)
|
||||
{
|
||||
bool ret = false;
|
||||
for (auto cueTrack : cueTracks)
|
||||
ret |= cueTrack->adjustOffset(offset, delta);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset) const
|
||||
{
|
||||
if (!trackNumber) {
|
||||
debug("Cue track number not set");
|
||||
return false;
|
||||
}
|
||||
if (!clusterPosition) {
|
||||
debug("Cue track cluster position not set");
|
||||
return false;
|
||||
}
|
||||
file.seek(segmentDataOffset + clusterPosition);
|
||||
if (EBML::Element::readId(file) != EBML::ElementIDs::MkCluster) {
|
||||
debug("No cluster found at position");
|
||||
return false;
|
||||
}
|
||||
if (codecState) {
|
||||
file.seek(segmentDataOffset + codecState);
|
||||
if (EBML::Element::readId(file) != EBML::ElementIDs::MkCodecState) {
|
||||
debug("No codec state found at position");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
119
taglib/matroska/matroskacues.h
Normal file
119
taglib/matroska/matroskacues.h
Normal file
@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HAS_MATROSKACUES_H
|
||||
#define HAS_MATROSKACUES_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "tlist.h"
|
||||
#include "matroskaelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
namespace EBML {
|
||||
class MkCues;
|
||||
}
|
||||
|
||||
namespace Matroska {
|
||||
class CuePoint;
|
||||
class CueTrack;
|
||||
class Cues : public Element
|
||||
{
|
||||
public:
|
||||
using CuePointList = List<CuePoint*>;
|
||||
Cues();
|
||||
~Cues() override = default;
|
||||
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
|
||||
void addCuePoint(CuePoint *cuePoint) { cuePoints.append(cuePoint); }
|
||||
CuePointList cuePointList() { return cuePoints; }
|
||||
bool sizeChanged(Element &caller, offset_t delta) override;
|
||||
bool render() override;
|
||||
|
||||
|
||||
private:
|
||||
friend class EBML::MkCues;
|
||||
ByteVector renderInternal();
|
||||
bool needsRender = false;
|
||||
|
||||
List<CuePoint*> cuePoints;
|
||||
};
|
||||
|
||||
class CuePoint
|
||||
{
|
||||
public:
|
||||
using CueTrackList = List<CueTrack*>;
|
||||
using Time = unsigned long long;
|
||||
CuePoint();
|
||||
~CuePoint() = default;
|
||||
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
|
||||
void addCueTrack(CueTrack *cueTrack) { cueTracks.append(cueTrack); }
|
||||
CueTrackList cueTrackList() const { return cueTracks; }
|
||||
void setTime(Time time) { this->time = time; }
|
||||
Time getTime() const { return time; }
|
||||
bool adjustOffset(offset_t offset, offset_t delta);
|
||||
|
||||
|
||||
private:
|
||||
CueTrackList cueTracks;
|
||||
Time time = 0;
|
||||
};
|
||||
|
||||
class CueTrack
|
||||
{
|
||||
public:
|
||||
using ReferenceTimeList = List<unsigned long long>;
|
||||
CueTrack() = default;
|
||||
~CueTrack() = default;
|
||||
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
|
||||
void setTrackNumber(unsigned int trackNumber) { this->trackNumber = trackNumber; }
|
||||
unsigned int getTrackNumber() const { return trackNumber; }
|
||||
void setClusterPosition(offset_t clusterPosition) { this->clusterPosition = clusterPosition; }
|
||||
offset_t getClusterPosition() const { return clusterPosition; }
|
||||
void setRelativePosition(offset_t relativePosition) { this->relativePosition = relativePosition; }
|
||||
offset_t getRelativePosition() const { return relativePosition; }
|
||||
void setCodecState(offset_t codecState) { this->codecState = codecState; }
|
||||
offset_t getCodecState() const { return codecState; }
|
||||
void setBlockNumber(unsigned int blockNumber) { this->blockNumber = blockNumber; }
|
||||
unsigned int getBlockNumber() const { return blockNumber; }
|
||||
void setDuration(unsigned long long duration) { this->duration = duration; }
|
||||
unsigned long long getDuration() const { return duration; }
|
||||
void addReferenceTime(unsigned long long refTime) { refTimes.append(refTime); }
|
||||
ReferenceTimeList referenceTimes() const { return refTimes; }
|
||||
bool adjustOffset(offset_t offset, offset_t delta);
|
||||
|
||||
|
||||
private:
|
||||
unsigned int trackNumber = 0;
|
||||
offset_t clusterPosition = 0;
|
||||
offset_t relativePosition = 0;
|
||||
unsigned int blockNumber = 0;
|
||||
unsigned long long duration = 0;
|
||||
offset_t codecState = 0;
|
||||
ReferenceTimeList refTimes;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user