mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 20:01:53 +00:00
Reworked the audio synchronization code which was not working for Matroska source files.
This commit is contained in:
parent
739580d885
commit
89b68ad397
@ -1,3 +1,8 @@
|
||||
2003-11-15 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: Reworked the audio sychronization which did
|
||||
not work correctly for Matroska source files.
|
||||
|
||||
2003-11-13 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: Increased the size of the space reserved for
|
||||
|
@ -593,8 +593,6 @@ int cluster_helper_c::render() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define iabs(a) ((a) < 0 ? (-1 * (a)) : (a))
|
||||
|
||||
ch_contents_t *cluster_helper_c::find_packet_cluster(int64_t ref_timecode,
|
||||
void *source) {
|
||||
int i, k;
|
||||
|
@ -64,6 +64,8 @@ using namespace libebml;
|
||||
#define TYPEREAL 14
|
||||
#define TYPEQTMP4 15
|
||||
|
||||
#define iabs(a) ((a) < 0 ? (-1 * (a)) : (a))
|
||||
|
||||
#define FOURCC(a, b, c, d) (uint32_t)((((unsigned char)a) << 24) + \
|
||||
(((unsigned char)b) << 16) + \
|
||||
(((unsigned char)c) << 8) + \
|
||||
|
@ -74,21 +74,17 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
|
||||
if ((pos + aacheader->bytes) > size)
|
||||
return NULL;
|
||||
|
||||
pims = ((double)aacheader->bytes) * 1000.0 /
|
||||
((double)aacheader->bit_rate / 8.0);
|
||||
pims = 1024000.0 / samples_per_sec;
|
||||
|
||||
if (ti->async.displacement < 0) {
|
||||
if (needs_negative_displacement(pims)) {
|
||||
/*
|
||||
* AAC audio synchronization. displacement < 0 means skipping an
|
||||
* appropriate number of packets at the beginning.
|
||||
*/
|
||||
ti->async.displacement += (int)pims;
|
||||
if (ti->async.displacement > -(pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(-pims);
|
||||
byte_buffer.remove(pos + aacheader->bytes);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (verbose && (pos > 0))
|
||||
@ -120,7 +116,7 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
|
||||
}
|
||||
}
|
||||
|
||||
if (ti->async.displacement > 0) {
|
||||
if (needs_positive_displacement(pims)) {
|
||||
/*
|
||||
* AAC audio synchronization. displacement > 0 is solved by duplicating
|
||||
* the very first AAC packet as often as necessary. I cannot create
|
||||
@ -128,9 +124,8 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
|
||||
* settings the packet's values to 0 does not work as the AAC header
|
||||
* contains a CRC of its data.
|
||||
*/
|
||||
ti->async.displacement -= (int)pims;
|
||||
if (ti->async.displacement < (pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
mxinfo("displacing for %f\n", pims);
|
||||
displace(pims);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@ -177,7 +172,7 @@ int aac_packetizer_c::process(unsigned char *buf, int size,
|
||||
unsigned char *packet;
|
||||
unsigned long header;
|
||||
aac_header_t aacheader;
|
||||
int64_t my_timecode;
|
||||
int64_t my_timecode, duration;
|
||||
|
||||
debug_enter("aac_packetizer_c::process");
|
||||
|
||||
@ -185,25 +180,34 @@ int aac_packetizer_c::process(unsigned char *buf, int size,
|
||||
if (timecode != -1)
|
||||
my_timecode = timecode;
|
||||
else
|
||||
my_timecode = (int64_t)(1000.0 * packetno * 1024 * ti->async.linear /
|
||||
samples_per_sec);
|
||||
add_packet(buf, size, my_timecode,
|
||||
(int64_t)(1000.0 * 1024 * ti->async.linear / samples_per_sec));
|
||||
die("aac_packetizer_c::process: headerless && timecode == -1\n");
|
||||
duration = (int64_t)(1000.0 * 1024 * ti->async.linear / samples_per_sec);
|
||||
|
||||
if (needs_negative_displacement(duration)) {
|
||||
displace(-duration);
|
||||
return EMOREDATA;
|
||||
}
|
||||
while (needs_positive_displacement(duration)) {
|
||||
add_packet(buf, size, my_timecode + ti->async.displacement, duration);
|
||||
displace(duration);
|
||||
}
|
||||
|
||||
my_timecode = (int64_t)((my_timecode + ti->async.displacement) *
|
||||
ti->async.linear);
|
||||
add_packet(buf, size, my_timecode, duration);
|
||||
|
||||
debug_leave("aac_packetizer_c::process");
|
||||
|
||||
return EMOREDATA;
|
||||
}
|
||||
|
||||
if (timecode != -1)
|
||||
my_timecode = timecode;
|
||||
|
||||
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 /
|
||||
samples_per_sec);
|
||||
|
||||
my_timecode = (int64_t)(1000.0 * packetno * 1024 / samples_per_sec);
|
||||
else
|
||||
my_timecode = timecode + ti->async.displacement;
|
||||
my_timecode = (int64_t)(my_timecode * ti->async.linear);
|
||||
add_packet(packet, aacheader.data_byte_size, my_timecode,
|
||||
(int64_t)(1000.0 * 1024 * ti->async.linear / samples_per_sec));
|
||||
packetno++;
|
||||
|
@ -72,18 +72,14 @@ unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
|
||||
if ((pos + ac3header->bytes) > size)
|
||||
return NULL;
|
||||
|
||||
pims = ((double)ac3header->bytes) * 1000.0 /
|
||||
((double)ac3header->bit_rate / 8.0);
|
||||
pims = 1536000.0 / samples_per_sec;
|
||||
|
||||
if (ti->async.displacement < 0) {
|
||||
if (needs_negative_displacement(pims)) {
|
||||
/*
|
||||
* AC3 audio synchronization. displacement < 0 means skipping an
|
||||
* appropriate number of packets at the beginning.
|
||||
*/
|
||||
ti->async.displacement += (int)pims;
|
||||
if (ti->async.displacement > -(pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(-pims);
|
||||
byte_buffer.remove(pos + ac3header->bytes);
|
||||
|
||||
return NULL;
|
||||
@ -98,7 +94,7 @@ unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
|
||||
else
|
||||
buf = (unsigned char *)safememdup(packet_buffer + pos, ac3header->bytes);
|
||||
|
||||
if (ti->async.displacement > 0) {
|
||||
if (needs_positive_displacement(pims)) {
|
||||
/*
|
||||
* AC3 audio synchronization. displacement > 0 is solved by duplicating
|
||||
* the very first AC3 packet as often as necessary. I cannot create
|
||||
@ -106,10 +102,7 @@ unsigned char *ac3_packetizer_c::get_ac3_packet(unsigned long *header,
|
||||
* settings the packet's values to 0 does not work as the AC3 header
|
||||
* contains a CRC of its data.
|
||||
*/
|
||||
ti->async.displacement -= (int)pims;
|
||||
if (ti->async.displacement < (pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(pims);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -141,15 +134,13 @@ int ac3_packetizer_c::process(unsigned char *buf, int size,
|
||||
|
||||
debug_enter("ac3_packetizer_c::process");
|
||||
|
||||
if (timecode != -1)
|
||||
my_timecode = timecode;
|
||||
|
||||
add_to_buffer(buf, size);
|
||||
while ((packet = get_ac3_packet(&header, &ac3header)) != NULL) {
|
||||
if (timecode == -1)
|
||||
my_timecode = (int64_t)(1000.0 * packetno * 1536 * ti->async.linear /
|
||||
samples_per_sec);
|
||||
|
||||
my_timecode = (int64_t)(1000.0 * packetno * 1536 / samples_per_sec);
|
||||
else
|
||||
my_timecode = timecode + initial_displacement;
|
||||
my_timecode = (int64_t)(my_timecode * ti->async.linear);
|
||||
add_packet(packet, ac3header.bytes, my_timecode,
|
||||
(int64_t)(1000.0 * 1536 * ti->async.linear / samples_per_sec));
|
||||
packetno++;
|
||||
|
@ -168,15 +168,12 @@ unsigned char *dts_packetizer_c::get_dts_packet(dts_header_t &dtsheader) {
|
||||
|
||||
pims = get_dts_packet_length_in_milliseconds(&dtsheader);
|
||||
|
||||
if (ti->async.displacement < 0) {
|
||||
if (needs_negative_displacement(pims)) {
|
||||
/*
|
||||
* DTS audio synchronization. displacement < 0 means skipping an
|
||||
* appropriate number of packets at the beginning.
|
||||
*/
|
||||
ti->async.displacement += (int)pims;
|
||||
if (ti->async.displacement > -(pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(-pims);
|
||||
remove_dts_packet(pos, dtsheader.frame_byte_size);
|
||||
|
||||
return 0;
|
||||
@ -190,7 +187,7 @@ unsigned char *dts_packetizer_c::get_dts_packet(dts_header_t &dtsheader) {
|
||||
buf = (unsigned char *)safememdup(packet_buffer + pos,
|
||||
dtsheader.frame_byte_size);
|
||||
|
||||
if (ti->async.displacement > 0) {
|
||||
if (needs_positive_displacement(pims)) {
|
||||
/*
|
||||
* DTS audio synchronization. displacement > 0 is solved by duplicating
|
||||
* the very first DTS packet as often as necessary. I cannot create
|
||||
@ -198,10 +195,7 @@ unsigned char *dts_packetizer_c::get_dts_packet(dts_header_t &dtsheader) {
|
||||
* settings the packet's values to 0 does not work as the DTS header
|
||||
* contains a CRC of its data.
|
||||
*/
|
||||
ti->async.displacement -= (int)pims;
|
||||
if (ti->async.displacement < (pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(pims);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -239,9 +233,11 @@ int dts_packetizer_c::process(unsigned char *buf, int size,
|
||||
if (timecode == -1)
|
||||
my_timecode = (int64_t)(((double)samples_written * 1000.0) /
|
||||
((double)dtsheader.core_sampling_frequency));
|
||||
|
||||
else
|
||||
my_timecode = timecode + initial_displacement;
|
||||
my_timecode = (int64_t)(my_timecode * ti->async.linear);
|
||||
add_packet(packet, dtsheader.frame_byte_size, my_timecode,
|
||||
packet_len_in_ms);
|
||||
(int64_t)(packet_len_in_ms * ti->async.linear));
|
||||
|
||||
bytes_written += dtsheader.frame_byte_size;
|
||||
samples_written += get_dts_packet_length_in_core_samples(&dtsheader);
|
||||
|
@ -43,9 +43,7 @@ mp3_packetizer_c::mp3_packetizer_c(generic_reader_c *nreader,
|
||||
spf = 1152;
|
||||
|
||||
set_track_type(track_audio);
|
||||
if (use_durations)
|
||||
set_track_default_duration_ns((int64_t)(1152000000000.0 *
|
||||
ti->async.linear /
|
||||
set_track_default_duration_ns((int64_t)(1152000000000.0 * ti->async.linear /
|
||||
samples_per_sec));
|
||||
duplicate_data_on_add(false);
|
||||
}
|
||||
@ -84,7 +82,7 @@ unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
|
||||
codec_id[codec_id.length() - 1] = (char)(mp3header->layer + '0');
|
||||
*(static_cast<EbmlString *>
|
||||
(&GetChild<KaxCodecID>(*track_entry))) = codec_id;
|
||||
if ((spf != 1152) && use_durations) {
|
||||
if (spf != 1152) {
|
||||
set_track_default_duration_ns((int64_t)(1000000000.0 * spf *
|
||||
ti->async.linear /
|
||||
samples_per_sec));
|
||||
@ -100,45 +98,44 @@ unsigned char *mp3_packetizer_c::get_mp3_packet(mp3_header_t *mp3header) {
|
||||
|
||||
pims = 1000.0 * (float)spf / mp3header->sampling_frequency;
|
||||
|
||||
if (ti->async.displacement < 0) {
|
||||
if (needs_negative_displacement(pims)) {
|
||||
/*
|
||||
* MP3 audio synchronization. displacement < 0 means skipping an
|
||||
* appropriate number of packets at the beginning.
|
||||
*/
|
||||
ti->async.displacement += (int)pims;
|
||||
if (ti->async.displacement > -(pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
|
||||
displace(-pims);
|
||||
byte_buffer.remove(mp3header->framesize + pos);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((verbose > 1) && (pos > 1))
|
||||
mxwarn("mp3_packetizer: skipping %d bytes (no valid MP3 header found).\n",
|
||||
pos);
|
||||
if (pos > 0) {
|
||||
if (verbose)
|
||||
mxwarn("mp3_packetizer: skipping %d bytes (no valid MP3 header found)."
|
||||
"\n", pos);
|
||||
byte_buffer.remove(pos);
|
||||
pos = 0;
|
||||
}
|
||||
if (fast_mode)
|
||||
buf = (unsigned char *)safemalloc(mp3header->framesize);
|
||||
else
|
||||
buf = (unsigned char *)safememdup(byte_buffer.get_buffer() + pos,
|
||||
buf = (unsigned char *)safememdup(byte_buffer.get_buffer(),
|
||||
mp3header->framesize);
|
||||
|
||||
if (ti->async.displacement > 0) {
|
||||
if (needs_positive_displacement(pims)) {
|
||||
/*
|
||||
* MP3 audio synchronization. displacement > 0 is solved by creating
|
||||
* silent MP3 packets and repeating it over and over again (well only as
|
||||
* often as necessary of course. Wouldn't want to spoil your movie by
|
||||
* providing a silent MP3 stream ;)).
|
||||
*/
|
||||
ti->async.displacement -= (int)pims;
|
||||
if (ti->async.displacement < (pims / 2))
|
||||
ti->async.displacement = 0;
|
||||
displace(pims);
|
||||
memset(buf + 4, 0, mp3header->framesize - 4);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
byte_buffer.remove(mp3header->framesize + pos);
|
||||
byte_buffer.remove(mp3header->framesize);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@ -155,28 +152,24 @@ int mp3_packetizer_c::process(unsigned char *buf, int size,
|
||||
int64_t timecode, int64_t, int64_t, int64_t) {
|
||||
unsigned char *packet;
|
||||
mp3_header_t mp3header;
|
||||
int64_t my_timecode, old_packetno;
|
||||
int64_t my_timecode;
|
||||
|
||||
debug_enter("mp3_packetizer_c::process");
|
||||
|
||||
if (timecode != -1)
|
||||
my_timecode = timecode;
|
||||
|
||||
byte_buffer.add(buf, size);
|
||||
while ((packet = get_mp3_packet(&mp3header)) != NULL) {
|
||||
old_packetno = packetno;
|
||||
packetno++;
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_packet(packet, mp3header.framesize);
|
||||
#endif
|
||||
|
||||
if (timecode == -1)
|
||||
my_timecode = (int64_t)(1000.0 * old_packetno * spf * ti->async.linear /
|
||||
samples_per_sec);
|
||||
|
||||
my_timecode = (int64_t)(1000.0 * packetno * spf / samples_per_sec);
|
||||
else
|
||||
my_timecode = timecode + ti->async.displacement;
|
||||
my_timecode = (int64_t)(my_timecode * ti->async.linear);
|
||||
add_packet(packet, mp3header.framesize, my_timecode,
|
||||
(int64_t)(1000.0 * spf * ti->async.linear / samples_per_sec));
|
||||
packetno++;
|
||||
}
|
||||
|
||||
debug_leave("mp3_packetizer_c::process");
|
||||
|
@ -50,7 +50,25 @@ int passthrough_packetizer_c::process(unsigned char *buf, int size,
|
||||
|
||||
packets_processed++;
|
||||
bytes_processed += size;
|
||||
if (needs_negative_displacement(duration)) {
|
||||
displace(-duration);
|
||||
sync_to_keyframe = true;
|
||||
return EMOREDATA;
|
||||
}
|
||||
while (needs_positive_displacement(duration)) {
|
||||
add_packet(buf, size, (int64_t)((timecode + ti->async.displacement) *
|
||||
ti->async.linear), bref, fref);
|
||||
displace(duration);
|
||||
}
|
||||
|
||||
if (sync_to_keyframe && (bref != -1)) {
|
||||
if (!duplicate_data)
|
||||
safefree(buf);
|
||||
return EMOREDATA;
|
||||
}
|
||||
sync_to_keyframe = false;
|
||||
timecode = (int64_t)((timecode + ti->async.displacement) * ti->async.linear);
|
||||
duration = (int64_t)(duration * ti->async.linear);
|
||||
add_packet(buf, size, timecode, duration, false, bref, fref);
|
||||
|
||||
debug_leave("passthrough_packetizer_c::process");
|
||||
|
@ -29,6 +29,7 @@
|
||||
class passthrough_packetizer_c: public generic_packetizer_c {
|
||||
private:
|
||||
int64_t packets_processed, bytes_processed;
|
||||
bool sync_to_keyframe;
|
||||
|
||||
public:
|
||||
passthrough_packetizer_c(generic_reader_c *nreader, track_info_t *nti)
|
||||
|
@ -85,20 +85,20 @@ int pcm_packetizer_c::process(unsigned char *buf, int size,
|
||||
|
||||
new_buf = buf;
|
||||
|
||||
if (ti->async.displacement != 0) {
|
||||
if (ti->async.displacement > 0) {
|
||||
if (initial_displacement != 0) {
|
||||
if (initial_displacement > 0) {
|
||||
// Add silence.
|
||||
int pad_size;
|
||||
|
||||
pad_size = bps * ti->async.displacement / 1000;
|
||||
pad_size = bps * initial_displacement / 1000;
|
||||
new_buf = (unsigned char *)safemalloc(size + pad_size);
|
||||
memset(new_buf, 0, pad_size);
|
||||
memcpy(&new_buf[pad_size], buf, size);
|
||||
size += pad_size;
|
||||
} else
|
||||
// Skip bytes.
|
||||
remaining_sync = -1 * bps * ti->async.displacement / 1000;
|
||||
ti->async.displacement = 0;
|
||||
remaining_sync = -1 * bps * initial_displacement / 1000;
|
||||
initial_displacement = 0;
|
||||
}
|
||||
|
||||
if (remaining_sync > 0) {
|
||||
|
@ -75,9 +75,9 @@ int textsubs_packetizer_c::process(unsigned char *_subs, int, int64_t start,
|
||||
|
||||
end = start + length;
|
||||
// Adjust the start and end values according to the audio adjustment.
|
||||
start += ti->async.displacement;
|
||||
start += initial_displacement;
|
||||
start = (int64_t)(ti->async.linear * start);
|
||||
end += ti->async.displacement;
|
||||
end += initial_displacement;
|
||||
end = (int64_t)(ti->async.linear * end);
|
||||
|
||||
if (end < 0)
|
||||
|
@ -72,10 +72,10 @@ void vobsub_packetizer_c::set_headers() {
|
||||
track_entry->EnableLacing(false);
|
||||
}
|
||||
|
||||
#define TIMECODE (timecode - ti->async.displacement) / 60 / 60 / 1000, \
|
||||
((timecode - ti->async.displacement) / 60 / 1000) % 60, \
|
||||
((timecode - ti->async.displacement) / 1000) % 60, \
|
||||
(timecode - ti->async.displacement) % 1000
|
||||
#define TIMECODE (timecode - initial_displacement) / 60 / 60 / 1000, \
|
||||
((timecode - initial_displacement) / 60 / 1000) % 60, \
|
||||
((timecode - initial_displacement) / 1000) % 60, \
|
||||
(timecode - initial_displacement) % 1000
|
||||
#define FMT_TIMECODE "%02lld:%02lld:%02lld.%03lld"
|
||||
|
||||
int vobsub_packetizer_c::extract_duration(unsigned char *data, int buf_size,
|
||||
@ -156,7 +156,7 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
||||
|
||||
packet_num++;
|
||||
|
||||
timecode += ti->async.displacement;
|
||||
timecode += initial_displacement;
|
||||
if (timecode < 0)
|
||||
return EMOREDATA;
|
||||
|
||||
|
@ -71,6 +71,7 @@ vorbis_packetizer_c::vorbis_packetizer_c(generic_reader_c *nreader,
|
||||
if (use_durations)
|
||||
set_track_default_duration_ns((int64_t)(1024000000000.0 *
|
||||
ti->async.linear / vi.rate));
|
||||
ti->async.displacement = initial_displacement;
|
||||
}
|
||||
|
||||
vorbis_packetizer_c::~vorbis_packetizer_c() {
|
||||
@ -142,12 +143,8 @@ int vorbis_packetizer_c::process(unsigned char *data, int size,
|
||||
|
||||
debug_enter("vorbis_packetizer_c::process");
|
||||
|
||||
// Recalculate the timecode if needed.
|
||||
if (timecode == -1)
|
||||
timecode = samples * 1000 / vi.rate;
|
||||
|
||||
// Positive displacement, first packet? Well then lets create silence.
|
||||
if ((packetno == 0) && (ti->async.displacement > 0)) {
|
||||
if ((packetno == 0) && (initial_displacement > 0)) {
|
||||
// Create a fake packet so we can use vorbis_packet_blocksize().
|
||||
zero[0] = 0;
|
||||
zero[1] = 0;
|
||||
@ -156,7 +153,7 @@ int vorbis_packetizer_c::process(unsigned char *data, int size,
|
||||
op.bytes = 2;
|
||||
|
||||
// Calculate how many samples we have to create.
|
||||
samples_needed = vi.rate * ti->async.displacement / 1000;
|
||||
samples_needed = vi.rate * initial_displacement / 1000;
|
||||
|
||||
this_bs = vorbis_packet_blocksize(&vi, &op);
|
||||
samples_here = (this_bs + last_bs) / 4;
|
||||
@ -167,8 +164,6 @@ int vorbis_packetizer_c::process(unsigned char *data, int size,
|
||||
add_packet(zero, 2, samples * 1000 / vi.rate, samples_here * 1000 /
|
||||
vi.rate);
|
||||
}
|
||||
|
||||
ti->async.displacement = 0;
|
||||
}
|
||||
|
||||
// Update the number of samples we have processed so that we can
|
||||
@ -180,8 +175,14 @@ int vorbis_packetizer_c::process(unsigned char *data, int size,
|
||||
samples += samples_here;
|
||||
last_bs = this_bs;
|
||||
|
||||
// Handle the displacement.
|
||||
timecode += ti->async.displacement;
|
||||
// Recalculate the timecode if needed.
|
||||
if (timecode == -1) {
|
||||
if (initial_displacement > 0)
|
||||
timecode = samples * 1000 / vi.rate;
|
||||
else
|
||||
timecode = samples * 1000 / vi.rate + initial_displacement;
|
||||
} else
|
||||
timecode += initial_displacement;
|
||||
|
||||
// Handle the linear sync - simply multiply with the given factor.
|
||||
timecode = (int64_t)((double)timecode * ti->async.linear);
|
||||
|
@ -51,6 +51,7 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader,
|
||||
ti = duplicate_track_info(nti);
|
||||
free_refs = -1;
|
||||
enqueued_bytes = 0;
|
||||
safety_last_timecode = 0;
|
||||
|
||||
// Let's see if the user specified audio sync for this track.
|
||||
found = false;
|
||||
@ -66,6 +67,8 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader,
|
||||
ti->async.linear = 1.0;
|
||||
ti->async.displacement = 0;
|
||||
}
|
||||
initial_displacement = ti->async.displacement;
|
||||
ti->async.displacement = 0;
|
||||
|
||||
// Let's see if the user has specified which cues he wants for this track.
|
||||
ti->cues = CUES_UNSPECIFIED;
|
||||
@ -598,9 +601,14 @@ void generic_packetizer_c::add_packet(unsigned char *data, int length,
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
if (timecode < 0)
|
||||
die("pr_generic.cpp/generic_packetizer_c::add_packet(): timecode < 0 "
|
||||
"(%lld)", timecode);
|
||||
if (timecode < 0) {
|
||||
drop_packet(data);
|
||||
return;
|
||||
}
|
||||
if (timecode < safety_last_timecode)
|
||||
die("pr_generic.cpp/generic_packetizer_c::add_packet(): timecode < "
|
||||
"last_timecode (%lld < %lld)", timecode, safety_last_timecode);
|
||||
safety_last_timecode = timecode;
|
||||
|
||||
pack = (packet_t *)safemalloc(sizeof(packet_t));
|
||||
memset(pack, 0, sizeof(packet_t));
|
||||
@ -631,6 +639,11 @@ void generic_packetizer_c::add_packet(unsigned char *data, int length,
|
||||
enqueued_bytes += pack->length;
|
||||
}
|
||||
|
||||
void generic_packetizer_c::drop_packet(unsigned char *data) {
|
||||
if (!duplicate_data)
|
||||
safefree(data);
|
||||
}
|
||||
|
||||
packet_t *generic_packetizer_c::get_packet() {
|
||||
packet_t *pack;
|
||||
|
||||
@ -842,6 +855,27 @@ int64_t generic_packetizer_c::get_next_timecode(int64_t timecode) {
|
||||
return new_timecode;
|
||||
}
|
||||
|
||||
bool generic_packetizer_c::needs_negative_displacement(float duration) {
|
||||
return ((initial_displacement < 0) &&
|
||||
(ti->async.displacement > initial_displacement));
|
||||
}
|
||||
|
||||
bool generic_packetizer_c::needs_positive_displacement(float duration) {
|
||||
return ((initial_displacement > 0) &&
|
||||
(iabs(ti->async.displacement - initial_displacement) >
|
||||
(duration / 2)));
|
||||
}
|
||||
|
||||
void generic_packetizer_c::displace(float by_ms) {
|
||||
ti->async.displacement += (int64_t)by_ms;
|
||||
if (initial_displacement < 0) {
|
||||
if (ti->async.displacement < initial_displacement)
|
||||
initial_displacement = 0;
|
||||
} else if (iabs(initial_displacement - ti->async.displacement) <
|
||||
(by_ms / 2))
|
||||
initial_displacement = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
generic_reader_c::generic_reader_c(track_info_t *nti) {
|
||||
|
@ -145,7 +145,8 @@ protected:
|
||||
bool duplicate_data;
|
||||
|
||||
track_info_t *ti;
|
||||
int64_t free_refs, enqueued_bytes;
|
||||
int64_t initial_displacement;
|
||||
int64_t free_refs, enqueued_bytes, safety_last_timecode;
|
||||
|
||||
KaxTrackEntry *track_entry;
|
||||
|
||||
@ -189,6 +190,7 @@ public:
|
||||
int64_t duration, bool duration_mandatory = false,
|
||||
int64_t bref = -1, int64_t fref = -1,
|
||||
int ref_priority = -1);
|
||||
virtual void drop_packet(unsigned char *data);
|
||||
virtual packet_t *get_packet();
|
||||
virtual int packet_available();
|
||||
virtual int64_t get_smallest_timecode();
|
||||
@ -246,6 +248,10 @@ public:
|
||||
virtual int64_t get_next_timecode(int64_t timecode);
|
||||
virtual void parse_ext_timecode_file(const char *name);
|
||||
|
||||
virtual bool needs_negative_displacement(float duration);
|
||||
virtual bool needs_positive_displacement(float duration);
|
||||
virtual void displace(float by_ms);
|
||||
|
||||
protected:
|
||||
virtual void dump_packet(const void *buffer, int size);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user