Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

97 wiersze
3.3KB

  1. // RFC6184 RTP Payload Format for H.264 Video
  2. #include "mpeg4-avc.h"
  3. #include "sdp-payload.h"
  4. #include "base64.h"
  5. #include <stdio.h>
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <assert.h>
  10. #include <errno.h>
  11. int sdp_h264(uint8_t *data, int bytes, const char* proto, unsigned short port, int payload, int frequence, const void* extra, int extra_size)
  12. {
  13. static const char* pattern =
  14. "m=video %hu %s %d\n"
  15. "a=rtpmap:%d H264/90000\n"
  16. "a=fmtp:%d packetization-mode=1;profile-level-id=%02X%02X%02X;sprop-parameter-sets=";
  17. int r, n;
  18. uint8_t i;
  19. struct mpeg4_avc_t avc;
  20. assert(90000 == frequence);
  21. r = mpeg4_avc_decoder_configuration_record_load((const uint8_t*)extra, extra_size, &avc);
  22. if (r < 0) return r;
  23. assert(avc.nb_pps + avc.nb_sps > 0);
  24. n = snprintf((char*)data, bytes, pattern, port, proto && *proto ? proto : "RTP/AVP", payload, payload, payload,
  25. (unsigned int)avc.profile, (unsigned int)avc.compatibility, (unsigned int)avc.level);
  26. for (i = 0; i < avc.nb_sps; i++)
  27. {
  28. if (n + 1 + avc.sps[i].bytes * 2 > bytes)
  29. return -ENOMEM; // // don't have enough memory
  30. if (i > 0 && n < bytes) data[n++] = ',';
  31. n += (int)base64_encode((char*)data + n, avc.sps[i].data, avc.sps[i].bytes);
  32. }
  33. for (i = 0; i < avc.nb_pps; i++)
  34. {
  35. if (n + 1 + avc.sps[i].bytes * 2 > bytes)
  36. return -ENOMEM; // // don't have enough memory
  37. if (n < bytes) data[n++] = ',';
  38. n += (int)base64_encode((char*)data + n, avc.pps[i].data, avc.pps[i].bytes);
  39. }
  40. if (n < bytes)
  41. data[n++] = '\n';
  42. return n;
  43. }
  44. int sdp_h264_load(uint8_t* data, int bytes, const char* config)
  45. {
  46. int n, len, off;
  47. const char* p, *next;
  48. const uint8_t startcode[] = { 0x00, 0x00, 0x00, 0x01 };
  49. off = 0;
  50. p = config;
  51. while (p)
  52. {
  53. next = strchr(p, ',');
  54. len = next ? (int)(next - p) : (int)strlen(p);
  55. if (off + (len + 3) / 4 * 3 + (int)sizeof(startcode) > bytes)
  56. return -ENOMEM; // don't have enough space
  57. memcpy(data + off, startcode, sizeof(startcode));
  58. n = (int)base64_decode(data + off + sizeof(startcode), p, len);
  59. assert(n <= (len + 3) / 4 * 3);
  60. off += n + sizeof(startcode);
  61. p = next ? next + 1 : NULL;
  62. }
  63. return off;
  64. }
  65. #if defined(_DEBUG) || defined(DEBUG)
  66. void sdp_h264_test(void)
  67. {
  68. const char* sdp = "m=video 0 RTP/AVP 96\na=rtpmap:96 H264/90000\na=fmtp:96 packetization-mode=1;profile-level-id=64001F;sprop-parameter-sets=Z2QAH6zZQFAFumoCGgKAAAADAIAAAB5HjBjL,aO+8sA==\n";
  69. const char* config = "Z2QAH6zZQFAFumoCGgKAAAADAIAAAB5HjBjL,aO+8sA==";
  70. static const uint8_t extra[] = { 0x01, 0x64, 0x00, 0x1f, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50, 0x05, 0xba, 0x6a, 0x02, 0x1a, 0x02, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x1e, 0x47, 0x8c, 0x18, 0xcb, 0x01, 0x00, 0x04, 0x68, 0xef, 0xbc, 0xb0 };
  71. static const uint8_t ps[] = { 0x00, 0x00, 0x00, 0x1, 0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50, 0x05, 0xba, 0x6a, 0x02, 0x1a, 0x02, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x1e, 0x47, 0x8c, 0x18, 0xcb, 0x00, 0x00, 0x00, 0x1, 0x68, 0xef, 0xbc, 0xb0 };
  72. uint8_t buffer[256];
  73. assert((int)strlen(sdp) == sdp_h264(buffer, sizeof(buffer), "RTP/AVP", 0, 96, 90000, extra, sizeof(extra)));
  74. assert(0 == memcmp(sdp, buffer, strlen(sdp)));
  75. assert(sizeof(ps) == sdp_h264_load(buffer, sizeof(buffer), config));
  76. assert(0 == memcmp(buffer, ps, sizeof(ps)));
  77. }
  78. #endif