功能如题。参考了此文:
http://blog.csdn.net/zblue78/article/details/6083374
本人觉得上文中的代码还有些bug,而且不是针对H.263,所以自己编写了一个。本工程除了截取H263视频帧外的代码仍不完善,待以后有时间的时候继续修改。还有就是代码中实现了RTP的包头编写,但payload部分并不是按照RFC2190来组织,少了一个payload header的实现。
完整的Android工程在此下载:
http://download.csdn.net/detail/qwertyuj/3865413
下面是实现视频帧截取的主要代码:
public void run() {
final int READ_SIZE = 1024; //bytes count for every reading from 'inputStreamForReceive'
final int BUFFER_SIZE_RECEIVE = READ_SIZE * 128;
final int BUFFER_SIZE_RTP = READ_SIZE * 20;
stateMachineOfFrameReceiving STM_Recv = stateMachineOfFrameReceiving.FRAMEHEAD_NOTFOUND;
int i;
byte[] PSC_checkArr = new byte[3];
byte[] RTP_pocket_buffer = new byte[BUFFER_SIZE_RTP];
byte[] bufferForReceive = new byte[BUFFER_SIZE_RECEIVE]; //64K
int num = 0;
InputStream inputStreamForReceive = null;
//udp
final int RTP_PORT_SENDING = 8000;
final int RTP_PORT_DEST = 8000;
DatagramSocket socketSendRPT = null;
DatagramPacket RtpPocket = null;
InetAddress PC_IpAddress = null;
try {
PC_IpAddress = InetAddress.getByName("192.168.1.100");
}
catch (UnknownHostException e){
e.printStackTrace();
}
try{
socketSendRPT = new DatagramSocket(RTP_PORT_SENDING);
}
catch (SocketException e){
e.printStackTrace();
}
//get the data stream from mediaRecorder
try {
inputStreamForReceive = receiver.getInputStream();
} catch (IOException e1) {
return;
}
//create a media file to store captured video data
try {
File file = new File("/sdcard/stream02.h263");
Log.d(TAG, "File created!");
if (file.exists())
file.delete();//delete old file
raf = new RandomAccessFile(file, "rw");
} catch (Exception ex) {
Log.v("System.out", ex.toString());
}
int offsetInBufferForReceive = 0;
m_timer.schedule(m_timerTask, 1000, 1000); //timer for statistics
STM_Recv = stateMachineOfFrameReceiving.FRAMEHEAD_NOTFOUND;
PSC_checkArr[0] = (byte)0xFF;
PSC_checkArr[1] = (byte)0xFF;
PSC_checkArr[2] = (byte)0xFF;
while (true && !threadCanStop) {
//1. read data from receive stream until to the end
offsetInBufferForReceive = 0;
do {
try {
num = inputStreamForReceive.read(bufferForReceive, offsetInBufferForReceive, READ_SIZE);//copy data to buffer
if(num < 0){ // there's nothing in there
//wait for a while
try {
Thread.currentThread().sleep(5);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
break;
}
offsetInBufferForReceive += num; //offsetInBufferForReceive points to next position can be wrote
if (num < READ_SIZE || offsetInBufferForReceive == BUFFER_SIZE_RECEIVE) { //indicating the end of this reading
break; // or bufferForReceive is full
}
} catch (IOException e) {
break;
}
}while(false);//do
//2. find Picture Start Code (PSC) (22 bits) in bufferForReceive
for(i=0; i< offsetInBufferForReceive; i++){
PSC_checkArr[0] = PSC_checkArr[1];
PSC_checkArr[1] = PSC_checkArr[2];
PSC_checkArr[2] = bufferForReceive[i];
//see if got the PSC
if(PSC_checkArr[0] == 0 && PSC_checkArr[1] == 0 && (PSC_checkArr[2] & (byte)0xFC) == (byte)0x80)
{
//found the PSC
if(STM_Recv == stateMachineOfFrameReceiving.FRAMEHEAD_NOTFOUND)
{
STM_Recv = stateMachineOfFrameReceiving.FRAMEHEAD_FOUND;
//copy current byte to packet buffer
intializeRTP_PocketBuffer(RTP_pocket_buffer);
RTP_pocket_buffer[offsetInRTP_pocket_buffer] = bufferForReceive[i];
offsetInRTP_pocket_buffer++;
}
else if(STM_Recv == stateMachineOfFrameReceiving.FRAMEHEAD_FOUND)
{
//delete two zeros in the end of the buffer
offsetInRTP_pocket_buffer -= 2;
//TODO:3. send the packet, and reset the buffer
RtpPocket = new DatagramPacket(RTP_pocket_buffer, offsetInRTP_pocket_buffer, PC_IpAddress, RTP_PORT_DEST);
try {
socketSendRPT.send(RtpPocket);
Log.v(TAG, "Sent bytes: " + String.valueOf(offsetInRTP_pocket_buffer));
} catch (IOException e) {
e.printStackTrace();
}
/*
try {
raf.write(RTP_pocket_buffer, 0, offsetInRTP_pocket_buffer);
//raf.close();
} catch (IOException e1) {
e1.printStackTrace();
}
*/
intCapturedFrameCount++; //for statistics
//copy current byte to packet buffer
intializeRTP_PocketBuffer(RTP_pocket_buffer);
RTP_pocket_buffer[offsetInRTP_pocket_buffer] = bufferForReceive[i];
offsetInRTP_pocket_buffer++;
}
}
else//if NOT got the PSC
{
if(STM_Recv == stateMachineOfFrameReceiving.FRAMEHEAD_NOTFOUND)
{
continue;
}
else if(STM_Recv == stateMachineOfFrameReceiving.FRAMEHEAD_FOUND)
{
//copy current byte to packet buffer
RTP_pocket_buffer[offsetInRTP_pocket_buffer] = bufferForReceive[i];
offsetInRTP_pocket_buffer++;
}
}//if(PSC_checkArr[0] == 0 && PSC_checkArr[1] == 0 && (PSC_checkArr[2] & (byte)0xFC) == (byte)0x80)
//4. if RTP_pocket_buffer is full then discard all the bytes in it
if(offsetInRTP_pocket_buffer >= BUFFER_SIZE_RTP)
{
STM_Recv = stateMachineOfFrameReceiving.FRAMEHEAD_NOTFOUND;
offsetInRTP_pocket_buffer = 0;
}
}//for(i=0; i< offsetInBufferForReceive; i++)
}// while (true && !threadCanStop)
m_timer.cancel();
releaseMediaRecorder();
}
})