summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2013-01-25 09:34:19 -0500
committerYonit Halperin <yhalperi@redhat.com>2013-04-22 16:30:55 -0400
commitbf9e210b21a66210b19f69fcaa4542b393b7dc22 (patch)
tree806052bc4f8f18d9b23de8bb2a48ae8bfbcbb8e6 /server
parent073aeec569e2bee3feec8042986b8434db8afad3 (diff)
downloadspice-bf9e210b21a66210b19f69fcaa4542b393b7dc22.tar.gz
spice-bf9e210b21a66210b19f69fcaa4542b393b7dc22.tar.xz
spice-bf9e210b21a66210b19f69fcaa4542b393b7dc22.zip
red_worker: video streams - adjust client playback latency
Diffstat (limited to 'server')
-rw-r--r--server/red_worker.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/server/red_worker.c b/server/red_worker.c
index 0249bcb8..f96ff076 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -81,6 +81,7 @@
#include "main_channel.h"
#include "migration_protocol.h"
#include "spice_timer_queue.h"
+#include "main_dispatcher.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
@@ -470,6 +471,7 @@ typedef struct StreamAgent {
int fps;
uint32_t report_id;
+ uint32_t client_required_latency;
} StreamAgent;
typedef struct StreamClipItem {
@@ -690,6 +692,7 @@ struct DisplayChannelClient {
StreamAgent stream_agents[NUM_STREAMS];
int use_mjpeg_encoder_rate_control;
+ uint32_t streams_max_latency;
};
struct DisplayChannel {
@@ -2901,6 +2904,55 @@ static uint32_t red_stream_mjpeg_encoder_get_source_fps(void *opaque)
return agent->stream->input_fps;
}
+static void red_display_update_streams_max_latency(DisplayChannelClient *dcc, StreamAgent *remove_agent)
+{
+ uint32_t new_max_latency = 0;
+ int i;
+
+ if (dcc->streams_max_latency != remove_agent->client_required_latency) {
+ return;
+ }
+
+ dcc->streams_max_latency = 0;
+ if (dcc->common.worker->stream_count == 1) {
+ return;
+ }
+ for (i = 0; i < NUM_STREAMS; i++) {
+ StreamAgent *other_agent = &dcc->stream_agents[i];
+ if (other_agent == remove_agent || !other_agent->mjpeg_encoder) {
+ continue;
+ }
+ if (other_agent->client_required_latency > new_max_latency) {
+ new_max_latency = other_agent->client_required_latency;
+ }
+ }
+ dcc->streams_max_latency = new_max_latency;
+}
+
+static void red_display_stream_agent_stop(DisplayChannelClient *dcc, StreamAgent *agent)
+{
+ red_display_update_streams_max_latency(dcc, agent);
+ if (agent->mjpeg_encoder) {
+ mjpeg_encoder_destroy(agent->mjpeg_encoder);
+ agent->mjpeg_encoder = NULL;
+ }
+}
+
+static void red_stream_update_client_playback_latency(void *opaque, uint32_t delay_ms)
+{
+ StreamAgent *agent = opaque;
+ DisplayChannelClient *dcc = agent->dcc;
+
+ red_display_update_streams_max_latency(dcc, agent);
+
+ agent->client_required_latency = delay_ms;
+ if (delay_ms > agent->dcc->streams_max_latency) {
+ agent->dcc->streams_max_latency = delay_ms;
+ }
+ spice_debug("reseting client latency: %u", agent->dcc->streams_max_latency);
+ main_dispatcher_set_mm_time_latency(agent->dcc->common.base.client, agent->dcc->streams_max_latency);
+}
+
static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
{
StreamAgent *agent = &dcc->stream_agents[get_stream_id(dcc->common.worker, stream)];
@@ -2924,6 +2976,7 @@ static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
mjpeg_cbs.get_roundtrip_ms = red_stream_mjpeg_encoder_get_roundtrip;
mjpeg_cbs.get_source_fps = red_stream_mjpeg_encoder_get_source_fps;
+ mjpeg_cbs.update_client_playback_delay = red_stream_update_client_playback_latency;
initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
agent->mjpeg_encoder = mjpeg_encoder_new(TRUE, initial_bit_rate, &mjpeg_cbs, agent);
@@ -8895,11 +8948,7 @@ static void red_display_marshall_stream_end(RedChannelClient *rcc,
red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
destroy.id = get_stream_id(dcc->common.worker, agent->stream);
-
- if (agent->mjpeg_encoder) {
- mjpeg_encoder_destroy(agent->mjpeg_encoder);
- agent->mjpeg_encoder = NULL;
- }
+ red_display_stream_agent_stop(dcc, agent);
spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
}