1 /*
2 mkvmerge -- utility for splicing together matroska files
3 from component media subtypes
4
5 Distributed under the GPL v2
6 see the file COPYING for details
7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8
9 Written by Moritz Bunkus <moritz@bunkus.org>.
10 */
11
12 #include "common/common_pch.h"
13
14 #include "common/construct.h"
15 #include "common/date_time.h"
16 #include "common/strings/formatting.h"
17 #include "common/tags/tags.h"
18 #include "common/track_statistics.h"
19
20 void
create_tags(libmatroska::KaxTags & tags,std::string const & writing_app,std::optional<QDateTime> const & writing_date) const21 track_statistics_c::create_tags(libmatroska::KaxTags &tags,
22 std::string const &writing_app,
23 std::optional<QDateTime> const &writing_date)
24 const {
25 auto bps = get_bits_per_second();
26 auto duration = get_duration();
27 auto names = std::vector<std::string>{ "BPS"s, "DURATION"s, "NUMBER_OF_FRAMES"s, "NUMBER_OF_BYTES"s };
28
29 mtx::tags::remove_simple_tags_for<libmatroska::KaxTagTrackUID>(tags, m_track_uid, "BPS");
30 mtx::tags::remove_simple_tags_for<libmatroska::KaxTagTrackUID>(tags, m_track_uid, "DURATION");
31 mtx::tags::remove_simple_tags_for<libmatroska::KaxTagTrackUID>(tags, m_track_uid, "NUMBER_OF_FRAMES");
32 mtx::tags::remove_simple_tags_for<libmatroska::KaxTagTrackUID>(tags, m_track_uid, "NUMBER_OF_BYTES");
33
34 auto tag = find_or_create_tag(tags);
35
36 mtx::tags::set_simple(*tag, "BPS", fmt::to_string(bps ? *bps : 0));
37 mtx::tags::set_simple(*tag, "DURATION", mtx::string::format_timestamp(duration ? *duration : 0));
38 mtx::tags::set_simple(*tag, "NUMBER_OF_FRAMES", fmt::to_string(m_num_frames));
39 mtx::tags::set_simple(*tag, "NUMBER_OF_BYTES", fmt::to_string(m_num_bytes));
40
41 if (!m_source_id.empty()) {
42 mtx::tags::set_simple(*tag, "SOURCE_ID", m_source_id);
43 names.emplace_back("SOURCE_ID"s);
44 }
45
46 mtx::tags::set_simple(*tag, "_STATISTICS_WRITING_APP", writing_app);
47
48 if (writing_date) {
49 auto writing_date_str = mtx::date_time::format(writing_date->toUTC(), "%Y-%m-%d %H:%M:%S");
50 mtx::tags::set_simple(*tag, "_STATISTICS_WRITING_DATE_UTC", writing_date_str);
51 }
52
53 mtx::tags::set_simple(*tag, "_STATISTICS_TAGS", mtx::string::join(names, " "));
54 }
55
56 libmatroska::KaxTag *
find_or_create_tag(libmatroska::KaxTags & tags) const57 track_statistics_c::find_or_create_tag(libmatroska::KaxTags &tags)
58 const {
59 for (auto &element : tags) {
60 auto tag = dynamic_cast<libmatroska::KaxTag *>(element);
61 if (!tag)
62 continue;
63
64 auto targets = FindChild<libmatroska::KaxTagTargets>(*tag);
65 if (!targets)
66 continue;
67
68 auto actual_target_type_value = static_cast<mtx::tags::target_type_e>(FindChildValue<libmatroska::KaxTagTargetTypeValue>(*targets, 0ull));
69 auto actual_id = FindChildValue<libmatroska::KaxTagTrackUID>(*targets, 0ull);
70 auto actual_target_type = FindChild<libmatroska::KaxTagTargetType>(*targets);
71
72 if ( (actual_target_type_value == mtx::tags::Movie)
73 && (actual_id == m_track_uid)
74 && !actual_target_type)
75 return tag;
76 }
77
78 using namespace mtx::construct;
79
80 auto tag = cons<libmatroska::KaxTag>(cons<libmatroska::KaxTagTargets>(new libmatroska::KaxTagTargetTypeValue, mtx::tags::Movie,
81 new libmatroska::KaxTagTrackUID, m_track_uid));
82 tags.PushElement(*tag);
83
84 return tag;
85 }
86