从RTP包中解析H264数据(修改版)

package com.zhuyun.rtp;

import java.nio.ByteBuffer;

import org.jitsi.service.neomedia.RawPacket;


public class RtpUtils {
	
	public static byte[] h264Pack(RawPacket rtpPacket){
		if (rtpPacket.getPayloadType() == 96) {												//以下处理仅针对H264码流
		    ByteBuffer bb = null;														//存放RTP解析后的NALU的数据
		    
		    byte[] rtpPayload = rtpPacket.getPayload();
		    byte fu_indicator = rtpPayload[0];
		    byte fu_header = rtpPayload[1];
		    byte nalu_type = (byte) (fu_indicator & 0x1f);		
		      
//		    System.out.println("=======nalu_type========" + nalu_type);
		    if (nalu_type == 0x1C) {  //FU-A										//分片封包模式
		          byte start_flag = (byte) (fu_header & 0x80);
		          byte end_flag = (byte) (fu_header & 0x40);
		          byte nalu_header = (byte) ((fu_indicator & 0xe0) | (fu_header & 0x1f));	//根据fu_indicator和fu_header来重构出nalu_header
		          if (start_flag != 0) {											//第一个分片
//		        	  System.out.println("===================start");
		        	  bb = ByteBuffer.allocate(rtpPayload.length + 3);
		        	  bb.put(new byte[]{0x0, 0x0, 0x0, 0x1});
		        	  bb.put(nalu_header);
		        	  byte[] dest = new byte[rtpPayload.length-2];
		        	  System.arraycopy(rtpPayload, 2, dest, 0, rtpPayload.length-2);
		        	  bb.put(dest);
		          } else if (end_flag != 0) {										//最后一个分片
//		        	  System.out.println("===================end");
		        	  bb = ByteBuffer.allocate(rtpPayload.length-2);
		              byte[] dest = new byte[rtpPayload.length-2];
		        	  System.arraycopy(rtpPayload, 2, dest, 0, rtpPayload.length-2);
		        	  bb.put(dest);
		          } else {															//中间分片
//		        	  System.out.println("===================middle");
		        	  bb = ByteBuffer.allocate(rtpPayload.length-2);
		        	  byte[] dest = new byte[rtpPayload.length-2];
		        	  System.arraycopy(rtpPayload, 2, dest, 0, rtpPayload.length-2);
		        	  bb.put(dest);
		          }
		     } else if (nalu_type == 0x18) {  //STAP-A								//组合封包模式
		        int srcOffset = 1;										//第一个字节是STAP-A头,跳过
		        int bufferLen = 0;
		        //先计算需要的ByteBuffer长度,再将内容放进去
		        while ((rtpPayload.length - srcOffset) > 2)				//循环解析RTP,将组合后的NALU取出来,再加上起始码
		        {	
		            int size = 0;										//NALU的长度,2个字节
		            size |= rtpPayload[srcOffset] << 8;						
		            size |= rtpPayload[srcOffset + 1];
		
		            srcOffset += 2;										//将NALU header和NALU payload一起放进去,然后进入下一个循环
		        	bufferLen += (4+size);
		            srcOffset += size;
		        }
		        
		        srcOffset = 1;
		        bb = ByteBuffer.allocate(bufferLen);
		        while ((rtpPayload.length - srcOffset) > 2)				//循环解析RTP,将组合后的NALU取出来,再加上起始码
		        {	
		            int size = 0;										//NALU的长度,2个字节
		            size |= rtpPayload[srcOffset] << 8;						
		            size |= rtpPayload[srcOffset + 1];
		
		            srcOffset += 2;										//将NALU header和NALU payload一起放进去,然后进入下一个循环
		            byte[] dest = new byte[size];
		        	System.arraycopy(rtpPayload, srcOffset, dest, 0, size);
		        	
		        	bb.put(new byte[]{0x0, 0x0, 0x0, 0x1});				//NALU的起始码
		        	bb.put(dest);
		        	
		            srcOffset += size;
		        }
		        
		        
		     } else if (nalu_type == 0x1) {											//单一NAL 单元模式
		          bb = ByteBuffer.allocate(rtpPayload.length + 4);					//将整个rtpPayload一起放进去
		    	  bb.put(new byte[]{0x0, 0x0, 0x0, 0x1});
		    	  bb.put(rtpPayload);
		     } else {
		    	 System.out.println("Unsupport nalu type!");
		     }
		    
		    return bb.array();
		}
		return null;
	
	}
}

主要修改部分,是在nalu_type == 0x18的时候。之前长度直接定为了rtpPayload.length,其实是不对的。

 

这种情况下,必须要循环解析RTP,才能获取到长度,即:

while ((rtpPayload.length - srcOffset) > 2)	//循环解析RTP,将组合后的NALU取出来,再加上起始码
	{	
	    int size = 0;										//NALU的长度,2个字节
		size |= rtpPayload[srcOffset] << 8;						
		size |= rtpPayload[srcOffset + 1];
		
		srcOffset += 2;			
		bufferLen += (4+size);
		srcOffset += size;
	}

其他内容不变。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值