mkvpropedit: add option for removing statistics tags for all tracks

Part of the implementation of #1507.
This commit is contained in:
Moritz Bunkus 2015-12-19 14:28:39 +01:00
parent 8cc0918d8f
commit c494170054
10 changed files with 89 additions and 7 deletions

View File

@ -1,5 +1,9 @@
2015-12-19 Moritz Bunkus <moritz@bunkus.org>
* mkvpropedit: new feature: added an option for removing all
existing track statistics tags from a file. Part of the
implementation of #1507.
* mkvmerge: bug fix: AAC with low sampling frequencies was
sometimes mis-detected with the wrong profile preventing appending
it to other AAC tracks. Fixes #1540.

View File

@ -95,6 +95,11 @@ options_c::add_attachment_command(attachment_target_c::command_e command,
m_targets.push_back(target);
}
void
options_c::add_delete_track_statistics_tags(tag_target_c::tag_operation_mode_e operation_mode) {
m_targets.push_back(std::make_shared<tag_target_c>(operation_mode));
}
void
options_c::set_file_name(const std::string &file_name) {
if (!m_file_name.empty())

View File

@ -17,7 +17,7 @@
#include "common/kax_analyzer.h"
#include "propedit/attachment_target.h"
#include "propedit/target.h"
#include "propedit/tag_target.h"
class options_c {
public:
@ -36,6 +36,7 @@ public:
void add_tags(const std::string &spec);
void add_chapters(const std::string &spec);
void add_attachment_command(attachment_target_c::command_e command, std::string const &spec, attachment_target_c::options_t const &options);
void add_delete_track_statistics_tags(tag_target_c::tag_operation_mode_e operation_mode);
void set_file_name(const std::string &file_name);
void set_parse_mode(const std::string &parse_mode);
void dump_info() const;

View File

@ -47,6 +47,22 @@ display_update_element_result(const EbmlCallbacks &callbacks,
mxerror(message + "\n");
}
namespace mtx {
template<typename Trange,
typename Tpredicate> bool
any(Trange range,
Tpredicate predicate) {
return boost::range::find_if(range, predicate) != boost::end(range);
}
}
bool
has_content_been_modified(options_cptr const &options) {
return mtx::any(options->m_targets, [](target_cptr const &t) { return t->has_content_been_modified(); });
}
static void
write_changes(options_cptr &options,
kax_analyzer_c *analyzer) {
@ -120,11 +136,15 @@ run(options_cptr &options) {
options->execute();
mxinfo(Y("The changes are written to the file.\n"));
if (has_content_been_modified(options)) {
mxinfo(Y("The changes are written to the file.\n"));
write_changes(options, analyzer.get());
write_changes(options, analyzer.get());
mxinfo(Y("Done.\n"));
mxinfo(Y("Done.\n"));
} else
mxinfo(Y("No changes were made.\n"));
mxexit();
}
@ -136,7 +156,6 @@ void setup(char **argv) {
version_info = get_version_info("mkvpropedit", vif_full);
}
/** \brief Setup and high level program control
Calls the functions for setup, handling the command line arguments,

View File

@ -127,6 +127,11 @@ propedit_cli_parser_c::replace_attachment() {
}
}
void
propedit_cli_parser_c::handle_track_statistics_tags() {
m_options->add_delete_track_statistics_tags(m_current_arg == "--add-track-statistics-tags" ? tag_target_c::tom_add_track_statistics : tag_target_c::tom_delete_track_statistics);
}
std::map<property_element_c::ebml_type_e, const char *> &
propedit_cli_parser_c::get_ebml_type_abbrev_map() {
static std::map<property_element_c::ebml_type_e, const char *> s_ebml_type_abbrevs;
@ -216,6 +221,8 @@ propedit_cli_parser_c::init_parser() {
"(see below and man page for syntax)"));
OPT("c|chapters=<filename>", add_chapters, YT("Add or replace chapters in the file with the ones from 'filename' "
"or remove them if 'filename' is empty"));
// OPT("add-track-statistics-tags", handle_track_statistics_tags, YT("Calculate statistics for all tracks and add new/update existing tags for them"));
OPT("delete-track-statistics-tags", handle_track_statistics_tags, YT("Delete all existing track statistics tags"));
add_section_header(YT("Actions for handling attachments"));
OPT("add-attachment=<filename>", add_attachment, YT("Add the file 'filename' as a new attachment"));

View File

@ -50,6 +50,8 @@ protected:
void list_property_names();
void list_property_names_for_table(const std::vector<property_element_c> &table, const std::string &title, const std::string &edit_spec);
void handle_track_statistics_tags();
std::map<property_element_c::ebml_type_e, const char *> &get_ebml_type_abbrev_map();
};

View File

@ -13,6 +13,7 @@
#include <matroska/KaxTag.h>
#include <matroska/KaxTags.h>
#include "common/list_utils.h"
#include "common/output.h"
#include "common/strings/editing.h"
#include "common/strings/parsing.h"
@ -28,6 +29,12 @@ tag_target_c::tag_target_c()
{
}
tag_target_c::tag_target_c(tag_operation_mode_e operation_mode)
: track_target_c{""}
, m_operation_mode{operation_mode}
{
}
tag_target_c::~tag_target_c() {
}
@ -45,6 +52,9 @@ tag_target_c::operator ==(target_c const &cmp)
void
tag_target_c::validate() {
if (mtx::included_in(m_operation_mode, tom_add_track_statistics, tom_delete_track_statistics))
return;
if (!m_file_name.empty() && !m_new_tags)
m_new_tags = mtx::xml::ebml_tags_converter_c::parse_file(m_file_name, false);
}
@ -103,8 +113,7 @@ tag_target_c::has_changes()
bool
tag_target_c::non_track_target()
const {
return (tom_all == m_operation_mode)
|| (tom_global == m_operation_mode);
return mtx::included_in(m_operation_mode, tom_all, tom_global, tom_add_track_statistics, tom_delete_track_statistics);
}
bool
@ -130,6 +139,9 @@ tag_target_c::execute() {
else if (tom_track == m_operation_mode)
add_or_replace_track_tags(m_new_tags.get());
else if (tom_delete_track_statistics == m_operation_mode)
delete_track_statistics_tags();
else
assert(false);
@ -151,6 +163,8 @@ tag_target_c::add_or_replace_global_tags(KaxTags *tags) {
delete tag;
m_level1_element->Remove(idx);
}
m_tags_modified = true;
}
if (tags) {
@ -163,6 +177,8 @@ tag_target_c::add_or_replace_global_tags(KaxTags *tags) {
m_level1_element->PushElement(*tag);
tags->Remove(idx);
}
m_tags_modified = true;
}
}
}
@ -180,6 +196,8 @@ tag_target_c::add_or_replace_track_tags(KaxTags *tags) {
delete tag;
m_level1_element->Remove(idx);
}
m_tags_modified = true;
}
if (tags) {
@ -195,6 +213,19 @@ tag_target_c::add_or_replace_track_tags(KaxTags *tags) {
m_level1_element->PushElement(*tag);
tags->Remove(idx);
}
m_tags_modified = true;
}
}
}
void
tag_target_c::delete_track_statistics_tags() {
m_tags_modified = mtx::tags::remove_track_statistics(static_cast<KaxTags *>(m_level1_element), boost::none);
}
bool
tag_target_c::has_content_been_modified()
const {
return m_tags_modified;
}

View File

@ -26,13 +26,17 @@ public:
tom_all,
tom_global,
tom_track,
tom_add_track_statistics,
tom_delete_track_statistics,
};
tag_operation_mode_e m_operation_mode;
std::shared_ptr<KaxTags> m_new_tags;
bool m_tags_modified{};
public:
tag_target_c();
tag_target_c(tag_operation_mode_e operation_mode);
virtual ~tag_target_c();
virtual void validate();
@ -42,12 +46,14 @@ public:
virtual void dump_info() const;
virtual bool has_changes() const;
virtual bool has_content_been_modified() const override;
virtual void execute();
protected:
virtual void add_or_replace_global_tags(KaxTags *tags);
virtual void add_or_replace_track_tags(KaxTags *tags);
virtual void delete_track_statistics_tags();
virtual bool non_track_target() const;
virtual bool sub_master_is_track() const;

View File

@ -90,3 +90,9 @@ target_c::get_level1_element()
const {
return m_level1_element;
}
bool
target_c::has_content_been_modified()
const {
return true;
}

View File

@ -49,6 +49,7 @@ public:
virtual void set_level1_element(ebml_element_cptr level1_element, ebml_element_cptr track_headers = ebml_element_cptr{});
virtual bool has_changes() const = 0;
virtual bool has_content_been_modified() const;
virtual void execute() = 0;