aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2020-09-17 15:10:13 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2020-09-17 15:11:58 +0200
commitcd2198f0b60a01e7f40755efd8e4ab98e60d103c (patch)
treee37dbba1357f607efd771bb52976b1e1be3ff7c9
parente36865985abf9c4f31d34a9542c790f5baf8fe60 (diff)
parent867ec108066adb47a4f86fc5241fff96a28708d9 (diff)
downloadODR-PadEnc-cd2198f0b60a01e7f40755efd8e4ab98e60d103c.tar.gz
ODR-PadEnc-cd2198f0b60a01e7f40755efd8e4ab98e60d103c.tar.bz2
ODR-PadEnc-cd2198f0b60a01e7f40755efd8e4ab98e60d103c.zip
Merge branch 'next' into padsocket
-rw-r--r--ChangeLog24
-rw-r--r--README.md2
-rw-r--r--configure.ac2
-rw-r--r--src/odr-padenc.cpp44
-rw-r--r--src/odr-padenc.h2
-rw-r--r--src/sls.cpp77
-rw-r--r--src/sls.h6
7 files changed, 132 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 6484f05..e18a84c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2020-09-15: Matthias P. Braendli <matthias@mpb.li>
+ (v2.4.0):
+ Add --version option.
+ Handle slides ending in _PadEncRawMode.jpg always in RAW.
+ Some build system changes.
+ DLS: allow to use separate DL Plus item state file and add request to file reread.
+
+2018-03-18: Stefan Pöschel <odr@basicmaster.de>
+ (v2.3.0)
+
+2017-04-17: Stefan Pöschel <odr@basicmaster.de>
+ (v2.2.0)
+
+2017-03-09: Stefan Pöschel <odr@basicmaster.de>
+ (v2.1.1)
+
+2017-02-19: Stefan Pöschel <odr@basicmaster.de>
+ (v2.1.0)
+
+2016-10-14: Stefan Pöschel <odr@basicmaster.de>
+ (v2.0.1)
+
+In 2016 the project gets renamed to odr-padenc
+
2016-09-02: Matthias P. Braendli <matthias@mpb.li>
(v1.2.0):
* mot-encoder:
diff --git a/README.md b/README.md
index fe47d46..5d00e24 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,8 @@ RAW Format
If ImageMagick is not compiled in, or when enabled with the `-R` option, the images
are not modified, and are transmitted as-is. Use this if you can guarantee that
the generated files are smaller than 50kB and not larger than 320x240 pixels.
+Files whose name end in `_PadEncRawMode.png` or `_PadEncRawMode.jpg` will always
+be transmitted in RAW mode.
It may be useful to apply [`optipng`](http://optipng.sourceforge.net) to any PNG file prior to transmission.
Supported Encoders
diff --git a/configure.ac b/configure.ac
index f7e0d8c..3c073e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([ODR-PadEnc], [2.3.0], [http://opendigitalradio.org/])
+AC_INIT([ODR-PadEnc], [2.4.0], [http://opendigitalradio.org/])
AC_CONFIG_AUX_DIR(.)
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([tar-ustar foreign])
diff --git a/src/odr-padenc.cpp b/src/odr-padenc.cpp
index 41a1ea1..a22cba6 100644
--- a/src/odr-padenc.cpp
+++ b/src/odr-padenc.cpp
@@ -61,6 +61,8 @@ static void usage(const char* name) {
" -s, --sleep=DUR Wait DUR seconds between each slide\n"
" Default: %d\n"
" -o, --output=IDENTIFIER Socket to communicate with audio encoder\n"
+ " --dump-current-slide=F1 Write the slide currently being transmitted to the file F1\n"
+ " --dump-completed-slide=F2 Once the slide is transmitted, move the file from F1 to F2\n"
" -t, --dls=FILENAME FIFO or file to read DLS text from.\n"
" If specified more than once, use next file after -l delay.\n"
" -c, --charset=ID ID of the character set encoding used for DLS text input.\n"
@@ -76,10 +78,11 @@ static void usage(const char* name) {
" Default: %zu (Simple Profile)\n"
" -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"
+ " Slides whose name ends in _PadEncRawMode.jpg or _PadEncRawMode.png are always transmitted unprocessed, regardless of\n"
+ " the -R option being set \n"
" It is useful only when -d is used\n"
" -v, --verbose Print more information to the console (may be used more than once)\n"
- "\n"
- "Parameters for uniform PAD encoder only:\n"
+ " --version Print version information and quit\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"
@@ -111,6 +114,18 @@ static std::string list_dls_files(std::vector<std::string> dls_files) {
int main(int argc, char *argv[]) {
+ // Version handling is done very early to ensure nothing else but the version gets printed out
+ if (argc == 2 and strcmp(argv[1], "--version") == 0) {
+ fprintf(stdout, "%s\n",
+#if defined(GITVERSION)
+ GITVERSION
+#else
+ PACKAGE_VERSION
+#endif
+ );
+ return 0;
+ }
+
header();
// get/check options
@@ -133,6 +148,8 @@ int main(int argc, char *argv[]) {
{"label-ins", required_argument, 0, 'L'},
{"xpad-interval", required_argument, 0, 'X'},
{"verbose", no_argument, 0, 'v'},
+ {"dump-current-slide", required_argument, 0, 1},
+ {"dump-completed-slide", required_argument, 0, 2},
{0,0,0,0},
};
@@ -184,6 +201,12 @@ int main(int argc, char *argv[]) {
case 'v':
verbose++;
break;
+ case 1: // dump-current-slide
+ options.current_slide_dump_name = optarg;
+ break;
+ case 2: // dump-completed-slide
+ options.completed_slide_dump_name = optarg;
+ break;
case '?':
case 'h':
usage(argv[0]);
@@ -409,7 +432,7 @@ int PadEncoder::EncodeSlide(bool skip_if_already_queued) {
if (!slides.Empty()) {
slide_metadata_t slide = slides.GetSlide();
- if (sls_encoder.encodeSlide(slide.filepath, slide.fidx, options.raw_slides, options.max_slide_size)) {
+ if (sls_encoder.encodeSlide(slide.filepath, slide.fidx, options.raw_slides, options.max_slide_size, options.current_slide_dump_name)) {
slides_success = true;
if (options.erase_after_tx) {
if (unlink(slide.filepath.c_str()))
@@ -453,6 +476,21 @@ int PadEncoder::Encode(PadInterface& intf) {
// handle SLS
if (options.SLSEnabled()) {
+
+ // Check if slide transmission is complete
+ if ( not options.completed_slide_dump_name.empty() and
+ not options.current_slide_dump_name.empty() and
+ not pad_packetizer.QueueContainsDG(SLSEncoder::APPTYPE_MOT_START)) {
+ if (rename(options.current_slide_dump_name.c_str(), options.completed_slide_dump_name.c_str())) {
+ if (errno != ENOENT) {
+ perror("ODR-PadEnc Error: renaming completed slide file failed");
+ }
+ }
+ else {
+ fprintf(stderr, "ODR-PadEnc completed slide transmission.\n");
+ }
+ }
+
if (options.slide_interval > 0) {
// encode slides regularly
if (pad_timeline >= next_slide) {
diff --git a/src/odr-padenc.h b/src/odr-padenc.h
index 85dd11b..56b48f8 100644
--- a/src/odr-padenc.h
+++ b/src/odr-padenc.h
@@ -65,6 +65,8 @@ struct PadEncoderOptions {
std::string socket_ident;
std::vector<std::string> dls_files;
const char *item_state_file = nullptr;
+ std::string current_slide_dump_name;
+ std::string completed_slide_dump_name;
bool DLSEnabled() const { return !dls_files.empty(); }
bool SLSEnabled() const { return sls_dir; }
diff --git a/src/sls.cpp b/src/sls.cpp
index f19829f..f6cfb6f 100644
--- a/src/sls.cpp
+++ b/src/sls.cpp
@@ -353,8 +353,36 @@ size_t SLSEncoder::resizeImage(MagickWand* m_wand, unsigned char** blob, const s
}
#endif
+static void dump_slide(const std::string& dump_name, const uint8_t *blob, size_t size)
+{
+ FILE* fd = fopen(dump_name.c_str(), "w");
+
+ if (fd == nullptr) {
+ perror(("ODR-PadEnc Error: Unable to open file '" + dump_name + "' for writing").c_str());
+ return;
+ }
+
+ if (fwrite(blob, size, 1, fd) == 0) {
+ perror(("ODR-PadEnc Error: Unable to write to file '" + dump_name + "'").c_str());
+ }
+
+ fclose(fd);
+}
+
+static bool filename_specifies_raw_mode(const std::string& fname)
+{
+ const size_t sep = fname.rfind("_");
+ if (sep != std::string::npos) {
+ std::string suffix = fname.substr(sep, std::string::npos);
+ std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
+ return suffix == "_padencrawmode.png" or suffix == "_padencrawmode.jpg";
+ }
+ else {
+ return false;
+ }
+}
-bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides, size_t max_slide_size)
+bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides, size_t max_slide_size, const std::string& dump_name)
{
bool result = false;
@@ -362,11 +390,14 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
MagickWand *m_wand = NULL;
#endif
- uint8_t* blob = NULL;
+ uint8_t *raw_blob = NULL;
+ uint8_t *magick_blob = NULL;
size_t blobsize;
bool jfif_not_png = true;
- if (!raw_slides) {
+ const bool raw_slide = filename_specifies_raw_mode(fname) or raw_slides;
+
+ if (!raw_slide) {
#if HAVE_MAGICKWAND
/*! By default, we do resize the image to 320x240, with a quality such that
* the blobsize is at most MAXSLIDESIZE.
@@ -436,7 +467,7 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
if (native_support && height <= 240 && width <= 320 && not jpeg_progr) {
// Don't recompress the image and check if the blobsize is suitable
- blob = MagickGetImageBlob(m_wand, &blobsize);
+ magick_blob = MagickGetImageBlob(m_wand, &blobsize);
if (blobsize <= max_slide_size) {
if (verbose) {
@@ -445,13 +476,13 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
}
resize_required = false;
} else {
- MagickRelinquishMemory(blob);
- blob = NULL;
+ MagickRelinquishMemory(magick_blob);
+ magick_blob = NULL;
}
}
if (resize_required) {
- blobsize = resizeImage(m_wand, &blob, fname, &jfif_not_png, max_slide_size);
+ blobsize = resizeImage(m_wand, &magick_blob, fname, &jfif_not_png, max_slide_size);
} else {
// warn if unresized image smaller than default dimension
warnOnSmallerImage(height, width, fname);
@@ -486,15 +517,15 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
}
// allocate memory to contain the whole file:
- blob = (uint8_t*) malloc(blobsize);
- if (blob == NULL) {
+ raw_blob = (uint8_t*) malloc(blobsize);
+ if (raw_blob == NULL) {
fprintf(stderr, "ODR-PadEnc Error: Memory allocation error\n");
fclose(pFile);
goto encodefile_out;
}
// copy the file into the buffer:
- if (fread(blob, blobsize, 1, pFile) != 1) {
+ if (fread(raw_blob, blobsize, 1, pFile) != 1) {
fprintf(stderr, "ODR-PadEnc Error: Could not read file\n");
fclose(pFile);
goto encodefile_out;
@@ -522,6 +553,12 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
}
if (blobsize) {
+ if (raw_blob == nullptr and magick_blob == nullptr) {
+ fprintf(stderr, "ODR-PadEnc logic error: either raw_blob or magick_blob must be non-null! See src/sls.cpp line %d\n", __LINE__);
+ abort();
+ }
+ const uint8_t *blob = raw_blob ? raw_blob : magick_blob;
+
MSCDG msc;
DATA_GROUP* dgli;
DATA_GROUP* mscdg;
@@ -546,7 +583,7 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
// MOT Body
for (size_t i = 0; i < nseg; i++) {
- unsigned char *curseg = blob + i * MAXSEGLEN;
+ const uint8_t *curseg = blob + i * MAXSEGLEN;
size_t curseglen;
int last;
@@ -566,18 +603,22 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides
pad_packetizer->AddDG(mscdg, false);
}
+ if (not dump_name.empty()) {
+ dump_slide(dump_name, blob, blobsize);
+ }
+
result = true;
}
encodefile_out:
- if (blob) {
- if(raw_slides) {
- free(blob);
- } else {
+ if (raw_blob) {
+ free(raw_blob);
+ }
+
+ if (magick_blob) {
#if HAVE_MAGICKWAND
- MagickRelinquishMemory(blob);
+ MagickRelinquishMemory(magick_blob);
#endif
- }
}
#if HAVE_MAGICKWAND
@@ -711,7 +752,7 @@ uint8_vector_t SLSEncoder::createMotHeader(size_t blobsize, int fidx, bool jfif_
void SLSEncoder::createMscDG(MSCDG* msc, unsigned short int dgtype,
int *cindex, unsigned short int segnum, unsigned short int lastseg,
- unsigned short int tid, unsigned char* data,
+ unsigned short int tid, const uint8_t* data,
unsigned short int datalen)
{
msc->extflag = 0;
diff --git a/src/sls.h b/src/sls.h
index 97b6ed4..dbbcf3c 100644
--- a/src/sls.h
+++ b/src/sls.h
@@ -73,7 +73,7 @@ struct MSCDG {
unsigned char rcount; // 3 bits
unsigned short int seglen; // 13 bits
// Mot segment
- unsigned char* segdata;
+ const uint8_t* segdata;
// MSC data group CRC
unsigned short int crc; // 16 bits
};
@@ -237,7 +237,7 @@ private:
uint8_vector_t createMotHeader(size_t blobsize, int fidx, bool jfif_not_png, const std::string &params_fname);
void createMscDG(MSCDG* msc, unsigned short int dgtype,
int *cindex, unsigned short int segnum, unsigned short int lastseg,
- unsigned short int tid, unsigned char* data,
+ unsigned short int tid, const uint8_t* data,
unsigned short int datalen);
DATA_GROUP* packMscDG(MSCDG* msc);
@@ -252,7 +252,7 @@ public:
SLSEncoder(PADPacketizer* pad_packetizer) : pad_packetizer(pad_packetizer), cindex_header(0), cindex_body(0) {}
- bool encodeSlide(const std::string& fname, int fidx, bool raw_slides, size_t max_slide_size);
+ bool encodeSlide(const std::string& fname, int fidx, bool raw_slides, size_t max_slide_size, const std::string& dump_name);
static bool isSlideParamFileFilename(const std::string& filename);
};