X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=server.cpp;h=1637d94fc068ff4f56acc0f099aad0ed60221772;hp=7acf501236e1ee2db9cac22db0b72a5ddf8ecf69;hb=4ec6a7f04455b023d3ca91d4e84a19993ec4d34e;hpb=44f74dbce7ed19d8218318ce5ecc0da2fb4ae9f0 diff --git a/server.cpp b/server.cpp index 7acf501..1637d94 100644 --- a/server.cpp +++ b/server.cpp @@ -194,8 +194,9 @@ void Server::add_client_from_serialized(const ClientProto &client) exit(1); } - if (client_ptr->state == Client::SENDING_DATA && - client_ptr->stream_pos == client_ptr->stream->bytes_received) { + if (client_ptr->state == Client::WAITING_FOR_KEYFRAME || + (client_ptr->state == Client::SENDING_DATA && + client_ptr->stream_pos == client_ptr->stream->bytes_received)) { client_ptr->stream->put_client_to_sleep(client_ptr); } else { process_client(client_ptr); @@ -269,11 +270,11 @@ void Server::set_mark_pool(int stream_index, MarkPool *mark_pool) streams[stream_index]->mark_pool = mark_pool; } -void Server::add_data_deferred(int stream_index, const char *data, size_t bytes) +void Server::add_data_deferred(int stream_index, const char *data, size_t bytes, StreamStartSuitability suitable_for_stream_start) { MutexLock lock(&queued_data_mutex); assert(stream_index >= 0 && stream_index < ssize_t(streams.size())); - streams[stream_index]->add_data_deferred(data, bytes); + streams[stream_index]->add_data_deferred(data, bytes, suitable_for_stream_start); } // See the .h file for postconditions after this function. @@ -380,22 +381,37 @@ sending_header_or_error_again: return; } - // Start sending from the end. In other words, we won't send any of the backlog, - // but we'll start sending immediately as we get data. + // Start sending from the first keyframe we get. In other + // words, we won't send any of the backlog, but we'll start + // sending immediately as we get the next keyframe block. // This is postcondition #3. - client->state = Client::SENDING_DATA; if (client->stream_pos == size_t(-2)) { client->stream_pos = std::min( client->stream->bytes_received - client->stream->backlog_size, 0); + client->state = Client::SENDING_DATA; } else { // client->stream_pos should be -1, but it might not be, // if we have clients from an older version. client->stream_pos = client->stream->bytes_received; + client->state = Client::WAITING_FOR_KEYFRAME; } client->stream->put_client_to_sleep(client); return; } + case Client::WAITING_FOR_KEYFRAME: { + Stream *stream = client->stream; + if (ssize_t(client->stream_pos) > stream->last_suitable_starting_point) { + // We haven't received a keyframe since this stream started waiting, + // so keep on waiting for one. + // This is postcondition #3. + stream->put_client_to_sleep(client); + return; + } + client->stream_pos = stream->last_suitable_starting_point; + client->state = Client::SENDING_DATA; + // Fall through. + } case Client::SENDING_DATA: { skip_lost_data(client); Stream *stream = client->stream;