[Spice-devel] [PATCH spice-server 23/28] red_worker: video streams - adjust client playback latency
Yonit Halperin
yhalperi at redhat.com
Tue Feb 26 10:04:09 PST 2013
---
server/red_worker.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 51 insertions(+), 5 deletions(-)
diff --git a/server/red_worker.c b/server/red_worker.c
index 46dd069..acf391d 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,52 @@ 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)
+{
+ if (dcc->streams_max_latency == remove_agent->client_required_latency) {
+ dcc->streams_max_latency = 0;
+ if (dcc->common.worker->stream_count > 1) {
+ uint32_t new_max_latency = 0;
+ int i;
+
+ 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 +2973,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);
@@ -8894,11 +8944,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);
}
--
1.8.1
More information about the Spice-devel
mailing list