zoukankan      html  css  js  c++  java
  • 【流媒體】 Android 实时视频编码—H.264硬编码


    【流媒體】 Android 实时视频编码—H.264硬编码

    SkySeraph Apr 4th 2012

    Email:skyseraph00@163.com 

     流媒体系列: http://skyseraph.com/2012/04/11/Media/流媒体专题/ 

    1  硬编码 & 软编码

    硬编码:通过调用Android系统自带的Camera录制视频,实际上是调用了底层的高清编码硬件模块,也即显卡,不使用CPU,速度快

    软编码:使用CPU进行编码,如常见C/C++代码,一般编译生成的二进制都是的,速度相对较慢。例如使用Android NDK编译H264生成so库,编写jni接口,再使用java调用so库。

     


    2  原理

    ① 过程:通过MediaRecoder采集视频,再将视频流映射到LocalSocket实现收发

    ② 原理:详见【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流 和  “【流媒體】Android 实时视频采集—MediaRecoder录制 ” 

     


    3 核心代码

    MediaRecoder视频采集

     视频采集采用了MediaRecorde录制方式,详见 “【流媒體】Android 实时视频采集—MediaRecoder录制 ”

     

    ② 在initiativeVideosetOutputFile设置以流方式输出

     

                // 设置输出文件方式: 直接本地存储   or LocalSocket远程输出        
    if (bIfNativeORRemote == true) // Native
    {
    lVideoFileFullPath = strRecVideoFilePath + String.valueOf(System.currentTimeMillis())
    + lVideoFileFullPath;
    mRecVideoFile = new File(lVideoFileFullPath);
    // mMediaRecorder.setOutputFile(mRecVideoFile.getAbsolutePath());
    mMediaRecorder.setOutputFile(mRecVideoFile.getPath()); // called after set**Source before prepare
    Log.i(TAG, "start write into file~");
    }
    else // Remote
    {
    mMediaRecorder.setOutputFile(sender.getFileDescriptor()); // 设置以流方式输出
    Log.i(TAG, "start send into sender~");
    }

    startRecording

    功能:通过这个函数启动线程实现视频流映射到LocalSocket,同时实现编码

        private void startRecording()
    {
    Log.i(TAG, "##startRecording....");
    new Thread(this).start();
    }

    run:

    @Override
    public void run()
    {
    Log.i(TAG, "##run....");

    // defines
    DataInputStream dataInputStream = null;
    int offSet=0,tmp=0,beLeft=0;

    try
    {
    dataInputStream = new DataInputStream(receiver.getInputStream());
    } catch (IOException e2)
    {
    // TODO Auto-generated catch block
    e2.printStackTrace();
    }
    try
    {
    Thread.currentThread().sleep(500);
    } catch (InterruptedException e1)
    {
    e1.printStackTrace();
    }

    // ①方式一:通过查看预先录制的视频,需要跳过mdat前面32个字节(不同硬件平台不同!)
    try
    {
    dataInputStream.read(h264frame, 0, 32);
    Log.i(TAG, "read mdat from");
    } catch (IOException e1)
    {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }
    // ②方式二:自动化查找(待补充)


    try
    {
    h264FileOutputStream = new FileOutputStream("/sdcard/avss/h264.264");//264码流
    Log.i(TAG, "h264FileOutputStream");
    } catch (FileNotFoundException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    try
    {
    h264FileOutputStream.write(h264head);
    h264FileOutputStream.write(h264sps);
    h264FileOutputStream.write(h264head);
    h264FileOutputStream.write(h264pps);
    Log.i(TAG, "run-write SPS/PPS to file");
    } catch (IOException e1)
    {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }

    while (bIfRecInProcess && (!bIfNativeORRemote))
    {
    try
    {
    Log.i(TAG, "**while...");
    int h264length = dataInputStream.readInt();
    Log.i(TAG, "h264length:"+h264length);
    tmp=0; offSet = 0; beLeft = 0;

    h264FileOutputStream.write(h264head);
    while (offSet < h264length)
    {
    beLeft = h264length - offSet;
    tmp = dataInputStream.read(h264frame, 0, READ_SIZE < beLeft ? READ_SIZE : beLeft);
    Log.i(TAG, String.format("H264 %d,%d,%d", h264length, offSet, tmp));
    offSet += tmp;
    h264FileOutputStream.write(h264frame, 0, tmp);
    }

    } catch (Exception e)
    {
    // TODO: handle exception
    e.printStackTrace();
    }
    }
    //
    }

     


    4 Ref/Related

    http://blog.csdn.net/zblue78/article/details/6078040

    2 http://blog.csdn.net/zblue78/article/details/6083374

    3 http://www.docin.com/p-282454756.html

    4 http://blog.csdn.net/qwertyuj/article/details/7029836

    5 http://www.cnblogs.com/skyseraph/archive/2012/03/31/2427593.html

    6 http://www.cnblogs.com/skyseraph/archive/2012/03/23/2415018.html

    7 http://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.html

     

     


    作者:skyseraph
    出处:http://www.cnblogs.com/skyseraph/
    更多精彩请直接访问SkySeraph个人站点:http://skyseraph.com//
    Email/GTalk: zgzhaobo@gmail.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Java中File类的使用
    Java集合中Comparator和Comparable接口的使用
    ODP.NET
    DllImport
    .net 项目与网站区别
    sqlserver 2012 分页
    sqlserver 分页
    ORACLE 中ROWNUM
    mysql 分页优化
    mysql windows 安装
  • 原文地址:https://www.cnblogs.com/skyseraph/p/2431771.html
Copyright © 2011-2022 走看看