mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 07:29:32 +00:00
mjpeg_encoder: move the control over frame drops to mjpeg_encoder
This commit is contained in:
parent
44ce87b55a
commit
6f883d0eb5
@ -651,9 +651,15 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format,
|
||||
MJpegEncoderRateControl *rate_control = &encoder->rate_control;
|
||||
struct timespec time;
|
||||
uint64_t now;
|
||||
uint64_t interval;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
now = ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
|
||||
interval = (now - rate_control->bit_rate_info.last_frame_time);
|
||||
|
||||
if (interval < (1000*1000*1000) / rate_control->fps) {
|
||||
return MJPEG_ENCODER_FRAME_DROP;
|
||||
}
|
||||
|
||||
mjpeg_encoder_adjust_params_to_bit_rate(encoder);
|
||||
|
||||
@ -700,14 +706,14 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format,
|
||||
break;
|
||||
default:
|
||||
spice_warning("unsupported format %d", format);
|
||||
return FALSE;
|
||||
return MJPEG_ENCODER_FRAME_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (encoder->pixel_converter != NULL) {
|
||||
unsigned int stride = width * 3;
|
||||
/* check for integer overflow */
|
||||
if (stride < width) {
|
||||
return FALSE;
|
||||
return MJPEG_ENCODER_FRAME_UNSUPPORTED;
|
||||
}
|
||||
if (encoder->row_size < stride) {
|
||||
encoder->row = spice_realloc(encoder->row, stride);
|
||||
@ -725,7 +731,7 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format,
|
||||
jpeg_set_quality(&encoder->cinfo, quality, TRUE);
|
||||
jpeg_start_compress(&encoder->cinfo, encoder->first_frame);
|
||||
|
||||
return TRUE;
|
||||
return MJPEG_ENCODER_FRAME_ENCODE_START;
|
||||
}
|
||||
|
||||
int mjpeg_encoder_encode_scanline(MJpegEncoder *encoder, uint8_t *src_pixels,
|
||||
@ -783,14 +789,6 @@ size_t mjpeg_encoder_end_frame(MJpegEncoder *encoder)
|
||||
return encoder->rate_control.last_enc_size;
|
||||
}
|
||||
|
||||
uint32_t mjpeg_encoder_get_fps(MJpegEncoder *encoder)
|
||||
{
|
||||
if (!encoder->rate_control_is_active) {
|
||||
spice_warning("bit rate control is not active");
|
||||
}
|
||||
return encoder->rate_control.fps;
|
||||
}
|
||||
|
||||
static void mjpeg_encoder_quality_eval_stop(MJpegEncoder *encoder)
|
||||
{
|
||||
MJpegEncoderRateControl *rate_control = &encoder->rate_control;
|
||||
|
||||
@ -21,6 +21,12 @@
|
||||
|
||||
#include "red_common.h"
|
||||
|
||||
enum {
|
||||
MJPEG_ENCODER_FRAME_UNSUPPORTED = -1,
|
||||
MJPEG_ENCODER_FRAME_DROP,
|
||||
MJPEG_ENCODER_FRAME_ENCODE_START,
|
||||
};
|
||||
|
||||
typedef struct MJpegEncoder MJpegEncoder;
|
||||
|
||||
/*
|
||||
@ -44,8 +50,15 @@ void mjpeg_encoder_destroy(MJpegEncoder *encoder);
|
||||
uint8_t mjpeg_encoder_get_bytes_per_pixel(MJpegEncoder *encoder);
|
||||
|
||||
/*
|
||||
* *dest must be either NULL or allocated by malloc, since it might be freed
|
||||
* dest must be either NULL or allocated by malloc, since it might be freed
|
||||
* during the encoding, if its size is too small.
|
||||
*
|
||||
* return:
|
||||
* MJPEG_ENCODER_FRAME_UNSUPPORTED : frame cannot be encoded
|
||||
* MJPEG_ENCODER_FRAME_DROP : frame should be dropped. This value can only be returned
|
||||
* if mjpeg rate control is active.
|
||||
* MJPEG_ENCODER_FRAME_ENCODE_START: frame encoding started. Continue with
|
||||
* mjpeg_encoder_encode_scanline.
|
||||
*/
|
||||
int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format,
|
||||
int width, int height,
|
||||
@ -59,12 +72,6 @@ size_t mjpeg_encoder_end_frame(MJpegEncoder *encoder);
|
||||
* bit rate control
|
||||
*/
|
||||
|
||||
/*
|
||||
* The recommended output frame rate (per second) for the
|
||||
* current available bit rate.
|
||||
*/
|
||||
uint32_t mjpeg_encoder_get_fps(MJpegEncoder *encoder);
|
||||
|
||||
/*
|
||||
* Data that should be periodically obtained from the client. The report contains:
|
||||
* num_frames : the number of frames that reached the client during the time
|
||||
|
||||
@ -8352,6 +8352,7 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc,
|
||||
RedWorker *worker = dcc->common.worker;
|
||||
int n;
|
||||
int width, height;
|
||||
int ret;
|
||||
|
||||
if (!stream) {
|
||||
spice_assert(drawable->sized_stream);
|
||||
@ -8389,13 +8390,24 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc,
|
||||
}
|
||||
|
||||
outbuf_size = dcc->send_data.stream_outbuf_size;
|
||||
if (!mjpeg_encoder_start_frame(agent->mjpeg_encoder, image->u.bitmap.format,
|
||||
width, height,
|
||||
&dcc->send_data.stream_outbuf,
|
||||
&outbuf_size,
|
||||
drawable->red_drawable->mm_time)) {
|
||||
ret = mjpeg_encoder_start_frame(agent->mjpeg_encoder, image->u.bitmap.format,
|
||||
width, height,
|
||||
&dcc->send_data.stream_outbuf,
|
||||
&outbuf_size,
|
||||
drawable->red_drawable->mm_time);
|
||||
switch (ret) {
|
||||
case MJPEG_ENCODER_FRAME_DROP:
|
||||
spice_warning("mjpeg rate control is not supported yet");
|
||||
return TRUE;
|
||||
case MJPEG_ENCODER_FRAME_UNSUPPORTED:
|
||||
return FALSE;
|
||||
case MJPEG_ENCODER_FRAME_ENCODE_START:
|
||||
break;
|
||||
default:
|
||||
spice_error("bad return value (%d) from mjpeg_encoder_start_frame", ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!encode_frame(dcc, &drawable->red_drawable->u.copy.src_area,
|
||||
&image->u.bitmap, stream)) {
|
||||
return FALSE;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user