spice/server/stream.h
Francois Gouget 97fcad82eb streaming: Always delegate bit rate control to the video encoder
The video encoders already have sophisticated bit rate control code that
can react to both stream reports sent by the client, and server frame
drop notifications. Furthermore they can adjust both the frame rate and
the image quality to best match the network conditions.

But if the client cannot send stream reports all this is bypassed and
instead the streaming code performs its own primitive bit rate control
that can only adjust the frame rate.

So this patch removes the code duplication and lets the video encoders
do their job.

Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
2016-11-21 16:47:51 +00:00

154 lines
5.7 KiB
C

/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (C) 2009-2015 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STREAM_H_
#define STREAM_H_
#include <glib.h>
#include <common/region.h>
#include "utils.h"
#include "video-encoder.h"
#include "red-channel.h"
#include "dcc.h"
#define RED_STREAM_DETECTION_MAX_DELTA (NSEC_PER_SEC / 5)
#define RED_STREAM_CONTINUOUS_MAX_DELTA NSEC_PER_SEC
#define RED_STREAM_TIMEOUT NSEC_PER_SEC
#define RED_STREAM_FRAMES_START_CONDITION 20
#define RED_STREAM_GRADUAL_FRAMES_START_CONDITION 0.2
#define RED_STREAM_FRAMES_RESET_CONDITION 100
#define RED_STREAM_MIN_SIZE (96 * 96)
#define RED_STREAM_INPUT_FPS_TIMEOUT (NSEC_PER_SEC * 5)
#define RED_STREAM_CHANNEL_CAPACITY 0.8
/* the client's stream report frequency is the minimum of the 2 values below */
#define RED_STREAM_CLIENT_REPORT_WINDOW 5 // #frames
#define RED_STREAM_CLIENT_REPORT_TIMEOUT MSEC_PER_SEC
#define RED_STREAM_DEFAULT_HIGH_START_BIT_RATE (10 * 1024 * 1024) // 10Mbps
#define RED_STREAM_DEFAULT_LOW_START_BIT_RATE (2.5 * 1024 * 1024) // 2.5Mbps
#define MAX_FPS 30
typedef struct Stream Stream;
typedef struct RedStreamActivateReportItem {
RedPipeItem pipe_item;
uint32_t stream_id;
} RedStreamActivateReportItem;
#ifdef STREAM_STATS
typedef struct StreamStats {
uint64_t num_drops_pipe;
uint64_t num_drops_fps;
uint64_t num_frames_sent;
uint64_t num_input_frames;
uint64_t size_sent;
uint64_t start;
uint64_t end;
} StreamStats;
#endif
typedef struct StreamAgent {
QRegion vis_region; /* the part of the surface area that is currently occupied by video
fragments */
QRegion clip; /* the current video clipping. It can be different from vis_region:
for example, let c1 be the clip area at time t1, and c2
be the clip area at time t2, where t1 < t2. If c1 contains c2, and
at least part of c1/c2, hasn't been covered by a non-video images,
vis_region will contain c2 and also the part of c1/c2 that still
displays fragments of the video */
Stream *stream;
VideoEncoder *video_encoder;
DisplayChannelClient *dcc;
int fps;
uint32_t report_id;
uint32_t client_required_latency;
#ifdef STREAM_STATS
StreamStats stats;
#endif
} StreamAgent;
typedef struct RedStreamClipItem {
RedPipeItem base;
StreamAgent *stream_agent;
int clip_type;
SpiceClipRects *rects;
} RedStreamClipItem;
RedStreamClipItem * red_stream_clip_item_new (StreamAgent *agent);
typedef struct StreamCreateDestroyItem {
RedPipeItem base;
StreamAgent *agent;
} StreamCreateDestroyItem;
typedef struct ItemTrace {
red_time_t time;
red_time_t first_frame_time;
int frames_count;
int gradual_frames_count;
int last_gradual_frame;
int width;
int height;
SpiceRect dest_area;
} ItemTrace;
struct Stream {
uint8_t refs;
Drawable *current;
red_time_t last_time;
int width;
int height;
SpiceRect dest_area;
int top_down;
Stream *next;
RingItem link;
uint32_t num_input_frames;
uint64_t input_fps_start_time;
uint32_t input_fps;
};
void display_channel_init_streams (DisplayChannel *display);
void stream_stop (DisplayChannel *display,
Stream *stream);
void stream_unref (DisplayChannel *display,
Stream *stream);
void stream_trace_update (DisplayChannel *display,
Drawable *drawable);
void stream_maintenance (DisplayChannel *display,
Drawable *candidate,
Drawable *prev);
void stream_timeout (DisplayChannel *display);
void stream_detach_and_stop (DisplayChannel *display);
void stream_trace_add_drawable (DisplayChannel *display,
Drawable *item);
void stream_detach_behind (DisplayChannel *display,
QRegion *region,
Drawable *drawable);
void stream_agent_unref (DisplayChannel *display,
StreamAgent *agent);
void stream_agent_stop (StreamAgent *agent);
void stream_detach_drawable(Stream *stream);
#endif /* STREAM_H */