whip-output.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #pragma once
  2. #include <obs-module.h>
  3. #include <util/curl/curl-helper.h>
  4. #include <util/platform.h>
  5. #include <util/base.h>
  6. #include <util/dstr.h>
  7. #include <string>
  8. #include <atomic>
  9. #include <mutex>
  10. #include <thread>
  11. #include <rtc/rtc.h>
  12. #define do_log(level, format, ...) \
  13. blog(level, "[obs-webrtc] [whip_output: '%s'] " format, \
  14. obs_output_get_name(output), ##__VA_ARGS__)
  15. #define do_log_s(level, format, ...) \
  16. blog(level, "[obs-webrtc] [whip_output: '%s'] " format, \
  17. obs_output_get_name(whipOutput->output), ##__VA_ARGS__)
  18. class WHIPOutput {
  19. public:
  20. WHIPOutput(obs_data_t *settings, obs_output_t *output);
  21. ~WHIPOutput();
  22. bool Start();
  23. void Stop(bool signal = true);
  24. void Data(struct encoder_packet *packet);
  25. inline size_t GetTotalBytes() { return total_bytes_sent; }
  26. inline int GetConnectTime() { return connect_time_ms; }
  27. private:
  28. void ConfigureAudioTrack(std::string media_stream_id,
  29. std::string cname);
  30. void ConfigureVideoTrack(std::string media_stream_id,
  31. std::string cname);
  32. bool Setup();
  33. bool Connect();
  34. void StartThread();
  35. void SendDelete();
  36. void StopThread(bool signal);
  37. void Send(void *data, uintptr_t size, uint64_t duration, int track);
  38. obs_output_t *output;
  39. std::string endpoint_url;
  40. std::string bearer_token;
  41. std::string resource_url;
  42. std::atomic<bool> running;
  43. std::mutex start_stop_mutex;
  44. std::thread start_stop_thread;
  45. int peer_connection;
  46. int audio_track;
  47. int video_track;
  48. std::atomic<size_t> total_bytes_sent;
  49. std::atomic<int> connect_time_ms;
  50. int64_t start_time_ns;
  51. int64_t last_audio_timestamp;
  52. int64_t last_video_timestamp;
  53. };
  54. void register_whip_output();
  55. static std::string trim_string(const std::string &source)
  56. {
  57. std::string ret(source);
  58. ret.erase(0, ret.find_first_not_of(" \n\r\t"));
  59. ret.erase(ret.find_last_not_of(" \n\r\t") + 1);
  60. return ret;
  61. }
  62. static size_t curl_writefunction(char *data, size_t size, size_t nmemb,
  63. void *priv_data)
  64. {
  65. auto read_buffer = static_cast<std::string *>(priv_data);
  66. size_t real_size = size * nmemb;
  67. read_buffer->append(data, real_size);
  68. return real_size;
  69. }
  70. #define LOCATION_HEADER_LENGTH 10
  71. static size_t curl_headerfunction(char *data, size_t size, size_t nmemb,
  72. void *priv_data)
  73. {
  74. auto header_buffer = static_cast<std::string *>(priv_data);
  75. size_t real_size = size * nmemb;
  76. if (real_size < LOCATION_HEADER_LENGTH)
  77. return real_size;
  78. if (!astrcmpi_n(data, "location: ", LOCATION_HEADER_LENGTH)) {
  79. char *val = data + LOCATION_HEADER_LENGTH;
  80. header_buffer->append(val, real_size - LOCATION_HEADER_LENGTH);
  81. *header_buffer = trim_string(*header_buffer);
  82. }
  83. return real_size;
  84. }