mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-23 19:31:44 +00:00
Changed the chapter handling to a per-reader basis. This will allow for chapter concatenation when concatenating files. This also means that chapters cannot be written before the output file is closed. Reserving enough space at the beginning is therefore necessary.
This commit is contained in:
parent
f4b2713eab
commit
03184bb462
@ -569,3 +569,55 @@ find_chapter_with_uid(KaxChapters &chapters,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Move all chapter atoms to another container keeping editions intact
|
||||
*
|
||||
* This function moves all chapter atoms from \a src to \a dst.
|
||||
* If there's already an edition in \a dst with the same UID as the current
|
||||
* one in \a src, then all atoms will be put into that edition. Otherwise
|
||||
* the complete edition will simply be moved over.
|
||||
*
|
||||
* After processing \a src will be empty.
|
||||
*
|
||||
* \param dst The container the atoms and editions will be put into.
|
||||
* \param src The container the atoms and editions will be taken from.
|
||||
*/
|
||||
void
|
||||
move_chapters_by_edition(KaxChapters &dst,
|
||||
KaxChapters &src) {
|
||||
int i, k;
|
||||
|
||||
for (i = 0; i < src.ListSize(); i++) {
|
||||
KaxEditionEntry *ee_dst;
|
||||
KaxEditionUID *euid_src, *euid_dst;
|
||||
EbmlMaster *m;
|
||||
|
||||
m = static_cast<EbmlMaster *>(src[i]);
|
||||
|
||||
// Find an edition to which these atoms will be added.
|
||||
ee_dst = NULL;
|
||||
euid_src = FINDFIRST(m, KaxEditionUID);
|
||||
if (euid_src != NULL) {
|
||||
for (k = 0; k < dst.ListSize(); k++) {
|
||||
euid_dst = FINDFIRST(static_cast<EbmlMaster *>(dst[k]),
|
||||
KaxEditionUID);
|
||||
if ((euid_dst != NULL) && (uint32(*euid_src) == uint32(*euid_dst))) {
|
||||
ee_dst = static_cast<KaxEditionEntry *>(dst[k]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// No edition with the same UID found as the one we want to handle?
|
||||
// Then simply move the complete edition over.
|
||||
if (ee_dst == NULL)
|
||||
dst.PushElement(*m);
|
||||
else {
|
||||
// Move all atoms from the old edition to the new one.
|
||||
for (k = 0; k < m->ListSize(); k++)
|
||||
ee_dst->PushElement(*(*m)[k]);
|
||||
m->RemoveAll();
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
src.RemoveAll();
|
||||
}
|
||||
|
@ -94,5 +94,7 @@ KaxEditionEntry *MTX_DLL_API find_edition_with_uid(KaxChapters &chapters,
|
||||
KaxChapterAtom *MTX_DLL_API find_chapter_with_uid(KaxChapters &chapters,
|
||||
uint64_t uid);
|
||||
|
||||
void MTX_DLL_API move_chapters_by_edition(KaxChapters &dst, KaxChapters &src);
|
||||
|
||||
#endif // __CHAPTERS_H
|
||||
|
||||
|
@ -680,12 +680,12 @@ void
|
||||
kax_reader_c::handle_chapters(mm_io_c *io,
|
||||
EbmlElement *l0,
|
||||
int64_t pos) {
|
||||
KaxChapters *chapters;
|
||||
KaxChapters *tmp_chapters;
|
||||
EbmlElement *l1, *l2;
|
||||
int upper_lvl_el, i;
|
||||
bool found;
|
||||
|
||||
if (ti->no_chapters || (kax_chapters != NULL))
|
||||
if (ti->no_chapters)
|
||||
return;
|
||||
|
||||
found = false;
|
||||
@ -702,13 +702,18 @@ kax_reader_c::handle_chapters(mm_io_c *io,
|
||||
l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL,
|
||||
true);
|
||||
|
||||
if ((l1 != NULL) && (EbmlId(*l1) == KaxChapters::ClassInfos.GlobalId)) {
|
||||
chapters = (KaxChapters *)l1;
|
||||
if ((l1 != NULL) && is_id(l1, KaxChapters)) {
|
||||
tmp_chapters = static_cast<KaxChapters *>(l1);
|
||||
l2 = NULL;
|
||||
upper_lvl_el = 0;
|
||||
chapters->Read(*es, KaxChapters::ClassInfos.Context, upper_lvl_el,
|
||||
tmp_chapters->Read(*es, KaxChapters::ClassInfos.Context, upper_lvl_el,
|
||||
l2, true);
|
||||
kax_chapters = copy_chapters(chapters);
|
||||
|
||||
if (chapters == NULL)
|
||||
chapters = new KaxChapters;
|
||||
for (i = 0; i < tmp_chapters->ListSize(); i++)
|
||||
chapters->PushElement(*(*tmp_chapters)[i]);
|
||||
tmp_chapters->RemoveAll();
|
||||
|
||||
delete l1;
|
||||
} else if (l1 != NULL)
|
||||
|
@ -147,6 +147,7 @@ static KaxAttachments *kax_as = NULL;
|
||||
|
||||
static EbmlVoid *kax_sh_void = NULL;
|
||||
static EbmlVoid *kax_chapters_void = NULL;
|
||||
static int64_t max_chapter_size = 0;
|
||||
static EbmlVoid *void_after_track_headers = NULL;
|
||||
|
||||
string chapter_file_name;
|
||||
@ -991,6 +992,57 @@ check_append_mapping() {
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Add chapters from the readers and calculate the max size
|
||||
*
|
||||
* The reader do not add their chapters to the global chapter pool.
|
||||
* This has to be done after creating the readers. Only the chapters
|
||||
* of readers that aren't appended are put into the pool right away.
|
||||
* The other chapters are added when a packetizer is appended because
|
||||
* the chapter timecodes have to be adjusted by the length of the file
|
||||
* the packetizer is appended to.
|
||||
* This function also calculates the sum of all chapter sizes so that
|
||||
* enough space can be allocated at the start of each output file.
|
||||
*/
|
||||
void
|
||||
calc_max_chapter_size() {
|
||||
vector<filelist_t>::iterator file;
|
||||
KaxChapters *chapters;
|
||||
|
||||
// Step 1: Add all chapters from files that are not being appended.
|
||||
foreach(file, files) {
|
||||
if (file->appending)
|
||||
continue;
|
||||
chapters = file->reader->chapters;
|
||||
if (chapters == NULL)
|
||||
continue;
|
||||
|
||||
if (kax_chapters == NULL)
|
||||
kax_chapters = new KaxChapters;
|
||||
|
||||
move_chapters_by_edition(*kax_chapters, *chapters);
|
||||
delete chapters;
|
||||
file->reader->chapters = NULL;
|
||||
}
|
||||
|
||||
// Step 2: Fix the mandatory elements and count the size of all chapters.
|
||||
max_chapter_size = 0;
|
||||
if (kax_chapters != NULL) {
|
||||
fix_mandatory_chapter_elements(kax_chapters);
|
||||
kax_chapters->UpdateSize(true);
|
||||
max_chapter_size += kax_chapters->ElementSize();
|
||||
}
|
||||
|
||||
foreach(file, files) {
|
||||
chapters = file->reader->chapters;
|
||||
if (chapters == NULL)
|
||||
continue;
|
||||
|
||||
fix_mandatory_chapter_elements(chapters);
|
||||
chapters->UpdateSize(true);
|
||||
max_chapter_size += chapters->ElementSize();
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Creates the file readers
|
||||
*
|
||||
* For each file the appropriate file reader class is instantiated.
|
||||
@ -1084,6 +1136,8 @@ create_readers() {
|
||||
if (att->to_all_files)
|
||||
attachment_sizes_others += att->size;
|
||||
}
|
||||
|
||||
calc_max_chapter_size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1232,29 +1286,11 @@ create_next_output_file() {
|
||||
cluster_helper->set_output(out);
|
||||
render_headers(out);
|
||||
render_attachments(out);
|
||||
if (kax_chapters != NULL) {
|
||||
fix_mandatory_chapter_elements(kax_chapters);
|
||||
sort_ebml_master(kax_chapters);
|
||||
if (splitting) {
|
||||
kax_chapters_void = new EbmlVoid;
|
||||
kax_chapters->UpdateSize(true);
|
||||
kax_chapters_void->SetSize(kax_chapters->ElementSize() + 10);
|
||||
kax_chapters_void->Render(*out);
|
||||
if (hack_engaged(ENGAGE_SPACE_AFTER_CHAPTERS)) {
|
||||
EbmlVoid evoid;
|
||||
evoid.SetSize(100);
|
||||
evoid.Render(*out);
|
||||
}
|
||||
} else {
|
||||
chapters_in_this_file =
|
||||
static_cast<KaxChapters *>(kax_chapters->Clone());
|
||||
kax_chapters->Render(*out, true);
|
||||
if (hack_engaged(ENGAGE_SPACE_AFTER_CHAPTERS)) {
|
||||
EbmlVoid evoid;
|
||||
evoid.SetSize(100);
|
||||
evoid.Render(*out);
|
||||
}
|
||||
}
|
||||
|
||||
if (max_chapter_size > 0) {
|
||||
kax_chapters_void = new EbmlVoid;
|
||||
kax_chapters_void->SetSize(max_chapter_size + 100);
|
||||
kax_chapters_void->Render(*out);
|
||||
}
|
||||
|
||||
add_tags_from_cue_chapters();
|
||||
@ -1346,9 +1382,9 @@ finish_file(bool last_file) {
|
||||
}
|
||||
out->restore_pos();
|
||||
|
||||
// If splitting is active: Select the chapters that lie in this file
|
||||
// and render them in the space that was resesrved at the beginning.
|
||||
if ((kax_chapters != NULL) && splitting) {
|
||||
// Select the chapters that lie in this file and render them in the space
|
||||
// that was resesrved at the beginning.
|
||||
if (kax_chapters != NULL) {
|
||||
if (no_linking)
|
||||
offset = cluster_helper->get_timecode_offset();
|
||||
else
|
||||
@ -1357,10 +1393,12 @@ finish_file(bool last_file) {
|
||||
end = cluster_helper->get_max_timecode() + offset;
|
||||
|
||||
chapters_here = copy_chapters(kax_chapters);
|
||||
chapters_here = select_chapters_in_timeframe(chapters_here, start, end,
|
||||
offset);
|
||||
if (splitting)
|
||||
chapters_here = select_chapters_in_timeframe(chapters_here, start, end,
|
||||
offset);
|
||||
if (chapters_here != NULL) {
|
||||
kax_chapters_void->ReplaceWith(*chapters_here, *out, true, false);
|
||||
sort_ebml_master(chapters_here);
|
||||
kax_chapters_void->ReplaceWith(*chapters_here, *out, true, true);
|
||||
chapters_in_this_file =
|
||||
static_cast<KaxChapters *>(chapters_here->Clone());
|
||||
}
|
||||
|
@ -1022,6 +1022,7 @@ generic_reader_c::generic_reader_c(track_info_c *nti) {
|
||||
ti = new track_info_c(*nti);
|
||||
max_timecode_seen = 0;
|
||||
appending = false;
|
||||
chapters = NULL;
|
||||
|
||||
add_all_requested_track_ids2(atracks);
|
||||
add_all_requested_track_ids2(vtracks);
|
||||
@ -1048,6 +1049,8 @@ generic_reader_c::~generic_reader_c() {
|
||||
for (i = 0; i < reader_packetizers.size(); i++)
|
||||
delete reader_packetizers[i];
|
||||
delete ti;
|
||||
if (chapters != NULL)
|
||||
delete chapters;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <matroska/KaxAttachments.h>
|
||||
#include <matroska/KaxBlock.h>
|
||||
#include <matroska/KaxChapters.h>
|
||||
#include <matroska/KaxCluster.h>
|
||||
#include <matroska/KaxTracks.h>
|
||||
#include <matroska/KaxTags.h>
|
||||
@ -249,6 +250,7 @@ public:
|
||||
vector<generic_packetizer_c *> reader_packetizers;
|
||||
vector<int64_t> requested_track_ids, available_track_ids, used_track_ids;
|
||||
int64_t max_timecode_seen;
|
||||
KaxChapters *chapters;
|
||||
bool appending;
|
||||
|
||||
public:
|
||||
|
@ -13,18 +13,18 @@ T_012ssa:9ecbc6bdfa5dec6495f99c7a97342844:passed:20040825-175700
|
||||
T_013vobsubs:8983288ea21b811fbb85d2ea272ccfe5:passed:20040825-175700
|
||||
T_014splitting_by_size:feeb1aba481b5a51d7142599359f2eac-5c639e8a08cf526d051fdf64f856c0d2:passed:20040825-175700
|
||||
T_015splitting_by_time:d0e769a906ec4eacc9c9af929add6474-c32e2d8c31e21e71f68875f2d9735565:passed:20040825-175700
|
||||
T_016cuesheet:01f54d36479c8ae4b4d357607a42a967:passed:20040825-175700
|
||||
T_017chapters:990b4b6b0931b7d52e589f715c919e10-4fff45a76f54708f881312aca04fd887:passed:20040825-175700
|
||||
T_016cuesheet:61b3a09c06ba2a8c7018d045d80f9c30:passed:20040825-175700
|
||||
T_017chapters:562b2281edfa5acca556c3f77f60a291-4b54a7add7783cb99d83dd476a50e135:passed:20040825-175700
|
||||
T_018attachments:bac27359516bab4984df3021aa295213-7e8e1f17615f157db0e98fba9ad88bad:passed:20040825-175700
|
||||
T_019attachments2:8d9ba46c4edbf3daf50175f9de2f87b4-94349d68c9b7d493ec0d5a49f7291e40-8d9ba46c4edbf3daf50175f9de2f87b4-5c639e8a08cf526d051fdf64f856c0d2:passed:20040825-175700
|
||||
T_020languages:7d853f21fe2d3e73b3ca0d29801e8d39:passed:20040825-234208
|
||||
T_020languages:a2ade9796f89718812d0ef9926922c38:passed:20040825-234208
|
||||
T_021aspect_ratio:f6e8aa4cfd776d99ff824f21d4e3c640-990a5f94678b5c8886dc8c3a5c6a22dd:passed:20040825-234244
|
||||
T_022display_dimensions:108880396ffe5244465a3d25e8a57f93:passed:20040825-234339
|
||||
T_023no_x:0b7f257f1c801da7b2ef1976291e5d44-49870185a891e8b3f6f265dca6f0e707-c43a34f68db19f5a318bd90c6f6446ab:passed:20040825-234343
|
||||
T_023no_x:d9050dde3ea2a39a35b9efb780a61fff-49870185a891e8b3f6f265dca6f0e707-d15f9adb4f18c8b6c363a16c78da5108:passed:20040825-234343
|
||||
T_024sync_mp3:a6c35d309947a52196d2a5428f87224a-6a638028d795bd48db95446f3521c302:passed:20040825-234344
|
||||
T_025sync_vorbis:e9d13a6b769cf6c2e4987bf6bd160698-51fcfab150642a66484d3c6bedff697a:passed:20040825-234344
|
||||
T_026sync_pcm:f337f057c059d771128206c0da3d4807-9b559191edb65655e49186c302c4b815:passed:20040825-234346
|
||||
T_027default_track:5e3cdf80eff356e84a94c877f6514b02:passed:20040825-234348
|
||||
T_027default_track:83aac330703cc65128bb74b5edb21e8a:passed:20040825-234348
|
||||
T_028compression:f6c15855e42e5a0e80d22a2060ae13e8:passed:20040825-234348
|
||||
T_029link:d92e5f123b799212f65bb7b394dd4f6e:passed:20040825-235039
|
||||
T_032cues:f84c58a6380b3104434b6943e0eb87e3:passed:20040825-235040
|
||||
|
Loading…
Reference in New Issue
Block a user