android基于rtp的音视频通信(1)

rtp套接字

/*
 * Copyright (C) 2009 The Sipdroid Open Source Project
 * Copyright (C) 2005 Luca Veltri - University of Parma - Italy
 * 
 * This file is part of Sipdroid (http://www.sipdroid.org)
 * 
 * Sipdroid is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This source code 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this source code; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
/**
 * RtpSocket implements a RTP socket for receiving and sending RTP packets.
 * <p>
 * RtpSocket is associated to a DatagramSocket that is used to send and/or
 * receive RtpPackets.
 */
public class RtpSocket {
    /**
     * UDP socket
     */
    SipdroidSocket socket;
    DatagramPacket datagram;
    /**
     * Remote address
     */
    InetAddress r_addr;
    /**
     * Remote port
     */
    int r_port;
    /**
     * Creates a new RTP socket (only receiver)
     */
    public RtpSocket(SipdroidSocket datagram_socket) {
        socket = datagram_socket;
        r_addr = null;
        r_port = 0;
        datagram = new DatagramPacket(new byte[1], 1);
    }
    /**
     * Creates a new RTP socket (sender and receiver)
     */
    public RtpSocket(SipdroidSocket datagram_socket,
                     InetAddress remote_address, int remote_port) {
        socket = datagram_socket;
        r_addr = remote_address;
        r_port = remote_port;
        datagram = new DatagramPacket(new byte[1], 1);
    }
    /**
     * Returns the RTP SipdroidSocket
     */
    public SipdroidSocket getDatagramSocket() {
        return socket;
    }
    /**
     * Receives a RTP packet from this socket
     */
    public void receive(RtpPacket rtpp) throws IOException {
        datagram.setData(rtpp.packet);
        datagram.setLength(rtpp.packet.length);
        socket.receive(datagram);
        if (!socket.isConnected())
            socket.connect(datagram.getAddress(), datagram.getPort());
        rtpp.packet_len = datagram.getLength();
    }
    /**
     * Sends a RTP packet from this socket
     */
    public void send(RtpPacket rtpp) throws IOException {
        datagram.setData(rtpp.packet);
        datagram.setLength(rtpp.packet_len);
        datagram.setAddress(r_addr);
        datagram.setPort(r_port);
        socket.send(datagram);
    }
    /**
     * Closes this socket
     */
    public void close() { // socket.close();
        socket.close();
    }
}

rtp发送包

/**
 * RtpPacket implements a RTP packet.
 */
public class RtpPacket {
	/* RTP packet buffer containing both the RTP header and payload */
	byte[] packet;

	/* RTP packet length */
	int packet_len;

	/* RTP header length */
	// int header_len;
	/** Gets the RTP packet */
	public byte[] getPacket() {
		return packet;
	}

	/** Gets the RTP packet length */
	public int getLength() {
		return packet_len;
	}

	/** Gets the RTP header length */
	public int getHeaderLength() {
		if (packet_len >= 12)
			return 12 + 4 * getCscrCount();
		else
			return packet_len; // broken packet
	}

	/** Gets the RTP header length */
	public int getPayloadLength() {
		if (packet_len >= 12)
			return packet_len - getHeaderLength();
		else
			return 0; // broken packet
	}

	/** Sets the RTP payload length */
	public void setPayloadLength(int len) {
		packet_len = getHeaderLength() + len;
	}

	// version (V): 2 bits
	// padding (P): 1 bit
	// extension (X): 1 bit
	// CSRC count (CC): 4 bits
	// marker (M): 1 bit
	// payload type (PT): 7 bits
	// sequence number: 16 bits
	// timestamp: 32 bits
	// SSRC: 32 bits
	// CSRC list: 0 to 15 items, 32 bits each

	/** Gets the version (V) */
	public int getVersion() {
		if (packet_len >= 12)
			return (packet[0] >> 6 & 0x03);
		else
			return 0; // broken packet
	}

	/** Sets the version (V) */
	public void setVersion(int v) {
		if (packet_len >= 12)
			packet[0] = (byte) ((packet[0] & 0x3F) | ((v & 0x03) << 6));
	}

	/** Whether has padding (P) */
	public boolean hasPadding() {
		if (packet_len >= 12)
			return getBit(packet[0], 5);
		else
			return false; // broken packet
	}

	/** Set padding (P) */
	public void setPadding(boolean p) {
		if (packet_len >= 12)
			packet[0] = setBit(p, packet[0], 5);
	}

	/** Whether has extension (X) */
	public boolean hasExtension() {
		if (packet_len >= 12)
			return getBit(packet[0], 4);
		else
			return false; // broken packet
	}

	/** Set extension (X) */
	public void setExtension(boolean x) {
		if (packet_len >= 12)
			packet[0] = setBit(x, packet[0], 4);
	}

	/** Gets the CSCR count (CC) */
	public int getCscrCount() {
		if (packet_len >= 12)
			return (packet[0] & 0x0F);
		else
			return 0; // broken packet
	}

	/** Whether has marker (M) */
	public boolean hasMarker() {
		if (packet_len >= 12)
			return getBit(packet[1], 7);
		else
			return false; // broken packet
	}

	/** Set marker (M) */
	public void setMarker(boolean m) {
		if (packet_len >= 12)
			packet[1] = setBit(m, packet[1], 7);
	}

	/** Gets the payload type (PT) */
	public int getPayloadType() {
		if (packet_len >= 12)
			return (packet[1] & 0x7F);
		else
			return -1; // broken packet
	}

	/** Sets the payload type (PT) */
	public void setPayloadType(int pt) {
		if (packet_len >= 12)
			packet[1] = (byte) ((packet[1] & 0x80) | (pt & 0x7F));
	}

	/** Gets the sequence number */
	public int getSequenceNumber() {
		if (packet_len >= 12)
			return getInt(packet, 2, 4);
		else
			return 0; // broken packet
	}

	/** Sets the sequence number */
	public void setSequenceNumber(int sn) {
		if (packet_len >= 12) {
			setInt(sn, packet, 2, 4);
		}
	}

	/** Gets the timestamp */
	public long getTimestamp() {
		if (packet_len >= 12)
			return getLong(packet, 4, 8);
		else
			return 0; // broken packet
	}

	/** Sets the timestamp */
	public void setTimestamp(long timestamp) {
		if (packet_len >= 12)
			setLong(timestamp, packet, 4, 8);
	}

	/** Gets the SSCR */
	public long getSscr() {
		if (packet_len >= 12)
			return getLong(packet, 8, 12);
		else
			return 0; // broken packet
	}

	/** Sets the SSCR */
	public void setSscr(long ssrc) {
		if (packet_len >= 12)
			setLong(ssrc, packet, 8, 12);
	}

	/** Gets the CSCR list */
	public long[] getCscrList() {
		int cc = getCscrCount();
		long[] cscr = new long[cc];
		for (int i = 0; i < cc; i++)
			cscr[i] = getLong(packet, 12 + 4 * i, 16 + 4 * i);
		return cscr;
	}

	/** Sets the CSCR list */
	public void setCscrList(long[] cscr) {
		if (packet_len >= 12) {
			int cc = cscr.length;
			if (cc > 15)
				cc = 15;
			packet[0] = (byte) (((packet[0] >> 4) << 4) + cc);
			cscr = new long[cc];
			for (int i = 0; i < cc; i++)
				setLong(cscr[i], packet, 12 + 4 * i, 16 + 4 * i);
			// header_len=12+4*cc;
		}
	}

	/** Sets the payload */
	public void setPayload(byte[] payload, int len) {
		if (packet_len >= 12) {
			int header_len = getHeaderLength();
			for (int i = 0; i < len; i++)
				packet[header_len + i] = payload[i];
			packet_len = header_len + len;
		}
	}

	/** Gets the payload */
	public byte[] getPayload() {
		int header_len = getHeaderLength();
		int len = packet_len - header_len;
		byte[] payload = new byte[len];
		for (int i = 0; i < len; i++)
			payload[i] = packet[header_len + i];
		return payload;
	}

	/** Creates a new RTP packet */
	public RtpPacket(byte[] buffer, int packet_length) {
		packet = buffer;
		packet_len = packet_length;
		if (packet_len < 12)
			packet_len = 12;
		init(0x0F);
	}

	/** init the RTP packet header (only PT) */
	public void init(int ptype) {
		init(ptype, Random.nextLong());
	}

	/** init the RTP packet header (PT and SSCR) */
	public void init(int ptype, long sscr) {
		init(ptype, Random.nextInt(), Random.nextLong(), sscr);
	}

	/** init the RTP packet header (PT, SQN, TimeStamp, SSCR) */
	public void init(int ptype, int seqn, long timestamp, long sscr) {
		setVersion(2);
		setPayloadType(ptype);
		setSequenceNumber(seqn);
		setTimestamp(timestamp);
		setSscr(sscr);
	}

	// *********************** Private and Static ***********************

	/** Gets int value */
	/*private static int getInt(byte b) {
		return ((int) b + 256) % 256;
	}*/

	/** Gets long value */
	private static long getLong(byte[] data, int begin, int end) {
		long n = 0;
		for (; begin < end; begin++) {
			n <<= 8;
			n += data[begin] & 0xFF;
		}
		return n;
	}

	/** Sets long value */
	private static void setLong(long n, byte[] data, int begin, int end) {
		for (end--; end >= begin; end--) {
			data[end] = (byte) (n % 256);
			n >>= 8;
		}
	}

	/** Gets Int value */
	private static int getInt(byte[] data, int begin, int end) {
		return (int) getLong(data, begin, end);
	}

	/** Sets Int value */
	private static void setInt(int n, byte[] data, int begin, int end) {
		setLong(n, data, begin, end);
	}

	/** Gets bit value */
	private static boolean getBit(byte b, int bit) {
		//return (b >> bit) == 1;
		return (b>>bit & 0x01) == 1;  //hzq
	}

	/** Sets bit value */
	private static byte setBit(boolean value, byte b, int bit) {
		if (value)
			return (byte) (b | (1 << bit));
		else
			return (byte) ((b | (1 << bit)) ^ (1 << bit));
	}
}

编码器(yuv转h264)

/*
 * H264 编码
 */
public class Send {
    //包含库文件
    static {
        System.loadLibrary("VideoEncoder");
    }
    //接口函数
    public native long CreateEncoder(int width, int height); //底层创建编码器,返回编码器
    //编码一帧图像,返回包的数目
    //type=编码帧的类型,frame=原始yuv图像,stream=原始图像码流,packetSize=包的尺寸
    public native int EncoderOneFrame(long encoder, int type, byte[] frame, byte[] stream, int[] packetSize);

    public native int DestroyEncoder(long encoder); //销毁编码器,释放资源 
}

使用

 	private RtpSocket rtp_socket = null; //创建RTP套接字
    private RtpPacket rtp_send_packet = null; //创建RTP发送包
    private long encoder_handle = -1; //创建编码器的句柄
    private int send_packetNum = 0; //包的数目
    private int[] send_packetSize = new int[200]; //包的尺寸
    private byte[] send_stream = new byte[65536]; //码流
    private byte[] socket_send_Buffer = new byte[65536];

 	@Override
    public void onFrame(byte[] frame, long timestamp) {
        if (!isSending) {
            return;
        }
        if (encoder_handle != -1) {
            //底层函数,返回包的数目,返回包的大小存储在数组packetSize中,返回码流在stream中
            send_packetNum = send.EncoderOneFrame(encoder_handle, -1, frame, send_stream, send_packetSize);
            if (send_packetNum > 0) {
                //通过RTP协议发送帧
                final int[] pos = {0}; //从码流头部开始取
                /**
                 * 因为可能传输数据过大 会将一次数据分割成好几段来传输
                 * 接受方 根据序列号和结束符 来将这些数据拼接成完整数据
                 */
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int sequence = 0; //初始化序列号
                        for (int i = 0; i < send_packetNum; i++) {
                            rtp_send_packet.setPayloadType(2);//定义负载类型,视频为2
                            rtp_send_packet.setMarker(i == send_packetNum - 1 ? true : false); //是否是最后一个RTP包
                            rtp_send_packet.setSequenceNumber(sequence++); //序列号依次加1
                            rtp_send_packet.setTimestamp(timestamp); //时间戳
                            rtp_send_packet.setPayloadLength(send_packetSize[i]); //包的长度,packetSize[i]+头文件
                            //从码流stream的pos处开始复制,从socketBuffer的第12个字节开始粘贴,packetSize为粘贴的长度
                            System.arraycopy(send_stream, pos[0], socket_send_Buffer, 12, send_packetSize[i]); //把一个包存在socketBuffer中
                            pos[0] += send_packetSize[i]; //重定义下次开始复制的位置
                           // Log.d("发送", "序列号:" + sequence + " bMark:" + rtp_send_packet.hasMarker() +  " timestamp:" + timestamp);
                            try {
                                if (rtp_socket != null && rtp_send_packet != null) {
                                    rtp_socket.send(rtp_send_packet);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
            }
        }
    }
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你丶快乐吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值