NALUParsing.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * 叶海辉
  3. * QQ群121376426
  4. * http://blog.yundiantech.com/
  5. */
  6. #include "NALUParsing.h"
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. NALUParsing::NALUParsing()
  11. {
  12. ///初始化一段内存 用于临时存放h264数据
  13. mH264Buffer = (uint8_t*)malloc(1024*1024*10);
  14. mBufferSize = 0;
  15. }
  16. int NALUParsing::inputH264Data(uint8_t *buf, int len)
  17. {
  18. memcpy(mH264Buffer + mBufferSize, buf, len);
  19. mBufferSize += len;
  20. return mBufferSize;
  21. }
  22. T_NALU *NALUParsing::getNextFrame()
  23. {
  24. /*根据h264文件的特性 逐个字节搜索 直到遇到h264的帧头 视为获取到了完整的一帧h264视频数据*/
  25. /// 关于起始码startcode的两种形式:3字节的0x000001和4字节的0x00000001
  26. /// 3字节的0x000001只有一种场合下使用,就是一个完整的帧被编为多个slice的时候,
  27. /// 包含这些slice的nalu使用3字节起始码。其余场合都是4字节的。
  28. /// 因此查找一帧的话,只需要查找四字节的起始码即可。
  29. ///首先查找第一个起始码
  30. int pos = 0; //记录当前处理的数据偏移量
  31. int StartCode = 0;
  32. while(1)
  33. {
  34. unsigned char* Buf = mH264Buffer + pos;
  35. int lenth = mBufferSize - pos; //剩余没有处理的数据长度
  36. if (lenth <= 4)
  37. {
  38. return NULL;
  39. }
  40. ///查找起始码(0x00000001)
  41. if(Buf[0]==0 && Buf[1]==0 && Buf[2] ==0 && Buf[3] ==1)
  42. //Check whether buf is 0x00000001
  43. {
  44. StartCode = 4;
  45. break;
  46. }
  47. else
  48. {
  49. //否则 往后查找一个字节
  50. pos++;
  51. }
  52. }
  53. ///然后查找下一个起始码查找第一个起始码
  54. int pos_2 = pos + StartCode; //记录当前处理的数据偏移量
  55. int StartCode_2 = 0;
  56. while(1)
  57. {
  58. unsigned char* Buf = mH264Buffer + pos_2;
  59. int lenth = mBufferSize - pos_2; //剩余没有处理的数据长度
  60. if (lenth <= 4)
  61. {
  62. return nullptr;
  63. }
  64. ///查找起始码(0x00000001)
  65. if(Buf[0]==0 && Buf[1]==0 && Buf[2] ==0 && Buf[3] ==1)
  66. //Check whether buf is 0x00000001
  67. {
  68. StartCode_2 = 4;
  69. break;
  70. }
  71. else
  72. {
  73. //否则 往后查找一个字节
  74. pos_2++;
  75. }
  76. }
  77. /// 现在 pos和pos_2之间的数据就是一帧数据了
  78. /// 把他取出来
  79. ///由于传递给ffmpeg解码的数据 需要带上起始码 因此这里的nalu带上了起始码
  80. unsigned char* Buf = mH264Buffer + pos; //这帧数据的起始数据(包含起始码)
  81. int naluSize = pos_2 - pos; //nalu数据大小 包含起始码
  82. T_NALU * nalu = AllocNALU(naluSize, mVideoType);//分配nal 资源
  83. if (mVideoType == T_NALU_H264)
  84. {
  85. T_H264_NALU_HEADER *nalu_header = (T_H264_NALU_HEADER *)(Buf + StartCode);
  86. nalu->nalu.h264Nalu.startcodeprefix_len = StartCode; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
  87. nalu->nalu.h264Nalu.len = naluSize; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
  88. nalu->nalu.h264Nalu.forbidden_bit = 0; //! should be always FALSE
  89. nalu->nalu.h264Nalu.nal_reference_idc = nalu_header->NRI; //! NALU_PRIORITY_xxxx
  90. nalu->nalu.h264Nalu.nal_unit_type = nalu_header->TYPE; //! NALU_TYPE_xxxx
  91. nalu->nalu.h264Nalu.lost_packets = false; //! true, if packet loss is detected
  92. memcpy(nalu->nalu.h264Nalu.buf, Buf, naluSize); //! contains the first byte followed by the EBSP
  93. // {
  94. // char *bufTmp = (char*)(Buf + StartCode);
  95. // char s[10];
  96. // itoa(bufTmp[0], s, 2);
  97. // fprintf(stderr, "%s %08s %x %d\n", __FUNCTION__, s, bufTmp[0] , nalu_header->TYPE);
  98. // }
  99. }
  100. else
  101. {
  102. T_H265_NALU_HEADER *nalu_header = (T_H265_NALU_HEADER *)(Buf + StartCode);
  103. nalu->nalu.h265Nalu.startCodeLen = StartCode; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
  104. nalu->nalu.h265Nalu.len = naluSize; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
  105. nalu->nalu.h265Nalu.h265NaluHeader = *nalu_header;
  106. memcpy(nalu->nalu.h265Nalu.buf, Buf, naluSize); //! contains the first byte followed by the EBSP
  107. // {
  108. // char *bufTmp = (char*)(Buf);
  109. // fprintf(stderr, "%s %02x%02x%02x%02x%02x%02x %d %d\n", __FUNCTION__, bufTmp[0], bufTmp[1], bufTmp[2], bufTmp[3], bufTmp[4], bufTmp[5], nalu->nalu.h265Nalu.h265NaluHeader.nal_unit_type, nalu_header->nal_unit_type);
  110. // }
  111. }
  112. /// 将这一帧数据去掉
  113. /// 把后一帧数据覆盖上来
  114. int leftSize = mBufferSize - pos_2;
  115. memmove(mH264Buffer, mH264Buffer + pos_2, leftSize);
  116. mBufferSize = leftSize;
  117. return nalu;
  118. }
  119. T_NALU *NALUParsing::AllocNALU(int buffersize, T_NALU_TYPE type)
  120. {
  121. T_NALU *n = NULL;
  122. n = (T_NALU*)malloc (sizeof(T_NALU));
  123. n->type = type;
  124. if (type == T_NALU_H264)
  125. {
  126. n->nalu.h264Nalu.max_size = buffersize; //Assign buffer size
  127. n->nalu.h264Nalu.buf = (unsigned char*)malloc (buffersize);
  128. n->nalu.h264Nalu.len = buffersize;
  129. }
  130. else
  131. {
  132. n->nalu.h265Nalu.buf = (unsigned char*)malloc (buffersize);
  133. n->nalu.h265Nalu.len = buffersize;
  134. }
  135. return n;
  136. }
  137. void NALUParsing::FreeNALU(T_NALU *n)
  138. {
  139. if (n == nullptr) return;
  140. if (n->type == T_NALU_H264)
  141. {
  142. free(n->nalu.h264Nalu.buf);
  143. }
  144. else
  145. {
  146. free(n->nalu.h265Nalu.buf);
  147. }
  148. }