mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 12:27:21 +00:00
169 lines
4.5 KiB
C++
169 lines
4.5 KiB
C++
/*
|
|
mkvmerge -- utility for splicing together matroska files
|
|
from component media subtypes
|
|
|
|
r_aac.h
|
|
|
|
Written by Moritz Bunkus <moritz@bunkus.org>
|
|
|
|
Distributed under the GPL
|
|
see the file COPYING for details
|
|
or visit http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
/*!
|
|
\file
|
|
\version $Id$
|
|
\brief AAC demultiplexer module
|
|
\author Moritz Bunkus <moritz@bunkus.org>
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "mkvmerge.h"
|
|
#include "common.h"
|
|
#include "error.h"
|
|
#include "r_aac.h"
|
|
#include "p_aac.h"
|
|
|
|
int aac_reader_c::probe_file(mm_io_c *mm_io, int64_t size) {
|
|
char buf[4096];
|
|
aac_header_t aacheader;
|
|
|
|
if (size < 4096)
|
|
return 0;
|
|
try {
|
|
mm_io->setFilePointer(0, seek_beginning);
|
|
if (mm_io->read(buf, 4096) != 4096)
|
|
mm_io->setFilePointer(0, seek_beginning);
|
|
mm_io->setFilePointer(0, seek_beginning);
|
|
} catch (exception &ex) {
|
|
return 0;
|
|
}
|
|
if (parse_aac_adif_header((unsigned char *)buf, 4096, &aacheader))
|
|
return 1;
|
|
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;
|
|
aac_header_t aacheader;
|
|
|
|
try {
|
|
mm_io = new mm_io_c(ti->fname, MODE_READ);
|
|
mm_io->setFilePointer(0, seek_end);
|
|
size = mm_io->getFilePointer();
|
|
mm_io->setFilePointer(0, seek_beginning);
|
|
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, INITCHUNKSIZE, &aacheader)) {
|
|
throw error_c("aac_reader: ADIF header files are not supported.");
|
|
adif = 1;
|
|
} 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,
|
|
emphasis_present);
|
|
} catch (exception &ex) {
|
|
throw error_c("aac_reader: Could not open the file.");
|
|
}
|
|
if (verbose)
|
|
fprintf(stdout, "Using AAC demultiplexer for %s.\n+-> Using "
|
|
"AAC output module for audio stream.\n", ti->fname);
|
|
}
|
|
|
|
aac_reader_c::~aac_reader_c() {
|
|
delete mm_io;
|
|
if (chunk != NULL)
|
|
safefree(chunk);
|
|
if (aacpacketizer != NULL)
|
|
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;
|
|
|
|
nread = mm_io->read(chunk, 4096);
|
|
if (nread <= 0)
|
|
return 0;
|
|
|
|
aacpacketizer->process(chunk, nread);
|
|
bytes_processed += nread;
|
|
|
|
return EMOREDATA;
|
|
}
|
|
|
|
packet_t *aac_reader_c::get_packet() {
|
|
return aacpacketizer->get_packet();
|
|
}
|
|
|
|
int aac_reader_c::display_priority() {
|
|
return DISPLAYPRIORITY_HIGH - 1;
|
|
}
|
|
|
|
void aac_reader_c::display_progress() {
|
|
fprintf(stdout, "progress: %lld/%lld bytes (%d%%)\r",
|
|
bytes_processed, size,
|
|
(int)(bytes_processed * 100L / size));
|
|
fflush(stdout);
|
|
}
|
|
|
|
void aac_reader_c::set_headers() {
|
|
aacpacketizer->set_headers();
|
|
}
|
|
|
|
void aac_reader_c::identify() {
|
|
fprintf(stdout, "File '%s': container: AAC\nTrack ID 0: audio (AAC)\n",
|
|
ti->fname);
|
|
}
|