view src/main/java/jp/ac/u_ryukyu/treevnc/SendSound.java @ 291:a310be14d757

send rtp+sound packet(client node version).
author oc
date Tue, 13 Jan 2015 06:43:15 +0900
parents c10e0dee7bbb
children d1ceb4b7097a
line wrap: on
line source

package jp.ac.u_ryukyu.treevnc;

import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
import java.net.*;

/**
 * Created by OcBookPro on 15/01/13.
 */
public class SendSound implements Runnable {

    public static final int recvPort = 60004;
    private TreeRFBProto rfb;
    private DatagramSocket socket;
    private boolean isStop;

    private int sequenceNum;
    private int timeStamp;
    private int syncSourceId;
    private byte marker;

    // Destination ip and port.
    private String destIp;
    private String destPort;

    // Constructor root version.
    public SendSound(TreeRFBProto rfb) {
        this.rfb = rfb;
    }

    // Constructor node version.
    public SendSound(TreeRFBProto rfb, String destIp, String destPort) throws UnknownHostException, SocketException {
        this.rfb = rfb;
        this.socket = new DatagramSocket(recvPort, InetAddress.getLocalHost());
        this.destIp = destIp;
        this.destPort = destPort;
    }

    @Override
    public void run() {
        try {
            byte[] soundPacket = new byte[160];

            AudioFormat linearFormat = new AudioFormat(8000,16,1,true,false);
            AudioFormat ulawFormat = new AudioFormat(AudioFormat.Encoding.ULAW,8000,8,1,1,8000,false);

            DataLine.Info info = new DataLine.Info(TargetDataLine.class,linearFormat);
            TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
            targetDataLine.open(linearFormat);
            targetDataLine.start();

            AudioInputStream linearStream = new AudioInputStream(targetDataLine);
            AudioInputStream ulawStream = AudioSystem.getAudioInputStream(ulawFormat,linearStream);

            byte[] byteaddress;
            byte[] rtpPacket;
            DatagramPacket packet = null;
            InetSocketAddress address = null;

            if (!rfb.isTreeManager()) {
                // rtp+sound packet
                rtpPacket = new byte[172];
                address = new InetSocketAddress(this.destIp, Integer.parseInt(this.destPort));
            }

            while(!isStop) {
                try {
                    ulawStream.read(soundPacket,0,soundPacket.length);
                    if (rfb.isTreeManager()) {
                        // soundPacketをframebufferUpdateに乗せて送信する処理
                        return;
                    }
                    // client node version.
                    rtpPacket = this.addRtpHeader(soundPacket);
                    packet = new DatagramPacket(rtpPacket,rtpPacket.length,address);
                    this.socket.send(packet);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void stopSendSound() {
        this.isStop = true;
    }

    private byte[] addRtpHeader(byte[] voiceData)
    {
        byte[] rtpHeader = new byte[12];	// RTPヘッダ
        byte version	= -128;				// バージョン番号10000000
        byte padding	= 0;				// パディング
        byte extention	= 0;				// 拡張ビット
        byte contribute	= 0;				// コントリビュートカウント
        byte payload	= 0;				// ペイロードタイプ

        // RTPヘッダーの生成
        rtpHeader[0]  = (byte)(version | padding | extention | contribute);
        rtpHeader[1]  = (byte)(marker | payload);
        rtpHeader[2]  = (byte)(this.sequenceNum >> 8);
        rtpHeader[3]  = (byte)(this.sequenceNum >> 0);
        rtpHeader[4]  = (byte)(this.timeStamp >> 24);
        rtpHeader[5]  = (byte)(this.timeStamp >> 16);
        rtpHeader[6]  = (byte)(this.timeStamp >>  8);
        rtpHeader[7]  = (byte)(this.timeStamp >>  0);
        rtpHeader[8]  = (byte)(this.syncSourceId >> 24);
        rtpHeader[9]  = (byte)(this.syncSourceId >> 16);
        rtpHeader[10] = (byte)(this.syncSourceId >>  8);
        rtpHeader[11] = (byte)(this.syncSourceId >>  0);

        // シーケンス番号、タイムスタンプ、マーカービット移行
        this.sequenceNum ++;
        this.timeStamp += 160;
        if(this.marker == -128)
            this.marker = 0;

        // RTPヘッダー+音声データ = RTPパケット
        ByteArrayOutputStream out = new ByteArrayOutputStream(172);
        out.write(rtpHeader,0,12);
        out.write(voiceData,0,160);

        return out.toByteArray();
    }
}