From 60df978a075e57ca2b4de611e0cb4ded3c36cd0a Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 21 Jul 2020 15:40:19 +0200 Subject: Add dump current and completed slide options --- src/odr-padenc.cpp | 28 +++++++++++++++++++++++++++- src/odr-padenc.h | 3 +++ src/sls.cpp | 21 ++++++++++++++++++++- src/sls.h | 2 +- 4 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/odr-padenc.cpp b/src/odr-padenc.cpp index 0a7629a..b919074 100644 --- a/src/odr-padenc.cpp +++ b/src/odr-padenc.cpp @@ -61,6 +61,9 @@ static void usage(const char* name) { " been encoded.\n" " -s, --sleep=DUR Wait DUR seconds between each slide\n" " Default: %d\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" + " Works only in uniform mode\n" " -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" @@ -144,6 +147,8 @@ int main(int argc, char *argv[]) { {"init-burst", required_argument, 0, 'i'}, {"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}, }; @@ -204,6 +209,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]); @@ -423,7 +434,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())) @@ -527,6 +538,21 @@ int UniformPadEncoder::Encode() { // 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 9ecf4a4..bda82f4 100644 --- a/src/odr-padenc.h +++ b/src/odr-padenc.h @@ -67,6 +67,9 @@ struct PadEncoderOptions { std::vector dls_files; const char* item_state_file; + std::string current_slide_dump_name; + std::string completed_slide_dump_name; + PadEncoderOptions() : padlen(58), erase_after_tx(false), diff --git a/src/sls.cpp b/src/sls.cpp index f19829f..f0b72f7 100644 --- a/src/sls.cpp +++ b/src/sls.cpp @@ -353,8 +353,23 @@ 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); +} -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; @@ -566,6 +581,10 @@ 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; } diff --git a/src/sls.h b/src/sls.h index 97b6ed4..07e05dc 100644 --- a/src/sls.h +++ b/src/sls.h @@ -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); }; -- cgit v1.2.3 From be7c6e78d334ffa9919b970aaecf2ff5f27a0354 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 21 Jul 2020 15:43:06 +0200 Subject: Add --version option --- src/odr-padenc.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/odr-padenc.cpp b/src/odr-padenc.cpp index b919074..da47d5b 100644 --- a/src/odr-padenc.cpp +++ b/src/odr-padenc.cpp @@ -86,6 +86,7 @@ static void usage(const char* name) { " 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 (may be used more than once)\n" + " --version Print version information and quit\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" @@ -122,6 +123,18 @@ static std::string list_dls_files(std::vector 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 -- cgit v1.2.3 From 6ea59e3c2b2fba81ed01a11c0ddfdd2d26455bfb Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 14 Sep 2020 14:53:28 +0200 Subject: Handle slides ending in _PadEncRawMode.jpg always in RAW --- README.md | 2 ++ src/odr-padenc.cpp | 2 ++ src/sls.cpp | 56 +++++++++++++++++++++++++++++++++++++----------------- src/sls.h | 4 ++-- 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'src') 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/src/odr-padenc.cpp b/src/odr-padenc.cpp index da47d5b..e348713 100644 --- a/src/odr-padenc.cpp +++ b/src/odr-padenc.cpp @@ -84,6 +84,8 @@ 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" " --version Print version information and quit\n" diff --git a/src/sls.cpp b/src/sls.cpp index f0b72f7..f6cfb6f 100644 --- a/src/sls.cpp +++ b/src/sls.cpp @@ -369,6 +369,19 @@ static void dump_slide(const std::string& dump_name, const uint8_t *blob, size_t 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, const std::string& dump_name) { bool result = false; @@ -377,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. @@ -451,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) { @@ -460,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); @@ -501,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; @@ -537,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; @@ -561,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; @@ -589,14 +611,14 @@ bool SLSEncoder::encodeSlide(const std::string& fname, int fidx, bool raw_slides } 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 @@ -730,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 07e05dc..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 ¶ms_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); -- cgit v1.2.3