aboutsummaryrefslogtreecommitdiffstats
path: root/src/odr-audioenc.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2017-10-07 11:47:05 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2017-10-07 11:51:46 +0200
commit84febca8b268129cdd79ff0d1c4f8eeed092c5fb (patch)
tree3e75880241e0fcd2951c04aad77d7077b4ec130c /src/odr-audioenc.cpp
parent9c2615425bb4f35a417eb04b1ceebfc77d8e2c8b (diff)
downloadODR-AudioEnc-84febca8b268129cdd79ff0d1c4f8eeed092c5fb.tar.gz
ODR-AudioEnc-84febca8b268129cdd79ff0d1c4f8eeed092c5fb.tar.bz2
ODR-AudioEnc-84febca8b268129cdd79ff0d1c4f8eeed092c5fb.zip
Use queue for all inputs and unify interface
This also changes the --fifo-silence option. Instead of inserting silence separately, it uses the drift compensation to do that.
Diffstat (limited to 'src/odr-audioenc.cpp')
-rw-r--r--src/odr-audioenc.cpp128
1 files changed, 46 insertions, 82 deletions
diff --git a/src/odr-audioenc.cpp b/src/odr-audioenc.cpp
index 11978a9..098d700 100644
--- a/src/odr-audioenc.cpp
+++ b/src/odr-audioenc.cpp
@@ -299,12 +299,12 @@ static int prepare_aac_encoder(
return 1;
}
}
- if (aacEncEncode(*encoder, NULL, NULL, NULL, NULL) != AACENC_OK) {
+ if (aacEncEncode(*encoder, nullptr, nullptr, nullptr, nullptr) != AACENC_OK) {
fprintf(stderr, "Unable to initialize the encoder\n");
return 1;
}
- uint32_t bw = aacEncoder_GetParam(*encoder, AACENC_BANDWIDTH);
+ const uint32_t bw = aacEncoder_GetParam(*encoder, AACENC_BANDWIDTH);
fprintf(stderr, "Bandwidth is %d\n", bw);
return 0;
@@ -395,6 +395,7 @@ int main(int argc, char *argv[])
// For the file input
string infile;
+ bool continue_after_eof = false;
int raw_input = 0;
// For the VLC input
@@ -407,17 +408,16 @@ int main(int argc, char *argv[])
unsigned verbosity = 0;
// For the file output
- FILE *out_fh = NULL;
+ FILE *out_fh = nullptr;
string jack_name;
vector<string> output_uris;
int sample_rate=48000, channels=2;
- void *rs_handler = NULL;
+ void *rs_handler = nullptr;
bool afterburner = true;
uint32_t bandwidth = 0;
- bool inFifoSilence = false;
bool drift_compensation = false;
AACENC_InfoStruct info = { 0 };
int aot = AOT_NONE;
@@ -449,7 +449,7 @@ int main(int argc, char *argv[])
int show_level = 0;
/* Data for ZMQ CURVE authentication */
- char* keyfile = NULL;
+ char* keyfile = nullptr;
char secretkey[CURVE_KEYLEN+1];
const struct option longopts[] = {
@@ -519,7 +519,11 @@ int main(int argc, char *argv[])
case 2: // PS
aot = AOT_DABPLUS_PS;
break;
- case 3: // FIFO SILENCE
+ case 3: // FIFO Silence
+ continue_after_eof = true;
+ // Enable drift compensation, otherwise we would block instead of inserting silence.
+ drift_compensation = true;
+ break;
case 4: // DAB channel mode
dab_channel_mode = optarg;
if (not( dab_channel_mode == "s" or
@@ -694,7 +698,7 @@ int main(int argc, char *argv[])
if (not output_uris.empty()) {
for (auto uri : output_uris) {
if (uri == "-") {
- if (out_fh != NULL) {
+ if (out_fh != nullptr) {
fprintf(stderr, "You can't write to more than one file!\n");
return 1;
}
@@ -722,7 +726,7 @@ int main(int argc, char *argv[])
zmq_sock.connect(uri.c_str());
}
else { // We assume it's a file name
- if (out_fh != NULL) {
+ if (out_fh != nullptr) {
fprintf(stderr, "You can't write to more than one file!\n");
return 1;
}
@@ -860,7 +864,7 @@ int main(int argc, char *argv[])
/* symsize=8, gfpoly=0x11d, fcr=0, prim=1, nroots=10, pad=135 */
rs_handler = init_rs_char(8, 0x11d, 0, 1, 10, 135);
- if (rs_handler == NULL) {
+ if (rs_handler == nullptr) {
perror("init_rs_char failed");
return 1;
}
@@ -868,9 +872,9 @@ int main(int argc, char *argv[])
// We'll use one of the tree possible inputs
#if HAVE_ALSA
AlsaInputThreaded alsa_in_threaded(alsa_device, channels, sample_rate, queue);
- AlsaInputDirect alsa_in_direct(alsa_device, channels, sample_rate);
+ AlsaInputDirect alsa_in_direct(alsa_device, channels, sample_rate, queue);
#endif
- FileInput file_in(infile, raw_input, sample_rate);
+ FileInput file_in(infile, raw_input, sample_rate, continue_after_eof, queue);
#if HAVE_JACK
JackInput jack_in(jack_name, channels, sample_rate, queue);
#endif
@@ -992,8 +996,8 @@ int main(int argc, char *argv[])
* without drift compensation) or in a non-blocking way (VLC or ALSA
* with drift compensation, JACK).
*
- * The file input doesn't need the queue at all. But the other inputs
- * do, and either use \c pop() or \c pop_wait() depending on if it's blocking or not
+ * All inputs write samples into the queue, and either use \c pop() or
+ * \c pop_wait() depending on if it's blocking or not
*
* In non-blocking, the \c queue makes the data available without delay, and the
* \c drift_compensation_delay() function handles rate throttling.
@@ -1005,68 +1009,14 @@ int main(int argc, char *argv[])
break;
}
- if (not infile.empty()) {
- read_bytes = file_in.read(&input_buf[0], input_buf.size());
- if (read_bytes < 0) {
- break;
- }
- else if (read_bytes != input_buf.size()) {
- if (inFifoSilence && file_in.eof()) {
- memset(&input_buf[0], 0, input_buf.size());
- read_bytes = input_buf.size();
- usleep((long)input_buf.size() * 1000000 /
- (BYTES_PER_SAMPLE * channels * sample_rate));
- }
- else {
- fprintf(stderr, "Short file read !\n");
- read_bytes = 0;
- }
- }
+ if (not input->read_source(input_buf.size())) {
+ fprintf(stderr, "End of input reached\n");
+ retval = 0;
+ break;
}
-#if HAVE_VLC
- else if (not vlc_uri.empty()) {
-
- if (drift_compensation) {
- size_t overruns;
- size_t bytes_from_queue = queue.pop(&input_buf[0], input_buf.size(), &overruns); // returns bytes
- if (bytes_from_queue != input_buf.size()) {
- expand_missing_samples(input_buf, channels, bytes_from_queue);
- }
- read_bytes = input_buf.size();
- drift_compensation_delay(sample_rate, channels, read_bytes);
-
- if (bytes_from_queue != input_buf.size()) {
- status |= STATUS_UNDERRUN;
- }
-
- if (overruns) {
- status |= STATUS_OVERRUN;
- }
- }
- else {
- const int timeout_ms = 10000;
- read_bytes = input_buf.size();
-
- /*! pop_wait() must return after a timeout, otherwise the silence detector cannot do
- * its job.
- */
- size_t bytes_from_queue = queue.pop_wait(&input_buf[0], read_bytes, timeout_ms); // returns bytes
- if (bytes_from_queue < read_bytes) {
- // queue timeout occurred
- fprintf(stderr, "Detected fault in VLC input! No data in time.\n");
- retval = 5;
- break;
- }
- }
-
- if (not vlc_icytext_file.empty()) {
- vlc_input.write_icy_text(vlc_icytext_file, vlc_icytext_dlplus);
- }
- }
-#endif
- else if (drift_compensation or not jack_name.empty()) {
- size_t overruns;
+ if (drift_compensation) {
+ size_t overruns = 0;
size_t bytes_from_queue = queue.pop(&input_buf[0], input_buf.size(), &overruns); // returns bytes
if (bytes_from_queue != input_buf.size()) {
expand_missing_samples(input_buf, channels, bytes_from_queue);
@@ -1083,17 +1033,31 @@ int main(int argc, char *argv[])
}
}
else {
-#if HAVE_ALSA
- read_bytes = alsa_in_direct.read(&input_buf[0], input_buf.size());
- if (read_bytes < 0) {
+ const int timeout_ms = 10000;
+ read_bytes = input_buf.size();
+
+ /*! pop_wait() must return after a timeout, otherwise the silence detector cannot do
+ * its job. */
+ size_t bytes_from_queue = queue.pop_wait(&input_buf[0], read_bytes, timeout_ms); // returns bytes
+
+ if (bytes_from_queue < read_bytes) {
+ // queue timeout occurred
+ fprintf(stderr, "Detected fault in VLC input! No data in time.\n");
+ retval = 5;
break;
}
- else if (read_bytes != input_buf.size()) {
- fprintf(stderr, "Short alsa read !\n");
- }
-#endif
}
+ /*! \section MetadataFromSource
+ * The VLC input is the only input that can also give us metadata, which
+ * we can hand over to ODR-PadEnc.
+ */
+#if HAVE_VLC
+ if (not vlc_uri.empty() and not vlc_icytext_file.empty()) {
+ vlc_input.write_icy_text(vlc_icytext_file, vlc_icytext_dlplus);
+ }
+#endif
+
/*! \section AudioLevel
* Audio level measurement is always done assuming we have two
* channels, and is formally wrong in mono, but still gives
@@ -1113,7 +1077,7 @@ int main(int argc, char *argv[])
* only useful if the connection dropped, or if no data is available. It is not
* useful if the source is nearly silent (some noise present), because the
* threshold is 0, and not configurable. The rationale is that we want to
- * guard against connection issues, not source level issues
+ * guard against connection issues, not source level issues.
*/
if (die_on_silence && MAX(peak_left, peak_right) == 0) {
const unsigned int frame_time_msec = 1000ul *