mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 20:01:53 +00:00
Added support for TTA lossless audio files.
This commit is contained in:
parent
b82fa8eb8f
commit
c8d86da5a3
@ -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.
|
||||
|
@ -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) + \
|
||||
|
@ -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"
|
||||
|
@ -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
157
src/input/r_tta.cpp
Normal 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
56
src/input/r_tta.h
Normal 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
|
@ -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
100
src/output/p_tta.cpp
Normal 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
53
src/output/p_tta.h
Normal 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
|
Loading…
Reference in New Issue
Block a user