aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Pöschel <github@basicmaster.de>2017-08-24 13:37:42 +0200
committerStefan Pöschel <github@basicmaster.de>2017-08-24 13:37:42 +0200
commit9f62da63eb7577d30dc67fc2823201b4f2598ffa (patch)
tree85e123da8382690ae9df283835d81d7aa65f465d
parentb709a05a1873cfdff864866d71733ca8290e7f0a (diff)
downloadODR-PadEnc-9f62da63eb7577d30dc67fc2823201b4f2598ffa.tar.gz
ODR-PadEnc-9f62da63eb7577d30dc67fc2823201b4f2598ffa.tar.bz2
ODR-PadEnc-9f62da63eb7577d30dc67fc2823201b4f2598ffa.zip
Add uniform PAD encoder
The uniform PAD encoder encodes every PAD on demand and is kind of synchronized to the audio encoder by means of the frame duration. Insertion intervals for slides and labels can be set indepentent from each other. It is also possible to specify how often the label is inserted. If the slides interval "0" is used, the next slide is inserted just after the previous one has been transmitted. This is useful e.g. for stations that transmit just a logo slide. An initial burst count can be set to ensure that an audio encoder has enough PADs available e.g. in case the audio encoder encodes DAB+ Superframes at once and hence needs all related PADs. If a slide/label is still in transmission when the transmission of the next one is scheduled, the new transmission is skipped and a warning is shown. In this case it makes sense to increase the PAD length or to instead decrease the slide size or label insertion interval (`-L`). This new PAD encoder does not require any changes on the audio encoder side. Only in case of MP2, a recent revision of ODR-AudioEnc has to be used (commit ce25f2c or later), as it fixes a problem with PADs that solely consist of the F-PAD.
-rw-r--r--src/odr-padenc.cpp117
-rw-r--r--src/odr-padenc.h22
2 files changed, 133 insertions, 6 deletions
diff --git a/src/odr-padenc.cpp b/src/odr-padenc.cpp
index b656c02..319a037 100644
--- a/src/odr-padenc.cpp
+++ b/src/odr-padenc.cpp
@@ -64,7 +64,7 @@ static void usage(const char* name) {
" -o, --output=FILENAME FIFO to write PAD data into.\n"
" Default: %s\n"
" -t, --dls=FILENAME FIFO or file to read DLS text from.\n"
- " If specified more than once, use next file after slide switch.\n"
+ " If specified more than once, use next file after slide switch (for uniform PAD encoder, -l is used instead).\n"
" -p, --pad=LENGTH Set the PAD length.\n"
" Possible values: %s\n"
" Default: %zu\n"
@@ -79,11 +79,23 @@ static void usage(const char* name) {
" -R, --raw-slides Do not process slides. Integrity checks and resizing\n"
" slides is skipped. Use this if you know what you are doing !\n"
" It is useful only when -d is used\n"
- " -v, --verbose Print more information to the console\n",
+ " -v, --verbose Print more information to the console\n"
+ "\n"
+ "Parameters for uniform PAD encoder only:\n"
+ " -f, --frame-dur=DUR Enable the uniform PAD encoder and set the duration of one frame/AU in milliseconds.\n"
+ " -l, --label=DUR Wait DUR seconds between each label (if more than one file used)\n"
+ " Default: %d\n"
+ " -L, --label-ins=DUR Insert label every DUR milliseconds\n"
+ " Default: %d\n"
+ " -i, --init-burst=COUNT Sets a PAD burst amount to initially fill the output FIFO\n"
+ " Default: %d\n",
options_default.slide_interval,
options_default.output,
PADPacketizer::ALLOWED_PADLEN.c_str(),
- options_default.padlen
+ options_default.padlen,
+ options_default.label_interval,
+ options_default.label_insertion,
+ options_default.init_burst
);
}
@@ -117,12 +129,16 @@ int main(int argc, char *argv[]) {
{"sleep", required_argument, 0, 's'},
{"raw-slides", no_argument, 0, 'R'},
{"help", no_argument, 0, 'h'},
+ {"frame-dur", required_argument, 0, 'f'},
+ {"label", required_argument, 0, 'l'},
+ {"label-ins", required_argument, 0, 'L'},
+ {"init-burst", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{0,0,0,0},
};
int ch;
- while((ch = getopt_long(argc, argv, "eChRrc:d:o:p:s:t:v", longopts, NULL)) != -1) {
+ while((ch = getopt_long(argc, argv, "eChRrc:d:o:p:s:t:f:l:L:i:v", longopts, NULL)) != -1) {
switch (ch) {
case 'c':
options.dl_params.charset = (DABCharset) atoi(optarg);
@@ -154,6 +170,18 @@ int main(int argc, char *argv[]) {
case 'R':
options.raw_slides = true;
break;
+ case 'f':
+ options.frame_dur = atoi(optarg);
+ break;
+ case 'l':
+ options.label_interval = atoi(optarg);
+ break;
+ case 'L':
+ options.label_insertion = atoi(optarg);
+ break;
+ case 'i':
+ options.init_burst = atoi(optarg);
+ break;
case 'v':
verbose++;
break;
@@ -231,8 +259,18 @@ int main(int argc, char *argv[]) {
}
}
- // invoke encoder
- pad_encoder = new BurstPadEncoder(options);
+
+ // TODO: check uniform PAD encoder options!?
+
+
+ // invoke selected encoder
+ if (options.frame_dur) {
+ fprintf(stderr, "ODR-PadEnc using uniform PAD encoder\n");
+ pad_encoder = new UniformPadEncoder(options);
+ } else {
+ fprintf(stderr, "ODR-PadEnc using burst PAD encoder\n");
+ pad_encoder = new BurstPadEncoder(options);
+ }
int result = pad_encoder->Main();
delete pad_encoder;
@@ -391,3 +429,70 @@ int BurstPadEncoder::Encode() {
return 0;
}
+
+
+// --- UniformPadEncoder -----------------------------------------------------------------
+UniformPadEncoder::UniformPadEncoder(PadEncoderOptions options) : PadEncoder(options) {
+ // PAD related timelines
+ pad_timeline = steady_clock::now();
+ next_slide = pad_timeline;
+ next_label = pad_timeline;
+ next_label_insertion = pad_timeline;
+
+ // consider initial burst
+ run_timeline -= std::chrono::milliseconds(options.init_burst * options.frame_dur);
+
+ // if multiple DLS files, ensure that initial increment leads to first one
+ if (options.dls_files.size() > 1)
+ curr_dls_file = -1;
+}
+
+int UniformPadEncoder::Encode() {
+ int result = 0;
+
+ // handle SLS
+ if (options.SLSEnabled()) {
+ if (options.slide_interval > 0) {
+ // encode slides regularly
+ if (pad_timeline >= next_slide) {
+ result = EncodeSlide(true);
+ next_slide += std::chrono::seconds(options.slide_interval);
+ }
+ } else {
+ // encode slide as soon as previous slide has been transmitted
+ if (!pad_packetizer.QueueContainsDG(SLSEncoder::APPTYPE_MOT_START))
+ result = EncodeSlide(true);
+ }
+ }
+ if (result)
+ return result;
+
+ // handle DLS
+ if (options.DLSEnabled()) {
+ if (options.dls_files.size() > 1 && pad_timeline >= next_label) {
+ // switch to next DLS file
+ curr_dls_file = (curr_dls_file + 1) % options.dls_files.size();
+ next_label += std::chrono::seconds(options.label_interval);
+
+ // enforce label insertion
+ next_label_insertion = pad_timeline;
+ }
+
+ if (pad_timeline >= next_label_insertion) {
+ // encode label
+ result = EncodeLabel(true);
+ next_label_insertion += std::chrono::milliseconds(options.label_insertion);
+ }
+ }
+ if (result)
+ return result;
+
+ // flush one PAD
+ pad_packetizer.WriteAllPADs(output_fd, 1, true);
+ pad_timeline += std::chrono::milliseconds(options.frame_dur);
+
+ // schedule next run at next frame/AU
+ run_timeline += std::chrono::milliseconds(options.frame_dur);
+
+ return 0;
+}
diff --git a/src/odr-padenc.h b/src/odr-padenc.h
index 7bdb057..fe5d375 100644
--- a/src/odr-padenc.h
+++ b/src/odr-padenc.h
@@ -51,6 +51,10 @@ struct PadEncoderOptions {
size_t padlen;
bool erase_after_tx;
int slide_interval;
+ int frame_dur; // uniform PAD encoder only
+ int label_interval; // uniform PAD encoder only
+ int label_insertion; // uniform PAD encoder only
+ int init_burst; // uniform PAD encoder only
bool raw_slides;
DL_PARAMS dl_params;
@@ -62,6 +66,10 @@ struct PadEncoderOptions {
padlen(58),
erase_after_tx(false),
slide_interval(10),
+ frame_dur(0),
+ label_interval(12),
+ label_insertion(1200),
+ init_burst(12),
raw_slides(false),
sls_dir(NULL),
output("/tmp/pad.fifo")
@@ -118,3 +126,17 @@ private:
public:
BurstPadEncoder(PadEncoderOptions options) : PadEncoder(options) {}
};
+
+
+// --- UniformPadEncoder -----------------------------------------------------------------
+class UniformPadEncoder : public PadEncoder {
+private:
+ steady_clock::time_point pad_timeline;
+ steady_clock::time_point next_slide;
+ steady_clock::time_point next_label;
+ steady_clock::time_point next_label_insertion;
+
+ int Encode();
+public:
+ UniformPadEncoder(PadEncoderOptions options);
+};