Improve dealing with muxing/writing application of Matroska files
* Allow reading the current muxing/writing application * Allow to preserve the original muxing/writing application instead of always overriding
This commit is contained in:
parent
f5497fb300
commit
e6bb98d6e6
|
@ -7,7 +7,9 @@ using namespace CppUtilities;
|
|||
namespace TagParser {
|
||||
|
||||
/// \brief The AbstractContainerPrivate struct contains private fields of the AbstractContainer class.
|
||||
struct AbstractContainerPrivate {};
|
||||
struct AbstractContainerPrivate {
|
||||
std::vector<std::string> muxingApps, writingApps;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \class TagParser::AbstractContainer
|
||||
|
@ -475,6 +477,40 @@ bool AbstractContainer::supportsTitle() const
|
|||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the muxing applications specified as meta-data.
|
||||
*/
|
||||
const std::vector<std::string> &AbstractContainer::muxingApplications() const
|
||||
{
|
||||
static const auto empty = std::vector<std::string>();
|
||||
return m_p ? m_p->muxingApps : empty;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the muxing applications specified as meta-data.
|
||||
*/
|
||||
std::vector<std::string> &AbstractContainer::muxingApplications()
|
||||
{
|
||||
return p()->muxingApps;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the writing applications specified as meta-data.
|
||||
*/
|
||||
const std::vector<std::string> &AbstractContainer::writingApplications() const
|
||||
{
|
||||
static const auto empty = std::vector<std::string>();
|
||||
return m_p ? m_p->writingApps : empty;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the writing applications specified as meta-data.
|
||||
*/
|
||||
std::vector<std::string> &AbstractContainer::writingApplications()
|
||||
{
|
||||
return p()->writingApps;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the number of segments.
|
||||
*/
|
||||
|
@ -502,4 +538,15 @@ void AbstractContainer::reset()
|
|||
m_titles.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the private data for the container.
|
||||
*/
|
||||
std::unique_ptr<AbstractContainerPrivate> &AbstractContainer::p()
|
||||
{
|
||||
if (!m_p) {
|
||||
m_p = std::make_unique<AbstractContainerPrivate>();
|
||||
}
|
||||
return m_p;
|
||||
}
|
||||
|
||||
} // namespace TagParser
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
const std::vector<std::string> &titles() const;
|
||||
void setTitle(std::string_view title, std::size_t segmentIndex = 0);
|
||||
virtual bool supportsTitle() const;
|
||||
const std::vector<std::string> &muxingApplications() const;
|
||||
const std::vector<std::string> &writingApplications() const;
|
||||
virtual std::size_t segmentCount() const;
|
||||
CppUtilities::TimeSpan duration() const;
|
||||
CppUtilities::DateTime creationTime() const;
|
||||
|
@ -97,6 +99,8 @@ protected:
|
|||
virtual void internalParseChapters(Diagnostics &diag, AbortableProgressFeedback &progress);
|
||||
virtual void internalParseAttachments(Diagnostics &diag, AbortableProgressFeedback &progress);
|
||||
virtual void internalMakeFile(Diagnostics &diag, AbortableProgressFeedback &progress);
|
||||
std::vector<std::string> &muxingApplications();
|
||||
std::vector<std::string> &writingApplications();
|
||||
|
||||
std::uint64_t m_version;
|
||||
std::uint64_t m_readVersion;
|
||||
|
@ -117,6 +121,8 @@ protected:
|
|||
bool m_attachmentsParsed;
|
||||
|
||||
private:
|
||||
std::unique_ptr<AbstractContainerPrivate> &p();
|
||||
|
||||
std::uint64_t m_startOffset;
|
||||
std::iostream *m_stream;
|
||||
CppUtilities::BinaryReader m_reader;
|
||||
|
|
|
@ -627,6 +627,12 @@ void MatroskaContainer::parseSegmentInfo(Diagnostics &diag)
|
|||
case MatroskaIds::TimeCodeScale:
|
||||
timeScale = subElement->readUInteger();
|
||||
break;
|
||||
case MatroskaIds::MuxingApp:
|
||||
muxingApplications().emplace_back(subElement->readString());
|
||||
break;
|
||||
case MatroskaIds::WrittingApp:
|
||||
writingApplications().emplace_back(subElement->readString());
|
||||
break;
|
||||
}
|
||||
subElement = subElement->nextSibling();
|
||||
}
|
||||
|
@ -942,13 +948,18 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee
|
|||
const std::uint64_t ebmlHeaderSize = 4 + EbmlElement::calculateSizeDenotationLength(ebmlHeaderDataSize) + ebmlHeaderDataSize;
|
||||
|
||||
// calculate size of "WritingLib"-element
|
||||
constexpr std::string_view muxingAppName = APP_NAME " v" APP_VERSION;
|
||||
constexpr std::uint64_t muxingAppElementTotalSize = 2 + 1 + muxingAppName.size();
|
||||
const auto &muxingApps = const_cast<const MatroskaContainer *>(this)->muxingApplications();
|
||||
const auto muxingAppName = (fileInfo().fileHandlingFlags() == MediaFileHandlingFlags::PreserveMuxingApplication && !muxingApps.empty())
|
||||
? std::string_view(muxingApps.front())
|
||||
: std::string_view(APP_NAME " v" APP_VERSION);
|
||||
const auto muxingAppElementTotalSize = std::uint64_t(2 + 1 + muxingAppName.size());
|
||||
|
||||
// calculate size of "WritingApp"-element
|
||||
const std::uint64_t writingAppElementDataSize
|
||||
= fileInfo().writingApplication().empty() ? muxingAppName.size() : fileInfo().writingApplication().size();
|
||||
const std::uint64_t writingAppElementTotalSize = 2 + 1 + writingAppElementDataSize;
|
||||
const auto writingApps = const_cast<const MatroskaContainer *>(this)->writingApplications();
|
||||
const auto writingAppName = (fileInfo().fileHandlingFlags() == MediaFileHandlingFlags::PreserveWritingApplication && !writingApps.empty())
|
||||
? std::string_view(writingApps.front())
|
||||
: std::string_view(fileInfo().writingApplication().empty() ? muxingAppName : std::string_view(fileInfo().writingApplication()));
|
||||
const auto writingAppElementTotalSize = std::uint64_t(2 + 1 + writingAppName.size());
|
||||
|
||||
try {
|
||||
// calculate size of "Tags"-element
|
||||
|
|
|
@ -43,7 +43,7 @@ enum SeekIds { SeekID = 0x53AB, SeekPosition = 0x53AC };
|
|||
enum SegmentInfoIds {
|
||||
TimeCodeScale = 0x2AD7B1,
|
||||
Duration = 0x4489,
|
||||
WrittingApp = 0x5741,
|
||||
WrittingApp = 0x5741, // TODOv13: change to WritingApp
|
||||
MuxingApp = 0x4D80,
|
||||
DateUTC = 0x4461,
|
||||
SegmentUID = 0x73A4,
|
||||
|
|
|
@ -64,6 +64,8 @@ enum class MediaFileHandlingFlags : std::uint64_t {
|
|||
ForceIndexPosition = (1 << 3), /**< enforces the index position when applying changes, see remarks of MediaFileInfo::setIndexPosition() */
|
||||
NormalizeKnownTagFieldIds = (1 << 4), /**< normalizes known tag field IDs when parsing to match the tag specification's recommendations */
|
||||
PreserveRawTimingValues = (1 << 8), /**< preverves raw timing values (so far only used when making MP4 tracks) */
|
||||
PreserveMuxingApplication = (1 << 9), /**< preverves the muxing application (so far only used when making Matroska container) */
|
||||
PreserveWritingApplication = (1 << 10), /**< preverves the writing application (so far only used when making Matroska container) */
|
||||
};
|
||||
|
||||
} // namespace TagParser
|
||||
|
@ -471,7 +473,9 @@ inline const std::string &MediaFileInfo::writingApplication() const
|
|||
|
||||
/*!
|
||||
* \brief Sets the writing application as container-level meta-data. Put the name of your application here.
|
||||
* \remarks Might not be used (depends on the format).
|
||||
* \remarks
|
||||
* - Currently only used when making Matroska files.
|
||||
* - The assigned value is ignored when MediaFileHandlingFlags::PreserveWritingApplication is set.
|
||||
*/
|
||||
inline void MediaFileInfo::setWritingApplication(std::string_view writingApplication)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue