上篇博客是使用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(二)相关推荐

  1. android 硬编码h264,windows 平台 ffmeg h264 硬编码

    本文讲述windows 平台下ffmpeg如何利用intel media SDK 进行 h264硬编码(测试版本为3.2.2). ffmeg硬编编码的流程与软件编码流程相同,唯一不同的地方在初始化en ...

  2. EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式

    EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式 最近在研究EasyDarwin的Push库EasyPusher,EasyPusher可以推送H264视频到 ...

  3. Android视频编码--H264编码

    Android视频编码–H264编码 Android中的H264编码有两种编码方式: 硬编码 软编码 1.硬编码 Android中的H264硬编码主要是通过自身提供的API,调用底层的硬件模块实现编码 ...

  4. miui7开发版 Android6.0,Android 6.0 MIUI7开发版内测开始推送:

    原标题:Android 6.0 MIUI7开发版内测开始推送: 前瞻科技 1 月 7 日讯:Android 6.0 系统推出至今已经有几个月了,小米用户也一直在吐槽基于 Android 6.0 MIU ...

  5. 友盟小米收不到推送消息_一个轻量级、可插拔的Android消息推送框架。一键集成推送(极光推送、友盟推送、华为、小米推送等)...

    XPush 一个轻量级.可插拔的Android消息推送框架.一键集成推送(极光推送.友盟推送.华为.小米推送等),提供有效的保活机制,支持推送的拓展,充分解耦推送和业务逻辑,解放你的双手! 在提iss ...

  6. 【转】设备数据通过Azure Functions 推送到 Power BI 数据大屏进行展示

    设备数据通过Azure Functions 推送到 Power BI 数据大屏进行展示(1.准备工作) 原创 Sean Yu 云计算实战 2019-12-06 本案例适用于开发者入门理解Azure F ...

  7. android版本10好不好,一加正式推送Android 10系统 流畅性怎么样

    近日,一加正式推送Android 10系统,不知道流畅性如何呢? 一加官方推特正式宣布Android 10系统已进行阶段性推送,从今天开始一加7和一加7 Pro手机用户将会陆续收到氧OS系统的更新,国 ...

  8. 大数据时代的精准推送限制了我们的视野

    现在我们处于一个大数据时代,我们的喜好.习惯.每天出入的场所.我们关注的新闻甚至于我们的一切都在被这个大数据时代所监听.亚马逊知道我喜欢读IT类的书,网易云知道我喜欢日系音乐,沃尔玛知道我喜欢甜品,我 ...

  9. JVM第五讲:纵横数据如何应对洪峰推送

    JVM第五讲:纵横数据如何应对洪峰推送 本文是JVM第五讲:纵横数据如何应对洪峰推送.纵横系统最初定位为数据推送平台,用于将公司内部系统的各项业务数据(如:合同.公共.采购计划等)推送至对接的外部第三 ...

  10. Android集成Huawei PUSH(一)——华为推送服务简介

    Android集成Huawei PUSH(一)--华为推送服务简介 一.华为推送服务简介 华为推送服务(Huawei PUSH)是华为为开发者提供的消息推送平台,创建了一条从云端到用户客户端的消息推送 ...

最新文章

  1. selenium常用命令之操作页面元素及获取元素内容的事件整理
  2. 如何在Flexbox中垂直对齐文本?
  3. android_通过高级应用程序开发策略在Android中进行用户参与
  4. things to do in English debate: scenario
  5. nginx中的try_files指令解释
  6. Spring Cloud Zuul –编写过滤器
  7. JSP Workshop
  8. HTML5新特征、窍门和技术(16~20)
  9. ZooKeeper(一)linux上单机与集群的搭建
  10. android开发之AsyncTask的用法
  11. C#实现关机的两种方法
  12. dubbo SPI机制与@Adaptive自适应扩展机制
  13. Java——图形 继承Shapes(形状)计算周长,面积。
  14. 古文选读161篇--蔡礼旭老师选
  15. MyEclipse 9 0正式版官网下载(附Win+Llinux激活方法 汉化包)
  16. HTML5(李炎恢)学习笔记四 ------------- HTML5元素(中)
  17. 数论——余数相关定理
  18. android蓝牙开发 蓝牙设备的查找和连接
  19. 第一章 使用 matplotlib 绘制折线图
  20. 基于Spark的电影推荐系统(推荐系统~5)

热门文章

  1. spring data jpa 出现Not a managed type
  2. html文件默认浏览器改不了,怎么设置默认浏览器 3种更改默认浏览器方法
  3. 解决iframe嵌套微信公众号文章图片不显示的方案
  4. 15s是什么意思c语言,15s是什么意思
  5. 关于web服务器硬件配置
  6. IFrame里面的子页面html内容变化时,怎么动态改变IFrame的高度
  7. 服务器共享文件设成禁止删除,服务器共享文件夹权限 禁止删除共享文件方法...
  8. ewb交通灯报告和文件_简易交通灯控制逻辑电路设计报告
  9. 计算机专业助理工程师,计算机助理工程师是职称吗,是什么等级的职称?
  10. reduce具体使用以及使用reduce,toString,flat进行数组降维