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.

171 lines
4.5KB

  1. // RFC7741 RTP Payload Format for VP8 Video
  2. #include "rtp-packet.h"
  3. #include "rtp-profile.h"
  4. #include "rtp-payload-helper.h"
  5. #include "rtp-payload-internal.h"
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <errno.h>
  11. /*
  12. 0 1 2 3
  13. 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
  14. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  15. |V=2|P|X| CC |M| PT | sequence number |
  16. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  17. | timestamp |
  18. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19. | synchronization source (SSRC) identifier |
  20. +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  21. | contributing source (CSRC) identifiers |
  22. | .... |
  23. +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  24. | VP8 payload descriptor (integer #octets) |
  25. : :
  26. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  27. | : VP8 payload header (3 octets) |
  28. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  29. | VP8 pyld hdr : |
  30. +-+-+-+-+-+-+-+-+ |
  31. : Octets 4..N of VP8 payload :
  32. | |
  33. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  34. | : OPTIONAL RTP padding |
  35. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. */
  37. static int rtp_decode_vp8(void* p, const void* packet, int bytes)
  38. {
  39. uint8_t extended_control_bits;
  40. uint8_t start_of_vp8_partition;
  41. //uint8_t PID;
  42. const uint8_t *ptr, *pend;
  43. struct rtp_packet_t pkt;
  44. struct rtp_payload_helper_t *helper;
  45. helper = (struct rtp_payload_helper_t *)p;
  46. if (!helper || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < 1)
  47. return -EINVAL;
  48. rtp_payload_check(helper, &pkt);
  49. ptr = (const uint8_t *)pkt.payload;
  50. pend = ptr + pkt.payloadlen;
  51. // VP8 payload descriptor
  52. extended_control_bits = ptr[0] & 0x80;
  53. start_of_vp8_partition = ptr[0] & 0x10;
  54. //PID = ptr[0] & 0x0f;
  55. ptr++;
  56. if (extended_control_bits && ptr < pend)
  57. {
  58. /*
  59. 0 1 2 3 4 5 6 7
  60. +-+-+-+-+-+-+-+-+
  61. |X|R|N|S|R| PID | (REQUIRED)
  62. +-+-+-+-+-+-+-+-+
  63. X: |I|L|T|K| RSV | (OPTIONAL)
  64. +-+-+-+-+-+-+-+-+
  65. I: |M| PictureID | (OPTIONAL)
  66. +-+-+-+-+-+-+-+-+
  67. | PictureID |
  68. +-+-+-+-+-+-+-+-+
  69. L: | TL0PICIDX | (OPTIONAL)
  70. +-+-+-+-+-+-+-+-+
  71. T/K:|TID|Y| KEYIDX | (OPTIONAL)
  72. +-+-+-+-+-+-+-+-+
  73. */
  74. uint8_t pictureid_present;
  75. uint8_t tl0picidx_present;
  76. uint8_t tid_present;
  77. uint8_t keyidx_present;
  78. pictureid_present = ptr[0] & 0x80;
  79. tl0picidx_present = ptr[0] & 0x40;
  80. tid_present = ptr[0] & 0x20;
  81. keyidx_present = ptr[0] & 0x10;
  82. ptr++;
  83. if (pictureid_present && ptr < pend)
  84. {
  85. uint16_t picture_id;
  86. picture_id = ptr[0] & 0x7F;
  87. if ((ptr[0] & 0x80) && ptr + 1 < pend)
  88. {
  89. picture_id = (picture_id << 8) | ptr[1];
  90. ptr++;
  91. }
  92. ptr++;
  93. }
  94. if (tl0picidx_present && ptr < pend)
  95. {
  96. // ignore temporal level zero index
  97. ptr++;
  98. }
  99. if ((tid_present || keyidx_present) && ptr < pend)
  100. {
  101. // ignore KEYIDX
  102. ptr++;
  103. }
  104. }
  105. if (ptr >= pend)
  106. {
  107. assert(0);
  108. //helper->size = 0;
  109. helper->lost = 1;
  110. //helper->flags |= RTP_PAYLOAD_FLAG_PACKET_LOST;
  111. return -1; // invalid packet
  112. }
  113. // VP8 payload header (3 octets)
  114. if (start_of_vp8_partition)
  115. {
  116. /*
  117. 0 1 2 3 4 5 6 7
  118. +-+-+-+-+-+-+-+-+
  119. |Size0|H| VER |P|
  120. +-+-+-+-+-+-+-+-+
  121. | Size1 |
  122. +-+-+-+-+-+-+-+-+
  123. | Size2 |
  124. +-+-+-+-+-+-+-+-+
  125. */
  126. // P: Inverse key frame flag. When set to 0, the current frame is a key
  127. // frame. When set to 1, the current frame is an interframe.
  128. // Defined in [RFC6386]
  129. //int keyframe;
  130. //keyframe = ptr[0] & 0x01; // PID == 0
  131. // new frame begin
  132. rtp_payload_onframe(helper);
  133. }
  134. pkt.payload = ptr;
  135. pkt.payloadlen = (int)(pend - ptr);
  136. rtp_payload_write(helper, &pkt);
  137. if (pkt.rtp.m)
  138. {
  139. rtp_payload_onframe(helper);
  140. }
  141. return 1; // packet handled
  142. }
  143. struct rtp_payload_decode_t *rtp_vp8_decode()
  144. {
  145. static struct rtp_payload_decode_t unpacker = {
  146. rtp_payload_helper_create,
  147. rtp_payload_helper_destroy,
  148. rtp_decode_vp8,
  149. };
  150. return &unpacker;
  151. }