[Spice-devel] [PATCH spice-server 17/28] red_worker: support SPICE_MSGC_DISPLAY_STREAM_REPORT

Alon Levy alevy at redhat.com
Sun Apr 14 06:30:50 PDT 2013


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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list