H264的I幀通常 0x00 0x00 0x00 0x01 0x67 開始,到下一個幀頭開始之前是完整一幀.可放入FFMPEG的AVPacket中處理
無論是文件流還是網絡流,思路是將接收到的數據放入緩衝區,同時開啓一個待拼幀的緩衝區1024*1024大小(我的是高清1920*1080,足夠)
一、尋I幀頭
//判斷H264的I幀數據。返回I幀在本緩衝位置,或-1未找到
int _find_head(unsigned char *buffer, int len)
{
int i;
BOOL isMatch=FALSE;
for (i=0;i<len;i++){
if (buffer[i] == 0 && buffer[i+1] == 0 && buffer[i+2] == 0 && buffer[i+3] == 1 && buffer[i+4]==0x67){
isMatch=TRUE;
break;
}
}
return isMatch?i:-1;
}
二、拼幀
//應在循環代碼中完成:while 或 for
header_position = _find_head(data,data_len);
//如果在當前解出的H264中找到頭
if(header_position>-1){
//如果頭在解出數據的首部0索引處
if(header_position==0){
//如果之前已經有上一完整的FRAME緩存
if(total>0){
//printf("%s\ Frame size:%d\n","Frame has got.",total);//提交FRAME
//寫H264
//written = fwrite( frameData, total, 1, p810 );
//或解264爲YUV數據
//這是FFMPEG的方法,具體看FFMPEG:len = avcodec_decode_video(c, picture, &got_picture, data,data_len);
memset(frameData,0,FF_INPUT_BUFFER_PADDING_SIZE);//清空上一幀FRAME緩存
total=0;
}
//新讀入數據放入緩衝區,data是讀入數據緩衝區,frameData是將要拼成一幀的緩衝區
memcpy(frameData,data+header_position,data_len-header_position);
total+=data_len;
}else{
//如果頭不在解出數據的首部,表示data含有上一幀和下一幀的數據,要進行截取
memcpy(frameData+total,data,header_position);
total+=header_position;
//printf("%s\n","Frame has got.");//提交上一幀FRAME
//寫H264
//written = fwrite( frameData, total, 1, p810 );
//或解264爲YUV數據
//這是FFMPEG的方法,具體看FFMPEG:len = avcodec_decode_video(c, picture, &got_picture, data,data_len);
memset(frameData,0,FF_INPUT_BUFFER_PADDING_SIZE);//清空上一幀FRAME緩存
total=0;
//同時將截取的下一幀數據放入frameData
memcpy(frameData,data+header_position,data_len-header_position);
total+=data_len-header_position;
}
}else{//最後一個數據包,因爲沒有I幀數據,要如何處理看大家自己了。
memcpy(frameData+total,data,data_len);
total+=data_len;
}
以上。
2012-06-09 23:12:59