pusher.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
  5. *
  6. * Use of this source code is governed by MIT-like license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include "mk_mediakit.h"
  13. typedef struct {
  14. mk_player player;
  15. mk_media media;
  16. mk_pusher pusher;
  17. char push_url[1024];
  18. } Context;
  19. void release_media(mk_media *ptr) {
  20. if (ptr && *ptr) {
  21. mk_media_release(*ptr);
  22. *ptr = NULL;
  23. }
  24. }
  25. void release_player(mk_player *ptr) {
  26. if (ptr && *ptr) {
  27. mk_player_release(*ptr);
  28. *ptr = NULL;
  29. }
  30. }
  31. void release_pusher(mk_pusher *ptr) {
  32. if (ptr && *ptr) {
  33. mk_pusher_release(*ptr);
  34. *ptr = NULL;
  35. }
  36. }
  37. void release_context(Context **ptr){
  38. if (ptr && *ptr) {
  39. release_pusher(&(*ptr)->pusher);
  40. release_media(&(*ptr)->media);
  41. release_player(&(*ptr)->player);
  42. free(*ptr);
  43. *ptr = NULL;
  44. }
  45. }
  46. void API_CALL on_mk_push_event_func(void *user_data,int err_code,const char *err_msg){
  47. Context *ctx = (Context *) user_data;
  48. if (err_code == 0) {
  49. //push success
  50. log_info("push %s success!", ctx->push_url);
  51. } else {
  52. log_warn("push %s failed:%d %s", ctx->push_url, err_code, err_msg);
  53. release_pusher(&(ctx->pusher));
  54. }
  55. }
  56. void API_CALL on_mk_media_source_regist_func(void *user_data, mk_media_source sender, int regist){
  57. Context *ctx = (Context *) user_data;
  58. const char *schema = mk_media_source_get_schema(sender);
  59. if (strncmp(schema, ctx->push_url, strlen(schema)) == 0) {
  60. // 判断是否为推流协议相关的流注册或注销事件 [AUTO-TRANSLATED:00a88a17]
  61. // Determine if it is a stream registration or deregistration event related to the streaming protocol
  62. release_pusher(&(ctx->pusher));
  63. if (regist) {
  64. ctx->pusher = mk_pusher_create_src(sender);
  65. mk_pusher_set_on_result(ctx->pusher, on_mk_push_event_func, ctx);
  66. mk_pusher_set_on_shutdown(ctx->pusher, on_mk_push_event_func, ctx);
  67. mk_pusher_publish(ctx->pusher, ctx->push_url);
  68. } else {
  69. log_info("push stoped!");
  70. }
  71. }
  72. }
  73. void API_CALL on_track_frame_out(void *user_data, mk_frame frame) {
  74. Context *ctx = (Context *) user_data;
  75. mk_media_input_frame(ctx->media, frame);
  76. }
  77. void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *err_msg, mk_track tracks[], int track_count) {
  78. Context *ctx = (Context *) user_data;
  79. release_media(&(ctx->media));
  80. release_pusher(&(ctx->pusher));
  81. if (err_code == 0) {
  82. //success
  83. log_debug("play success!");
  84. ctx->media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
  85. int i;
  86. for (i = 0; i < track_count; ++i) {
  87. mk_media_init_track(ctx->media, tracks[i]);
  88. mk_track_add_delegate(tracks[i], on_track_frame_out, user_data);
  89. }
  90. mk_media_init_complete(ctx->media);
  91. mk_media_set_on_regist(ctx->media, on_mk_media_source_regist_func, ctx);
  92. } else {
  93. log_warn("play failed: %d %s", err_code, err_msg);
  94. }
  95. }
  96. void context_start(Context *ctx, const char *url_pull, const char *url_push){
  97. release_player(&(ctx->player));
  98. ctx->player = mk_player_create();
  99. mk_player_set_on_result(ctx->player, on_mk_play_event_func, ctx);
  100. mk_player_set_on_shutdown(ctx->player, on_mk_play_event_func, ctx);
  101. mk_player_play(ctx->player, url_pull);
  102. strcpy(ctx->push_url, url_push);
  103. }
  104. int main(int argc, char *argv[]){
  105. mk_config config = {
  106. .ini = NULL,
  107. .ini_is_path = 0,
  108. .log_level = 0,
  109. .log_mask = LOG_CONSOLE,
  110. .ssl = NULL,
  111. .ssl_is_path = 1,
  112. .ssl_pwd = NULL,
  113. .thread_num = 0
  114. };
  115. mk_env_init(&config);
  116. if (argc != 3) {
  117. printf("Usage: ./pusher.c pull_url push_url\n");
  118. return -1;
  119. }
  120. // 可以通过 [AUTO-TRANSLATED:9a320d61]
  121. // Can be achieved through
  122. //rtmp://127.0.0.1/live/test
  123. //rtsp://127.0.0.1/live/test
  124. // 播放mk_media的数据 [AUTO-TRANSLATED:623dc58f]
  125. // Playing the data of mk_media
  126. mk_rtsp_server_start(554, 0);
  127. mk_rtmp_server_start(1935, 0);
  128. Context *ctx = (Context *) malloc(sizeof(Context));
  129. memset(ctx, 0, sizeof(Context));
  130. // 推流给自己测试,当然也可以推流给其他服务器测试 [AUTO-TRANSLATED:616e4dc2]
  131. // Stream to yourself for testing, of course, you can also stream to other servers for testing
  132. context_start(ctx, argv[1], argv[2]);
  133. log_info("enter any key to exit");
  134. getchar();
  135. release_context(&ctx);
  136. return 0;
  137. }