rtsp_client.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #ifndef JTJAI_MEDIA_RTSP_CLIENT_H
  2. #define JTJAI_MEDIA_RTSP_CLIENT_H
  3. #include "config.h"
  4. #include <string>
  5. #include <atomic>
  6. #include <memory>
  7. #include <chrono>
  8. #include <functional>
  9. #include <mutex>
  10. extern "C" {
  11. #include <libavformat/avformat.h>
  12. #include <libavcodec/avcodec.h>
  13. #include <libavutil/time.h>
  14. #include <libswscale/swscale.h>
  15. }
  16. namespace jtjai_media {
  17. enum class RTSPClientStatus {
  18. IDLE, // 空闲状态
  19. CONNECTING, // 连接中
  20. CONNECTED, // 已连接
  21. RECORDING, // 录制中
  22. FINISHED, // 完成
  23. ERROR_CONNECT, // 连接错误
  24. ERROR_RECORD, // 录制错误
  25. TIMEOUT, // 超时
  26. CANCELLED, // 已取消
  27. STREAM_UNAVAILABLE // 流不可用(快速失败)
  28. };
  29. struct RTSPClientStats {
  30. int stream_index;
  31. std::string rtsp_url;
  32. std::string output_file;
  33. RTSPClientStatus status;
  34. std::chrono::system_clock::time_point start_time;
  35. std::chrono::system_clock::time_point end_time;
  36. int64_t bytes_received;
  37. int64_t frames_received;
  38. int duration_seconds;
  39. std::string error_message;
  40. RTSPClientStats()
  41. : stream_index(-1)
  42. , status(RTSPClientStatus::IDLE)
  43. , bytes_received(0)
  44. , frames_received(0)
  45. , duration_seconds(0) {}
  46. };
  47. class RTSPClient {
  48. public:
  49. RTSPClient(int stream_index, const StreamConfig& config, const std::string& output_dir);
  50. ~RTSPClient();
  51. // 禁用拷贝构造和赋值
  52. RTSPClient(const RTSPClient&) = delete;
  53. RTSPClient& operator=(const RTSPClient&) = delete;
  54. // 启动录制(阻塞调用)
  55. bool start_recording(int duration_seconds);
  56. // 异步启动录制
  57. void start_recording_async(int duration_seconds,
  58. std::function<void(const RTSPClientStats&)> completion_callback = nullptr);
  59. // 停止录制
  60. void stop_recording();
  61. // 获取当前状态
  62. RTSPClientStatus get_status() const { return stats_.status; }
  63. // 获取统计信息
  64. RTSPClientStats get_stats() const;
  65. // 设置连接超时时间(秒)
  66. void set_connection_timeout(int timeout_seconds) { connection_timeout_ = timeout_seconds; }
  67. // 设置读取超时时间(秒)
  68. void set_read_timeout(int timeout_seconds) { read_timeout_ = timeout_seconds; }
  69. // 检查是否正在运行
  70. bool is_running() const;
  71. private:
  72. StreamConfig config_;
  73. std::string output_dir_;
  74. std::string full_output_path_;
  75. mutable std::mutex stats_mutex_;
  76. RTSPClientStats stats_;
  77. // FFmpeg相关
  78. AVFormatContext* input_format_ctx_;
  79. AVFormatContext* output_format_ctx_;
  80. AVStream* input_video_stream_;
  81. AVStream* output_video_stream_;
  82. AVStream* input_audio_stream_;
  83. AVStream* output_audio_stream_;
  84. // 控制标志
  85. std::atomic<bool> should_stop_;
  86. std::atomic<bool> is_recording_;
  87. // 超时设置
  88. int connection_timeout_;
  89. int read_timeout_;
  90. // 私有方法
  91. bool initialize_input();
  92. bool initialize_output();
  93. void cleanup();
  94. bool process_stream(int duration_seconds);
  95. void update_status(RTSPClientStatus status, const std::string& error_msg = "");
  96. void update_final_file_stats();
  97. // FFmpeg日志回调
  98. static void ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl);
  99. // 超时控制
  100. static int interrupt_callback(void* ctx);
  101. int64_t start_time_us_;
  102. int64_t timeout_us_;
  103. };
  104. } // namespace jtjai_media
  105. #endif // JTJAI_MEDIA_RTSP_CLIENT_H