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.

344 lines
11KB

  1. // RFC6184 RTP Payload Format for H.264 Video
  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. #define H264_NAL(v) (v & 0x1F)
  9. #define FU_START(v) (v & 0x80)
  10. #define FU_END(v) (v & 0x40)
  11. #define FU_NAL(v) (v & 0x1F)
  12. struct rtp_decode_h264_t
  13. {
  14. struct rtp_payload_t handler;
  15. void* cbparam;
  16. uint16_t seq; // rtp seq
  17. uint32_t timestamp;
  18. uint8_t* ptr;
  19. int size, capacity;
  20. int flags;
  21. };
  22. static void* rtp_h264_unpack_create(struct rtp_payload_t *handler, void* param)
  23. {
  24. struct rtp_decode_h264_t *unpacker;
  25. unpacker = (struct rtp_decode_h264_t *)calloc(1, sizeof(*unpacker));
  26. if(!unpacker)
  27. return NULL;
  28. memcpy(&unpacker->handler, handler, sizeof(unpacker->handler));
  29. unpacker->cbparam = param;
  30. unpacker->flags = -1;
  31. return unpacker;
  32. }
  33. static void rtp_h264_unpack_destroy(void* p)
  34. {
  35. struct rtp_decode_h264_t *unpacker;
  36. unpacker = (struct rtp_decode_h264_t *)p;
  37. if(unpacker->ptr)
  38. free(unpacker->ptr);
  39. #if defined(_DEBUG) || defined(DEBUG)
  40. memset(unpacker, 0xCC, sizeof(*unpacker));
  41. #endif
  42. free(unpacker);
  43. }
  44. // 5.7.1. Single-Time Aggregation Packet (STAP) (p23)
  45. /*
  46. 0 1 2 3
  47. 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
  48. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  49. | RTP Header |
  50. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  51. |STAP-B NAL HDR | DON | NALU 1 Size |
  52. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  53. | NALU 1 Size | NALU 1 HDR | NALU 1 Data |
  54. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
  55. : :
  56. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  57. | | NALU 2 Size | NALU 2 HDR |
  58. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  59. | NALU 2 Data |
  60. : :
  61. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  62. | : ...OPTIONAL RTP padding |
  63. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64. */
  65. static int rtp_h264_unpack_stap(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp, int stap_b)
  66. {
  67. int r, n;
  68. uint16_t len;
  69. uint16_t don;
  70. r = 0;
  71. n = stap_b ? 3 : 1;
  72. if (bytes < n)
  73. {
  74. assert(0);
  75. return -EINVAL; // error
  76. }
  77. don = stap_b ? nbo_r16(ptr + 1) : 0;
  78. ptr += n; // STAP-A / STAP-B HDR + DON
  79. for(bytes -= n; 0 == r && bytes > 2; bytes -= len + 2)
  80. {
  81. len = nbo_r16(ptr);
  82. if(len + 2 > bytes)
  83. {
  84. assert(0);
  85. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  86. unpacker->size = 0;
  87. return -EINVAL; // error
  88. }
  89. assert(H264_NAL(ptr[2]) > 0 && H264_NAL(ptr[2]) < 24);
  90. r = unpacker->handler.packet(unpacker->cbparam, ptr + 2, len, timestamp, unpacker->flags);
  91. unpacker->flags = 0;
  92. unpacker->size = 0;
  93. ptr += len + 2; // next NALU
  94. don = (don + 1) % 65536;
  95. }
  96. return 0 == r ? 1 : r; // packet handled
  97. }
  98. // 5.7.2. Multi-Time Aggregation Packets (MTAPs) (p27)
  99. /*
  100. 0 1 2 3
  101. 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
  102. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  103. | RTP Header |
  104. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  105. |MTAP16 NAL HDR | decoding order number base | NALU 1 Size |
  106. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  107. | NALU 1 Size | NALU 1 DOND | NALU 1 TS offset |
  108. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  109. | NALU 1 HDR | NALU 1 DATA |
  110. +-+-+-+-+-+-+-+-+ +
  111. : :
  112. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  113. | | NALU 2 SIZE | NALU 2 DOND |
  114. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  115. | NALU 2 TS offset | NALU 2 HDR | NALU 2 DATA |
  116. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
  117. : :
  118. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  119. | : ...OPTIONAL RTP padding |
  120. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  121. */
  122. static int rtp_h264_unpack_mtap(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp, int n)
  123. {
  124. int r;
  125. //uint16_t dond;
  126. uint16_t donb;
  127. uint16_t len;
  128. uint32_t ts;
  129. r = 0;
  130. if (bytes < 3)
  131. {
  132. assert(0);
  133. return -EINVAL; // error
  134. }
  135. donb = nbo_r16(ptr + 1);
  136. ptr += 3; // MTAP16/MTAP24 HDR + DONB
  137. for(bytes -= 3; 0 == r && n + 3 < bytes; bytes -= len + 2)
  138. {
  139. len = nbo_r16(ptr);
  140. if(len + 2 > bytes || len < 1 /*DOND*/ + n /*TS offset*/ + 1 /*NALU*/)
  141. {
  142. assert(0);
  143. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  144. unpacker->size = 0;
  145. return -EINVAL; // error
  146. }
  147. //dond = (ptr[2] + donb) % 65536;
  148. ts = (uint16_t)nbo_r16(ptr + 3);
  149. if (3 == n) ts = (ts << 16) | ptr[5]; // MTAP24
  150. // if the NALU-time is larger than or equal to the RTP timestamp of the packet,
  151. // then the timestamp offset equals (the NALU - time of the NAL unit - the RTP timestamp of the packet).
  152. // If the NALU - time is smaller than the RTP timestamp of the packet,
  153. // then the timestamp offset is equal to the NALU - time + (2 ^ 32 - the RTP timestamp of the packet).
  154. ts += timestamp; // wrap 1 << 32
  155. assert(H264_NAL(ptr[n + 3]) > 0 && H264_NAL(ptr[n + 3]) < 24);
  156. r = unpacker->handler.packet(unpacker->cbparam, ptr + 1 + n, len - 1 - n, ts, unpacker->flags);
  157. unpacker->flags = 0;
  158. unpacker->size = 0;
  159. ptr += len + 2; // next NALU
  160. }
  161. return 0 == r ? 1 : r; // packet handled
  162. }
  163. // 5.8. Fragmentation Units (FUs) (p29)
  164. /*
  165. 0 1 2 3
  166. 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
  167. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  168. | FU indicator | FU header | DON |
  169. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
  170. | |
  171. | FU payload |
  172. | |
  173. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  174. | : ...OPTIONAL RTP padding |
  175. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  176. */
  177. static int rtp_h264_unpack_fu(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp, int fu_b)
  178. {
  179. int r, n;
  180. uint8_t fuheader;
  181. //uint16_t don;
  182. r = 0;
  183. n = fu_b ? 4 : 2;
  184. if (bytes < n || unpacker->size + bytes - n > RTP_PAYLOAD_MAX_SIZE)
  185. {
  186. assert(0);
  187. return -EINVAL; // error
  188. }
  189. if (unpacker->size + bytes - n + 1 /*NALU*/ > unpacker->capacity)
  190. {
  191. void* p = NULL;
  192. int size = unpacker->size + bytes + 1;
  193. size += size / 4 > 128000 ? size / 4 : 128000;
  194. p = realloc(unpacker->ptr, size);
  195. if (!p)
  196. {
  197. // set packet lost flag
  198. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  199. unpacker->size = 0;
  200. return -ENOMEM; // error
  201. }
  202. unpacker->ptr = (uint8_t*)p;
  203. unpacker->capacity = size;
  204. }
  205. fuheader = ptr[1];
  206. //don = nbo_r16(ptr + 2);
  207. if (FU_START(fuheader))
  208. {
  209. #if 0
  210. if (unpacker->size > 0)
  211. {
  212. unpacker->flags |= RTP_PAYLOAD_FLAG_PACKET_CORRUPT;
  213. unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, unpacker->timestamp, unpacker->flags);
  214. unpacker->flags = 0;
  215. unpacker->size = 0; // reset
  216. }
  217. #endif
  218. unpacker->size = 1; // NAL unit type byte
  219. unpacker->ptr[0] = (ptr[0]/*indicator*/ & 0xE0) | (fuheader & 0x1F);
  220. assert(H264_NAL(unpacker->ptr[0]) > 0 && H264_NAL(unpacker->ptr[0]) < 24);
  221. }
  222. else
  223. {
  224. if (0 == unpacker->size)
  225. {
  226. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  227. return 0; // packet discard
  228. }
  229. assert(unpacker->size > 0);
  230. }
  231. unpacker->timestamp = timestamp;
  232. if (bytes > n)
  233. {
  234. assert(unpacker->capacity >= unpacker->size + bytes - n);
  235. memmove(unpacker->ptr + unpacker->size, ptr + n, bytes - n);
  236. unpacker->size += bytes - n;
  237. }
  238. if(FU_END(fuheader))
  239. {
  240. if(unpacker->size > 0)
  241. r = unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, timestamp, unpacker->flags);
  242. unpacker->flags = 0;
  243. unpacker->size = 0; // reset
  244. }
  245. return 0 == r ? 1 : r; // packet handled
  246. }
  247. static int rtp_h264_unpack_input(void* p, const void* packet, int bytes)
  248. {
  249. int r;
  250. uint8_t nalt;
  251. struct rtp_packet_t pkt;
  252. struct rtp_decode_h264_t *unpacker;
  253. unpacker = (struct rtp_decode_h264_t *)p;
  254. if(!unpacker || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < 1)
  255. return -EINVAL;
  256. if (-1 == unpacker->flags)
  257. {
  258. unpacker->flags = 0;
  259. unpacker->seq = (uint16_t)(pkt.rtp.seq - 1); // disable packet lost
  260. }
  261. if ((uint16_t)pkt.rtp.seq != (uint16_t)(unpacker->seq + 1))
  262. {
  263. unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;
  264. unpacker->size = 0; // discard previous packets
  265. }
  266. unpacker->seq = (uint16_t)pkt.rtp.seq;
  267. nalt = ((unsigned char *)pkt.payload)[0];
  268. switch(nalt & 0x1F)
  269. {
  270. case 0: // reserved
  271. case 31: // reserved
  272. assert(0);
  273. return 0; // packet discard
  274. case 24: // STAP-A
  275. return rtp_h264_unpack_stap(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 0);
  276. case 25: // STAP-B
  277. return rtp_h264_unpack_stap(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 1);
  278. case 26: // MTAP16
  279. return rtp_h264_unpack_mtap(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 2);
  280. case 27: // MTAP24
  281. return rtp_h264_unpack_mtap(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 3);
  282. case 28: // FU-A
  283. return rtp_h264_unpack_fu(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 0);
  284. case 29: // FU-B
  285. return rtp_h264_unpack_fu(unpacker, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, 1);
  286. default: // 1-23 NAL unit
  287. r = unpacker->handler.packet(unpacker->cbparam, (const uint8_t*)pkt.payload, pkt.payloadlen, pkt.rtp.timestamp, unpacker->flags);
  288. unpacker->flags = 0;
  289. unpacker->size = 0;
  290. return 0 == r ? 1 : r; // packet handled
  291. }
  292. }
  293. struct rtp_payload_decode_t *rtp_h264_decode()
  294. {
  295. static struct rtp_payload_decode_t unpacker = {
  296. rtp_h264_unpack_create,
  297. rtp_h264_unpack_destroy,
  298. rtp_h264_unpack_input,
  299. };
  300. return &unpacker;
  301. }