main.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include <pthread.h>
  2. #include <signal.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/time.h>
  6. #include <unistd.h>
  7. #include "peer.h"
  8. #include "reader.h"
  9. int g_interrupted = 0;
  10. PeerConnection* g_pc = NULL;
  11. PeerConnectionState g_state;
  12. static void onconnectionstatechange(PeerConnectionState state, void* data) {
  13. printf("state is changed: %s\n", peer_connection_state_to_string(state));
  14. g_state = state;
  15. }
  16. static void onopen(void* user_data) {
  17. }
  18. static void onclose(void* user_data) {
  19. }
  20. static void onmessage(char* msg, size_t len, void* user_data, uint16_t sid) {
  21. printf("on message: %d %.*s", sid, (int)len, msg);
  22. if (strncmp(msg, "ping", 4) == 0) {
  23. printf(", send pong\n");
  24. peer_connection_datachannel_send(g_pc, "pong", 4);
  25. }
  26. }
  27. static void signal_handler(int signal) {
  28. g_interrupted = 1;
  29. }
  30. static void* peer_singaling_task(void* data) {
  31. while (!g_interrupted) {
  32. peer_signaling_loop();
  33. usleep(1000);
  34. }
  35. pthread_exit(NULL);
  36. }
  37. static void* peer_connection_task(void* data) {
  38. while (!g_interrupted) {
  39. peer_connection_loop(g_pc);
  40. usleep(1000);
  41. }
  42. pthread_exit(NULL);
  43. }
  44. static uint64_t get_timestamp() {
  45. struct timeval tv;
  46. gettimeofday(&tv, NULL);
  47. return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  48. }
  49. void print_usage(const char* prog_name) {
  50. printf("Usage: %s -u <url> [-t <token>]\n", prog_name);
  51. }
  52. void parse_arguments(int argc, char* argv[], const char** url, const char** token, const char** video) {
  53. *token = NULL;
  54. *url = NULL;
  55. *video = NULL;
  56. for (int i = 1; i < argc; i++) {
  57. if (strcmp(argv[i], "-u") == 0 && (i + 1) < argc) {
  58. *url = argv[++i];
  59. } else if (strcmp(argv[i], "-t") == 0 && (i + 1) < argc) {
  60. *token = argv[++i];
  61. } else if (strcmp(argv[i], "-v") == 0 && (i + 1) < argc) {
  62. *video = argv[++i];
  63. }else {
  64. print_usage(argv[0]);
  65. exit(1);
  66. }
  67. }
  68. if (*url == NULL) {
  69. print_usage(argv[0]);
  70. exit(1);
  71. }
  72. if (*video == NULL) {
  73. printf("this demo use -v set video file");
  74. exit(1);
  75. }
  76. }
  77. int video_frame_count = 0;
  78. int audio_frame_count = 0;
  79. int main(int argc, char* argv[]) {
  80. uint64_t curr_time, video_time, audio_time;
  81. uint8_t* buf = NULL;
  82. const char* url = NULL;
  83. const char* token = NULL;
  84. const char* video_url = NULL;
  85. int size;
  86. pthread_t peer_singaling_thread;
  87. pthread_t peer_connection_thread;
  88. parse_arguments(argc, argv, &url, &token, &video_url);
  89. signal(SIGINT, signal_handler);
  90. PeerConfiguration config = {
  91. .ice_servers = {
  92. {.urls = "stun:stun.l.google.com:19302"},
  93. },
  94. .datachannel = DATA_CHANNEL_NONE,
  95. .video_codec = CODEC_H264,
  96. .audio_codec = CODEC_PCMA};
  97. printf("=========== Parsed Arguments ===========\n");
  98. printf(" %-5s : %s\n", "URL", url);
  99. printf(" %-5s : %s\n", "Token", token ? token : "");
  100. printf(" %-5s : %s\n", "video", video_url ? video_url : "");
  101. printf("========================================\n");
  102. peer_init();
  103. g_pc = peer_connection_create(&config);
  104. peer_connection_oniceconnectionstatechange(g_pc, onconnectionstatechange);
  105. peer_connection_ondatachannel(g_pc, onmessage, onopen, onclose);
  106. peer_signaling_connect(url, token, g_pc);
  107. pthread_create(&peer_connection_thread, NULL, peer_connection_task, NULL);
  108. pthread_create(&peer_singaling_thread, NULL, peer_singaling_task, NULL);
  109. reader_init(video_url);
  110. while (!g_interrupted) {
  111. if (g_state == PEER_CONNECTION_COMPLETED) {
  112. curr_time = get_timestamp();
  113. // FPS 25
  114. if (curr_time - video_time > 40) {
  115. video_time = curr_time;
  116. if ((buf = reader_get_video_frame(&size)) != NULL) {
  117. peer_connection_send_video(g_pc, buf, size);
  118. // need to free the buffer
  119. free(buf);
  120. buf = NULL;
  121. }
  122. }
  123. if (curr_time - audio_time > 20) {
  124. if ((buf = reader_get_audio_frame(&size)) != NULL) {
  125. peer_connection_send_audio(g_pc, buf, size);
  126. buf = NULL;
  127. }
  128. }
  129. }
  130. // 短暂休眠,避免忙等待
  131. usleep(1000);
  132. }
  133. pthread_join(peer_singaling_thread, NULL);
  134. pthread_join(peer_connection_thread, NULL);
  135. reader_deinit();
  136. peer_signaling_disconnect();
  137. peer_connection_destroy(g_pc);
  138. peer_deinit();
  139. return 0;
  140. }