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.

129 lines
3.7KB

  1. #include "rtmp-internal.h"
  2. #include "rtmp-msgtypeid.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #define RTMP_MESSAGE_HEADER_LENGTH 11 // RTMP 6.1.1
  8. static int rtmp_audio(struct rtmp_t* rtmp, const uint8_t* payload, uint32_t bytes, uint32_t timestamp)
  9. {
  10. return rtmp->onaudio(rtmp->param, payload, bytes, timestamp);
  11. }
  12. static int rtmp_video(struct rtmp_t* rtmp, const uint8_t* payload, uint32_t bytes, uint32_t timestamp)
  13. {
  14. return rtmp->onvideo(rtmp->param, payload, bytes, timestamp);
  15. }
  16. static int rtmp_script(struct rtmp_t* rtmp, const uint8_t* payload, uint32_t bytes, uint32_t timestamp)
  17. {
  18. // filter @setDataFrame
  19. const static uint8_t s_setFrameData[] = { 0x02, 0x00, 0x0d, 0x40, 0x73, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65 };
  20. if (bytes > sizeof(s_setFrameData) && 0 == memcmp(s_setFrameData, payload, sizeof(s_setFrameData)))
  21. return rtmp->onscript(rtmp->param, payload + sizeof(s_setFrameData), bytes - sizeof(s_setFrameData), timestamp);
  22. return rtmp->onscript(rtmp->param, payload, bytes, timestamp);
  23. }
  24. static int rtmp_aggregate(struct rtmp_t* rtmp, struct rtmp_chunk_header_t* header, const uint8_t* payload)
  25. {
  26. int r;
  27. uint32_t i;
  28. uint32_t n;
  29. uint32_t t, t0, timestamp;
  30. timestamp = header->timestamp;
  31. for (t0 = i = r = 0; i + RTMP_MESSAGE_HEADER_LENGTH + 4 /*previous tag size*/ < header->length && 0 == r; i+= n + RTMP_MESSAGE_HEADER_LENGTH + 4)
  32. {
  33. n = ((uint32_t)payload[i + 1] << 16) | ((uint32_t)payload[i + 2] << 8) | payload[i + 3];
  34. t = ((uint32_t)payload[i + 4] << 16) | ((uint32_t)payload[i + 5] << 8) | payload[i + 6] | ((uint32_t)payload[i + 7] << 24);
  35. if (i + n + RTMP_MESSAGE_HEADER_LENGTH + 4 > header->length)
  36. {
  37. assert(0);
  38. return 0; // ignore
  39. }
  40. if (0 != i)
  41. timestamp += t - t0;
  42. t0 = t;
  43. switch (payload[i])
  44. {
  45. case RTMP_TYPE_AUDIO:
  46. r = rtmp_audio(rtmp, payload + i + RTMP_MESSAGE_HEADER_LENGTH, n, timestamp);
  47. break;
  48. case RTMP_TYPE_VIDEO:
  49. r = rtmp_video(rtmp, payload + i + RTMP_MESSAGE_HEADER_LENGTH, n, timestamp);
  50. break;
  51. case RTMP_TYPE_DATA:
  52. r = rtmp_script(rtmp, payload + i + RTMP_MESSAGE_HEADER_LENGTH, n, timestamp);
  53. break;
  54. default:
  55. assert(0);
  56. r = 0;
  57. break;
  58. }
  59. }
  60. assert(r || i == header->length);
  61. return r;
  62. }
  63. int rtmp_handler(struct rtmp_t* rtmp, struct rtmp_chunk_header_t* header, const uint8_t* payload)
  64. {
  65. switch (header->type)
  66. {
  67. case RTMP_TYPE_FLEX_MESSAGE:
  68. // filter AMF3 0x00
  69. payload += (header->length > 0) ? 1 : 0; // fix header->length = 0
  70. header->length -= (header->length > 0) ? 1 : 0;
  71. return rtmp_invoke_handler(rtmp, header, payload);
  72. case RTMP_TYPE_INVOKE:
  73. return rtmp_invoke_handler(rtmp, header, payload);
  74. case RTMP_TYPE_VIDEO:
  75. return rtmp_video(rtmp, payload, header->length, header->timestamp);
  76. case RTMP_TYPE_AUDIO:
  77. return rtmp_audio(rtmp, payload, header->length, header->timestamp);
  78. case RTMP_TYPE_EVENT:
  79. // User Control Message Events
  80. return 0 == rtmp_event_handler(rtmp, header, payload) ? -1 : 0;
  81. // Protocol Control Messages
  82. case RTMP_TYPE_SET_CHUNK_SIZE:
  83. case RTMP_TYPE_ABORT:
  84. case RTMP_TYPE_ACKNOWLEDGEMENT:
  85. case RTMP_TYPE_WINDOW_ACKNOWLEDGEMENT_SIZE:
  86. case RTMP_TYPE_SET_PEER_BANDWIDTH:
  87. return 0 == rtmp_control_handler(rtmp, header, payload) ? -1 : 0;
  88. case RTMP_TYPE_DATA:
  89. case RTMP_TYPE_FLEX_STREAM:
  90. // play -> RtmpSampleAccess
  91. // finish -> onPlayStatus("NetStream.Play.Complete")
  92. return rtmp_script(rtmp, payload, header->length, header->timestamp);
  93. case RTMP_TYPE_SHARED_OBJECT:
  94. case RTMP_TYPE_FLEX_OBJECT:
  95. break;
  96. case RTMP_TYPE_METADATA:
  97. return rtmp_aggregate(rtmp, header, payload);
  98. default:
  99. assert(0);
  100. printf("%s: unknown rtmp header type: %d\n", __FUNCTION__, (int)header->type);
  101. break;
  102. }
  103. return 0;
  104. }