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);
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.
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<size_t>(
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;