예제 #1
0
static int end_block( void *d )
{
	struct framedropper *drop = (struct framedropper *)d;

	if( ! drop->input )
	{
		spook_log( SL_ERR,
			"framedrop: missing input stream name" );
		return -1;
	}
	if( ! drop->output )
	{
		spook_log( SL_ERR,
			"framedrop: missing output stream name" );
		return -1;
	}
	if( drop->scale < 1 )
	{
		spook_log( SL_ERR,
			"framedrop: missing scale factor" );
		return -1;
	}

	return 0;
}
예제 #2
0
static int end_block(void *d)
{
	struct adpcm_encoder *en = (struct adpcm_encoder *)d;
	int32_t i32Ret;

	if (! en->output) {
		spook_log(SL_ERR, "adpcm: missing output stream name");
		return -1;
	}

	i32Ret = ImportAdpcmEncConfig(&en->sAdpcmEncConfig);

	if (i32Ret < 0)
		return i32Ret;

	if (en->sAdpcmEncConfig.m_eFormat == eADPCM_IMA) {
		spook_log(SL_ERR, "adpcm: missing DVI format");
		return -1;
	}

	//create import alaw thread
	en->ex = new_exchanger(4, deliver_frame_to_stream, en->output);
	pthread_create(&en->thread, NULL, adpcm_loop, en);

	return 0;
}
예제 #3
0
static int set_format( int num_tokens, struct token *tokens, void *d )
{
	struct rtp_spook_input *conf = (struct rtp_spook_input *)d;

	if( conf->output )
	{
		spook_log( SL_ERR, "rtpi: output format must be specified "
				"before output stream name" );
		return -1;
	}
	if( ! strcasecmp( tokens[1].v.str, "pcm" ) )
		conf->format = FORMAT_PCM;
	else if( ! strcasecmp( tokens[1].v.str, "mpeg4" ) )
		conf->format = FORMAT_MPEG4;
	else if( ! strcasecmp( tokens[1].v.str, "mjpeg" ) )
		conf->format = FORMAT_JPEG;
	else
	{
		spook_log( SL_ERR, "rtpi: format \"%s\" is unsupported; try "
				"PCM, MJPEG, or MPEG4", tokens[1].v.str );
		return -1;
	}

	return 0;
}
예제 #4
0
static void do_accept( struct event_info *ei, void *d )
{
	struct listener *listener = (struct listener *)d;
	int fd, addrlen;
	struct sockaddr_un addr;
	struct ctl_sock *cs;

	addrlen = sizeof( addr );
	if( ( fd = accept( listener->fd, (struct sockaddr *)&addr, &addrlen ) ) < 0 )
	{
		spook_log( SL_WARN, "error accepting control connection: %s",
				strerror( errno ) );
		return;
	}
	spook_log( SL_DEBUG, "accepted control connection" );

	cs = (struct ctl_sock *)malloc( sizeof( struct ctl_sock ) );
	if( ! cs )
	{
		spook_log( SL_ERR, "out of memory on malloc ctl_sock" );
		close( fd );
		return;
	}
	cs->fd = fd;
	cs->read_event = add_fd_event( fd, 0, 0, do_read, cs );
}
예제 #5
0
static bool
SimpleAnalyserHasImproved(
	S_QOS_ANALYSER *psObjBase
)
{
	SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase;
	S_RTP_STATS *psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY];
	S_RTP_STATS *psPrev = &psObj->sStats[(STATS_HISTORY + psObj->i32CurIndex - 1) % STATS_HISTORY];

	if (psPrev->fLostPercentage >= fUnacceptableLossRate) {
		if (psCur->fLostPercentage < psPrev->fLostPercentage) {
			spook_log(SL_INFO, "MSQosAnalyser: lost percentage has improved");
			return true;
		}
		else goto end;
	}

	if (psObj->bRoundTripPropDoubled && psCur->fRoundTripProp < psPrev->fRoundTripProp) {
		spook_log(SL_INFO, "MSQosAnalyser: rt prop decrased");
		psObj->bRoundTripPropDoubled = false;
		return true;
	}

end:
	spook_log(SL_INFO, "MSQosAnalyser: no improvements.");
	return false;
}
예제 #6
0
static int end_block( void *d )
{
	struct mpeg4_encoder *en = (struct mpeg4_encoder *)d;

	if( ! en->output )
	{
		spook_log( SL_ERR, "mpeg4: missing output stream name" );
		return -1;
	}
	if( ! en->input )
	{
		spook_log( SL_ERR, "mpeg4: missing input stream name" );
		return -1;
	}
	if( en->bitrate < 0 )
	{
		spook_log( SL_ERR, "mpeg4: bitrate must be specified" );
		return -1;
	}

	en->ex = new_exchanger( 8, deliver_frame_to_stream, en->output );
	pthread_create( &en->encoding_thread, NULL, mpeg4_loop, en );

	return 0;
}
예제 #7
0
static int end_block( void *d )
{
	struct rtp_spook_input *conf = (struct rtp_spook_input *)d;
	int i;

	if( ! conf->output )
	{
		spook_log( SL_ERR, "rtpi: missing output stream name" );
		return -1;
	}
	if( conf->fps < 0 )
	{
		spook_log( SL_ERR,
			"v4l: framerate not specified for webcam" );
		return -1;
	} else if( conf->fps > 0 )
	{
		conf->fincr = 1;
		conf->fbase = conf->fps;
	} 
    else
    {
    	spook_log( SL_INFO, "v4l: must figure out framerate" );
        return -1;
    }
        
	if( rtp_setup( conf ) < 0 ) return -1;
	conf->ex = new_exchanger( conf->fps, get_back_frame1, conf );
	for( i = 0; i < conf->fps; ++i ) 
        exchange_frame( conf->ex, new_frame() );
	pthread_create( &conf->thread, NULL, capture_loop, conf );

	return 0;
}
예제 #8
0
static int dc1394_setup( struct dc1394_input *conf )
{
	raw1394handle_t raw_handle;
	nodeid_t *camera_nodes = NULL;
	int numPorts;
	int actual_count = 0, c, i;
	struct raw1394_portinfo ports[16];

	raw_handle = raw1394_new_handle();
	if( ! raw_handle )
	{
		spook_log( SL_ERR,
			"dc1394: unable to acquire a raw1394 handle" );
		return -1;
	}

	numPorts = raw1394_get_port_info( raw_handle, ports, 16 );
	raw1394_destroy_handle( raw_handle );
	for( i = 0; i < numPorts; ++i )
	{
		int camCount = 0;

		raw_handle = raw1394_new_handle();
		raw1394_set_port( raw_handle, i );
		camera_nodes = dc1394_get_camera_nodes( raw_handle,
							&camCount, 1 );
		raw1394_destroy_handle( raw_handle );
		spook_log( SL_INFO, "dc1394: found %d cams on port %d",
				camCount, i );
		for( c = 0; c < camCount; ++c )
		{
			if( cam_setup( conf, actual_count, i,
						camera_nodes[c], c ) < 0 )
				return -1;
			if( ++actual_count == conf->cam_count ) return 0;
		}
		// this doesn't work, fix later (just a li'l memory leak...)
		//dc1394_free_camera_nodes( camera_nodes );
	}

	if( actual_count == 0 )
	{
		spook_log( SL_ERR, "dc1394: did not find any IIDC cameras" );
		return -1;
	}

	if( actual_count < conf->cam_count )
		spook_log( SL_WARN,
			"dc1394: only found %d cameras, some outputs will be inactive",
			actual_count );

	return 0;
}
예제 #9
0
static void drop_sock( struct ctl_sock *cs )
{
	spook_log( SL_DEBUG, "closed control connection" );
	remove_event( cs->read_event );
	close( cs->fd );
	free( cs );
}
예제 #10
0
static int end_block(void *d)
{
	struct h264_encoder *en = (struct h264_encoder *)d;
	int32_t i32Ret;

	if (! en->output) {
		spook_log(SL_ERR, "h264: missing output stream name");
		return -1;
	}

	i32Ret = ImportH264EncConfig(&en->sH264EncConfig);

	if (i32Ret < 0)
		return i32Ret;

	if (en->eH264EncRes >= en->sH264EncConfig.m_ui32WorkablePipes) {
		printf("plugin-rtsp: No H264 workable pipes \n");
		return -2;
	}

	en->ex = new_exchanger(get_max_frame_slot() * 2, deliver_frame_to_stream, en->output);
	//	en->ex = new_exchanger( 8, deliver_frame_to_stream, en->output );

	//use push callback instead of import
	//	pthread_create( &en->thread, NULL, h264_loop, en );

	return 0;
}
예제 #11
0
static bool
SimpleAnalyserProcRTCP(
	S_QOS_ANALYSER *psObjBase,
	S_RTCP_MBLK *psRTCPBlk,
	int32_t i32ClockRate
)
{
	SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase;
	S_RTP_STATS *psCur;
	const S_RTCP_REPORT_BLOCK *psRB = NULL;

	psRB = RTCP_RR_GetReportBlock(psRTCPBlk, 0);

	if (psRB && (REPORT_BLOCK_GET_SSRC(psRB) == psObj->u32SSRC)) {

		psObj->i32CurIndex ++;

		psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY];

		psCur->u64HighSeqRecv = REPORT_BLOCK_GET_HIGH_EXT_SEQ(psRB);
		psCur->fLostPercentage = 100.0 * (float)REPORT_BLOCK_GET_FRACTION_LOST(psRB) / 256.0;
		psCur->fIntJitter = 1000.0 * (float)REPORT_BLOCK_GET_INTERARRIVAL_JITTER(psRB) / (float)i32ClockRate;
		psCur->fRoundTripProp = psObj->psRTPep->dRTT;

		spook_log(SL_INFO, "MSQosAnalyser: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec", psCur->fLostPercentage,
				  psCur->fIntJitter, psCur->fRoundTripProp);
	}

	return psRB != NULL;
}
예제 #12
0
static void *capture_loop( void *d )
{
	struct oss_input *conf = (struct oss_input *)d;
	unsigned char *buf;
	int len = 0, ret, blocksize;

	blocksize = conf->rate * conf->channels * 2 / 50;

	spook_log( SL_VERBOSE, "input-oss: blocksize is %d", blocksize );
	buf = malloc( blocksize );

	for(;;)
	{
		ret = read( conf->fd, buf + len, blocksize - len );
		if( ret < 0 )
		{
			perror( "read" );
			break;
		}
		len += ret;
		if( len == blocksize )
		{
			audio_ring_input( conf->ring, buf, len );
			len = 0;
		}
	}
	return NULL;
}
예제 #13
0
static void mpeg4_stop( struct mpeg4_decoder *en )
{
	spook_log( SL_DEBUG, "mpeg4: destroying mpeg4 decoder" );

	xvid_decore( en->xvid_handle, XVID_DEC_DESTROY, NULL, NULL );
	en->xvid_handle = NULL;
}
예제 #14
0
static void mpeg4_start( struct mpeg4_encoder *en, struct frame *f )
{
	xvid_enc_create_t xvid_enc_create;
	xvid_enc_plugin_t plugins[1];
	xvid_plugin_single_t single;

	en->reset_pending = 0;
	en->width = f->width;
	en->height = f->height;

	memset( &xvid_enc_create, 0, sizeof( xvid_enc_create ) );
	xvid_enc_create.version = XVID_VERSION;
	xvid_enc_create.width = en->width;
	xvid_enc_create.height = en->height;
	xvid_enc_create.profile = XVID_PROFILE_ARTS_L4;
	en->input->stream->get_framerate( en->input->stream,
						&xvid_enc_create.fincr,
						&xvid_enc_create.fbase );
	spook_log( SL_DEBUG, "creating mpeg4 encoder with fincr=%d fbase=%d",
			xvid_enc_create.fincr, xvid_enc_create.fbase );
	xvid_enc_create.zones = NULL;
	xvid_enc_create.num_zones = 0;
	xvid_enc_create.plugins = plugins;
	xvid_enc_create.num_plugins = 1;
	xvid_enc_create.num_threads = 0;
	xvid_enc_create.max_key_interval = 300;
	xvid_enc_create.max_bframes = 0;
	xvid_enc_create.bquant_ratio = 150;
	xvid_enc_create.bquant_offset = 100;
	xvid_enc_create.frame_drop_ratio = 0;
	xvid_enc_create.global = 0;

	memset( &single, 0, sizeof( single ) );
	single.version = XVID_VERSION;
	single.bitrate = en->bitrate * 1000;
	plugins[0].func = xvid_plugin_single;
	plugins[0].param = &single;

	if( xvid_encore( NULL, XVID_ENC_CREATE,
				&xvid_enc_create, NULL ) )
	{
		spook_log( SL_ERR, "mpeg4: unable to start XviD!" );
		return;
	}

	en->xvid_handle = xvid_enc_create.handle;
}
예제 #15
0
static void *mpeg4_loop( void *d )
{
	struct mpeg4_decoder *en = (struct mpeg4_decoder *)d;
	xvid_dec_frame_t xvid_dec_frame;
	xvid_dec_stats_t xvid_dec_stats;
	struct frame *out, *input;
	int used, pos;

	for(;;)
	{
		input = get_next_frame( en->ex, 1 );

		if( en->reset_pending && en->xvid_handle ) mpeg4_stop( en );
		if( ! en->xvid_handle ) mpeg4_start( en, input );

		out = new_frame();
		out->width = en->width;
		out->height = en->height;

		pos = 0;

		while( input->length - pos > 0 )
		{
			memset( &xvid_dec_frame, 0, sizeof( xvid_dec_frame ) );
			xvid_dec_frame.version = XVID_VERSION;
			xvid_dec_frame.general = 0;
			xvid_dec_frame.bitstream = input->d + pos;
			xvid_dec_frame.length = input->length - pos;
			xvid_dec_frame.output.plane[0] = out->d;
			xvid_dec_frame.output.stride[0] = 2 * out->width;
			xvid_dec_frame.output.csp = XVID_CSP_UYVY;
			xvid_dec_stats.version = XVID_VERSION;

			used = xvid_decore( en->xvid_handle, XVID_DEC_DECODE,
					&xvid_dec_frame, &xvid_dec_stats );
			if( used < 0 )
			{
				out->length = 0;
				spook_log( SL_WARN, "mpeg4: XviD decoding failed!" );
			}
			if( xvid_dec_stats.type == XVID_TYPE_VOL )
			{
				out->width = en->width = xvid_dec_stats.data.vol.width;
				out->height = en->height = xvid_dec_stats.data.vol.height;
			}
			pos += used;
		}

		out->format = FORMAT_RAW_UYVY;
		out->length = 2 * out->width * out->height;
		out->key = 1;

		deliver_frame( en->ex, out );

		unref_frame( input );
	}

	return NULL;
}
예제 #16
0
static int cam_setup( struct dc1394_input *conf, int cam, int port,
				nodeid_t node, int dma_chan )
{
	unsigned int channel;
	unsigned int speed;

	conf->cam[cam].running = 0;
	conf->camera[cam].node = node;
	conf->cam[cam].handle = dc1394_create_handle( port );
	if( ! conf->cam[cam].handle )
	{
		spook_log( SL_ERR, "dc1394: unable to create a camera handle" );
		return -1;
	}
	if( dc1394_get_iso_channel_and_speed( conf->cam[cam].handle, node,
				&channel, &speed ) != DC1394_SUCCESS )
	{
		spook_log( SL_ERR, "dc1394: unable to create an ISO channel" );
		return -1;
	}

	if( dc1394_dma_setup_capture( conf->cam[cam].handle, node, dma_chan,
				FORMAT_VGA_NONCOMPRESSED, MODE_320x240_YUV422,
				SPEED_400, FRAMERATE_30, 8 /* num buffers */,
#ifdef DC1394_EXTRA_BUFFERING_FLAG
				0 /* do_extra_buffering */,
#endif
				1 /* drop frames */, NULL /* device name */,
				&conf->camera[cam] ) != DC1394_SUCCESS )
	{
		spook_log( SL_ERR, "dc1394: unable to set up DMA for camera" );
		return -1;
	}
	if( dc1394_start_iso_transmission( conf->cam[cam].handle,
				conf->camera[cam].node ) != DC1394_SUCCESS )
	{
		spook_log( SL_ERR,
			"dc1394: unable to start ISO transfer from camera" );
		return -1;
	}
	conf->cam[cam].outq = new_soft_queue( 16 );
	add_softqueue_event( conf->cam[cam].outq, 0,
			get_back_frame, &conf->cam[cam] );
	return 0;
}
예제 #17
0
static int end_block( void *d )
{
	struct dc1394_input *conf = (struct dc1394_input *)d;

	if( conf->cam_count == 0 )
	{
		spook_log( SL_ERR, "dc1394: missing output stream name" );
		return -1;
	}
	if( dc1394_setup( conf ) < 0 )
	{
		spook_log( SL_ERR, "dc1394: unable to initialize video input" );
		return -1;
	}
	pthread_create( &conf->thread, NULL, capture_loop, conf );

	return 0;
}
예제 #18
0
static void set_running( struct stream *s, int running )
{
	struct mpeg4_decoder *en = (struct mpeg4_decoder *)s->private;

	spook_log( SL_DEBUG,
		"mpeg4 decoder is told to set running to %d", running );

	if( ! en->running && running ) en->reset_pending = 1;
	set_waiting( en->input, running );
	en->running = running;
}
예제 #19
0
int control_listen(void)
{
	struct sockaddr_un addr;
	struct listener *listener;
	int fd;

	addr.sun_family = AF_UNIX;
	strcpy( addr.sun_path, "spook.sock" );

	unlink( addr.sun_path );
	if( ( fd = socket( PF_UNIX, SOCK_STREAM, 0 ) ) < 0 )
	{
		spook_log( SL_ERR, "error creating control socket: %s",
				strerror( errno ) );
		return -1;
	}
	if( bind( fd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 )
	{
		spook_log( SL_ERR, "unable to bind control socket: %s",
				strerror( errno ) );
		close( fd );
		return -1;
	}
	if( listen( fd, 5 ) < 0 )
	{
		spook_log( SL_ERR,
			"error attempting to listen on control socket: %s",
			strerror( errno ) );
		close( fd );
		return -1;
	}

	listener = (struct listener *)malloc( sizeof( struct listener ) );
	listener->fd = fd;

	add_fd_event( fd, 0, 0, do_accept, listener );

	spook_log( SL_INFO, "listening on control socket %s", addr.sun_path );

	return 0;
}
예제 #20
0
bool
QOSAnalyser_HasImproved(
	S_QOS_ANALYSER *psObj
)
{
	if (psObj->psDesc->pfn_has_improved) {
		return psObj->psDesc->pfn_has_improved(psObj);
	}

	spook_log(SL_VERBOSE, "Unimplemented has_improved() call.");
	return true;
}
예제 #21
0
static int set_framerate_num( int num_tokens, struct token *tokens, void *d )
{
	struct rtp_spook_input *conf = (struct rtp_spook_input *)d;

	if( conf->fps >= 0 )
	{
		spook_log( SL_ERR, "v4l: frame rate has already been set!" );
		return -1;
	}
	conf->fps = tokens[1].v.num;

	return 0;
}
예제 #22
0
static int set_scale( int num_tokens, struct token *tokens, void *d )
{
	struct framedropper *drop = (struct framedropper *)d;

	if( tokens[1].v.num < 1 )
	{
		spook_log( SL_ERR,
			"framedrop: scale factor cannot be less than 1!" );
		return -1;
	}
	drop->scale = tokens[1].v.num;
	return 0;
}
예제 #23
0
static int set_bitrate( int num_tokens, struct token *tokens, void *d )
{
	struct mpeg4_encoder *en = (struct mpeg4_encoder *)d;

	if( tokens[1].v.num < 10 || tokens[1].v.num > 4000 )
	{
		spook_log( SL_ERR,
			"mpeg4: bitrate must be between 10 and 4000" );
		return -1;
	}
	en->bitrate = tokens[1].v.num;
	return 0;
}
예제 #24
0
static int set_samplerate( int num_tokens, struct token *tokens, void *d )
{
	struct oss_input *conf = (struct oss_input *)d;

	if( conf->rate > 0 )
	{
		spook_log( SL_ERR, "oss: sample rate has already been set!" );
		return -1;
	}
	conf->rate = tokens[1].v.num;

	return 0;
}
예제 #25
0
static int mpv_process_frame(struct frame *f, void *d)
{
	struct rtp_mpv *out = (struct rtp_mpv *)d;
	int flen, start, in_picture = 0, have_vsh = 0;
	unsigned int start_code;

	out->blk_count = 0;

	for (start = 0; start < f->length; start += flen) {
		if (out->blk_count == 48) {
			spook_log(SL_WARN,
					  "rtp-mpv: too many elements to send");
			break;
		}

		flen = find_next_code(f->d + start, f->length - start);

		if (flen == 0) flen = f->length - start;

		start_code = GET_32(f->d + start);

		if (start_code <= 0x000001AF || start_code == 0x000001B8)
			in_picture = 1;

		if (in_picture) {
			if (start_code == 0x00000100)
				parse_picture_header(out, f->d + start, flen);

			out->blk[out->blk_count].d = f->d + start;
			out->blk[out->blk_count].len = flen;
			++out->blk_count;
		}
		else { /* we have not seen a GOP or picture start code yet */
			if (start_code == 0x000001B3) {
				out->vsh_len = 0;
				have_vsh = 1;
				parse_video_sequence_header(out,
											f->d + start, flen);
			}

			if (have_vsh) {
				memcpy(out->vsh + out->vsh_len,
					   f->d + start, flen);
				out->vsh_len += flen;
			}
		}
	}

	return out->init_done;
}
예제 #26
0
static int set_output( int num_tokens, struct token *tokens, void *d )
{
	struct framedropper *drop = (struct framedropper *)d;

	if( ! drop->input )
	{
		spook_log( SL_ERR,
			"framedrop: input must be specified before output" );
		return -1;
	}
	drop->output = new_stream( tokens[1].v.str,
					drop->input->stream->format, drop );
	if( ! drop->output )
	{
		spook_log( SL_ERR,
			"framedrop: unable to create stream \"%s\"",
			tokens[1].v.str );
		return -1;
	}
	drop->output->get_framerate = get_framerate;
	drop->output->set_running = set_running;
	return 0;
}
예제 #27
0
static int set_input( int num_tokens, struct token *tokens, void *d )
{
	struct mpeg4_decoder *en = (struct mpeg4_decoder *)d;
	int formats[1] = { FORMAT_MPEG4 };

	if( ! ( en->input = connect_to_stream( tokens[1].v.str, mpeg4_decode,
						en, formats, 1 ) ) )
	{
		spook_log( SL_ERR, "mpeg4: unable to connect to stream \"%s\"",
				tokens[1].v.str );
		return -1;
	}
	return 0;
}
예제 #28
0
bool
QOSAnalyser_ProcRTCP(
	S_QOS_ANALYSER *psObj,
	S_RTCP_MBLK *psRTCPBlk,
	int32_t i32ClockRate
)
{
	if (psObj->psDesc->pfn_proc_rtcp) {
		return psObj->psDesc->pfn_proc_rtcp(psObj, psRTCPBlk, i32ClockRate);
	}

	spook_log(SL_VERBOSE, "Unimplemented process_rtcp() call.");
	return false;
}
예제 #29
0
static int set_input( int num_tokens, struct token *tokens, void *d )
{
	struct framedropper *drop = (struct framedropper *)d;

	if( ! ( drop->input = connect_to_stream( tokens[1].v.str, do_framedrop,
						drop, NULL, 0 ) ) )
	{
		spook_log( SL_ERR,
			"framedrop: unable to connect to stream \"%s\"\n",
				tokens[1].v.str );
		return -1;
	}
	return 0;
}
예제 #30
0
static void
SimpleAnalyserSuggestAction(
	S_QOS_ANALYSER *psObjBase,
	S_RATE_CTRL_ACT *psAction
)
{
	SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase;
	S_RTP_STATS *psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY];


	/*big losses and big jitter */
	if (psCur->fLostPercentage >= fUnacceptableLossRate && psCur->fIntJitter >= i32BigJitter) {
		psAction->eActType = eRATE_CTRL_ACT_DEC_BITRATE;

		if (psCur->fLostPercentage > 50)
			psAction->i32Value = 50;
		else
			psAction->i32Value = (int32_t) psCur->fLostPercentage;

		spook_log(SL_INFO, "MSQosAnalyser: loss rate unacceptable and big jitter. Decreasing video bitrate %d percent.",
				  psAction->i32Value);
	}
	else if (RoundTripPropIncreased(psObj)) {
		psAction->eActType = eRATE_CTRL_ACT_DEC_BITRATE;
		psAction->i32Value = 20;
		spook_log(SL_INFO, "MSQosAnalyser: rt_prop doubled. Decreasing video bitrate %d percent.", psAction->i32Value);
	}
	else if (psCur->fLostPercentage >= fUnacceptableLossRate) {
		/*big loss rate but no jitter, and no big rtp_prop: pure lossy network*/
		psAction->eActType = eRATE_CTRL_ACT_DEC_PACKETRATE;
		spook_log(SL_INFO, "MSQosAnalyser: loss rate unacceptable.");
	}
	else {
		psAction->eActType = eRATE_CTRL_ACT_DO_NOTHING;
		spook_log(SL_INFO, "MSQosAnalyser: everything is fine.");
	}
}