You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
8.4KB

  1. // RFC7798 RTP Payload Format for High Efficiency Video Coding (HEVC)
  2. #include "rtp-packet.h"
  3. #include "rtp-payload-internal.h"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <errno.h>
  8. /*
  9. 0 1
  10. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  11. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  12. |F| Type | LayerId | TID |
  13. +-------------+-----------------+
  14. Forbidden zero(F) : 1 bit
  15. NAL unit type(Type) : 6 bits
  16. NUH layer ID(LayerId) : 6 bits
  17. NUH temporal ID plus 1 (TID) : 3 bits
  18. */
  19. #define H265_TYPE(v) ((v >> 1) & 0x3f)
  20. #define FU_START(v) (v & 0x80)
  21. #define FU_END(v) (v & 0x40)
  22. #define FU_NAL(v) (v & 0x3F)
  23. struct rtp_decode_h265_t
  24. {
  25. struct rtp_payload_t handler;
  26. void* cbparam;
  27. uint16_t seq; // rtp seq
  28. uint32_t timestamp;
  29. uint8_t* ptr;
  30. int size, capacity;
  31. int flags;
  32. int using_donl_field;
  33. };
  34. static void* rtp_h265_unpack_create(struct rtp_payload_t *handler, void* param)
  35. {
  36. struct rtp_decode_h265_t *unpacker;
  37. unpacker = (struct rtp_decode_h265_t *)calloc(1, sizeof(*unpacker));
  38. if (!unpacker)
  39. return NULL;
  40. memcpy(&unpacker->handler, handler, sizeof(unpacker->handler));
  41. unpacker->cbparam = param;
  42. unpacker->flags = -1;
  43. return unpacker;
  44. }
  45. static void rtp_h265_unpack_destroy(void* p)
  46. {
  47. struct rtp_decode_h265_t *unpacker;
  48. unpacker = (struct rtp_decode_h265_t *)p;
  49. if (unpacker->ptr)
  50. free(unpacker->ptr);
  51. #if defined(_DEBUG) || defined(DEBUG)
  52. memset(unpacker, 0xCC, sizeof(*unpacker));
  53. #endif
  54. free(unpacker);
  55. }
  56. // 4.4.2. Aggregation Packets (APs) (p25)
  57. /*
  58. 0 1 2 3
  59. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  60. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  61. | RTP Header |
  62. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  63. | PayloadHdr (Type=48) | NALU 1 DONL |
  64. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  65. | NALU 1 Size | NALU 1 HDR |
  66. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  67. | |
  68. | NALU 1 Data . . . |
  69. | |
  70. + . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  71. | | NALU 2 DOND | NALU 2 Size |
  72. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73. | NALU 2 HDR | |
  74. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ NALU 2 Data |
  75. | |
  76. | . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  77. | : ...OPTIONAL RTP padding |
  78. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  79. */
  80. static int rtp_h265_unpack_ap(struct rtp_decode_h265_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp)
  81. {
  82. int r;
  83. int n;
  84. int len;
  85. //uint16_t donl;
  86. //uint16_t dond;
  87. //donl = unpacker->using_donl_field ? nbo_r16(ptr + 2) : 0;
  88. ptr += 2; // PayloadHdr
  89. n = 2 /*LEN*/ + (unpacker->using_donl_field ? 2 : 0);
  90. r = 0;
  91. for (bytes -= 2 /*PayloadHdr*/; 0 == r && bytes > n; bytes -= len + 2)
  92. {
  93. bytes -= n - 2; // skip DON
  94. ptr += n - 2; // skip DON
  95. len = nbo_r16(ptr);
  96. if (len + 2 > bytes)
  97. {
  98. assert(0);
  99. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  100. unpacker->size = 0;
  101. return -EINVAL; // error
  102. }
  103. assert(H265_TYPE(ptr[2]) >= 0 && H265_TYPE(ptr[2]) < 48);
  104. r = unpacker->handler.packet(unpacker->cbparam, ptr + 2, len, timestamp, unpacker->flags);
  105. unpacker->flags = 0;
  106. unpacker->size = 0;
  107. ptr += len + 2; // next NALU
  108. n = 2 /*LEN*/ + (unpacker->using_donl_field ? 1 : 0);
  109. }
  110. return 0 == r ? 1 : r; // packet handled
  111. }
  112. // 4.4.3. Fragmentation Units (p29)
  113. /*
  114. 0 1 2 3
  115. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  116. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  117. | PayloadHdr (Type=49) | FU header | DONL (cond) |
  118. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
  119. | DONL (cond) | |
  120. |-+-+-+-+-+-+-+-+ |
  121. | FU payload |
  122. | |
  123. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  124. | : ...OPTIONAL RTP padding |
  125. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  126. +---------------+
  127. |0|1|2|3|4|5|6|7|
  128. +-+-+-+-+-+-+-+-+
  129. |S|E| FuType |
  130. +---------------+
  131. */
  132. static int rtp_h265_unpack_fu(struct rtp_decode_h265_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp)
  133. {
  134. int r, n;
  135. uint8_t fuheader;
  136. r = 0;
  137. n = 1 /*FU header*/ + (unpacker->using_donl_field ? 4 : 2);
  138. if (bytes < n || unpacker->size + bytes - n > RTP_PAYLOAD_MAX_SIZE)
  139. {
  140. assert(0);
  141. return -EINVAL;
  142. }
  143. if (unpacker->size + bytes - n + 2 /*NALU*/ > unpacker->capacity)
  144. {
  145. void* p = NULL;
  146. int size = unpacker->size + bytes + 2;
  147. size += size / 4 > 128000 ? size / 4 : 128000;
  148. p = realloc(unpacker->ptr, size);
  149. if (!p)
  150. {
  151. // set packet lost flag
  152. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  153. unpacker->size = 0;
  154. return -ENOMEM;
  155. }
  156. unpacker->ptr = (uint8_t*)p;
  157. unpacker->capacity = size;
  158. }
  159. fuheader = ptr[2];
  160. if (FU_START(fuheader))
  161. {
  162. #if 0
  163. if (unpacker->size > 0)
  164. {
  165. unpacker->flags |= RTP_PAYLOAD_FLAG_PACKET_CORRUPT;
  166. unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, unpacker->timestamp, unpacker->flags);
  167. unpacker->flags = 0;
  168. unpacker->size = 0; // reset
  169. }
  170. #endif
  171. assert(unpacker->capacity > 2);
  172. unpacker->size = 2; // NAL unit type byte
  173. unpacker->ptr[0] = (FU_NAL(fuheader) << 1) | (ptr[0] & 0x81); // replace NAL Unit Type Bits
  174. unpacker->ptr[1] = ptr[1];
  175. assert(H265_TYPE(unpacker->ptr[0]) >= 0 && H265_TYPE(unpacker->ptr[0]) <= 63);
  176. }
  177. else
  178. {
  179. if (0 == unpacker->size)
  180. {
  181. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  182. return 0; // packet discard
  183. }
  184. assert(unpacker->size > 0);
  185. }
  186. unpacker->timestamp = timestamp;
  187. if (bytes > n)
  188. {
  189. assert(unpacker->capacity >= unpacker->size + bytes - n);
  190. memmove(unpacker->ptr + unpacker->size, ptr + n, bytes - n);
  191. unpacker->size += bytes - n;
  192. }
  193. if (FU_END(fuheader))
  194. {
  195. r = unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, timestamp, unpacker->flags);
  196. unpacker->flags = 0;
  197. unpacker->size = 0;
  198. }
  199. return 0 == r ? 1 : r; // packet handled
  200. }
  201. static int rtp_h265_unpack_input(void* p, const void* packet, int bytes)
  202. {
  203. int r, nal;
  204. const uint8_t* ptr;
  205. struct rtp_packet_t pkt;
  206. struct rtp_decode_h265_t *unpacker;
  207. unpacker = (struct rtp_decode_h265_t *)p;
  208. if (!unpacker || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < (unpacker->using_donl_field ? 5 : 3))
  209. return -EINVAL;
  210. if (-1 == unpacker->flags)
  211. {
  212. unpacker->flags = 0;
  213. unpacker->seq = (uint16_t)(pkt.rtp.seq - 1); // disable packet lost
  214. }
  215. if ((uint16_t)pkt.rtp.seq != (uint16_t)(unpacker->seq + 1))
  216. {
  217. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  218. unpacker->size = 0; // discard previous packets
  219. }
  220. unpacker->seq = (uint16_t)pkt.rtp.seq;
  221. assert(pkt.payloadlen > 2);
  222. ptr = (const uint8_t*)pkt.payload;
  223. nal = H265_TYPE(ptr[0]);
  224. if (nal > 50)
  225. return 0; // packet discard, Unsupported (HEVC) NAL type
  226. switch (nal)
  227. {
  228. case 48: // aggregated packet (AP) - with two or more NAL units
  229. return rtp_h265_unpack_ap(unpacker, ptr, pkt.payloadlen, pkt.rtp.timestamp);
  230. case 49: // fragmentation unit (FU)
  231. return rtp_h265_unpack_fu(unpacker, ptr, pkt.payloadlen, pkt.rtp.timestamp);
  232. case 50: // TODO: 4.4.4. PACI Packets (p32)
  233. assert(0);
  234. return 0; // packet discard
  235. case 32: // video parameter set (VPS)
  236. case 33: // sequence parameter set (SPS)
  237. case 34: // picture parameter set (PPS)
  238. case 39: // supplemental enhancement information (SEI)
  239. default: // 4.4.1. Single NAL Unit Packets (p24)
  240. r = unpacker->handler.packet(unpacker->cbparam, ptr, pkt.payloadlen, pkt.rtp.timestamp, unpacker->flags);
  241. unpacker->flags = 0;
  242. unpacker->size = 0;
  243. return 0 == r ? 1 : r; // packet handled
  244. }
  245. }
  246. struct rtp_payload_decode_t *rtp_h265_decode()
  247. {
  248. static struct rtp_payload_decode_t unpacker = {
  249. rtp_h265_unpack_create,
  250. rtp_h265_unpack_destroy,
  251. rtp_h265_unpack_input,
  252. };
  253. return &unpacker;
  254. }