From 9b0d74b6adf310f31b09c2503d82899ddb39d27e Mon Sep 17 00:00:00 2001 From: Martchus Date: Sun, 11 Jun 2017 22:57:28 +0200 Subject: [PATCH] Implement applying changed track meta-data for Mkv --- abstracttrack.h | 10 +++++ matroska/matroskatrack.cpp | 77 ++++++++++++++++++++++++++++++++------ matroska/matroskatrack.h | 11 ++++++ tests/overallmkv.cpp | 3 +- 4 files changed, 88 insertions(+), 13 deletions(-) diff --git a/abstracttrack.h b/abstracttrack.h index 8e6647d..e5233e4 100644 --- a/abstracttrack.h +++ b/abstracttrack.h @@ -63,6 +63,7 @@ public: const char *mediaTypeName() const; uint64 size() const; uint32 trackNumber() const; + void setTrackNumber(uint32 trackNumber); uint64 id() const; void setId(uint64 id); const std::string name() const; @@ -322,6 +323,15 @@ inline uint32 AbstractTrack::trackNumber() const return m_trackNumber; } +/*! + * \brief Sets the track number. + * \remarks Whether the new value is applied when saving changes depends on the implementation. + */ +inline void AbstractTrack::setTrackNumber(uint32 trackNumber) +{ + m_trackNumber = trackNumber; +} + /*! * \brief Returns the track ID if known; otherwise returns 0. */ diff --git a/matroska/matroskatrack.cpp b/matroska/matroskatrack.cpp index 3d62f91..d39b201 100644 --- a/matroska/matroskatrack.cpp +++ b/matroska/matroskatrack.cpp @@ -471,17 +471,39 @@ void MatroskaTrack::internalParseHeader() * \sa See MatroskaTrack::prepareMakingHeader() for more information. */ MatroskaTrackHeaderMaker::MatroskaTrackHeaderMaker(const MatroskaTrack &track) : - m_track(track) + m_track(track), + m_dataSize(0) { - m_track.m_trackElement->makeBuffer(); -} - -/*! - * \brief Returns the associated tag. - */ -uint64 MatroskaTrackHeaderMaker::requiredSize() const -{ - return m_track.m_trackElement->totalSize(); + for(EbmlElement *trackInfoElement = m_track.m_trackElement->firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) { + switch(trackInfoElement->id()) { + case MatroskaIds::TrackNumber: + m_dataSize += 1 + 1 + EbmlElement::calculateUIntegerLength(m_track.trackNumber()); + break; + case MatroskaIds::TrackUID: + m_dataSize += 2 + 1 + EbmlElement::calculateUIntegerLength(m_track.id()); + break; + case MatroskaIds::TrackName: + m_dataSize += 2 + EbmlElement::calculateSizeDenotationLength(m_track.name().size()) + m_track.name().size(); + break; + case MatroskaIds::TrackLanguage: + m_dataSize += 3 + EbmlElement::calculateSizeDenotationLength(m_track.language().size()) + m_track.language().size(); + break; + case MatroskaIds::TrackFlagEnabled: + m_dataSize += 1 + 1 + EbmlElement::calculateUIntegerLength(m_track.isEnabled()); + break; + case MatroskaIds::TrackFlagDefault: + m_dataSize += 1 + 1 + EbmlElement::calculateUIntegerLength(m_track.isDefault()); + break; + case MatroskaIds::TrackFlagForced: + m_dataSize += 2 + 1 + EbmlElement::calculateUIntegerLength(m_track.isForced()); + break; + default: + trackInfoElement->makeBuffer(); + m_dataSize += trackInfoElement->totalSize(); + } + } + m_sizeDenotationLength = EbmlElement::calculateSizeDenotationLength(m_dataSize); + m_requiredSize = 2 + m_sizeDenotationLength + m_dataSize; } /*! @@ -493,7 +515,40 @@ uint64 MatroskaTrackHeaderMaker::requiredSize() const */ void MatroskaTrackHeaderMaker::make(ostream &stream) const { - m_track.m_trackElement->copyBuffer(stream); + // make ID and size + char buffer[10]; + BE::getBytes(static_cast(MatroskaIds::TrackEntry), buffer); + EbmlElement::makeSizeDenotation(m_dataSize, buffer + 2); + stream.write(buffer, 2 + m_sizeDenotationLength); + + // make child elements + for(EbmlElement *trackInfoElement = m_track.m_trackElement->firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) { + switch(trackInfoElement->id()) { + case MatroskaIds::TrackNumber: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackNumber, m_track.trackNumber()); + break; + case MatroskaIds::TrackUID: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackUID, m_track.id()); + break; + case MatroskaIds::TrackName: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackName, m_track.name()); + break; + case MatroskaIds::TrackLanguage: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackLanguage, m_track.language()); + break; + case MatroskaIds::TrackFlagEnabled: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackFlagEnabled, m_track.isEnabled()); + break; + case MatroskaIds::TrackFlagDefault: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackFlagDefault, m_track.isDefault()); + break; + case MatroskaIds::TrackFlagForced: + EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackFlagForced, m_track.isForced()); + break; + default: + trackInfoElement->copyBuffer(stream); + } + } } } diff --git a/matroska/matroskatrack.h b/matroska/matroskatrack.h index b5d9db1..c8f4f5d 100644 --- a/matroska/matroskatrack.h +++ b/matroska/matroskatrack.h @@ -22,6 +22,9 @@ private: MatroskaTrackHeaderMaker(const MatroskaTrack &track); const MatroskaTrack &m_track; + uint64 m_dataSize; + uint64 m_requiredSize; + byte m_sizeDenotationLength; }; /*! @@ -32,6 +35,14 @@ inline const MatroskaTrack &MatroskaTrackHeaderMaker::track() const return m_track; } +/*! + * \brief Returns the number of bytes which will be written when calling make(). + */ +inline uint64 MatroskaTrackHeaderMaker::requiredSize() const +{ + return m_requiredSize; +} + class TAG_PARSER_EXPORT MatroskaTrack : public AbstractTrack { friend class MatroskaContainer; diff --git a/tests/overallmkv.cpp b/tests/overallmkv.cpp index 9a96f49..c1c2697 100644 --- a/tests/overallmkv.cpp +++ b/tests/overallmkv.cpp @@ -174,8 +174,7 @@ void OverallTests::checkMkvTestfile4() break; case TagStatus::TestMetaDataPresent: // not implemented yet, so currently still undefined instead of German - CPPUNIT_ASSERT_EQUAL("und"s, track->language()); - //CPPUNIT_ASSERT_EQUAL("ger"s, track->language()); + CPPUNIT_ASSERT_EQUAL("ger"s, track->language()); break; } break;