android硬编码h264数据,并使用rtp推送数据流,实现一个简单的直播-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();}}@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {new PreviewThread(new Surface(surface),800,480);//手机的分辨率}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {if (socket != null){socket.close();socket = null;}return false;}@Overridepublic 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();}@Overridepublic 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]<<8) & 0x0000ff00;int l4 = rtpData[15]&0x000000FF;h264Length = l1+l2+l3+l4;Log.e(TAG, "run: h264Length="+h264Length);System.arraycopy(rtpData,16, h264Data,0,h264Length);Log.e(TAG, "run:h264Data[0]="+h264Data[0]+","+h264Data[1]+","+h264Data[2]+","+h264Data[3]+","+h264Data[4]+","+h264Data[5]+","+h264Data[6]+","+h264Data[7]+","+h264Data[8]+","+h264Data[9]+","+h264Data[10]+","+h264Data[11]+","+h264Data[12]+","+h264Data[13]+","+h264Data[14]+","+h264Data[15]+","+h264Data[16]+","+h264Data[17]+","+h264Data[18]+","+h264Data[19]+","+h264Data[20]+","+h264Data[21]+","+h264Data[22]);//打印sps、ppsofferDecoder(h264Data,h264Data.length);Log.e(TAG, "run: offerDecoder=");}}}}}//解码h264数据private void offerDecoder(byte[] input, int length) {Log.d(TAG, "offerDecoder: ");try {ByteBuffer[] inputBuffers = decode.getInputBuffers();int inputBufferIndex = decode.dequeueInputBuffer(0);if (inputBufferIndex >= 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();}}
}
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]<<8) & 0x0000ff00;
int l4 = rtpData[15]&0x000000FF;
h264Length = l1+l2+l3+l4;
Log.e(TAG, "run: h264Length="+h264Length);
System.arraycopy(rtpData,16, h264Data,0,h264Length);
Log.e(TAG, "run:h264Data[0]="+h264Data[0]+","+h264Data[1]+","+h264Data[2]+","+h264Data[3]
+","+h264Data[4]+","+h264Data[5]+","+h264Data[6]+","+h264Data[7]
+","+h264Data[8]+","+h264Data[9]+","+h264Data[10]
+","+h264Data[11]+","+h264Data[12]+","+h264Data[13]
+","+h264Data[14]+","+h264Data[15]+","+h264Data[16]
+","+h264Data[17]+","+h264Data[18]+","+h264Data[19]
+","+h264Data[20]+","+h264Data[21]+","+h264Data[22]);//打印sps、pps
offerDecoder(h264Data,h264Data.length);
Log.e(TAG, "run: offerDecoder=");
}
}
}
}
}//解码h264数据
private void offerDecoder(byte[] input, int length) {
Log.d(TAG, "offerDecoder: ");
try {
ByteBuffer[] inputBuffers = decode.getInputBuffers();
int inputBufferIndex = decode.dequeueInputBuffer(0);
if (inputBufferIndex >= 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 {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}
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。
android硬编码h264数据,并使用rtp推送数据流,实现一个简单的直播-MediaCodec(二)相关推荐
- android 硬编码h264,windows 平台 ffmeg h264 硬编码
本文讲述windows 平台下ffmpeg如何利用intel media SDK 进行 h264硬编码(测试版本为3.2.2). ffmeg硬编编码的流程与软件编码流程相同,唯一不同的地方在初始化en ...
- EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式
EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式 最近在研究EasyDarwin的Push库EasyPusher,EasyPusher可以推送H264视频到 ...
- Android视频编码--H264编码
Android视频编码–H264编码 Android中的H264编码有两种编码方式: 硬编码 软编码 1.硬编码 Android中的H264硬编码主要是通过自身提供的API,调用底层的硬件模块实现编码 ...
- miui7开发版 Android6.0,Android 6.0 MIUI7开发版内测开始推送:
原标题:Android 6.0 MIUI7开发版内测开始推送: 前瞻科技 1 月 7 日讯:Android 6.0 系统推出至今已经有几个月了,小米用户也一直在吐槽基于 Android 6.0 MIU ...
- 友盟小米收不到推送消息_一个轻量级、可插拔的Android消息推送框架。一键集成推送(极光推送、友盟推送、华为、小米推送等)...
XPush 一个轻量级.可插拔的Android消息推送框架.一键集成推送(极光推送.友盟推送.华为.小米推送等),提供有效的保活机制,支持推送的拓展,充分解耦推送和业务逻辑,解放你的双手! 在提iss ...
- 【转】设备数据通过Azure Functions 推送到 Power BI 数据大屏进行展示
设备数据通过Azure Functions 推送到 Power BI 数据大屏进行展示(1.准备工作) 原创 Sean Yu 云计算实战 2019-12-06 本案例适用于开发者入门理解Azure F ...
- android版本10好不好,一加正式推送Android 10系统 流畅性怎么样
近日,一加正式推送Android 10系统,不知道流畅性如何呢? 一加官方推特正式宣布Android 10系统已进行阶段性推送,从今天开始一加7和一加7 Pro手机用户将会陆续收到氧OS系统的更新,国 ...
- 大数据时代的精准推送限制了我们的视野
现在我们处于一个大数据时代,我们的喜好.习惯.每天出入的场所.我们关注的新闻甚至于我们的一切都在被这个大数据时代所监听.亚马逊知道我喜欢读IT类的书,网易云知道我喜欢日系音乐,沃尔玛知道我喜欢甜品,我 ...
- JVM第五讲:纵横数据如何应对洪峰推送
JVM第五讲:纵横数据如何应对洪峰推送 本文是JVM第五讲:纵横数据如何应对洪峰推送.纵横系统最初定位为数据推送平台,用于将公司内部系统的各项业务数据(如:合同.公共.采购计划等)推送至对接的外部第三 ...
- Android集成Huawei PUSH(一)——华为推送服务简介
Android集成Huawei PUSH(一)--华为推送服务简介 一.华为推送服务简介 华为推送服务(Huawei PUSH)是华为为开发者提供的消息推送平台,创建了一条从云端到用户客户端的消息推送 ...
最新文章
- selenium常用命令之操作页面元素及获取元素内容的事件整理
- 如何在Flexbox中垂直对齐文本?
- android_通过高级应用程序开发策略在Android中进行用户参与
- things to do in English debate: scenario
- nginx中的try_files指令解释
- Spring Cloud Zuul –编写过滤器
- JSP Workshop
- HTML5新特征、窍门和技术(16~20)
- ZooKeeper(一)linux上单机与集群的搭建
- android开发之AsyncTask的用法
- C#实现关机的两种方法
- dubbo SPI机制与@Adaptive自适应扩展机制
- Java——图形 继承Shapes(形状)计算周长,面积。
- 古文选读161篇--蔡礼旭老师选
- MyEclipse 9 0正式版官网下载(附Win+Llinux激活方法 汉化包)
- HTML5(李炎恢)学习笔记四 ------------- HTML5元素(中)
- 数论——余数相关定理
- android蓝牙开发 蓝牙设备的查找和连接
- 第一章 使用 matplotlib 绘制折线图
- 基于Spark的电影推荐系统(推荐系统~5)
热门文章
- spring data jpa 出现Not a managed type
- html文件默认浏览器改不了,怎么设置默认浏览器 3种更改默认浏览器方法
- 解决iframe嵌套微信公众号文章图片不显示的方案
- 15s是什么意思c语言,15s是什么意思
- 关于web服务器硬件配置
- IFrame里面的子页面html内容变化时,怎么动态改变IFrame的高度
- 服务器共享文件设成禁止删除,服务器共享文件夹权限 禁止删除共享文件方法...
- ewb交通灯报告和文件_简易交通灯控制逻辑电路设计报告
- 计算机专业助理工程师,计算机助理工程师是职称吗,是什么等级的职称?
- reduce具体使用以及使用reduce,toString,flat进行数组降维