Example #1
0
//这个函数输入为一个NAL结构体,主要功能为得到一个完整的NALU并保存在NALU_t的buf中,获取他的长度,填充F,IDC,TYPE位。
//并且返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
int GetAnnexbNALU (NALU_t *nalu)
{
  int pos = 0;
  int StartCodeFound, rewind;
  unsigned char *Buf;
    
  if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL) 
	  printf ("GetAnnexbNALU: Could not allocate Buf memory\n");

  nalu->startcodeprefix_len=3;//初始化码流序列的开始字符为3个字节
  
   if (3 != fread (Buf, 1, 3, bits))//从码流中读3个字节
	   {
		free(Buf);
		return 0;
	   }
   info2 = FindStartCode2 (Buf);//判断是否为0x000001
   if(info2 != 1) 
   {
	//如果不是,再读一个字节
    if(1 != fread(Buf+3, 1, 1, bits))//读一个字节
		{
		 free(Buf);
		 return 0;
		}
    info3 = FindStartCode3 (Buf);//判断是否为0x00000001
    if (info3 != 1)//如果不是,返回-1
		{ 
		 free(Buf);
		 return -1;
		}
    else 
		{
		//如果是0x00000001,得到开始前缀为4个字节
		 pos = 4;
		 nalu->startcodeprefix_len = 4;
		}
   }
   
   else
	   {
	   //如果是0x000001,得到开始前缀为3个字节
		nalu->startcodeprefix_len = 3;
		pos = 3;
	   }
   //查找下一个开始字符的标志位
   StartCodeFound = 0;
   info2 = 0;
   info3 = 0;
  
  while (!StartCodeFound)
  {
    if (feof (bits))//判断是否到了文件尾
    {
      nalu->len = (pos-1)-nalu->startcodeprefix_len;
      memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);     
      nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
	  nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
	  nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
      free(Buf);
      return pos-1;
    }
    Buf[pos++] = fgetc (bits);//读一个字节到BUF中
    info3 = FindStartCode3(&Buf[pos-4]);//判断是否为0x00000001
    if(info3 != 1)
      info2 = FindStartCode2(&Buf[pos-3]);//判断是否为0x000001
    StartCodeFound = (info2 == 1 || info3 == 1);
  }
  

 
  // Here, we have found another start code (and read length of startcode bytes more than we should
  // have.  Hence, go back in the file
  rewind = (info3 == 1)? -4 : -3;

  if (0 != fseek (bits, rewind, SEEK_CUR))//把文件指针指向前一个NALU的末尾
  {
    free(Buf);
	printf("GetAnnexbNALU: Cannot fseek in the bit stream file");
  }

  // Here the Start code, the complete NALU, and the next start code is in the Buf.  
  // The size of Buf is pos, pos+rewind are the number of bytes excluding the next
  // start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start code

  nalu->len = (pos+rewind)-nalu->startcodeprefix_len;
  memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);//拷贝一个完整NALU,不拷贝起始前缀0x000001或0x00000001
  nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
  nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
  nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
  free(Buf);
 
  return (pos+rewind);//返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
}
Example #2
0
//这个函数输入为一个NAL结构体,主要功能为得到一个完整的NALU并保存在NALU_t的buf中,
//获取他的长度,填充F,IDC,TYPE位。
//并且返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
int GetAnnexbNALU (sp<ABuffer> nalu)
{
	int pos = 0;
	int StartCodeFound, rewind;
//	unsigned char *Buf;
	int info2,info3,startcodeprefix_len,len;

	static unsigned char Buf[50000];

	startcodeprefix_len=3;//初始化码流序列的开始字符为3个字节

	if (3 != fread (Buf, 1, 3, bits))//从码流中读3个字节
	{
		//free(Buf);
		return 0;
	}
	info2 = FindStartCode2 (Buf);//判断是否为0x000001 
	if(info2 != 1) 
	{
		//如果不是,再读一个字节
		if(1 != fread(Buf+3, 1, 1, bits))//读一个字节
		{
			//free(Buf);
			return 0;
		}
		info3 = FindStartCode3 (Buf);//判断是否为0x00000001
		if (info3 != 1)//如果不是,返回-1
		{ 
			//free(Buf);
			return -1;
		}
		else 
		{
			//如果是0x00000001,得到开始前缀为4个字节
			pos = 4;
			startcodeprefix_len = 4;
		}
	}
	else
	{
		//如果是0x000001,得到开始前缀为3个字节
		startcodeprefix_len = 3;
		pos = 3;
	}
	//查找下一个开始字符的标志位
	StartCodeFound = 0;
	info2 = 0;
	info3 = 0;

	while (!StartCodeFound)
	{
		if (feof (bits))//判断是否到了文件尾
		{
			//return 0;
			len = (pos-1)- startcodeprefix_len;
			memcpy (nalu->data(), &Buf[startcodeprefix_len], len);     
			//free(Buf);
			printf("lcy 1991 len %d\n",len);
			return pos-1;
		}
		Buf[pos++] = fgetc (bits);//读一个字节到BUF中
		info3 = FindStartCode3(&Buf[pos-4]);//判断是否为0x00000001
		if(info3 != 1)
			info2 = FindStartCode2(&Buf[pos-3]);//判断是否为0x000001
		StartCodeFound = (info2 == 1 || info3 == 1);
	}

	// Here, we have found another start code (and read length of startcode bytes more than we should
	// have.  Hence, go back in the file
	rewind = (info3 == 1)? -4 : -3;

	if (0 != fseek (bits, rewind, SEEK_CUR))//把文件指针指向前一个NALU的末尾
	{
		//free(Buf);
		printf("GetAnnexbNALU: Cannot fseek in the bit stream file");
	}

	// Here the Start code, the complete NALU, and the next start code is in the Buf.  
	// The size of Buf is pos, pos+rewind are the number of bytes excluding the next
	// start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start code

	len = (pos+rewind)-startcodeprefix_len;
	memcpy (nalu->data(), &Buf[startcodeprefix_len], len);//拷贝一个完整NALU,不拷贝起始前缀0x000001或0x00000001
	//free(Buf);
	printf("memcpy2\n");

	return (pos+rewind);//返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
}
Example #3
0
void CRTPRecv::SendH264Nalu(unsigned char* m_h264Buf,int buflen) 
{
	//时间戳
	//int TimesTampInc=3600;
	//Mark标志
	//int Mark = 1;
	//NAL单元(非发送结构)
	NALU_t  Nalu;

	//待处理的单帧数据指针s
	unsigned char *pSendbuf=NULL;
	int SendLen=0;

	//发送的数据缓冲
	char sendbuf[1430];
	memset(sendbuf,0,1430);

	//上一个startcode位置
	int LastStartPos=0;
	//本次STARTCODE位置
	int StartPos=0;
	//前导码为 0x00 00 01 或者 0x00 00 00 01
	int DataCount=3;
	unsigned char *pData=m_h264Buf;
	int res=0;
	while (DataCount<buflen)
	{
		res=FindStartCode3(pData+DataCount-3);
		if (res!=true)
		{	
			//未找到前导码
			if (DataCount!=buflen-1)
			{
				DataCount++;
				continue;
			}
			else
			{
				//最后一段数据
				StartPos = buflen;
			}
		}
		else
		{
			//找到前导码 0x00 00 01
			StartPos=DataCount-3;
			res=FindStartCode4(pData+DataCount-4);
			if(res==true)
			{

				//找到前导码 0x00 00 00 01
				StartPos=DataCount-4;
			}
		} 

		//切一个nal进行处理
		pSendbuf = pData+LastStartPos;
		SendLen = StartPos-LastStartPos;
		LastStartPos = StartPos;
		DataCount++;
		if (SendLen==0)
		{
			//第一个前导码不用处理
			continue;
		}
		int frontFlag=0;
		//去除前导码0x000001 或者0x00000001
		if( 0x01 == pSendbuf[2] )
		{
			pSendbuf = &pSendbuf[3];
			SendLen -= 3;
			frontFlag=3;
		}
		else if(0x01==pSendbuf[3])
		{
			pSendbuf = &pSendbuf[4];
			SendLen -= 4;
			frontFlag=4;
		}
		if (SendLen==0)
		{
			//前导码后没有数据
			LOG_WARN("NULL 264 packet");
			return;
		}
		//如果前导码为0x00 00 00 01 表示上一帧已经结束 发送分界nal
		/*if (frontFlag==4)
		{
			m_TimesTampInc=3600;
			char buf[6];
			memset(buf,0,6);
			buf[0]=0x09;
			buf[1]=0x30;
			SendPacket(buf,6,H264,1,m_TimesTampInc);
			m_TimesTampInc=0;
		}*/
		//解析nal头
		NALU_t na;
		na.forbidden_bit      = pSendbuf[0] & 0x80;
		na.nal_reference_idc  = (pSendbuf[0] & 0x60)>>5;
		na.nal_unit_type      = pSendbuf[0] & 0x1f;

		int status=0; 
		//单包
		if ( SendLen <= MAX_RTP_PKT_LENGTH )
		{
			//SetDefaultMark(true);
			status = this->SendPacket((void *)pSendbuf,SendLen,H264,1,TIMESTAMP);
		}  
		//分片
		else if(SendLen > MAX_RTP_PKT_LENGTH)
		{
			FU_INDICATOR    *pstFuInd;
			FU_HEADER       *pstFuHdr;
			char			*pNaluPayLoad;

			//解析nal头
			Nalu.forbidden_bit      = pSendbuf[0] & 0x80;
			Nalu.nal_reference_idc  = pSendbuf[0] & 0x60;
			Nalu.nal_unit_type      = pSendbuf[0] & 0x1f;
			pSendbuf+=1;
			SendLen-=1;
			//分片数量
			int PackCount=0;
			//最后一个分片长度
			int RemainLen=0; 
			PackCount = SendLen / MAX_RTP_PKT_LENGTH;
			RemainLen = SendLen % MAX_RTP_PKT_LENGTH;
			int PackNumber=0;//用指示当前发送的是第几个分片RTP包

			while (PackNumber<=PackCount)
			{
				pstFuInd       = (FU_INDICATOR*)&sendbuf[0];
				pstFuInd->F    = Nalu.forbidden_bit;
				pstFuInd->NRI  = Nalu.nal_reference_idc >> 5;
				pstFuInd->TYPE = NALU_TYPE_FU_A;
				//第一个分片
				if (PackNumber==0)
				{

					pstFuHdr         = (FU_HEADER*)&sendbuf[1];
					pstFuHdr->E    = 0;
					pstFuHdr->R    = 0;
					pstFuHdr->S    = 1;
					pstFuHdr->TYPE = Nalu.nal_unit_type;
					pNaluPayLoad     = &sendbuf[2];
					memcpy(pNaluPayLoad,pSendbuf+PackNumber*MAX_RTP_PKT_LENGTH,MAX_RTP_PKT_LENGTH);
					//SetDefaultMark(false);
					status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2,H264,0,0);
					PackNumber++;
					continue;
				}
				//最后一个分片
				else if (((PackNumber==PackCount-1)&&RemainLen==0)||((PackNumber==PackCount)&&(RemainLen!=0)))
				{
					pstFuHdr         = (FU_HEADER*)&sendbuf[1];
					pstFuHdr->E    = 1;
					pstFuHdr->R    = 0;
					pstFuHdr->S    = 0;
					pstFuHdr->TYPE = Nalu.nal_unit_type;
					pNaluPayLoad     = &sendbuf[2];
					//SetDefaultMark(true);
					if (RemainLen==0)
					{
						memcpy(pNaluPayLoad,pSendbuf+PackNumber*MAX_RTP_PKT_LENGTH,MAX_RTP_PKT_LENGTH);
						status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2,H264,1,0);
					}
					else
					{
						memcpy(pNaluPayLoad,pSendbuf+PackNumber*MAX_RTP_PKT_LENGTH,RemainLen);
						status = this->SendPacket((void *)sendbuf,RemainLen+2,H264,1,TIMESTAMP);
					}
					break;
				}
				//中间分片
				else
				{
					pstFuHdr         = (FU_HEADER*)&sendbuf[1];
					pstFuHdr->E    = 0;
					pstFuHdr->R    = 0;
					pstFuHdr->S    = 0;
					pstFuHdr->TYPE = Nalu.nal_unit_type;
					pNaluPayLoad     = &sendbuf[2];
					memcpy(pNaluPayLoad,pSendbuf+PackNumber*MAX_RTP_PKT_LENGTH,MAX_RTP_PKT_LENGTH);
					//SetDefaultMark(false);
					status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2,H264,0,0);
					PackNumber++;
					continue;
				}

			}
		}


	}