Added support for TTA lossless audio files.

This commit is contained in:
Moritz Bunkus 2004-07-02 23:01:05 +00:00
parent b82fa8eb8f
commit c8d86da5a3
9 changed files with 395 additions and 2 deletions

View File

@ -1,3 +1,8 @@
2004-07-03 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: new feature: Added support for TTA lossless audio
files.
2004-06-29 Moritz Bunkus <moritz@bunkus.org>
* Released v0.9.2.

View File

@ -61,6 +61,7 @@ using namespace std;
#define TYPEREAL 14
#define TYPEQTMP4 15
#define TYPEFLAC 16
#define TYPETTA 17
#define FOURCC(a, b, c, d) (uint32_t)((((unsigned char)a) << 24) + \
(((unsigned char)b) << 16) + \

View File

@ -47,6 +47,7 @@
#define MKV_A_REAL_SIPR "A_REAL/SIPR"
#define MKV_A_REAL_ATRC "A_REAL/ATRC"
#define MKV_A_FLAC "A_FLAC"
#define MKV_A_TTA "A_TTA1"
#define MKV_V_MPEG4_SP "V_MPEG4/ISO/SP"
#define MKV_V_MPEG4_ASP "V_MPEG4/ISO/ASP"

View File

@ -75,6 +75,7 @@ extern "C" { // for BITMAPINFOHEADER
#include "p_passthrough.h"
#include "p_pcm.h"
#include "p_textsubs.h"
#include "p_tta.h"
#include "p_video.h"
#include "p_vobsub.h"
#include "p_vorbis.h"
@ -535,7 +536,8 @@ kax_reader_c::verify_tracks() {
"Ignoring track %u.\n", t->tnum);
continue;
#endif
}
} else if (!strcmp(t->codec_id, MKV_A_TTA))
t->a_formattag = FOURCC('T', 'T', 'A', '1');
}
if (t->a_sfreq == 0.0)
@ -1616,6 +1618,17 @@ kax_reader_c::create_packetizer(int64_t tid) {
(int64_t)t->tnum);
#endif
} else if (t->a_formattag == FOURCC('T', 'T', 'A', '1')) {
safefree(nti->private_data);
nti->private_data = NULL;
nti->private_size = 0;
t->ptzr =
add_packetizer(new tta_packetizer_c(this, t->a_channels,
t->a_bps, (int32_t)t->a_sfreq,
nti));
mxinfo(FMT_TID "Using the TTA output module.\n", ti->fname,
(int64_t)t->tnum);
} else
init_passthrough_packetizer(t);

157
src/input/r_tta.cpp Normal file
View File

@ -0,0 +1,157 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
r_tta.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 r_tta.cpp
\version $Id$
\brief TTA 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 "p_tta.h"
#include "r_tta.h"
int
tta_reader_c::probe_file(mm_io_c *mm_io,
int64_t size) {
unsigned char buf[4];
if (size < 26)
return 0;
try {
mm_io->setFilePointer(0, seek_beginning);
if (mm_io->read(buf, 4) != 4)
mm_io->setFilePointer(0, seek_beginning);
mm_io->setFilePointer(0, seek_beginning);
} catch (exception &ex) {
return 0;
}
if (!strncmp((char *)buf, "TTA1", 4))
return 1;
return 0;
}
tta_reader_c::tta_reader_c(track_info_c *nti)
throw (error_c):
generic_reader_c(nti) {
uint32_t seek_point;
int64_t seek_sum;
try {
mm_io = new mm_io_c(ti->fname, MODE_READ);
size = mm_io->get_size();
mm_io->setFilePointer(6, seek_beginning);
if (identifying)
return;
channels = mm_io->read_uint16();
bits_per_sample = mm_io->read_uint16();
sample_rate = mm_io->read_uint32();
data_length = mm_io->read_uint32();
mm_io->skip(4);
seek_sum = mm_io->getFilePointer() + 4;
do {
seek_point = mm_io->read_uint32();
seek_sum += seek_point + 4;
seek_points.push_back(seek_point);
} while (seek_sum < size);
if (seek_sum != size)
mxerror(FMT_FN "The seek table in this TTA file seems to be broken.\n",
ti->fname);
mm_io->skip(4);
mxverb(2, "tta: ch %u bps %u sr %u dl %u seek_sum %lld size %lld num %u\n",
channels, bits_per_sample, sample_rate, data_length, seek_sum, size,
seek_points.size());
bytes_processed = 0;
pos = 0;
ti->id = 0; // ID for this track.
} catch (exception &ex) {
throw error_c("tta_reader: Could not open the file.");
}
if (verbose)
mxinfo(FMT_FN "Using the TTA demultiplexer.\n", ti->fname);
}
tta_reader_c::~tta_reader_c() {
delete mm_io;
}
void
tta_reader_c::create_packetizer(int64_t) {
generic_packetizer_c *ttapacketizer;
if (NPTZR() != 0)
return;
ttapacketizer = new tta_packetizer_c(this, channels, bits_per_sample,
sample_rate, ti);
add_packetizer(ttapacketizer);
mxinfo(FMT_TID "Using the TTA output module.\n", ti->fname, (int64_t)0);
}
int
tta_reader_c::read(generic_packetizer_c *) {
unsigned char *buf;
int nread;
if (pos >= seek_points.size())
return 0;
buf = (unsigned char *)safemalloc(seek_points[pos]);
nread = mm_io->read(buf, seek_points[pos]);
if (nread <= 0) {
PTZR0->flush();
return 0;
}
memory_c mem(buf, nread, true);
PTZR0->process(mem);
bytes_processed += nread;
pos++;
return EMOREDATA;
}
int
tta_reader_c::display_priority() {
return DISPLAYPRIORITY_HIGH - 1;
}
void
tta_reader_c::display_progress(bool final) {
if (final)
mxinfo("progress: %lld/%lld bytes (100%%)\r", size, size);
else
mxinfo("progress: %lld/%lld bytes (%d%%)\r", bytes_processed, size,
(int)(bytes_processed * 100L / size));
}
void
tta_reader_c::identify() {
mxinfo("File '%s': container: TTA\nTrack ID 0: audio (TTA)\n", ti->fname);
}

56
src/input/r_tta.h Normal file
View File

@ -0,0 +1,56 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
r_avi.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 r_tta.h
\version $Id$
\brief class definitions for the TTA demultiplexer module
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef __R_TTA_H
#define __R_TTA_H
#include "os.h"
#include <stdio.h>
#include "common.h"
#include "error.h"
#include "mm_io.h"
#include "pr_generic.h"
class tta_reader_c: public generic_reader_c {
private:
unsigned char *chunk;
mm_io_c *mm_io;
int64_t bytes_processed, size;
uint16_t channels, bits_per_sample;
uint32_t sample_rate, data_length;
vector<uint32_t> seek_points;
int pos;
public:
tta_reader_c(track_info_c *nti) throw (error_c);
virtual ~tta_reader_c();
virtual int read(generic_packetizer_c *ptzr);
virtual int display_priority();
virtual void display_progress(bool final = false);
virtual void identify();
virtual void create_packetizer(int64_t id);
static int probe_file(mm_io_c *mm_io, int64_t size);
};
#endif // __R_TTA_H

View File

@ -89,6 +89,7 @@
#include "r_real.h"
#include "r_srt.h"
#include "r_ssa.h"
#include "r_tta.h"
#include "r_vobsub.h"
#include "r_wav.h"
#include "tagparser.h"
@ -218,8 +219,9 @@ file_type_t file_types[] =
{"idx ", TYPEVOBSUB, "VobSub subtitles"},
{"wav ", TYPEWAV, "WAVE (uncompressed PCM)"},
#if defined(HAVE_FLAC_FORMAT_H)
{"flac", TYPEFLAC, "FLAC lossless audio (slow!)"},
{"flac", TYPEFLAC, "FLAC lossless audio"},
#endif
{"tta", TYPETTA, "TTA lossless audio"},
{"output modules:", -1, ""},
{" ", -1, "AAC audio"},
{" ", -1, "AC3 audio"},
@ -414,6 +416,8 @@ get_type(char *filename) {
type = TYPEREAL;
else if (qtmp4_reader_c::probe_file(mm_io, size))
type = TYPEQTMP4;
else if (tta_reader_c::probe_file(mm_io, size))
type = TYPETTA;
else if (mp3_reader_c::probe_file(mm_io, size))
type = TYPEMP3;
else if (ac3_reader_c::probe_file(mm_io, size))
@ -1417,6 +1421,9 @@ create_readers() {
file->reader = new flac_reader_c(file->ti);
break;
#endif
case TYPETTA:
file->reader = new tta_reader_c(file->ti);
break;
default:
mxerror("EVIL internal bug! (unknown file type)\n");
break;

100
src/output/p_tta.cpp Normal file
View File

@ -0,0 +1,100 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_tta.cpp
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: p_tta.cpp 1657 2004-04-09 17:37:25Z mosu $
\brief TTA output 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 "pr_generic.h"
#include "p_tta.h"
#include "matroska.h"
using namespace libmatroska;
static const double tta_frame_time = 1.04489795918367346939l;
tta_packetizer_c::tta_packetizer_c(generic_reader_c *nreader,
int nchannels,
int nbits_per_sample,
int nsample_rate,
track_info_c *nti)
throw (error_c):
generic_packetizer_c(nreader, nti) {
sample_rate = nsample_rate;
channels = nchannels;
bits_per_sample = nbits_per_sample;
samples_output = 0;
set_track_type(track_audio);
set_track_default_duration((int64_t)(1000000000.0 * ti->async.linear *
tta_frame_time));
}
tta_packetizer_c::~tta_packetizer_c() {
}
void
tta_packetizer_c::set_headers() {
set_codec_id(MKV_A_TTA);
set_audio_sampling_freq((float)sample_rate);
set_audio_channels(channels);
set_audio_bit_depth(bits_per_sample);
generic_packetizer_c::set_headers();
}
int
tta_packetizer_c::process(memory_c &mem,
int64_t,
int64_t,
int64_t,
int64_t) {
debug_enter("tta_packetizer_c::process");
add_packet(mem, samples_output * 1000000000 / sample_rate,
(int64_t)(1000000000.0 * ti->async.linear * tta_frame_time));
samples_output += (int64_t)(tta_frame_time * sample_rate);
debug_leave("tta_packetizer_c::process");
return EMOREDATA;
}
void
tta_packetizer_c::dump_debug_info() {
mxdebug("tta_packetizer_c: queue: %d\n", packet_queue.size());
}
int
tta_packetizer_c::can_connect_to(generic_packetizer_c *src) {
tta_packetizer_c *psrc;
psrc = dynamic_cast<tta_packetizer_c *>(src);
if (psrc == NULL)
return CAN_CONNECT_NO_FORMAT;
if ((sample_rate != psrc->sample_rate) ||
(channels != psrc->channels) ||
(bits_per_sample != psrc->bits_per_sample))
return CAN_CONNECT_NO_PARAMETERS;
return CAN_CONNECT_YES;
}

53
src/output/p_tta.h Normal file
View File

@ -0,0 +1,53 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_tta.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 p_tta.h
\version $Id$
\brief class definition for the TTA output module
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef __P_TTA_H
#define __P_TTA_H
#include "os.h"
#include "common.h"
#include "pr_generic.h"
class tta_packetizer_c: public generic_packetizer_c {
private:
int channels, bits_per_sample, sample_rate;
int64_t samples_output;
public:
tta_packetizer_c(generic_reader_c *nreader, int nchannels,
int nbits_per_sample, int nsample_rate, track_info_c *nti)
throw (error_c);
virtual ~tta_packetizer_c();
virtual int process(memory_c &mem, int64_t timecode = -1,
int64_t length = -1, int64_t bref = -1,
int64_t fref = -1);
virtual void set_headers();
virtual void dump_debug_info();
virtual const char *get_format_name() {
return "TTA";
}
virtual int can_connect_to(generic_packetizer_c *src);
};
#endif // __P_TTA_H