On Tue, Feb 26, 2013 at 01:04:03PM -0500, Yonit Halperin wrote: ACK, one spelling error below. > update mjpeg_encoder with reports from the client about > the playback quality. > --- > server/red_dispatcher.c | 1 + > server/red_worker.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 85 insertions(+), 2 deletions(-) > > diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c > index 97e9737..e054b5a 100644 > --- a/server/red_dispatcher.c > +++ b/server/red_dispatcher.c > @@ -1143,6 +1143,7 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl) > red_channel_register_client_cbs(display_channel, &client_cbs); > red_channel_set_data(display_channel, red_dispatcher); > red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); > + red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_STREAM_REPORT); > reds_register_channel(display_channel); > } > > diff --git a/server/red_worker.c b/server/red_worker.c > index 470ad7a..23f9ca5 100644 > --- a/server/red_worker.c > +++ b/server/red_worker.c > @@ -117,6 +117,9 @@ > #define RED_STREAM_MIN_SIZE (96 * 96) > #define RED_STREAM_INPUT_FPS_TIMEOUT (5 * 1000) // 5 sec > #define RED_STREAM_CHANNEL_CAPACITY 0.8 > +/* the client's stream report frequency the minimum of the 2 values bellow */ s/bellow/below/ > +#define RED_STREAM_CLIENT_REPORT_WINDOW 5 // #frames > +#define RED_STREAM_CLIENT_REPORT_TIMEOUT 1000 // milliseconds > > #define FPS_TEST_INTERVAL 1 > #define MAX_FPS 30 > @@ -292,6 +295,7 @@ enum { > PIPE_ITEM_TYPE_CREATE_SURFACE, > PIPE_ITEM_TYPE_DESTROY_SURFACE, > PIPE_ITEM_TYPE_MONITORS_CONFIG, > + PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT, > }; > > typedef struct VerbItem { > @@ -351,6 +355,11 @@ typedef struct MonitorsConfigItem { > MonitorsConfig *monitors_config; > } MonitorsConfigItem; > > +typedef struct StreamActivateReportItem { > + PipeItem pipe_item; > + uint32_t stream_id; > +} StreamActivateReportItem; > + > typedef struct CursorItem { > uint32_t group_id; > int refs; > @@ -459,6 +468,8 @@ typedef struct StreamAgent { > int frames; > int drops; > int fps; > + > + uint32_t report_id; > } StreamAgent; > > typedef struct StreamClipItem { > @@ -2917,6 +2928,17 @@ static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream) > agent->mjpeg_encoder = mjpeg_encoder_new(FALSE, 0, NULL, NULL); > } > red_channel_client_pipe_add(&dcc->common.base, &agent->create_item); > + > + if (red_channel_client_test_remote_cap(&dcc->common.base, SPICE_DISPLAY_CAP_STREAM_REPORT)) { > + StreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item)); > + > + agent->report_id = rand(); > + red_channel_pipe_item_init(dcc->common.base.channel, &report_pipe_item->pipe_item, > + PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT); > + report_pipe_item->stream_id = get_stream_id(dcc->common.worker, stream); > + red_channel_client_pipe_add(&dcc->common.base, &report_pipe_item->pipe_item); > + } > + > } > > static void red_stream_input_fps_timer_cb(void *opaque) > @@ -3007,7 +3029,8 @@ static void red_display_client_init_streams(DisplayChannelClient *dcc) > red_channel_pipe_item_init(channel, &agent->create_item, PIPE_ITEM_TYPE_STREAM_CREATE); > red_channel_pipe_item_init(channel, &agent->destroy_item, PIPE_ITEM_TYPE_STREAM_DESTROY); > } > - dcc->use_mjpeg_encoder_rate_control = TRUE; > + dcc->use_mjpeg_encoder_rate_control = > + red_channel_client_test_remote_cap(&dcc->common.base, SPICE_DISPLAY_CAP_STREAM_REPORT); > } > > static void red_display_destroy_streams(DisplayChannelClient *dcc) > @@ -8999,6 +9022,22 @@ static void red_marshall_monitors_config(RedChannelClient *rcc, SpiceMarshaller > free(msg); > } > > +static void red_marshall_stream_activate_report(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + uint32_t stream_id) > +{ > + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + StreamAgent *agent = &dcc->stream_agents[stream_id]; > + SpiceMsgDisplayStreamActivateReport msg; > + > + red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT, NULL); > + msg.stream_id = stream_id; > + msg.unique_id = agent->report_id; > + msg.max_window_size = RED_STREAM_CLIENT_REPORT_WINDOW; > + msg.timeout_ms = RED_STREAM_CLIENT_REPORT_TIMEOUT; > + spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg); > +} > + > static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item) > { > SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); > @@ -9069,6 +9108,13 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item > red_marshall_monitors_config(rcc, m, monconf_item->monitors_config); > break; > } > + case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: { > + StreamActivateReportItem *report_item = SPICE_CONTAINEROF(pipe_item, > + StreamActivateReportItem, > + pipe_item); > + red_marshall_stream_activate_report(rcc, m, report_item->stream_id); > + break; > + } > default: > spice_error("invalid pipe item type"); > } > @@ -9986,6 +10032,37 @@ static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t s > return TRUE; > } > > +static int display_channel_handle_stream_report(DisplayChannelClient *dcc, > + SpiceMsgcDisplayStreamReport *stream_report) > +{ > + StreamAgent *stream_agent; > + > + if (stream_report->stream_id >= NUM_STREAMS) { > + spice_warning("stream_report: invalid stream id %u", stream_report->stream_id); > + return FALSE; > + } > + stream_agent = &dcc->stream_agents[stream_report->stream_id]; > + if (!stream_agent->mjpeg_encoder) { > + spice_info("stream_report: no encoder for stream id %u." > + "Probably the stream has been destroyed", stream_report->stream_id); > + return TRUE; > + } > + > + if (stream_report->unique_id != stream_agent->report_id) { > + spice_warning("local reoprt-id (%u) != msg report-id (%u)", > + stream_agent->report_id, stream_report->unique_id); > + return TRUE; > + } > + mjpeg_encoder_client_stream_report(stream_agent->mjpeg_encoder, > + stream_report->num_frames, > + stream_report->num_drops, > + stream_report->start_frame_mm_time, > + stream_report->end_frame_mm_time, > + stream_report->last_frame_delay, > + stream_report->audio_delay); > + return TRUE; > +} > + > static int display_channel_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, > void *message) > { > @@ -9999,6 +10076,9 @@ static int display_channel_handle_message(RedChannelClient *rcc, uint32_t size, > } > dcc->expect_init = FALSE; > return display_channel_init(dcc, (SpiceMsgcDisplayInit *)message); > + case SPICE_MSGC_DISPLAY_STREAM_REPORT: > + return display_channel_handle_stream_report(dcc, > + (SpiceMsgcDisplayStreamReport *)message); > default: > return red_channel_client_handle_message(rcc, size, type, message); > } > @@ -10348,6 +10428,7 @@ static void display_channel_client_release_item_before_push(DisplayChannelClient > case PIPE_ITEM_TYPE_PIXMAP_SYNC: > case PIPE_ITEM_TYPE_PIXMAP_RESET: > case PIPE_ITEM_TYPE_INVAL_PALLET_CACHE: > + case PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: > free(item); > break; > default: > @@ -10517,7 +10598,7 @@ static void handle_new_display_channel(RedWorker *worker, RedClient *client, Red > spice_info("zlib-over-glz %s", display_channel->enable_zlib_glz_wrap ? "enabled" : "disabled"); > > guest_set_client_capabilities(worker); > - > + > // todo: tune level according to bandwidth > display_channel->zlib_level = ZLIB_DEFAULT_COMPRESSION_LEVEL; > red_display_client_init_streams(dcc); > @@ -11885,6 +11966,7 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data) > if (!spice_timer_queue_create()) { > spice_error("failed to create timer queue"); > } > + srand(time(NULL)); > > message = RED_WORKER_MESSAGE_READY; > write_message(worker->channel, &message); > -- > 1.8.1 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel