Package org.bigbluebutton.deskshare.client.blocks

Source Code of org.bigbluebutton.deskshare.client.blocks.Block

/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.deskshare.client.blocks;

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.concurrent.atomic.AtomicLong;

import org.bigbluebutton.deskshare.client.net.EncodedBlockData;
import org.bigbluebutton.deskshare.common.PixelExtractException;
import org.bigbluebutton.deskshare.common.ScreenVideoEncoder;
import org.bigbluebutton.deskshare.common.Dimension;

public final class Block {
    private static final int KEEP_ALIVE_INTERVAL = 30000;
    private static final int DIRTY_COUNT_LIMIT = 10;
   
    private final BlockChecksum checksum;
    private final Dimension dim;
    private final int position;
    private final Point location;   
    private int[] capturedPixels;
    private final Object pixelsLock = new Object();
    private long lastSent = System.currentTimeMillis();
    private AtomicLong sentCount = new AtomicLong();
    private Integer dirtyCount = DIRTY_COUNT_LIMIT; // initially, blocks are sent immediately
    private boolean useSVC2;
   
    Block(Dimension dim, int position, Point location, boolean useSVC2) {
        checksum = new BlockChecksum();
        this.dim = dim;
        this.position = position;
        this.location = location;
        this.useSVC2 = useSVC2;
    }
   
    public boolean hasChanged(BufferedImage capturedScreen) {  
      synchronized(pixelsLock) {
            try {
              capturedPixels = ScreenVideoEncoder.getPixels(capturedScreen, getX(), getY(), getWidth(), getHeight(), useSVC2);
            } catch (PixelExtractException e) {
              System.out.println(e.toString());
         
           
           
      }
        synchronized (dirtyCount) {
            if ((! checksumSame(capturedPixels)) || sendKeepAliveBlock()) {
                if (dirtyCount >= DIRTY_COUNT_LIMIT) {
                    dirtyCount = 0;
                    return true;
                } else {
                    dirtyCount++;
                    return false;
                }
            } else {
                if (dirtyCount > 0) {
                    dirtyCount = 0;
                    return true;
                } else {
                    return false;
                }
            }
        }
    }
        
    private boolean isKeepAliveBlock() {
      // Use block 1 as our keepalive block. The keepalive block is our audit so that the server knows
      // that the applet is still connected to the server. So it there's no change in the desktop, the applet
      // should still send this keepalive block.
      return position == 1;
    }
   
    private boolean sendKeepAliveBlock() {
      long now = System.currentTimeMillis();
      if (isKeepAliveBlock() && (now - lastSent > KEEP_ALIVE_INTERVAL)) {
        // Send keepalive block every 30 seconds.
        lastSent = now;
        System.out.println("Sending keep alive block!");
        return true;
      }
      return false;
    }
   
    public void sent() {
      sentCount.incrementAndGet();
    }
   
    public EncodedBlockData encode() {  
      int[] pixelsCopy = new int[capturedPixels.length];
     
      synchronized (pixelsLock) {        
            System.arraycopy(capturedPixels, 0, pixelsCopy, 0, capturedPixels.length);
    }

      byte[] encodedBlock = useSVC2 ?
          ScreenVideoEncoder.encodePixelsSVC2(pixelsCopy, getWidth(), getHeight()) :
          ScreenVideoEncoder.encodePixels(pixelsCopy, getWidth(), getHeight(), (sentCount.longValue() < 5) /* send grayscale image */);  
        return new EncodedBlockData(position, encodedBlock);   
    }
   
    private boolean checksumSame(int[] pixels) {
      return checksum.isChecksumSame(convertIntPixelsToBytePixels(pixels));
    }
         
    private byte[] convertIntPixelsToBytePixels(int[] pixels) {
      byte[] p = new byte[pixels.length * 3];
      int position = 0;
   
    for (int i = 0; i < pixels.length; i++) {
      byte red = (byte) ((pixels[i] >> 16) & 0xff);
      byte green = (byte) ((pixels[i] >> 8) & 0xff);
      byte blue = (byte) (pixels[i] & 0xff);

      // Sequence should be BGR
      p[position++] = blue;
      p[position++] = green;
      p[position++] = red;
    }
   
    return p;
    }
   
    public int getWidth() {
        return new Integer(dim.getWidth()).intValue();
    }
   
    public int getHeight() {
        return new Integer(dim.getHeight()).intValue();
    }
   
    public int getPosition() {
    return new Integer(position).intValue();
  }
   
    public int getX() {
    return new Integer(location.x).intValue();
  }

    public int getY() {
    return new Integer(location.y).intValue();
  }
 
    Dimension getDimension() {
    return new Dimension(dim.getWidth(), dim.getHeight());
  }
 
    Point getLocation() {
    return new Point(location.x, location.y);
  }
}
TOP

Related Classes of org.bigbluebutton.deskshare.client.blocks.Block

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.