android rtp h264代码完整示例
时间: 2024-01-07 16:05:13 浏览: 132
android使用H264库示例
以下是一个简单的 Android RTP H264 的代码示例:
```
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.net.rtp.*;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
public class RtpH264Sender {
private MediaCodec mEncoder;
private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
private byte[] mSPS;
private byte[] mPPS;
private byte[] mBuffer = new byte[1024 * 1024];
private int mBufferPosition = 0;
private LinkedBlockingQueue<byte[]> mFrameQueue = new LinkedBlockingQueue<>();
private Thread mEncoderThread;
private Thread mSenderThread;
private boolean mIsEncoding = false;
private boolean mIsSending = false;
private RtpSocket mRtpSocket;
private Handler mHandler;
private final int MSG_SEND_FRAME = 1;
private final int MSG_STOP_SENDING = 2;
public RtpH264Sender() {
try {
mEncoder = MediaCodec.createEncoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat("video/avc", 640, 480);
format.setInteger(MediaFormat.KEY_BIT_RATE, 500000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SEND_FRAME:
byte[] frame = (byte[])msg.obj;
sendFrame(frame);
break;
case MSG_STOP_SENDING:
mIsSending = false;
break;
}
}
};
} catch (IOException e) {
e.printStackTrace();
}
}
public void startSending(String ip, int port) throws IOException {
mRtpSocket = new RtpSocket(new DatagramSocket(port));
mRtpSocket.setDestination(InetAddress.getByName(ip), port);
mIsSending = true;
mSenderThread = new Thread(new Runnable() {
@Override
public void run() {
while (mIsSending) {
try {
byte[] data = mFrameQueue.take();
sendRtpPacket(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mRtpSocket.close();
}
});
mSenderThread.start();
mIsEncoding = true;
mEncoderThread = new Thread(new Runnable() {
@Override
public void run() {
while (mIsEncoding) {
int inputBufferIndex = mEncoder.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mEncoder.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
byte[] data = getNextFrame();
if (data == null) {
mIsEncoding = false;
break;
}
inputBuffer.put(data);
mEncoder.queueInputBuffer(inputBufferIndex, 0, data.length, System.nanoTime() / 1000, 0);
}
int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 10000);
if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = mEncoder.getOutputBuffer(outputBufferIndex);
outputBuffer.position(mBufferInfo.offset);
outputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
byte[] data = new byte[mBufferInfo.size];
outputBuffer.get(data);
outputBuffer.clear();
if ((mBufferPosition + data.length + 4) > mBuffer.length) {
sendBuffer();
}
System.arraycopy(data, 0, mBuffer, mBufferPosition + 4, data.length);
if (mSPS != null && mPPS != null) {
mBuffer[0] = mSPS[0];
mBuffer[1] = mSPS[1];
mBuffer[2] = mSPS[2];
mBuffer[3] = mSPS[3];
mBufferPosition += 4;
}
mBufferPosition += data.length;
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
}
}
sendBuffer();
mHandler.sendEmptyMessage(MSG_STOP_SENDING);
}
});
mEncoderThread.start();
}
public void stopSending() {
mIsEncoding = false;
mIsSending = false;
mHandler.sendEmptyMessage(MSG_STOP_SENDING);
}
public void feedData(byte[] data) {
mFrameQueue.offer(data);
}
private void sendRtpPacket(byte[] data) {
try {
int timestamp = (int)System.nanoTime() / 1000;
RtpPacket packet = new RtpPacket(data, 0, data.length);
packet.setTimestamp(timestamp);
mRtpSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] getNextFrame() {
byte[] frame = null;
try {
frame = mFrameQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return frame;
}
private void sendBuffer() {
if (mBufferPosition > 0) {
byte[] buffer = new byte[mBufferPosition];
System.arraycopy(mBuffer, 0, buffer, 0, mBufferPosition);
Message message = mHandler.obtainMessage(MSG_SEND_FRAME, buffer);
mHandler.sendMessage(message);
mBufferPosition = 0;
}
}
}
```
这个例子使用了 Android 的 `MediaCodec` 来进行 H.264 编码,然后将编码后的数据传输到 RTP socket 中。在发送 RTP 数据包时,我们构建了一个 `RtpPacket` 对象,并将其发送到指定的 IP 和端口上。
请注意,这个代码示例中缺少错误处理和一些细节,仅用于演示目的。在实际应用中,应该根据需要进行适当的修改和改进。
阅读全文