mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-17 05:52:39 +00:00
93 lines
3.0 KiB
C++
93 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include "IMediaController.hpp"
|
|
|
|
#include <wx/image.h>
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <cstddef>
|
|
#include <condition_variable>
|
|
#include <cstdint>
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
namespace rtc {
|
|
class DataChannel;
|
|
class PeerConnection;
|
|
}
|
|
|
|
namespace Slic3r { namespace GUI {
|
|
|
|
class WebRtcMediaController : public IMediaController {
|
|
public:
|
|
struct Status {
|
|
enum Kind { Connecting, Playing, Stopped, Failed } kind = Stopped;
|
|
enum Code {
|
|
ICE_FAILED,
|
|
SIGNALING_CLOSED,
|
|
UNAVAILABLE_BUSY,
|
|
UNAVAILABLE_ERROR,
|
|
UNAVAILABLE_DISABLED,
|
|
DECODE_ERROR,
|
|
TIMEOUT,
|
|
} code = ICE_FAILED;
|
|
// Identifies the StartSession attempt this status belongs to, so the
|
|
// consumer can drop CallAfter-queued events from a superseded attempt.
|
|
std::uint64_t epoch = 0;
|
|
};
|
|
|
|
WebRtcMediaController(std::function<void(const wxImage&, wxSize)> frame_sink,
|
|
std::function<void(Status)> on_status);
|
|
~WebRtcMediaController() override;
|
|
|
|
void StartSession(std::unique_ptr<ICameraSignalingChannel> channel) override;
|
|
void StopSession() override;
|
|
std::uint64_t epoch() const { return m_epoch.load(); }
|
|
bool is_active() const { return m_alive.load(); }
|
|
|
|
void Load(wxURI) override {}
|
|
void Play() override {}
|
|
void Stop() override { StopSession(); }
|
|
wxMediaState GetState() override;
|
|
wxSize GetVideoSize() const override;
|
|
|
|
private:
|
|
void teardown(bool notify);
|
|
void report(Status status);
|
|
void bind_data_channel(const std::shared_ptr<rtc::DataChannel>& dc);
|
|
void on_ready(std::vector<CameraIceServer> servers);
|
|
void on_answer(std::string sdp);
|
|
void on_ice(std::string candidate, std::string mid);
|
|
void on_unavailable(CameraUnavailableReason reason, std::string detail);
|
|
void decode_loop();
|
|
void enqueue_jpeg(std::vector<std::byte> jpeg);
|
|
void deliver_jpeg(std::vector<std::byte> jpeg);
|
|
|
|
mutable std::mutex m_mutex;
|
|
std::condition_variable m_cond;
|
|
std::deque<std::vector<std::byte>> m_jpeg_queue;
|
|
// Remote candidates can arrive before the answer; libdatachannel rejects
|
|
// addRemoteCandidate until a remote description is set, so buffer them.
|
|
std::vector<std::pair<std::string, std::string>> m_pending_candidates;
|
|
bool m_remote_description_set = false;
|
|
std::unique_ptr<ICameraSignalingChannel> m_signaling;
|
|
std::shared_ptr<rtc::PeerConnection> m_peer_connection;
|
|
std::shared_ptr<rtc::DataChannel> m_data_channel;
|
|
std::thread m_decode_thread;
|
|
std::atomic<bool> m_alive{false};
|
|
std::atomic<std::uint64_t> m_epoch{0};
|
|
wxMediaState m_state = static_cast<wxMediaState>(3);
|
|
wxSize m_video_size = wxDefaultSize;
|
|
std::function<void(const wxImage&, wxSize)> m_frame_sink;
|
|
std::function<void(Status)> m_on_status;
|
|
bool m_has_frame = false;
|
|
std::chrono::steady_clock::time_point m_last_frame_time{};
|
|
};
|
|
|
|
}} // namespace Slic3r::GUI
|