Re: [Spice-devel] [PATCH spice 01/13] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 4)

2015-08-04 Thread Francois Gouget
This patch simply replaces the mjpeg_encoder_xxx() call points with a 
more object oriented
design.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---


On Fri, 31 Jul 2015, Victor Toso wrote:
[...]
  +static inline uint8_t *get_image_line(SpiceChunks *chunks, size_t *offset,
  +  int *chunk_nr, int stride)
 
 Lining up with opening parenthesis

Done.


  +static int encode_mjpeg_frame(MJpegEncoder *encoder, const SpiceRect *src,
  +const SpiceBitmap *image, int top_down)
 
 Lining up with opening parenthesis

Done.


  +for (i = 0; i  skip_lines; i++) {
  +get_image_line(chunks, offset, chunk, image_stride);
 
 Decrease one level of identation

Done.


  +if (!src_line) {
  +return FALSE;
  +}
 
 I would remove the brances of above if to keep equal to the if bellow
 
  +
  +src_line += src-left * mjpeg_encoder_get_bytes_per_pixel(encoder);
  +if (mjpeg_encoder_encode_scanline(encoder, src_line, stream_width) 
  == 0)
  +return FALSE;
  +}

Actually I introduced the if below too and it violates the coding 
standard that says if statements should always have braces. So I've done 
a pass through all my patches and it seems this file contained the only 
3 incorrect if statements.


  @@ -2693,18 +2693,19 @@ static void red_stop_stream(RedWorker *worker, 
  Stream *stream)
   region_clear(stream_agent-vis_region);
   region_clear(stream_agent-clip);
   spice_assert(!pipe_item_is_linked(stream_agent-destroy_item));
  -if (stream_agent-mjpeg_encoder  
  dcc-use_mjpeg_encoder_rate_control) {
  -uint64_t stream_bit_rate = 
  mjpeg_encoder_get_bit_rate(stream_agent-mjpeg_encoder);
  -
  -if (stream_bit_rate  dcc-streams_max_bit_rate) {
  -spice_debug(old max-bit-rate=%.2f new=%.2f,
  -dcc-streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
  -stream_bit_rate / 8.0 / 1024.0 / 1024.0);
  -dcc-streams_max_bit_rate = stream_bit_rate;
  +if (stream_agent-video_encoder) {
  +if (dcc-use_video_encoder_rate_control) {
  +uint64_t stream_bit_rate = 
  stream_agent-video_encoder-get_bit_rate(stream_agent-video_encoder);
  +if (stream_bit_rate  dcc-streams_max_bit_rate) {
  +spice_debug(old max-bit-rate=%.2f new=%.2f,
  +dcc-streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
  +stream_bit_rate / 8.0 / 1024.0 / 1024.0);
  +dcc-streams_max_bit_rate = stream_bit_rate;
  +}
   }
  +stream-refs++;
  +red_channel_client_pipe_add(dcc-common.base, 
  stream_agent-destroy_item);
 
 Here you actually changed the logic a bit, moving the strem ref and
 red_channel_client_pipe_add into the if. It does seem correct but I was
 wondering if stream_agent-mjpeg_encoder could be NULL before...

I have not been able to determine that.

mjpeg_encoder is set in the following locations:
 * red_display_create_stream()
   This is where mjpeg_encoder is initialized and in the old code this 
   could not fail. In future patches this may fail.

 * red_display_stream_agent_stop()
 * red_display_destroy_streams_agents()
   Checks whether it is non-NULL and then resets it to NULL.

And mjpeg_encoder is checked against NULL in the following places.
 * red_print_stream_stats()
 * red_stop_stream()
 * red_display_update_streams_max_latency()

But red_marshall_stream_data() assumes it is not NULL.


So clearly mjpeg_encoder is normally not NULL in red_stop_stream() and 
red_print_stream_stats() otherwise they would be unable to collect the 
bit rate and stream statistics. But I could not rule it out 
with certainty.

Let me know if you'd prefer this chunk to go in separately.





diff --git a/server/Makefile.am b/server/Makefile.am
index 89a375c..36b6d45 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -81,7 +81,6 @@ libspice_server_la_SOURCES =  \
main_channel.c  \
main_channel.h  \
mjpeg_encoder.c \
-   mjpeg_encoder.h \
red_bitmap_utils.h  \
red_channel.c   \
red_channel.h   \
@@ -115,6 +114,7 @@ libspice_server_la_SOURCES =\
spicevmc.c  \
spice_timer_queue.c \
spice_timer_queue.h \
+   video_encoder.h \
zlib_encoder.c  \
zlib_encoder.h  \
spice_bitmap_utils.h\
diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 9a41ef3..48042ba 

Re: [Spice-devel] [PATCH spice 01/13] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 4)

2015-07-31 Thread Victor Toso
Hello,

Few comments/suggestions below,

On Tue, Jul 21, 2015 at 08:00:40PM +0200, Francois Gouget wrote:
 This patch simply replaces the mjpeg_encoder_xxx() call points with a more 
 object oriented design.
 
 Signed-off-by: Francois Gouget fgou...@codeweavers.com
 ---
 
 Changes since take 3:
  - A NULL video_encoder means that the stream creation failed so 
red_stop_stream() no longer sends messages to destroy it in
that case. This avoids getting error messages in spice-gtk.
 
  - Removed some forward declarations and made more functions static.
 
  - Tweaked some video_encoder.h comments.
 
 Changes since take 2:
  - No change.
 
 Changes since take 1:
  - I fixed the width/height comments and they now state that they always 
match src.
 
 
  server/Makefile.am |   2 +-
  server/mjpeg_encoder.c | 227 
 +++--
  server/mjpeg_encoder.h | 114 -
  server/red_worker.c| 173 -
  server/video_encoder.h | 165 +++
  5 files changed, 381 insertions(+), 300 deletions(-)
  delete mode 100644 server/mjpeg_encoder.h
  create mode 100644 server/video_encoder.h
 
 diff --git a/server/Makefile.am b/server/Makefile.am
 index 89a375c..36b6d45 100644
 --- a/server/Makefile.am
 +++ b/server/Makefile.am
 @@ -81,7 +81,6 @@ libspice_server_la_SOURCES =\
   main_channel.c  \
   main_channel.h  \
   mjpeg_encoder.c \
 - mjpeg_encoder.h \
   red_bitmap_utils.h  \
   red_channel.c   \
   red_channel.h   \
 @@ -115,6 +114,7 @@ libspice_server_la_SOURCES =  \
   spicevmc.c  \
   spice_timer_queue.c \
   spice_timer_queue.h \
 + video_encoder.h \
   zlib_encoder.c  \
   zlib_encoder.h  \
   spice_bitmap_utils.h\
 diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
 index 9a41ef3..48042ba 100644
 --- a/server/mjpeg_encoder.c
 +++ b/server/mjpeg_encoder.c
 @@ -20,7 +20,11 @@
  #endif
  
  #include red_common.h
 -#include mjpeg_encoder.h
 +
 +typedef struct MJpegEncoder MJpegEncoder;
 +#define VIDEO_ENCODER_T MJpegEncoder
 +#include video_encoder.h
 +
  #include jerror.h
  #include jpeglib.h
  #include inttypes.h
 @@ -154,6 +158,7 @@ typedef struct MJpegEncoderRateControl {
  } MJpegEncoderRateControl;
  
  struct MJpegEncoder {
 +VideoEncoder base;
  uint8_t *row;
  uint32_t row_size;
  int first_frame;
 @@ -165,7 +170,7 @@ struct MJpegEncoder {
  void (*pixel_converter)(uint8_t *src, uint8_t *dest);
  
  MJpegEncoderRateControl rate_control;
 -MJpegEncoderRateControlCbs cbs;
 +VideoEncoderRateControlCbs cbs;
  void *cbs_opaque;
  
  /* stats */
 @@ -174,11 +179,6 @@ struct MJpegEncoder {
  uint32_t num_frames;
  };
  
 -static inline void mjpeg_encoder_reset_quality(MJpegEncoder *encoder,
 -   int quality_id,
 -   uint32_t fps,
 -   uint64_t frame_enc_size);
 -static uint32_t get_max_fps(uint64_t frame_size, uint64_t bytes_per_sec);
  static void mjpeg_encoder_process_server_drops(MJpegEncoder *encoder);
  static uint32_t get_min_required_playback_delay(uint64_t frame_enc_size,
  uint64_t byte_rate,
 @@ -189,49 +189,14 @@ static inline int rate_control_is_active(MJpegEncoder* 
 encoder)
  return encoder-cbs.get_roundtrip_ms != NULL;
  }
  
 -MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 -MJpegEncoderRateControlCbs *cbs, void 
 *opaque)
 -{
 -MJpegEncoder *enc;
 -
 -spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
 cbs-get_source_fps));
 -
 -enc = spice_new0(MJpegEncoder, 1);
 -
 -enc-first_frame = TRUE;
 -enc-rate_control.byte_rate = starting_bit_rate / 8;
 -enc-starting_bit_rate = starting_bit_rate;
 -
 -if (cbs) {
 -struct timespec time;
 -
 -clock_gettime(CLOCK_MONOTONIC, time);
 -enc-cbs = *cbs;
 -enc-cbs_opaque = opaque;
 -mjpeg_encoder_reset_quality(enc, MJPEG_QUALITY_SAMPLE_NUM / 2, 5, 0);
 -enc-rate_control.during_quality_eval = TRUE;
 -enc-rate_control.quality_eval_data.type = 
 MJPEG_QUALITY_EVAL_TYPE_SET;
 -enc-rate_control.quality_eval_data.reason = 
 MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
 -enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
 10 + time.tv_nsec;
 -} else {
 -enc-cbs.get_roundtrip_ms = NULL;
 -mjpeg_encoder_reset_quality(enc, 

[Spice-devel] [PATCH spice 01/13] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 4)

2015-07-21 Thread Francois Gouget
This patch simply replaces the mjpeg_encoder_xxx() call points with a more 
object oriented design.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Changes since take 3:
 - A NULL video_encoder means that the stream creation failed so 
   red_stop_stream() no longer sends messages to destroy it in
   that case. This avoids getting error messages in spice-gtk.

 - Removed some forward declarations and made more functions static.

 - Tweaked some video_encoder.h comments.

Changes since take 2:
 - No change.

Changes since take 1:
 - I fixed the width/height comments and they now state that they always 
   match src.


 server/Makefile.am |   2 +-
 server/mjpeg_encoder.c | 227 +++--
 server/mjpeg_encoder.h | 114 -
 server/red_worker.c| 173 -
 server/video_encoder.h | 165 +++
 5 files changed, 381 insertions(+), 300 deletions(-)
 delete mode 100644 server/mjpeg_encoder.h
 create mode 100644 server/video_encoder.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 89a375c..36b6d45 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -81,7 +81,6 @@ libspice_server_la_SOURCES =  \
main_channel.c  \
main_channel.h  \
mjpeg_encoder.c \
-   mjpeg_encoder.h \
red_bitmap_utils.h  \
red_channel.c   \
red_channel.h   \
@@ -115,6 +114,7 @@ libspice_server_la_SOURCES =\
spicevmc.c  \
spice_timer_queue.c \
spice_timer_queue.h \
+   video_encoder.h \
zlib_encoder.c  \
zlib_encoder.h  \
spice_bitmap_utils.h\
diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 9a41ef3..48042ba 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -20,7 +20,11 @@
 #endif
 
 #include red_common.h
-#include mjpeg_encoder.h
+
+typedef struct MJpegEncoder MJpegEncoder;
+#define VIDEO_ENCODER_T MJpegEncoder
+#include video_encoder.h
+
 #include jerror.h
 #include jpeglib.h
 #include inttypes.h
@@ -154,6 +158,7 @@ typedef struct MJpegEncoderRateControl {
 } MJpegEncoderRateControl;
 
 struct MJpegEncoder {
+VideoEncoder base;
 uint8_t *row;
 uint32_t row_size;
 int first_frame;
@@ -165,7 +170,7 @@ struct MJpegEncoder {
 void (*pixel_converter)(uint8_t *src, uint8_t *dest);
 
 MJpegEncoderRateControl rate_control;
-MJpegEncoderRateControlCbs cbs;
+VideoEncoderRateControlCbs cbs;
 void *cbs_opaque;
 
 /* stats */
@@ -174,11 +179,6 @@ struct MJpegEncoder {
 uint32_t num_frames;
 };
 
-static inline void mjpeg_encoder_reset_quality(MJpegEncoder *encoder,
-   int quality_id,
-   uint32_t fps,
-   uint64_t frame_enc_size);
-static uint32_t get_max_fps(uint64_t frame_size, uint64_t bytes_per_sec);
 static void mjpeg_encoder_process_server_drops(MJpegEncoder *encoder);
 static uint32_t get_min_required_playback_delay(uint64_t frame_enc_size,
 uint64_t byte_rate,
@@ -189,49 +189,14 @@ static inline int rate_control_is_active(MJpegEncoder* 
encoder)
 return encoder-cbs.get_roundtrip_ms != NULL;
 }
 
-MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
-MJpegEncoderRateControlCbs *cbs, void *opaque)
-{
-MJpegEncoder *enc;
-
-spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
-
-enc = spice_new0(MJpegEncoder, 1);
-
-enc-first_frame = TRUE;
-enc-rate_control.byte_rate = starting_bit_rate / 8;
-enc-starting_bit_rate = starting_bit_rate;
-
-if (cbs) {
-struct timespec time;
-
-clock_gettime(CLOCK_MONOTONIC, time);
-enc-cbs = *cbs;
-enc-cbs_opaque = opaque;
-mjpeg_encoder_reset_quality(enc, MJPEG_QUALITY_SAMPLE_NUM / 2, 5, 0);
-enc-rate_control.during_quality_eval = TRUE;
-enc-rate_control.quality_eval_data.type = MJPEG_QUALITY_EVAL_TYPE_SET;
-enc-rate_control.quality_eval_data.reason = 
MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
-enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
10 + time.tv_nsec;
-} else {
-enc-cbs.get_roundtrip_ms = NULL;
-mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, 
MJPEG_MAX_FPS, 0);
-}
-
-enc-cinfo.err = jpeg_std_error(enc-jerr);
-jpeg_create_compress(enc-cinfo);
-
-return enc;
-}
-
-void mjpeg_encoder_destroy(MJpegEncoder *encoder)