Skip to content
Snippets Groups Projects
muebtransmitter.cc 3.05 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "muebtransmitter.h"
    
    
    #include "muebtransmitter_p.h"
    
    
    MuebTransmitter::MuebTransmitter(QObject* parent)
        : QObject(parent), d_ptr_(new MuebTransmitterPrivate(this)) {}
    
    MuebTransmitter::~MuebTransmitter() { delete d_ptr_; }
    
    void MuebTransmitter::SendFrame(libmueb::Frame frame) {
    
    bodzsoaa's avatar
    bodzsoaa committed
      Q_D(MuebTransmitter);
    
    
    bodzsoaa's avatar
    bodzsoaa committed
      if (frame.isNull() || frame.format() != QImage::Format_RGB888 ||
    
    bodzsoaa's avatar
    bodzsoaa committed
          frame.width() != d->configuration_.width() ||
          frame.height() != d->configuration_.height()) {
    
        qWarning() << "[MuebTransmitter] Frame is invalid";
        return;
      }
    
      frame.convertTo(QImage::Format_RGB888);
    
    
      QByteArray reduced_compressed_frame;
      // Frame color reduction and compression
      if (d->configuration_.color_depth() < 5) {
        reduced_compressed_frame = QtConcurrent::blockingMappedReduced<QByteArray>(
            frame.constBits(), frame.constBits() + frame.sizeInBytes(),
            /* Reference:
             * http://threadlocalmutex.com/?p=48
             * http://threadlocalmutex.com/?page_id=60
             */
            [d](const uchar& color) -> uchar {
              if (d->configuration_.color_depth() == 3) {
                return (color * 225 + 4096) >> 13;
              } else if (d->configuration_.color_depth() == 4) {
                return (color * 15 + 135) >> 8;
              }
    
              return color;
            },
            [d](QByteArray& compressed_colors, const uchar& color) {
              static bool msb{true};
    
              // Compress 2 color components into 1 byte
              if (msb) {
                compressed_colors.append(color << d->configuration_.factor());
              } else {
                compressed_colors.back() = compressed_colors.back() | color;
              }
    
              msb = !msb;
            },
            QtConcurrent::OrderedReduce | QtConcurrent::SequentialReduce);
      }
      // No compression
      else {
        reduced_compressed_frame.setRawData(
            reinterpret_cast<const char*>(frame.bits()), frame.sizeInBytes());
      }
    
      if (d->configuration_.max_packet_number() == 1) {
        reduced_compressed_frame.insert(0, d->configuration_.protocol_type())
            .insert(1, static_cast<char>(0) /*packet number*/);
    
        d->datagram_.setData(reduced_compressed_frame);
        d->socket_.writeDatagram(d->datagram_);
      } else {
        for (std::uint8_t i = 0; i < d->configuration_.max_packet_number(); ++i) {
          QByteArray data;
          data.append(d->configuration_.protocol_type())
              .append(i /*packet number*/)
              .append(reduced_compressed_frame.sliced(
                  i * d->configuration_.packet_payload_size(),
                  d->configuration_.packet_payload_size()));
    
          d->datagram_.setData(data);
          d->socket_.writeDatagram(d->datagram_);
        }
      }
    
    }
    
    MuebTransmitter& MuebTransmitter::Instance() {
      static MuebTransmitter instance;
    
      return instance;
    }
    
    
    bodzsoaa's avatar
    bodzsoaa committed
    std::int32_t MuebTransmitter::width() const {
    
    bodzsoaa's avatar
    bodzsoaa committed
      Q_D(const MuebTransmitter);
    
      return d->configuration_.width();
    
    bodzsoaa's avatar
    bodzsoaa committed
    std::int32_t MuebTransmitter::height() const {
    
    bodzsoaa's avatar
    bodzsoaa committed
      Q_D(const MuebTransmitter);
    
      return d->configuration_.height();
    
    }
    
    libmueb::Frame MuebTransmitter::frame() const {
    
    bodzsoaa's avatar
    bodzsoaa committed
      Q_D(const MuebTransmitter);
    
      return d->configuration_.frame();