X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=stream.cpp;h=5ea2cd03601491f8fe64070fd4b33b71f33dd4d8;hp=2b9a69593a478605800fd21c9585063eebec8d0c;hb=7c26826d3c485f4f18a6c427f520dc470e68f94a;hpb=8cc780cf37063ce29f13380976a54dd8302fe3a9 diff --git a/stream.cpp b/stream.cpp index 2b9a695..5ea2cd0 100644 --- a/stream.cpp +++ b/stream.cpp @@ -1,19 +1,23 @@ +#include #include -#include +#include #include +#include #include #include #include -#include "state.pb.h" #include "log.h" +#include "metacube.h" +#include "state.pb.h" #include "stream.h" #include "util.h" using namespace std; -Stream::Stream(const string &stream_id, size_t backlog_size) +Stream::Stream(const string &stream_id, size_t backlog_size, Encoding encoding) : stream_id(stream_id), + encoding(encoding), data_fd(make_tempfile("")), backlog_size(backlog_size), bytes_received(0), @@ -27,20 +31,16 @@ Stream::Stream(const string &stream_id, size_t backlog_size) Stream::~Stream() { if (data_fd != -1) { - int ret; - do { - ret = close(data_fd); - } while (ret == -1 && errno == EINTR); - if (ret == -1) { - log_perror("close"); - } + safe_close(data_fd); } } -Stream::Stream(const StreamProto &serialized) +Stream::Stream(const StreamProto &serialized, int data_fd) : stream_id(serialized.stream_id()), - header(serialized.header()), - data_fd(make_tempfile(serialized.data())), + http_header(serialized.http_header()), + stream_header(serialized.stream_header()), + encoding(Stream::STREAM_ENCODING_RAW), // Will be changed later. + data_fd(data_fd), backlog_size(serialized.backlog_size()), bytes_received(serialized.bytes_received()), mark_pool(NULL) @@ -48,15 +48,27 @@ Stream::Stream(const StreamProto &serialized) if (data_fd == -1) { exit(1); } + + // Split old-style headers into HTTP and video headers. + if (!serialized.header().empty()) { + string header = serialized.header(); + size_t split = header.find("\r\n\r\n"); + if (split == string::npos) { + http_header = header; + stream_header = ""; + } else { + http_header = header.substr(0, split + 2); // Split off the second \r\n. + stream_header = header.substr(split, string::npos); + } + } } StreamProto Stream::serialize() { StreamProto serialized; - serialized.set_header(header); - if (!read_tempfile(data_fd, serialized.mutable_data())) { // Closes data_fd. - exit(1); - } + serialized.set_http_header(http_header); + serialized.set_stream_header(stream_header); + serialized.add_data_fds(data_fd); serialized.set_backlog_size(backlog_size); serialized.set_bytes_received(bytes_received); serialized.set_stream_id(stream_id); @@ -71,7 +83,7 @@ void Stream::set_backlog_size(size_t new_size) } string existing_data; - if (!read_tempfile(data_fd, &existing_data)) { // Closes data_fd. + if (!read_tempfile_and_close(data_fd, &existing_data)) { exit(1); } @@ -92,11 +104,14 @@ void Stream::set_backlog_size(size_t new_size) // Create a new, empty data file. data_fd = make_tempfile(""); + if (data_fd == -1) { + exit(1); + } backlog_size = new_size; // Now cheat a bit by rewinding, and adding all the old data back. bytes_received -= existing_data.size(); - add_data(existing_data.data(), existing_data.size()); + add_data_raw(existing_data.data(), existing_data.size()); } void Stream::put_client_to_sleep(Client *client) @@ -105,6 +120,26 @@ void Stream::put_client_to_sleep(Client *client) } void Stream::add_data(const char *data, ssize_t bytes) +{ + if (encoding == Stream::STREAM_ENCODING_RAW) { + add_data_raw(data, bytes); + } else if (encoding == STREAM_ENCODING_METACUBE) { + metacube_block_header hdr; + memcpy(hdr.sync, METACUBE_SYNC, sizeof(hdr.sync)); + hdr.size = htonl(bytes); + hdr.flags = htonl(0); + + char *block = new char[bytes + sizeof(hdr)]; + memcpy(block, &hdr, sizeof(hdr)); + memcpy(block + sizeof(hdr), data, bytes); + add_data_raw(block, bytes + sizeof(hdr)); + delete[] block; + } else { + assert(false); + } +} + +void Stream::add_data_raw(const char *data, ssize_t bytes) { size_t pos = bytes_received % backlog_size; bytes_received += bytes;