MediaRecoder分别获取音频、视频保存本地

package com.example.getaac264ts;

import java.io.BufferedOutputStream;
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.InputStream;
import java.io.RandomAccessFile;


import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
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.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements Callback, Runnable{

	private static final String TAG = "H264_AAC";
	private Camera mCamera;
	Button sendButton;
	Button receivedButton;
	//初始化MediaRecorder
		private MediaRecorder mMediaRecorder = null;
		//private int videoWidth = 1280;
		//private int videoHeight = 720;
		private int videoWidth = 640;
		private int videoHeight = 480;
		private int videoRate = 25;	
		private String fd = "/sdcard/MediaRecorder/videotest.3gp";
		 private SurfaceView mSurfaceView;
		 private SurfaceHolder mSurfaceHolder;
		    private boolean mMediaRecorderRecording = false;
		    LocalServerSocket lss;
			LocalSocket receiver, sender;
			private final int MAXFRAMEBUFFER = 20480;//20K
			private byte[] h264frame = new byte[MAXFRAMEBUFFER];
			private final byte[] head = new byte[]{0x00,0x00,0x00,0x01};
			private RandomAccessFile file_test;
			private byte[] SPS;
			private byte[] PPS;
			private int StartMdatPlace = 0;

	
	
	public MediaRecorder mediarecorder;
	public LocalSocket senderaac;
	public LocalSocket receivedaac;
	public LocalServerSocket lssaac;
	public static final int BUFFER_SIZE=5000;
	public InputStream inputStream;
	public Recoder recoder;
	byte[] buffer;
	public BufferedOutputStream bufferedoutstream;
	public RandomAccessFile raf;
	public boolean ISrunning;
	public Thread getAudio;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
   
        sendButton=(Button)findViewById(R.id.start);
		receivedButton=(Button)findViewById(R.id.stop);
        InitSurfaceView();
        InitMediaSharePreference();
        
        
        sendButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Log.e("fdsa", "start button.....");
				ISrunning=true;
				recoder=new Recoder();
				recoder.start();
				Log.e("fdsfd", "before the MediaRorder Init");
				MediaRecoderInit();	
				Log.e("fdsfd", "after the MediaRorder Init");
				getAudio=new GetAudio();
				getAudio.start();
			}
		});
		
        
		receivedButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Log.e("fdsa", "stop the recording...");
				ISrunning=false;
				if (recoder!=null) {
					recoder.interrupt();
				}
				if(mediarecorder!=null){
					mediarecorder.stop();
					mediarecorder.release();
					mediarecorder=null;
				}
				if (inputStream!=null) {
					try {
						inputStream.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					inputStream=null;
				}
				
			}
		});
    }

    
    //初始化SurfaceView  
	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);		
	}


   
    
	public void surfaceCreated(SurfaceHolder holder) {
		mSurfaceHolder = holder;
		initPreview();
	}

	
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		mSurfaceHolder = holder;
		if(!mMediaRecorderRecording) {
			InitLocalSocket();
			Log.i(TAG, "before getSPSAndPPS()");
			getSPSAndPPS();
			initializeVideo();
			startVideoRecording();
		}
		
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		mCamera.stopPreview();
		mCamera.release();
		mCamera = null;
        mSurfaceHolder = null;
	}
	
	
	//初始化LocalServerSocket LocalSocket
	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);
		Log.e(TAG, "StartMdatPlace---->"+StartMdatPlace);
		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, "=====get sps length:"+index);
				SPS = new byte[index];
				System.arraycopy(temp, 0, SPS, 0, index);
				               
				file_in.close();
				
				index =0;
				//read PPS
				file_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, "==========get 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 {
			Log.e(TAG,"==============StartMdatPlace = -1");
			SPS = null;
			PPS = null;
		}
	}
	
	
	
	private boolean initializeVideo(){
		if(mSurfaceHolder == null) {
			return false;
		}
		mCamera.unlock();
		mMediaRecorderRecording = true;
		
		if(mMediaRecorder == null) {
			
			mMediaRecorder = new MediaRecorder();
		} else {
			mMediaRecorder.reset();
		}
		
		mMediaRecorder.setCamera(mCamera);
		
		mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
		//mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
		
		
		mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
		
		mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
		
		//mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
		mMediaRecorder.setVideoSize(videoWidth, videoHeight);
		
		mMediaRecorder.setVideoFrameRate(videoRate);
		
		mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
		
		mMediaRecorder.setMaxDuration(0);
		
		mMediaRecorder.setMaxFileSize(0);
		if(SPS==null)
		{
			Log.e(TAG, "==============  SPS  is null!!!!!!!!!!");
			mMediaRecorder.setOutputFile(fd);
		}
		else
		{
			Log.e(TAG,"=============== SPS have value!!!!!!!");
			mMediaRecorder.setOutputFile(sender.getFileDescriptor());
		}
		Log.i(TAG, "&&&&&&&&&&&&");
		try {
			mMediaRecorder.prepare();
			Log.i(TAG, "before start()");
			mMediaRecorder.start();
			Log.i(TAG, "after start()");
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
			releaseMediaRecorder();
		}
		Log.e(TAG, "chu shi hua MediaRecoder chen gong");
		return true;
	}

	//释放MediaRecorder资源
	private void releaseMediaRecorder(){
		if(mMediaRecorder != null) {
			if(mMediaRecorderRecording) {
				mMediaRecorder.stop();
				mMediaRecorderRecording = false;
			}
			mMediaRecorder.reset();
			mMediaRecorder.release();
			mMediaRecorder = null;
			Log.i(TAG, "releaseMediaRecoder...");
		}
	}
	
	//开始录像,启动线程
	private void startVideoRecording() {
		new Thread(this).start();
	}
	
	
	public void run() {
		try {
			
			if(SPS == null) {
				Log.e(TAG, "Rlease MediaRecorder and get SPS and PPS");
				Thread.sleep(1000);
				//释放MediaRecorder资源
				releaseMediaRecorder();
				//从已采集的视频数据中获取SPS和PPS
				findSPSAndPPS();
				//找到后重新初始化MediaRecorder
				initializeVideo();
			}			
			
			DataInputStream dataInput = new DataInputStream(receiver.getInputStream());
			//先读取ftpy box and mdat box, 目的是skip ftpy and mdat data,(decisbe by phone)
			Log.e(TAG,"=============StartMdatPlace :" + StartMdatPlace);
			//dataInput.read(h264frame, 0, StartMdatPlace);
			dataInput.read(h264frame, 0, 28);
			dataInput.skipBytes(16);
			
			try {
				File file = new File("/sdcard/MediaRecorder/MediaRecorder.264");
				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 sps
			
			file_test.write(head);
			file_test.write(PPS);//write pps
			
			int 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);
//				Log.e(TAG, "h264length-->"+h264length);
//				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 PPS
	
	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 mdat
				break;
			}
		}
		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 data
				byte[] sps_3gp = new byte[2];//sps length
				sps_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 length
				SPS = new byte[sps_length];
				System.arraycopy(data, sps_start, SPS, 0, sps_length);
				for(int si=0;si<sps_length;si++)
				Log.e(TAG, "==========SPS :" + si + SPS[si]);
				//save sps
				FileOutputStream 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 data
				int 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);
				for (int pi =0;pi<pps_length;pi++)
				   Log.e(TAG, "==========PPS :" +pi + PPS[pi]);
				
				//Save PPS
				file_out = MainActivity.this.openFileOutput(
						String.format("%d%d.pps",videoWidth,videoHeight),
						Context.MODE_PRIVATE);
				file_out.write(PPS);
				file_out.close();
				Log.e(TAG, "==========SPS :" + SPS+ ",  PPS :" +PPS);
				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
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		if(mMediaRecorderRecording)
		{
			releaseMediaRecorder();
			
			try {
				lssaac.close();
				receiver.close();
				sender.close();
			} catch (IOException e) {
				Log.e(TAG, e.toString());
			}
			
			mMediaRecorderRecording = false;
		}
		finish();
	}

	
	 private void initPreview()
	    {
	        //mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
		 	mCamera = Camera.open();
	        Camera.Parameters parameters = mCamera.getParameters();
	        // size = parameters.getPreviewSize();

	        mCamera.setDisplayOrientation(90);

	        try
	        {
	            mCamera.setPreviewDisplay(mSurfaceHolder);
	        }
	        catch (IOException e)
	        {
	            e.printStackTrace();
	        }

	        mCamera.startPreview();
	    }

	    private void releaseCamera()
	    {
	        if (null != mCamera)
	        {
	            mCamera.stopPreview();
	            mCamera.release();
	            mCamera = null;
	        }
	    }
	
	    /*****************音频采集**********************/

	    	
	 public void MediaRecoderInit(){//设置参数
	    		
	    		//设置MediaRecoder
	    		File file=new File("/sdcard/kaifa/getaac/LocalSocket.aac");
	    		try {
	    			raf=new RandomAccessFile(file, "rw");
	    		} catch (FileNotFoundException e1) {
	    			// TODO Auto-generated catch block
	    			e1.printStackTrace();
	    		}
	    		Log.e("fdssa", "aaaaaaaaaa");
	    		if (mediarecorder==null) {
	    			mediarecorder=new MediaRecorder();
	    		}
	    		Log.e("fdssa", "bbbbbbbbbbb");
	    		mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
	    		mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
	    		Log.e("fdssa", "cccccccccccccccccccc");
	    		mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
	    		Log.e("fdssa", "11111111111111");
	    		mediarecorder.setOutputFile(senderaac.getFileDescriptor());
	    		Log.e("fdssa", "ddddddddddddd");
	    		try {
	    			mediarecorder.prepare();
	    			Log.e("fdssa", "eeeeeeeeeeeee");
	    		} catch (IllegalStateException e) {
	    			// TODO Auto-generated catch block
	    			e.printStackTrace();
	    		} catch (IOException e) {
	    			// TODO Auto-generated catch block
	    			e.printStackTrace();
	    		}
	    		mediarecorder.start();
	    	}
	    	
	public class GetAudio extends Thread{//得到写入数据
	    		
	    		byte[] buffer=new byte[1024];
	    		int length=0;
	    		int len=0;
	    		int readlength=0;
	    		public void run() {
	    			try {
	    				while(ISrunning){	
	    				while(readlength<1024){
	    						readlength +=inputStream.read(buffer,readlength,1024-readlength);
	    						Log.v("fds", "readlength--->"+readlength);
	    					}
	    				raf.write(buffer,0,readlength);
	    				readlength=0;
	    				}				
	    			} catch (IOException e) {
	    				// TODO Auto-generated catch block
	    				e.printStackTrace();
	    			}
	    		};	
	    	}

	    	
	    	
	 public class Recoder extends Thread{//采集线程
	    		@Override
	    		public void run() {
	    			// TODO Auto-generated method stub
	    			super.run();
	    			//localsocket可以类比socket,在源(mediaRcoder.setOutputFile(sender.getFileDescriptor()))中
	    			//使用serversocket,发送本地,用socket在本地接收,得到的就是流;
	    			//在本地用InputStream inprutstream = receiver.getInputStream();在本地得到流
	    			receivedaac=new LocalSocket();
	    			
	    			try {
	    				lss=new LocalServerSocket("today_Socket");//相当于serversocekt开端口
	    				
	    				receivedaac.connect(new LocalSocketAddress("today_Socket"));//相当于socket客户端
	    				receivedaac.setReceiveBufferSize(BUFFER_SIZE);
	    				receivedaac.setSendBufferSize(BUFFER_SIZE);
	    				
	    				senderaac=lss.accept();//相当于serversocket等待连接,成功返回一个localsocket
	    				Log.i("fds", "sender init....");
	    				senderaac.setReceiveBufferSize(BUFFER_SIZE);
	    				senderaac.setSendBufferSize(BUFFER_SIZE);
	    				inputStream=receivedaac.getInputStream();
	    			} catch (IOException e1) {
	    				// TODO Auto-generated catch block
	    				e1.printStackTrace();
	    			}	
	    		
	    			Log.v("fdsa", "recoding audio....");
	    		}
	    	}
	    


}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值