mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 11:54:01 +00:00
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:
parent
0d248c3595
commit
844f1feeb1
@ -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,
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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
|
||||
|
10
p_aac.cpp
10
p_aac.cpp
@ -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)
|
||||
|
6
p_aac.h
6
p_aac.h
@ -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,
|
||||
|
56
r_aac.cpp
56
r_aac.cpp
@ -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;
|
||||
|
||||
|
4
r_aac.h
4
r_aac.h
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user