Implemented some speedups, especially during the 1st pass of splitting.

This commit is contained in:
Moritz Bunkus 2003-10-14 13:16:22 +00:00
parent 1bc0b8e5f8
commit af66b02552
12 changed files with 135 additions and 190 deletions

View File

@ -1,3 +1,10 @@
2003-10-14 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: Implemented some speedups for a couple of container
formats and track types (mainly AVI reader, MP3/AC3/AAC
packetizers). Especially noticeable when splitting is active as
well.
2003-10-12 Moritz Bunkus <moritz@bunkus.org>
* mkvextract: bug fix: Support for extracting SBR AAC (previous

View File

@ -178,6 +178,7 @@ bool accept_tags = true;
// pass of the splitting run.
int pass = 0;
int file_num = 1;
bool fast_mode = false;
// Specs say that track numbers should start at 1.
int track_number = 1;
@ -1905,6 +1906,7 @@ void create_next_output_file(bool last_file, bool first_file) {
die("mkvmerge.cpp/create_next_output_file(): Could not create a dummy "
"output class.");
}
fast_mode = true;
cluster_helper->set_output(out);
render_headers(out, last_file, first_file);
@ -1949,6 +1951,7 @@ void create_next_output_file(bool last_file, bool first_file) {
if (verbose)
mxinfo("Opened '%s\' for writing.\n", this_outfile.c_str());
fast_mode = false;
cluster_helper->set_output(out);
render_headers(out, last_file, first_file);
render_attachments(out);
@ -2184,6 +2187,7 @@ int main(int argc, char **argv) {
mxinfo("\nPass 1 took %u second%s.\nPass 2: merging the files. This will "
"take even longer.\n\n", end - start,
(end - start) == 1 ? "" : "s");
// mxexit(0);
start = time(NULL);

View File

@ -66,7 +66,10 @@ void create_next_output_file(bool last_file = false, bool first_file = false);
void finish_file();
string create_output_name();
extern int pass, file_num, max_ms_per_cluster, max_blocks_per_cluster;
extern int pass, file_num;
extern bool fast_mode;
extern int max_ms_per_cluster, max_blocks_per_cluster;
extern int default_tracks[3];
extern int64_t split_after;
extern int split_max_num_files;

View File

@ -40,8 +40,6 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader, int nid,
throw (error_c): generic_packetizer_c(nreader, nti) {
packetno = 0;
bytes_output = 0;
packet_buffer = NULL;
buffer_size = 0;
samples_per_sec = nsamples_per_sec;
channels = nchannels;
id = nid;
@ -58,63 +56,23 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader, int nid,
}
aac_packetizer_c::~aac_packetizer_c() {
if (packet_buffer != NULL)
safefree(packet_buffer);
}
void aac_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
unsigned char *new_buffer;
new_buffer = (unsigned char *)saferealloc(packet_buffer, buffer_size + size);
memcpy(new_buffer + buffer_size, buf, size);
packet_buffer = new_buffer;
buffer_size += size;
}
int aac_packetizer_c::aac_packet_available() {
int pos;
aac_header_t aacheader;
if (packet_buffer == NULL)
return 0;
pos = find_aac_header(packet_buffer, buffer_size, &aacheader,
emphasis_present);
if (pos < 0)
return 0;
return 1;
}
void aac_packetizer_c::remove_aac_packet(int pos, int framesize) {
int new_size;
unsigned char *temp_buf;
new_size = buffer_size - (pos + framesize);
if (new_size != 0)
temp_buf = (unsigned char *)safememdup(&packet_buffer[pos + framesize],
new_size);
else
temp_buf = NULL;
safefree(packet_buffer);
packet_buffer = temp_buf;
buffer_size = new_size;
}
unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
aac_header_t *aacheader) {
int pos, i, up_shift, down_shift;
unsigned char *buf, *src;
int pos, i, up_shift, down_shift, size;
unsigned char *buf, *src, *packet_buffer;
double pims;
if (packet_buffer == NULL)
return 0;
pos = find_aac_header(packet_buffer, buffer_size, aacheader,
emphasis_present);
packet_buffer = byte_buffer.get_buffer();
size = byte_buffer.get_size();
if (buf == NULL)
return NULL;
pos = find_aac_header(packet_buffer, size, aacheader, emphasis_present);
if (pos < 0)
return 0;
if ((pos + aacheader->bytes) > buffer_size)
return 0;
return NULL;
if ((pos + aacheader->bytes) > size)
return NULL;
pims = ((double)aacheader->bytes) * 1000.0 /
((double)aacheader->bit_rate / 8.0);
@ -128,7 +86,7 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
if (ti->async.displacement > -(pims / 2))
ti->async.displacement = 0;
remove_aac_packet(pos, aacheader->bytes);
byte_buffer.remove(pos + aacheader->bytes);
return 0;
}
@ -137,19 +95,24 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
mxwarn("aac_packetizer: skipping %d bytes (no valid AAC header "
"found). This might make audio/video go out of sync, but this "
"stream is damaged.\n", pos);
if ((aacheader->header_bit_size % 8) == 0)
buf = (unsigned char *)safememdup(packet_buffer + pos +
aacheader->header_byte_size,
aacheader->data_byte_size);
if ((aacheader->header_bit_size % 8) == 0) {
if (fast_mode)
buf = (unsigned char *)safemalloc(aacheader->data_byte_size);
else
buf = (unsigned char *)safememdup(packet_buffer + pos +
aacheader->header_byte_size,
aacheader->data_byte_size);
} else if (!fast_mode)
buf = (unsigned char *)safemalloc(aacheader->data_byte_size);
else {
// Header is not byte aligned, i.e. MPEG-4 ADTS
// This code is from mpeg4ip/server/mp4creator/aac.cpp
buf = (unsigned char *)safemalloc(aacheader->data_byte_size);
up_shift = aacheader->header_bit_size % 8;
down_shift = 8 - up_shift;
src = packet_buffer + pos + aacheader->header_bit_size / 8;
buf = (unsigned char *)safemalloc(aacheader->data_byte_size);
buf[0] = src[0] << up_shift;
for (i = 1; i < aacheader->data_byte_size; i++) {
buf[i - 1] |= (src[i] >> down_shift);
@ -172,7 +135,7 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
return buf;
}
remove_aac_packet(pos, aacheader->bytes);
byte_buffer.remove(pos + aacheader->bytes);
return buf;
}
@ -235,7 +198,7 @@ int aac_packetizer_c::process(unsigned char *buf, int size,
if (timecode != -1)
my_timecode = timecode;
add_to_buffer(buf, size);
byte_buffer.add(buf, size);
while ((packet = get_aac_packet(&header, &aacheader)) != NULL) {
if (timecode == -1)
my_timecode = (int64_t)(1000.0 * packetno * 1024 * ti->async.linear /
@ -253,5 +216,5 @@ int aac_packetizer_c::process(unsigned char *buf, int size,
void aac_packetizer_c::dump_debug_info() {
mxdebug("aac_packetizer_c: queue: %d; buffer size: %d\n",
packet_queue.size(), buffer_size);
packet_queue.size(), byte_buffer.get_size());
}

View File

@ -23,6 +23,7 @@
#include "os.h"
#include "byte_buffer.h"
#include "common.h"
#include "pr_generic.h"
#include "aac_common.h"
@ -40,9 +41,9 @@ class aac_packetizer_c: public generic_packetizer_c {
private:
int64_t bytes_output, packetno;
unsigned long samples_per_sec;
int channels, buffer_size, id, profile;
unsigned char *packet_buffer;
int channels, id, profile;
bool headerless, emphasis_present;
byte_buffer_c byte_buffer;
public:
aac_packetizer_c(generic_reader_c *nreader, int nid, int nprofile,
@ -57,11 +58,8 @@ public:
virtual void set_headers();
private:
virtual void add_to_buffer(unsigned char *buf, int size);
virtual unsigned char *get_aac_packet(unsigned long *header,
aac_header_t *aacheader);
virtual int aac_packet_available();
virtual void remove_aac_packet(int pos, int framesize);
virtual void dump_debug_info();
};

View File

@ -37,8 +37,6 @@ ac3_packetizer_c::ac3_packetizer_c(generic_reader_c *nreader,
throw (error_c): generic_packetizer_c(nreader, nti) {
packetno = 0;
bytes_output = 0;
packet_buffer = NULL;
buffer_size = 0;
samples_per_sec = nsamples_per_sec;
channels = nchannels;
bsid = nbsid;
@ -51,61 +49,28 @@ ac3_packetizer_c::ac3_packetizer_c(generic_reader_c *nreader,
}
ac3_packetizer_c::~ac3_packetizer_c() {
if (packet_buffer != NULL)
safefree(packet_buffer);
}
void ac3_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
unsigned char *new_buffer;
new_buffer = (unsigned char *)saferealloc(packet_buffer, buffer_size + size);
memcpy(new_buffer + buffer_size, buf, size);
packet_buffer = new_buffer;
buffer_size += size;
}
int ac3_packetizer_c::ac3_packet_available() {
int pos;
ac3_header_t ac3header;
if (packet_buffer == NULL)
return 0;
pos = find_ac3_header(packet_buffer, buffer_size, &ac3header);
if (pos < 0)
return 0;
return 1;
}
void ac3_packetizer_c::remove_ac3_packet(int pos, int framesize) {
int new_size;
unsigned char *temp_buf;
new_size = buffer_size - (pos + framesize);
if (new_size != 0)
temp_buf = (unsigned char *)safememdup(&packet_buffer[pos + framesize],
new_size);
else
temp_buf = NULL;
safefree(packet_buffer);
packet_buffer = temp_buf;
buffer_size = new_size;
byte_buffer.add(buf, size);
}
unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
ac3_header_t *ac3header) {
int pos;
unsigned char *buf;
int pos, size;
unsigned char *buf, *packet_buffer;
double pims;
packet_buffer = byte_buffer.get_buffer();
size = byte_buffer.get_size();
if (packet_buffer == NULL)
return 0;
pos = find_ac3_header(packet_buffer, buffer_size, ac3header);
return NULL;
pos = find_ac3_header(packet_buffer, size, ac3header);
if (pos < 0)
return 0;
if ((pos + ac3header->bytes) > buffer_size)
return 0;
return NULL;
if ((pos + ac3header->bytes) > size)
return NULL;
pims = ((double)ac3header->bytes) * 1000.0 /
((double)ac3header->bit_rate / 8.0);
@ -119,16 +84,19 @@ unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
if (ti->async.displacement > -(pims / 2))
ti->async.displacement = 0;
remove_ac3_packet(pos, ac3header->bytes);
byte_buffer.remove(pos + ac3header->bytes);
return 0;
return NULL;
}
if (verbose && (pos > 1))
mxwarn("ac3_packetizer: skipping %d bytes (no valid AC3 header "
"found). This might make audio/video go out of sync, but this "
"stream is damaged.\n", pos);
buf = (unsigned char *)safememdup(packet_buffer + pos, ac3header->bytes);
if (fast_mode)
buf = (unsigned char *)safemalloc(ac3header->bytes);
else
buf = (unsigned char *)safememdup(packet_buffer + pos, ac3header->bytes);
if (ti->async.displacement > 0) {
/*
@ -145,7 +113,7 @@ unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
return buf;
}
remove_ac3_packet(pos, ac3header->bytes);
byte_buffer.remove(pos + ac3header->bytes);
return buf;
}
@ -194,7 +162,7 @@ int ac3_packetizer_c::process(unsigned char *buf, int size,
void ac3_packetizer_c::dump_debug_info() {
mxdebug("ac3_packetizer_c: queue: %d; buffer size: %d\n",
packet_queue.size(), buffer_size);
packet_queue.size(), byte_buffer.get_size());
}
ac3_bs_packetizer_c::ac3_bs_packetizer_c(generic_reader_c *nreader,
@ -236,9 +204,8 @@ void ac3_bs_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
} else
new_bsb_present = false;
new_buffer = (unsigned char *)saferealloc(packet_buffer, buffer_size +
size_add);
dptr = new_buffer + buffer_size;
new_buffer = (unsigned char *)safemalloc(size_add);
dptr = new_buffer;
sptr = buf;
if (bsb_present) {
@ -258,7 +225,7 @@ void ac3_bs_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
if (new_bsb_present)
bsb = *sptr;
bsb_present = new_bsb_present;
packet_buffer = new_buffer;
buffer_size += size_add;
byte_buffer.add(new_buffer, size_add);
safefree(new_buffer);
}

View File

@ -23,6 +23,7 @@
#include "os.h"
#include "byte_buffer.h"
#include "common.h"
#include "pr_generic.h"
#include "ac3_common.h"
@ -31,8 +32,8 @@ class ac3_packetizer_c: public generic_packetizer_c {
protected:
int64_t bytes_output, packetno;
unsigned long samples_per_sec;
int channels, buffer_size, bsid;
unsigned char *packet_buffer;
int channels, bsid;
byte_buffer_c byte_buffer;
public:
ac3_packetizer_c(generic_reader_c *nreader, unsigned long nsamples_per_sec,
@ -46,11 +47,9 @@ public:
virtual void set_headers();
protected:
virtual void add_to_buffer(unsigned char *buf, int size);
virtual unsigned char *get_ac3_packet(unsigned long *header,
ac3_header_t *ac3header);
virtual int ac3_packet_available();
virtual void remove_ac3_packet(int pos, int framesize);
virtual void add_to_buffer(unsigned char *buf, int size);
virtual void dump_debug_info();
};

View File

@ -34,14 +34,13 @@ using namespace libmatroska;
mp3_packetizer_c::mp3_packetizer_c(generic_reader_c *nreader,
unsigned long nsamples_per_sec,
int nchannels, int nlayer,
track_info_t *nti)
throw (error_c): generic_packetizer_c(nreader, nti) {
track_info_t *nti) throw (error_c):
generic_packetizer_c(nreader, nti),
byte_buffer(128 * 1024) {
samples_per_sec = nsamples_per_sec;
channels = nchannels;
layer = nlayer;
bytes_output = 0;
packet_buffer = NULL;
buffer_size = 0;
packetno = 0;
spf = 1152;
@ -54,53 +53,30 @@ mp3_packetizer_c::mp3_packetizer_c(generic_reader_c *nreader,
}
mp3_packetizer_c::~mp3_packetizer_c() {
if (packet_buffer != NULL)
safefree(packet_buffer);
}
void mp3_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
unsigned char *new_buffer;
new_buffer = (unsigned char *)saferealloc(packet_buffer, buffer_size + size);
memcpy(new_buffer + buffer_size, buf, size);
packet_buffer = new_buffer;
buffer_size += size;
}
void mp3_packetizer_c::remove_mp3_packet(int pos, int framesize) {
int new_size;
unsigned char *temp_buf;
new_size = buffer_size - (pos + framesize) + 1;
temp_buf = (unsigned char *)safemalloc(new_size);
if (new_size != 0)
memcpy(temp_buf, &packet_buffer[pos + framesize - 1], new_size);
safefree(packet_buffer);
packet_buffer = temp_buf;
buffer_size = new_size;
}
unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
int pos;
int pos, size;
unsigned char *buf;
double pims;
if (packet_buffer == NULL)
if (byte_buffer.get_size() == 0)
return 0;
while (1) {
pos = find_mp3_header(packet_buffer, buffer_size);
buf = byte_buffer.get_buffer();
size = byte_buffer.get_size();
pos = find_mp3_header(buf, size);
if (pos < 0)
return NULL;
decode_mp3_header(&packet_buffer[pos], mp3header);
if ((pos + mp3header->framesize) > buffer_size)
decode_mp3_header(&buf[pos], mp3header);
if ((pos + mp3header->framesize) > size)
return NULL;
if (!mp3header->is_tag)
break;
mxverb(2, "mp3_packetizer: Removing TAG packet with size %d\n",
mp3header->framesize);
remove_mp3_packet(pos, mp3header->framesize);
byte_buffer.remove(mp3header->framesize + pos);
}
if (packetno == 0) {
@ -116,7 +92,7 @@ unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
}
}
if ((pos + mp3header->framesize) > buffer_size)
if ((pos + mp3header->framesize) > byte_buffer.get_size())
return NULL;
pims = 1000.0 * (float)spf / mp3header->sampling_frequency;
@ -130,15 +106,19 @@ unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
if (ti->async.displacement > -(pims / 2))
ti->async.displacement = 0;
remove_mp3_packet(pos, mp3header->framesize);
byte_buffer.remove(mp3header->framesize + pos);
return 0;
return NULL;
}
if ((verbose > 1) && (pos > 1))
mxwarn("mp3_packetizer: skipping %d bytes (no valid MP3 header found).\n",
pos);
buf = (unsigned char *)safememdup(packet_buffer + pos, mp3header->framesize);
if (fast_mode)
buf = (unsigned char *)safemalloc(mp3header->framesize);
else
buf = (unsigned char *)safememdup(byte_buffer.get_buffer() + pos,
mp3header->framesize);
if (ti->async.displacement > 0) {
/*
@ -155,7 +135,7 @@ unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
return buf;
}
remove_mp3_packet(pos, mp3header->framesize);
byte_buffer.remove(mp3header->framesize + pos);
return buf;
}
@ -183,7 +163,7 @@ int mp3_packetizer_c::process(unsigned char *buf, int size,
if (timecode != -1)
my_timecode = timecode;
add_to_buffer(buf, size);
byte_buffer.add(buf, size);
while ((packet = get_mp3_packet(&mp3header)) != NULL) {
old_packetno = packetno;
packetno++;
@ -207,5 +187,5 @@ int mp3_packetizer_c::process(unsigned char *buf, int size,
void mp3_packetizer_c::dump_debug_info() {
mxdebug("mp3_packetizer_c: queue: %d; buffer_size: %d\n",
packet_queue.size(), buffer_size);
packet_queue.size(), byte_buffer.get_size());
}

View File

@ -23,6 +23,7 @@
#include "os.h"
#include "byte_buffer.h"
#include "common.h"
#include "pr_generic.h"
#include "mp3_common.h"
@ -31,8 +32,8 @@ class mp3_packetizer_c: public generic_packetizer_c {
private:
int64_t bytes_output, packetno;
unsigned long samples_per_sec;
int channels, buffer_size, spf, layer;
unsigned char *packet_buffer;
int channels, spf, layer;
byte_buffer_c byte_buffer;
public:
mp3_packetizer_c(generic_reader_c *nreader, unsigned long nsamples_per_sec,
@ -46,9 +47,7 @@ public:
virtual void set_headers();
private:
virtual void add_to_buffer(unsigned char *buf, int size);
virtual unsigned char *get_mp3_packet(mp3_header_t *mp3header);
virtual void remove_mp3_packet(int pos, int framesize);
virtual void dump_debug_info();
};

View File

@ -549,9 +549,12 @@ void generic_packetizer_c::add_packet(unsigned char *data, int length,
pack = (packet_t *)safemalloc(sizeof(packet_t));
memset(pack, 0, sizeof(packet_t));
if (duplicate_data)
pack->data = (unsigned char *)safememdup(data, length);
else
if (duplicate_data) {
if (!fast_mode)
pack->data = (unsigned char *)safememdup(data, length);
else
pack->data = (unsigned char *)safemalloc(length);
} else
pack->data = data;
pack->length = length;
pack->timecode = timecode;

View File

@ -479,21 +479,30 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
#ifdef HAVE_AVICLASSES
debug_enter("aviclasses->Read() video");
key = s_video->IsKeyFrame(frames);
if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread, &blread) !=
AVIERR_OK)
if (fast_mode) {
if (s_video->Read(frames, 1, NULL, 0, &nread, &blread) != S_OK)
nread = -1;
} else if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread,
&blread) != S_OK)
nread = -1;
debug_leave("aviclasses->Read() video");
#else
debug_enter("AVI_read_frame");
nread = AVI_read_frame(avi, (char *)chunk, &key);
if (fast_mode)
nread = AVI_read_frame(avi, NULL, &key);
else
nread = AVI_read_frame(avi, (char *)chunk, &key);
debug_leave("AVI_read_frame");
#endif
if (nread < 0) {
frames = maxframes + 1;
done = true;
} else {
key = is_keyframe(chunk, nread, key);
old_chunk = (unsigned char *)safememdup(chunk, nread);
// key = is_keyframe(chunk, nread, key);
if (fast_mode)
old_chunk = (unsigned char *)safemalloc(nread);
else
old_chunk = (unsigned char *)safememdup(chunk, nread);
old_key = key;
old_nread = nread;
frames++;
@ -506,13 +515,19 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
#ifdef HAVE_AVICLASSES
debug_enter("aviclasses->Read() video");
key = s_video->IsKeyFrame(frames);
if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread, &blread) !=
AVIERR_OK)
if (fast_mode) {
if (s_video->Read(frames, 1, NULL, 0, &nread, &blread) != S_OK)
nread = -1;
} else if (s_video->Read(frames, 1, chunk, 0x7FFFFFFF, &nread,
&blread) != S_OK)
nread = -1;
debug_leave("aviclasses->Read() video");
#else
debug_enter("AVI_read_frame");
nread = AVI_read_frame(avi, (char *)chunk, &key);
if (fast_mode)
nread = AVI_read_frame(avi, NULL, &key);
else
nread = AVI_read_frame(avi, (char *)chunk, &key);
debug_leave("AVI_read_frame");
#endif
if (nread < 0) {
@ -523,7 +538,7 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
frames = maxframes + 1;
break;
}
key = is_keyframe(chunk, nread, key);
// key = is_keyframe(chunk, nread, key);
if (frames == (maxframes - 1)) {
last_frame = 1;
done = true;
@ -543,7 +558,10 @@ int avi_reader_c::read(generic_packetizer_c *ptzr) {
if (! last_frame) {
if (old_chunk != NULL)
safefree(old_chunk);
old_chunk = (unsigned char *)safememdup(chunk, nread);
if (fast_mode)
old_chunk = (unsigned char *)safemalloc(nread);
else
old_chunk = (unsigned char *)safememdup(chunk, nread);
old_key = key;
old_nread = nread;
} else if (nread > 0) {

View File

@ -725,7 +725,8 @@ void real_reader_c::deliver_segments(real_demuxer_t *dmx, int64_t timecode) {
for (i = 0; i < dmx->segments->size(); i++) {
segment = &(*dmx->segments)[i];
memcpy(ptr, segment->data, segment->size);
if (!fast_mode)
memcpy(ptr, segment->data, segment->size);
ptr += segment->size;
}
@ -822,7 +823,10 @@ void real_reader_c::assemble_packet(real_demuxer_t *dmx, unsigned char *p,
segment.offset = vpkg_offset;
segment.data = (unsigned char *)safemalloc(len);
segment.size = len;
bc.get_bytes(segment.data, len);
if (!fast_mode || !dmx->rv_dimensions)
bc.get_bytes(segment.data, len);
else
bc.skip(len);
dmx->segments->push_back(segment);
dmx->c_timecode = this_timecode;