car-eye 车载流媒体开发中数据采集和编码传输

车载流媒体作为一个热点越来越引起大家的重视,car-eye 行车记录仪,是基于RTSP协议开发的开源android程序,支持最多四路视频录像,支持最多四路视频上传。传输视频采用RTSP协议。首先我们介绍一下,视频数据从摄像头获取到编码,到传输给流媒体服务器的过程:

1. 摄像头数据通过priewcallback获得数据为YV12的数据

设置好基本的预览的参数:

parameters.setPreviewSize(Constants.RECORD_VIDEO_WIDTH, Constants.RECORD_VIDEO_HEIGHT);

parameters.setPreviewFpsRange(20,20);

camera[index].startPreview();

在需要数据的时候打开预览callback:

camera[index].setPreviewCallback(preview[index]);

preview[0] = new PreviewCallback() {

  
@Override
public void onPreviewFrame(byte[] data, Camera camera1) {
// TODO Auto-generated method stub
MediaCodecManager.getInstance().onPreviewFrameUpload(data,0,camera[0]);
}
};

public void onPreviewFrameUpload(byte[] data,int index,Camera camera){

 if (data == null ) {
camera.addCallbackBuffer(data);
         return;
     }
     Camera.Size previewSize = camera.getParameters().getPreviewSize();
     if (data.length != Constants.UPLOAD_VIDEO_HEIGHT * Constants.UPLOAD_VIDEO_WIDTH * 3 / 2) {
    camera.addCallbackBuffer(data);
    Log.d("CMD", " onPreviewFrameUpload return"+data.length);
         return;
     }   
     MainService.getInstance().SetPreviewValid(index);
     
     if(mVC[index]!= null)
     {
    mVC[index].onVideo(data, previewFormat);
    
     }else
     {   
    camera.setPreviewCallback(null);    
     }
     camera.addCallbackBuffer(data);      
 }


}

2. 讲H264的数据流,传输到编码器进行编码传输:

 public int onVideo(byte[] data, int format) {
        if (!mVideoStarted)return 0;        
inputBuffers = mMediaCodec.getInputBuffers();
outputBuffers = mMediaCodec.getOutputBuffers();
        int bufferIndex = mMediaCodec.dequeueInputBuffer(0);        
       // MainService.mEasyPusher.addwatermarkScale(data, Scaler, data.length,Constants.RECORD_VIDEO_WIDTH,Constants.RECORD_VIDEO_HEIGHT,Constants.UPLOAD_VIDEO_WIDTH,Constants.UPLOAD_VIDEO_HEIGHT);
if (bufferIndex >= 0) {
   ByteBuffer buffer = null;
   buffer = inputBuffers[bufferIndex];  
   buffer.clear();
   buffer.put(data);
   buffer.clear();
   mMediaCodec.queueInputBuffer(bufferIndex, 0, data.length, System.nanoTime() / 1000, 0);
}
         /*if (time > 0)
try {
Thread.sleep(time / 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lastPush = System.currentTimeMillis();*/
        return 0;
    }


    @Override
    public void run(){
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        int outputBufferIndex = 0;
        byte[] mPpsSps = new byte[0];
        byte[]h264 = new byte[mWidth*mHeight*3/2];        


        do {
            outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 30000);
            if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
                // no output available yet
            } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                // not expected for an encoder
            } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
               /* EasyMuxer muxer = mMuxer;
                if (muxer != null) {
                    // should happen before receiving buffers, and should only happen once
                    MediaFormat newFormat = mMediaCodec.getOutputFormat();
                    muxer.addTrack(newFormat, true);
                }*/
            } else if (outputBufferIndex < 0) {
                // let's ignore it
            } else {
                ByteBuffer outputBuffer;
                outputBuffer = outputBuffers[outputBufferIndex];        
                EasyMuxer muxer = mMuxer;
                if (muxer != null) {
                    muxer.pumpStream(outputBuffer, bufferInfo, true);
                }
                boolean sync = false;
                if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {// sps
                    sync = (bufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
                    if (!sync) {
                        byte[] temp = new byte[bufferInfo.size];
                        outputBuffer.get(temp);
                        mPpsSps = temp;
                        mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                        continue;
                    } else {
                        mPpsSps = new byte[0];
                    }
                }
                sync |= (bufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
                int len = mPpsSps.length + bufferInfo.size;
                if (len > h264.length){
                    h264 = new byte[len];
                }
                if (sync) {
                 System.arraycopy(mPpsSps, 0, h264, 0, mPpsSps.length);
                      outputBuffer.get(h264, mPpsSps.length, bufferInfo.size); 
                      int Time =(int)( ( bufferInfo.presentationTimeUs / 1000) &0xffffff);
                      mPusher.SendBuffer(0, h264,  mPpsSps.length + bufferInfo.size, 0, m_index); 
                      
                   }else{
                  int Time =(int)( ( bufferInfo.presentationTimeUs / 1000) &0xffffff);                                   
                      outputBuffer.get(h264, 0, bufferInfo.size);  
                      mPusher.SendBuffer(0, h264,  bufferInfo.size, 0, m_index);                      
                      
                  }


                mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
            }
        }
        while (mVideoStarted);
    }

其中 mPusher.SendBuffer(0, h264,  mPpsSps.length + bufferInfo.size, 0, m_index); 讲获得H264的流传输到多媒体平台。

相关代码下载car-eye开源平台网址:https://github.com/Car-eye-admin/  有关技术咨询可以加群590411159。 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android非凡行车记录仪源码,适用于所有类似行车记录仪的应用,包含后台录像、录音等强大功能。录像方案有基于camera2的实现、基于opengles的实现,非常适合相关项目开发者进行参考和复用,也可直接基于此项目进行二次开发。 此APP已经上架到华为应用商城,链接https://appgallery.huawei.com/#/app/C101080713,大家可以去看看。 如需答疑,请在csdn上给我留言。 应用简介: 这是一个非常好用的行车记录仪APP,当然除了行车记录外,也可用于日常的录像录音。主要功能有 1. 录音录像及拍照 此APP支持后台录音录像,所以不需要再录音录像时请及时停止录像,录音录像都可设置分段时间,可根据自行设置; 2. 文件浏览 录音录像及拍照文件会存储在本机上,可在文件浏览界面查看。如需要批量删除文件,请到设置里面删除; 3. 轨迹回放 如果设置的GPS开关处于打开状态,那么在录像时,APP就会定时记下当前位置,并绑定到对应录像文件的对应时间点上,点击地图上的坐标点,可跳转到对应视频的对应时间点开始进行播放; 4. 文件清理 APP每次启动时,都会自动检测过期文件和剩余存储空间大小,如有过期文件或存储空间不足,则自动进行文件删除操作。默认优先删除非重点文件,在剩余存储空间不足时,重点文件也会被删除。如果存储空间不足,那么即使文件没过期,也会被自动删除,请及时将重要文件拷贝到PC等其他地方保存; 5. 视频剪辑 可对手机上的视频进行任意裁剪,裁剪的视频可应用多种滤镜效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值