Made the AAC reader automatically recognize if a MPEG4 AAC file contains the emphasis header (deprecated) or not (current standard).

This commit is contained in:
Moritz Bunkus 2003-06-19 19:32:50 +00:00
parent 0d248c3595
commit 844f1feeb1
8 changed files with 77 additions and 23 deletions

View File

@ -1,5 +1,12 @@
2003-06-19 Moritz Bunkus <moritz@bunkus.org>
* Made the AAC reader automatically recognize if a MPEG4 AAC file
contains the emphasis header (deprecated) or not (current standard).
2003-06-15 Moritz Bunkus <moritz@bunkus.org>
* Released v0.4.4.
* Several options now need an explicity track ID to specify
which tracks of an input file the option should be applied
to. These options include --atracks, --vtracks, --stracks, --sync,

View File

@ -112,7 +112,7 @@ int parse_aac_adif_header(unsigned char *buf, int size,
}
static int is_adts_header(unsigned char *buf, int size, int bpos,
aac_header_t *aac_header) {
aac_header_t *aac_header, bool emphasis_present) {
int id, profile, sfreq_index, channels, frame_length;
bool eob, protection_absent, b;
unsigned int bits;
@ -133,7 +133,7 @@ static int is_adts_header(unsigned char *buf, int size, int bpos,
bc.get_bits(3, channels);
bc.get_bit(b); // original/copy
bc.get_bit(b); // home
if (id == 0)
if ((id == 0) && emphasis_present)
bc.get_bits(2, bits); // emphasis, MPEG-4 only
bc.get_bit(b); // copyright_id_bit
bc.get_bit(b); // copyright_id_start
@ -152,7 +152,7 @@ static int is_adts_header(unsigned char *buf, int size, int bpos,
aac_header->bytes = frame_length;
aac_header->channels = channels > 6 ? 2 : channels;
aac_header->bit_rate = 1024;
if (id == 0) // MPEG-4
if ((id == 0) && emphasis_present) // MPEG-4
aac_header->header_bit_size = 58;
else
aac_header->header_bit_size = 56;
@ -165,12 +165,13 @@ static int is_adts_header(unsigned char *buf, int size, int bpos,
return 1;
}
int find_aac_header(unsigned char *buf, int size, aac_header_t *aac_header) {
int find_aac_header(unsigned char *buf, int size, aac_header_t *aac_header,
bool emphasis_present) {
int bpos;
bpos = 0;
while (bpos < size) {
if (is_adts_header(buf, size, bpos, aac_header))
if (is_adts_header(buf, size, bpos, aac_header, emphasis_present))
return bpos;
bpos++;
}

View File

@ -33,6 +33,7 @@ typedef struct {
int parse_aac_adif_header(unsigned char *buf, int size,
aac_header_t *aac_header);
int find_aac_header(unsigned char *buf, int size, aac_header_t *aac_header);
int find_aac_header(unsigned char *buf, int size, aac_header_t *aac_header,
bool emphasis_present);
#endif // __AACCOMMON_H

View File

@ -34,6 +34,7 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader, int nid,
int nprofile,
unsigned long nsamples_per_sec,
int nchannels, track_info_t *nti,
bool nemphasis_present,
bool nheaderless)
throw (error_c): generic_packetizer_c(nreader, nti) {
packetno = 0;
@ -45,6 +46,7 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader, int nid,
id = nid;
profile = nprofile;
headerless = nheaderless;
emphasis_present = nemphasis_present;
set_track_type(track_audio);
duplicate_data_on_add(headerless);
@ -67,11 +69,12 @@ void aac_packetizer_c::add_to_buffer(unsigned char *buf, int size) {
int aac_packetizer_c::aac_packet_available() {
int pos;
aac_header_t aacheader;
aac_header_t aacheader;
if (packet_buffer == NULL)
return 0;
pos = find_aac_header(packet_buffer, buffer_size, &aacheader);
pos = find_aac_header(packet_buffer, buffer_size, &aacheader,
emphasis_present);
if (pos < 0)
return 0;
@ -101,7 +104,8 @@ unsigned char *aac_packetizer_c::get_aac_packet(unsigned long *header,
if (packet_buffer == NULL)
return 0;
pos = find_aac_header(packet_buffer, buffer_size, aacheader);
pos = find_aac_header(packet_buffer, buffer_size, aacheader,
emphasis_present);
if (pos < 0)
return 0;
if ((pos + aacheader->bytes) > buffer_size)

View File

@ -39,13 +39,13 @@ private:
unsigned long samples_per_sec;
int channels, buffer_size, id, profile;
unsigned char *packet_buffer;
bool headerless;
bool headerless, emphasis_present;
public:
aac_packetizer_c(generic_reader_c *nreader, int nid, int nprofile,
unsigned long nsamples_per_sec, int nchannels,
track_info_t *nti, bool nheaderless = false)
throw (error_c);
track_info_t *nti, bool emphasis_present,
bool nheaderless = false) throw (error_c);
virtual ~aac_packetizer_c();
virtual int process(unsigned char *buf, int size, int64_t timecode = -1,

View File

@ -45,12 +45,15 @@ int aac_reader_c::probe_file(mm_io_c *mm_io, int64_t size) {
}
if (parse_aac_adif_header((unsigned char *)buf, 4096, &aacheader))
return 1;
if (find_aac_header((unsigned char *)buf, 4096, &aacheader) < 0)
if (find_aac_header((unsigned char *)buf, 4096, &aacheader, false) != 0)
return 0;
return 1;
}
#define INITCHUNKSIZE 16384
#define SINITCHUNKSIZE "16384"
aac_reader_c::aac_reader_c(track_info_t *nti) throw (error_c):
generic_reader_c(nti) {
int adif;
@ -61,23 +64,29 @@ aac_reader_c::aac_reader_c(track_info_t *nti) throw (error_c):
mm_io->setFilePointer(0, seek_end);
size = mm_io->getFilePointer();
mm_io->setFilePointer(0, seek_beginning);
chunk = (unsigned char *)safemalloc(4096);
if (mm_io->read(chunk, 4096) != 4096)
throw error_c("aac_reader: Could not read 4096 bytes.");
chunk = (unsigned char *)safemalloc(INITCHUNKSIZE);
if (mm_io->read(chunk, INITCHUNKSIZE) != INITCHUNKSIZE)
throw error_c("aac_reader: Could not read " SINITCHUNKSIZE " bytes.");
mm_io->setFilePointer(0, seek_beginning);
if (parse_aac_adif_header(chunk, 4096, &aacheader)) {
if (parse_aac_adif_header(chunk, INITCHUNKSIZE, &aacheader)) {
throw error_c("aac_reader: ADIF header files are not supported.");
adif = 1;
} else if (find_aac_header(chunk, 4096, &aacheader) < 0)
throw error_c("aac_reader: No valid AAC packet found in the first "
"4096 bytes.\n");
else
} else {
if (find_aac_header(chunk, INITCHUNKSIZE, &aacheader, emphasis_present)
!= 0)
throw error_c("aac_reader: No valid AAC packet found in the first "
SINITCHUNKSIZE " bytes.\n");
guess_adts_version();
fprintf(stdout, "emphasis_present: %s\n", emphasis_present ? "true" :
"false");
adif = 0;
}
bytes_processed = 0;
ti->id = 0; // ID for this track.
aacpacketizer = new aac_packetizer_c(this, aacheader.id, aacheader.profile,
aacheader.sample_rate,
aacheader.channels, ti);
aacheader.channels, ti,
emphasis_present);
} catch (exception &ex) {
throw error_c("aac_reader: Could not open the file.");
}
@ -94,6 +103,33 @@ aac_reader_c::~aac_reader_c() {
delete aacpacketizer;
}
// Try to guess if the MPEG4 header contains the emphasis field (2 bits)
void aac_reader_c::guess_adts_version() {
int pos;
aac_header_t aacheader;
emphasis_present = false;
// Due to the checks we do have an ADTS header at 0.
find_aac_header(chunk, INITCHUNKSIZE, &aacheader, emphasis_present);
if (aacheader.id != 0) // MPEG2
return;
// Now make some sanity checks on the size field.
if (aacheader.bytes > 8192) {
emphasis_present = true; // Looks like it's borked.
return;
}
// Looks ok so far. See if the next ADTS is right behind this packet.
pos = find_aac_header(&chunk[aacheader.bytes], INITCHUNKSIZE -
aacheader.bytes, &aacheader, emphasis_present);
if (pos != 0) { // Not ok - what do we do now?
emphasis_present = true;
return;
}
}
int aac_reader_c::read() {
int nread;

View File

@ -36,6 +36,7 @@ private:
mm_io_c *mm_io;
aac_packetizer_c *aacpacketizer;
int64_t bytes_processed, size;
bool emphasis_present;
public:
aac_reader_c(track_info_t *nti) throw (error_c);
@ -49,6 +50,9 @@ public:
virtual void identify();
static int probe_file(mm_io_c *mm_io, int64_t size);
protected:
virtual void guess_adts_version();
};
#endif // __R_AAC_H

View File

@ -990,7 +990,8 @@ void mkv_reader_c::create_packetizers() {
t->packetizer = new aac_packetizer_c(this, id, profile,
(unsigned long)t->a_sfreq,
t->a_channels, &nti, true);
t->a_channels, &nti,
false, true);
if (verbose)
fprintf(stdout, "Matroska demultiplexer (%s): using the AAC "
"output module for track ID %u.\n", ti->fname, t->tnum);