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.

141 lines
2.8KB

  1. #include <string.h>
  2. #include <assert.h>
  3. #include <stdint.h>
  4. #include <stddef.h>
  5. #define RTP_H2645_BITSTREAM_FORMAT_DETECT 1
  6. static const uint8_t* h264_startcode(const uint8_t* data, int bytes)
  7. {
  8. int i;
  9. for (i = 2; i + 1 < bytes; i++)
  10. {
  11. if (0x01 == data[i] && 0x00 == data[i - 1] && 0x00 == data[i - 2])
  12. return data + i + 1;
  13. }
  14. return NULL;
  15. }
  16. /// @return >0-ok, <=0-error
  17. static inline int h264_avcc_length(const uint8_t* h264, int bytes, int avcc)
  18. {
  19. int i;
  20. uint32_t n;
  21. n = 0;
  22. assert(3 <= avcc && avcc <= 4);
  23. for (i = 0; i < avcc && i < bytes; i++)
  24. n = (n << 8) | h264[i];
  25. return avcc >= bytes ? -1 : (int)n;
  26. }
  27. /// @return 1-true, 0-false
  28. static int h264_avcc_bitstream_valid(const uint8_t* h264, int bytes, int avcc)
  29. {
  30. int n;
  31. while (avcc + 1 < bytes)
  32. {
  33. n = h264_avcc_length(h264, bytes, avcc);
  34. if (n < 0 || n + avcc > bytes)
  35. return 0; // invalid
  36. h264 += n + avcc;
  37. bytes -= n + avcc;
  38. }
  39. return 0 == bytes ? 1 : 0;
  40. }
  41. /// @return 0-annexb, >0-avcc, <0-error
  42. static int h264_bitstream_format(const uint8_t* h264, int bytes)
  43. {
  44. uint32_t n;
  45. if (bytes < 4)
  46. return -1;
  47. n = ((uint32_t)h264[0]) << 16 | ((uint32_t)h264[1]) << 8 | ((uint32_t)h264[2]);
  48. if (0 == n && h264[3] <= 1)
  49. {
  50. return 0; // annexb
  51. }
  52. else if (1 == n)
  53. {
  54. // try avcc & annexb
  55. return h264_avcc_bitstream_valid(h264, bytes, 4) ? 4 : 0;
  56. }
  57. else
  58. {
  59. // try avcc 4/3 bytes
  60. return h264_avcc_bitstream_valid(h264, bytes, 4) ? 4 : (h264_avcc_bitstream_valid(h264, bytes, 3) ? 3 : -1);
  61. }
  62. }
  63. static int h264_avcc_nalu(const void* h264, int bytes, int avcc, int (*handler)(void* param, const uint8_t* nalu, int bytes, int last), void* param)
  64. {
  65. int r;
  66. uint32_t n;
  67. const uint8_t* p, * end;
  68. r = 0;
  69. p = (const uint8_t*)h264;
  70. end = (const uint8_t*)h264 + bytes;
  71. for (n = h264_avcc_length(p, (int)(end - p), avcc); 0 == r && p + n + avcc <= end; n = h264_avcc_length(p, (int)(end - p), avcc))
  72. {
  73. assert(n > 0);
  74. if (n > 0)
  75. {
  76. r = handler(param, p + avcc, (int)n, p + avcc + n < end ? 0 : 1);
  77. }
  78. p += n + avcc;
  79. }
  80. return r;
  81. }
  82. ///@param[in] h264 H.264 byte stream format data(A set of NAL units)
  83. int rtp_h264_annexb_nalu(const void* h264, int bytes, int (*handler)(void* param, const uint8_t* nalu, int bytes, int last), void* param)
  84. {
  85. int r;
  86. ptrdiff_t n;
  87. const uint8_t* p, * next, * end;
  88. #if defined(RTP_H2645_BITSTREAM_FORMAT_DETECT)
  89. int avcc;
  90. avcc = h264_bitstream_format(h264, bytes);
  91. if (avcc > 0)
  92. return h264_avcc_nalu(h264, bytes, avcc, handler, param);
  93. #endif
  94. end = (const uint8_t*)h264 + bytes;
  95. p = h264_startcode((const uint8_t*)h264, bytes);
  96. r = 0;
  97. while (p && 0 == r)
  98. {
  99. next = h264_startcode(p, (int)(end - p));
  100. if (next)
  101. {
  102. n = next - p - 3;
  103. }
  104. else
  105. {
  106. n = end - p;
  107. }
  108. while (n > 0 && 0 == p[n - 1]) n--; // filter tailing zero
  109. assert(n > 0);
  110. if (n > 0)
  111. {
  112. r = handler(param, p, (int)n, next ? 0 : 1);
  113. }
  114. p = next;
  115. }
  116. return r;
  117. }