No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

246 líneas
8.5KB

  1. #include "rtmp-internal.h"
  2. #include "amf0.h"
  3. #include <errno.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #if defined(_WIN32) || defined(_WIN64)
  9. #define strcasecmp _stricmp
  10. #endif
  11. struct rtmp_result_t
  12. {
  13. char code[64]; // NetStream.Play.Start
  14. char level[8]; // warning/status/error
  15. char description[256];
  16. };
  17. //static const char* s_rtmp_command_code[] = {
  18. // "NetConnection.Connect.Success",
  19. // "NetConnection.Connect.Closed",
  20. // "NetConnection.Connect.Failed",
  21. // "NetConnection.Connect.AppShutdown",
  22. // "NetConnection.Connect.InvalidApp",
  23. // "NetConnection.Connect.Rejected",
  24. //
  25. // "NetStream.Failed",
  26. // "NetStream.Play.Failed",
  27. // "NetStream.Play.StreamNotFound",
  28. // "NetStream.Play.Start",
  29. // "NetStream.Play.Stop",
  30. // "NetStream.Play.Complete",
  31. // "NetStream.Play.PublishNotify",
  32. // "NetStream.Play.UnpublishNotify",
  33. // "NetStream.Seek.Notify",
  34. // "NetStream.Seek.Failed",
  35. // "NetStream.Pause.Notify",
  36. // "NetStream.Unpause.Notify",
  37. // "NetStream.Publish.Start",
  38. // "NetStream.Publish.BadName",
  39. // "NetStream.Unpublish.Success",
  40. // "NetStream.Record.Failed",
  41. // "NetStream.Record.NoAccess",
  42. // "NetStream.Record.Start",
  43. // "NetStream.Record.Stop",
  44. //};
  45. #define AMF_OBJECT_ITEM_VALUE(v, amf_type, amf_name, amf_value, amf_size) { v.type=amf_type; v.name=amf_name; v.value=amf_value; v.size=amf_size; }
  46. // s -> c
  47. static int rtmp_command_onconnect_reply(struct rtmp_result_t* result, const uint8_t* data, uint32_t bytes)
  48. {
  49. char fmsver[64] = { 0 };
  50. double capabilities = 0;
  51. struct amf_object_item_t prop[2];
  52. struct amf_object_item_t info[3];
  53. struct amf_object_item_t items[2];
  54. AMF_OBJECT_ITEM_VALUE(prop[0], AMF_STRING, "fmsVer", fmsver, sizeof(fmsver));
  55. AMF_OBJECT_ITEM_VALUE(prop[1], AMF_NUMBER, "capabilities", &capabilities, sizeof(capabilities));
  56. AMF_OBJECT_ITEM_VALUE(info[0], AMF_STRING, "code", result->code, sizeof(result->code));
  57. AMF_OBJECT_ITEM_VALUE(info[1], AMF_STRING, "level", result->level, sizeof(result->level));
  58. AMF_OBJECT_ITEM_VALUE(info[2], AMF_STRING, "description", result->description, sizeof(result->description));
  59. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "Properties", prop, sizeof(prop) / sizeof(prop[0]));
  60. AMF_OBJECT_ITEM_VALUE(items[1], AMF_OBJECT, "Information", info, sizeof(info) / sizeof(info[0]));
  61. //rtmp->onstatus();
  62. return amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])) ? 0 : EINVAL;
  63. }
  64. // s -> c
  65. static int rtmp_command_oncreate_stream_reply(const uint8_t* data, uint32_t bytes, double *stream_id)
  66. {
  67. struct amf_object_item_t items[2];
  68. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "command", NULL, 0);
  69. AMF_OBJECT_ITEM_VALUE(items[1], AMF_NUMBER, "streamId", stream_id, 8);
  70. //rtmp->onstatus();
  71. return amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])) ? 0 : EINVAL;
  72. }
  73. // s -> c
  74. static int rtmp_command_onresult(struct rtmp_t* rtmp, double transaction, const uint8_t* data, uint32_t bytes)
  75. {
  76. int r;
  77. double stream_id = 0;
  78. double duration = 0;
  79. struct rtmp_result_t result;
  80. switch ((uint32_t)transaction)
  81. {
  82. case RTMP_TRANSACTION_CONNECT:
  83. // next:
  84. // 1. releaseStream/FCPublish or serverBW/user control message event buffer time
  85. // 2. createStream
  86. // 3. FCSubscribe
  87. r = rtmp_command_onconnect_reply(&result, data, bytes);
  88. return 0 == r ? (rtmp->client.onconnect ? rtmp->client.onconnect(rtmp->param) : -1) : r;
  89. case RTMP_TRANSACTION_CREATE_STREAM:
  90. // next:
  91. // publish
  92. // or play/user control message event buffer time
  93. r = rtmp_command_oncreate_stream_reply(data, bytes, &stream_id);
  94. return 0 == r ? (rtmp->client.oncreate_stream ? rtmp->client.oncreate_stream(rtmp->param, stream_id) : -1) : r;
  95. case RTMP_TRANSACTION_GET_STREAM_LENGTH:
  96. return rtmp_command_oncreate_stream_reply(data, bytes, &duration);
  97. default:
  98. return 0;
  99. }
  100. }
  101. // s -> c
  102. static int rtmp_command_onerror(struct rtmp_t* rtmp, double transaction, const uint8_t* data, uint32_t bytes)
  103. {
  104. struct rtmp_result_t result;
  105. struct amf_object_item_t info[3];
  106. struct amf_object_item_t items[2];
  107. AMF_OBJECT_ITEM_VALUE(info[0], AMF_STRING, "code", result.code, sizeof(result.code));
  108. AMF_OBJECT_ITEM_VALUE(info[1], AMF_STRING, "level", result.level, sizeof(result.level));
  109. AMF_OBJECT_ITEM_VALUE(info[2], AMF_STRING, "description", result.description, sizeof(result.description));
  110. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "command", NULL, 0);
  111. AMF_OBJECT_ITEM_VALUE(items[1], AMF_OBJECT, "Information", info, sizeof(info) / sizeof(info[0]));
  112. if (NULL == amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])))
  113. {
  114. return -EINVAL; // format error
  115. }
  116. //rtmp->onerror(rtmp->param, -1, result.code);
  117. (void)transaction;
  118. (void)rtmp;
  119. return -1;
  120. }
  121. // s -> c
  122. static int rtmp_command_onstatus(struct rtmp_t* rtmp, double transaction, const uint8_t* data, uint32_t bytes)
  123. {
  124. struct rtmp_result_t result;
  125. struct amf_object_item_t info[3];
  126. struct amf_object_item_t items[2];
  127. AMF_OBJECT_ITEM_VALUE(info[0], AMF_STRING, "code", result.code, sizeof(result.code));
  128. AMF_OBJECT_ITEM_VALUE(info[1], AMF_STRING, "level", result.level, sizeof(result.level));
  129. AMF_OBJECT_ITEM_VALUE(info[2], AMF_STRING, "description", result.description, sizeof(result.description));
  130. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "command", NULL, 0); // Command object
  131. AMF_OBJECT_ITEM_VALUE(items[1], AMF_OBJECT, "information", info, sizeof(info) / sizeof(info[0])); // Information object
  132. if (NULL == amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])))
  133. {
  134. return -EINVAL;
  135. }
  136. assert(0 == strcmp(RTMP_LEVEL_ERROR, result.level)
  137. || 0 == strcmp(RTMP_LEVEL_STATUS, result.level)
  138. || 0 == strcmp(RTMP_LEVEL_WARNING, result.level)
  139. || 0 == strcmp(RTMP_LEVEL_FINISH, result.level));
  140. if (0 == strcmp(RTMP_LEVEL_ERROR, result.level))
  141. {
  142. //rtmp->onerror(rtmp->param, -1, result.code);
  143. return -1;
  144. }
  145. else
  146. {
  147. if (0 == strcasecmp(result.code, "NetStream.Play.Start")
  148. || 0 == strcasecmp(result.code, "NetStream.Record.Start")
  149. || 0 == strcasecmp(result.code, "NetStream.Publish.Start"))
  150. {
  151. rtmp->client.onnotify ? rtmp->client.onnotify(rtmp->param, RTMP_NOTIFY_START) : 0;
  152. }
  153. else if (0 == strcasecmp(result.code, "NetStream.Seek.Notify"))
  154. {
  155. rtmp->client.onnotify ? rtmp->client.onnotify(rtmp->param, RTMP_NOTIFY_SEEK) : 0;
  156. }
  157. else if (0 == strcasecmp(result.code, "NetStream.Pause.Notify"))
  158. {
  159. rtmp->client.onnotify ? rtmp->client.onnotify(rtmp->param, RTMP_NOTIFY_PAUSE) : 0;
  160. }
  161. else if (0 == strcasecmp(result.code, "NetStream.Unpause.Notify"))
  162. {
  163. rtmp->client.onnotify ? rtmp->client.onnotify(rtmp->param, RTMP_NOTIFY_START) : 0;
  164. }
  165. else if (0 == strcasecmp(result.code, "NetStream.Play.Reset"))
  166. {
  167. //rtmp->u.client.onnotify(rtmp->param, RTMP_NOTIFY_RESET);
  168. }
  169. else if (0 == strcasecmp(result.code, "NetStream.Play.Stop")
  170. || 0 == strcasecmp(result.code, "NetStream.Record.Stop")
  171. || 0 == strcasecmp(result.code, "NetStream.Play.Complete"))
  172. {
  173. rtmp->client.onnotify ? rtmp->client.onnotify(rtmp->param, RTMP_NOTIFY_STOP) : 0;
  174. }
  175. else if (0 == strcasecmp(result.code, "NetStream.Play.PublishNotify")
  176. || 0 == strcasecmp(result.code, "NetStream.Play.UnpublishNotify"))
  177. {
  178. }
  179. else if (0 == strcasecmp(result.code, "NetConnection.Connect.InvalidApp")
  180. || 0 == strcasecmp(result.code, "NetConnection.Connect.Rejected")
  181. || 0 == strcasecmp(result.code, "NetStream.Connect.IllegalApplication") // ksyun cdn: level finish, auth failed
  182. || 0 == strcasecmp(result.code, "NetStream.Publish.AlreadyExistStream") // ksyun cdn: level finish, description Already exist stream!
  183. || 0 == strcasecmp(result.code, "NetStream.Failed")
  184. || 0 == strcasecmp(result.code, "NetStream.Play.Failed")
  185. || 0 == strcasecmp(result.code, "NetStream.Play.StreamNotFound"))
  186. {
  187. //rtmp->onerror(rtmp->param, -1, result.code);
  188. return -1;
  189. }
  190. else
  191. {
  192. assert(0);
  193. printf("%s: level: %s, code: %s, description: %s\n", __FUNCTION__, result.level, result.code, result.description);
  194. return -1;
  195. }
  196. }
  197. (void)transaction;
  198. return 0;
  199. }
  200. /*
  201. static int rtmp_command_onbwdone(struct rtmp_t* rtmp, double transaction, const uint8_t* data, uint32_t bytes)
  202. {
  203. struct amf_object_item_t items[1];
  204. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "command", NULL, 0);
  205. return amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])) ? 0 : -1;
  206. }
  207. static int rtmp_command_onbwcheck(struct rtmp_t* rtmp, double transaction, const uint8_t* data, uint32_t bytes)
  208. {
  209. struct amf_object_item_t items[1];
  210. AMF_OBJECT_ITEM_VALUE(items[0], AMF_OBJECT, "command", NULL, 0);
  211. return amf_read_items(data, data + bytes, items, sizeof(items) / sizeof(items[0])) ? 0 : -1;
  212. }
  213. */