diff options
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | src/mot-encoder.cpp | 73 | 
2 files changed, 73 insertions, 17 deletions
@@ -16,7 +16,7 @@ The JACK input does not automatically connect to anything. The encoder runs  at the rate defined by the system clock, and therefore sound  card clock drift compensation is also used. -*dabplus-enc* includes support for DAB MOT Slideshow and DLS, written by +*dabplus-enc* includes support for DAB MOT Slideshow and DLS, contributed by  [CSP](http://rd.csp.it).  To encode DLS and Slideshow data, the *mot-encoder* tool reads images @@ -188,14 +188,15 @@ dabplus-enc returns:  Usage of MOT Slideshow and DLS  ============================== -MOT Slideshow is a new feature, which has been tested on several receivers and -using [XPADxpert](http://www.basicmaster.de/xpadxpert/), but is still a work -in progress. +*mot-encoder* reads images from the specified folder, and generates the PAD +data for the encoder. This is communicated through a fifo to the encoder. It +also reads DLS from a file, and includes this information in the PAD. -*mot-encoder* reads images from -the specified folder, and generates the PAD data for the encoder. This is -communicated through a fifo to the encoder. It also reads DLS from a file, and -includes this information in the PAD. +It can read all file formats supported by ImageMagick, and by default resizes +them to 320x240 pixels, and compresses them as JPEG. If the input file is already +a JPEG file of the correct size, and smaller than 50kB, it is sent without further +compression. If the input file is a PNG that satisfies the same criteria, it is +transmitted as PNG without any recompression.  *dabplus-enc* can insert the PAD data from mot-encoder into the bitstream.  The mp2 encoder [toolame-dab](https://github.com/Opendigitalradio/toolame-dab) diff --git a/src/mot-encoder.cpp b/src/mot-encoder.cpp index 832ad50..c92a596 100644 --- a/src/mot-encoder.cpp +++ b/src/mot-encoder.cpp @@ -197,7 +197,14 @@ unsigned char contname[14];     // 0xCC 0x0C 0x00 imgXXXX.jpg  } MOTSLIDEHDR;  */  int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw_slides); -void createMotHeader(size_t blobsize, int fidx, unsigned char* mothdr, int* mothdrlen); + +void createMotHeader( +        size_t blobsize, +        int fidx, +        unsigned char* mothdr, +        int* mothdrlen, +        bool jfif_not_png); +  void createMscDG(MSCDG* msc, unsigned short int dgtype, unsigned short int cindex,          unsigned short int lastseg, unsigned short int tid, unsigned char* data,          unsigned short int datalen); @@ -525,6 +532,11 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw       */      bool orig_is_jpeg = false; +    /* If the original is a PNG, we transmit it as is, if the resolution is correct +     * and the file is not too large. Otherwise it gets resized and sent as JPEG. +     */ +    bool orig_is_png = false; +      /* By default, we do resize the image to 320x240, with a quality such that       * the blobsize is at most MAXSLIDESIZE.       * @@ -533,6 +545,7 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw       */      bool resize_required = true; +    bool jfif_not_png = true;      if (!raw_slides) { @@ -564,6 +577,16 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw                              fname.c_str(), fidx, width, height, orig_format, orig_quality);                  }              } +            else if (strcmp(orig_format, "PNG") == 0) { +                orig_is_png = true; +                jfif_not_png = false; + +                if (verbose) { +                    fprintf(stderr, "mot-encoder image: %s (id=%d)." +                            " Original size: %zu x %zu. (%s)\n", +                            fname.c_str(), fidx, width, height, orig_format); +                } +            }              else if (verbose) {                  fprintf(stderr, "mot-encoder image: %s (id=%d)."                          " Original size: %zu x %zu. (%s)\n", @@ -580,23 +603,28 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw                      fname.c_str(), fidx, width, height);          } -        if (orig_is_jpeg && height == 240 && width == 320) { +        if ((orig_is_jpeg || orig_is_png) && height == 240 && width == 320) {              // Don't recompress the image and check if the blobsize is suitable              blob = MagickGetImagesBlob(m_wand, &blobsize);              if (blobsize < MAXSLIDESIZE) { -                fprintf(stderr, "mot-encoder image: %s (id=%d).  No resize needed: %zu Bytes\n", -                        fname.c_str(), fidx, blobsize); +                if (verbose) { +                    fprintf(stderr, "mot-encoder image: %s (id=%d).  No resize needed: %zu Bytes\n", +                            fname.c_str(), fidx, blobsize); +                }                  resize_required = false;              }          }          if (resize_required) {              blobsize = resizeImage(m_wand, &blob); + +            // resizeImage always creates a jpg output +            jfif_not_png = true;          }      } -    else { +    else { // Use RAW data, it might not even be a jpg !          // read file          FILE* pFile = fopen(fname.c_str(), "rb");          if (pFile == NULL) { @@ -625,6 +653,20 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw          // copy the file into the buffer:          size_t dummy = fread(blob, 1, blobsize, pFile); +        size_t last_dot = fname.rfind("."); + +        // default: +        jfif_not_png = true; // This is how we did it in the past. +                             // It's wrong anyway, so we're at least compatible + +        if (last_dot != std::string::npos) { +            std::string file_extension = fname.substr(last_dot, std::string::npos); + +            if (file_extension == ".png") { +                jfif_not_png = false; +            } +        } +          if (pFile != NULL) {              fclose(pFile);          } @@ -637,7 +679,7 @@ int encodeFile(int output_fd, std::string& fname, int fidx, int padlen, bool raw              nseg++;          } -        createMotHeader(blobsize, fidx, mothdr, &mothdrlen); +        createMotHeader(blobsize, fidx, mothdr, &mothdrlen, jfif_not_png);          // Create the MSC Data Group C-Structure          createMscDG(&msc, 3, 0, 1, fidx, mothdr, mothdrlen);          // Generate the MSC DG frame (Figure 9 en 300 401) @@ -675,21 +717,34 @@ encodefile_out:  } -void createMotHeader(size_t blobsize, int fidx, unsigned char* mothdr, int* mothdrlen) +void createMotHeader(size_t blobsize, int fidx, unsigned char* mothdr, int* mothdrlen, bool jfif_not_png)  {      struct stat s; -    uint8_t MotHeaderCore[7] = {0x00,0x00,0x00,0x00,0x0D,0x04,0x01}; +    uint8_t MotHeaderCore[7] = {0x00,0x00,0x00,0x00,0x0D,0x04,0x00};      uint8_t MotHeaderExt[19] = {0x85,0x00,0x00,0x00,0x00,0xcc,0x0c,          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};      char cntemp[12];      int i; +    // Set correct content subtype +    //  ETSI TS 101 756 V1.2.1 Clause 6.1 Table 17 +    if (jfif_not_png) { +        MotHeaderCore[6] = 0x01; +    } +    else { +        MotHeaderCore[6] = 0x03; +    } +      MotHeaderCore[0] = (blobsize<<4 & 0xFF000000) >> 24;      MotHeaderCore[1] = (blobsize<<4 & 0x00FF0000) >> 16;      MotHeaderCore[2] = (blobsize<<4 & 0x0000FF00) >> 8;      MotHeaderCore[3] = (blobsize<<4 & 0x000000FF); -    sprintf(cntemp, "img%04d.jpg", fidx); +    sprintf(cntemp, +            "img%04d.%s", +            fidx, +            jfif_not_png ? "jpg" : "png" ); +      for (i = 0; i < strlen(cntemp); i++) {          MotHeaderExt[8+i] = cntemp[i];      }  | 
