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:
Moritz Bunkus 2004-11-13 12:59:02 +00:00
parent f4b2713eab
commit 03184bb462
7 changed files with 142 additions and 40 deletions

View File

@ -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();
}

View File

@ -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

View File

@ -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)

View File

@ -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());
}

View File

@ -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

View File

@ -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:

View File

@ -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