Made the AAC detection code stricter.

The code now requires five consecutive identical AAC headers
instead of just two arbitrary headers. This fixes mis-detection

issues, e.g. those of bugs 373 and 374.
This commit is contained in:
Moritz Bunkus 2009-04-25 13:13:48 +02:00
parent e820f7e390
commit 5f7d53b56e
6 changed files with 109 additions and 51 deletions

View File

@ -1,3 +1,9 @@
2009-04-25 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: bug fix: Made the AAC detection code stricter in what
it accepts. This results in fewer mis-detections. Fix for bugs 373
and 374.
2009-04-16 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: bug fix: Splitting without the option "--engage

View File

@ -23,8 +23,8 @@ const int aac_sampling_freq[16] = {96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000,
0, 0, 0, 0}; // filling
bool
parse_aac_adif_header_internal(unsigned char *buf,
static bool
parse_aac_adif_header_internal(const unsigned char *buf,
int size,
aac_header_t *aac_header) {
int i, k;
@ -93,7 +93,7 @@ parse_aac_adif_header_internal(unsigned char *buf,
}
bool
parse_aac_adif_header(unsigned char *buf,
parse_aac_adif_header(const unsigned char *buf,
int size,
aac_header_t *aac_header) {
try {
@ -104,7 +104,7 @@ parse_aac_adif_header(unsigned char *buf,
}
static bool
is_adts_header(unsigned char *buf,
is_adts_header(const unsigned char *buf,
int size,
aac_header_t *aac_header,
bool emphasis_present) {
@ -128,6 +128,8 @@ is_adts_header(unsigned char *buf,
bc.skip_bits(2); // emphasis, MPEG-4 only
bc.skip_bits(1 + 1); // copyright_id_bit & copyright_id_start
frame_length = bc.get_bits(13);
if (0 == frame_length)
return false;
bc.skip_bits(11); // adts_buffer_fullness
bc.skip_bits(2); // no_raw_blocks_in_frame
if (!protection_absent)
@ -153,7 +155,7 @@ is_adts_header(unsigned char *buf,
}
int
find_aac_header(unsigned char *buf,
find_aac_header(const unsigned char *buf,
int size,
aac_header_t *aac_header,
bool emphasis_present) {
@ -184,7 +186,7 @@ get_aac_sampling_freq_idx(int sampling_freq) {
}
bool
parse_aac_data(unsigned char *data,
parse_aac_data(const unsigned char *data,
int size,
int &profile,
int &channels,
@ -273,3 +275,66 @@ create_aac_data(unsigned char *data,
}
return 2;
}
int
find_consecutive_aac_headers(const unsigned char *buf,
int size,
int num) {
aac_header_t aac_header, new_header;
int base = 0;
int pos = find_aac_header(&buf[base], size - base, &aac_header, false);
if (0 > pos)
return -1;
if (1 == num)
return pos;
base += pos;
do {
mxverb(4, boost::format("find_cons_aac_h: starting with base at %1%\n") % base);
int offset = aac_header.bytes;
int i;
for (i = 0; (num - 1) > i; ++i) {
if ((size - base - offset) < 2)
break;
pos = find_aac_header(&buf[base + offset], size - base - offset, &new_header, false);
if (0 == pos) {
if (new_header == aac_header) {
mxverb(4, boost::format("find_cons_aac_h: found good header %1%\n") % i);
offset += new_header.bytes;
continue;
} else
break;
} else
break;
}
if (i == (num - 1))
return base;
++base;
offset = 0;
pos = find_aac_header(&buf[base], size - base, &aac_header, false);
if (-1 == pos)
return -1;
base += pos;
} while (base < (size - 5));
return -1;
}
bool
operator ==(const aac_header_t &h1,
const aac_header_t &h2) {
return (h1.sample_rate == h2.sample_rate)
&& (h1.bit_rate == h2.bit_rate)
&& (h1.channels == h2.channels)
&& (h1.id == h2.id)
&& (h1.profile == h2.profile);
}

View File

@ -45,12 +45,15 @@ typedef struct {
int header_bit_size, header_byte_size, data_byte_size;
} aac_header_t;
bool MTX_DLL_API parse_aac_adif_header(unsigned char *buf, int size, aac_header_t *aac_header);
int MTX_DLL_API find_aac_header(unsigned char *buf, int size, aac_header_t *aac_header, bool emphasis_present);
bool MTX_DLL_API operator ==(const aac_header_t &h1, const aac_header_t &h2);
bool MTX_DLL_API parse_aac_adif_header(const unsigned char *buf, int size, aac_header_t *aac_header);
int MTX_DLL_API find_aac_header(const unsigned char *buf, int size, aac_header_t *aac_header, bool emphasis_present);
int MTX_DLL_API find_consecutive_aac_headers(const unsigned char *buf, int size, int num);
int MTX_DLL_API get_aac_sampling_freq_idx(int sampling_freq);
bool MTX_DLL_API parse_aac_data(unsigned char *data, int size, int &profile, int &channels, int &sample_rate, int &output_sample_rate, bool &sbr);
bool MTX_DLL_API parse_aac_data(const unsigned char *data, int size, int &profile, int &channels, int &sample_rate, int &output_sample_rate, bool &sbr);
int MTX_DLL_API create_aac_data(unsigned char *data, int profile, int channels, int sample_rate, int output_sample_rate, bool sbr);
bool MTX_DLL_API parse_aac_codec_id(const string &codec_id, int &id, int &profile);

View File

@ -22,49 +22,15 @@
#include "p_aac.h"
#include "output_control.h"
#define PROBESIZE 8192
int
aac_reader_c::probe_file(mm_io_c *io,
int64_t size) {
unsigned char buf[PROBESIZE];
aac_header_t aacheader;
int pos;
if (size < PROBESIZE)
return 0;
try {
io->setFilePointer(0, seek_beginning);
skip_id3v2_tag(*io);
if (io->read(buf, PROBESIZE) != PROBESIZE)
io->setFilePointer(0, seek_beginning);
io->setFilePointer(0, seek_beginning);
} catch (...) {
return 0;
}
if (parse_aac_adif_header(buf, PROBESIZE, &aacheader))
return 1;
pos = find_aac_header(buf, PROBESIZE, &aacheader, false);
if ((0 > pos) || ((pos + aacheader.bytes) >= PROBESIZE)) {
pos = find_aac_header(buf, PROBESIZE, &aacheader, true);
if ((0 > pos) || ((pos + aacheader.bytes) >= PROBESIZE))
return 0;
pos = find_aac_header(&buf[pos + aacheader.bytes], PROBESIZE - pos - aacheader.bytes, &aacheader, true);
if (0 != pos)
return 0;
}
pos = find_aac_header(&buf[pos + aacheader.bytes], PROBESIZE - pos - aacheader.bytes, &aacheader, false);
if (0 != pos)
return 0;
return 1;
int64_t size,
int64_t probe_range,
int num_headers) {
return (find_valid_headers(io, probe_range, num_headers) != -1) ? 1 : 0;
}
#define INITCHUNKSIZE 16384
#define SINITCHUNKSIZE "16384"
#define INITCHUNKSIZE 16384
aac_reader_c::aac_reader_c(track_info_c &_ti)
throw (error_c):
@ -219,3 +185,20 @@ aac_reader_c::identify() {
id_result_container("AAC");
id_result_track(0, ID_RESULT_TRACK_AUDIO, "AAC", verbose_info);
}
int
aac_reader_c::find_valid_headers(mm_io_c *io,
int64_t probe_range,
int num_headers) {
try {
io->setFilePointer(0, seek_beginning);
memory_cptr buf = memory_c::alloc(probe_range);
int num_read = io->read(buf->get(), probe_range);
int pos = find_consecutive_aac_headers(buf->get(), num_read, num_headers);
io->setFilePointer(0, seek_beginning);
return pos;
} catch (...) {
return -1;
}
}

View File

@ -42,10 +42,11 @@ public:
virtual int get_progress();
virtual void create_packetizer(int64_t id);
static int probe_file(mm_io_c *io, int64_t size);
static int probe_file(mm_io_c *io, int64_t size, int64_t probe_range, int num_headers);
protected:
virtual void guess_adts_version();
static int find_valid_headers(mm_io_c *io, int64_t probe_range, int num_headers);
};
#endif // __R_AAC_H

View File

@ -353,6 +353,8 @@ get_file_type(filelist_t &file) {
type = FILE_TYPE_MP3;
else if (ac3_reader_c::probe_file(io, size, probe_sizes[i], 5))
type = FILE_TYPE_AC3;
else if (aac_reader_c::probe_file(io, size, probe_sizes[i], 5))
type = FILE_TYPE_AAC;
}
// More file types with detection issues.
if (type != FILE_TYPE_IS_UNKNOWN)
@ -363,8 +365,6 @@ get_file_type(filelist_t &file) {
type = FILE_TYPE_MP3;
else if (dts_reader_c::probe_file(io, size))
type = FILE_TYPE_DTS;
else if (aac_reader_c::probe_file(io, size))
type = FILE_TYPE_AAC;
else if (vobbtn_reader_c::probe_file(io, size))
type = FILE_TYPE_VOBBTN;
else if (avc_es_reader_c::probe_file(io, size))