实时视频相关
来源:互联网 发布:听新闻软件 编辑:程序博客网 时间:2024/05/17 07:08
原文地址:http://www.apkbus.com/blog-86476-43829.html
废话不说直接贴代码,看不懂代码的同志可以参考:
http://blog.csdn.net/zblue78/article/details/6078040
http://blog.csdn.net/zblue78/article/details/6058147
这两篇讲的比较详细,不过他的代码我没有跑通。下面贴出我跑通的代码:
CSDN代码地址,能正常运行:http://download.csdn.net/detail/cooler126/5777745
上一篇文章进行了思路和16进制文件的分析。这篇该代码实现了。目前没有在真实手机上测试, android4.0之后的模拟器可以用模拟摄像头或者叫做webcam的【其实就是笔记本摄像头】。之后会在程序安装包data/data/edu.ustb.videoencoder/下面会有h264.3gp,sps【存放sps数据】、pps【存放pps数据】、media.xml【存放找到mdat的位置】,/sdcard/encoder.h264【这个文件就是编码后的h264文件】。
不多说,上源码。
[代码]:AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="edu.ustb.videoencoder" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
[主程序代码]MainActivity.java:
package edu.ustb.videoencoder;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.RandomAccessFile;import android.media.MediaRecorder;import android.net.LocalServerSocket;import android.net.LocalSocket;import android.net.LocalSocketAddress;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;import android.util.Log;import android.view.Menu;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;public class MainActivity extends Activity implements Callback, Runnable{private static final String TAG = "VideoCamera"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InitSurfaceView(); InitMediaSharePreference(); } //初始化SurfaceView private SurfaceView mSurfaceView;private void InitSurfaceView() {mSurfaceView = (SurfaceView) this.findViewById(R.id.surface_camera);SurfaceHolder holder = mSurfaceView.getHolder();holder.addCallback(this);holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);mSurfaceView.setVisibility(View.VISIBLE);}//初始化,记录mdat开始位置的参数SharedPreferences sharedPreferences;private final String mediaShare = "media"; private void InitMediaSharePreference() {sharedPreferences = this.getSharedPreferences(mediaShare, MODE_PRIVATE);} private SurfaceHolder mSurfaceHolder; private boolean mMediaRecorderRecording = false; public void surfaceCreated(SurfaceHolder holder) {mSurfaceHolder = holder;}public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {mSurfaceHolder = holder;if(!mMediaRecorderRecording) {InitLocalSocket();getSPSAndPPS();initializeVideo();startVideoRecording();}}public void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stub}//初始化LocalServerSocket LocalSocketLocalServerSocket lss;LocalSocket receiver, sender;private void InitLocalSocket(){try {lss = new LocalServerSocket("H264");receiver = new LocalSocket();receiver.connect(new LocalSocketAddress("H264"));receiver.setReceiveBufferSize(500000);receiver.setSendBufferSize(50000);sender = lss.accept();sender.setReceiveBufferSize(500000);sender.setSendBufferSize(50000);} catch (IOException e) {Log.e(TAG, e.toString());this.finish();return;}}//得到序列参数集SPS和图像参数集PPS,如果已经存储在本地private void getSPSAndPPS(){StartMdatPlace = sharedPreferences.getInt(String.format("mdata_%d%d.mdat", videoWidth, videoHeight), -1);if(StartMdatPlace != -1) {byte[] temp = new byte[100];try {FileInputStream file_in = MainActivity.this.openFileInput(String.format("%d%d.sps", videoWidth,videoHeight));int index = 0;int read=0;while(true){read = file_in.read(temp,index,10);if(read==-1) break;else index += read;}Log.e(TAG, "sps length:"+index);SPS = new byte[index];System.arraycopy(temp, 0, SPS, 0, index); file_in.close();index =0;//read PPSfile_in = MainActivity.this.openFileInput(String.format("%d%d.pps", videoWidth,videoHeight));while(true){read = file_in.read(temp,index,10);if(read==-1) break;else index+=read;}Log.e(TAG, "pps length:"+index);PPS = new byte[index];System.arraycopy(temp, 0, PPS, 0, index);} catch (FileNotFoundException e) {//e.printStackTrace();Log.e(TAG, e.toString());} catch (IOException e) {//e.printStackTrace();Log.e(TAG, e.toString());}} else {SPS = null;PPS = null;}}//初始化MediaRecorderprivate MediaRecorder mMediaRecorder = null;private int videoWidth = 320;private int videoHeight = 240;private int videoRate = 10;private String fd = "data/data/edu.ustb.videoencoder/h264.3gp";private boolean initializeVideo(){if(mSurfaceHolder == null) {return false;}mMediaRecorderRecording = true;if(mMediaRecorder == null) {mMediaRecorder = new MediaRecorder();} else {mMediaRecorder.reset();}mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mMediaRecorder.setVideoFrameRate(videoRate);mMediaRecorder.setVideoSize(videoWidth, videoHeight);mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());mMediaRecorder.setMaxDuration(0);mMediaRecorder.setMaxFileSize(0);if(SPS==null){mMediaRecorder.setOutputFile(fd);}else{mMediaRecorder.setOutputFile(sender.getFileDescriptor());}try {mMediaRecorder.prepare();mMediaRecorder.start();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();releaseMediaRecorder();}return true;}//释放MediaRecorder资源private void releaseMediaRecorder(){if(mMediaRecorder != null) {if(mMediaRecorderRecording) {mMediaRecorder.stop();mMediaRecorderRecording = false;}mMediaRecorder.reset();mMediaRecorder.release();mMediaRecorder = null;}}//开始录像,启动线程private void startVideoRecording() {new Thread(this).start();}private final int MAXFRAMEBUFFER = 20480;//20Kprivate byte[] h264frame = new byte[MAXFRAMEBUFFER];private final byte[] head = new byte[]{0x00,0x00,0x00,0x01};private RandomAccessFile file_test;public void run() {try {if(SPS == null) {Log.e(TAG, "Rlease MediaRecorder and get SPS and PPS");Thread.sleep(1000);//释放MediaRecorder资源releaseMediaRecorder();//从已采集的视频数据中获取SPS和PPSfindSPSAndPPS();//找到后重新初始化MediaRecorderinitializeVideo();}DataInputStream dataInput = new DataInputStream(receiver.getInputStream());//先读取ftpy box and mdat box, 目的是skip ftpy and mdat data,(decisbe by phone)dataInput.read(h264frame, 0, StartMdatPlace);try {File file = new File("/sdcard/encoder.h264");if (file.exists())file.delete();file_test = new RandomAccessFile(file, "rw");} catch (Exception ex) {Log.v("System.out", ex.toString());}file_test.write(head);file_test.write(SPS);//write spsfile_test.write(head);file_test.write(PPS);//write ppsint h264length =0;while(mMediaRecorderRecording) {h264length = dataInput.readInt();Log.e(TAG, "h264 length :" + h264length);//int number=0 , num=0;//int frame_size = 1024;//file_test.write(head);//while(number<h264length)//{//int lost=h264length-number;//num = dataInput.read(h264frame,0,frame_size<lost?frame_size:lost);//Log.d(TAG,String.format("H264 %d,%d,%d", h264length,number,num));//number+=num;//file_test.write(h264frame, 0, num);//}ReadSize(h264length, dataInput);byte[] h264 = new byte[h264length];System.arraycopy(h264frame, 0, h264, 0, h264length);file_test.write(head);file_test.write(h264);//write selice} file_test.close();} catch (Exception e) {e.printStackTrace();}}private void ReadSize(int h264length,DataInputStream dataInput) throws IOException, InterruptedException{int read = 0;int temp = 0;while(read<h264length){temp= dataInput.read(h264frame, read, h264length-read);Log.e(TAG, String.format("h264frame %d,%d,%d", h264length,read,h264length-read));if(temp==-1){Log.e(TAG, "no data get wait for data coming.....");Thread.sleep(2000);continue;}read += temp;}}//从 fd文件中找到SPS And PPSprivate byte[] SPS;private byte[] PPS;private int StartMdatPlace = 0;private void findSPSAndPPS() throws Exception{File file = new File(fd);FileInputStream fileInput = new FileInputStream(file);int length = (int)file.length();byte[] data = new byte[length];fileInput.read(data);final byte[] mdat = new byte[]{0x6D,0x64,0x61,0x74};final byte[] avcc = new byte[]{0x61,0x76,0x63,0x43};for(int i=0 ; i<length; i++){if(data[i] == mdat[0] && data[i+1] == mdat[1] && data[i+2] == mdat[2] && data[i+3] == mdat[3]){StartMdatPlace = i+4;//find mdatbreak;}}Log.e(TAG, "StartMdatPlace:"+StartMdatPlace);//记录到xml文件里String mdatStr = String.format("mdata_%d%d.mdat",videoWidth,videoHeight);Editor editor = sharedPreferences.edit();editor.putInt(mdatStr, StartMdatPlace);editor.commit();for(int i=0 ; i<length; i++){if(data[i] == avcc[0] && data[i+1] == avcc[1] && data[i+2] == avcc[2] && data[i+3] == avcc[3]){int sps_start = i+3+7;//其中i+3指到avcc的c,再加7跳过6位AVCDecoderConfigurationRecord参数//sps length and sps databyte[] sps_3gp = new byte[2];//sps lengthsps_3gp[1] = data[sps_start];sps_3gp[0] = data[sps_start + 1];int sps_length = bytes2short(sps_3gp);Log.e(TAG, "sps_length :" + sps_length);sps_start += 2;//skip lengthSPS = new byte[sps_length];System.arraycopy(data, sps_start, SPS, 0, sps_length);//save spsFileOutputStream file_out = MainActivity.this.openFileOutput(String.format("%d%d.sps",videoWidth,videoHeight), Context.MODE_PRIVATE);file_out.write(SPS);file_out.close();//pps length and pps dataint pps_start = sps_start + sps_length + 1;byte[] pps_3gp =new byte[2];pps_3gp[1] = data[pps_start];pps_3gp[0] =data[pps_start+1];int pps_length = bytes2short(pps_3gp);Log.e(TAG, "PPS LENGTH:"+pps_length);pps_start+=2;PPS = new byte[pps_length];System.arraycopy(data, pps_start, PPS,0,pps_length);//Save PPSfile_out = MainActivity.this.openFileOutput(String.format("%d%d.pps",videoWidth,videoHeight),Context.MODE_PRIVATE);file_out.write(PPS);file_out.close();break;}}}//计算长度public short bytes2short(byte[] b) { short mask=0xff; short temp=0; short res=0; for(int i=0;i<2;i++) { res<<=8; temp=(short)(b[1-i]&mask); res|=temp; } return res; }@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; }@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();if(mMediaRecorderRecording){releaseMediaRecorder();try {lss.close();receiver.close();sender.close();} catch (IOException e) {Log.e(TAG, e.toString());}mMediaRecorderRecording = false;}finish();}}
阅读全文
0 0
- 实时视频相关
- (视频相关)Android手机间通过Socket,Udp实时传输视频
- 实时视频抠像
- 视频实时抠像
- 实时视频网站架构
- Android 实时视频采集
- Android视频实时传输
- 视频实时数据
- ffmpeg 网络实时视频
- RTP视频实时传输
- 视频实时滤镜
- 实时音视频效果
- android 实时视频采集
- 实时视频流
- 实时音视频
- 点对点视频实时传输
- MFC2-实时读取视频
- Android视频实时传输
- 主机上使用b-link无线网卡无法连接WiFi
- wc
- 局部立体匹配算法BM中的匹配代价聚合方法
- 谷歌浏览器页面卡死的时候:快捷键Shift+Esc来了
- MyBatis解决Update动态SQL逗号的问题
- 实时视频相关
- CSS控制列表样式属性list-style有哪些?怎么用?
- Dubbo系列(十一)Dubbo应用之集群服务
- Eclipse中导入SVN库里的Maven项目
- 流、浮动和定位
- android自定义view之 判断一个点是否在制定矩形内
- (测试通过)Capture NX2破解方法
- tinker第1部-集成
- 数据分析,我该想些什么-以共享单车为例