From: Steinar H. Gunderson Date: Mon, 18 Apr 2016 22:19:43 +0000 (+0200) Subject: Add Metacube stream output (for Cubemap). X-Git-Tag: 1.3.0~78 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=ae6eccf4792e276970fa4fb985dc4588947b767b Add Metacube stream output (for Cubemap). --- diff --git a/Makefile b/Makefile index f68d898..ffc1f1c 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ OBJS=glwidget.o main.o mainwindow.o vumeter.o lrameter.o vu_common.o correlation OBJS += glwidget.moc.o mainwindow.moc.o vumeter.moc.o lrameter.moc.o correlation_meter.moc.o aboutdialog.moc.o # Mixer objects -OBJS += h264encode.o x264encode.o mixer.o bmusb/bmusb.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampling_queue.o httpd.o mux.o ebu_r128_proc.o flags.o image_input.o stereocompressor.o filter.o alsa_output.o correlation_measurer.o +OBJS += h264encode.o x264encode.o mixer.o bmusb/bmusb.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampling_queue.o metacube2.o httpd.o mux.o ebu_r128_proc.o flags.o image_input.o stereocompressor.o filter.o alsa_output.o correlation_measurer.o # DeckLink OBJS += decklink_capture.o decklink/DeckLinkAPIDispatch.o diff --git a/httpd.cpp b/httpd.cpp index ed46f52..5226885 100644 --- a/httpd.cpp +++ b/httpd.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,6 +11,7 @@ #include "defs.h" #include "flags.h" +#include "metacube2.h" #include "timebase.h" struct MHD_Connection; @@ -53,7 +55,18 @@ int HTTPD::answer_to_connection(MHD_Connection *connection, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { - HTTPD::Stream *stream = new HTTPD::Stream; + // See if the URL ends in “.metacube”. + HTTPD::Stream::Framing framing; + printf("url=[%s]\n", url); + if (strstr(url, ".metacube") == url + strlen(url) - strlen(".metacube")) { + printf("metacube\n"); + framing = HTTPD::Stream::FRAMING_METACUBE; + } else { + printf("raw\n"); + framing = HTTPD::Stream::FRAMING_RAW; + } + + HTTPD::Stream *stream = new HTTPD::Stream(framing); stream->add_data(header.data(), header.size(), Stream::DATA_TYPE_HEADER); { unique_lock lock(streams_mutex); @@ -64,6 +77,11 @@ int HTTPD::answer_to_connection(MHD_Connection *connection, // Does not strictly have to be equal to MUX_BUFFER_SIZE. MHD_Response *response = MHD_create_response_from_callback( (size_t)-1, MUX_BUFFER_SIZE, &HTTPD::Stream::reader_callback_thunk, stream, &HTTPD::free_stream); + + // TODO: Content-type? + if (framing == HTTPD::Stream::FRAMING_METACUBE) { + MHD_add_response_header(response, "Content-encoding", "metacube"); + } int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); //MHD_destroy_response(response); @@ -148,6 +166,21 @@ void HTTPD::Stream::add_data(const char *buf, size_t buf_size, HTTPD::Stream::Da } unique_lock lock(buffer_mutex); + + if (framing == FRAMING_METACUBE) { + metacube2_block_header hdr; + memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync)); + hdr.size = htonl(buf_size); + int flags = 0; + if (data_type == DATA_TYPE_HEADER) { + flags |= METACUBE_FLAGS_HEADER; + } else if (data_type == DATA_TYPE_OTHER) { + flags |= METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START; + } + hdr.flags = htons(flags); + hdr.csum = htons(metacube2_compute_crc(&hdr)); + buffered_data.emplace_back((char *)&hdr, sizeof(hdr)); + } buffered_data.emplace_back(buf, buf_size); has_buffered_data.notify_all(); } diff --git a/httpd.h b/httpd.h index 21d8746..94de031 100644 --- a/httpd.h +++ b/httpd.h @@ -48,6 +48,12 @@ private: class Stream { public: + enum Framing { + FRAMING_RAW, + FRAMING_METACUBE + }; + Stream(Framing framing) : framing(framing) {} + 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); @@ -59,6 +65,8 @@ private: void add_data(const char *buf, size_t size, DataType data_type); private: + Framing framing; + std::mutex buffer_mutex; std::condition_variable has_buffered_data; std::deque buffered_data; // Protected by . diff --git a/metacube2.cpp b/metacube2.cpp new file mode 100644 index 0000000..1bf9efb --- /dev/null +++ b/metacube2.cpp @@ -0,0 +1,48 @@ +/* + * Implementation of Metacube2 utility functions. + * + * Note: This file is meant to compile as both C and C++, for easier inclusion + * in other projects. + */ + +#include "metacube2.h" + +/* + * https://www.ece.cmu.edu/~koopman/pubs/KoopmanCRCWebinar9May2012.pdf + * recommends this for messages as short as ours (see table at page 34). + */ +#define METACUBE2_CRC_POLYNOMIAL 0x8FDB + +/* Semi-random starting value to make sure all-zero won't pass. */ +#define METACUBE2_CRC_START 0x1234 + +/* This code is based on code generated by pycrc. */ +uint16_t metacube2_compute_crc(const struct metacube2_block_header *hdr) +{ + static const int data_len = sizeof(hdr->size) + sizeof(hdr->flags); + const uint8_t *data = (uint8_t *)&hdr->size; + uint16_t crc = METACUBE2_CRC_START; + int i, j; + + for (i = 0; i < data_len; ++i) { + uint8_t c = data[i]; + for (j = 0; j < 8; j++) { + int bit = crc & 0x8000; + crc = (crc << 1) | ((c >> (7 - j)) & 0x01); + if (bit) { + crc ^= METACUBE2_CRC_POLYNOMIAL; + } + } + } + + /* Finalize. */ + for (i = 0; i < 16; i++) { + int bit = crc & 0x8000; + crc = crc << 1; + if (bit) { + crc ^= METACUBE2_CRC_POLYNOMIAL; + } + } + + return crc; +} diff --git a/metacube2.h b/metacube2.h new file mode 100644 index 0000000..43de8b7 --- /dev/null +++ b/metacube2.h @@ -0,0 +1,26 @@ +#ifndef _METACUBE2_H +#define _METACUBE2_H + +/* + * Definitions for the Metacube2 protocol, used to communicate with Cubemap. + * + * Note: This file is meant to compile as both C and C++, for easier inclusion + * in other projects. + */ + +#include + +#define METACUBE2_SYNC "cube!map" /* 8 bytes long. */ +#define METACUBE_FLAGS_HEADER 0x1 +#define METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START 0x2 + +struct metacube2_block_header { + char sync[8]; /* METACUBE2_SYNC */ + uint32_t size; /* Network byte order. Does not include header. */ + uint16_t flags; /* Network byte order. METACUBE_FLAGS_*. */ + uint16_t csum; /* Network byte order. CRC16 of size and flags. */ +}; + +uint16_t metacube2_compute_crc(const struct metacube2_block_header *hdr); + +#endif /* !defined(_METACUBE_H) */