You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bluesky-commits@incubator.apache.org by pi...@apache.org on 2009/11/30 12:01:26 UTC

svn commit: r885392 [22/25] - in /incubator/bluesky/trunk/RealClass: Student/src/ Teacher/ Teacher/autom4te.cache/ Teacher/src/ Teacher/src/.deps/ Teacher/src/pic/

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.cpp?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.cpp (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.cpp Mon Nov 30 12:01:23 2009
@@ -0,0 +1,1145 @@
+/** \file en_de_audio.cpp Implementation for audio operation:capture,encoder,decoder,sender,receiver
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+#include "en_de_audio.h"
+//!CODEC_ID_MP2 for network transmission 
+#define ENCODE_ID CODEC_ID_MP2//CODEC_ID_PCM_S16LE
+//!CODEC_ID_MP3 the codec for the saved file
+#define DECODE_ID CODEC_ID_MP3
+//!maxinum frames to store in the fifo buffer
+#define STATIC_AUDIO_FRAMES 10
+//!maxinum packet size
+#define MAX_PACKET_SIZE 10*1024
+//!maxinum audio packet size
+#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
+
+//!Print the error text
+extern void PErrorText(const char* error);
+
+
+CAEncoder::CAEncoder() :
+	m_soundcard("/dev/dsp")
+{
+
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_bInit = false;
+
+	m_audio_buf = 0;
+	m_fifo = 0;
+
+}
+
+CAEncoder::~CAEncoder()
+{
+	m_bInit = false;
+	CloseAudio();
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+	if (m_audio_buf)
+		free( m_audio_buf);
+
+	if (m_fifo)
+	{
+		fifo_free( m_fifo);
+		free(m_fifo);
+	}
+
+}
+
+void CAEncoder::CloseAudio()
+{
+}
+
+bool CAEncoder::OpenAudio()
+{
+	if (m_soundcard.start_record() < 0)
+	{
+		printf("\nopen audio error.\n");
+		return false;
+	}
+
+	SOUNDPARAMS sp;
+	sp.format = 2;
+
+	sp.channels = 1;
+
+	sp.rate = AUDIO_ENCODE_sample_rate;
+
+	m_soundcard.setparams(&sp);
+
+	printf("\nopen audio success.\n");
+	return true;
+
+}
+
+#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
+bool CAEncoder::Init(enum CodecID nCodecID /*=CODEC_ID_MPEG4*/)
+{
+	m_bInit = false;
+	/*Init for encode*/
+	avienc_init();
+	av_register_all();
+
+	if (!OpenAudio())
+		return false;
+
+	m_pCodec = avcodec_find_encoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("codec not found");
+		return false;
+	}
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+	m_pCodecCtx = avcodec_alloc_context();
+	/* put sample parameters */
+	m_pCodecCtx->codec_id = nCodecID;
+	m_pCodecCtx->codec_type = CODEC_TYPE_AUDIO;
+	m_pCodecCtx->bit_rate = AUDIO_ENCODE_bit_rate;
+	m_pCodecCtx->sample_rate = AUDIO_ENCODE_sample_rate;
+	m_pCodecCtx->channels = 1;
+
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		PErrorText("could not open codec");
+		return false;
+	}
+
+	if (0 == m_audio_buf)
+		m_audio_buf = (uint8_t*) av_malloc(2 * MAX_AUDIO_PACKET_SIZE);
+
+	if (m_fifo == 0)
+	{
+		m_fifo = (FifoBuffer*) malloc(sizeof(FifoBuffer));
+		fifo_init(m_fifo, 10000);
+
+	}
+
+	m_bInit = true;
+	return true;
+}
+
+int CAEncoder::EncodeProcess(uint8_t* data, uint8_t *pOutBuf[2], int nOutsize)
+{
+	int size_out = nOutsize;
+	int loop_times = 0;
+
+	if (!m_bInit)
+		return -1;
+
+	/* now encode as many frames as possible */
+	if (m_pCodecCtx->frame_size > 1)
+	{
+
+		fifo_write(m_fifo, data, nOutsize, &m_fifo->wptr);
+
+		int frame_bytes = m_pCodecCtx->frame_size * 2 * m_pCodecCtx->channels;
+
+		while (fifo_read(m_fifo, m_audio_buf, frame_bytes, &m_fifo->rptr) == 0)
+		{
+
+			m_encode_length[loop_times] = avcodec_encode_audio(m_pCodecCtx,
+					pOutBuf[loop_times], 4 * MAX_AUDIO_PACKET_SIZE,
+					(short *) m_audio_buf);
+			++loop_times;
+
+			if (loop_times >= 2)
+				break;
+
+		}
+	}
+	else
+	{
+
+		switch (m_pCodecCtx->codec->id)
+		{
+		case CODEC_ID_PCM_S16LE:
+		case CODEC_ID_PCM_S16BE:
+		case CODEC_ID_PCM_U16LE:
+		case CODEC_ID_PCM_U16BE:
+			break;
+		default:
+			size_out = size_out >> 1;
+			break;
+		}
+		m_encode_length[0] = avcodec_encode_audio(m_pCodecCtx, pOutBuf[0],
+				size_out, (short *) data);
+		loop_times = 1;
+		printf("now encode here!\n");
+	}
+
+	return loop_times;
+
+}
+
+int CAEncoder::Capture(uint8_t** pOutBuf, int &size)
+{
+	int ret;
+	static uint8_t buf[10000];
+	if (!m_bInit)
+		return -1;
+
+	m_soundcard.sounddata(buf, ret);
+	if (ret > 0)
+	{
+		*pOutBuf = buf;
+		size = ret;
+		return ret;
+	}
+
+	return -1;
+}
+
+// For CADecoder class.
+CADecoder::CADecoder()
+{
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_pSDLBuf = 0;
+	m_bInit = false;
+
+
+
+}
+
+CADecoder::~CADecoder()
+{
+
+	m_bInit = false;
+
+	CloseAudio();
+
+	if (m_pSDLBuf)
+	{
+		free( m_pSDLBuf);
+		m_pSDLBuf = 0;
+	}
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+}
+
+void CADecoder::CloseAudio()
+{
+
+}
+
+bool CADecoder::OpenAudio()
+{
+
+	return true;
+}
+
+bool CADecoder::Init(enum CodecID nCodecID/* = CODEC_ID_MP3*/, int nOutBufSize /*= SDLBufSize*/)
+{
+	m_bInit = false;
+
+	avcodec_init();
+	avcodec_register_all();
+
+	if (!OpenAudio())
+	{
+		printf("\n Open audio device faild!");
+		return false;
+	}
+	//malloc SDLBuf.
+	if (m_pSDLBuf)
+	{
+		free( m_pSDLBuf);
+		m_pSDLBuf = 0;
+	}
+
+	m_pSDLBuf = (uint8_t*) malloc(nOutBufSize * sizeof(uint8_t));
+	if (m_pSDLBuf == 0)
+	{
+		PErrorText("OutBuf malloc failed!");
+		return false;
+	}
+	// find the video decoder
+	m_pCodec = avcodec_find_decoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("Codec not found");
+		return false;
+	}
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+	m_pCodecCtx = avcodec_alloc_context();
+
+	// frames per second
+	m_pCodecCtx->frame_rate = A_DECODE_framerate;
+	m_pCodecCtx->frame_rate_base = A_DECODE_frame_rate_base;
+	// emit one intra frame every ten frames
+	m_pCodecCtx->gop_size = A_DECODE_gop_size;
+	m_pCodecCtx->bit_rate = AUDIO_DECODE_bit_rate;
+	m_pCodecCtx->sample_rate = AUDIO_DECODE_sample_rate;
+	m_pCodecCtx->channels = 1;
+
+	m_pCodecCtx->codec_type = CODEC_TYPE_AUDIO;
+
+	if (m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
+		m_pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
+
+	// open it
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		PErrorText("could not open codec");
+		return false;
+	}
+	m_bInit = true;
+	return true;
+}
+
+int SetFormat(unsigned int fd, unsigned int bits, unsigned int chn,
+		unsigned int hz)
+{
+	int ioctl_val;
+
+	/* set bit format */
+	ioctl_val = bits;
+	if (ioctl(fd, SNDCTL_DSP_SETFMT, &ioctl_val) == -1)
+	{
+		fprintf(stderr, "Set fmt to bit  failed:\n");
+		return (-1);
+	}
+	if (ioctl_val != bits)
+	{
+		fprintf(stderr, "do not support bit  supported \n");
+		return (-1);
+	}
+
+	/*set channel */
+	ioctl_val = chn;
+	if ((ioctl(fd, SNDCTL_DSP_CHANNELS, &ioctl_val)) == -1)
+	{
+		fprintf(stderr, "Set Audio Channels %d failed:\n", chn);
+		return (-1);
+	}
+	if (ioctl_val != chn)
+	{
+		fprintf(stderr, "do not support channel %d,supported\n", chn);
+		return (-1);
+	}
+
+	/*set speed */
+	ioctl_val = hz;
+	if (ioctl(fd, SNDCTL_DSP_SPEED, &ioctl_val) == -1)
+	{
+		fprintf(stderr, "Set speed to %d failed:\n", hz);
+		return (-1);
+	}
+	if (ioctl_val != hz)
+	{
+		fprintf(stderr, "do not support speed %d,supported is\n", hz);
+		return (-1);
+	}
+
+	return (0);
+}
+
+int CADecoder::DecodeProcess(uint8_t *encodeddata_a,
+		const int encodeddatasize_a)
+{
+
+	static JMutex writemutex;
+	int len;
+	int encodedAudioSize;
+	int outAudioBufSize;
+	int kkk;
+
+	if (!m_bInit)
+	{
+		return -1;
+	}
+
+	if (!writemutex.IsInitialized())
+	{
+		if (!writemutex.Init())
+		{
+			PErrorText("\nDecodeProcess: writemutex Init error\n");
+			return -1;
+
+		}
+	}
+
+	encodedAudioSize = encodeddatasize_a;
+	len = 0;
+	kkk = 0;
+	while (encodedAudioSize > 0)
+	{
+		len = avcodec_decode_audio(m_pCodecCtx, (short *) m_pSDLBuf,
+				&outAudioBufSize, encodeddata_a + kkk, encodedAudioSize);
+		if (len < 0)
+		{
+			PErrorText("Error While Decoding Audio");
+			return -2;
+		}
+
+		encodedAudioSize -= len;
+		kkk += len;
+	}
+	static int s_iloops = 0;
+	static char s_chAudioBuf[STATIC_AUDIO_FRAMES * 2 * 4096];
+	static int s_AudioBuflength = 0;
+	memcpy(s_chAudioBuf + s_AudioBuflength, m_pSDLBuf, outAudioBufSize);
+	s_AudioBuflength += outAudioBufSize;
+	s_iloops++;
+
+	if (outAudioBufSize > 0)
+		if (s_iloops >= STATIC_AUDIO_FRAMES)
+		{
+			writemutex.Lock();
+			static int64_t pre, cur, inteval;
+			pre = av_gettime();
+			//write
+			int fd2;
+			fd2 = open("/dev/dsp", O_WRONLY);
+			if (SetFormat(fd2, AFMT_S16_LE, 1, 44100) < 0)
+			{
+				fprintf(stderr, "cannot set............\n");
+				return (-1);
+			}
+			printf("here test 2 %d , %d ........\n", m_pCodecCtx->sample_rate,
+					fd2);
+			write(fd2, s_chAudioBuf, s_AudioBuflength);
+			close(fd2);
+
+			s_iloops = 0;
+			s_AudioBuflength = 0;
+			cur = av_gettime();
+			inteval = (cur - pre);
+
+			writemutex.Unlock();
+		}
+
+	return 0;
+}
+
+//CAudioSender class.
+
+CAudioSender::CAudioSender()
+{
+	stop = false;
+	m_bIsRecord = false;
+	m_bInit = 0;
+	m_sendpause = false;
+
+	m_hFile = 0;
+}
+
+CAudioSender::~CAudioSender()
+{
+	Stop();
+
+	if (m_hFile)
+	{
+		fclose( m_hFile);
+		m_hFile = 0;
+	}
+
+	if (m_pOutBuf[0] != 0)
+		free( m_pOutBuf[0]);
+
+	if (m_pOutBuf[1] != 0)
+		free( m_pOutBuf[1]);
+}
+
+#define MAX_PACKET_SIZE 10*1024
+bool CAudioSender::Init(int nPort)
+{
+	if (m_bInit)
+		return true;
+
+	//init rtpsession.
+	RTPSessionParams sessParams1;
+	sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+	sessParams1.SetUsePollThread(0); //background thread to call virtual callbacks - set by default, but just to be sure
+	sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+	//setup transmission parameters
+	RTPUDPv4TransmissionParams transParams1;
+	transParams1.SetPortbase(nPort);
+	//CREATE THE SESSION
+	int status1 = m_fecrtpsession.Create(sessParams1, &transParams1);
+	if (status1)
+	{
+		return false;
+	}
+	//must set for fec SendFECPacket. 
+	m_fecrtpsession.SetDefaultMark(true);
+	m_fecrtpsession.SetDefaultPayloadType(1);
+	m_fecrtpsession.SetDefaultTimestampIncrement(0);
+
+	for (int i = 0; i <= 1; i++)
+	{
+		if (m_pOutBuf[i] == 0)
+		{
+			m_pOutBuf[i] = (uint8_t*) malloc(CAEncoder::A_OutBufSize);
+			if (m_pOutBuf[i] == 0)
+			{
+				return false;
+			}
+		}
+	}
+
+	//Init vencoder.
+	if (!m_aencoder.Init(ENCODE_ID))
+	{
+		return false;
+	}
+
+	m_bIsRecord = false;
+	m_bInit = true;
+	return m_bInit;
+}
+
+int CAudioSender::Start(char* szFile /* =0 */, bool bIsRecord /* =false */)
+{
+	if (!m_bInit)
+		return -1;
+
+	if (JThread::IsRunning())
+		return 0;
+
+	if (!stopmutex.IsInitialized())
+	{
+		if (stopmutex.Init() < 0)
+			return -2;
+	}
+
+	stop = false;
+
+	if (!m_sendpausemutex.IsInitialized())
+	{
+		if (m_sendpausemutex.Init() < 0)
+			return -2;
+	}
+
+	m_sendpause = false;
+
+	if (!m_recordmutex.IsInitialized())
+	{
+		if (m_recordmutex.Init() < 0)
+			return -2;
+	}
+
+	m_bIsRecord = bIsRecord;
+
+	if (bIsRecord && szFile != 0)
+	{
+		if (m_hFile)
+		{
+			fclose( m_hFile);
+			m_hFile = 0;
+		}
+
+		m_hFile = fopen(szFile, "wb");
+
+		if (m_hFile == 0)
+		{
+			return -3;
+		}
+
+		m_bIsRecord = true;
+	}
+
+	if (JThread::Start() < 0)
+	{
+		m_bIsRecord = false;
+		return -6;
+	}
+
+	return 0;
+}
+
+void CAudioSender::Stop()
+{
+	if (!IsRunning())
+		return;
+
+	stopmutex.Lock();
+	stop = true;
+	stopmutex.Unlock();
+
+	sleep(2);
+	if (JThread::IsRunning())
+	{
+		JThread::Kill();
+	}
+	stop = false;
+
+	//close file.
+	if (m_hFile)
+	{
+		fclose( m_hFile);
+		m_hFile = 0;
+	}
+
+	m_bIsRecord = false;
+}
+
+void CAudioSender::Pause()
+{
+	if (!m_bInit)
+		return;
+	m_sendpausemutex.Lock();
+	m_sendpause = true;
+	m_sendpausemutex.Unlock();
+
+}
+
+void CAudioSender::Resume()
+{
+	if (!m_bInit)
+		return;
+
+	m_sendpausemutex.Lock();
+	m_sendpause = false;
+	m_sendpausemutex.Unlock();
+
+}
+
+void CAudioSender::Record(bool bInRecord /* =true */)
+{
+	if (!m_bInit)
+		return;
+
+	m_recordmutex.Lock();
+	m_bIsRecord = bInRecord;
+	m_recordmutex.Unlock();
+
+}
+
+void *CAudioSender::Thread()
+{
+	uint8_t * data;
+	int datasize;
+	int OutBufSzie;
+	int status;
+	int i = 0;
+
+	JThread::ThreadStarted();
+
+	bool stopthread;
+
+	stopmutex.Lock();
+	stopthread = stop;
+	stopmutex.Unlock();
+
+	bool sendpause;
+
+	m_sendpausemutex.Lock();
+	sendpause = m_sendpause;
+	m_sendpausemutex.Unlock();
+
+	bool isrecord;
+	m_recordmutex.Lock();
+	isrecord = m_bIsRecord;
+	m_recordmutex.Unlock();
+
+	int64_t pre_time, cur_time;
+	useconds_t delay = 0;
+	pre_time = av_gettime();
+	while (!stopthread)
+	{
+
+		cur_time = av_gettime();
+		delay = cur_time - pre_time;
+		if (delay < 20000 * 2)
+		{
+			usleep(20000 * 2 - delay);
+
+		}
+		pre_time = av_gettime();
+
+		if ((status = m_aencoder.Capture(&data, datasize)) < 0)
+		{
+			printf("\naudio capture failed");
+			stopthread = true;
+		}
+		else
+		{
+			if (datasize <= 0)
+				continue;
+			OutBufSzie = datasize;
+			if ((status = m_aencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie))
+					< 0)
+			{
+				printf("\naudio EncodeProcess failed");
+				stopthread = true;
+			}
+			else
+			{
+				if (status > 0)
+				{
+
+					if (!sendpause)
+					{
+						static int s_iTemp = 0;
+						s_iTemp++;
+
+						for (i = 0; i < status; i++)
+						{
+
+							static char temp_buf[1000];
+							int *temp_p = (int *) temp_buf;
+							*temp_p = s_iTemp;
+							memcpy(temp_buf + sizeof(int), m_pOutBuf[i],
+									m_aencoder.encodelength(i));
+							m_fecrtpsession.SendPacket(temp_buf,
+									m_aencoder.encodelength(i) + sizeof(int));
+							if (m_hFile != 0 && isrecord)
+							{
+
+								fwrite(m_pOutBuf[i],
+										m_aencoder.encodelength(i), 1, m_hFile);
+							}
+						}
+					}
+				}
+
+				m_recordmutex.Lock();
+				isrecord = m_bIsRecord;
+				m_recordmutex.Unlock();
+
+				m_sendpausemutex.Lock();
+				sendpause = m_sendpause;
+				m_sendpausemutex.Unlock();
+
+				stopmutex.Lock();
+				stopthread = stop;
+				stopmutex.Unlock();
+			}
+		}
+
+	}
+	printf("\naudio thread stop normally.");
+	return 0;
+}
+
+bool CAudioSender::AddDestination(const RTPIPv4Address &des)
+{
+	if (!m_bInit)
+		return false;
+	if (m_fecrtpsession.AddDestination(des) < 0)
+		return false;
+
+	return true;
+}
+
+void CAudioSender::ClearDestinations()
+{
+	if (!m_bInit)
+		return;
+	m_fecrtpsession.ClearDestinations();
+}
+
+
+//CAudioReceiver class.
+
+CAudioReceiver::CAudioReceiver()
+{
+	m_bInit = false;
+}
+
+CAudioReceiver::~CAudioReceiver()
+{
+
+}
+
+bool CAudioReceiver::Init()
+{
+	if (m_bInit)
+		return m_bInit;
+
+	//init video decoder.
+	if (!m_adecoder.Init(DECODE_ID))
+	{
+		return false;
+	}
+
+	m_bInit = true;
+	return m_bInit;
+
+}
+
+int CAudioReceiver::Start(int nPort)
+{
+	if (!m_bInit)
+		return -1;
+
+	if (IsActive())
+		return 0;
+
+	//init rtpsession.
+	RTPSessionParams sessParams1;
+	sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+	sessParams1.SetUsePollThread(1); //background thread to call virtual callbacks - set by default, but just to be sure
+	sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+	//setup transmission parameters
+	RTPUDPv4TransmissionParams transParams1;
+	transParams1.SetPortbase(nPort);
+	//CREATE THE SESSION
+	int status1 = Create(sessParams1, &transParams1);
+	if (status1)
+	{
+		return -2; //unable to create the session
+	}
+
+	return 0;
+}
+
+void CAudioReceiver::Stop()
+{
+	Destroy();
+}
+
+void CAudioReceiver::OnRTPPacket(RTPPacket *pack, const RTPTime &receivetime,
+		const RTPAddress *senderaddress)
+{
+	int *iTemp = 0;
+	iTemp = (int *) pack->GetPayloadData();
+	printf("now  receive audio sequen is %d\n", *iTemp);
+
+	m_adecoder.DecodeProcess(pack->GetPayloadData() + sizeof(int),
+			pack->GetPayloadLength() - sizeof(int));
+
+}
+
+
+
+/* ---------------------------------------------------------------------- */
+
+Soundcard::Soundcard(const char *dev)
+{
+	if (dev)
+		strcpy(devname, dev);
+	else
+		strcpy(devname, "/dev/dsp");
+
+	driver_name[0] = '\0';
+
+	stat = STATUS_CLOSED;
+	get_capabilities();
+	channels = 1;
+	rate = 22050;
+	fd = -1;
+}
+
+Soundcard::~Soundcard()
+{
+	/* nothing */
+	close_dev();
+}
+
+int Soundcard::start_record()
+{
+	switch (stat)
+	{
+	case STATUS_CLOSED:
+		if (!init_done)
+			get_capabilities();
+		if (!init_done)
+			return -1;
+		return open_dev(TRUE);
+	case STATUS_RECORD:
+		return 0;
+	case STATUS_PLAYBACK:
+		close_dev();
+		return open_dev(TRUE);
+	}
+	return -1;
+}
+
+int Soundcard::start_playback()
+{
+	switch (stat)
+	{
+	case STATUS_CLOSED:
+		if (!init_done)
+			get_capabilities();
+		if (!init_done)
+			return -1;
+		return open_dev(FALSE);
+	case STATUS_RECORD:
+		close_dev();
+		return open_dev(FALSE);
+	case STATUS_PLAYBACK:
+		return 0;
+	}
+	return -1;
+}
+
+void Soundcard::get_capabilities()
+{
+	int i, dsp;
+	int try_afmt;
+	int try_channels;
+
+	afmt = 0;
+	if (-1 != (dsp = open(devname, O_RDONLY)))
+	{
+
+		ioctl(dsp, SNDCTL_DSP_SETFMT, &afmt); /* current */
+		ioctl(dsp, SNDCTL_DSP_GETFMTS, &afmt_hw); /* hardware cap */
+		afmt_sw = 0;
+
+		for (i = 0; i < 16; i++)
+		{
+			try_afmt = (1 << i);
+			if (-1 == ioctl(dsp, SNDCTL_DSP_SETFMT, &try_afmt))
+				continue;
+			if (try_afmt != (1 << i))
+				continue;
+			afmt_sw |= try_afmt;
+		}
+
+		try_channels = 2;
+		if (-1 != ioctl(dsp, SNDCTL_DSP_CHANNELS, &try_channels) && 2
+				== try_channels)
+			channels_hw = 2;
+		else
+			channels_hw = 1;
+
+		close(dsp);
+		init_done = 1;
+
+	}
+	else
+	{
+		init_done = 0;
+	}
+}
+
+int Soundcard::open_dev(int record)
+{
+	struct SOUNDPARAMS p;
+	int frag, rrate;
+
+	if (-1 == (fd = open(devname, record ? O_RDONLY : O_WRONLY)))
+		goto err;
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+	/* try to get ~50 ms latency */
+	blocksize = 50 * channels * rate / 1000;
+	if (afmt == AFMT_U16_BE || afmt == AFMT_S16_BE || afmt == AFMT_U16_LE
+			|| afmt == AFMT_S16_LE)
+		blocksize *= 2;
+	for (frag = 0; blocksize != 1; frag++)
+		blocksize >>= 1;
+#if 0
+	fprintf(stderr,"asking for %d byte blocksize\n",1 << frag);
+#endif
+	frag |= 0x7fff0000;
+	if (-1 == ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag))
+		perror("ioctl SNDCTL_DSP_SETFRAGMENT");
+
+	rrate = rate;
+	if (-1 == ioctl(fd, SNDCTL_DSP_SETFMT, &afmt))
+	{
+		perror("ioctl SNDCTL_DSP_SETFMT");
+		goto err;
+	}
+	if (-1 == ioctl(fd, SNDCTL_DSP_CHANNELS, &channels))
+	{
+		perror("ioctl SNDCTL_DSP_SETFMT");
+		goto err;
+	}
+	if (-1 == ioctl(fd, SNDCTL_DSP_SPEED, &rrate))
+	{
+		perror("ioctl SNDCTL_DSP_SETFMT");
+		goto err;
+	}
+	if (-1 == ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blocksize))
+	{
+		perror("ioctl SNDCTL_DSP_SETFMT");
+		goto err;
+	}
+	if (0 == blocksize)
+		blocksize = 4096;
+	if (rrate != rate)
+	{
+		fprintf(stderr, "sample rate: asked for %d, hardware uses %d. ", rate,
+				rrate);
+		if (abs(rate - rrate) * 100 < rate)
+		{
+			fprintf(stderr, "that's fine (diff <1%%).\n");
+		}
+		else
+		{
+			fprintf(stderr, "way off, using hardware rate.\n");
+			rate = rrate;
+		}
+	}
+
+	latency = blocksize * 1000 / channels / rate;
+	if (afmt == AFMT_U16_BE || afmt == AFMT_S16_BE || afmt == AFMT_U16_LE
+			|| afmt == AFMT_S16_LE)
+		latency = latency / 2;
+
+	stat = record ? STATUS_RECORD : STATUS_PLAYBACK;
+#if 0
+	fprintf(stderr,"%s (format=%d, %s, rate=%d, blocksize=%d, latency=%d ms)\n",
+			record ? "recording" : "playback",
+			afmt,
+			(channels == 2) ? "stereo" : "mono",
+			rate, blocksize, latency);
+#endif
+	p.channels = channels;
+	p.rate = rate;
+	p.blocksize = blocksize;
+	p.latency = latency;
+	switch (afmt)
+	{
+	case AFMT_U8:
+		p.format = FMT_8BIT;
+		break;
+	case AFMT_S16_LE:
+		p.format = FMT_16BIT;
+		break;
+	default:
+		fprintf(stderr, "oops(open): unsupported sound format\n");
+		exit(1);
+	}
+
+	if (record)
+	{
+		trigger = ~PCM_ENABLE_INPUT;
+		ioctl(fd, SNDCTL_DSP_SETTRIGGER, &trigger);
+		trigger = PCM_ENABLE_INPUT;
+		ioctl(fd, SNDCTL_DSP_SETTRIGGER, &trigger);
+	}
+	return 0;
+
+	err: if (-1 != fd)
+		close( fd);
+	stat = STATUS_CLOSED;
+	fd = -1;
+	return -1;
+}
+
+void Soundcard::close_dev()
+{
+	close( fd);
+	fd = -1;
+	stat = STATUS_CLOSED;
+
+	return;
+}
+
+void Soundcard::setparams(struct SOUNDPARAMS *p)
+{
+	rate = p->rate;
+	channels = p->channels;
+	switch (p->format)
+	{
+	case FMT_8BIT:
+		afmt = AFMT_U8;
+		break;
+	case FMT_16BIT:
+		afmt = AFMT_S16_LE;
+		break;
+	default:
+		fprintf(stderr, "oops(set): unsupported sound format\n");
+		exit(1);
+	}
+
+	switch (stat)
+	{
+	case STATUS_RECORD:
+		close_dev();
+		open_dev( TRUE);
+		break;
+	case STATUS_PLAYBACK:
+		close_dev();
+		open_dev( FALSE);
+		break;
+	case STATUS_CLOSED:
+		if (!init_done)
+			get_capabilities();
+		if (!init_done)
+			return;
+		if (0 == open_dev(TRUE))
+			close_dev();
+		break;
+	}
+	printf("\nchannels=%d\n", channels);
+	printf("\nrate=%d\n", rate);
+	printf("\nblocksize=%d\n", blocksize);
+	printf("\nlatency=%d\n", latency);
+
+}
+
+void
+//Soundcard::sounddata(int s)
+Soundcard::sounddata(uint8_t* buf, int &size)
+{
+	int rc, have;
+
+	switch (stat)
+	{
+	case STATUS_RECORD:
+		/* read */
+		for (have = 0; have < blocksize;)
+		{
+			rc = read(fd, buf + have, blocksize - have);
+			switch (rc)
+			{
+			case -1:
+			{
+				printf("\naudio capture failed\n");
+				size = -1;
+				return;
+			}
+				break;
+			case 0:
+				fprintf(stderr, "Huh? got 0 bytes from sound device?\n");
+				exit(1);
+			default:
+				have += rc;
+			}
+		}
+		size = have;
+		break;
+	case STATUS_PLAYBACK:
+		if (-1 != fd)
+			write(fd, buffer, blocksize);
+		break;
+	}
+}
+

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.h
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.h?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.h (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_audio.h Mon Nov 30 12:01:23 2009
@@ -0,0 +1,318 @@
+/** \file en_de_audio.h Classes for audio operation:capture,encoder,decoder,sender,receiver
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+
+#include "fecrtpsession.h"
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <time.h>
+// FFmpeg
+#include <ffmpeg/avcodec.h>
+#include <ffmpeg/avformat.h>
+// X11
+#include <X11/Intrinsic.h>
+#include <X11/XWDFile.h>
+
+// Jthread and JMutex
+#include <jthread.h>
+#include <jmutex.h>
+
+// Audio
+#include <linux/soundcard.h>
+
+#define STATUS_CLOSED    0
+#define STATUS_RECORD    1
+#define STATUS_PLAYBACK  2
+
+#define FMT_UNDEFINED  0
+#define FMT_8BIT       1          /* unsigned */
+#define FMT_16BIT      2          /* signed - native byte order */
+#define FMT_MULAW      4          /* NOT SUPPORTED (yet) */
+#define FMT_ALAW       8          /* NOT SUPPORTED (yet) */
+
+#define FMT_MAX        2
+//!sound card params
+struct SOUNDPARAMS
+{
+	int format;
+	int channels;
+	int rate;
+	int blocksize;
+	int latency;
+};
+//!sound card operation
+class Soundcard
+{
+
+public:
+	/* sound card capabilities */
+	char devname[32];
+	int init_done;
+	int afmt_hw;
+	int afmt_sw;
+	int channels_hw;
+
+	int trigger;
+	char driver_name[64];
+
+	/* current settings */
+	int afmt;
+	int channels;
+	int rate;
+	int blocksize;
+	int latency;
+
+	//!file handle
+	int fd;
+	//!reference count
+	int stat;
+	char buffer[65536];
+
+	/* internal functions */
+	//!get capabilities
+	void get_capabilities();
+	//!open device
+	int open_dev(int record);
+	//close device
+	void close_dev();
+
+public: 
+	//!constructor
+	Soundcard(const char *dev);
+	//!Destructor
+	~Soundcard();
+	//!set sound card param
+	void setparams(struct SOUNDPARAMS *params);
+	//!start record
+	int start_record();
+	// strat playback
+	int start_playback();
+
+public:
+	//!set sound data
+	void sounddata(uint8_t* buf, int &size);
+
+};
+
+#if !defined(_EN_DE_AUDIO_H__INCLUDED_)
+#define _EN_DE_AUDIO_H__INCLUDED_
+
+//!Audio decoder class.
+class CADecoder
+{
+public:
+	//!constructor
+	CADecoder();
+	//!Destructor
+	virtual ~CADecoder();
+	//!Decode a frame
+	/*!
+	\param encodeddata_a the pointer to data
+	\param encodeddatasize_a data size
+	*/
+	int DecodeProcess(uint8_t *encodeddata_a, const int encodeddatasize_a);
+	//!Initialize
+	/*!
+	\param nCodecID the specific CODEC_ID, use CODEC_ID_MP3
+	\param nOutBufSize the decoded data buffer size
+	*/
+	bool Init(enum CodecID nCodecID = CODEC_ID_MP3, int nOutBufSize =
+			A_SDLBufSize);
+private:
+	enum ADECODERBUFSIZE
+	{
+		A_SDLBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE
+	};
+	//!Param for the ENCODEC
+	enum AUDIO_DECODEC_PARA
+	{
+		AUDIO_DECODE_bit_rate = 64000,
+		AUDIO_DECODE_sample_rate = 44100,
+		A_DECODE_framerate = 25,
+		A_DECODE_frame_rate_base = 1,
+		A_DECODE_gop_size = 12
+	};
+
+	//!Bool variable to mark the initiallise
+	bool m_bInit;
+	//!AVCodec Instance to store the codec
+	AVCodec *m_pCodec;
+	//!AVCodecContext Instance to store the codec content
+	AVCodecContext *m_pCodecCtx;
+	//!Buffer to store the decoded data
+	uint8_t *m_pSDLBuf;
+
+	//!open audio device
+	bool OpenAudio();
+	//!close audio device
+	void CloseAudio();
+};
+
+//!Audio Encoder class 
+class CAEncoder
+{
+	friend class CAudioSender;
+public:
+	//!Constructor
+	CAEncoder();
+	//!Virtual Donstructor
+	virtual ~CAEncoder();
+	//!capture data
+	int Capture(uint8_t** pOutBuf, int &size);
+	//!Encode a frame
+	/*!
+	\param data the pointer to captured data
+	\param pOutBuf the buffer to store encoded data
+	\param nOutsize the encoded data size
+	*/
+	int EncodeProcess(uint8_t* data, uint8_t *pOutBuf[2], int nOutsize);
+	//!Initialize
+	/*!
+	\param nCodecID the specific CODEC_ID, use CODEC_ID_MP3
+	*/
+	bool Init(enum CodecID nCodecID = CODEC_ID_MP2);
+	//!Get the encoded data length
+	inline int encodelength(int i)
+	{
+		return m_encode_length[i];
+	}
+	//!Soundcard Instance
+	Soundcard m_soundcard;
+	//!Buffer for encode
+	uint8_t* m_audio_buf;
+	//!FifoBuffer to read the audio data to encode
+	FifoBuffer *m_fifo;
+ 
+private:
+	//!open audio device
+	bool OpenAudio();
+	//!close audio device
+	void CloseAudio();
+	enum AUDIO_ENCODEC_PARA
+	{
+		AUDIO_ENCODE_bit_rate = 64000,
+		AUDIO_ENCODE_sample_rate = 44100,
+		A_ENCODE_framerate = 25,
+		A_ENCODE_frame_rate_base = 1,
+		A_ENCODE_gop_size = 12
+	};
+	//!Define encode buffer size
+	enum AENCODERBUFSIZE
+	{
+		A_OutBufSize = 4 * 128 * 1024
+	};//128000
+
+	//!Bool variable to mark the initiallise
+	bool m_bInit;
+	//!AVCodec Instance to store the codec
+	AVCodec *m_pCodec;
+	//!AVCodecContext Instance to store the codec content
+	AVCodecContext *m_pCodecCtx;
+	//!To store Encoded data
+	int m_encode_length[2];
+
+};
+
+class CAudioSender: private JThread
+{
+public:
+	//!Constructor
+	CAudioSender();
+	//!Destructor
+	~CAudioSender();
+	//!Initialise 
+	bool Init(int nPort);
+	//!Add Destination 
+	bool AddDestination(const RTPIPv4Address &des);
+	//!Clear Destinations
+	void ClearDestinations();
+	int Start(char* szFile = 0, bool bIsRecord = false);
+	//!Pause to send
+	void Pause();
+	//!Resume to send
+	void Resume();
+	//!record
+	void Record(bool bInRecord = true);
+	//!stop sender thread
+	void Stop();
+
+private:
+	//!sender thread
+	void *Thread();
+	//!thread stop status
+	bool stop;
+	//!mutex for the thread stop
+	JMutex stopmutex;
+private:
+	//!CAEncoder Instance
+	CAEncoder m_aencoder;
+	//!store the data
+	uint8_t *m_pOutBuf[2]; //only record endcode data 2 times
+	//!RTPSession Instance
+	RTPSession m_fecrtpsession;
+	//!mark the init status
+	int m_bInit;
+	//!mark pause status
+	bool m_sendpause;
+	//!mutex for send pause
+	JMutex m_sendpausemutex;
+ 	//!record status
+	bool m_bIsRecord;
+	//!mutex for record
+	JMutex m_recordmutex;
+	//!file for recored data
+	FILE* m_hFile;
+};
+
+//!Audio Receiver class
+class CAudioReceiver: public RTPSession
+{
+public:
+	//!Constructor
+	CAudioReceiver();
+	//!Virtual Destructor
+	virtual ~CAudioReceiver();
+	//!Initialize
+	bool Init();
+	//!Start Receive audio data
+	int Start(int nPort);
+	//!Stop receive audio data
+	void Stop();
+
+private:
+	//!Deal with the RTPPacket
+	virtual void OnRTPPacket(RTPPacket *pack, const RTPTime &receivetime,
+			const RTPAddress *senderaddress);
+
+private:
+	//!mark the init status
+	bool m_bInit;
+	CADecoder m_adecoder;
+};
+
+#endif // !defined(_EN_DE_AUDIO_H__INCLUDED_)

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.cpp?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.cpp (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.cpp Mon Nov 30 12:01:23 2009
@@ -0,0 +1,1412 @@
+/** \file en_de_screen.cpp Implementation for screen operation:capture,encoder,decoder,sender,receiver
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+#include "en_de_screen.h"
+
+extern int delay_time;
+
+extern void PErrorText(const char* error);
+//CSEncoder class.
+
+CSEncoder::CSEncoder()
+{
+	m_pFrameBuf = 0;
+	m_pFrame = 0;
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_bInit = false;
+	m_bInitScreen = false;
+
+	m_image = 0;
+	m_display = 0;
+	m_d = 0;
+	m_width = 0;
+	m_height = 0;
+	m_screen_num = 0;
+
+}
+
+CSEncoder::~CSEncoder()
+{
+	m_bInitScreen = false;
+	m_bInit = false;
+
+	if (m_pFrameBuf)
+	{
+		free( m_pFrameBuf);
+		m_pFrameBuf = 0;
+	}
+
+	if (m_pFrame)
+	{
+		free( m_pFrame);
+		m_pFrame = 0;
+	}
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+	if (m_image)
+	{
+		XDestroyImage( m_image);
+		m_image = 0;
+	}
+
+	if (m_display)
+	{
+		if (m_d)
+		{
+			XClearWindow(m_display, m_d);
+			m_d = 0;
+		}
+
+		XCloseDisplay( m_display);
+		m_display = 0;
+	}
+
+}
+
+bool CSEncoder::Init(enum CodecID nCodecID /*=CODEC_ID_MPEG4*/)
+{
+	m_bInit = false;
+	/*Init for encode*/
+	avcodec_init();
+	avcodec_register_all();
+
+	if (!InitScreen(S_CODEC_width, S_CODEC_height))
+		return false;
+
+	if (m_pFrame)
+	{
+		free( m_pFrame);
+		m_pFrame = 0;
+	}
+	m_pFrame = avcodec_alloc_frame();
+
+	/* find the mpeg4 video encoder */
+	m_pCodec = avcodec_find_encoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("codec not found\n");
+		return false;
+	}
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+	m_pCodecCtx = avcodec_alloc_context();
+	/* resolution must be a multiple of two */
+	m_pCodecCtx->width = m_width;
+	m_pCodecCtx->height = m_height;
+	/* frames per second */
+	m_pCodecCtx->frame_rate = S_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = S_CODEC_frame_rate_base;
+	m_pCodecCtx->gop_size = S_CODEC_gop_size; /* emit one intra frame every ten frames */
+
+	m_pCodecCtx->bit_rate = 512 * 1024;
+	m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+	m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+
+	/* open it */
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		fprintf(stderr, "could not open codec\n");
+		return false;
+	}
+
+	if (m_pFrameBuf)
+	{
+		free( m_pFrameBuf);
+		m_pFrameBuf = 0;
+	}
+
+	int image_size = avpicture_get_size(PIX_FMT_YUV420P, m_pCodecCtx->width,
+			m_pCodecCtx->height);
+
+	m_pFrameBuf = (uint8_t*) malloc(image_size);
+	if (m_pFrameBuf == 0)
+	{
+		PErrorText("FrameBuf malloc failed!");
+		return false;
+	}
+	/*Init for encode*/
+
+	avpicture_fill((AVPicture*) m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P,
+			m_pCodecCtx->width, m_pCodecCtx->height);
+	m_pFrame->type = FF_BUFFER_TYPE_SHARED;
+
+	m_bInit = true;
+	return true;
+}
+
+int CSEncoder::EncodeProcess(XImage *image, uint8_t *pOutBuf, int nOutsize)
+{
+
+	if (!m_bInit)
+		return -1;
+
+	if (nOutsize < S_En_OutBufSize)
+	{
+		return -2;
+	}
+
+	int k, j;
+	unsigned long r32, g32, b32, color32;
+
+	for (k = 0; k < m_pCodecCtx->height; k++)
+	{
+		for (j = 0; j < m_pCodecCtx->width; j++)
+		{
+			color32 = *((unsigned long*) (image->data + k * m_pCodecCtx->width
+					* 4 + j * 4));
+			r32 = color32 & (image->red_mask);
+			g32 = color32 & (image->green_mask);
+			b32 = color32 & (image->blue_mask);
+			r32 = ((r32 >> 16) & 255) << 16;
+			g32 = ((g32 >> 8) & 255) << 8;
+			b32 = ((b32) & 255);
+			color32 = r32 | g32 | b32;
+			color32 = color32 & 16777215;
+			*((unsigned long*) (image->data + k * m_pCodecCtx->width * 4 + j
+					* 4)) = color32;
+		}
+	}
+	GetColorInfo(image, &c_info);
+	switch (image->bits_per_pixel)
+	{
+	case 8:
+		input_pixfmt = PIX_FMT_PAL8;
+		break;
+	case 16:
+		if (image->red_mask == 0xF800 && image->green_mask == 0x07E0
+				&& image->blue_mask == 0x1F)
+		{
+			input_pixfmt = PIX_FMT_RGB565;
+		}
+		else if (image->red_mask == 0x7C00 && image->green_mask == 0x03E0
+				&& image->blue_mask == 0x1F)
+		{
+			input_pixfmt = PIX_FMT_RGB555;
+		}
+		else
+		{
+			fprintf(
+					stderr,
+					"xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth %i not supported ... aborting\n",
+					image->bits_per_pixel);
+			fprintf(
+					stderr,
+					"xtoffmpeg.XImageToFFMPEG(): color masks: r 0x%.6lX g 0x%.6lX b 0x%.6lX\n",
+					image->red_mask, image->green_mask, image->blue_mask);
+		}
+		break;
+	case 24:
+		if (image->red_mask == 0xFF0000 && image->green_mask == 0xFF00
+				&& image->blue_mask == 0xFF)
+		{
+			input_pixfmt = PIX_FMT_BGR24;
+		}
+		else if (image->red_mask == 0xFF && image->green_mask == 0xFF00
+				&& image->blue_mask == 0xFF0000)
+		{
+			input_pixfmt = PIX_FMT_RGB24;
+		}
+		else
+		{
+			PErrorText(
+					"xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth not supported ... aborting\n");
+			PErrorText("xtoffmpeg.XImageToFFMPEG()");
+			return false;
+		}
+		break;
+	case 32:
+		if (c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00)
+		{
+			input_pixfmt = PIX_FMT_RGBA32;
+		}
+		else
+		{
+			PErrorText(
+					"xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting");
+			return false;
+		}
+		break;
+	default:
+		PErrorText(
+				"xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting");
+		return false;
+	}
+
+	avpicture_fill(&m_pic_rgb, (uint8_t *) image->data, input_pixfmt,
+			m_pCodecCtx->width, m_pCodecCtx->height);
+	avpicture_fill((AVPicture*) m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P,
+			m_pCodecCtx->width, m_pCodecCtx->height);
+
+	if (img_convert((AVPicture*) m_pFrame, PIX_FMT_YUV420P, &m_pic_rgb,
+			input_pixfmt, m_pCodecCtx->width, m_pCodecCtx->height) < 0)
+	{
+		PErrorText(
+				"xtoffmpeg.XImageToFFMPEG(): pixel format conversion not handled ... aborting");
+		return -2;
+	}
+
+	m_ScreenHeader.width = m_width;
+	m_ScreenHeader.height = m_height;
+	memcpy((char *) pOutBuf, &m_ScreenHeader, sizeof(ScreenHeader));
+
+	int ret;
+	ret = avcodec_encode_video(m_pCodecCtx, pOutBuf + sizeof(ScreenHeader),
+			nOutsize, m_pFrame);
+
+	if (ret <= 0)
+		return ret;
+
+	return ret + sizeof(ScreenHeader);
+
+}
+
+bool CSEncoder::InitScreen(int width, int height)
+{
+	if (m_bInitScreen)
+		return true;
+	m_display = XOpenDisplay(NULL);
+
+	m_width = width;
+	m_height = height;
+	m_screen_num = DefaultScreen(m_display);
+
+	m_d = RootWindow(m_display, m_screen_num);
+
+	XWindowAttributes win_attr;
+
+	if (!XGetWindowAttributes(m_display, m_d, &win_attr))
+
+		perror("Can't get window attributes!\n");
+
+	m_image = 0;
+	m_bInitScreen = true;
+	return true;
+}
+
+bool CSEncoder::GetScreenSize(int &width, int &height)
+{
+	if (!m_bInit)
+		return false;
+
+	width = m_pCodecCtx->width;
+	height = m_pCodecCtx->height;
+
+	return true;
+}
+
+//Mouse capture.
+uint16_t mousePointerBlack[] =
+{ 0, 49152, 40960, 36864, 34816, 33792, 33280, 33024, 32896, 32832, 33728,
+		37376, 43264, 51456, 1152, 1152, 576, 576, 448, 0 };
+uint16_t mousePointerWhite[] =
+{ 0, 0, 16384, 24576, 28672, 30720, 31744, 32256, 32512, 32640, 31744, 27648,
+		17920, 1536, 768, 768, 384, 384, 0, 0 };
+
+void CSEncoder::getCurrentPointer(int *x, int *y)
+{
+	Window mrootwindow, childwindow;
+	int dummy;
+
+	if (!m_bInit)
+		return;
+
+	mrootwindow = DefaultRootWindow(m_display);
+
+	if (XQueryPointer(m_display, mrootwindow, &mrootwindow, &childwindow, x, y,
+			&dummy, &dummy, (unsigned int *) &dummy))
+	{
+
+	}
+	else
+	{
+		*x = -1;
+		*y = -1;
+	}
+
+	XClearWindow(m_display, mrootwindow);
+}
+
+void CSEncoder::paintMousePointer(int *x, int *y, XImage *image)
+{
+	// only paint a mouse pointer into the dummy frame if the position of the mouse
+	// is within the rectangle defined by the capture frame
+
+	if (*x >= 0 && *x < S_CODEC_width - 25 && //25 is width and height of cursor .
+			*y >= 0 && *y < S_CODEC_height - 25)
+	{
+		int line;
+		uint8_t *im_data = (uint8_t *) image->data;
+
+		// move the cursor to the right starting position
+		im_data += (image->bytes_per_line * (*y)); // shift to right line
+		im_data += (image->bits_per_pixel / 8 * (*x)); // shift to right pixel
+
+		uint32_t *cursor;
+		int width;
+		uint16_t bm_b, bm_w, mask;
+
+		// the dummy mouse pointer is 20 pixels high ...
+		for (line = 0; line < 20; line++)
+		{
+			bm_b = mousePointerBlack[line];
+			bm_w = mousePointerWhite[line];
+
+			mask = (0x0001 << 15);
+
+			// ... and 16 pixels wide
+			for (cursor = (uint32_t*) im_data, width = 0; ((width + *x)
+					< S_CODEC_width && width < 16); cursor++, width++)
+			{
+				if ((bm_b & mask) > 0)
+				{
+					*cursor &= ((~image->red_mask) & (~image->green_mask)
+							& (~image->blue_mask));
+				}
+				else if ((bm_w & mask) > 0)
+				{
+					*cursor |= (image->red_mask | image->green_mask
+							| image->blue_mask);
+				}
+				mask >>= 1;
+			}
+			im_data += image->bytes_per_line;
+		}
+
+	}
+}
+
+//Mouse capture.
+
+bool CSEncoder::Capture(XImage **image)
+{
+	int x, y;
+	if (!m_bInitScreen)
+		return false;
+
+	if (m_image)
+	{
+		m_image->f.destroy_image(m_image);
+		m_image = 0;
+	}
+	getCurrentPointer(&x, &y);
+	m_image = XGetImage(m_display, m_d, 0, 0, m_width, m_height, AllPlanes,
+			ZPixmap);
+
+	if (m_image == 0)
+	{
+		PErrorText("GetImage error");
+		return false;
+	}
+	paintMousePointer(&x, &y, m_image);
+
+	*image = m_image;
+	return true;
+}
+
+void CSEncoder::GetColorInfo(XImage *image, ColorInfo *ci /* return struct */)
+{
+	unsigned long red_mask, green_mask, blue_mask, alpha_mask;
+	// the shifts are unsigned longs as well
+
+	if (!ci)
+		return;
+
+	// setting shifts and bit_depths to zero
+	ci->red_shift = ci->green_shift = ci->blue_shift = ci->alpha_shift = 0;
+	ci->red_bit_depth = ci->green_bit_depth = ci->blue_bit_depth
+			= ci->alpha_bit_depth = 0;
+
+	red_mask = image->red_mask;
+	if (red_mask > 0)
+	{
+		// shift red_mask to the right till all empty bits have been
+		// shifted out and count how many they were
+		while ((red_mask & 0x01) == 0)
+		{
+			red_mask >>= 1;
+			ci->red_shift++;
+		}
+		// count how many bits are set in the mask = depth
+		while ((red_mask & 0x01) == 1)
+		{
+			red_mask >>= 1;
+			ci->red_bit_depth++;
+		}
+	}
+
+	ci->red_max_val = (1 << ci->red_bit_depth) - 1;
+
+	green_mask = image->green_mask;
+	if (green_mask > 0)
+	{
+		while ((green_mask & 0x01) == 0)
+		{
+			green_mask >>= 1;
+			ci->green_shift++;
+		}
+		while ((green_mask & 0x01) == 1)
+		{
+			green_mask >>= 1;
+			ci->green_bit_depth++;
+		}
+	}
+	ci->green_max_val = (1 << ci->green_bit_depth) - 1;
+
+	blue_mask = image->blue_mask;
+	if (blue_mask > 0)
+	{
+		while ((blue_mask & 0x01) == 0)
+		{
+			blue_mask >>= 1;
+			ci->blue_shift++;
+		}
+		while ((blue_mask & 0x01) == 1)
+		{
+			blue_mask >>= 1;
+			ci->blue_bit_depth++;
+		}
+	}
+	ci->blue_max_val = (1 << ci->blue_bit_depth) - 1;
+
+	ci->max_val = max(ci->red_max_val, ci->green_max_val);
+	ci->max_val = max(ci->blue_max_val, ci->max_val);
+	ci->bit_depth = max(ci->red_bit_depth, ci->green_bit_depth);
+	ci->bit_depth = max(ci->blue_bit_depth, ci->bit_depth);
+	if (image->bits_per_pixel > image->depth)
+	{
+
+		ci->alpha_mask = ~(image->red_mask | image->blue_mask
+				| image->green_mask);
+		alpha_mask = ci->alpha_mask;
+		if (alpha_mask > 0)
+		{
+			while ((alpha_mask & 0x01) == 0)
+			{
+				alpha_mask >>= 1;
+				ci->alpha_shift++;
+			}
+			while ((alpha_mask & 0x01) == 1)
+			{
+				alpha_mask >>= 1;
+				ci->alpha_bit_depth++;
+			}
+		}
+		ci->alpha_max_val = (1 << ci->alpha_bit_depth) - 1;
+	}
+}
+//CSDecoder class.
+CSDecoder::CSDecoder()
+{
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_pOutFrame = 0;
+	m_bInit = false;
+	m_display = 0;
+	m_win = 0;
+	m_d = 0;
+	m_image = 0;
+	m_parent = 0;
+
+	m_width = 0;
+	m_height = 0;
+
+}
+
+CSDecoder::~CSDecoder()
+{
+	m_bInit = false;
+
+	if (m_image)
+	{
+		XDestroyImage( m_image);
+		m_image = 0;
+	}
+
+	if (m_display)
+	{
+		if (m_win)
+		{
+			XClearWindow(m_display, m_win);
+			m_win = 0;
+		}
+		if (m_d)
+		{
+			XClearWindow(m_display, m_d);
+			m_d = 0;
+		}
+
+		XCloseDisplay( m_display);
+		m_display = 0;
+	}
+
+	if (m_pOutFrame)
+	{
+		free( m_pOutFrame);
+		m_pOutFrame = 0;
+	}
+	if (m_pCodecCtx)
+	{
+		if (m_pCodecCtx->extradata)
+		{
+			free(m_pCodecCtx->extradata);
+			m_pCodecCtx->extradata = 0;
+			m_pCodecCtx->extradata_size = 0;
+		}
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+}
+
+bool CSDecoder::CreateXImage(Drawable parent, int x, int y, int width,
+		int height)
+{
+	int screen_num;
+
+	if (!m_bInit)
+		return false;
+
+	CloseXImage();
+
+	m_imagemutex.Lock();
+
+	m_display = XOpenDisplay(NULL);
+	screen_num = DefaultScreen(m_display);
+
+	m_win = XCreateSimpleWindow(m_display, parent, x, y, width, height, 0,
+			BlackPixel(m_display, screen_num), 65535 / 20);
+
+	XMapWindow(m_display, m_win);
+	m_gc = DefaultGC(m_display, screen_num);
+
+	m_d = RootWindow(m_display, screen_num);
+
+	m_image = XGetImage(m_display, m_d, 0, 0, m_width, m_height, AllPlanes,
+			ZPixmap);
+	if (!m_image)
+	{
+		printf("error\n");
+		m_imagemutex.Unlock();
+		return false;
+	}
+
+	m_imagemutex.Unlock();
+	m_parent = parent;
+	return true;
+}
+
+void CSDecoder::CloseXImage()
+{
+	if (!m_bInit)
+		return;
+
+	m_imagemutex.Lock();
+	if (m_image)
+	{
+		XDestroyImage( m_image);
+		m_image = 0;
+	}
+
+	if (m_display)
+	{
+		if (m_win)
+		{
+			XUnmapWindow(m_display, m_win);
+			XClearWindow(m_display, m_win);
+			m_win = 0;
+		}
+
+		if (m_d)
+		{
+			XClearWindow(m_display, m_d);
+			m_d = 0;
+		}
+
+		XCloseDisplay( m_display);
+		m_display = 0;
+
+	}
+
+	m_imagemutex.Unlock();
+
+}
+
+void CSDecoder::CloseCodec()
+{
+	m_bInit = false;
+
+	if (m_pOutFrame)
+	{
+		free( m_pOutFrame);
+		m_pOutFrame = 0;
+	}
+	if (m_pCodecCtx)
+	{
+		if (m_pCodecCtx->extradata)
+		{
+			free(m_pCodecCtx->extradata);
+			m_pCodecCtx->extradata = 0;
+			m_pCodecCtx->extradata_size = 0;
+		}
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+
+}
+bool CSDecoder::ResetCodec(const int width, const int height)
+{
+	CodecID nCodecID = m_pCodecCtx->codec_id;
+	CloseCodec();
+	m_bInit = false;
+
+	m_width = width;
+	m_height = height;
+
+	// find the video decoder
+	m_pCodec = avcodec_find_decoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("Codec not found");
+		return false;
+	}
+
+	if (m_pOutFrame)
+	{
+		free( m_pOutFrame);
+		m_pOutFrame = 0;
+	}
+	m_pOutFrame = avcodec_alloc_frame();
+
+	if (m_pCodecCtx)
+	{
+		if (m_pCodecCtx->extradata)
+		{
+			free(m_pCodecCtx->extradata);
+			m_pCodecCtx->extradata = 0;
+			m_pCodecCtx->extradata_size = 0;
+		}
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+	m_pCodecCtx = avcodec_alloc_context();
+	m_pCodecCtx->extradata = 0;
+	m_pCodecCtx->extradata_size = 0;
+
+	// put sample parameters
+	/* resolution must be a multiple of two */
+	m_pCodecCtx->width = m_width;
+	m_pCodecCtx->height = m_height;
+	/* frames per second */
+	m_pCodecCtx->frame_rate = CSEncoder::S_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = CSEncoder::S_CODEC_frame_rate_base;
+	m_pCodecCtx->gop_size = CSEncoder::S_CODEC_gop_size; /* emit one intra frame every ten frames */
+
+	m_pCodecCtx->bit_rate = 512 * 1024;
+	m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+	m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+
+	m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+	m_pCodecCtx->extradata = malloc(S_De_ExtraHeaderSize);
+	if (m_pCodecCtx->extradata == 0)
+	{
+		return false;
+	}
+	m_pCodecCtx->extradata_size = S_De_ExtraHeaderSize / 8;
+
+	// we dont send complete frames
+	if (m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
+		m_pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
+
+	// open it
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		PErrorText("could not open codec");
+		return false;
+	}
+
+	if (m_image)
+	{
+		XDestroyImage( m_image);
+		m_image = 0;
+	}
+
+	m_image = XGetImage(m_display, m_parent, 0, 0, m_width, m_height,
+			AllPlanes, ZPixmap);
+	if (!m_image)
+	{
+		PErrorText("GetImage error");
+		m_imagemutex.Unlock();
+		return false;
+	}
+
+	m_bInit = true;
+	return true;
+
+}
+
+bool CSDecoder::Init(int width, int height, enum CodecID nCodecID)
+{
+
+	if (m_bInit)
+		return true;
+
+	avcodec_init();
+	avcodec_register_all();
+
+	if (!m_imagemutex.IsInitialized())
+	{
+		if (m_imagemutex.Init() < 0)
+			return false;
+	}
+
+	m_width = width;
+	m_height = height;
+
+	// find the video decoder
+	m_pCodec = avcodec_find_decoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("Codec not found");
+		return false;
+	}
+
+	if (m_pOutFrame)
+	{
+		free( m_pOutFrame);
+		m_pOutFrame = 0;
+	}
+	m_pOutFrame = avcodec_alloc_frame();
+
+	if (m_pCodecCtx)
+	{
+		if (m_pCodecCtx->extradata)
+		{
+			free(m_pCodecCtx->extradata);
+			m_pCodecCtx->extradata = 0;
+			m_pCodecCtx->extradata_size = 0;
+		}
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+	m_pCodecCtx = avcodec_alloc_context();
+	m_pCodecCtx->extradata = 0;
+	m_pCodecCtx->extradata_size = 0;
+
+	// put sample parameters
+	/* resolution must be a multiple of two */
+	m_pCodecCtx->width = m_width;
+	m_pCodecCtx->height = m_height;
+	/* frames per second */
+	m_pCodecCtx->frame_rate = CSEncoder::S_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = CSEncoder::S_CODEC_frame_rate_base;
+	m_pCodecCtx->gop_size = CSEncoder::S_CODEC_gop_size; /* emit one intra frame every ten frames */
+
+	m_pCodecCtx->bit_rate = 512 * 1024;
+	m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+	m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+
+	m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+	m_pCodecCtx->extradata = malloc(S_De_ExtraHeaderSize);
+	if (m_pCodecCtx->extradata == 0)
+	{
+		return false;
+	}
+	m_pCodecCtx->extradata_size = S_De_ExtraHeaderSize / 8;
+
+	// we dont send complete frames
+	if (m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
+		m_pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
+
+	// open it
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		PErrorText("could not open codec");
+		return false;
+	}
+
+	//	m_bIsFirstKeyFrame = false;
+	m_bInit = true;
+	return true;
+}
+
+int CSDecoder::DecodeProcess(uint8_t *encodeddata_v,
+		const int encodeddatasize_v)
+{
+	bool isPaintPic;
+	int realsize, i;
+	int got_picture;
+	if (!m_bInit)
+	{
+		return -1;
+	}
+
+	//	int ngot = 0;
+	int left = 0;
+	int len;
+	m_imagemutex.Lock();
+	for (i = 0;; i++)
+	{
+		if (encodeddatasize_v - i * S_De_INBUF_SIZE >= S_De_INBUF_SIZE)
+			realsize = S_De_INBUF_SIZE;
+		else
+			realsize = encodeddatasize_v - i * S_De_INBUF_SIZE;
+
+		if (realsize <= 0)
+			break;
+
+		left = 0;
+		isPaintPic = false;
+		while (realsize > 0)
+		{
+			m_pCodecCtx->width = m_width;
+			m_pCodecCtx->height = m_height;
+			len = avcodec_decode_video(m_pCodecCtx, m_pOutFrame, &got_picture,
+					(encodeddata_v + i * S_De_INBUF_SIZE + left), realsize);
+
+			if (len < 0)
+			{
+				PErrorText("Error while decoding");
+				m_imagemutex.Unlock();
+				return -2;
+			}
+
+			if (m_image != 0)
+			{
+
+				m_encoder.GetColorInfo(m_image, &c_info);
+				switch (m_image->bits_per_pixel)
+				{
+				case 8:
+					input_pixfmt = PIX_FMT_PAL8;
+					break;
+				case 16:
+					if (m_image->red_mask == 0xF800 && m_image->green_mask
+							== 0x07E0 && m_image->blue_mask == 0x1F)
+					{
+						input_pixfmt = PIX_FMT_RGB565;
+					}
+					else if (m_image->red_mask == 0x7C00 && m_image->green_mask
+							== 0x03E0 && m_image->blue_mask == 0x1F)
+					{
+						input_pixfmt = PIX_FMT_RGB555;
+					}
+					else
+					{
+						fprintf(
+								stderr,
+								"xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth %i not supported ... aborting\n",
+								m_image->bits_per_pixel);
+						fprintf(
+								stderr,
+								"xtoffmpeg.XImageToFFMPEG(): color masks: r 0x%.6lX g 0x%.6lX b 0x%.6lX\n",
+								m_image->red_mask, m_image->green_mask,
+								m_image->blue_mask);
+					}
+					break;
+				case 24:
+					if (m_image->red_mask == 0xFF0000 && m_image->green_mask
+							== 0xFF00 && m_image->blue_mask == 0xFF)
+					{
+						input_pixfmt = PIX_FMT_BGR24;
+					}
+					else if (m_image->red_mask == 0xFF && m_image->green_mask
+							== 0xFF00 && m_image->blue_mask == 0xFF0000)
+					{
+						input_pixfmt = PIX_FMT_RGB24;
+					}
+					else
+					{
+						PErrorText(
+								"xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth not supported ... aborting");
+						PErrorText("xtoffmpeg.XImageToFFMPEG(): color masks");
+						return false;
+					}
+					break;
+				case 32:
+					if (c_info.alpha_mask == 0xFF000000 && m_image->green_mask
+							== 0xFF00)
+					{
+
+						input_pixfmt = PIX_FMT_RGBA32;
+					}
+					else
+					{
+						PErrorText(
+								"xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting\n");
+						return false;
+					}
+					break;
+				default:
+					PErrorText(
+							"xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting\n");
+					return false;
+				}
+			}
+
+			if (got_picture)
+			{
+				if (!isPaintPic)
+				{
+					if (m_display && m_image && m_win)
+					{
+						avpicture_fill(&pic_rgb, (uint8_t*) m_image->data,
+								input_pixfmt, m_width, m_height);
+
+						if (img_convert(&pic_rgb, input_pixfmt,
+								(AVPicture*) m_pOutFrame, PIX_FMT_YUV420P,
+								m_width, m_height) < 0)
+						{
+							PErrorText("Error pixel format conversion");
+							m_imagemutex.Unlock();
+							return -3;
+						}
+
+						XPutImage(m_display, m_win, m_gc, m_image, 0, 0, 0, 0,
+								m_width, m_height);
+					}
+				}
+				isPaintPic = true;
+
+			}
+			realsize -= len;
+			left += len;
+		}
+	}
+
+	m_imagemutex.Unlock();
+	return 0;
+}
+
+//CScreenSender class.
+CScreenSender::CScreenSender() :
+	m_sendthread(SendBufSize)
+{
+	stop = false;
+	m_bIsRecord = false;
+	m_bInit = 0;
+
+	m_hFile = 0;
+
+}
+
+CScreenSender::~CScreenSender()
+{
+	//first stop thread, because  m_pOutBuf is being used by Thread();
+	Stop();
+
+	//close file.
+	if (m_hFile)
+	{
+		fclose( m_hFile);
+		m_hFile = 0;
+	}
+
+	//free buffer.
+	if (m_pOutBuf != 0)
+		free( m_pOutBuf);
+}
+
+bool CScreenSender::Init(int nPort)
+{
+	if (m_bInit)
+		return true;
+
+	//init sendthread.
+	if (!m_sendthread.Init(nPort))
+		return false;
+
+	if (m_pOutBuf == 0)
+	{
+		m_pOutBuf = (uint8_t*) malloc(CSEncoder::S_En_OutBufSize);
+		if (m_pOutBuf == 0)
+		{
+			return false;
+		}
+
+	}
+
+	//Init sencoder.
+	if (!m_sencoder.Init(CODEC_ID_MPEG4))
+	{
+		return false;
+	}
+
+	m_bInit = true;
+	return m_bInit;
+}
+
+int CScreenSender::Start(char* szFile /* =0 */, bool bIsRecord /* =false */)
+{
+	if (!m_bInit)
+		return -1;
+
+	if (JThread::IsRunning())
+		return 0;
+
+	if (!stopmutex.IsInitialized())
+	{
+		if (stopmutex.Init() < 0)
+			return -2;
+	}
+
+	stop = false;
+
+	if (!m_recordmutex.IsInitialized())
+	{
+		if (m_recordmutex.Init() < 0)
+			return -2;
+	}
+
+	m_bIsRecord = bIsRecord;
+
+	if (bIsRecord && szFile != 0)
+	{
+		if (m_hFile)
+		{
+			fclose( m_hFile);
+			m_hFile = 0;
+		}
+
+		m_hFile = fopen(szFile, "wb");
+		if (m_hFile == 0)
+		{
+			return -3;
+		}
+
+	}
+
+	if (m_sendthread.Start() < 0)
+	{
+		return -6;
+	}
+
+	if (JThread::Start() < 0)
+	{
+		return -6;
+	}
+
+	return 0;
+}
+
+void CScreenSender::Stop()
+{
+	if (!IsRunning())
+		return;
+
+	stopmutex.Lock();
+	stop = true;
+	stopmutex.Unlock();
+
+	int count = 0;
+	while (1)
+	{
+		if (count >= 100)
+		{
+			if (JThread::IsRunning())
+			{
+				JThread::Kill();
+			}
+			break;
+		}
+
+		if (JThread::IsRunning())
+		{
+			count++;
+			usleep(10000);
+			continue;
+		}
+
+		break;
+	}
+
+	stop = false;
+
+	//close file.
+	if (m_hFile)
+	{
+		fclose( m_hFile);
+		m_hFile = 0;
+	}
+
+	m_bIsRecord = false;
+
+	m_sendthread.Stop();
+
+}
+
+void CScreenSender::Record(bool bInRecord /* =true */)
+{
+	if (!m_bInit)
+		return;
+
+	m_recordmutex.Lock();
+	m_bIsRecord = bInRecord;
+	m_recordmutex.Unlock();
+
+}
+
+void *CScreenSender::Thread()
+{
+	XImage * pImage;
+	int OutBufSzie;
+
+	JThread::ThreadStarted();
+
+	bool stopthread;
+
+	stopmutex.Lock();
+	stopthread = stop;
+	stopmutex.Unlock();
+
+	bool isrecord;
+	m_recordmutex.Lock();
+	isrecord = m_bIsRecord;
+	m_recordmutex.Unlock();
+
+	int status;
+
+	int64_t pre_time, cur_time;
+	useconds_t delay, delay1;
+
+	if (m_sencoder.m_pCodecCtx->frame_rate != 0)
+	{
+		if (m_sencoder.m_pCodecCtx->frame_rate_base != 0)
+			delay1 = 1000000 * m_sencoder.m_pCodecCtx->frame_rate_base
+					/ m_sencoder.m_pCodecCtx->frame_rate;
+		else
+			delay1 = 1000000 / m_sencoder.m_pCodecCtx->frame_rate;
+	}
+	else
+	{
+		delay1 = 1000000;
+	}
+
+	// sleep for sync
+	if (delay_time > 0)
+	{
+		sleep( delay_time);
+	}
+
+	// for Utiltiy rate of CPU
+	cur_time = av_gettime();
+	pre_time = cur_time - delay1;
+
+	// for compensate.
+	int64_t nFrame = 0;
+	int64_t rec_time = 0;
+	int64_t rec_start;
+	rec_start = av_gettime();
+
+	while (!stopthread)
+	{
+		delay = cur_time - pre_time;
+		if (delay < delay1)
+		{
+			usleep(delay1 - delay);
+		}
+		pre_time = av_gettime();
+
+		if ((status = m_sencoder.Capture(&pImage)) < 0)
+		{
+			stopthread = true;
+			continue;
+		}
+		else
+		{
+			OutBufSzie = CSEncoder::S_En_OutBufSize;
+			if ((status = m_sencoder.EncodeProcess(pImage, m_pOutBuf,
+					OutBufSzie)) < 0)
+			{
+				stopthread = true;
+				continue;
+			}
+			else
+			{
+				if (status > 0)
+				{
+					//static int iiii=0;					
+					m_sendthread.SendData(m_pOutBuf, status);
+
+					if (m_hFile != 0 && isrecord)
+					{
+						fwrite(m_pOutBuf + sizeof(ScreenHeader), status
+								- sizeof(ScreenHeader), 1, m_hFile);
+						nFrame++;
+
+						//add up rec_time;
+						rec_time = av_gettime() - rec_start;
+						int i;
+						for (i = 0; rec_time > nFrame * delay1; nFrame++, i++)
+						{
+							printf("\nScreen Frame=%d\n", nFrame);
+							if ((status = m_sencoder.EncodeProcess(pImage,
+									m_pOutBuf, OutBufSzie)) < 0)
+							{
+								printf("\nscreen: encode vital error.");
+								stopthread = true;
+								printf(
+										"\nscreen capture thread stoped by EncodeProcess error!\n");
+								return 0;
+							}
+							if (status > 0)
+								fwrite(m_pOutBuf + sizeof(ScreenHeader), status
+										- sizeof(ScreenHeader), 1, m_hFile);
+						}
+
+					}
+					else
+					{
+						rec_start = av_gettime();
+						nFrame = 0;
+					}
+
+				}
+
+			}
+		}
+
+		m_recordmutex.Lock();
+		isrecord = m_bIsRecord;
+		m_recordmutex.Unlock();
+
+		stopmutex.Lock();
+		stopthread = stop;
+		stopmutex.Unlock();
+
+		cur_time = av_gettime();
+
+	}
+
+	printf("\nscreen capture thread stoped!\n");
+	return 0;
+}
+
+bool CScreenSender::AddDestination(const RTPIPv4Address &des)
+{
+	if (!m_bInit)
+		return false;
+	if (m_sendthread.AddDestination(des) < 0)
+		return false;
+
+	return true;
+}
+void CScreenSender::ClearDestinations()
+{
+	if (!m_bInit)
+		return;
+	m_sendthread.ClearDestinations();
+}
+
+//CScreenReceiver class.
+
+CScreenReceiver::CScreenReceiver()
+{
+	m_bInit = false;
+	m_ScreenInit = false;
+}
+
+CScreenReceiver::~CScreenReceiver()
+{
+
+}
+bool CScreenReceiver::Init()
+{
+	if (m_bInit)
+		return m_bInit;
+
+	//init video decoder.
+	if (!m_sdecoder.Init(800, 600, CODEC_ID_MPEG4))
+	{
+		return false;
+	}
+
+	m_bInit = true;
+	return m_bInit;
+
+}
+bool CScreenReceiver::CreateXImage(Drawable parent, int x, int y, int width,
+		int height)
+{
+	bool ret;
+	ret = m_sdecoder.CreateXImage(parent, x, y, width, height);
+
+	return ret;
+}
+
+void CScreenReceiver::CloseXImage()
+{
+	m_sdecoder.CloseXImage();
+}
+
+#define MAX_PACKET_SIZE 10240
+
+int CScreenReceiver::Start(int nPort)
+{
+
+	if (IsActive())
+		return 0;
+
+	//init rtpsession.
+	RTPSessionParams sessParams1;
+	sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+	sessParams1.SetUsePollThread(1);
+	//background thread to call virtual callbacks - set by default, but just to be sure
+	sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+	//setup transmission parameters
+	RTPUDPv4TransmissionParams transParams1;
+	transParams1.SetPortbase(nPort);
+	//CREATE THE SESSION
+	int status1 = Create(sessParams1, &transParams1);
+	if (status1)
+	{
+		return -2;
+	}
+
+	return 0;
+}
+
+void CScreenReceiver::Stop()
+{
+	Destroy();
+}
+
+void CScreenReceiver::ProcessFrame(unsigned char* framedata, int framelen)
+{
+	pScreen = (ScreenHeader*) framedata;
+
+	if (pScreen->width != m_sdecoder.m_width || pScreen->height
+			!= m_sdecoder.m_height)
+	{
+		m_sdecoder.ResetCodec(pScreen->width, pScreen->height);
+	}
+	m_sdecoder.DecodeProcess(framedata + sizeof(ScreenHeader), framelen
+			- sizeof(ScreenHeader));
+
+}

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.h
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.h?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.h (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_screen.h Mon Nov 30 12:01:23 2009
@@ -0,0 +1,368 @@
+/** \file en_de_screen.h Classes for screen operation:capture,encoder,decoder,sender,receiver
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+
+#include "fecrtpsession.h"
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+// FFmpeg
+#include <ffmpeg/avcodec.h>
+#include <ffmpeg/avformat.h>
+//Time
+#include <time.h>
+// X11
+#include <X11/Intrinsic.h>
+#include <X11/XWDFile.h>
+// Jthread and JMutex
+#include <jthread.h>
+#include <jmutex.h>
+
+#include "en_de_sendthread.h"
+
+#define max(x,y) (x > y ? x : y)
+
+#if !defined(_EN_DE_SCREEN_H__INCLUDED_)
+#define _EN_DE_SCREEN_H__INCLUDED_
+
+//!Screen Header Information
+/*!
+\param width Screen width
+\param height Screen height
+*/
+typedef struct ScreenHeader
+{
+	int width;
+	int height;
+} ScreenHeader;
+//!Color Info
+typedef struct
+{
+	unsigned long red_shift;
+	unsigned long green_shift;
+	unsigned long blue_shift;
+	unsigned long alpha_shift;
+	unsigned long max_val;
+	unsigned long bit_depth;
+	unsigned long red_max_val;
+	unsigned long green_max_val;
+	unsigned long blue_max_val;
+	unsigned long alpha_max_val;
+	unsigned long red_bit_depth;
+	unsigned long green_bit_depth;
+	unsigned long blue_bit_depth;
+	unsigned long alpha_bit_depth;
+	u_int32_t alpha_mask;
+} ColorInfo;
+
+//!Screen encoder.
+class CSEncoder
+{
+	friend class CSDecoder;
+	friend class CScreenSender;
+	friend class CWScreenRecorder;
+private:
+	//!buffer size
+	enum SENCODERBUFSIZE
+	{
+		S_En_OutBufSize = 400 * 1024
+	};
+	//!Screen codec params
+	enum SCREEN_CODEC_PARA
+	{
+		S_CODEC_width = 800,
+		S_CODEC_height = 600,
+		S_CODEC_framerate = 3,
+		S_CODEC_frame_rate_base = 1,
+		S_CODEC_gop_size = 4,
+		S_CODEC_max_b_frames
+	};
+public:
+	//!Constructor
+	CSEncoder();
+	//!Destructor
+	virtual ~CSEncoder();
+	//!Get Screen Size
+	/*!
+	\param width Screen width
+	\param height Screen height
+	*/
+	bool GetScreenSize(int &width, int &height);
+	//!capture Screen
+	/*!
+	\param image store in XImage struct
+	*/
+	bool Capture(XImage **image);
+	//!Encode the captured Screen image
+	/*!
+	\param image pointer to captured Screen image
+	\param pOutBuf store the encoded Screen image
+	\param nOutsize the encoded data size
+	*/
+	int EncodeProcess(XImage *image, uint8_t *pOutBuf, int nOutsize);
+	//!Initialise
+	/*!
+	\param nCodecID the Codec ID
+	*/
+	bool Init(enum CodecID nCodecID = CODEC_ID_MPEG4);
+	//!Get image Color Info
+	/*!
+	\param image the source XImage Struct
+	\param ci the return ColorInfo Struct
+	*/
+	void GetColorInfo(XImage *image, ColorInfo *ci /* return struct */);
+
+private:
+	//!paint Mouse Pointer
+	void paintMousePointer(int *x, int *y, XImage *image);
+	//!get Current Pointer
+	void getCurrentPointer(int *x, int *y);
+	//!Initialise
+	/*!
+	\param width Screen width
+	\param height Screen height
+	*/
+	bool InitScreen(int width, int height);
+
+private:
+
+	//!Display Instance 
+	Display *m_display;
+	//!Root window
+	Drawable m_d;
+	//!image to be displayed
+	XImage *m_image;
+	//!Store color infor
+	ColorInfo c_info;
+	//!screen number
+	int m_screen_num;
+
+	unsigned int m_width, m_height;
+	//!mark init screen status
+	bool m_bInitScreen;
+	//!pixel format
+	int input_pixfmt;
+	//!Screen Header information
+	ScreenHeader m_ScreenHeader;
+
+private:
+	//!init status
+	bool m_bInit;
+
+	//!AVCodec Instance to store the codec
+	AVCodec *m_pCodec;
+	//!AVCodecContext Instance to store the codec content
+	AVCodecContext *m_pCodecCtx;
+	//!AVFrame Instance to store decoded frame
+	AVFrame *m_pFrame;
+	//!AVPicture Instance to store decoded picture
+	AVPicture m_pic_rgb;
+	//!frame buffer
+	uint8_t *m_pFrameBuf;
+
+};
+
+//!Screen decoder.
+class CSDecoder
+{
+	friend class CScreenReceiver;
+private:
+	enum VDECODERBUFSIZE
+	{
+		S_De_ExtraHeaderSize = 10000, S_De_INBUF_SIZE = 1024
+	};
+public:
+	//!Constructor
+	CSDecoder();
+	//!Destructor
+	virtual ~CSDecoder();
+public:
+	//!Decode a screen frame
+	/*!
+	\param encodeddata_v pointer to encodeddata
+	\param encodeddatasize_v the encodeddata size
+	*/
+	int DecodeProcess(uint8_t *encodeddata_v, const int encodeddatasize_v);
+	//!Initialise
+	/*!
+	\param width the screen width
+	\param height the screen height
+	\param nCodecID the Codec ID
+	*/	
+	bool Init(int width, int height, enum CodecID nCodecID);
+
+	//!Show the decoded screen (image)
+	/*!
+	\param parent the Drawable parent window
+	\param x the coordinate 
+	\param y the coordinate 
+	\param width image width
+	\param height image height
+	*/
+	bool CreateXImage(Drawable parent, int x, int y, int width, int height);
+	//!close image display	
+	void CloseXImage();
+
+private:
+	//!close the codec
+	void CloseCodec();
+	//!reset codec params
+	/*!
+	\param width the image width
+	\param height the image height
+	*/	
+	bool ResetCodec(const int width, const int height);
+	//!Drawable root window
+	Drawable m_parent;
+	//!Display Instance 
+	Display *m_display;
+	//!For dislay image
+	GC m_gc;
+	//!Root window
+	Window m_d;
+	//!window for display image
+	Window m_win;
+	//!image to be displayed
+	XImage *m_image;
+	//!mutex variable for image display
+	JMutex m_imagemutex;
+	//!Store color infor
+	ColorInfo c_info;
+	//!for call encoder getColorInfo
+	CSEncoder m_encoder;
+	//!pixel format
+	int input_pixfmt;
+
+private:
+	//!mark init status	
+	bool m_bInit;
+	//!AVCodec Instance to store the codec
+	AVCodec *m_pCodec;
+	//!AVCodecContext Instance to store the codec content
+	AVCodecContext *m_pCodecCtx;
+	//!AVFrame Instance to store decoded frame
+	AVFrame *m_pOutFrame;
+	//!AVPicture Instance to store decoded picture
+	AVPicture pic_rgb;
+	//!codec width 
+	int m_width;
+	//!codec height
+	int m_height;
+};
+
+//!screen sender.
+class CScreenSender: private JThread
+{
+private:
+	enum SCREENSENDBUFSIZE
+	{
+		SendBufSize = 2
+	};
+public:
+	//!Constructor
+	CScreenSender();
+	//!Destructor
+	~CScreenSender();
+	//!Initialise
+	bool Init(int nHostPort);
+	//!Add Destination for sending
+	bool AddDestination(const RTPIPv4Address &des);
+	//!Clear Destinations
+	void ClearDestinations();
+	//!Start sender thread
+	int Start(char* szFile = 0, bool bIsRecord = false);
+	//!stop the thread	
+	void Stop();
+	//!record screen
+	void Record(bool bInRecord = true);
+
+private:
+	//!work thread
+	void *Thread();
+	//!stoo status
+	bool stop;
+	//!mutex for stoping thread
+	JMutex stopmutex;
+private:
+	//!record status
+	bool m_bIsRecord;
+	//!mutex for record
+	JMutex m_recordmutex;
+	//!call screen encoder
+	CSEncoder m_sencoder;
+	//!output buffer
+	uint8_t *m_pOutBuf;
+	//!store the recorded screen data
+	FILE* m_hFile;
+	//!call send thread
+	CSendThread m_sendthread;
+	//!init status
+	int m_bInit;
+
+};
+
+//!screen receiver
+class CScreenReceiver: public CFECRtpSession
+{
+public:
+	//!Constructor
+	CScreenReceiver();
+	//!Destructor
+	virtual ~CScreenReceiver();
+	//Initialise
+	bool Init();
+	//!start receive video data
+	int Start(int nHostPort);
+	//!stop receive the thread
+	void Stop();
+
+public:
+	//!show the image 
+	bool CreateXImage(Drawable parent, int x, int y, int width, int height);
+	//!close the image display	
+	void CloseXImage();
+
+private:
+	//!Deal with the received screen data
+	/*!
+	\param framedata pointer to frame data
+	\param framelen length of frame
+	*/
+	virtual void ProcessFrame(unsigned char* framedata, int framelen);
+private:
+	//!screen init
+	bool m_ScreenInit;
+	//!receiver init
+	bool m_bInit;
+	//!call screen decoder
+	CSDecoder m_sdecoder;
+public:
+	//!screen header information
+	ScreenHeader* pScreen;
+};
+
+#endif // !defined(_EN_DE_SCREEN_H__INCLUDED_)

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.cpp?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.cpp (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.cpp Mon Nov 30 12:01:23 2009
@@ -0,0 +1,250 @@
+/** \file en_de_sendthread.cpp Implementation for send data clas
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+#include "en_de_sendthread.h"
+
+extern void PErrorText(const char* error);
+//CSendThread class.
+CSendThread::CSendThread(int nSendBufSize)
+{
+	stop = false;
+	m_bInit = 0;
+
+	if (nSendBufSize <= 2)
+	{
+		m_nSendBufSize = 2;
+	}
+	else if (nSendBufSize >= 25)
+	{
+		m_nSendBufSize = 25;
+	}
+	else
+		m_nSendBufSize = nSendBufSize;
+
+}
+
+CSendThread::~CSendThread()
+{
+	Stop();
+
+}
+
+#define MAX_PACKET_SIZE 10*1024
+bool CSendThread::Init(int nPort)
+{
+	if (m_bInit)
+		return true;
+
+	//init rtpsession.
+	RTPSessionParams sessParams1;
+	sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+	sessParams1.SetUsePollThread(0); //background thread to call virtual callbacks - set by default, but just to be sure
+	sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+	//setup transmission parameters
+	RTPUDPv4TransmissionParams transParams1;
+	transParams1.SetPortbase(nPort);
+	//CREATE THE SESSION
+	int status1 = m_fecrtpsession.Create(sessParams1, &transParams1);
+	if (status1)
+	{
+		return false; //unable to create the session
+	}
+
+	//must set for fec SendFECPacket. 
+	m_fecrtpsession.SetDefaultMark(true);
+	m_fecrtpsession.SetDefaultPayloadType(1);
+	m_fecrtpsession.SetDefaultTimestampIncrement(0);
+
+	m_bInit = true;
+	return m_bInit;
+}
+
+int CSendThread::Start()
+{
+	if (!m_bInit)
+		return -1;
+
+	if (JThread::IsRunning())
+		return 0;
+
+	if (!stopmutex.IsInitialized())
+	{
+		if (stopmutex.Init() < 0)
+			return -2;
+	}
+
+	stop = false;
+
+	if (!m_senddatamutex.IsInitialized())
+	{
+		if (m_senddatamutex.Init() < 0)
+			return -2;
+	}
+
+	if (JThread::Start() < 0)
+	{
+		return -6;
+	}
+
+	return 0;
+}
+
+void CSendThread::Stop()
+{
+	if (!IsRunning())
+		return;
+
+	stopmutex.Lock();
+	stop = true;
+	stopmutex.Unlock();
+
+	//wait for two minute;
+	sleep(1);
+	if (JThread::IsRunning())
+	{
+		JThread::Kill();
+	}
+	stop = false;
+
+}
+
+int CSendThread::SendData(uint8_t *data, int datalen)
+{
+	SENDBUFDATA *pData;
+	if (!m_bInit)
+		return -1;
+
+	pData = new SENDBUFDATA;
+	if (pData == 0)
+	{
+		PErrorText("Error: CSendThread::SendData new SENDBUFDATA");
+		return -2;
+	}
+
+	pData->data = new uint8_t[datalen];
+	if (pData->data == 0)
+	{
+		delete pData;
+		PErrorText("Error: CSendThread::SendData new uint8_t");
+		return -3;
+	}
+
+	memcpy(pData->data, data, datalen);
+	pData->datalen = datalen;
+
+	m_senddatamutex.Lock();
+	m_senddata.insert(m_senddata.end(), pData);
+	m_senddatamutex.Unlock();
+
+	return 0;
+}
+
+void *CSendThread::Thread()
+{
+	JThread::ThreadStarted();
+
+	SENDBUFDATA *senddata = new SENDBUFDATA[m_nSendBufSize];
+	bool stopthread;
+
+	stopmutex.Lock();
+	stopthread = stop;
+	stopmutex.Unlock();
+
+	int size;
+	SENDBUFDATA* p;
+	SendDatalist::iterator itera;
+	int index;
+	while (!stopthread)
+	{
+
+		m_senddatamutex.Lock();
+		size = m_senddata.size();
+		if (size == 0)
+		{
+			m_senddatamutex.Unlock();
+
+			usleep(50000);
+
+			stopmutex.Lock();
+			stopthread = stop;
+			stopmutex.Unlock();
+			continue;
+		}
+		if (size > m_nSendBufSize)
+		{
+			for (itera = m_senddata.begin(); itera != m_senddata.end(); itera++)
+			{
+				p = *itera;
+				delete p->data;
+				delete p;
+				p = 0;
+			}
+			m_senddata.clear();
+			size = 0;
+		}
+		else
+		{
+			for (itera = m_senddata.begin(), index = 0; itera
+					!= m_senddata.end(); itera++, index++)
+			{
+				p = *itera;
+				senddata[index].data = p->data;
+				senddata[index].datalen = p->datalen;
+				delete p;
+				p = 0;
+			}
+			m_senddata.clear();
+			size = index;
+		}
+
+		m_senddatamutex.Unlock();
+
+		for (index = 0; index < size; index++)
+		{
+			m_fecrtpsession.SendFECPacket(senddata[index].data,
+					senddata[index].datalen, 5000);
+			delete senddata[index].data;
+		}
+
+		stopmutex.Lock();
+		stopthread = stop;
+		stopmutex.Unlock();
+
+	}
+	printf("\nSendthread stoped.\n");
+	return 0;
+}
+
+bool CSendThread::AddDestination(const RTPIPv4Address &des)
+{
+	if (!m_bInit)
+		return false;
+	if (m_fecrtpsession.AddDestination(des) < 0)
+		return false;
+
+	return true;
+}
+
+void CSendThread::ClearDestinations()
+{
+	if (!m_bInit)
+		return;
+	m_fecrtpsession.ClearDestinations();
+}

Added: incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.h
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.h?rev=885392&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.h (added)
+++ incubator/bluesky/trunk/RealClass/Teacher/src/en_de_sendthread.h Mon Nov 30 12:01:23 2009
@@ -0,0 +1,106 @@
+/** \file en_de_sendthread.h Class for send data
+*
+*
+*Licensed to the Apache Software Foundation (ASF) under one
+*or more contributor license agreements.  See the NOTICE file
+*distributed with this work for additional information
+*regarding copyright ownership.  The ASF licenses this file
+*to you under the Apache License, Version 2.0 (the
+*"License"); you may not use this file except in compliance
+*with the License.  You may obtain a copy of the License at
+*
+*  http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing,
+*software distributed under the License is distributed on an
+*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*KIND, either express or implied.  See the License for the
+*specific language governing permissions and limitations
+*under the License. 
+*/
+
+#include "fecrtpsession.h"
+// Linux sys.
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+// FFmpeg
+#include <ffmpeg/avcodec.h>
+#include <ffmpeg/avformat.h>
+
+#include <time.h>
+
+// X11
+#include <X11/Intrinsic.h>
+#include <X11/XWDFile.h>
+// Jthread and JMutex
+#include <jthread.h>
+#include <jmutex.h>
+
+#if !defined(_EN_DE_SENDTHREAD_H__INCLUDED_)
+#define _EN_DE_SENDTHREAD_H__INCLUDED_
+//!Send buffer
+struct SENDBUFDATA
+{
+	uint8_t* data;
+	int datalen;
+};
+typedef std::list<SENDBUFDATA*> SendDatalist;
+
+//CSendThread class.
+class CSendThread: private JThread
+{
+public:
+	//!Constuctor
+	CSendThread(int nSendBufSize);
+	//!Destructor
+	~CSendThread();
+	//!Initialise
+	bool Init(int nPort);
+	//!Add Destination
+	/*!
+	\param RTPIPv4Address destination address
+	*/
+	bool AddDestination(const RTPIPv4Address &des);
+	//!Clear Destinations
+	void ClearDestinations();
+	//!Send Data
+	/*!
+	\param data opinter to data buffer
+	\param datalen data size
+	*/
+	int SendData(uint8_t *data, int datalen);
+	//!start send
+	int Start();
+	//!stop send
+	void Stop();
+
+private:
+
+	//!work thread
+	void *Thread();
+	//!stop status
+	bool stop;
+	//!mutex for stop
+	JMutex stopmutex;
+private:
+	//!CFECRtpSession instance to ensure communication
+	CFECRtpSession m_fecrtpsession;
+	//!init status
+	int m_bInit;
+	//!send buffer size
+	int m_nSendBufSize;
+	//!send data store as list
+	SendDatalist m_senddata;
+	//!mutex for access data
+	JMutex m_senddatamutex;
+};
+
+#endif // !defined(_EN_DE_SENDTHREAD_H__INCLUDED_)