解决h264readInt()值太大 以及 SPS和PPS的获取


借鉴:http://blog.csdn.net/zgyulongfei/article/details/7538523    博客详细结束了SPS和PPS的获取

           http://blog.csdn.net/zblue78/article/details/6083374      文章【Android 的视频编码 H263 MP4V H264】的代码实现

           http://blog.csdn.net/jzl19901027/article/details/9864351    Android MediaRecorder H264 编码实时视频流不能播放(readInt()值太大)的问题


 再利用mediarecorder录制视频过程中,首先录制一段钟视频数据后,将数据流传入StsBox对象,调用getMdat()即可得到mdat的合适的开始位置和结束位置

............
try {
			fis = receiver.getInputStream();
			Thread.currentThread().sleep(500);
		} catch (IOException e2) {
			e2.printStackTrace();
			return;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		releaseVideo();
		
		StsdBox stsdBox = new StsdBox(fis);
//		stsdBox.saveStsBoxHead(context);
		stsdBox.getMdat();
		Log.i(TAG, "mdat: " + (stsdBox.getEndMdat() - stsdBox.getStartMdat()));
............

代码:


public class StsdBox {
	
	private byte[] buffer = new byte[1024 * 64];
	private int spsStartPos;
	private int spsLength;
	
	private int num, number = 0;
	private int frame_size = 1024;
	
	public StsdBox(InputStream fis) {
		initByte(fis);
	}
	
	private void initByte(InputStream fis) {
		while (true) {
			try {
				if(number >= buffer.length) {
					break;
				}
				num = fis.read(buffer, number, frame_size);
				number += num;
				if (num < frame_size) {
					break;
				}
			} catch (IOException e) {
				e.printStackTrace();
				Log.i("number: ", "" + number);
				break;
			}
		}
	}
	
	private int startMdat = 0;
	private int endMdat = 0;
	public int getStartMdat() {
		return startMdat;
	}
	public void setStartMdat(int startMdat) {
		this.startMdat = startMdat;
	}
	public int getEndMdat() {
		return endMdat;
	}
	public void setEndMdat(int endMdat) {
		this.endMdat = endMdat;
	}
	public void getMdat() {
		for(int im=0; im < buffer.length; im++) {
			if (buffer[im] == 'm' && buffer[im + 1] == 'd'
					&& buffer[im + 2] == 'a'
					&& buffer[im + 3] == 't') {
				if(im > 0 && buffer[im - 1] == '?') {
					startMdat = im - 4;
				} else {
					startMdat = im;
				}
				if(im < (buffer.length - 1) && buffer[im + 5] == '?') {
					if(buffer[im + 9] == '?') {
						endMdat = im + 12;
					} else {
						endMdat = im + 8;
					}
				} else {
					endMdat = im + 4;
				}
				break;
			}
		}
	}
	
	private int getAvcC() {
		byte[] avcC = new byte[] { 0x61, 0x76, 0x63, 0x43 };
		int avcRecord = 0;
		for (int ix = 0; ix < buffer.length; ++ix) {
			if (buffer[ix] == avcC[0] && buffer[ix + 1] == avcC[1]
					&& buffer[ix + 2] == avcC[2]
					&& buffer[ix + 3] == avcC[3]) {
				
				avcRecord = ix + 4;
				break;
			}
		}
		if (0 == avcRecord) {
			System.out.println(R.string.no_found_avcc);
			avcRecord = 0;
		}
		return avcRecord;
	}
	
	public byte[] findSPS() {
		if(getAvcC() == 0) {
			return null;
		}
		spsStartPos = getAvcC() + 6;
		byte[] spsbt = new byte[] { buffer[spsStartPos],
				buffer[spsStartPos + 1] };
		spsLength = CalculateUtil.bytes2Int(spsbt);
		byte[] h264sps = new byte[spsLength];
		// ���2���ֽڵ� sequenceParameterSetLength
		spsStartPos += 2;
		System.arraycopy(buffer, spsStartPos, h264sps, 0, spsLength);
		printResult("SPS", h264sps, spsLength);
		
		return h264sps;
	}
	
	public byte[] findPPS() {
		if(getAvcC() == 0) {
			return null;
		}

		int ppsStartPos = spsStartPos + spsLength + 1;
		byte[] ppsbt = new byte[] { buffer[ppsStartPos],
				buffer[ppsStartPos + 1] };
		int ppsLength = CalculateUtil.bytes2Int(ppsbt);
		byte[] h264pps = new byte[ppsLength];
		ppsStartPos += 2;
		System.arraycopy(buffer, ppsStartPos, h264pps, 0, ppsLength);
		printResult("PPS", h264pps, ppsLength);
		
		return h264pps;
	}
	
	private void printResult(String type, byte[] bt, int len) {
		System.out.println(type + "������" + len);
		String cont = type + "��������";
		System.out.print(cont);
		for (int ix = 0; ix < len; ++ix) {
			System.out.printf("%02x ", bt[ix]);
		}
		System.out.println("\n----------");
	}
}

你可能感兴趣的:(android实时音视频传输)