mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 11:54:01 +00:00
Implemented a switch that has to be used for SBR AAC / AAC+ / HE-AAC if the source file is an AAC file and the AAC file contains SBR AAC data (no automatic detection possible in this case!).
This commit is contained in:
parent
e622f34e61
commit
a58d1beb74
@ -1,3 +1,9 @@
|
|||||||
|
2003-08-18 Moritz Bunkus <moritz@bunkus.org>
|
||||||
|
|
||||||
|
* mkvmerge: Implemented a switch that has to be used for SBR AAC /
|
||||||
|
AAC+ / HE-AAC if the source file is an AAC file and the AAC file
|
||||||
|
contains SBR AAC data (no automatic detection possible in this case!).
|
||||||
|
|
||||||
2003-08-14 Moritz Bunkus <moritz@bunkus.org>
|
2003-08-14 Moritz Bunkus <moritz@bunkus.org>
|
||||||
|
|
||||||
* mkvmerge: Low bitrate AC3 tracks from Real's DNET are identified
|
* mkvmerge: Low bitrate AC3 tracks from Real's DNET are identified
|
||||||
|
@ -226,6 +226,21 @@ tracks by selecting different track IDs each time.
|
|||||||
\fB\-t\fR, \fB\-\-tags\fR <\fITID\fR:\fIfile\fR>
|
\fB\-t\fR, \fB\-\-tags\fR <\fITID\fR:\fIfile\fR>
|
||||||
Read tags for the track with the number \fITID\fR from the \fIfile\fR. See
|
Read tags for the track with the number \fITID\fR from the \fIfile\fR. See
|
||||||
the section about tags below for details.
|
the section about tags below for details.
|
||||||
|
.TP
|
||||||
|
\fB\-\-aab\-is\-sbr\fR <\fITID\fR>
|
||||||
|
Tells \fBmkvmerge\fR that the track with the ID \fITID\fR is SBR AAC (also
|
||||||
|
known as HE-AAC or AAC+). This options is needed if a) the source file is an
|
||||||
|
AAC file (NOT for a Matroska file) and b) the AAC file contains SBR AAC data.
|
||||||
|
The reason for this switch is that it is technically impossible to
|
||||||
|
automatically tell normal AAC data from SBR AAC data without decoding a
|
||||||
|
complete AAC frame. As there are several patent issues with AAC decoders I
|
||||||
|
won't implement this decoding stage. So for SBR AAC files this switch is
|
||||||
|
mandatory. The resulting file might not play back correctly or even not at
|
||||||
|
all if the switch was omitted.
|
||||||
|
.br
|
||||||
|
If the source file is a Matroska file then the CodecID should be enough to
|
||||||
|
detect SBR AAC. However, if the CodecID is wrong then this switch can be used
|
||||||
|
to correct that.
|
||||||
|
|
||||||
.LP
|
.LP
|
||||||
Options that only apply to video tracks:
|
Options that only apply to video tracks:
|
||||||
|
@ -26,11 +26,12 @@
|
|||||||
#define MKV_A_AAC_2MAIN "A_AAC/MPEG2/MAIN"
|
#define MKV_A_AAC_2MAIN "A_AAC/MPEG2/MAIN"
|
||||||
#define MKV_A_AAC_2LC "A_AAC/MPEG2/LC"
|
#define MKV_A_AAC_2LC "A_AAC/MPEG2/LC"
|
||||||
#define MKV_A_AAC_2SSR "A_AAC/MPEG2/SSR"
|
#define MKV_A_AAC_2SSR "A_AAC/MPEG2/SSR"
|
||||||
|
#define MKV_A_AAC_2SBR "A_AAC/MPEG2/LC/SBR"
|
||||||
#define MKV_A_AAC_4MAIN "A_AAC/MPEG4/MAIN"
|
#define MKV_A_AAC_4MAIN "A_AAC/MPEG4/MAIN"
|
||||||
#define MKV_A_AAC_4LC "A_AAC/MPEG4/LC"
|
#define MKV_A_AAC_4LC "A_AAC/MPEG4/LC"
|
||||||
#define MKV_A_AAC_4SSR "A_AAC/MPEG4/SSR"
|
#define MKV_A_AAC_4SSR "A_AAC/MPEG4/SSR"
|
||||||
#define MKV_A_AAC_4LTP "A_AAC/MPEG4/LTP"
|
#define MKV_A_AAC_4LTP "A_AAC/MPEG4/LTP"
|
||||||
#define MKV_A_AAC_4SBR "A_AAC/MPEG4/SBR"
|
#define MKV_A_AAC_4SBR "A_AAC/MPEG4/LC/SBR"
|
||||||
#define MKV_A_AC3 "A_AC3"
|
#define MKV_A_AC3 "A_AC3"
|
||||||
#define MKV_A_DTS "A_DTS"
|
#define MKV_A_DTS "A_DTS"
|
||||||
#define MKV_A_MP3 "A_MPEG/L3"
|
#define MKV_A_MP3 "A_MPEG/L3"
|
||||||
|
@ -279,6 +279,7 @@ static void usage() {
|
|||||||
" --language <TID:lang> Sets the language for the track (ISO639-2\n"
|
" --language <TID:lang> Sets the language for the track (ISO639-2\n"
|
||||||
" code, see --list-languages).\n"
|
" code, see --list-languages).\n"
|
||||||
" -t, --tags <TID:file> Read tags for the track from a XML file.\n"
|
" -t, --tags <TID:file> Read tags for the track from a XML file.\n"
|
||||||
|
" --aac-is-sbr <TID> Track with the ID is HE-AAC/AAC+/SBR-AAC.\n"
|
||||||
"\n Options that only apply to video tracks:\n"
|
"\n Options that only apply to video tracks:\n"
|
||||||
" -f, --fourcc <FOURCC> Forces the FourCC to the specified value.\n"
|
" -f, --fourcc <FOURCC> Forces the FourCC to the specified value.\n"
|
||||||
" Works only for video tracks.\n"
|
" Works only for video tracks.\n"
|
||||||
@ -1043,6 +1044,7 @@ static void identify(const char *filename) {
|
|||||||
ti.atracks = new vector<int64_t>;
|
ti.atracks = new vector<int64_t>;
|
||||||
ti.vtracks = new vector<int64_t>;
|
ti.vtracks = new vector<int64_t>;
|
||||||
ti.stracks = new vector<int64_t>;
|
ti.stracks = new vector<int64_t>;
|
||||||
|
ti.aac_is_sbr = new vector<int64_t>;
|
||||||
|
|
||||||
file = (filelist_t *)safemalloc(sizeof(filelist_t));
|
file = (filelist_t *)safemalloc(sizeof(filelist_t));
|
||||||
|
|
||||||
@ -1096,6 +1098,7 @@ static void parse_args(int argc, char **argv) {
|
|||||||
ti.languages = new vector<language_t>;
|
ti.languages = new vector<language_t>;
|
||||||
ti.sub_charsets = new vector<language_t>;
|
ti.sub_charsets = new vector<language_t>;
|
||||||
ti.all_tags = new vector<tags_t>;
|
ti.all_tags = new vector<tags_t>;
|
||||||
|
ti.aac_is_sbr = new vector<int64_t>;
|
||||||
ti.aspect_ratio = 0.0;
|
ti.aspect_ratio = 0.0;
|
||||||
ti.atracks = new vector<int64_t>;
|
ti.atracks = new vector<int64_t>;
|
||||||
ti.vtracks = new vector<int64_t>;
|
ti.vtracks = new vector<int64_t>;
|
||||||
@ -1474,6 +1477,18 @@ static void parse_args(int argc, char **argv) {
|
|||||||
parse_tags(argv[i + 1], tags);
|
parse_tags(argv[i + 1], tags);
|
||||||
ti.all_tags->push_back(tags);
|
ti.all_tags->push_back(tags);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
} else if (!strcmp(argv[i], "--aac-is-sbr")) {
|
||||||
|
if ((i + 1) >= argc) {
|
||||||
|
mxprint(stderr, "Error: %s lacks the track ID.\n", argv[i]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!parse_int(argv[i + 1], id) || (id < 0)) {
|
||||||
|
mxprint(stderr, "Error: '%s' is not a valid track ID.\n", argv[i + 1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ti.aac_is_sbr->push_back(id);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The argument is an input file.
|
// The argument is an input file.
|
||||||
@ -1523,6 +1538,7 @@ static void parse_args(int argc, char **argv) {
|
|||||||
delete ti.languages;
|
delete ti.languages;
|
||||||
delete ti.sub_charsets;
|
delete ti.sub_charsets;
|
||||||
delete ti.all_tags;
|
delete ti.all_tags;
|
||||||
|
delete ti.aac_is_sbr;
|
||||||
memset(&ti, 0, sizeof(track_info_t));
|
memset(&ti, 0, sizeof(track_info_t));
|
||||||
ti.audio_syncs = new vector<audio_sync_t>;
|
ti.audio_syncs = new vector<audio_sync_t>;
|
||||||
ti.cue_creations = new vector<cue_creation_t>;
|
ti.cue_creations = new vector<cue_creation_t>;
|
||||||
@ -1530,6 +1546,7 @@ static void parse_args(int argc, char **argv) {
|
|||||||
ti.languages = new vector<language_t>;
|
ti.languages = new vector<language_t>;
|
||||||
ti.sub_charsets = new vector<language_t>;
|
ti.sub_charsets = new vector<language_t>;
|
||||||
ti.all_tags = new vector<tags_t>;
|
ti.all_tags = new vector<tags_t>;
|
||||||
|
ti.aac_is_sbr = new vector<int64_t>;
|
||||||
ti.aspect_ratio = 0.0;
|
ti.aspect_ratio = 0.0;
|
||||||
ti.atracks = new vector<int64_t>;
|
ti.atracks = new vector<int64_t>;
|
||||||
ti.vtracks = new vector<int64_t>;
|
ti.vtracks = new vector<int64_t>;
|
||||||
|
@ -184,6 +184,8 @@ void aac_packetizer_c::set_headers() {
|
|||||||
set_codec_id(MKV_A_AAC_4SSR);
|
set_codec_id(MKV_A_AAC_4SSR);
|
||||||
else if (profile == AAC_PROFILE_LTP)
|
else if (profile == AAC_PROFILE_LTP)
|
||||||
set_codec_id(MKV_A_AAC_4LTP);
|
set_codec_id(MKV_A_AAC_4LTP);
|
||||||
|
else if (profile == AAC_PROFILE_SBR)
|
||||||
|
set_codec_id(MKV_A_AAC_4SBR);
|
||||||
else
|
else
|
||||||
die("aac_packetizer: Unknown AAC MPEG-4 object type %d.", profile);
|
die("aac_packetizer: Unknown AAC MPEG-4 object type %d.", profile);
|
||||||
} else {
|
} else {
|
||||||
@ -193,6 +195,8 @@ void aac_packetizer_c::set_headers() {
|
|||||||
set_codec_id(MKV_A_AAC_2LC);
|
set_codec_id(MKV_A_AAC_2LC);
|
||||||
else if (profile == AAC_PROFILE_SSR)
|
else if (profile == AAC_PROFILE_SSR)
|
||||||
set_codec_id(MKV_A_AAC_2SSR);
|
set_codec_id(MKV_A_AAC_2SSR);
|
||||||
|
else if (profile == AAC_PROFILE_SBR)
|
||||||
|
set_codec_id(MKV_A_AAC_2SBR);
|
||||||
else
|
else
|
||||||
die("aac_packetizer: Unknown AAC MPEG-2 profile %d.", profile);
|
die("aac_packetizer: Unknown AAC MPEG-2 profile %d.", profile);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define AAC_PROFILE_LC 1
|
#define AAC_PROFILE_LC 1
|
||||||
#define AAC_PROFILE_SSR 2
|
#define AAC_PROFILE_SSR 2
|
||||||
#define AAC_PROFILE_LTP 3
|
#define AAC_PROFILE_LTP 3
|
||||||
|
#define AAC_PROFILE_SBR 4
|
||||||
|
|
||||||
class aac_packetizer_c: public generic_packetizer_c {
|
class aac_packetizer_c: public generic_packetizer_c {
|
||||||
private:
|
private:
|
||||||
|
@ -614,6 +614,7 @@ track_info_t *duplicate_track_info(track_info_t *src) {
|
|||||||
dst->all_tags = new vector<tags_t>(*src->all_tags);
|
dst->all_tags = new vector<tags_t>(*src->all_tags);
|
||||||
for (i = 0; i < src->all_tags->size(); i++)
|
for (i = 0; i < src->all_tags->size(); i++)
|
||||||
(*dst->all_tags)[i].file_name = safestrdup((*src->all_tags)[i].file_name);
|
(*dst->all_tags)[i].file_name = safestrdup((*src->all_tags)[i].file_name);
|
||||||
|
dst->aac_is_sbr = new vector<int64_t>(*src->aac_is_sbr);
|
||||||
dst->private_data = (unsigned char *)safememdup(src->private_data,
|
dst->private_data = (unsigned char *)safememdup(src->private_data,
|
||||||
src->private_size);
|
src->private_size);
|
||||||
dst->sub_charset = safestrdup(src->sub_charset);
|
dst->sub_charset = safestrdup(src->sub_charset);
|
||||||
@ -643,6 +644,7 @@ void free_track_info(track_info_t *ti) {
|
|||||||
for (i = 0; i < ti->all_tags->size(); i++)
|
for (i = 0; i < ti->all_tags->size(); i++)
|
||||||
safefree((*ti->all_tags)[i].file_name);
|
safefree((*ti->all_tags)[i].file_name);
|
||||||
delete ti->all_tags;
|
delete ti->all_tags;
|
||||||
|
delete ti->aac_is_sbr;
|
||||||
safefree(ti->language);
|
safefree(ti->language);
|
||||||
safefree(ti->private_data);
|
safefree(ti->private_data);
|
||||||
safefree(ti->sub_charset);
|
safefree(ti->sub_charset);
|
||||||
|
@ -109,6 +109,8 @@ typedef struct {
|
|||||||
vector<tags_t> *all_tags; // As given on the command line
|
vector<tags_t> *all_tags; // As given on the command line
|
||||||
tags_t *tags_ptr; // For this very track
|
tags_t *tags_ptr; // For this very track
|
||||||
KaxTags *tags; // For this very track
|
KaxTags *tags; // For this very track
|
||||||
|
|
||||||
|
vector<int64_t> *aac_is_sbr; // For AAC+/HE-AAC/SBR
|
||||||
} track_info_t;
|
} track_info_t;
|
||||||
|
|
||||||
class generic_reader_c;
|
class generic_reader_c;
|
||||||
|
@ -56,7 +56,7 @@ int aac_reader_c::probe_file(mm_io_c *mm_io, int64_t size) {
|
|||||||
|
|
||||||
aac_reader_c::aac_reader_c(track_info_t *nti) throw (error_c):
|
aac_reader_c::aac_reader_c(track_info_t *nti) throw (error_c):
|
||||||
generic_reader_c(nti) {
|
generic_reader_c(nti) {
|
||||||
int adif;
|
int adif, i;
|
||||||
aac_header_t aacheader;
|
aac_header_t aacheader;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -77,12 +77,24 @@ aac_reader_c::aac_reader_c(track_info_t *nti) throw (error_c):
|
|||||||
throw error_c("aac_reader: No valid AAC packet found in the first "
|
throw error_c("aac_reader: No valid AAC packet found in the first "
|
||||||
SINITCHUNKSIZE " bytes.\n");
|
SINITCHUNKSIZE " bytes.\n");
|
||||||
guess_adts_version();
|
guess_adts_version();
|
||||||
mxprint(stdout, "emphasis_present: %s\n", emphasis_present ? "true" :
|
|
||||||
"false");
|
|
||||||
adif = 0;
|
adif = 0;
|
||||||
}
|
}
|
||||||
bytes_processed = 0;
|
bytes_processed = 0;
|
||||||
ti->id = 0; // ID for this track.
|
ti->id = 0; // ID for this track.
|
||||||
|
|
||||||
|
for (i = 0; i < ti->aac_is_sbr->size(); i++)
|
||||||
|
if ((*ti->aac_is_sbr)[i] == 0) {
|
||||||
|
aacheader.profile = AAC_PROFILE_SBR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (aacheader.profile != AAC_PROFILE_SBR)
|
||||||
|
mxprint(stdout,
|
||||||
|
"WARNING! AAC files may contain HE-AAC / AAC+ / SBR AAC audio. "
|
||||||
|
"This can NOT be detected automatically. Therefore you have to "
|
||||||
|
"specifiy '--aac-is-sbr 0' manually for this input file if the "
|
||||||
|
"file actually contains SBR AAC. The file will be muxed in the "
|
||||||
|
"WRONG way otherwise. Also read mkvmerge's documentation.\n");
|
||||||
|
|
||||||
aacpacketizer = new aac_packetizer_c(this, aacheader.id, aacheader.profile,
|
aacpacketizer = new aac_packetizer_c(this, aacheader.id, aacheader.profile,
|
||||||
aacheader.sample_rate,
|
aacheader.sample_rate,
|
||||||
aacheader.channels, ti,
|
aacheader.channels, ti,
|
||||||
|
@ -392,6 +392,8 @@ void kax_reader_c::verify_tracks() {
|
|||||||
!strcmp(t->codec_id, MKV_A_AAC_4LC) ||
|
!strcmp(t->codec_id, MKV_A_AAC_4LC) ||
|
||||||
!strcmp(t->codec_id, MKV_A_AAC_4SSR) ||
|
!strcmp(t->codec_id, MKV_A_AAC_4SSR) ||
|
||||||
!strcmp(t->codec_id, MKV_A_AAC_4LTP) ||
|
!strcmp(t->codec_id, MKV_A_AAC_4LTP) ||
|
||||||
|
!strcmp(t->codec_id, MKV_A_AAC_4SBR) ||
|
||||||
|
!strcmp(t->codec_id, MKV_A_AAC_2SBR) ||
|
||||||
!strcmp(t->codec_id, MKV_A_AAC_4SBR))
|
!strcmp(t->codec_id, MKV_A_AAC_4SBR))
|
||||||
t->a_formattag = FOURCC('M', 'P', '4', 'A');
|
t->a_formattag = FOURCC('M', 'P', '4', 'A');
|
||||||
else {
|
else {
|
||||||
@ -1179,7 +1181,7 @@ void kax_reader_c::create_packetizers() {
|
|||||||
} else if (t->a_formattag == FOURCC('M', 'P', '4', 'A')) {
|
} else if (t->a_formattag == FOURCC('M', 'P', '4', 'A')) {
|
||||||
// A_AAC/MPEG2/MAIN
|
// A_AAC/MPEG2/MAIN
|
||||||
// 0123456789012345
|
// 0123456789012345
|
||||||
int id, profile;
|
int id, profile, sbridx;
|
||||||
|
|
||||||
if (t->codec_id[10] == '2')
|
if (t->codec_id[10] == '2')
|
||||||
id = AAC_ID_MPEG2;
|
id = AAC_ID_MPEG2;
|
||||||
@ -1198,11 +1200,18 @@ void kax_reader_c::create_packetizers() {
|
|||||||
profile = AAC_PROFILE_SSR;
|
profile = AAC_PROFILE_SSR;
|
||||||
else if (!strcmp(&t->codec_id[12], "LTP"))
|
else if (!strcmp(&t->codec_id[12], "LTP"))
|
||||||
profile = AAC_PROFILE_LTP;
|
profile = AAC_PROFILE_LTP;
|
||||||
|
else if (!strcmp(&t->codec_id[12], "LC/SBR"))
|
||||||
|
profile = AAC_PROFILE_SBR;
|
||||||
else {
|
else {
|
||||||
mxprint(stderr, "Error: matroska_reader: Malformed codec id "
|
mxprint(stderr, "Error: matroska_reader: Malformed codec id "
|
||||||
"%s for track %d.\n", t->codec_id, t->tnum);
|
"%s for track %d.\n", t->codec_id, t->tnum);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
for (sbridx = 0; sbridx < ti->aac_is_sbr->size(); sbridx++)
|
||||||
|
if ((*ti->aac_is_sbr)[sbridx] == t->tnum) {
|
||||||
|
profile = AAC_PROFILE_SBR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
t->packetizer = new aac_packetizer_c(this, id, profile,
|
t->packetizer = new aac_packetizer_c(this, id, profile,
|
||||||
(unsigned long)t->a_sfreq,
|
(unsigned long)t->a_sfreq,
|
||||||
|
Loading…
Reference in New Issue
Block a user