以读文件的方式解析H264裸码流

来源:互联网 发布:指南针炒股软件评价 编辑:程序博客网 时间:2024/06/15 13:38

H264 NALU类型

标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。

0:未规定 1:非IDR图像中不采用数据划分的片段 2:非IDR图像中A类数据划分片段 3:非IDR图像中B类数据划分片段 4:非IDR图像中C类数据划分片段 5:IDR图像的片段 6:补充增强信息 (SEI) 7:序列参数集 8:图像参数集 9:分割符 10:序列结束符 11:流结束符 12:填充数据 13 – 23:保留 24 – 31:未规定 

思路

思路是将每次填入的这帧数据提取出来,然后通过RTP实时发送。

*cam >> frame_in;if(frame_in.empty()){    cout<<"frame_in blank frame"<<endl;    return false;}int start_pos = get_fileSize(name);writer.write(frame_in);/* 将这一帧数据取出来放到buf里 *//*思路是将每次填入的这帧数据提取出来,然后通过RTP实时发送*/int end_pos = get_fileSize(name);file=fopen(name.c_str(), "rb+");fseek(file, start_pos, SEEK_SET);   if(end_pos-start_pos>0){    fread (buf, 1, end_pos-start_pos, file);    transmitter->sendFrame(buf, end_pos-start_pos);}

sendFrame

    void imageTransmitter :: sendFrame(unsigned char* buf,int len){    NALU_HEADER* nalu_hdr;    FU_INDICATOR* fu_ind;    FU_HEADER* fu_hdr;    char* nalu_payload;      unsigned char rltBuf[800000];    char sendbuf[1500];     int rlt = GetAnNALU(buf,len,rltBuf,n);    if(rlt<0){        printf("get null error!\n");                return;    }    /* 输出NALU长度和TYPE */    dump(n);    /*当一个NALU小于MAX_RTP_PKT_LENGTH字节的时候,采用一个单RTP包发送  */    if(n->len<=MAX_RTP_PKT_LENGTH){        nalu_hdr =(NALU_HEADER*)&sendbuf[0];         nalu_hdr->F=n->forbidden_bit;        nalu_hdr->NRI=n->nal_reference_idc>>5;        nalu_hdr->TYPE=n->nal_unit_type;         nalu_payload=&sendbuf[1];        memcpy(nalu_payload,n->buf+1,n->len-1);//去掉nalu头的nalu剩余内容写入sendbuf[13]开始的字符串。        this->sendPacket(sendbuf,n->len);    }else if(n->len>MAX_RTP_PKT_LENGTH){        int k=0,l=0;        k=n->len/MAX_RTP_PKT_LENGTH;//需要k个MAX_RTP_PKT_LENGTH字节的RTP包          l=n->len%MAX_RTP_PKT_LENGTH;//最后一个RTP包的需要装载的字节数         int t=0;//用于指示当前发送的是第几个分片RTP包         while(t<=k){            if(!t)//发送一个需要分片的NALU的第一个分片,置FU HEADER的S位             {                memset(sendbuf,0,1500);                 fu_ind =(FU_INDICATOR*)&sendbuf[0];                fu_ind->F=n->forbidden_bit;                fu_ind->NRI=n->nal_reference_idc>>5;                fu_ind->TYPE=28;                fu_hdr =(FU_HEADER*)&sendbuf[1];                fu_hdr->E=0;                  fu_hdr->R=0;                  fu_hdr->S=1;                  fu_hdr->TYPE=n->nal_unit_type;                 nalu_payload=&sendbuf[2];                memcpy(nalu_payload,n->buf+1,MAX_RTP_PKT_LENGTH);//去掉NALU头                this->sendPacket(sendbuf,MAX_RTP_PKT_LENGTH+2);                t++;             }else if(k==t)//发送的是最后一个分片,注意最后一个分片的长度可能超过            {                memset(sendbuf,0,1500);                 fu_ind =(FU_INDICATOR*)&sendbuf[0];                fu_ind->F=n->forbidden_bit;                fu_ind->NRI=n->nal_reference_idc>>5;                fu_ind->TYPE=28;                fu_hdr =(FU_HEADER*)&sendbuf[1];                fu_hdr->R=0;                  fu_hdr->S=0;                  fu_hdr->E=1;                  fu_hdr->TYPE=n->nal_unit_type;                 nalu_payload=&sendbuf[2];                memcpy(nalu_payload,n->buf+t*MAX_RTP_PKT_LENGTH+1,l-1);//将nalu最后剩余的                this->sendPacket(sendbuf,l+1);                 t++;             }else if(t<k&&0!=t){                memset(sendbuf,0,1500);                 fu_ind =(FU_INDICATOR*)&sendbuf[0];                fu_ind->F=n->forbidden_bit;                fu_ind->NRI=n->nal_reference_idc>>5;                fu_ind->TYPE=28;                fu_hdr =(FU_HEADER*)&sendbuf[1];                fu_hdr->R=0;                  fu_hdr->S=0;                  fu_hdr->E=0;                  fu_hdr->TYPE=n->nal_unit_type;                 nalu_payload=&sendbuf[2];                memcpy(nalu_payload,n->buf+t*MAX_RTP_PKT_LENGTH+1,MAX_RTP_PKT_LENGTH);                this->sendPacket(sendbuf,MAX_RTP_PKT_LENGTH+2);                t++;             }        }    }    if(rlt>0){        sendFrame(rltBuf, len-rlt);    }} 

GetAnNALU

/*主要功能为得到一个完整的NALU并保存在NALU_t的buf中,获取他的长度,填充F,IDC,TYPE位。* 并判断这个buf中是否还存在其他的NALU单元。* parms:* buf:为一帧原始码流* len:原始码流长度,* retBuf: 如果有多个NALU,则将已经获取的第一个NALU去掉,其余部分存储在retBuf中* nalu: 获取的一个NALU* 返回值:-1没有获取的NALU,0获取到NALU并且只有一个,大于0说明不止一个NALU,并且值代表被取出的NALU的长度包含前缀*/int GetAnNALU(unsigned char* buf,int len, unsigned char* retBuf, NALU_t *nalu){    int pos = 0;    int StartCodeFound;    if(len<4){        return -1;    }    nalu->startcodeprefix_len=3;//初始化码流序列的开始字符为3个字节    info2 = FindStartCode2 (buf);//判断是否为0x000001    if(info2 != 1)     {        info3 = FindStartCode3 (buf);//判断是否为0x00000001        if (info3 != 1)//如果不是,返回-1        {              return -1;        }        else         {            //如果是0x00000001,得到开始前缀为4个字节             pos = 4;            nalu->startcodeprefix_len = 4;        }    }    else    {       //如果是0x000001,得到开始前缀为3个字节        pos = 3;       nalu->startcodeprefix_len = 3;     }   //查找下一个开始字符的标志位   StartCodeFound = 0;   info2 = 0;   info3 = 0;  while (!StartCodeFound)  {    if(pos >= len-1){        break;    }    pos++;    info3 = FindStartCode3(&buf[pos-4]);//判断是否为0x00000001    if(info3 != 1)      info2 = FindStartCode2(&buf[pos-3]);//判断是否为0x000001    StartCodeFound = (info2 == 1 || info3 == 1);  }  if(!StartCodeFound){      nalu->len = (len)-nalu->startcodeprefix_len;  }else{      if(info2 == 1){        pos = pos - 3;      }else{        pos = pos - 4;      }      nalu->len = pos-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  if(!StartCodeFound){    return 0;  }else{      memcpy(retBuf, buf+pos, len-pos);      return pos;  }}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 指标查询 广州指标网 技术指标 通达信指标 股票指标 指标生 指标英文 指标 英文 wvad指标 绩效考核指标 广州指标摇号申请系统 kpi考核三大指标 宝宝发育指标对照表 婴儿发育指标 广州指标摇号 广州指标个人申请系统 4月宝宝发育指标 3月宝宝发育指标 肝功能主要指标 尿酸指标正常值范围 肝纤维化指标 尿酸指标正常值范围2018 广州指标查询 广州指标申请 指标是什么意思 什么是指标生 zlmm指标详解 北京市小客车 bjhjyd 北京小汽车 北京缓解拥堵网站 小汽车 4个月宝宝发育指标 3个月宝宝发育指标 10月宝宝发育指标 10个月宝宝发育指标 五个月宝宝发育指标 十一个月宝宝发育指标 14个月宝宝发育指标 六个月宝宝发育指标 指纹打卡做指模