Allocate space for the extra data after the RealMedia headers - otherwise the pointers would be invalid. Removed the "set number of samples per packet" function from the AAC packetizer as AAC is still always 1024 samples/packet.

This commit is contained in:
Moritz Bunkus 2004-01-23 19:15:12 +00:00
parent 5d2e36dc92
commit 4d3b90a3ee
5 changed files with 27 additions and 61 deletions

View File

@ -1,3 +1,7 @@
2004-01-23 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: bug fix: The AAC-in-Real stuff again.
2004-01-22 Moritz Bunkus <moritz@bunkus.org> 2004-01-22 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: Changed the complete timecode handling from ms * mkvmerge: Changed the complete timecode handling from ms

View File

@ -202,9 +202,16 @@ parse_aac_data(unsigned char *data,
int &sample_rate, int &sample_rate,
int &output_sample_rate, int &output_sample_rate,
bool &sbr) { bool &sbr) {
int i;
if (size < 2) if (size < 2)
return false; return false;
mxverb(4, "parse_aac_data: size %d, data: 0x", size);
for (i = 0; i < size; i++)
mxverb(4, "%02x ", data[i]);
mxverb(4, "\n");
profile = (data[0] >> 3) - 1; profile = (data[0] >> 3) - 1;
sample_rate = aac_sampling_freq[((data[0] & 0x07) << 1) | (data[1] >> 7)]; sample_rate = aac_sampling_freq[((data[0] & 0x07) << 1) | (data[1] >> 7)];
channels = (data[1] & 0x7f) >> 3; channels = (data[1] & 0x7f) >> 3;

View File

@ -190,6 +190,7 @@ real_reader_c::~real_reader_c() {
delete demuxer->segments; delete demuxer->segments;
} }
safefree(demuxer->private_data); safefree(demuxer->private_data);
safefree(demuxer->extra_data);
safefree(demuxer); safefree(demuxer);
} }
demuxers.clear(); demuxers.clear();
@ -393,10 +394,12 @@ real_reader_c::parse_headers() {
dmx->samples_per_second = get_uint16_be(&ra5p->sample_rate); dmx->samples_per_second = get_uint16_be(&ra5p->sample_rate);
dmx->bits_per_sample = get_uint16_be(&ra5p->sample_size); dmx->bits_per_sample = get_uint16_be(&ra5p->sample_size);
if (size > (sizeof(real_audio_v5_props_t) + 4)) { if (size > (sizeof(real_audio_v5_props_t) + 4)) {
dmx->extra_data = (unsigned char *)(ra5p + 1);
dmx->extra_data += 4;
dmx->extra_data_size = size - 4 - dmx->extra_data_size = size - 4 -
sizeof(real_audio_v5_props_t); sizeof(real_audio_v5_props_t);
dmx->extra_data =
(unsigned char *)safememdup((unsigned char *)ra5p + 4 +
sizeof(real_audio_v5_props_t),
dmx->extra_data_size);
} }
} }
mxverb(2, "real_reader: extra_data_size: %d\n", mxverb(2, "real_reader: extra_data_size: %d\n",
@ -545,7 +548,6 @@ real_reader_c::create_packetizer(int64_t tid) {
dmx->packetizer = dmx->packetizer =
new aac_packetizer_c(this, AAC_ID_MPEG4, profile, new aac_packetizer_c(this, AAC_ID_MPEG4, profile,
sample_rate, channels, ti, false, true); sample_rate, channels, ti, false, true);
((aac_packetizer_c *)dmx->packetizer)->set_samples_per_packet(2048);
mxverb(1, "+-> Using the AAC output module for stream " mxverb(1, "+-> Using the AAC output module for stream "
"%u (FourCC: %s).\n", dmx->id, dmx->fourcc); "%u (FourCC: %s).\n", dmx->id, dmx->fourcc);
if (profile == AAC_PROFILE_SBR) if (profile == AAC_PROFILE_SBR)
@ -619,10 +621,6 @@ real_reader_c::finish() {
for (i = 0; i < demuxers.size(); i++) { for (i = 0; i < demuxers.size(); i++) {
dmx = demuxers[i]; dmx = demuxers[i];
if ((dmx->type == 'a') && (dmx->c_data != NULL)) { if ((dmx->type == 'a') && (dmx->c_data != NULL)) {
if (dmx->is_aac) {
safefree(dmx->c_data);
continue;
}
dur = dmx->c_timecode / dmx->c_numpackets; dur = dmx->c_timecode / dmx->c_numpackets;
dmx->packetizer->process(dmx->c_data, dmx->c_len, dmx->c_timecode + dur, dmx->packetizer->process(dmx->c_data, dmx->c_len, dmx->c_timecode + dur,
dur, dmx->c_keyframe ? -1 : dmx->c_reftimecode); dur, dmx->c_keyframe ? -1 : dmx->c_reftimecode);
@ -708,44 +706,10 @@ real_reader_c::read(generic_packetizer_c *) {
assemble_packet(dmx, chunk, length, timecode, (flags & 2) == 2); assemble_packet(dmx, chunk, length, timecode, (flags & 2) == 2);
safefree(chunk); safefree(chunk);
} else if (dmx->is_aac) { } else if (dmx->is_aac)
if ((dmx->c_data == NULL) && (dmx->c_numpackets == 0)) {
// Cache the very first packet in order to find the number of
// samples per AAC frame ( = the duration).
dmx->c_data = chunk;
dmx->c_len = length;
dmx->c_timecode = timecode;
dmx->c_numpackets = 1;
return EMOREDATA;
} else if (dmx->c_data != NULL) {
if ((dmx->c_len < 2) || ((dmx->c_data[1] & 0xf0) == 0))
mxerror("real_reader: The AAC track %u of '%s' contains an invalid "
"data packet (either it's too short or the number of "
"AAC sub packets is 0). Aborting.\n", dmx->id, ti->fname);
// We've got the first packet cached. Now calculate the number of
// samples and store that in dmx->c_reftimecode.
dmx->c_reftimecode = (timecode - dmx->c_timecode) *
dmx->samples_per_second / 1000000000;
// Now devide the number of samples in this first packet by the
// number of AAC frames in that packet. Also round it to the nearest
// power of 2.
dmx->c_reftimecode /= chunk[1] >> 4;
dmx->c_reftimecode = round_to_nearest_pow2(dmx->c_reftimecode);
deliver_aac_frames(dmx, dmx->c_data, dmx->c_len);
dmx->c_data = NULL;
mxverb(2, "real_reader: %u/'%s': Samples per AAC frame: %lld\n",
dmx->id, ti->fname, dmx->c_reftimecode);
if (dmx->c_reftimecode != 2048) {
((aac_packetizer_c *)dmx->packetizer)->
set_samples_per_packet(dmx->c_reftimecode);
rerender_track_headers();
}
}
deliver_aac_frames(dmx, chunk, length); deliver_aac_frames(dmx, chunk, length);
} else { else {
if (dmx->c_data != NULL) if (dmx->c_data != NULL)
dmx->packetizer->process(dmx->c_data, dmx->c_len, dmx->c_timecode, dmx->packetizer->process(dmx->c_data, dmx->c_len, dmx->c_timecode,
timecode - dmx->c_timecode, timecode - dmx->c_timecode,

View File

@ -51,7 +51,8 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader,
emphasis_present = nemphasis_present; emphasis_present = nemphasis_present;
set_track_type(track_audio); set_track_type(track_audio);
set_samples_per_packet(1024); set_track_default_duration((int64_t)(1024 * 1000000000.0 * ti->async.linear /
samples_per_sec));
duplicate_data_on_add(headerless); duplicate_data_on_add(headerless);
} }
@ -73,7 +74,7 @@ aac_packetizer_c::get_aac_packet(unsigned long *header,
if ((pos + aacheader->bytes) > size) if ((pos + aacheader->bytes) > size)
return NULL; return NULL;
pins = samples_per_packet * 1000000000.0 / samples_per_sec; pins = 1024 * 1000000000.0 / samples_per_sec;
if (needs_negative_displacement(pins)) { if (needs_negative_displacement(pins)) {
/* /*
@ -184,9 +185,9 @@ aac_packetizer_c::process(unsigned char *buf,
if (timecode != -1) if (timecode != -1)
my_timecode = timecode; my_timecode = timecode;
else else
my_timecode = (int64_t)(1000000000.0 * packetno * samples_per_packet / my_timecode = (int64_t)(1024 * 1000000000.0 * packetno /
samples_per_sec); samples_per_sec);
duration = (int64_t)(1000000000.0 * samples_per_packet * ti->async.linear / duration = (int64_t)(1024 * 1000000000.0 * ti->async.linear /
samples_per_sec); samples_per_sec);
packetno++; packetno++;
@ -211,13 +212,13 @@ aac_packetizer_c::process(unsigned char *buf,
byte_buffer.add(buf, size); byte_buffer.add(buf, size);
while ((packet = get_aac_packet(&header, &aacheader)) != NULL) { while ((packet = get_aac_packet(&header, &aacheader)) != NULL) {
if (timecode == -1) if (timecode == -1)
my_timecode = (int64_t)(1000000000.0 * packetno * samples_per_packet / my_timecode = (int64_t)(1024 * 1000000000.0 * packetno /
samples_per_sec); samples_per_sec);
else else
my_timecode = timecode + ti->async.displacement; my_timecode = timecode + ti->async.displacement;
my_timecode = (int64_t)(my_timecode * ti->async.linear); my_timecode = (int64_t)(my_timecode * ti->async.linear);
add_packet(packet, aacheader.data_byte_size, my_timecode, add_packet(packet, aacheader.data_byte_size, my_timecode,
(int64_t)(1000000000.0 * samples_per_packet * (int64_t)(1024 * 1000000000.0 *
ti->async.linear / samples_per_sec)); ti->async.linear / samples_per_sec));
packetno++; packetno++;
} }
@ -228,16 +229,7 @@ aac_packetizer_c::process(unsigned char *buf,
} }
void void
aac_packetizer_c::set_samples_per_packet(int nsamples_per_packet) { aac_packetizer_c::dump_debug_info() {
samples_per_packet = nsamples_per_packet;
if (use_durations)
set_track_default_duration((int64_t)(samples_per_packet *
1000000000.0 *
ti->async.linear /
samples_per_sec));
}
void aac_packetizer_c::dump_debug_info() {
mxdebug("aac_packetizer_c: queue: %d; buffer size: %d\n", mxdebug("aac_packetizer_c: queue: %d; buffer size: %d\n",
packet_queue.size(), byte_buffer.get_size()); packet_queue.size(), byte_buffer.get_size());
} }

View File

@ -41,7 +41,7 @@ class aac_packetizer_c: public generic_packetizer_c {
private: private:
int64_t bytes_output, packetno; int64_t bytes_output, packetno;
unsigned long samples_per_sec; unsigned long samples_per_sec;
int channels, id, profile, samples_per_packet; int channels, id, profile;
bool headerless, emphasis_present; bool headerless, emphasis_present;
byte_buffer_c byte_buffer; byte_buffer_c byte_buffer;
@ -56,7 +56,6 @@ public:
int64_t length = -1, int64_t bref = -1, int64_t length = -1, int64_t bref = -1,
int64_t fref = -1); int64_t fref = -1);
virtual void set_headers(); virtual void set_headers();
virtual void set_samples_per_packet(int nsamples_per_packet);
private: private:
virtual unsigned char *get_aac_packet(unsigned long *header, virtual unsigned char *get_aac_packet(unsigned long *header,