return;
}
- // 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.
Stream *stream = client->stream;
if (client->stream_pos == size_t(-2)) {
+ // Start sending from the beginning of the backlog.
client->stream_pos = std::min<size_t>(
stream->bytes_received - stream->backlog_size,
0);
client->state = Client::SENDING_DATA;
goto sending_data;
- } else {
+ } else if (stream->prebuffering_bytes == 0) {
+ // 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.
+ // Note that this is functionally identical to the next if branch,
+ // except that we save a binary search.
client->stream_pos = stream->bytes_received;
client->state = Client::WAITING_FOR_KEYFRAME;
+ } else {
+ // We're not going to send anything to the client before we have
+ // N bytes. However, this wait might be boring; we can just as well
+ // use it to send older data if we have it. We use lower_bound()
+ // so that we are conservative and never add extra latency over just
+ // waiting (assuming CBR or nearly so); otherwise, we could want e.g.
+ // 100 kB prebuffer but end up sending a 10 MB GOP.
+ deque<size_t>::const_iterator starting_point_it =
+ lower_bound(stream->suitable_starting_points.begin(),
+ stream->suitable_starting_points.end(),
+ stream->bytes_received - stream->prebuffering_bytes);
+ if (starting_point_it == stream->suitable_starting_points.end()) {
+ // None found. Just put us at the end, and then wait for the
+ // first keyframe to appear.
+ client->stream_pos = stream->bytes_received;
+ client->state = Client::WAITING_FOR_KEYFRAME;
+ } else {
+ client->stream_pos = *starting_point_it;
+ client->state = Client::PREBUFFERING;
+ goto prebuffering;
+ }
}
// Fall through.
}
// Fall through.
}
case Client::PREBUFFERING: {
+prebuffering:
Stream *stream = client->stream;
size_t bytes_to_send = stream->bytes_received - client->stream_pos;
assert(bytes_to_send <= stream->backlog_size);