上篇博客是使用MediaCodec编码摄像头预览数据成h264数据,并用rtp发送实时数据流。这篇博客是接收h264数据流MediaCodec解
上篇博客是使用MediaCodec编码摄像头预览数据成h264数据,并用rtp发送实时数据流。这篇博客是接收h264数据流MediaCodec解码并显示。
先上代码的结构图:
eclipse的工程,接收端比较简单只有两个类
直接上解码部分的代码:
public class ClientTextureView extends TextureView implements TextureView.SurfaceTextureListener{
private static final String MIME_TYPE = "video/avc";
private static final String TAG = "ClientTextureView" ;
private MediaCodec decode;
byte[] rtpData = new byte[80000];
byte[] h264Data = new byte[80000];
int timestamp = 0;
DatagramSocket socket;
public ClientTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
setSurfaceTextureListener(this);
try {
socket = new DatagramSocket(5004);//端口号
socket.setReuseAddress(true);
socket.setBroadcast(true);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
new PreviewThread(new Surface(surface),800,480);//手机的分辨率
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (socket != null){
socket.close();
socket = null;
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
private class PreviewThread extends Thread {
DatagramPacket datagramPacket = null;
public PreviewThread(Surface surface, int width , int height){
Log.e(TAG, "PreviewThread: Gou zhao");
decode = MediaCodec.createDecoderByType(MIME_TYPE);
final MediaFORMat format = MediaFormat.createVideoFormat(MIME_TYPE,width,height);
format.setInteger(MediaFormat.KEY_BIT_RATE, 40000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 20);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
byte[] header_sps = {0, 0, 0, 1, 103, 66, 0 , 41, -115, -115, 64, 80 , 30 , -48 , 15 ,8,-124, 83, -128};
byte[] header_pps = {0,0 ,0, 1, 104, -54, 67, -56};
format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
decode.configure(format,surface,null,0);
decode.start();
start();
}
@Override
public void run() {
byte[] data = new byte[80000];
int h264Length = 0;
while (true){
if (socket != null){
try {
datagramPacket = new DatagramPacket(data,data.length);
socket.receive(datagramPacket);//接收数据
} catch (IOException e) {
e.printStackTrace();
}
}
rtpData = datagramPacket.getData();
if (rtpData != null ){
if (rtpData[0] == -128 && rtpData[1] == 96){
Log.e(TAG, "run:xxx");
int l1 = (rtpData[12]<<24)& 0xff000000;
int l2 = (rtpData[13]<<16)& 0x00ff0000;
int l3 = (rtpData[14]<= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
try{
inputBuffer.put(input, 0, length);
}catch (Exception e){
e.printStackTrace();
}
decode.queueInputBuffer(inputBufferIndex, 0, length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = decode.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
//If a valid surface was specified when configuring the codec,
//passing true renders this output buffer to the surface.
decode.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = decode.dequeueOutputBuffer(bufferInfo, 0);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
MainActivity的代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
源码已经放到GitHub,地址:https://github.com/xmc1715499699/MediaCodec_rtp_receive,欢迎下载star。
--结束END--
本文标题: android硬编码h264数据,并使用rtp推送数据流,实现一个简单的直播-MediaCodec(二)
本文链接: https://lsjlt.com/news/29245.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0