android mediarecorder 录制音频并通过socket,存储到本地

来源:互联网 发布:c语言全排列函数 编辑:程序博客网 时间:2024/05/15 14:58

原文地址: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();}}


原创粉丝点击