mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2025-02-26 08:22:31 +00:00
Added support for copying attachments selectively
Attachments are now included in the output of --identify. They can be selected just like the other track types. The option used for them is -m / --attachments and disabled with -M / --no-attachments.
This commit is contained in:
parent
a2b7d6b28c
commit
988ea9cc58
@ -43,6 +43,8 @@ using namespace std;
|
|||||||
static void
|
static void
|
||||||
handle_attachments(KaxAttachments *atts,
|
handle_attachments(KaxAttachments *atts,
|
||||||
vector<track_spec_t> &tracks) {
|
vector<track_spec_t> &tracks) {
|
||||||
|
static int64_t attachment_ui_id = 0;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; atts->ListSize() > i; ++i) {
|
for (i = 0; atts->ListSize() > i; ++i) {
|
||||||
KaxAttached *att = dynamic_cast<KaxAttached *>((*atts)[i]);
|
KaxAttached *att = dynamic_cast<KaxAttached *>((*atts)[i]);
|
||||||
@ -74,10 +76,12 @@ handle_attachments(KaxAttachments *atts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((-1 != id) && (-1 != size) && !type.empty()) {
|
if ((-1 != id) && (-1 != size) && !type.empty()) {
|
||||||
|
++attachment_ui_id;
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
for (k = 0; k < tracks.size(); k++)
|
for (k = 0; k < tracks.size(); k++)
|
||||||
if (tracks[k].tid == id) {
|
if (tracks[k].tid == attachment_ui_id) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -89,7 +93,7 @@ handle_attachments(KaxAttachments *atts,
|
|||||||
tracks[k].out_name = safestrdup(name.c_str());
|
tracks[k].out_name = safestrdup(name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
mxinfo(boost::format(Y("The attachment #%1%, MIME type %2%, size %3%, is written to '%4%'.\n")) % id % type % size % tracks[k].out_name);
|
mxinfo(boost::format(Y("The attachment #%1%, ID %2%, MIME type %3%, size %4%, is written to '%5%'.\n")) % attachment_ui_id % id % type % size % tracks[k].out_name);
|
||||||
mm_io_c *out = NULL;
|
mm_io_c *out = NULL;
|
||||||
try {
|
try {
|
||||||
out = new mm_file_io_c(tracks[k].out_name, MODE_CREATE);
|
out = new mm_file_io_c(tracks[k].out_name, MODE_CREATE);
|
||||||
|
@ -136,7 +136,6 @@ avi_reader_c::~avi_reader_c() {
|
|||||||
void
|
void
|
||||||
avi_reader_c::parse_subtitle_chunks() {
|
avi_reader_c::parse_subtitle_chunks() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; AVI_text_tracks(avi) > i; ++i) {
|
for (i = 0; AVI_text_tracks(avi) > i; ++i) {
|
||||||
AVI_set_text_track(avi, i);
|
AVI_set_text_track(avi, i);
|
||||||
|
|
||||||
@ -159,10 +158,8 @@ avi_reader_c::parse_subtitle_chunks() {
|
|||||||
mm_mem_io_c io(chunk->get(), chunk_size);
|
mm_mem_io_c io(chunk->get(), chunk_size);
|
||||||
uint32_t tag = io.read_uint32_be();
|
uint32_t tag = io.read_uint32_be();
|
||||||
|
|
||||||
if (GAB2_TAG != tag) {
|
if (GAB2_TAG != tag)
|
||||||
mxinfo("muuuuh :(( 1\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
io.skip(1);
|
io.skip(1);
|
||||||
|
|
||||||
@ -310,7 +307,7 @@ avi_reader_c::create_ssa_packetizer(int idx) {
|
|||||||
avi_subs_demuxer_t &demuxer = sdemuxers[idx];
|
avi_subs_demuxer_t &demuxer = sdemuxers[idx];
|
||||||
int id = idx + 1 + AVI_audio_tracks(avi);
|
int id = idx + 1 + AVI_audio_tracks(avi);
|
||||||
|
|
||||||
ssa_parser_c *parser = new ssa_parser_c(demuxer.text_io.get(), ti.fname, id);
|
ssa_parser_c *parser = new ssa_parser_c(this, demuxer.text_io.get(), ti.fname, id);
|
||||||
demuxer.subs = subtitles_cptr(parser);
|
demuxer.subs = subtitles_cptr(parser);
|
||||||
|
|
||||||
int cc_utf8 = map_has_key(ti.sub_charsets, id) ? utf8_init(ti.sub_charsets[id])
|
int cc_utf8 = map_has_key(ti.sub_charsets, id) ? utf8_init(ti.sub_charsets[id])
|
||||||
@ -319,7 +316,7 @@ avi_reader_c::create_ssa_packetizer(int idx) {
|
|||||||
: cc_local_utf8;
|
: cc_local_utf8;
|
||||||
|
|
||||||
parser->set_iconv_handle(cc_utf8);
|
parser->set_iconv_handle(cc_utf8);
|
||||||
parser->set_ignore_attachments(ti.no_attachments);
|
parser->set_attachment_id_base(g_attachments.size());
|
||||||
parser->parse();
|
parser->parse();
|
||||||
|
|
||||||
std::string global = parser->get_global();
|
std::string global = parser->get_global();
|
||||||
@ -799,6 +796,7 @@ avi_reader_c::identify() {
|
|||||||
identify_video();
|
identify_video();
|
||||||
identify_audio();
|
identify_audio();
|
||||||
identify_subtitles();
|
identify_subtitles();
|
||||||
|
identify_attachments();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -850,6 +848,27 @@ avi_reader_c::identify_subtitles() {
|
|||||||
: "unknown");
|
: "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
avi_reader_c::identify_attachments() {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; sdemuxers.size() > i; ++i) {
|
||||||
|
try {
|
||||||
|
avi_subs_demuxer_t &demuxer = sdemuxers[i];
|
||||||
|
mm_text_io_c text_io(new mm_mem_io_c(demuxer.subtitles->get(), demuxer.subtitles->get_size()));
|
||||||
|
ssa_parser_c parser(this, &text_io, ti.fname, i + 1 + AVI_audio_tracks(avi));
|
||||||
|
|
||||||
|
parser.set_attachment_id_base(g_attachments.size());
|
||||||
|
parser.parse();
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < g_attachments.size(); i++)
|
||||||
|
id_result_attachment(g_attachments[i].ui_id, g_attachments[i].mime_type, g_attachments[i].data->get_size(), g_attachments[i].name, g_attachments[i].description);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
avi_reader_c::add_available_track_ids() {
|
avi_reader_c::add_available_track_ids() {
|
||||||
int i;
|
int i;
|
||||||
|
@ -104,6 +104,7 @@ protected:
|
|||||||
virtual void identify_video();
|
virtual void identify_video();
|
||||||
virtual void identify_audio();
|
virtual void identify_audio();
|
||||||
virtual void identify_subtitles();
|
virtual void identify_subtitles();
|
||||||
|
virtual void identify_attachments();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __R_AVI_H
|
#endif // __R_AVI_H
|
||||||
|
@ -134,12 +134,13 @@ kax_reader_c::probe_file(mm_io_c *io,
|
|||||||
// {{{ C'TOR
|
// {{{ C'TOR
|
||||||
|
|
||||||
kax_reader_c::kax_reader_c(track_info_c &_ti)
|
kax_reader_c::kax_reader_c(track_info_c &_ti)
|
||||||
throw (error_c):
|
throw (error_c)
|
||||||
generic_reader_c(_ti),
|
: generic_reader_c(_ti)
|
||||||
segment_duration(0),
|
, segment_duration(0)
|
||||||
first_timecode(-1),
|
, first_timecode(-1)
|
||||||
writing_app_ver(-1) {
|
, writing_app_ver(-1)
|
||||||
|
, m_attachment_id(0)
|
||||||
|
{
|
||||||
if (!read_headers())
|
if (!read_headers())
|
||||||
throw error_c(Y("matroska_reader: Failed to read the headers."));
|
throw error_c(Y("matroska_reader: Failed to read the headers."));
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -543,17 +544,18 @@ kax_reader_c::handle_attachments(mm_io_c *io,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((-1 != id) && (-1 != size) && !mime_type.empty() && (0 < name.length())) {
|
attach_mode_e attach_mode;
|
||||||
attachment_t matt;
|
if ((-1 != id) && (-1 != size) && !mime_type.empty() && (0 != name.length()) && ((attach_mode = attachment_requested(m_attachment_id + 1)) != ATTACH_MODE_SKIP)) {
|
||||||
|
++m_attachment_id;
|
||||||
|
|
||||||
|
attachment_t matt;
|
||||||
matt.name = UTFstring_to_cstrutf8(name);
|
matt.name = UTFstring_to_cstrutf8(name);
|
||||||
matt.mime_type = mime_type;
|
matt.mime_type = mime_type;
|
||||||
matt.description = UTFstring_to_cstrutf8(description);
|
matt.description = UTFstring_to_cstrutf8(description);
|
||||||
matt.id = id;
|
matt.id = id;
|
||||||
matt.to_all_files = true;
|
matt.ui_id = m_attachment_id;
|
||||||
matt.data = counted_ptr<buffer_t>(new buffer_t);
|
matt.to_all_files = ATTACH_MODE_TO_ALL_FILES == attach_mode;
|
||||||
matt.data->m_size = size;
|
matt.data = clone_memory(data, size);
|
||||||
matt.data->m_buffer = (unsigned char *)safememdup(data, size);
|
|
||||||
|
|
||||||
add_attachment(matt);
|
add_attachment(matt);
|
||||||
}
|
}
|
||||||
@ -570,9 +572,6 @@ void
|
|||||||
kax_reader_c::handle_chapters(mm_io_c *io,
|
kax_reader_c::handle_chapters(mm_io_c *io,
|
||||||
EbmlElement *l0,
|
EbmlElement *l0,
|
||||||
int64_t pos) {
|
int64_t pos) {
|
||||||
if (ti.no_chapters)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < handled_chapters.size(); i++)
|
for (i = 0; i < handled_chapters.size(); i++)
|
||||||
@ -615,9 +614,6 @@ void
|
|||||||
kax_reader_c::handle_tags(mm_io_c *io,
|
kax_reader_c::handle_tags(mm_io_c *io,
|
||||||
EbmlElement *l0,
|
EbmlElement *l0,
|
||||||
int64_t pos) {
|
int64_t pos) {
|
||||||
if (ti.no_tags)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < handled_tags.size(); i++)
|
for (i = 0; i < handled_tags.size(); i++)
|
||||||
@ -1201,10 +1197,14 @@ kax_reader_c::read_headers() {
|
|||||||
if (!ti.no_attachments)
|
if (!ti.no_attachments)
|
||||||
for (i = 0; i < deferred_attachments.size(); i++)
|
for (i = 0; i < deferred_attachments.size(); i++)
|
||||||
handle_attachments(in, l0, deferred_attachments[i]);
|
handle_attachments(in, l0, deferred_attachments[i]);
|
||||||
for (i = 0; i < deferred_chapters.size(); i++)
|
|
||||||
handle_chapters(in, l0, deferred_chapters[i]);
|
if (!ti.no_chapters)
|
||||||
for (i = 0; i < deferred_tags.size(); i++)
|
for (i = 0; i < deferred_chapters.size(); i++)
|
||||||
handle_tags(in, l0, deferred_tags[i]);
|
handle_chapters(in, l0, deferred_chapters[i]);
|
||||||
|
|
||||||
|
if (!ti.no_tags)
|
||||||
|
for (i = 0; i < deferred_tags.size(); i++)
|
||||||
|
handle_tags(in, l0, deferred_tags[i]);
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
mxerror(Y("matroska_reader: caught exception\n"));
|
mxerror(Y("matroska_reader: caught exception\n"));
|
||||||
@ -2149,7 +2149,7 @@ kax_reader_c::identify() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < g_attachments.size(); i++)
|
for (i = 0; i < g_attachments.size(); i++)
|
||||||
id_result_attachment(g_attachments[i].id, g_attachments[i].mime_type, g_attachments[i].data->m_size, g_attachments[i].name, g_attachments[i].description);
|
id_result_attachment(g_attachments[i].ui_id, g_attachments[i].mime_type, g_attachments[i].data->get_size(), g_attachments[i].name, g_attachments[i].description);
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
@ -169,6 +169,8 @@ private:
|
|||||||
string writing_app, muxing_app;
|
string writing_app, muxing_app;
|
||||||
int64_t writing_app_ver;
|
int64_t writing_app_ver;
|
||||||
|
|
||||||
|
int64_t m_attachment_id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
kax_reader_c(track_info_c &_ti) throw (error_c);
|
kax_reader_c(track_info_c &_ti) throw (error_c);
|
||||||
virtual ~kax_reader_c();
|
virtual ~kax_reader_c();
|
||||||
|
@ -51,10 +51,9 @@ ssa_reader_c::ssa_reader_c(track_info_c &_ti)
|
|||||||
: cc_local_utf8;
|
: cc_local_utf8;
|
||||||
|
|
||||||
ti.id = 0;
|
ti.id = 0;
|
||||||
m_subs = ssa_parser_cptr(new ssa_parser_c(io.get(), ti.fname, 0));
|
m_subs = ssa_parser_cptr(new ssa_parser_c(this, io.get(), ti.fname, 0));
|
||||||
|
|
||||||
m_subs->set_iconv_handle(cc_utf8);
|
m_subs->set_iconv_handle(cc_utf8);
|
||||||
m_subs->set_ignore_attachments(ti.no_attachments);
|
|
||||||
m_subs->parse();
|
m_subs->parse();
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -101,4 +100,8 @@ void
|
|||||||
ssa_reader_c::identify() {
|
ssa_reader_c::identify() {
|
||||||
id_result_container("SSA/ASS");
|
id_result_container("SSA/ASS");
|
||||||
id_result_track(0, ID_RESULT_TRACK_SUBTITLES, "SSA/ASS");
|
id_result_track(0, ID_RESULT_TRACK_SUBTITLES, "SSA/ASS");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < g_attachments.size(); i++)
|
||||||
|
id_result_attachment(g_attachments[i].ui_id, g_attachments[i].mime_type, g_attachments[i].data->get_size(), g_attachments[i].name, g_attachments[i].description);
|
||||||
}
|
}
|
||||||
|
@ -234,15 +234,17 @@ ssa_parser_c::probe(mm_text_io_c *io) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_parser_c::ssa_parser_c(mm_text_io_c *io,
|
ssa_parser_c::ssa_parser_c(generic_reader_c *reader,
|
||||||
|
mm_text_io_c *io,
|
||||||
const std::string &file_name,
|
const std::string &file_name,
|
||||||
int64_t tid)
|
int64_t tid)
|
||||||
: m_io(io)
|
: m_reader(reader)
|
||||||
|
, m_io(io)
|
||||||
, m_file_name(file_name)
|
, m_file_name(file_name)
|
||||||
, m_tid(tid)
|
, m_tid(tid)
|
||||||
, m_cc_utf8(-1)
|
, m_cc_utf8(-1)
|
||||||
, m_is_ass(false)
|
, m_is_ass(false)
|
||||||
, m_ignore_attachments(true)
|
, m_attachment_id(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +456,15 @@ void
|
|||||||
ssa_parser_c::add_attachment_maybe(std::string &name,
|
ssa_parser_c::add_attachment_maybe(std::string &name,
|
||||||
std::string &data_uu,
|
std::string &data_uu,
|
||||||
ssa_section_e section) {
|
ssa_section_e section) {
|
||||||
if (m_ignore_attachments || name.empty() || data_uu.empty() || ((SSA_SECTION_FONTS != section) && (SSA_SECTION_GRAPHICS != section))) {
|
if (name.empty() || data_uu.empty() || ((SSA_SECTION_FONTS != section) && (SSA_SECTION_GRAPHICS != section))) {
|
||||||
|
name = "";
|
||||||
|
data_uu = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++m_attachment_id;
|
||||||
|
|
||||||
|
if (!m_reader->attachment_requested(m_attachment_id)) {
|
||||||
name = "";
|
name = "";
|
||||||
data_uu = "";
|
data_uu = "";
|
||||||
return;
|
return;
|
||||||
@ -471,27 +481,28 @@ ssa_parser_c::add_attachment_maybe(std::string &name,
|
|||||||
if (0 < pos)
|
if (0 < pos)
|
||||||
short_name.erase(0, pos + 1);
|
short_name.erase(0, pos + 1);
|
||||||
|
|
||||||
|
attachment.ui_id = m_attachment_id;
|
||||||
attachment.name = to_utf8(m_cc_utf8, name);
|
attachment.name = to_utf8(m_cc_utf8, name);
|
||||||
attachment.description = (boost::format(SSA_SECTION_FONTS == section ? Y("Imported font from %1%") : Y("Imported picture from %1%")) % short_name).str();
|
attachment.description = (boost::format(SSA_SECTION_FONTS == section ? Y("Imported font from %1%") : Y("Imported picture from %1%")) % short_name).str();
|
||||||
attachment.to_all_files = true;
|
attachment.to_all_files = true;
|
||||||
|
|
||||||
int allocated = 1024;
|
int allocated = 1024;
|
||||||
buffer_t *buffer = new buffer_t((unsigned char *)safemalloc(allocated), 0);
|
attachment.data = memory_c::alloc(allocated);
|
||||||
|
attachment.data->set_size(0);
|
||||||
|
|
||||||
const unsigned char *p = (const unsigned char *)data_uu.c_str();
|
const unsigned char *p = (const unsigned char *)data_uu.c_str();
|
||||||
for (pos = 0; data_uu.length() > (pos + 4); pos += 4)
|
for (pos = 0; data_uu.length() > (pos + 4); pos += 4)
|
||||||
decode_chars(p[pos], p[pos + 1], p[pos + 2], p[pos + 3], *buffer, 3, allocated);
|
decode_chars(p[pos], p[pos + 1], p[pos + 2], p[pos + 3], attachment.data, 3, allocated);
|
||||||
|
|
||||||
switch (data_uu.length() % 4) {
|
switch (data_uu.length() % 4) {
|
||||||
case 2:
|
case 2:
|
||||||
decode_chars(p[pos], p[pos + 1], 0, 0, *buffer, 1, allocated);
|
decode_chars(p[pos], p[pos + 1], 0, 0, attachment.data, 1, allocated);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
decode_chars(p[pos], p[pos + 1], p[pos + 2], 0, *buffer, 2, allocated);
|
decode_chars(p[pos], p[pos + 1], p[pos + 2], 0, attachment.data, 2, allocated);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachment.data = counted_ptr<buffer_t>(buffer);
|
|
||||||
attachment.mime_type = guess_mime_type(name, false);
|
attachment.mime_type = guess_mime_type(name, false);
|
||||||
|
|
||||||
if (attachment.mime_type == "")
|
if (attachment.mime_type == "")
|
||||||
@ -508,7 +519,7 @@ ssa_parser_c::decode_chars(unsigned char c1,
|
|||||||
unsigned char c2,
|
unsigned char c2,
|
||||||
unsigned char c3,
|
unsigned char c3,
|
||||||
unsigned char c4,
|
unsigned char c4,
|
||||||
buffer_t &buffer,
|
memory_cptr &buffer,
|
||||||
int bytes_to_add,
|
int bytes_to_add,
|
||||||
int &allocated) {
|
int &allocated) {
|
||||||
unsigned char bytes[3];
|
unsigned char bytes[3];
|
||||||
@ -518,15 +529,15 @@ ssa_parser_c::decode_chars(unsigned char c1,
|
|||||||
bytes[1] = (value & 0x00ff00) >> 8;
|
bytes[1] = (value & 0x00ff00) >> 8;
|
||||||
bytes[0] = (value & 0xff0000) >> 16;
|
bytes[0] = (value & 0xff0000) >> 16;
|
||||||
|
|
||||||
if ((buffer.m_size + bytes_to_add) > allocated) {
|
if ((buffer->get_size() + bytes_to_add) > allocated) {
|
||||||
allocated += 1024;
|
int old_size = buffer->get_size();
|
||||||
buffer.m_buffer = (unsigned char *)realloc(buffer.m_buffer, allocated);
|
allocated += 1024;
|
||||||
|
buffer->resize(allocated);
|
||||||
|
buffer->set_size(old_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
memcpy(buffer->get() + buffer->get_size(), bytes, bytes_to_add);
|
||||||
for (i = 0; i < bytes_to_add; ++i)
|
buffer->set_size(buffer->get_size() + bytes_to_add);
|
||||||
buffer.m_buffer[buffer.m_size + i] = bytes[i];
|
|
||||||
buffer.m_size += bytes_to_add;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "output_control.h"
|
||||||
#include "p_textsubs.h"
|
#include "p_textsubs.h"
|
||||||
|
|
||||||
typedef struct sub_t {
|
typedef struct sub_t {
|
||||||
@ -102,6 +103,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
generic_reader_c *m_reader;
|
||||||
mm_text_io_c *m_io;
|
mm_text_io_c *m_io;
|
||||||
const std::string &m_file_name;
|
const std::string &m_file_name;
|
||||||
int64_t m_tid;
|
int64_t m_tid;
|
||||||
@ -109,10 +111,13 @@ protected:
|
|||||||
std::vector<std::string> m_format;
|
std::vector<std::string> m_format;
|
||||||
bool m_is_ass;
|
bool m_is_ass;
|
||||||
std::string m_global;
|
std::string m_global;
|
||||||
bool m_ignore_attachments;
|
int64_t m_attachment_id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ssa_parser_c(mm_text_io_c *io, const std::string &file_name, int64_t tid);
|
vector<attachment_t> m_attachments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ssa_parser_c(generic_reader_c *reader, mm_text_io_c *io, const std::string &file_name, int64_t tid);
|
||||||
void parse();
|
void parse();
|
||||||
|
|
||||||
bool is_ass() {
|
bool is_ass() {
|
||||||
@ -123,14 +128,14 @@ public:
|
|||||||
m_cc_utf8 = cc_utf8;
|
m_cc_utf8 = cc_utf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_ignore_attachments(bool ignore_attachments) {
|
|
||||||
m_ignore_attachments = ignore_attachments;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_global() {
|
std::string get_global() {
|
||||||
return m_global;
|
return m_global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_attachment_id_base(int64_t id) {
|
||||||
|
m_attachment_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool probe(mm_text_io_c *io);
|
static bool probe(mm_text_io_c *io);
|
||||||
|
|
||||||
@ -139,7 +144,7 @@ protected:
|
|||||||
string get_element(const char *index, std::vector<std::string> &fields);
|
string get_element(const char *index, std::vector<std::string> &fields);
|
||||||
string recode_text(std::vector<std::string> &fields);
|
string recode_text(std::vector<std::string> &fields);
|
||||||
void add_attachment_maybe(std::string &name, std::string &data_uu, ssa_section_e section);
|
void add_attachment_maybe(std::string &name, std::string &data_uu, ssa_section_e section);
|
||||||
void decode_chars(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, buffer_t &buffer, int bytes_to_add, int &allocated);
|
void decode_chars(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, memory_cptr &buffer, int bytes_to_add, int &allocated);
|
||||||
};
|
};
|
||||||
typedef counted_ptr<ssa_parser_c> ssa_parser_cptr;
|
typedef counted_ptr<ssa_parser_c> ssa_parser_cptr;
|
||||||
|
|
||||||
|
@ -196,7 +196,11 @@ set_usage() {
|
|||||||
usage_text += Y(" -b, --btracks <n,m,...> Copy buttons tracks n,m etc. Default: copy\n"
|
usage_text += Y(" -b, --btracks <n,m,...> Copy buttons tracks n,m etc. Default: copy\n"
|
||||||
" all buttons tracks.\n");
|
" all buttons tracks.\n");
|
||||||
usage_text += Y(" -B, --nobuttons Don't copy any buttons track from this file.\n");
|
usage_text += Y(" -B, --nobuttons Don't copy any buttons track from this file.\n");
|
||||||
usage_text += Y(" --no-attachments Don't keep attachments from a Matroska file.\n");
|
usage_text += Y(" -m, --attachments <n[:all|first],m[:all|first],...>\n"
|
||||||
|
" Copy the attachments with the IDs n, m etc to\n"
|
||||||
|
" all or only the first output file. Default: copy\n"
|
||||||
|
" all attachments to all output files.\n");
|
||||||
|
usage_text += Y(" -M, --no-attachments Don't copy attachments from a Matroska file.\n");
|
||||||
usage_text += Y(" --no-chapters Don't keep chapters from a Matroska file.\n");
|
usage_text += Y(" --no-chapters Don't keep chapters from a Matroska file.\n");
|
||||||
usage_text += Y(" --no-tags Don't keep tags from a Matroska file.\n");
|
usage_text += Y(" --no-tags Don't keep tags from a Matroska file.\n");
|
||||||
usage_text += Y(" -y, --sync, --delay <TID:d[,o[/p]]>\n"
|
usage_text += Y(" -y, --sync, --delay <TID:d[,o[/p]]>\n"
|
||||||
@ -1407,14 +1411,13 @@ parse_arg_attach_file(attachment_t &attachment,
|
|||||||
attachment.mime_type = guess_mime_type_and_report(arg);
|
attachment.mime_type = guess_mime_type_and_report(arg);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
attachment.data = counted_ptr<buffer_t>(new buffer_t);
|
mm_io_cptr io = mm_io_cptr(new mm_file_io_c(attachment.name));
|
||||||
mm_io_cptr io = mm_io_cptr(new mm_file_io_c(attachment.name));
|
|
||||||
attachment.data->m_size = io->get_size();
|
|
||||||
|
|
||||||
if (0 == attachment.data->m_size)
|
if (0 == io->get_size())
|
||||||
mxerror(boost::format(Y("The size of attachment '%1%' is 0.\n")) % attachment.name);
|
mxerror(boost::format(Y("The size of attachment '%1%' is 0.\n")) % attachment.name);
|
||||||
|
|
||||||
attachment.data->m_buffer = (unsigned char *)safemalloc(attachment.data->m_size); io->read(attachment.data->m_buffer, attachment.data->m_size);
|
attachment.data = memory_c::alloc(io->get_size());
|
||||||
|
io->read(attachment.data->get(), attachment.data->get_size());
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
mxerror(boost::format(Y("The attachment '%1%' could not be read.\n")) % attachment.name);
|
mxerror(boost::format(Y("The attachment '%1%' could not be read.\n")) % attachment.name);
|
||||||
@ -1507,6 +1510,37 @@ parse_arg_default_language(const string &arg) {
|
|||||||
g_default_language = iso639_languages[i].iso639_2_code;
|
g_default_language = iso639_languages[i].iso639_2_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_arg_attachments(const string ¶m,
|
||||||
|
const string &arg,
|
||||||
|
track_info_c &ti) {
|
||||||
|
vector<string> elements = split(arg, ",");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; elements.size() > i; ++i) {
|
||||||
|
vector<string> pair = split(elements[i], ":");
|
||||||
|
|
||||||
|
if (1 == pair.size())
|
||||||
|
pair.push_back("all");
|
||||||
|
|
||||||
|
else if (2 != pair.size())
|
||||||
|
mxerror(boost::format(Y("The argument '%1%' to '%2%' is invalid: too many colons in element '%3%'.\n")) % arg % param % elements[i]);
|
||||||
|
|
||||||
|
int64_t id;
|
||||||
|
if (!parse_int(pair[0], id))
|
||||||
|
mxerror(boost::format(Y("The argument '%1%' to '%2%' is invalid: '%3%' is not a valid track ID.\n")) % arg % param % pair[0]);
|
||||||
|
|
||||||
|
if (pair[1] == "all")
|
||||||
|
ti.attach_mode_list[id] = ATTACH_MODE_TO_ALL_FILES;
|
||||||
|
|
||||||
|
else if (pair[1] == "first")
|
||||||
|
ti.attach_mode_list[id] = ATTACH_MODE_TO_FIRST_FILE;
|
||||||
|
|
||||||
|
else
|
||||||
|
mxerror(boost::format(Y("The argument '%1%' to '%2%' is invalid: '%3%' must be either 'all' or 'first'.\n")) % arg % param % pair[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** \brief Parses and handles command line arguments
|
/** \brief Parses and handles command line arguments
|
||||||
|
|
||||||
Also probes input files for their type and creates the appropriate
|
Also probes input files for their type and creates the appropriate
|
||||||
@ -1792,9 +1826,16 @@ parse_args(vector<string> args) {
|
|||||||
} else if (this_arg == "--no-chapters") {
|
} else if (this_arg == "--no-chapters") {
|
||||||
ti->no_chapters = true;
|
ti->no_chapters = true;
|
||||||
|
|
||||||
} else if (this_arg == "--no-attachments") {
|
} else if ((this_arg == "-M") || (this_arg == "--no-attachments")) {
|
||||||
ti->no_attachments = true;
|
ti->no_attachments = true;
|
||||||
|
|
||||||
|
} else if ((this_arg == "-m") || (this_arg == "--attachments")) {
|
||||||
|
if (no_next_arg)
|
||||||
|
mxerror(boost::format(Y("'%1%' lacks its argument.")) % this_arg);
|
||||||
|
|
||||||
|
parse_arg_attachments(this_arg, next_arg, *ti);
|
||||||
|
sit++;
|
||||||
|
|
||||||
} else if (this_arg == "--no-tags") {
|
} else if (this_arg == "--no-tags") {
|
||||||
ti->no_tags = true;
|
ti->no_tags = true;
|
||||||
|
|
||||||
|
@ -466,9 +466,9 @@ add_attachment(attachment_t attachment) {
|
|||||||
if (( (i->id == attachment.id)
|
if (( (i->id == attachment.id)
|
||||||
&& !hack_engaged(ENGAGE_NO_VARIABLE_DATA))
|
&& !hack_engaged(ENGAGE_NO_VARIABLE_DATA))
|
||||||
||
|
||
|
||||||
( (i->name == attachment.name)
|
( (i->name == attachment.name)
|
||||||
&& (i->description == attachment.description)
|
&& (i->description == attachment.description)
|
||||||
&& (i->data->m_size == attachment.data->m_size)))
|
&& (i->data->get_size() == attachment.data->get_size())))
|
||||||
return attachment.id;
|
return attachment.id;
|
||||||
|
|
||||||
add_unique_uint32(attachment.id, UNIQUE_ATTACHMENT_IDS);
|
add_unique_uint32(attachment.id, UNIQUE_ATTACHMENT_IDS);
|
||||||
@ -764,7 +764,7 @@ render_attachments(IOCallback *out) {
|
|||||||
GetChildAs<KaxFileName, EbmlUnicodeString>(kax_a) = cstr_to_UTFstring(name);
|
GetChildAs<KaxFileName, EbmlUnicodeString>(kax_a) = cstr_to_UTFstring(name);
|
||||||
GetChildAs<KaxFileUID, EbmlUInteger>(kax_a) = attch->id;
|
GetChildAs<KaxFileUID, EbmlUInteger>(kax_a) = attch->id;
|
||||||
|
|
||||||
GetChild<KaxFileData>(*kax_a).CopyBuffer(attch->data->m_buffer, attch->data->m_size);
|
GetChild<KaxFileData>(*kax_a).CopyBuffer(attch->data->get(), attch->data->get_size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,9 +1143,9 @@ create_readers() {
|
|||||||
|
|
||||||
// Calculate the size of all attachments for split control.
|
// Calculate the size of all attachments for split control.
|
||||||
mxforeach(att, g_attachments) {
|
mxforeach(att, g_attachments) {
|
||||||
g_attachment_sizes_first += att->data->m_size;
|
g_attachment_sizes_first += att->data->get_size();
|
||||||
if (att->to_all_files)
|
if (att->to_all_files)
|
||||||
g_attachment_sizes_others += att->data->m_size;
|
g_attachment_sizes_others += att->data->get_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
calc_max_chapter_size();
|
calc_max_chapter_size();
|
||||||
|
@ -96,19 +96,21 @@ struct attachment_t {
|
|||||||
string name, stored_name, mime_type, description;
|
string name, stored_name, mime_type, description;
|
||||||
int64_t id;
|
int64_t id;
|
||||||
bool to_all_files;
|
bool to_all_files;
|
||||||
counted_ptr<buffer_t> data;
|
memory_cptr data;
|
||||||
|
int64_t ui_id;
|
||||||
|
|
||||||
attachment_t() {
|
attachment_t() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
name = "";
|
name = "";
|
||||||
stored_name = "";
|
stored_name = "";
|
||||||
mime_type = "";
|
mime_type = "";
|
||||||
description = "";
|
description = "";
|
||||||
id = 0;
|
id = 0;
|
||||||
|
ui_id = 0;
|
||||||
to_all_files = false;
|
to_all_files = false;
|
||||||
data = counted_ptr<buffer_t>(NULL);
|
data = memory_cptr(NULL);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1124,6 +1124,23 @@ generic_reader_c::demuxing_requested(char type,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attach_mode_e
|
||||||
|
generic_reader_c::attachment_requested(int64_t id) {
|
||||||
|
if (ti.no_attachments)
|
||||||
|
return ATTACH_MODE_SKIP;
|
||||||
|
|
||||||
|
if (ti.attach_mode_list.empty())
|
||||||
|
return ATTACH_MODE_TO_ALL_FILES;
|
||||||
|
|
||||||
|
if (map_has_key(ti.attach_mode_list, id))
|
||||||
|
return ti.attach_mode_list[id];
|
||||||
|
|
||||||
|
if (map_has_key(ti.attach_mode_list, -1))
|
||||||
|
return ti.attach_mode_list[-1];
|
||||||
|
|
||||||
|
return ATTACH_MODE_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
generic_reader_c::add_packetizer(generic_packetizer_c *ptzr) {
|
generic_reader_c::add_packetizer(generic_packetizer_c *ptzr) {
|
||||||
reader_packetizers.push_back(ptzr);
|
reader_packetizers.push_back(ptzr);
|
||||||
@ -1454,6 +1471,8 @@ track_info_c::operator =(const track_info_c &src) {
|
|||||||
nalu_size_lengths = src.nalu_size_lengths;
|
nalu_size_lengths = src.nalu_size_lengths;
|
||||||
nalu_size_length = src.nalu_size_length;
|
nalu_size_length = src.nalu_size_length;
|
||||||
|
|
||||||
|
attach_mode_list = src.attach_mode_list;
|
||||||
|
|
||||||
no_chapters = src.no_chapters;
|
no_chapters = src.no_chapters;
|
||||||
no_attachments = src.no_attachments;
|
no_attachments = src.no_attachments;
|
||||||
no_tags = src.no_tags;
|
no_tags = src.no_tags;
|
||||||
|
@ -165,6 +165,12 @@ enum stereo_mode_e {
|
|||||||
STEREO_MODE_BOTH = 3,
|
STEREO_MODE_BOTH = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum attach_mode_e {
|
||||||
|
ATTACH_MODE_SKIP,
|
||||||
|
ATTACH_MODE_TO_FIRST_FILE,
|
||||||
|
ATTACH_MODE_TO_ALL_FILES,
|
||||||
|
};
|
||||||
|
|
||||||
class track_info_c {
|
class track_info_c {
|
||||||
protected:
|
protected:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
@ -234,6 +240,8 @@ public:
|
|||||||
map<int64_t, int> nalu_size_lengths;
|
map<int64_t, int> nalu_size_lengths;
|
||||||
int nalu_size_length;
|
int nalu_size_length;
|
||||||
|
|
||||||
|
map<int64_t, attach_mode_e> attach_mode_list; // As given on the command line
|
||||||
|
|
||||||
bool no_chapters, no_attachments, no_tags;
|
bool no_chapters, no_attachments, no_tags;
|
||||||
|
|
||||||
// Some file formats can contain chapters, but for some the charset
|
// Some file formats can contain chapters, but for some the charset
|
||||||
@ -315,6 +323,8 @@ public:
|
|||||||
|
|
||||||
virtual void flush_packetizers();
|
virtual void flush_packetizers();
|
||||||
|
|
||||||
|
virtual attach_mode_e attachment_requested(int64_t id);
|
||||||
|
|
||||||
virtual void display_identification_results();
|
virtual void display_identification_results();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -64,7 +64,7 @@ T_213mp4_broken_pixel_dimensions:dc4f6c0c82b1d1aabaadac51d70b77c0:passed:2005091
|
|||||||
T_214one_frame_avi:bea975277e91ded1a4085043e89608ce:passed:20051004-192755
|
T_214one_frame_avi:bea975277e91ded1a4085043e89608ce:passed:20051004-192755
|
||||||
T_215X_codec_extradata_avi:78d669fc6511b6b931cd0981e2e1cca9-3fabc505fdd377c05ce4557b1bc13545:passed:20051004-194707
|
T_215X_codec_extradata_avi:78d669fc6511b6b931cd0981e2e1cca9-3fabc505fdd377c05ce4557b1bc13545:passed:20051004-194707
|
||||||
T_216mp4_editlists:16705ae21c46e6d1b64ca55b5d54ed9d:passed:20051118-191453
|
T_216mp4_editlists:16705ae21c46e6d1b64ca55b5d54ed9d:passed:20051118-191453
|
||||||
T_217file_identification:ef3c502529537c1d3699d0e0487751c3-39c82d78b1ea6ffc1ccd20f07f2cfcc6-9e935f2c47c31e35d5267859601f4bf6-fdcd19f0b817e3db32c3d891f283462e-57f72aff43b852c96e8929495d91bebf-9c926be4a5c0dbf460ebc0c0ecf9a756-d7678dc91cba91a946c22e5b96f3b3b6-3f60e3a03129d1e4610ae668459457cc-c170654ad0688c40fc9e2ceeb9ef0b9f-6b44c4e351ac48b7fdb63355c65783eb-d701319c3f77c58adfee92b1186a3993-12aa395d3bc0431c5acb81bc4407b70f-3e7956db47487933b47241fc7bc76359-52dfc8091ce64db9f8ad44aee34748ec-6b7149a5774a37d214b8085c6409aab3-15beba0108723bff77bf8d88876f8f31-72fabb6ff0194c82321db1c317b11c63-2b03944260062946d1ceabde9c71e007-87cb6b0e3933210309228a79d3a3f823-34b0b13ac1b1b3ced17cbb31df973d62-e592a5d28c92ebb23fe6d7ea901ec0a9-f997737ca7eff867d33ee58af611e741:passed:20051209-180815
|
T_217file_identification:ef3c502529537c1d3699d0e0487751c3-39c82d78b1ea6ffc1ccd20f07f2cfcc6-9055d420c47bb3d615271d6af02bb9ce-fdcd19f0b817e3db32c3d891f283462e-57f72aff43b852c96e8929495d91bebf-9c926be4a5c0dbf460ebc0c0ecf9a756-d7678dc91cba91a946c22e5b96f3b3b6-3f60e3a03129d1e4610ae668459457cc-c170654ad0688c40fc9e2ceeb9ef0b9f-6b44c4e351ac48b7fdb63355c65783eb-d701319c3f77c58adfee92b1186a3993-12aa395d3bc0431c5acb81bc4407b70f-3e7956db47487933b47241fc7bc76359-52dfc8091ce64db9f8ad44aee34748ec-6b7149a5774a37d214b8085c6409aab3-15beba0108723bff77bf8d88876f8f31-72fabb6ff0194c82321db1c317b11c63-2b03944260062946d1ceabde9c71e007-87cb6b0e3933210309228a79d3a3f823-34b0b13ac1b1b3ced17cbb31df973d62-e592a5d28c92ebb23fe6d7ea901ec0a9-f997737ca7eff867d33ee58af611e741:passed:20051209-180815
|
||||||
T_218theora:b09cfce53d36b68422e315bf5ff12341-fac4b041366588e3c8215b9fbb696db2:passed:20060428-105054
|
T_218theora:b09cfce53d36b68422e315bf5ff12341-fac4b041366588e3c8215b9fbb696db2:passed:20060428-105054
|
||||||
T_219srt_short_timecodes:a7db07ee64751fcc24993dd4af73ccf1:passed:20060926-112658
|
T_219srt_short_timecodes:a7db07ee64751fcc24993dd4af73ccf1:passed:20060926-112658
|
||||||
T_220ass_with_comments_at_start:51ccd0cbe4e60b21817d7547310250bb:passed:20060926-120101
|
T_220ass_with_comments_at_start:51ccd0cbe4e60b21817d7547310250bb:passed:20060926-120101
|
||||||
|
Loading…
Reference in New Issue
Block a user