X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=httpd.h;h=1ff5c51108facf03ca1b0d8fc2f076a63938e595;hb=817fffe1ef3bd87f2387395f49487cf5255d8daf;hp=d546feec22180ab4c9bf7fe10be417d9f7b6dff5;hpb=6ebc7f7bd501d1115bf164ce3e1c22db326798c2;p=nageru diff --git a/httpd.h b/httpd.h index d546fee..1ff5c51 100644 --- a/httpd.h +++ b/httpd.h @@ -1,37 +1,62 @@ #ifndef _HTTPD_H #define _HTTPD_H -// A class dealing with stream output, both to HTTP (thus the class name) -// and to local output files. Since we generally have very few outputs -// (end clients are not meant to connect directly to our stream; it should be -// transcoded by something else and then sent to a reflector), we don't need to -// care a lot about performance. Thus, we solve this by the simplest possible -// way, namely having one ffmpeg mux per output. - -#include +// A class dealing with stream output to HTTP. + #include #include #include +#include #include #include -#include +#include #include +#include #include -#include - -struct MHD_Connection; +#include +#include extern "C" { -#include -#include -#include +#include } +struct MHD_Connection; +struct MHD_Daemon; + class HTTPD { public: - HTTPD(const char *output_filename, int width, int height); + // Returns a pair of content and content-type. + using EndpointCallback = std::function()>; + + HTTPD(); + ~HTTPD(); + + enum StreamType { + MAIN_STREAM, + MULTICAM_STREAM, + NUM_STREAM_TYPES + }; + + // Should be called before start(). + void set_header(StreamType stream_type, const std::string &data) { + header[stream_type] = data; + } + + // Should be called before start() (due to threading issues). + enum CORSPolicy { + NO_CORS_POLICY, + ALLOW_ALL_ORIGINS + }; + void add_endpoint(const std::string &url, const EndpointCallback &callback, CORSPolicy cors_policy) { + endpoints[url] = Endpoint{ callback, cors_policy }; + } + void start(int port); - void add_packet(const AVPacket &pkt, int64_t pts, int64_t dts); + void stop(); + void add_data(StreamType stream_type, const char *buf, size_t size, bool keyframe, int64_t time, AVRational timebase); + int64_t get_num_connected_clients() const { + return metric_num_connected_clients.load(); + } private: static int answer_to_connection_thunk(void *cls, MHD_Connection *connection, @@ -46,42 +71,54 @@ private: static void free_stream(void *cls); - class Mux { - public: - Mux(AVFormatContext *avctx, int width, int height); // Takes ownership of avctx. - ~Mux(); - void add_packet(const AVPacket &pkt, int64_t pts, int64_t dts); - - private: - AVFormatContext *avctx; - AVStream *avstream_video, *avstream_audio; - }; class Stream { public: - Stream(AVOutputFormat *oformat, int width, int height); + enum Framing { + FRAMING_RAW, + FRAMING_METACUBE + }; + Stream(HTTPD *parent, Framing framing, StreamType stream_type) + : parent(parent), framing(framing), stream_type(stream_type) {} static ssize_t reader_callback_thunk(void *cls, uint64_t pos, char *buf, size_t max); ssize_t reader_callback(uint64_t pos, char *buf, size_t max); - void add_packet(const AVPacket &pkt, int64_t pts, int64_t dts); + enum DataType { + DATA_TYPE_HEADER, + DATA_TYPE_KEYFRAME, + DATA_TYPE_OTHER + }; + void add_data(const char *buf, size_t size, DataType data_type, int64_t time, AVRational timebase); + void stop(); + HTTPD *get_parent() const { return parent; } + StreamType get_stream_type() const { return stream_type; } private: - static int write_packet_thunk(void *opaque, uint8_t *buf, int buf_size); - int write_packet(uint8_t *buf, int buf_size); - - std::unique_ptr mux; + HTTPD *parent; + Framing framing; std::mutex buffer_mutex; + bool should_quit = false; // Under . std::condition_variable has_buffered_data; - std::deque buffered_data; // Protected by . + std::deque buffered_data; // Protected by . size_t used_of_buffered_data = 0; // How many bytes of the first element of that is already used. Protected by . + size_t seen_keyframe = false; + StreamType stream_type; }; - std::vector streams; // Not owned. + MHD_Daemon *mhd = nullptr; + std::mutex streams_mutex; + std::set streams; // Not owned. + struct Endpoint { + EndpointCallback callback; + CORSPolicy cors_policy; + }; + std::unordered_map endpoints; + std::string header[NUM_STREAM_TYPES]; - int width, height; - std::unique_ptr file_mux; // To local disk. + // Metrics. + std::atomic metric_num_connected_clients{0}; }; #endif // !defined(_HTTPD_H)