1
// ------------------------------------------------------------------------
2
// audioio-faad.cpp: Interface class for FAAC/FAAD AAC encoder/decoder.
3
// Copyright (C) 2004-2005 Kai Vehmanen
6
// eca-style-version: 3
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License as published by
10
// the Free Software Foundation; either version 2 of the License, or
11
// (at your option) any later version.
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
// GNU General Public License for more details.
18
// You should have received a copy of the GNU General Public License
19
// along with this program; if not, write to the Free Software
20
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
// ------------------------------------------------------------------------
24
#include <cstdlib> /* atol() */
25
#include <unistd.h> /* stat() */
26
#include <sys/stat.h> /* stat() */
28
#include <kvu_message_item.h>
29
#include <kvu_numtostr.h>
31
#include "audioio-aac.h"
33
#include "eca-logger.h"
37
* http://www.audiocoding.com/
40
string AAC_FORKED_INTERFACE::default_input_cmd = "faad -w -b 1 -f 2 -d %f";
41
string AAC_FORKED_INTERFACE::default_output_cmd = "faac -P -o %f -R %s -B %b -C %c -";
43
void AAC_FORKED_INTERFACE::set_input_cmd(const std::string& value) { AAC_FORKED_INTERFACE::default_input_cmd = value; }
44
void AAC_FORKED_INTERFACE::set_output_cmd(const std::string& value) { AAC_FORKED_INTERFACE::default_output_cmd = value; }
46
AAC_FORKED_INTERFACE::AAC_FORKED_INTERFACE(const std::string& name)
52
AAC_FORKED_INTERFACE::~AAC_FORKED_INTERFACE(void)
54
if (is_open() == true) {
59
void AAC_FORKED_INTERFACE::open(void) throw (AUDIO_IO::SETUP_ERROR &)
61
std::string urlprefix;
62
triggered_rep = false;
65
* FIXME: we have no idea about the audio format of the
66
* stream we get from ogg123... maybe we should force decoder
67
* to generate RIFF wave to a named pipe and parse the header...?
70
if (io_mode() == io_read) {
72
int ret = ::stat(label().c_str(), &buf);
74
size_t offset = label().find_first_of("://");
75
if (offset == std::string::npos) {
76
throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIOIO-AAC: Can't open file " + label() + "."));
79
urlprefix = std::string(label(), 0, offset);
80
ECA_LOG_MSG(ECA_LOGGER::user_objects, "(audioio-aac) Found url; protocol '" + urlprefix + "'.");
84
/* decoder supports: fixed channel count and sample format,
85
sample rate unknown and must be set manually */
86
set_channels(2); /* 5.1 downmixed to stereo if needed by faad2 */
87
set_sample_format(ECA_AUDIO_FORMAT::sfmt_s16_be);
90
/* encoder supports: coding, channel-count and srate configurable;
92
set_sample_endianess(ECA_AUDIO_FORMAT::se_big);
98
void AAC_FORKED_INTERFACE::close(void)
100
if (pid_of_child() > 0) {
101
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Cleaning child process." + kvu_numtostr(pid_of_child()) + ".");
103
triggered_rep = false;
109
long int AAC_FORKED_INTERFACE::read_samples(void* target_buffer, long int samples)
111
if (triggered_rep != true) {
112
triggered_rep = true;
113
fork_input_process();
117
bytes_rep = std::fread(target_buffer, 1, frame_size() * samples, f1_rep);
123
if (bytes_rep < samples * frame_size() || bytes_rep == 0) {
124
if (position_in_samples() == 0)
125
ECA_LOG_MSG(ECA_LOGGER::info, "(audioio-aac) Can't start process \"" + AAC_FORKED_INTERFACE::default_input_cmd + "\". Please check your ~/.ecasound/ecasoundrc.");
127
triggered_rep = false;
130
finished_rep = false;
132
return bytes_rep / frame_size();
135
void AAC_FORKED_INTERFACE::write_samples(void* target_buffer, long int samples)
137
if (triggered_rep != true) {
138
triggered_rep = true;
139
fork_output_process();
142
if (wait_for_child() != true) {
144
triggered_rep = false;
147
if (filedes_rep > 0) {
148
bytes_rep = ::write(filedes_rep, target_buffer, frame_size() * samples);
153
if (bytes_rep < frame_size() * samples || bytes_rep == 0) {
154
ECA_LOG_MSG(ECA_LOGGER::info, "(audioio-aac) Can't start process \"" + AAC_FORKED_INTERFACE::default_output_cmd + "\". FAAC v1.24 or newer is required. Please check your ~/.ecasound/ecasoundrc.");
156
triggered_rep = false;
158
else finished_rep = false;
162
void AAC_FORKED_INTERFACE::seek_position(void)
164
if (pid_of_child() > 0) {
165
ECA_LOG_MSG(ECA_LOGGER::user_objects, "(audioio-aac) Cleaning child process." + kvu_numtostr(pid_of_child()) + ".");
167
triggered_rep = false;
169
set_position_in_samples(0);
172
void AAC_FORKED_INTERFACE::set_parameter(int param, string value)
181
string AAC_FORKED_INTERFACE::get_parameter(int param) const
190
void AAC_FORKED_INTERFACE::fork_input_process(void)
192
ECA_LOG_MSG(ECA_LOGGER::user_objects, AAC_FORKED_INTERFACE::default_input_cmd);
194
set_fork_command(AAC_FORKED_INTERFACE::default_input_cmd);
195
set_fork_file_name(label());
197
fork_child_for_read();
198
if (child_fork_succeeded() == true) {
199
/* NOTE: the file description will be closed by
200
* AUDIO_IO_FORKED_STREAM::clean_child() */
201
filedes_rep = file_descriptor();
202
f1_rep = fdopen(filedes_rep, "r"); /* not part of <cstdio> */
205
triggered_rep = false;
212
void AAC_FORKED_INTERFACE::fork_output_process(void)
214
string command = AAC_FORKED_INTERFACE::default_output_cmd;
216
set_fork_command(command);
217
set_fork_file_name(label());
219
set_fork_bits(bits());
220
set_fork_channels(channels());
221
set_fork_sample_rate(samples_per_second());
223
fork_child_for_write();
224
if (child_fork_succeeded() == true) {
225
filedes_rep = file_descriptor();