The start of support for situations like this: the user appends an AVI to an AVI and VobSubs to VobSubs. In such a case simply using the previous file's max timecode won't work for the subtitle-only files. Therefore mkvmerge has to look for an "associated" file whose max timecode it has to use. This has not been finished yet.

This commit is contained in:
Moritz Bunkus 2004-11-15 16:01:13 +00:00
parent aae24e6fef
commit df7fcc62de
7 changed files with 82 additions and 33 deletions

View File

@ -138,7 +138,7 @@ cluster_helper_c::add_packet(packet_t *packet) {
if (splitting && (file_num <= split_max_num_files) &&
(packet->bref == -1) &&
((packet->source->get_track_type() == track_video) ||
!video_track_present)) {
(video_packetizer == NULL))) {
split = false;
c = clusters[num_clusters - 1];
if (first_timecode_in_file == -1)
@ -536,7 +536,8 @@ cluster_helper_c::render_cluster(ch_contents_t *clstr) {
// ... or if this is an audio track, there is no video track and the
// last cue entry was created more than 2s ago.
((source->get_cue_creation() == CUES_SPARSE) &&
(source->get_track_type() == track_audio) && !video_track_present &&
(source->get_track_type() == track_audio) &&
(video_packetizer == NULL) &&
((source->get_last_cue_timecode() < 0) ||
((pack->assigned_timecode - source->get_last_cue_timecode()) >=
2000000000)))) {

View File

@ -323,8 +323,6 @@ identify(const string &filename) {
file.name);
file.appending = false;
file.fp = NULL;
file.status = EMOREDATA;
file.pack = NULL;
file.ti = new track_info_c(ti);
@ -1725,11 +1723,10 @@ parse_args(vector<string> &args) {
"your file type is supported but not recognized "
"properly.\n"), file.name);
file.fp = NULL;
if (file.type != TYPECHAPTERS) {
file.status = EMOREDATA;
file.pack = NULL;
file.ti = ti;
file.done = false;
files.push_back(file);
} else {

View File

@ -113,7 +113,7 @@ int64_t file_sizes = 0;
int max_blocks_per_cluster = 65535;
int64_t max_ns_per_cluster = 2000000000;
bool write_cues = true, cue_writing_requested = false;
bool video_track_present = false;
generic_packetizer_c *video_packetizer = NULL;
bool write_meta_seek_for_clusters = true;
bool no_lacing = false, no_linking = true;
int64_t split_after = -1;
@ -464,7 +464,7 @@ render_headers(mm_io_c *rout) {
kax_infos = &GetChild<KaxInfo>(*kax_segment);
if (!video_track_present ||
if ((video_packetizer == NULL) ||
(timecode_scale_mode == timecode_scale_mode_auto))
kax_duration = new KaxMyDuration(EbmlFloat::FLOAT_64);
else
@ -1511,9 +1511,36 @@ append_track(packetizer_t &ptzr,
// If we're dealing with a subtitle track or if the appending file contains
// chapters then we have to suck the previous file dry. See below for the
// reason (short version: we need all max_timecode_seen values).
if (((*gptzr)->get_track_type() == track_subtitle) ||
(src_file.reader->chapters != NULL))
if ((((*gptzr)->get_track_type() == track_subtitle) ||
(src_file.reader->chapters != NULL)) &&
!dst_file.done) {
vector<deferred_connection_t>::const_iterator def_con;
dst_file.reader->read_all();
dst_file.done = true;
foreach(def_con, dst_file.deferred_connections)
append_track(*def_con->ptzr, def_con->amap);
dst_file.deferred_connections.clear();
}
if (((*gptzr)->get_track_type() == track_subtitle) &&
(dst_file.reader->num_video_tracks == 0) &&
(video_packetizer != NULL) && !ptzr.deferred) {
vector<filelist_t>::iterator file;
foreach(file, files) {
if (mxfind(video_packetizer, file->reader->reader_packetizers) !=
file->reader->reader_packetizers.end()) {
deferred_connection_t new_def_con;
ptzr.deferred = true;
new_def_con.amap = amap;
new_def_con.ptzr = &ptzr;
file->deferred_connections.push_back(new_def_con);
return;
}
}
}
mxinfo("Appending track %lld from file no. %lld ('%s') to track %lld from "
"file no. %lld ('%s').\n",
@ -1550,8 +1577,9 @@ append_track(packetizer_t &ptzr,
// But then again I don't expect that people will try to concatenate such
// files if they've been split before.
timecode_adjustment = dst_file.reader->max_timecode_seen;
if ((ptzr.packetizer->get_track_type() == track_subtitle) ||
(src_file.reader->chapters != NULL)) {
if (((ptzr.packetizer->get_track_type() == track_subtitle) ||
(src_file.reader->chapters != NULL)) &&
!ptzr.deferred) {
vector<append_spec_t>::const_iterator cmp_amap;
if (src_file.reader->ptzr_first_packet == NULL)
@ -1587,6 +1615,8 @@ append_track(packetizer_t &ptzr,
delete src_file.reader->chapters;
src_file.reader->chapters = NULL;
}
ptzr.deferred = false;
}
/** \brief Decide if packetizers have to be appended
@ -1605,6 +1635,8 @@ append_tracks_maybe() {
appended_a_track = false;
foreach(ptzr, packetizers) {
if (ptzr->deferred)
continue;
if (!files[ptzr->orig_file].appended_to)
continue;
if ((ptzr->status == EMOREDATA) || (ptzr->status == EHOLDING))

View File

@ -38,26 +38,40 @@ class generic_packetizer_c;
class generic_reader_c;
typedef struct {
char *name;
mm_io_c *fp;
int type, status;
packet_t *pack;
generic_reader_c *reader;
track_info_c *ti;
bool appending, appended_to;
} filelist_t;
int64_t src_file_id;
int64_t src_track_id;
int64_t dst_file_id;
int64_t dst_track_id;
} append_spec_t;
typedef struct packetizer_t {
int status;
packet_t *pack;
generic_packetizer_c *packetizer, *orig_packetizer;
int64_t file, orig_file;
bool deferred;
} packetizer_t;
typedef struct {
append_spec_t amap;
packetizer_t *ptzr;
} deferred_connection_t;
typedef struct {
char *name;
int type;
packet_t *pack;
generic_reader_c *reader;
track_info_c *ti;
bool appending, appended_to, done;
vector<deferred_connection_t> deferred_connections;
} filelist_t;
typedef struct {
char *name, *mime_type, *description;
int64_t size;
@ -69,13 +83,6 @@ typedef struct {
int64_t track_id;
} track_order_t;
typedef struct {
int64_t src_file_id;
int64_t src_track_id;
int64_t dst_file_id;
int64_t dst_track_id;
} append_spec_t;
enum timecode_scale_mode_t {
timecode_scale_mode_normal = 0,
timecode_scale_mode_fixed,
@ -116,7 +123,8 @@ extern string default_language;
extern float video_fps;
extern bool write_cues, cue_writing_requested, video_track_present;
extern generic_packetizer_c *video_packetizer;
extern bool write_cues, cue_writing_requested;
extern bool no_lacing, no_linking, use_durations;
extern bool identifying, identify_verbose;

View File

@ -324,6 +324,14 @@ generic_packetizer_c::set_track_type(int type) {
if ((type == track_audio) && (ti->cues == CUES_UNSPECIFIED))
ti->cues = CUES_SPARSE;
if (type == track_audio)
reader->num_audio_tracks++;
else if (type == track_video) {
reader->num_video_tracks++;
if (video_packetizer == NULL)
video_packetizer = this;
} else
reader->num_subtitle_tracks++;
}
void
@ -1023,6 +1031,9 @@ generic_reader_c::generic_reader_c(track_info_c *nti) {
appending = false;
chapters = NULL;
ptzr_first_packet = NULL;
num_video_tracks = 0;
num_audio_tracks = 0;
num_subtitle_tracks = 0;
add_all_requested_track_ids2(atracks);
add_all_requested_track_ids2(vtracks);

View File

@ -253,6 +253,7 @@ public:
int64_t max_timecode_seen;
KaxChapters *chapters;
bool appending;
int num_video_tracks, num_audio_tracks, num_subtitle_tracks;
public:
generic_reader_c(track_info_c *nti);

View File

@ -50,7 +50,6 @@ video_packetizer_c::video_packetizer_c(generic_reader_c *nreader,
ref_timecode = -1;
if (get_cue_creation() == CUES_UNSPECIFIED)
set_cue_creation(CUES_IFRAMES);
video_track_present = true;
duration_shift = 0;
bref_frame.type = '?';
fref_frame.type = '?';