incubator-bluesky-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p...@apache.org
Subject svn commit: r819923 [3/4] - in /incubator/bluesky/trunk/RealClass/Student/src: ./ pic/
Date Tue, 29 Sep 2009 13:10:31 GMT
Added: incubator/bluesky/trunk/RealClass/Student/src/en_de_video.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Student/src/en_de_video.cpp?rev=819923&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Student/src/en_de_video.cpp (added)
+++ incubator/bluesky/trunk/RealClass/Student/src/en_de_video.cpp Tue Sep 29 13:10:30 2009
@@ -0,0 +1,2099 @@
+
+static char *primary_version = "";
+static char *video_version_ = "1.0";
+
+//V4l classes.
+#include <deque>
+#include <unistd.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include <pthread.h>
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "en_de_video.h"
+
+extern int v4l_dev_num = 0;
+extern int delay_time = 0;
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/soundcard.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+}
+
+static int ENCODE_YUV = 0;
+
+/** Send a request to the v4l device associated to a V4LStruct object.
+ */
+
+bool V4LDevice::request(int req, V4LStruct *v4l)
+{
+	ENCODE_YUV = getenv("KINO_V4L_PATCHED") != NULL;
+	return request(req, v4l->getStruct());
+}
+
+/** Send a request to the v4l device associated to an arbitrary address.
+ */
+
+bool V4LDevice::request(int req, void *addr)
+{
+	return ioctl(getHandle(), req, addr) != -1;
+}
+
+V4LCapability::V4LCapability(V4LDevice *device)
+{
+	device->request(VIDIOCGCAP, this);
+}
+
+V4LCapability::~V4LCapability()
+{
+}
+
+void *V4LCapability::getStruct()
+{
+	return &capability;
+}
+
+char *V4LCapability::getName()
+{
+	return capability.name;
+}
+
+int V4LCapability::getNumberOfChannels()
+{
+	return capability.channels;
+}
+
+int V4LCapability::getNumberOfAudioDevices()
+{
+	return capability.audios;
+}
+
+int V4LCapability::getMinWidth()
+{
+	return capability.minwidth;
+}
+
+int V4LCapability::getMinHeight()
+{
+	return capability.minheight;
+}
+
+int V4LCapability::getMaxWidth()
+{
+	return capability.maxwidth;
+}
+
+int V4LCapability::getMaxHeight()
+{
+	return capability.maxheight;
+}
+
+bool V4LCapability::canCapture()
+{
+	return capability.type & VID_TYPE_CAPTURE;
+}
+
+bool V4LCapability::hasTuner()
+{
+	return capability.type & VID_TYPE_TUNER;
+}
+
+bool V4LCapability::hasChromakey()
+{
+	return capability.type & VID_TYPE_CHROMAKEY;
+}
+
+bool V4LCapability::hasClipping()
+{
+	return capability.type & VID_TYPE_CLIPPING;
+}
+
+bool V4LCapability::hasOverwrite()
+{
+	return capability.type & VID_TYPE_FRAMERAM;
+}
+
+bool V4LCapability::hasScaling()
+{
+	return capability.type & VID_TYPE_SCALES;
+}
+
+bool V4LCapability::isMonochrome()
+{
+	return capability.type & VID_TYPE_MONOCHROME;
+}
+
+bool V4LCapability::canSubCapture()
+{
+	return capability.type & VID_TYPE_SUBCAPTURE;
+}
+
+void V4LCapability::report()
+{
+
+}
+
+V4LTuner::V4LTuner(V4LDevice *device, int index)
+{
+	this->device = device;
+	this->tuner.tuner = index;
+	this->device->request(VIDIOCGTUNER, this);
+}
+
+void *V4LTuner::getStruct()
+{
+	return &tuner;
+}
+
+void V4LTuner::report()
+{
+}
+
+int V4LTuner::getRangeLow()
+{
+	return tuner.rangelow;
+}
+
+void V4LTuner::setRangeLow(int low)
+{
+	tuner.rangelow = low;
+}
+
+int V4LTuner::getRangeHigh()
+{
+	return tuner.rangehigh;
+}
+
+void V4LTuner::setRangeHigh(int high)
+{
+	tuner.rangehigh = high;
+}
+
+int V4LTuner::getFlags()
+{
+	return tuner.flags;
+}
+
+void V4LTuner::setFlags(int flags)
+{
+	tuner.flags = flags;
+}
+
+int V4LTuner::getMode()
+{
+	return tuner.mode;
+}
+
+void V4LTuner::setMode(int mode)
+{
+	tuner.mode = mode;
+}
+
+int V4LTuner::getSignal()
+{
+	return tuner.signal;
+}
+
+V4LChannel::V4LChannel(V4LDevice *device, int index)
+{
+	memset(&channel, 0, sizeof(struct video_channel));
+	this->device = device;
+	this->channel.channel = index;
+	device->request(VIDIOCGCHAN, this);
+	device->request(VIDIOCSCHAN, this);
+	for (unsigned int i = 0; i < getNumberOfTuners(); i++)
+	{
+		V4LTuner *tuner = new V4LTuner(this->device, i);
+		tuners.insert(tuners.end(), tuner);
+	}
+}
+
+V4LChannel::~V4LChannel()
+{
+}
+
+void *V4LChannel::getStruct()
+{
+	return &channel;
+}
+
+char *V4LChannel::getName()
+{
+	return channel.name;
+}
+
+bool V4LChannel::setTuner(unsigned int index)
+{
+	if (index >= 0 && index < tuners.size())
+	{
+		current = tuners[index];
+		current->setRangeLow(0);
+		current->setRangeHigh(0xffff);
+		return device->request(VIDIOCSTUNER, current);
+	}
+	else
+	{
+		return false;
+	}
+}
+
+unsigned int V4LChannel::getNumberOfTuners()
+{
+	return channel.tuners;
+}
+
+V4LTuner *V4LChannel::getTuner(unsigned int index)
+{
+	if (index >= 0 && index < tuners.size())
+	{
+		return tuners[index];
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+int V4LChannel::getSignal()
+{
+	device->request(VIDIOCGTUNER, current);
+	return current->getSignal();
+}
+
+void V4LChannel::report()
+{
+	
+}
+
+/** Constructor for the V4L class.*/
+
+V4L::V4L()
+{
+
+}
+
+void V4L::setInfo(char *device, char *input, char *audio, int sample)
+{
+	this->device = device;
+	this->input = input;
+	this->audio = audio;
+	this->sample = sample;
+}
+
+bool V4L::openDevice()
+{
+	bool ret = true;
+
+	if (!strcmp(this->input, "PAL"))
+	{
+		this->width = VideoWidth;
+		this->height = VideoHeight;
+		this->fps = 25;
+		this->frameSample = this->sample / this->fps;
+	}
+	else if (!strcmp(this->input, "NTSC"))
+	{
+		this->width = 720;
+		this->height = 480;
+		this->fps = 30;
+		this->frameSample = this->sample / this->fps;
+	}
+
+	this->current = NULL;
+	this->fd = open(device, O_RDWR);
+	if (fd == -1)
+	{
+		perror("Unable to open video device");
+		return false;
+	}
+
+	{
+		video_capability capability;
+		if (ioctl(fd, VIDIOCGCAP, &capability) != -1)
+		{
+			printf(" query was successful\n");
+		}
+		else
+		{
+			perror("query");
+		}
+
+		if ((capability.type & VID_TYPE_CAPTURE) != 0)
+		{
+			printf("this device can capture video to memory\n");
+		}
+		else
+		{
+			perror("can't capture video to memtory");
+		}
+
+		struct video_channel queryChannel;
+		int i = 0;
+		while (i < capability.channels)
+		{
+			queryChannel.channel = i;
+			if (ioctl(fd, VIDIOCGCHAN, &queryChannel) != -1)
+			{ // ioctl success, queryChannel contains information about this channel
+				printf(" information about this channel:%d, %s\n",
+						queryChannel.channel, queryChannel.name);
+			}
+			
+			++i;
+		}
+
+		struct video_channel selectedChannel;
+		selectedChannel.channel = 0;
+		selectedChannel.norm = VIDEO_MODE_PAL;
+		if (ioctl(fd, VIDIOCSCHAN, &selectedChannel) == -1)
+		{
+			return false;
+		}
+
+		struct video_window captureWindow;
+		memset(&captureWindow, 0, sizeof(captureWindow));
+		captureWindow.width = VideoWidth;
+		captureWindow.height = VideoHeight;
+		
+		memset(&captureWindow, 0, sizeof(captureWindow));
+		if (ioctl(fd, VIDIOCGWIN, &captureWindow) == -1)
+		{
+			return false;
+		}
+
+		width = captureWindow.width;
+		height = captureWindow.height;
+		printf("width=%d,height=%d\n", width, height);
+
+	}
+
+	int depth;
+	int palette;
+	struct video_picture imageProperties;
+
+	if (ioctl(fd, VIDIOCGPICT, &imageProperties) == -1)
+	{ // failed to retrieve default image properties
+		return false;
+	}
+	depth = imageProperties.depth;
+	palette = imageProperties.palette;
+	printf("\nVideo:depth=%d,palette=%d\n", depth, palette);
+	if (ioctl(fd, VIDIOCSPICT, &imageProperties) == -1)
+	{ // failed to retrieve default image properties
+		return false;
+	}
+
+	return ret;
+}
+
+/** Destructor for the V4L device.*/
+
+V4L::~V4L()
+{
+	if (fd != -1)
+	{
+		close( fd);
+		for (unsigned int index = 0; index < channels.size(); index++)
+			delete channels[index];
+		delete this->capability;
+	}
+}
+
+
+
+bool V4L::deviceAvailable()
+{
+	return fd != -1;
+}
+
+
+int V4L::getHandle()
+{
+	return fd;
+}
+
+
+bool V4L::setChannel(unsigned int channel)
+{
+	if (channel >= 0 && channel < channels.size())
+	{
+		current = channels[channel];
+		return this->request(VIDIOCSCHAN, current);
+	}
+	else
+	{
+		return false;
+	}
+}
+
+unsigned int V4L::getNumberOfChannels()
+{
+	return channels.size();
+}
+
+V4LChannel *V4L::getChannel(unsigned int channel)
+{
+	if (channel >= 0 && channel < channels.size())
+		return channels[channel];
+	else
+		return NULL;
+}
+
+bool V4L::setTuner(unsigned int tuner)
+{
+	if (current != NULL)
+		return current->setTuner(tuner);
+	else
+		return false;
+}
+
+unsigned int V4L::getNumberOfTuners()
+{
+	if (current != NULL)
+		return current->getNumberOfTuners();
+	else
+		return 0;
+}
+
+
+V4LTuner *V4L::getTuner(unsigned int tuner)
+{
+	if (current != NULL)
+		return current->getTuner(tuner);
+	else
+		return NULL;
+}
+
+
+bool V4L::setCaptureResolution(int width, int height)
+{
+	if (width > capability->getMaxWidth() || width < capability->getMinWidth())
+		return false;
+	if (height > capability->getMaxHeight() || height
+			< capability->getMinHeight())
+		return false;
+	if (!capability->hasScaling() && (width != capability->getMaxWidth()
+			|| height != capability->getMaxHeight()))
+		return false;
+	this->width = width;
+	this->height = height;
+	return true;
+}
+
+int V4L::getWidth()
+{
+	return width;
+}
+
+int V4L::getHeight()
+{
+	return height;
+}
+
+void V4L::startAudio()
+{
+	struct video_audio audio;
+	ioctl(fd, VIDIOCGAUDIO, &audio);
+	if (audio.flags & VIDEO_AUDIO_MUTE)
+		audio.flags ^= VIDEO_AUDIO_MUTE;
+	audio.volume = 65535;
+	ioctl(fd, VIDIOCSAUDIO, &audio);
+}
+
+void V4L::stopAudio()
+{
+	struct video_audio audio;
+	ioctl(fd, VIDIOCGAUDIO, &audio);
+	audio.flags |= VIDEO_AUDIO_MUTE;
+	audio.volume = 0;
+	ioctl(fd, VIDIOCSAUDIO, &audio);
+}
+
+int V4L::mappedMemorySize(bool init)
+{
+	static video_mbuf buf;
+	if (init == true)
+	{
+		init = 1;
+		ioctl(fd, VIDIOCGMBUF, &buf);
+		frame_maps = buf.frames;
+	}
+	return buf.size;
+}
+
+bool V4L::initialiseCapture(int format)
+{
+	size = width * height * 4;
+
+	map = mmap(0, mappedMemorySize(true), PROT_READ | PROT_WRITE, MAP_SHARED,
+			fd, 0);
+
+	if (map != NULL)
+	{
+		for (int i = 0; i < frame_maps; i++)
+		{
+			frame[i].frame = i;
+			frame[i].width = getWidth();
+			frame[i].height = getHeight();
+			frame[i].format = format;
+		}
+
+		struct timeval tv;
+		gettimeofday(&tv, NULL);
+		starttime = tv.tv_sec * 1000000 + tv.tv_usec;
+		frames = 0;
+		frame_next = 0;
+
+		int retry = 0;
+		while (ioctl(fd, VIDIOCMCAPTURE, &frame[0]) == -1 && retry++
+				< frame_maps + 1)
+			;
+
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+void *V4L::getNextFrame()
+{
+	unsigned char * ret = NULL;
+
+	int current = frame_next;
+	frame_next = (frame_next + 1) % frame_maps;
+
+	if (ioctl(fd, VIDIOCMCAPTURE, &frame[frame_next]) == -1)
+		; //cout << "Frame 1 Failed to initialise" << endl;
+	if (ioctl(fd, VIDIOCSYNC, &frame[current].frame) == -1)
+		; //cout << "Frame 0 Failed to sync" << endl;
+	ret = (unsigned char *) map + current * (mappedMemorySize() / frame_maps);
+
+	frames++;
+
+	return (void *) ret;
+}
+
+void V4L::stopCapture()
+{
+	if (map != NULL)
+	{
+		struct timeval tv;
+		gettimeofday(&tv, NULL);
+		long long endtime = tv.tv_sec * 1000000 + tv.tv_usec;
+		double fps = (frames) / (((double) (endtime - starttime)) / 1000000);
+		munmap(map, mappedMemorySize());
+		map = NULL;
+		int enable = 0;
+		ioctl(getHandle(), VIDIOCCAPTURE, &enable);
+	}
+}
+
+int V4L::getFrequency()
+{
+	unsigned long current;
+	ioctl(fd, VIDIOCGFREQ, &current);
+	return (int) current;
+}
+
+/** Set the current frequency of the tuner.
+ 
+ \param	frequency	frequency to set
+ \return	the current tuned in frequency.
+ */
+
+bool V4L::setFrequency(int frequency)
+{
+	unsigned long val = (unsigned long) frequency & 0xffff;
+	return ioctl(fd, VIDIOCSFREQ, &val) != -1;
+}
+
+/** Get the signal of the current tuned in frequency.
+ */
+
+int V4L::getSignal()
+{
+	return current->getSignal();
+}
+
+void V4L::report()
+{
+	capability->report();
+
+	for (unsigned int index = 0; index < channels.size(); index++)
+	{
+		channels[index] ->report();
+	}
+}
+
+//V4l classes.
+
+
+extern void PErrorText(const char* error);
+
+int CVDecoder::input_pixfmt = PIX_FMT_RGBA32;
+
+#define STARTTIME { static int MaxTime=0;                         \
+	                static int MinTime=1000;                      \
+	                static int largecount=0;                      \
+	                int IntervalTime=0;                           \
+	                int64_t start_time=av_gettime();
+
+#define ENDTIME     IntervalTime = av_gettime()-start_time;       \
+	                if(IntervalTime>40000)                         \
+	                    largecount++;                             \
+	                if(MaxTime<IntervalTime)                      \
+	                    MaxTime=IntervalTime;                     \
+	                if(MinTime>IntervalTime)                      \
+	                    MinTime=IntervalTime;                     \
+	                printf("\nMaxTime=%d, MinTime=%d, largecount=%d, IntervalTime=%d\n", MaxTime, MinTime, largecount, IntervalTime);}
+
+//CVDecoder class.
+
+CVDecoder::CVDecoder()
+{
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_pOutFrame = 0;
+	m_bInit = false;
+
+	m_display = 0;
+	m_win = 0;
+	m_image = 0;
+
+}
+
+CVDecoder::~CVDecoder()
+{
+	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;
+	}
+
+	if (m_image)
+	{
+		XDestroyImage( m_image);
+		//m_image->f.destroy_image(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;
+	}
+
+}
+
+void CVDecoder::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;
+
+	/* over all max values */
+	// whatever they are good for
+	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)
+	{
+		/* alpha? */
+		// this seems to not reflect X's ignorance of alpha in its
+		// masks
+		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;
+	}
+}
+
+bool CVDecoder::CreateXImage(Drawable parent, int x, int y, int width,
+		int height)
+{
+	int screen_num;
+
+	GdkPixbuf *original_pixbuf;
+
+	gint original_width, original_height;
+	GdkColorspace original_color;
+	gboolean original_alpha;
+	gboolean pixbuf_has_alpha;
+	XSetWindowAttributes win_attr;
+	XImage *p_image = NULL;
+	if (!m_bInit)
+		return false;
+
+	CloseXImage();
+
+	m_imagemutex.Lock();
+
+	m_display = XOpenDisplay(NULL);
+	screen_num = DefaultScreen(m_display);
+	m_gc = DefaultGC(m_display, screen_num);
+	m_d = RootWindow(m_display, screen_num);
+
+	m_win = XCreateWindow(m_display, parent, x, y, width, height, 1,
+			XDefaultDepth(m_display, screen_num), InputOutput, CopyFromParent,
+			0, &win_attr);
+
+	if (gdk_pixbuf_new_from_file("pic/teacher2.bmp", NULL) == NULL)
+	{
+		XSetWindowBackgroundPixmap(m_display, m_win, ParentRelative);
+		XMapWindow(m_display, m_win);
+	}
+
+	else
+	{
+		original_pixbuf = gdk_pixbuf_new_from_file("pic/teacher2.bmp", NULL);
+		pixbuf_has_alpha = gdk_pixbuf_get_has_alpha(original_pixbuf);
+		original_color = gdk_pixbuf_get_colorspace(original_pixbuf);
+		original_alpha = gdk_pixbuf_get_has_alpha(original_pixbuf);
+		original_width = gdk_pixbuf_get_width(original_pixbuf);
+		original_height = gdk_pixbuf_get_height(original_pixbuf);
+		printf("original_alpha = %d\n", original_alpha);
+		printf("original_color = %d\n", original_color);
+		printf("original_width = %d\n", original_width);
+		printf("original_height = %d\n", original_height);
+		printf("n_channles = %d\n", gdk_pixbuf_get_n_channels(original_pixbuf));
+
+		Pixmap pixmap = XCreatePixmap(m_display, m_win, original_width,
+				original_height, XDefaultDepth(m_display, screen_num));
+		XSetWindowBackgroundPixmap(m_display, m_win, pixmap);
+
+		p_image = XGetImage(m_display, m_d, 0, 0, original_width,
+				original_height, AllPlanes, ZPixmap);
+		if (!p_image)
+		{
+			printf("error\n");
+			exit(10);
+		}
+
+		AVPicture pic_rgb24, pic_rgb32;
+		if (m_display && p_image && pixmap)
+		{
+			avpicture_fill(&pic_rgb32, (uint8_t*) p_image->data,
+					PIX_FMT_RGBA32, original_width, original_height);
+			avpicture_fill(&pic_rgb24, gdk_pixbuf_get_pixels(original_pixbuf),
+					PIX_FMT_RGB24, original_width, original_height);
+
+			if (img_convert(&pic_rgb32, PIX_FMT_RGBA32, &pic_rgb24,
+					PIX_FMT_RGB24, original_width, original_height) < 0)
+			{
+				printf("Error pixel format conversion");
+				return -1;
+			}
+
+			XPutImage(m_display, pixmap, m_gc, p_image, 0, 0, 0, 0,
+					original_width, original_height);
+
+		}
+
+		XMapWindow(m_display, m_win);
+		XFreePixmap(m_display, pixmap);
+		gdk_pixbuf_unref(original_pixbuf);
+		XDestroyImage(p_image);
+	}
+
+	m_image = XGetImage(m_display, m_d, 0, 0, m_width, m_height, AllPlanes,
+			ZPixmap);
+
+	if (!m_image)
+	{
+		printf("XGetImage error\n");
+		m_imagemutex.Unlock();
+		return false;
+	}
+
+	m_imagemutex.Unlock();
+	return true;
+}
+
+void CVDecoder::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();
+	return;
+}
+
+bool CVDecoder::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\n");
+		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
+	m_pCodecCtx->bit_rate = 512 * 1024;
+	// resolution must be a multiple of two 
+	m_pCodecCtx->width = m_width;
+	m_pCodecCtx->height = m_height;
+	// frames per second
+	m_pCodecCtx->frame_rate = V_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = V_CODEC_frame_rate_base;
+	// emit one intra frame every ten frames
+	m_pCodecCtx->gop_size = V_CODEC_gop_size;
+
+	m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+	m_pCodecCtx->extradata = malloc(V_De_ExtraHeaderSize);
+	if (m_pCodecCtx->extradata == 0)
+	{
+		return false;
+	}
+	m_pCodecCtx->extradata_size = V_De_ExtraHeaderSize;
+
+	// 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_bInit = true;
+	return true;
+}
+
+int CVDecoder::DecodeProcess(uint8_t *encodeddata_v,
+		const int encodeddatasize_v)
+{
+	bool isPaintPic;
+	int realsize, i;
+	int got_picture;
+
+	if (!m_bInit)
+	{
+		return -1;
+	}
+
+	int left = 0;
+	int len;
+
+	m_imagemutex.Lock();
+
+	for (i = 0;; i++)
+	{
+		if (encodeddatasize_v - i * V_De_INBUF_SIZE >= V_De_INBUF_SIZE)
+			realsize = V_De_INBUF_SIZE;
+		else
+			realsize = encodeddatasize_v - i * V_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 * V_De_INBUF_SIZE + left), realsize);
+			if (len < 0)
+			{
+				PErrorText("Error while decoding");
+				m_imagemutex.Unlock();
+				return -2;
+			}
+
+			if (m_image != 0)
+			{
+				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\n");
+						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");
+						return false;
+					}
+					break;
+				default:
+					PErrorText(
+							"xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting");
+					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;
+}
+
+void CVDecoder::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 CVDecoder::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
+	m_pCodecCtx->bit_rate = 512 * 1024;
+	// resolution must be a multiple of two 
+	m_pCodecCtx->width = m_width;
+	m_pCodecCtx->height = m_height;
+	// frames per second
+	m_pCodecCtx->frame_rate = V_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = V_CODEC_frame_rate_base;
+	// emit one intra frame every ten frames
+	m_pCodecCtx->gop_size = V_CODEC_gop_size;
+
+	m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+	m_pCodecCtx->extradata = malloc(V_De_ExtraHeaderSize);
+	if (m_pCodecCtx->extradata == 0)
+	{
+		return false;
+	}
+	m_pCodecCtx->extradata_size = V_De_ExtraHeaderSize;
+
+	// 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_bInit = true;
+	return true;
+
+}
+
+//CVideoReceiver class.
+
+CVideoReceiver::CVideoReceiver()
+{
+	m_bInit = false;
+}
+
+CVideoReceiver::~CVideoReceiver()
+{
+
+}
+
+bool CVideoReceiver::Init()
+{
+	if (m_bInit)
+		return m_bInit;
+
+	if (!m_vdecoder.Init(320, 240, CODEC_ID_MPEG4))
+	{
+		return false;
+	}
+
+	m_bInit = true;
+	return m_bInit;
+
+}
+
+bool CVideoReceiver::CreateXImage(Drawable parent, int x, int y, int width,
+		int height)
+{
+	bool ret;
+	ret = m_vdecoder.CreateXImage(parent, x, y, width, height);
+
+	return ret;
+}
+
+void CVideoReceiver::CloseXImage()
+{
+	m_vdecoder.CloseXImage();
+}
+
+#define MAX_PACKET_SIZE 10*1024
+int CVideoReceiver::Start(int nHostPort)
+{
+	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(nHostPort);
+	//CREATE THE SESSION
+	int status1 = Create(sessParams1, &transParams1);
+	if (status1)
+	{
+		//		ReportError(status1);
+		return -2; //unable to create the session
+	}
+
+	return 0;
+}
+
+void CVideoReceiver::Stop()
+{
+	Destroy();
+}
+
+void CVideoReceiver::ProcessFrame(unsigned char* framedata, int framelen)
+{
+	pVideo = (VideoHeader*) framedata;
+	if (pVideo->width != m_vdecoder.m_width || pVideo->height
+			!= m_vdecoder.m_height)
+	{
+		m_vdecoder.ResetCodec(pVideo->width, pVideo->height);
+	}
+	m_vdecoder.DecodeProcess(framedata + sizeof(VideoHeader), framelen
+			- sizeof(VideoHeader));
+}
+
+//CV4LVEncoder class.
+
+CV4LVEncoder::CV4LVEncoder()
+{
+	m_pFrameBuf = 0;
+	m_pFrame = 0;
+	m_pCodec = 0;
+	m_pCodecCtx = 0;
+	m_bInit = false;
+
+}
+
+CV4LVEncoder::~CV4LVEncoder()
+{
+	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;
+	}
+	m_bInit = false;
+
+}
+
+bool CV4LVEncoder::Init(int width, int height, enum CodecID nCodecID /*=CODEC_ID_MPEG4*/)
+{
+	m_bInit = false;
+	/*Init for encode*/
+	avcodec_init();
+	avcodec_register_all();
+	printf("1 good end\n");
+	if (m_pFrame)
+	{
+		free( m_pFrame);
+		m_pFrame = 0;
+	}
+	m_pFrame = avcodec_alloc_frame();
+	if (m_pFrame == 0)
+	{
+		return false;
+	}
+
+	/* find the video encoder */
+	m_pCodec = avcodec_find_encoder(nCodecID);
+	if (!m_pCodec)
+	{
+		PErrorText("codec not found");
+
+		printf("\ncodec not found\n");
+		return false;
+	}
+
+	if (m_pCodecCtx)
+	{
+		avcodec_close( m_pCodecCtx);
+		m_pCodecCtx = 0;
+	}
+	printf("avcodec_find_encoder OK %d\n", nCodecID);
+
+	m_pCodecCtx = avcodec_alloc_context();
+	/* resolution must be a multiple of two */
+	m_pCodecCtx->width = width;
+	m_pCodecCtx->height = height;
+	/* frames per second */
+	m_pCodecCtx->frame_rate = V_CODEC_framerate;
+	m_pCodecCtx->frame_rate_base = V_CODEC_frame_rate_base;
+
+	m_pCodecCtx->bit_rate = 512 * 1024; //1128kbps->512kbps
+	m_pCodecCtx->gop_size = V_CODEC_gop_size; /* emit one intra frame every ten frames */
+	m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+	m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+
+	/* open it */
+	printf("avcodec_open start\n");
+
+	if (avcodec_open(m_pCodecCtx, m_pCodec) < 0)
+	{
+		PErrorText("could not open codec");
+		return false;
+	}
+	printf("avcodec_open OK\n");
+
+	//malloc outbuf.
+	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 CV4LVEncoder::EncodeProcess(char *frameaddress, uint8_t *pOutBuf,
+		int nOutsize)
+{
+
+	if (!m_bInit)
+		return -1;
+
+	if (nOutsize < V_En_OutBufSize)
+		return -2;
+
+	avpicture_fill(&m_pic_rgb, (uint8_t *) frameaddress, PIX_FMT_BGR24,
+			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,
+			PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height) < 0)
+	{
+		fprintf(
+				stderr,
+				"xtoffmpeg.XImageToFFMPEG(): pixel format conversion not handled ... aborting\n");
+		return -3;
+	}
+
+	m_VideoHeader.width = m_pCodecCtx->width;
+	m_VideoHeader.height = m_pCodecCtx->height;
+	memcpy((char *) pOutBuf, &m_VideoHeader, sizeof(VideoHeader));
+
+	int iii = avcodec_encode_video(m_pCodecCtx, pOutBuf + sizeof(VideoHeader),
+			nOutsize, m_pFrame);
+
+	if (iii <= 0)
+		return -4;
+
+	return iii + sizeof(VideoHeader);
+}
+
+bool CV4LVEncoder::GetCapSize(int &width, int &height)
+{
+	if (!m_bInit)
+		return false;
+
+	width = m_pCodecCtx->width;
+	height = m_pCodecCtx->height;
+
+	return true;
+}
+
+//CV4LStuVideoSender class.
+
+CV4LStuVideoSender::CV4LStuVideoSender()
+{
+	stop = false;
+	m_bInit = 0;
+
+	m_pOutBuf = 0;
+	m_mode = ModeNone;
+	m_pV4Ldev = 0;
+
+	if (!m_initmutex.IsInitialized())
+	{
+		m_initmutex.Init();
+	}
+
+	m_display = 0;
+	m_win = 0;
+	m_d = 0;
+	m_image = 0;
+}
+
+CV4LStuVideoSender::~CV4LStuVideoSender()
+{
+	//first stop thread, because  m_pOutBuf is being used by Thread();
+	Stop();
+
+	//free buffer.
+	if (m_pOutBuf != 0)
+	{
+		free( m_pOutBuf);
+		m_pOutBuf = 0;
+	}
+
+	// for image
+	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;
+	}
+
+	CloseVideo();
+}
+
+bool CV4LStuVideoSender::Init(int nHostPort)
+{
+	m_initmutex.Lock();
+	m_bInit = false;
+
+	if (!m_imagemutex.IsInitialized())
+	{
+		if (m_imagemutex.Init() < 0)
+		{
+			m_initmutex.Unlock();
+			return false;
+		}
+	}
+
+	if (!OpenVideo())
+	{
+		m_initmutex.Unlock();
+		return false;
+	}
+
+	//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(nHostPort);
+	//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);
+
+	if (m_pOutBuf == 0)
+	{
+		m_pOutBuf = (uint8_t*) malloc(CV4LVEncoder::V_En_OutBufSize);
+		if (m_pOutBuf == 0)
+		{
+			m_initmutex.Unlock();
+			return false;
+		}
+
+	}
+	//Init sencoder.
+	if (!m_vencoder.Init(VideoWidth, VideoHeight, CODEC_ID_MPEG4))
+	{
+		m_initmutex.Unlock();
+		return false;
+	}
+
+	if (!m_modemutex.IsInitialized())
+	{
+		if (m_modemutex.Init() < 0)
+		{
+			m_initmutex.Unlock();
+			return false;
+		}
+
+	}
+
+	m_bInit = true;
+	m_initmutex.Unlock();
+	return true;
+}
+
+bool CV4LStuVideoSender::OpenVideo()
+{
+	CloseVideo();
+
+	m_pV4Ldev = new V4L();
+
+	if (m_pV4Ldev == 0)
+		return false;
+
+	m_pV4Ldev->setInfo("/dev/video0", "PAL", "", 0);
+
+	if (!m_pV4Ldev->openDevice())
+	{
+		return false;
+	}
+
+	if (!m_pV4Ldev->initialiseCapture(VIDEO_PALETTE_RGB24))
+	{
+		return false;
+	}
+
+	return true;
+}
+
+void CV4LStuVideoSender::CloseVideo()
+{
+	if (m_pV4Ldev != 0)
+	{
+		delete m_pV4Ldev;
+		m_pV4Ldev = 0;
+	}
+}
+
+bool CV4LStuVideoSender::IsInitialized()
+{
+	bool b;
+
+	m_initmutex.Lock();
+	b = m_bInit;
+	m_initmutex.Unlock();
+
+	return b;
+}
+
+bool CV4LStuVideoSender::CreateXImage(Drawable parent, int x, int y, int width,
+		int height)
+{
+
+	int screen_num;
+	XSetWindowAttributes win_attr;
+	GdkPixbuf *original_pixbuf;
+	//GdkPixbuf *scaled_pixbuf;
+	gint original_width, original_height;
+	GdkColorspace original_color;
+	gboolean original_alpha;
+	gboolean pixbuf_has_alpha;
+
+	XImage *p_image = NULL;
+	if (!m_bInit)
+		return false;
+
+	CloseXImage();
+
+	m_imagemutex.Lock();
+
+	m_display = XOpenDisplay(NULL);
+	screen_num = DefaultScreen(m_display);
+	m_gc = DefaultGC(m_display, screen_num);
+	m_d = RootWindow(m_display, screen_num);
+
+	m_win = XCreateWindow(m_display, parent, x, y, width, height, 1,
+			XDefaultDepth(m_display, screen_num), InputOutput, CopyFromParent,
+			0, &win_attr);
+
+	if (gdk_pixbuf_new_from_file("pic/teacher2.bmp", NULL) == NULL)
+	{
+		XSetWindowBackgroundPixmap(m_display, m_win, ParentRelative);
+
+		XMapWindow(m_display, m_win);
+	}
+
+	else
+	{
+		original_pixbuf = gdk_pixbuf_new_from_file("pic/teacher2.bmp", NULL);
+		pixbuf_has_alpha = gdk_pixbuf_get_has_alpha(original_pixbuf);
+		original_color = gdk_pixbuf_get_colorspace(original_pixbuf);
+		original_alpha = gdk_pixbuf_get_has_alpha(original_pixbuf);
+		original_width = gdk_pixbuf_get_width(original_pixbuf);
+		original_height = gdk_pixbuf_get_height(original_pixbuf);
+		printf("original_alpha = %d\n", original_alpha);
+		printf("original_color = %d\n", original_color);
+		printf("original_width = %d\n", original_width);
+		printf("original_height = %d\n", original_height);
+		printf("n_channles = %d\n", gdk_pixbuf_get_n_channels(original_pixbuf));
+
+		Pixmap pixmap = XCreatePixmap(m_display, m_win, original_width,
+				original_height, XDefaultDepth(m_display, screen_num));
+		XSetWindowBackgroundPixmap(m_display, m_win, pixmap);
+
+		p_image = XGetImage(m_display, m_d, 0, 0, original_width, original_height, AllPlanes, ZPixmap);
+		if (!p_image)
+		{
+			printf("error\n");
+			exit(10);
+		}
+
+		AVPicture pic_rgb24, pic_rgb32;
+		if (m_display && p_image && pixmap)
+		{
+			avpicture_fill(&pic_rgb32, (uint8_t*) p_image->data,
+					PIX_FMT_RGBA32, original_width, original_height);
+			avpicture_fill(&pic_rgb24, gdk_pixbuf_get_pixels(original_pixbuf),
+					PIX_FMT_RGB24, original_width, original_height);
+
+			if (img_convert(&pic_rgb32, PIX_FMT_RGBA32, &pic_rgb24,
+					PIX_FMT_RGB24, original_width, original_height) < 0)
+			{
+				printf("Error pixel format conversion");
+				return -1;
+			}
+
+			XPutImage(m_display, pixmap, m_gc, p_image, 0, 0, 0, 0,
+					original_width, original_height);
+
+		}
+
+		XMapWindow(m_display, m_win);
+		XFreePixmap(m_display, pixmap);
+		gdk_pixbuf_unref(original_pixbuf);
+		XDestroyImage(p_image);
+	}
+	int imagewidth, imageheight;
+	m_vencoder.GetCapSize(imagewidth, imageheight);
+
+	m_image = XGetImage(m_display, m_d, 0, 0, imagewidth, imageheight,
+			AllPlanes, ZPixmap);
+	if (!m_image)
+	{
+		PErrorText("GetImage error");
+		m_imagemutex.Unlock();
+		return false;
+	}
+
+	m_imagemutex.Unlock();
+	return true;
+
+}
+
+void CV4LStuVideoSender::CloseXImage()
+{
+
+	if (!IsInitialized())
+		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 CV4LStuVideoSender::Playback(uint8_t* videodata)
+{
+	AVPicture pic_rgb24, pic_rgb32;
+	int width, height;
+
+	if (!IsInitialized())
+		return;
+
+	m_vencoder.GetCapSize(width, height);
+
+	m_imagemutex.Lock();
+
+	if (m_display && m_image && m_win)
+	{
+
+		avpicture_fill(&pic_rgb32, (uint8_t*) m_image->data,
+				CVDecoder::input_pixfmt, width, height);
+		avpicture_fill(&pic_rgb24, videodata, PIX_FMT_BGR24, width, height);
+
+		if (img_convert(&pic_rgb32, CVDecoder::input_pixfmt, &pic_rgb24,
+				PIX_FMT_BGR24, width, height) < 0)
+		{
+			PErrorText("Error pixel format conversion");
+			m_imagemutex.Unlock();
+			return;
+		}
+
+		XPutImage(m_display, m_win, m_gc, m_image, 0, 0, 0, 0, width, height);
+	}
+
+	m_imagemutex.Unlock();
+	return;
+}
+
+int CV4LStuVideoSender::Start()
+{
+
+	if (!IsInitialized())
+		return -1;
+
+	if (JThread::IsRunning())
+		return 0;
+
+	if (!stopmutex.IsInitialized())
+	{
+		if (stopmutex.Init() < 0)
+			return -2;
+	}
+
+	stop = false;
+
+	if (JThread::Start() < 0)
+	{
+		return -6;
+	}
+
+	return 0;
+}
+
+void CV4LStuVideoSender::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;
+
+}
+
+void CV4LStuVideoSender::SetMode(V4LSTUVIDEO_SEND_MODE mode)
+{
+
+	if (!IsInitialized())
+		return;
+
+	if (mode == ModeCapture || mode == ModeTransmit || mode == ModeNone)
+	{
+
+		m_modemutex.Lock();
+		m_mode = mode;
+		m_modemutex.Unlock();
+	}
+
+}
+
+void *CV4LStuVideoSender::Thread()
+{
+	char * data;
+	int OutBufSzie;
+	int status;
+
+	JThread::ThreadStarted();
+
+	bool stopthread;
+	V4LSTUVIDEO_SEND_MODE mode;
+
+	stopmutex.Lock();
+	stopthread = stop;
+	stopmutex.Unlock();
+
+	int64_t pre_time, cur_time;
+	useconds_t delay, delay1;
+	pre_time = av_gettime();
+	if (m_vencoder.m_pCodecCtx->frame_rate != 0)
+	{
+		if (m_vencoder.m_pCodecCtx->frame_rate_base != 0)
+			delay1 = 1000000 * m_vencoder.m_pCodecCtx->frame_rate_base
+					/ m_vencoder.m_pCodecCtx->frame_rate;
+		else
+			delay1 = 1000000 / m_vencoder.m_pCodecCtx->frame_rate;
+	}
+	else
+	{
+		delay1 = 62500;
+	}
+
+	// for utility rate of CPU
+	cur_time = pre_time = av_gettime();
+	pre_time -= delay1;
+
+	while (!stopthread)
+	{
+		delay = cur_time - pre_time;
+		if (delay < delay1)
+		{
+			usleep(delay1 - delay);
+		}
+		pre_time = av_gettime();
+
+		m_modemutex.Lock();
+		mode = m_mode;
+		m_modemutex.Unlock();
+
+		if (mode == ModeNone)
+		{
+			stopmutex.Lock();
+			stopthread = stop;
+			stopmutex.Unlock();
+
+			cur_time = av_gettime();
+			continue;
+		}
+
+		if ((status = Capture((uint8_t**) &data)) < 0)
+		{
+			printf("\nvideo: capture vital error.");
+			stopthread = true;
+			continue;
+		}
+		else
+		{
+			if (mode == ModeCapture || mode == ModeTransmit)
+			{
+				Playback((uint8_t*) data);
+				if (mode == ModeCapture)
+				{
+					stopmutex.Lock();
+					stopthread = stop;
+					stopmutex.Unlock();
+
+					cur_time = av_gettime();
+					continue;
+				}
+			}
+
+			OutBufSzie = CV4LVEncoder::V_En_OutBufSize;
+			if ((status = m_vencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie))
+					< 0)
+			{
+				printf("\nvideo: encode vital error.");
+				stopthread = true;
+				continue;
+			}
+			else
+			{
+				if (status > 0 && mode == ModeTransmit)
+				{
+					m_fecrtpsession.SendFECPacket(m_pOutBuf, status, 10000);
+				}
+			}
+		}
+
+		cur_time = av_gettime();
+	}
+
+	stopmutex.Lock();
+	stopthread = stop;
+	stopmutex.Unlock();
+
+	printf("\nvideo capture thread stoped.\n");
+	return 0;
+}
+
+bool CV4LStuVideoSender::AddDestination(const RTPIPv4Address &des)
+{
+
+	if (!IsInitialized())
+		return false;
+
+	if (m_fecrtpsession.AddDestination(des) < 0)
+		return false;
+
+	return true;
+}
+
+void CV4LStuVideoSender::ClearDestinations()
+{
+
+	if (!IsInitialized())
+		return;
+
+	m_fecrtpsession.ClearDestinations();
+}
+
+int CV4LStuVideoSender::Capture(uint8_t** data)
+{
+	*data = (uint8_t*) m_pV4Ldev->getNextFrame();
+	return 0;
+}

Added: incubator/bluesky/trunk/RealClass/Student/src/en_de_video.h
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Student/src/en_de_video.h?rev=819923&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Student/src/en_de_video.h (added)
+++ incubator/bluesky/trunk/RealClass/Student/src/en_de_video.h Tue Sep 29 13:10:30 2009
@@ -0,0 +1,390 @@
+//en_de_video.h
+
+// rtp
+#include "fecrtpsession.h"
+
+#ifndef _KINO_V4L_H
+#define _KINO_V4L_H
+
+#include <vector>
+#include <deque>
+using std::vector;
+using std::deque;
+
+#include <string>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#define _DEVICE_H_
+#define _LINUX_TIME_H
+#include <linux/videodev.h>
+
+class V4LStruct
+{
+public:
+	virtual ~V4LStruct()
+	{
+	}
+	virtual void *getStruct() = 0;
+};
+
+class V4LDevice
+{
+public:
+	virtual ~V4LDevice()
+	{
+	}
+	virtual int getHandle() = 0;
+	bool request(int req, V4LStruct *v4l);
+	bool request(int req, void *addr);
+};
+
+class V4LCapability: public V4LStruct
+{
+private:
+	struct video_capability capability;
+
+public:
+	V4LCapability(V4LDevice *device);
+	virtual ~V4LCapability();
+	void *getStruct();
+	char *getName();
+	int getNumberOfChannels();
+	int getNumberOfAudioDevices();
+	int getMinWidth();
+	int getMinHeight();
+	int getMaxWidth();
+	int getMaxHeight();
+	bool canCapture();
+	bool hasTuner();
+	bool hasChromakey();
+	bool hasClipping();
+	bool hasOverwrite();
+	bool hasScaling();
+	bool isMonochrome();
+	bool canSubCapture();
+	void report();
+};
+
+class V4LTuner: public V4LStruct
+{
+private:
+	V4LDevice *device;
+	struct video_tuner tuner;
+
+public:
+	V4LTuner(V4LDevice *device, int index);
+	void *getStruct();
+	void report();
+	int getRangeLow();
+	void setRangeLow(int low);
+	int getRangeHigh();
+	void setRangeHigh(int high);
+	int getFlags();
+	void setFlags(int flags);
+	int getMode();
+	void setMode(int mode);
+	int getSignal();
+};
+
+class V4LChannel: public V4LStruct
+{
+private:
+	V4LDevice *device;
+	struct video_channel channel;
+	vector<V4LTuner *> tuners;
+	V4LTuner *current;
+
+public:
+	V4LChannel(V4LDevice *device, int index);
+	virtual ~V4LChannel();
+	void *getStruct();
+	char *getName();
+	bool setTuner(unsigned int index);
+	unsigned int getNumberOfTuners();
+	V4LTuner *getTuner(unsigned int index);
+	int getSignal();
+	void report();
+};
+
+class V4L: public V4LDevice
+{
+
+private:
+	enum V4LPARA
+	{
+		VideoWidth = 320, VideoHeight = 240
+	};
+
+private:
+	int fd;
+	vector<V4LChannel *> channels;
+	V4LChannel *current;
+	int width;
+	int height;
+	void *map;
+	struct video_mmap frame[32];
+	int frame_maps;
+	int frame_next;
+	int size;
+	int frames;
+	long long starttime;
+	char *device;
+	char *input;
+	int sample;
+	int fps;
+public:
+	char *audio;
+	V4LCapability *capability;
+	V4L();
+	virtual ~V4L();
+	void setInfo(char *device, char *input, char *audio, int sample);
+	bool openDevice();
+	bool deviceAvailable();
+	int getHandle();
+	unsigned int getNumberOfChannels();
+	V4LChannel *getChannel(unsigned int);
+	bool setChannel(unsigned int channel);
+	unsigned int getNumberOfTuners();
+	V4LTuner *getTuner(unsigned int);
+	bool setTuner(unsigned int tuner);
+	bool setCaptureResolution(int width, int height);
+	int getWidth();
+	int getHeight();
+	void startAudio();
+	void stopAudio();
+	bool initialiseCapture(int format);
+	void *getNextFrame();
+	void stopCapture();
+	int getFrequency();
+	bool setFrequency(int frequency);
+	int getSignal();
+	void report();
+	int mappedMemorySize(bool init = false);
+	int frameSample;
+};
+
+#endif
+
+// 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>
+// 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"
+#include "en_de_screen.h"
+
+#if !defined(_EN_DE_VIDEO_H__INCLUDED_)
+#define _EN_DE_VIDEO_H__INCLUDED_
+
+typedef void (*VideoPlayback)(uint8_t* videodata, int width, int height);
+
+typedef struct VideoHeader
+{
+	int width;
+	int height;
+} VideoHeader;
+
+//Video decoder.
+class CVDecoder
+{
+	friend class CVideoReceiver;
+
+private:
+	enum VDECODERBUFSIZE
+	{
+		V_De_ExtraHeaderSize = 10000,
+		V_De_SDLBufSize = 512 * 1024,
+		V_De_INBUF_SIZE = 1024
+	};
+public:
+	CVDecoder();
+	virtual ~CVDecoder();
+public:
+	int DecodeProcess(uint8_t *encodeddata_v, const int encodeddatasize_v);
+	bool Init(int width, int height, enum CodecID nCodecID);
+	enum VIDEO_CODEC_PARA
+	{
+		V_CODEC_width = 320,
+		V_CODEC_height = 240,
+		V_CODEC_framerate = 25,
+		V_CODEC_frame_rate_base = 1,
+		V_CODEC_gop_size = 8,
+		V_CODEC_max_b_frames = 1
+	};
+
+public:
+	bool CreateXImage(Drawable parent, int x, int y, int width, int height);
+	void CloseXImage();
+	void GetColorInfo(XImage *image, ColorInfo *ci /* return struct */);
+
+private:
+
+	void CloseCodec();
+	bool ResetCodec(const int width, const int height);
+	bool m_bInit;
+	AVCodec *m_pCodec;
+	AVCodecContext *m_pCodecCtx;
+	AVFrame *m_pOutFrame;
+	AVPicture pic_rgb;
+	int m_width;
+	int m_height;
+	//for ximage
+	Display *m_display;
+	GC m_gc;
+	Window m_d;
+
+	Window m_win;
+	XImage *m_image;
+	JMutex m_imagemutex;
+	ColorInfo c_info;
+public:
+	static int input_pixfmt;
+
+};
+
+
+class CVideoReceiver: public CFECRtpSession
+{
+public:
+	VideoHeader* pVideo;
+	CVideoReceiver();
+	virtual ~CVideoReceiver();
+
+	bool Init();
+	int Start(int nHostPort);
+	void Stop();
+
+public:
+	bool CreateXImage(Drawable parent, int x, int y, int width, int height);
+	void CloseXImage();
+
+private:
+	virtual void ProcessFrame(unsigned char* framedata, int framelen);
+
+private:
+	bool m_bInit;
+	CVDecoder m_vdecoder;
+};
+
+class CV4LVEncoder
+{
+	friend class CV4LStuVideoSender;
+
+private:
+	enum V4L_VENCODE_BUFSIZE
+	{
+		V_En_OutBufSize = 400 * 1024
+	};
+	enum V4L_VIDEO_CODEC_PARA
+	{
+		V_CODEC_framerate = 16,
+		V_CODEC_frame_rate_base = 1,
+		V_CODEC_gop_size = 12,
+		V_CODEC_max_b_frames = 1
+	};
+public:
+	bool GetCapSize(int &width, int &height);
+	int EncodeProcess(char * frameaddress, uint8_t * pOutBuf, int nOutsize);
+	bool Init(int width, int height, enum CodecID nCodecID = CODEC_ID_MPEG4);
+	CV4LVEncoder();
+	virtual ~CV4LVEncoder();
+
+private:
+	bool m_bInit;
+
+	AVPicture m_pic_rgb;
+	uint8_t *m_pFrameBuf;
+	AVFrame *m_pFrame;
+	AVCodec *m_pCodec;
+	AVCodecContext *m_pCodecCtx;
+	VideoHeader m_VideoHeader;
+};
+
+// V4L video for student sender.
+class CV4LStuVideoSender: private JThread
+{
+public:
+	enum V4LSTUVIDEO_SEND_MODE
+	{
+		ModeNone = 0, ModeCapture = 1, ModeTransmit = 2
+	};
+private:
+	enum V4LSTUVIDEO_SEND_PARA
+	{
+		VideoWidth = 320, VideoHeight = 240
+	};
+public:
+	CV4LStuVideoSender();
+	~CV4LStuVideoSender();
+	bool Init(int nHostPort);
+	bool AddDestination(const RTPIPv4Address &des);
+	void ClearDestinations();
+	int Start();
+	void Stop();
+	void SetMode(V4LSTUVIDEO_SEND_MODE mode);
+	bool CreateXImage(Drawable parent, int x, int y, int width, int height);
+	void CloseXImage();
+	bool IsInitialized();
+
+private:
+	bool OpenVideo();
+	void CloseVideo();
+	int Capture(uint8_t** data);
+	bool IsHavedV4LVideo();
+
+	void Playback(uint8_t* videodata);
+	void *Thread();
+	bool stop;
+	JMutex stopmutex;
+private:
+	CV4LVEncoder m_vencoder;
+	uint8_t *m_pOutBuf;
+	bool m_bInit;
+	JMutex m_initmutex;
+	V4LSTUVIDEO_SEND_MODE m_mode;
+	JMutex m_modemutex;
+
+	//for fec transmmiosn.
+	CFECRtpSession m_fecrtpsession;
+	//for ximage
+	Window m_d;
+
+	Display *m_display;
+	GC m_gc;
+	Window m_win;
+	XImage *m_image;
+	JMutex m_imagemutex;
+	ColorInfo c_info;
+	
+	V4L *m_pV4Ldev;
+
+};
+
+#endif // !defined(_EN_DE_VIDEO_H__INCLUDED_)

Added: incubator/bluesky/trunk/RealClass/Student/src/errormessage.h
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Student/src/errormessage.h?rev=819923&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Student/src/errormessage.h (added)
+++ incubator/bluesky/trunk/RealClass/Student/src/errormessage.h Tue Sep 29 13:10:30 2009
@@ -0,0 +1,124 @@
+
+#define  screensize_error "Screen config failure "
+
+#define  screensize_errorms "\n\nPlease set screen as 1024×768 "
+
+#define  getIP_error "Can't obtain local IP!"
+
+#define  getIP_errorms "\n\nManual configure please!"
+
+#define  usename_error "Logon failure"
+
+#define  usename_errorms "\n\nNo user name!"
+
+#define  usename_error1 "Logon failure"
+
+#define  usename_error1ms "User name too long!\n No more than 10 Chinese characters \nor 30 English characters"
+
+#define  config_error1 "Receive port error!"
+
+#define  config_error1ms "\nPlease set the port as an \neven number greater than 1024."
+
+#define  load_error1 "Logon server failure!"
+
+#define  load_error1ms "\nCan't logon server.\nCheck the configuration please."
+
+#define  load_error2 "Can't logon system."
+
+#define  load_error2ms "\nUser name have been used.\nChange another one please!"
+
+#define  load_error3 "Can't logon system."
+
+#define  load_error3ms "\n\nStudents client overload."
+
+#define  load_error4 "Can't logon system."
+
+#define  load_error4ms "\n\nNetwork error.Logon again!"
+
+#define  getclasslist_error "Obtain group message error."
+
+#define  getclasslist_errorms "\nJoin class later \nor logon system again."
+
+#define  addclass_error "Join class failure."
+
+#define  addclass_errorms "\n\nSelect class again please."
+
+#define  addclass_error1 "Join class failure."
+
+#define  addclass_error1ms "\nSorry!Too many students \njoin this class.Try later."
+
+#define  exitclass_error " "
+
+#define  exitclass_errorms "Quit class failure,try again!"
+
+#define  focus_error1 "Apply for focus failure."
+
+#define  focus_error1ms "\nFocus already exist.\nTry later."
+
+#define  focus_error2 "Apply for focus failure."
+
+#define  focus_error2ms "\nTeacher client deny.\nTry later."
+
+#define  killfocus_error "Kill focus failure."
+
+#define  killfocus_errorms "\nCan't get teacher's permit.\nTry later."
+
+#define  getstulist_error "Can't obtain the students list.\nTry again."
+
+#define  port_error "Receive port configuration error."
+
+#define  port_errorms "\nPlease set the port as an \neven number greater than 1024."
+
+//#define  screensize_error "   屏幕设置失败 "
+//#define  screensize_errorms "\n\n 请将屏幕设置为1024×768 "
+
+//#define  getIP_error "     		无法自动获取本机IP地址"
+//#define  getIP_errorms "\n\n请点击高级按钮手动设置" 
+
+//#define  usename_error     "     登陆失败! "
+//#define usename_errorms  "\n\n用户名不能为空"
+
+//#define usename_error1 "     登陆失败! "
+//#define usename_error1ms "\n\n用户名过长,请输入少于10个汉字或者30个英文字符"
+
+ 
+ //#define config_error1 "     接收端口设置错误    "
+ //#define config_error1ms " \n\n请将接收基准端口设为大于1024的偶数 "
+ 
+//#define load_error1  "        			登录失败!     "  
+//#define load_error1ms "\n\n无法连接课堂服务中心,请修改配置参数是否正确"
+
+//#define load_error2  "      无法登陆系统!      "
+//#define  load_error2ms   " \n\n该用户该用户已经存在,请更换用户名 "
+
+//#define  load_error3    "		无法登陆系统!"
+//#define  load_error3ms  "\n\n听课端人数已满"
+
+//#define  load_error4    " 		无法登陆系统!"
+//#define  load_error4ms  "\n\n网络出现故障,请重新登陆"
+
+//#define  getclasslist_error   "		获取组消息失败"
+//#define getclasslist_errorms "\n\n重新加入课堂或者稍候重新登陆系统"
+
+//#define addclass_error    "				加入课堂失败"
+//#define  addclass_errorms   "\n\n请重新选择课堂"
+
+//#define addclass_error1 "				加入课堂失败"
+//#define addclass_error1ms "\n\n对不起,该课堂人数已满,请稍候再试"
+
+//#define  exitclass_error "  "
+//#define  exitclass_errorms   "		退出课堂失败,请重试		"
+
+//#define focus_error1 "  		申请焦点失败"
+//#define  focus_error1ms"\n\n已经存在一个焦点,请稍候再试"
+
+//#define  focus_error2  "					申请焦点失败"
+//#define  focus_error2ms "\n\n教师端没有同意您的申请,请稍候再试"
+
+//#define  killfocus_error  "					撤消焦点失败"
+//#define  killfocus_errorms "\n\n您暂时未得到老师的同意撤消焦点,请稍候再试"
+
+//#define  getstulist_error   "无法得到学生列表,请重试"
+
+//#define port_error " 基准端口设置错误"
+//#define port_errorms " \n\n请将基准端口设置为大于1024的偶数"

Added: incubator/bluesky/trunk/RealClass/Student/src/fecrtpsession.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/trunk/RealClass/Student/src/fecrtpsession.cpp?rev=819923&view=auto
==============================================================================
--- incubator/bluesky/trunk/RealClass/Student/src/fecrtpsession.cpp (added)
+++ incubator/bluesky/trunk/RealClass/Student/src/fecrtpsession.cpp Tue Sep 29 13:10:30 2009
@@ -0,0 +1,1429 @@
+// fecrtpsession.cpp: implementation of the CFECRtpSession class.
+
+#include <unistd.h>
+#include "fecrtpsession.h"
+
+#ifndef GF_BITS
+#define GF_BITS  8	
+#endif
+
+#define u_char unsigned char
+#define u_short unsigned short
+#define u_long unsigned long
+
+#define bcmp(a,b,n) memcmp(a,b,n)
+#define bcopy(s, d, siz)        memcpy((d), (s), (siz))
+#define bzero(d, siz)   memset((d), '\0', (siz))
+
+#define DEB(x)
+#define DDB(x) x
+
+#if (GF_BITS < 2  && GF_BITS >16)
+#error "GF_BITS must be 2 .. 16"
+#endif
+
+#if (GF_BITS <= 8)
+typedef unsigned char gf;
+#else
+typedef unsigned short gf;
+#endif
+
+#define	GF_SIZE ((1 << GF_BITS) - 1)	/* powers of \alpha */
+
+static char *allPp[] =
+{ /* GF_BITS	polynomial		*/
+0, /*  0	no code			*/
+0, /*  1	no code			*/
+"111", /*  2	1+x+x^2			*/
+"1101", /*  3	1+x+x^3			*/
+"11001", /*  4	1+x+x^4			*/
+"101001", /*  5	1+x^2+x^5		*/
+"1100001", /*  6	1+x+x^6			*/
+"10010001", /*  7	1 + x^3 + x^7		*/
+"101110001", /*  8	1+x^2+x^3+x^4+x^8	*/
+"1000100001", /*  9	1+x^4+x^9		*/
+"10010000001", /* 10	1+x^3+x^10		*/
+"101000000001", /* 11	1+x^2+x^11		*/
+"1100101000001", /* 12	1+x+x^4+x^6+x^12	*/
+"11011000000001", /* 13	1+x+x^3+x^4+x^13	*/
+"110000100010001", /* 14	1+x+x^6+x^10+x^14	*/
+"1100000000000001", /* 15	1+x+x^15		*/
+"11010000000010001" /* 16	1+x+x^3+x^12+x^16	*/
+};
+
+static gf gf_exp[2 * GF_SIZE]; /* index->poly form conversion table	*/
+static int gf_log[GF_SIZE + 1]; /* Poly->index form conversion table	*/
+static gf inverse[GF_SIZE + 1]; /* inverse of field elem.		*/
+
+int modnn(int x)
+{
+	while (x >= GF_SIZE)
+	{
+		x -= GF_SIZE;
+		x = (x >> GF_BITS) + (x & GF_SIZE);
+	}
+	return x;
+}
+
+#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;}
+
+#if (GF_BITS <= 8)
+static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1];
+
+#define gf_mul(x,y) gf_mul_table[x][y]
+
+#define USE_GF_MULC register gf * __gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
+#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
+
+static void init_mul_table()
+{
+	int i, j;
+	for (i = 0; i < GF_SIZE + 1; i++)
+		for (j = 0; j < GF_SIZE + 1; j++)
+			gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j])];
+
+	for (j = 0; j < GF_SIZE + 1; j++)
+		gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
+}
+#else	
+static inline gf gf_mul(gf x,gf y)
+{
+	if ( (x) == 0 || (y)==0 ) return 0;
+
+	return gf_exp[gf_log[x] + gf_log[y] ];
+}
+#define init_mul_table()
+
+#define USE_GF_MULC register gf * __gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = &gf_exp[ gf_log[c] ]
+#define GF_ADDMULC(dst, x) { if (x) dst ^= __gf_mulc_[ gf_log[x] ] ; }
+#endif
+
+static void* my_malloc(int sz, char *err_string)
+{
+	void *p = malloc(sz);
+	if (p == 0)
+	{
+	}
+	return p;
+}
+
+#define NEW_GF_MATRIX(rows, cols) (gf *)my_malloc(rows * cols * sizeof(gf), " ## __LINE__ ## " )
+
+static void generate_gf(void)
+{
+	int i;
+	gf mask;
+	char *Pp = allPp[GF_BITS];
+
+	mask = 1; /* x ** 0 = 1 */
+	gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */
+
+	for (i = 0; i < GF_BITS; i++, mask <<= 1)
+	{
+		gf_exp[i] = mask;
+		gf_log[gf_exp[i]] = i;
+		if (Pp[i] == '1')
+			gf_exp[GF_BITS] ^= mask;
+	}
+	gf_log[gf_exp[GF_BITS]] = GF_BITS;
+
+	mask = 1 << (GF_BITS - 1);
+	for (i = GF_BITS + 1; i < GF_SIZE; i++)
+	{
+		if (gf_exp[i - 1] >= mask)
+			gf_exp[i] = gf_exp[GF_BITS] ^ ((gf_exp[i - 1] ^ mask) << 1);
+		else
+			gf_exp[i] = gf_exp[i - 1] << 1;
+		gf_log[gf_exp[i]] = i;
+	}
+
+	gf_log[0] = GF_SIZE;
+
+	for (i = 0; i < GF_SIZE; i++)
+		gf_exp[i + GF_SIZE] = gf_exp[i];
+
+	inverse[0] = 0;
+	inverse[1] = 1;
+	for (i = 2; i <= GF_SIZE; i++)
+		inverse[i] = gf_exp[GF_SIZE - gf_log[i]];
+}
+
+#define addmul(dst, src, c, sz) \
+    if (c != 0) addmul1(dst, src, c, sz)
+
+#define UNROLL 16 /* 1, 4, 8, 16 */
+static void addmul1(gf *dst1, gf *src1, gf c, int sz)
+{
+	USE_GF_MULC ;
+	register gf *dst = dst1, *src = src1;
+	gf *lim = &dst[sz - UNROLL + 1];
+
+	GF_MULC0(c);
+
+#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */
+	for (; dst < lim; dst += UNROLL, src += UNROLL)
+	{
+		GF_ADDMULC( dst[0] , src[0] );
+		GF_ADDMULC( dst[1] , src[1] );
+		GF_ADDMULC( dst[2] , src[2] );
+		GF_ADDMULC( dst[3] , src[3] );
+#if (UNROLL > 4)
+		GF_ADDMULC( dst[4] , src[4] );
+		GF_ADDMULC( dst[5] , src[5] );
+		GF_ADDMULC( dst[6] , src[6] );
+		GF_ADDMULC( dst[7] , src[7] );
+#endif
+#if (UNROLL > 8)
+		GF_ADDMULC( dst[8] , src[8] );
+		GF_ADDMULC( dst[9] , src[9] );
+		GF_ADDMULC( dst[10] , src[10] );
+		GF_ADDMULC( dst[11] , src[11] );
+		GF_ADDMULC( dst[12] , src[12] );
+		GF_ADDMULC( dst[13] , src[13] );
+		GF_ADDMULC( dst[14] , src[14] );
+		GF_ADDMULC( dst[15] , src[15] );
+#endif
+	}
+#endif
+	lim += UNROLL - 1;
+	for (; dst < lim; dst++, src++) /* final components */
+		GF_ADDMULC( *dst , *src );
+}
+
+static void matmul(gf *a, gf *b, gf *c, int n, int k, int m)
+{
+	int row, col, i;
+
+	for (row = 0; row < n; row++)
+	{
+		for (col = 0; col < m; col++)
+		{
+			gf *pa = &a[row * k];
+			gf *pb = &b[col];
+			gf acc = 0;
+			for (i = 0; i < k; i++, pa++, pb += m)
+				acc ^= gf_mul( *pa, *pb );
+			c[row * m + col] = acc;
+		}
+	}
+}
+
+#ifdef DEBUG
+static int is_identity(gf *m, int k)
+{
+	int row, col;
+	for (row=0; row<k; row++)
+	for (col=0; col<k; col++)
+	if ( (row==col && *m != 1) || (row!=col && *m != 0) )
+	return 0;
+	else
+	m++;
+	return 1;
+}
+#endif /* debug */
+
+DEB( int pivloops=0; int pivswaps=0; /* diagnostic */)
+static int invert_mat(gf *src, int k)
+{
+	gf c, *p;
+	int irow, icol, row, col, i, ix;
+
+	int error = 1;
+	int *indxc = (int *) my_malloc(k * sizeof(int), "indxc");
+
+	int *indxr = (int *) my_malloc(k * sizeof(int), "indxr");
+	int *ipiv = (int *) my_malloc(k * sizeof(int), "ipiv");
+	gf *id_row = NEW_GF_MATRIX(1, k);
+	gf *temp_row = NEW_GF_MATRIX(1, k);
+
+	if ((indxc == 0) || (indxr == 0) || (id_row == 0) || (temp_row == 0)
+			|| (ipiv == 0))
+	{
+		goto fail;
+	}
+
+	bzero(id_row, k*sizeof(gf));
+	DEB( pivloops=0; pivswaps=0; /* diagnostic */)
+
+	for (i = 0; i < k; i++)
+		ipiv[i] = 0;
+
+	for (col = 0; col < k; col++)
+	{
+		gf *pivot_row;
+
+		irow = icol = -1;
+		if (ipiv[col] != 1 && src[col * k + col] != 0)
+		{
+			irow = col;
+			icol = col;
+			goto found_piv;
+		}
+		for (row = 0; row < k; row++)
+		{
+			if (ipiv[row] != 1)
+			{
+				for (ix = 0; ix < k; ix++)
+				{
+					DEB( pivloops++; )
+					if (ipiv[ix] == 0)
+					{
+						if (src[row * k + ix] != 0)
+						{
+							irow = row;
+							icol = ix;
+							goto found_piv;
+						}
+					}
+					else if (ipiv[ix] > 1)
+					{
+						//fprintf(stderr, "singular matrix\n");
+						goto fail;
+					}
+				}
+			}
+		}
+		if (icol == -1)
+		{
+			goto fail;
+		}
+		found_piv: ++(ipiv[icol]);
+
+		if (irow != icol)
+		{
+			for (ix = 0; ix < k; ix++)
+			{
+				SWAP( src[irow*k + ix], src[icol*k + ix], gf);
+			}
+		}
+		indxr[col] = irow;
+		indxc[col] = icol;
+		pivot_row = &src[icol * k];
+		c = pivot_row[icol];
+		if (c == 0)
+		{
+			goto fail;
+		}
+		if (c != 1)
+		{
+			DEB( pivswaps++; )
+			c = inverse[c];
+			pivot_row[icol] = 1;
+			for (ix = 0; ix < k; ix++)
+				pivot_row[ix] = gf_mul(c, pivot_row[ix] );
+		}
+		id_row[icol] = 1;
+		if (bcmp(pivot_row, id_row, k*sizeof(gf)) != 0)
+		{
+			for (p = src, ix = 0; ix < k; ix++, p += k)
+			{
+				if (ix != icol)
+				{
+					c = p[icol];
+					p[icol] = 0;
+					addmul(p, pivot_row, c, k );
+				}
+			}
+		}
+		id_row[icol] = 0;
+	} /* done all columns */
+	for (col = k - 1; col >= 0; col--)
+	{
+		if (indxr[col] < 0 || indxr[col] >= k)
+		{
+			goto fail;
+		}
+		else if (indxc[col] < 0 || indxc[col] >= k)
+		{
+			goto fail;
+		}
+		else if (indxr[col] != indxc[col])
+		{
+			for (row = 0; row < k; row++)
+			{
+				SWAP( src[row*k + indxr[col]], src[row*k + indxc[col]], gf);
+			}
+		}
+	}
+
+	error = 0;
+	fail: if (indxc != 0)
+		free(indxc);
+	if (indxr != 0)
+		free(indxr);
+	if (ipiv != 0)
+		free(ipiv);
+	if (id_row != 0)
+		free(id_row);
+	if (temp_row != 0)
+		free(temp_row);
+	return error;
+}
+
+int invert_vdm(gf *src, int k)
+{
+	int i, j, row, col;
+	gf *b, *c, *p;
+	gf t, xx;
+
+	if (k == 1) /* degenerate case, matrix must be p^0 = 1 */
+		return 0;
+
+	c = NEW_GF_MATRIX(1, k);
+
+	b = NEW_GF_MATRIX(1, k);
+
+	p = NEW_GF_MATRIX(1, k);
+	if ((c == 0) || (b == 0) || (p == 0))
+	{
+		if (b == 0)
+			free(b);
+		if (c == 0)
+			free(c);
+		if (p == 0)
+			free(p);
+		return 1;
+	}
+
+	for (j = 1, i = 0; i < k; i++, j += k)
+	{
+		c[i] = 0;
+		p[i] = src[j]; /* p[i] */
+	}
+	c[k - 1] = p[0]; /* really -p(0), but x = -x in GF(2^m) */
+	for (i = 1; i < k; i++)
+	{
+		gf p_i = p[i]; /* see above comment */
+		for (j = k - 1 - (i - 1); j < k - 1; j++)
+			c[j] ^= gf_mul( p_i, c[j+1] );
+		c[k - 1] ^= p_i;
+	}
+
+	for (row = 0; row < k; row++)
+	{
+
+		xx = p[row];
+		t = 1;
+		b[k - 1] = 1; /* this is in fact c[k] */
+		for (i = k - 2; i >= 0; i--)
+		{
+			b[i] = c[i + 1] ^ gf_mul(xx, b[i+1]);
+			t = gf_mul(xx, t) ^ b[i];
+		}
+		for (col = 0; col < k; col++)
+			src[col * k + row] = gf_mul(inverse[t], b[col] );
+	}
+	free(c);
+	free(b);
+	free(p);
+	return 0;
+}
+
+static int fec_initialized = 0;
+static void init_fec()
+{
+
+	generate_gf();
+
+	init_mul_table();
+
+	fec_initialized = 1;
+}
+
+#define FEC_MAGIC	0xFECC0DEC
+
+struct fec_parms
+{
+	u_long magic;
+	int k, n; /* parameters of the code */
+	gf *enc_matrix;
+};
+
+void fec_free(struct fec_parms *p)
+{
+	if (p == 0 || p->magic != (((FEC_MAGIC ^ p->k) ^ p->n)
+			^ (int) (p->enc_matrix)))
+	{
+		return;
+	}
+	free(p->enc_matrix);
+	free(p);
+}
+
+struct fec_parms * fec_new(int k, int n)
+{
+	int row, col;
+	gf *p, *tmp_m;
+
+	struct fec_parms *retval;
+
+	if (fec_initialized == 0)
+		init_fec();
+
+	if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n)
+	{
+		return 0;
+	}
+
+	retval
+			= (struct fec_parms*) my_malloc(sizeof(struct fec_parms),
+					"new_code");
+	if (retval == 0)
+		return 0;
+
+	retval->k = k;
+	retval->n = n;
+	retval->enc_matrix = NEW_GF_MATRIX(n, k);
+	if (retval->enc_matrix == 0)
+	{
+		free(retval);
+		return 0;
+	}
+
+	retval->magic = ((FEC_MAGIC ^ k) ^ n) ^ (int) (retval->enc_matrix);
+	tmp_m = NEW_GF_MATRIX(n, k);
+	if (tmp_m == 0)
+	{
+		free(retval->enc_matrix);
+		free(retval);
+		return 0;
+	}
+
+	tmp_m[0] = 1;
+	for (col = 1; col < k; col++)
+		tmp_m[col] = 0;
+	for (p = tmp_m + k, row = 0; row < n - 1; row++, p += k)
+	{
+		for (col = 0; col < k; col++)
+			p[col] = gf_exp[modnn(row * col)];
+	}
+
+	if (invert_vdm(tmp_m, k)) /* much faster than invert_mat */
+	{
+		free(retval->enc_matrix);
+		free(retval);
+		free(tmp_m);
+		return 0;
+	}
+	matmul(tmp_m + k * k, tmp_m, retval->enc_matrix + k * k, n - k, k, k);
+
+	bzero(retval->enc_matrix, k*k*sizeof(gf) );
+	for (p = retval->enc_matrix, col = 0; col < k; col++, p += k + 1)
+		*p = 1;
+	free(tmp_m);
+
+	DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");)
+	return retval;
+}
+
+void fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz)
+{
+	int i, k = code->k;
+	gf *p;
+
+	if (GF_BITS > 8)
+		sz /= 2;
+
+	if (index < k)
+		bcopy(src[index], fec, sz*sizeof(gf) );
+	else if (index < code->n)
+	{
+		p = &(code->enc_matrix[index * k]);
+		bzero(fec, sz*sizeof(gf));
+		for (i = 0; i < k; i++)
+			addmul(fec, src[i], p[i], sz );
+	}
+	else
+		;
+
+}
+
+static int shuffle(gf *pkt[], int index[], int k)
+{
+	int i;
+
+	for (i = 0; i < k;)
+	{
+		if (index[i] >= k || index[i] == i)
+			i++;
+		else
+		{
+			int c = index[i];
+
+			if (index[c] == c)
+			{
+				return 1;
+			}
+			SWAP(index[i], index[c], int);
+			SWAP(pkt[i], pkt[c], gf *);
+		}
+	}
+	DEB(
+			for ( i = 0; i < k; i++ )
+			{
+				if (index[i] < k && index[i] != i)
+				{
+					return 1;
+				}
+			}
+	)
+	return 0;
+}
+
+static gf* build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[])
+{
+	int i, k = code->k;
+	gf *p, *matrix = NEW_GF_MATRIX(k, k);
+
+	if (matrix == 0)
+	{
+		return 0;
+	}
+	for (i = 0, p = matrix; i < k; i++, p += k)
+	{
+		if (index[i] < k)
+		{
+			bzero(p, k*sizeof(gf) );
+			p[i] = 1;
+		}
+		else if (index[i] < code->n)
+			bcopy( &(code->enc_matrix[index[i]*k]), p, k*sizeof(gf) );
+		else
+		{
+			free(matrix);
+			return 0;
+		}
+	}
+
+	if (invert_mat(matrix, k))
+	{
+		free(matrix);
+		matrix = 0;
+	}
+	return matrix;
+}
+
+int fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz)
+{
+	gf *m_dec;
+	gf **new_pkt;
+	int i, row, col, k = code->k;
+
+	if (GF_BITS > 8)
+		sz /= 2;
+
+	if (shuffle(pkt, index, k)) /* error if true */
+		return 1;
+	m_dec = build_decode_matrix(code, pkt, index);
+
+	if (m_dec == 0)
+		return 1; /* error */
+
+	new_pkt = (gf **) my_malloc(k * sizeof(gf *), "new pkt pointers");
+	if (new_pkt == 0)
+	{
+		free(m_dec);
+		return 1;
+	}
+	for (row = 0; row < k; row++)
+	{
+		if (index[row] >= k)
+		{
+			new_pkt[row] = (gf *) my_malloc(sz * sizeof(gf), "new pkt buffer");
+			if (new_pkt[row] == 0)
+			{
+				free(m_dec);
+				for (i = 0; i < row; i++)
+				{
+					free(new_pkt[row]);
+				}
+				free(new_pkt);
+				return 1;
+			}
+			bzero(new_pkt[row], sz * sizeof(gf) );
+			for (col = 0; col < k; col++)
+				addmul(new_pkt[row], pkt[col], m_dec[row*k + col], sz);
+		}
+	}
+
+	for (row = 0; row < k; row++)
+	{
+		if (index[row] >= k)
+		{
+			bcopy(new_pkt[row], pkt[row], sz*sizeof(gf));
+			free(new_pkt[row]);
+		}
+	}
+	free(new_pkt);
+	free(m_dec);
+	return 0;
+}
+
+CFECRtpSession::CFECRtpSession()
+{
+
+	//init for send.
+	m_nRedundentRate = 1;
+	m_nFrameNo = 0;
+
+	m_oldVideotimestamp = 0;
+	m_usLatestVideoSeq = 0;
+
+	int i;
+	for (i = 0; i < FECLISTSIZE; i++)
+	{
+		m_FECListInfo[i].b_isEmpty = true;
+		m_FECListInfo[i].ul_HaveArriveNum = 0;
+		m_FECListInfo[i].ul_timestamp = 0;
+		m_FECListInfo[i].ul_TotalNeedNum = 0;
+	}
+
+}
+
+CFECRtpSession::~CFECRtpSession()
+{
+
+}
+
+void CFECRtpSession::OnRTPPacket(RTPPacket *pack, const RTPTime &receivetime,
+		const RTPAddress *senderaddress)
+{
+	FECHEADER* fec_header;
+	unsigned char *RecvData;
+	RecvData = pack->GetPayloadData();
+	fec_header = (FECHEADER*) RecvData;
+	int Datalen = pack->GetPayloadLength();
+
+	int rtptimestamp = pack->GetTimestamp();
+	int rtpFramNo = pack->GetExtensionID();
+
+	if (m_oldVideotimestamp != 0 || m_usLatestVideoSeq != 0)
+	{
+		if (rtptimestamp <= m_oldVideotimestamp && rtpFramNo
+				<= m_usLatestVideoSeq)
+		{
+			if (m_usLatestVideoSeq - rtpFramNo <= 10 && m_oldVideotimestamp
+					- rtptimestamp <= 10)
+				return;
+
+		}
+		m_usLatestVideoSeq = 0;
+		m_oldVideotimestamp = 0;
+	}
+
+	if (fec_header->FecCoded == 0)
+	{
+
+		int nVideoframeNum;
+		bool bIsSameVideoUDP = false;
+		nVideoframeNum = m_PreSendFrameList.size();
+
+		if (bIsSameVideoUDP == false)
+		{
+			unsigned char* pPacket;
+			pPacket = new unsigned char[Datalen];
+			if (pPacket == NULL)
+			{
+				return;
+			}
+
+			memcpy(pPacket, RecvData, Datalen);
+
+			FRAMEINFO* pFrameInfo = NULL;
+			pFrameInfo = new FRAMEINFO;
+
+			if (pFrameInfo == NULL)
+			{
+				delete pPacket;
+				return;
+			}
+
+			pFrameInfo->FECCoded = false;
+			pFrameInfo->ul_timestamp = rtptimestamp;
+			pFrameInfo->us_latestseq = rtpFramNo;
+			pFrameInfo->l_datalen = Datalen - sizeof(FECHEADER);
+			pFrameInfo->pData = pPacket + sizeof(FECHEADER);
+
+			m_PreSendFrameList.insert(m_PreSendFrameList.end(), pFrameInfo);
+			UpdateFrames();
+
+		}
+	}
+	else
+	{
+		if (fec_header->FecCoded == 1)
+		{//7	
+
+			FRAMEINFO* pFrameInfo;
+			FRAMEINFOLIST::iterator itera;
+			for (itera = m_PreSendFrameList.begin(); itera
+					!= m_PreSendFrameList.end(); ++itera)
+			{
+				pFrameInfo = *itera;
+				if (rtptimestamp == pFrameInfo->ul_timestamp)
+					return;
+			}
+
+			int i;
+			bool b_isNotAdd = true;
+
+			for (i = 0; i < FECLISTSIZE; i++)
+			{//6
+				if (m_VideoDataList[i].size() != 0)
+				{//5
+					if (rtptimestamp == m_FECListInfo[i].ul_timestamp)
+					{
+						b_isNotAdd = false;
+
+						bool bIsSameFECVideoData = false;
+
+						if (bIsSameFECVideoData == false)
+						{
+							unsigned char *pPack = new unsigned char[Datalen];
+							if (pPack == NULL)
+							{
+								return;
+							}
+							memcpy(pPack, RecvData, Datalen);
+
+							m_VideoDataList[i].insert(m_VideoDataList[i].end(),
+									(char*) pPack);
+
+							m_FECListInfo[i].ul_HaveArriveNum++;
+
+							if (m_FECListInfo[i].ul_HaveArriveNum
+									== m_FECListInfo[i].ul_TotalNeedNum)
+							{
+								if (FECDecode(&(m_FECListInfo[i]),
+										&m_VideoDataList[i], pack) == 0)
+								{
+
+									UpdateFrames();
+								}
+								else
+								{
+									printf("\nFEC decode failed.");
+
+								}
+							}
+						}//4
+					}//5					
+				}//6
+			}
+			if (b_isNotAdd)
+			{
+				for (i = 0; i < FECLISTSIZE; i++)
+				{
+
+					if (m_FECListInfo[i].b_isEmpty)
+					{
+						unsigned char *pPack = new unsigned char[Datalen];
+						if (pPack == NULL)
+						{
+							return;
+						}
+						memcpy(pPack, RecvData, Datalen);
+
+						m_VideoDataList[i].insert(m_VideoDataList[i].end(),
+								(char*) pPack);
+
+						m_FECListInfo[i].b_isEmpty = false;
+						m_FECListInfo[i].ul_HaveArriveNum = 1;
+						m_FECListInfo[i].ul_timestamp = rtptimestamp;
+
+						m_FECListInfo[i].ul_TotalNeedNum
+								= fec_header->OriginalK;
+						b_isNotAdd = false;
+						return;
+					}
+				}
+			}
+			if (b_isNotAdd)
+			{
+				ulong time = m_FECListInfo[0].ul_timestamp;
+				int j = 0;
+
+				for (i = 1; i < FECLISTSIZE; i++)
+				{
+					if (m_FECListInfo[i].ul_timestamp < time)
+					{
+						time = m_FECListInfo[i].ul_timestamp;
+						j = i;
+					}
+				}
+
+				char* p;
+				FECDATALIST::iterator itera;
+				for (itera = m_VideoDataList[j].begin(); itera
+						!= m_VideoDataList[j].end(); ++itera)
+				{
+					p = *itera;
+					delete p;
+					p = 0;
+				}
+				m_VideoDataList[j].clear();
+
+				unsigned char *pPack = new unsigned char[Datalen];
+				if (pPack == NULL)
+				{
+					return;
+				}
+				memcpy(pPack, RecvData, Datalen);
+
+				m_VideoDataList[j].insert(m_VideoDataList[j].end(),
+						(char*) pPack);
+
+				m_FECListInfo[j].b_isEmpty = false;
+				m_FECListInfo[j].ul_HaveArriveNum = 1;
+				m_FECListInfo[j].ul_timestamp = rtptimestamp;
+				m_FECListInfo[j].ul_TotalNeedNum = fec_header->OriginalK;
+				return;
+			}
+		}
+	}
+	return;
+
+}
+
+int CFECRtpSession::FECDecode(FECLISTINFO* pFecListInfo,
+		FECDATALIST *pFecDataList, RTPPacket *pack)
+{
+	int PSize;
+	int *ixs;
+	void *code;
+	unsigned char* *d_src;
+
+	unsigned char * pDataBuf;
+	ulong ul_timestamp;
+	unsigned int kCount;
+	kCount = pFecListInfo->ul_TotalNeedNum;
+
+	FECHEADER* fec_header;
+	unsigned char *RecvData;
+	RecvData = pack->GetPayloadData();
+	fec_header = (FECHEADER*) RecvData;
+	int rtptimestamp = pack->GetTimestamp();
+	int rtpFramNo = pack->GetExtensionID();
+
+	ul_timestamp = rtptimestamp;
+	PSize = fec_header->PacketSize;
+
+	code = (*fec_new)(fec_header->OriginalK, fec_header->RedunN);
+	if (code == NULL)
+	{
+		return 1;
+	}
+	ixs = new int[kCount];
+	if (ixs == NULL)
+	{
+		fec_free((struct fec_parms *) code);
+		return 1;
+	}
+	d_src = new PUCHAR[kCount];
+	if (d_src == NULL)
+	{
+		delete ixs;
+		fec_free((struct fec_parms *) code);
+		return 1;
+	}
+	long OriginalDataLen;
+	unsigned int j;
+	for (j = 0; j < kCount; j++)
+	{
+		d_src[j] = new unsigned char[PSize];
+		if (d_src[j] == NULL)
+		{
+			delete ixs;
+			fec_free((struct fec_parms *) code);
+			for (unsigned int ii = 0; ii < j; ii++)
+			{
+				delete d_src[ii];
+			}
+			delete d_src;
+			return 1;
+		}
+	}
+	char* p;
+	FECDATALIST::iterator itera;
+	for (j = 0, itera = pFecDataList->begin(); j < kCount && itera
+			!= pFecDataList->end(); j++, itera++)
+	{
+		FECHEADER* fec_header1;
+		p = *itera;
+		fec_header1 = (FECHEADER*) (p);
+
+		ixs[j] = fec_header1->OrigiCol;
+		memcpy(d_src[j], (char*) (p + sizeof(FECHEADER)),
+				fec_header1->PacketSize);
+		delete p;
+	}
+
+	pFecDataList->clear();
+
+	pFecListInfo->b_isEmpty = true;
+	pFecListInfo->ul_HaveArriveNum = 0;
+	pFecListInfo->ul_timestamp = 0;
+	pFecListInfo->ul_TotalNeedNum = 0;
+
+	int CodeResult = 0;
+	try
+	{
+		CodeResult = fec_decode((struct fec_parms *) code,
+				(unsigned char **) d_src, ixs, PSize);
+	} catch (...)
+	{
+		CodeResult = 1;
+	}
+
+	if (CodeResult == 0)
+	{
+
+		OriginalDataLen = GetDataLen(d_src, PSize, kCount);
+		pDataBuf = new unsigned char[OriginalDataLen];
+		if (pDataBuf != NULL)
+		{
+			GetData(pDataBuf, d_src, PSize, kCount);
+
+			FRAMEINFO *pFrameInfo;
+			pFrameInfo = new FRAMEINFO;
+			if (pFrameInfo != NULL)
+			{
+				pFrameInfo->FECCoded = true;
+				pFrameInfo->ul_timestamp = ul_timestamp;
+				pFrameInfo->us_latestseq = rtpFramNo;
+				pFrameInfo->l_datalen = OriginalDataLen;
+				pFrameInfo->pData = pDataBuf;
+
+				m_PreSendFrameList.insert(m_PreSendFrameList.end(), pFrameInfo);
+			}
+		}
+
+	}
+
+	delete ixs;
+	for (unsigned int i = 0; i < kCount; i++)
+	{
+		delete d_src[i];
+	}
+	delete d_src;
+	fec_free((struct fec_parms *) code);
+
+	return CodeResult;
+
+}
+
+long CFECRtpSession::GetDataLen(PUCHAR* d_src, long lPacketSize,
+		unsigned int kCount)
+{
+	PADHEADER* pad_header;
+	long OriginalDataLen = 0;
+
+	for (unsigned int i = 0; i < kCount; i++)
+	{
+		pad_header = (PADHEADER*) (d_src[i]);
+		if (pad_header->paddled == 0)
+		{
+			OriginalDataLen = OriginalDataLen + lPacketSize - sizeof(PADHEADER);
+		}
+		else if (pad_header->paddled == 1)
+		{
+			OriginalDataLen = OriginalDataLen + lPacketSize - sizeof(PADHEADER)
+					- pad_header->padlen;
+		}
+	}
+	return OriginalDataLen;
+}
+
+void CFECRtpSession::GetData(unsigned char* pData, PUCHAR* d_src,
+		long lPacketSize, unsigned int kCount)
+{
+	unsigned char* midbuf;
+	midbuf = pData;
+	PADHEADER* pad_header;
+	for (unsigned int i = 0; i < kCount; i++)
+	{
+		pad_header = (PADHEADER*) (d_src[i]);
+		if (pad_header->paddled == 0)
+		{
+			memcpy(midbuf, d_src[i] + sizeof(PADHEADER), lPacketSize
+					- sizeof(PADHEADER));
+			midbuf = midbuf + lPacketSize - sizeof(PADHEADER);
+		}
+		else if (pad_header->paddled == 1)
+		{
+			memcpy(midbuf, d_src[i] + sizeof(PADHEADER), lPacketSize
+					- sizeof(PADHEADER) - pad_header->padlen);
+			midbuf = midbuf + lPacketSize - sizeof(PADHEADER)
+					- pad_header->padlen;
+		}
+	}
+
+}
+
+int CFECRtpSession::GetRtpMaxLen()
+{
+
+	return RtpMaxLen;
+}
+
+int CFECRtpSession::SendFECPacket(void *lpData, int datalen, int ndelay /* = 5000*/)
+{
+	int nRtpMaxLen;
+	char *pFECPacket;
+	FECHEADER* fec_header;
+
+	pFECPacket = 0;
+	nRtpMaxLen = GetRtpMaxLen();
+
+	IncrementTimestamp(1);
+	SetDefaultTimestampIncrement(0);
+	m_nFrameNo++;
+	if (datalen + sizeof(FECHEADER) <= nRtpMaxLen)
+	{ //Send a FEC packet directly.
+		pFECPacket = new char[datalen + sizeof(FECHEADER)];
+		if (pFECPacket == 0)
+		{
+			return -1;
+		}
+		fec_header = (FECHEADER*) pFECPacket;
+		fec_header->FecCoded = 0;
+		memcpy(pFECPacket + sizeof(FECHEADER), lpData, datalen);
+
+		SendPacketEx(pFECPacket, datalen + sizeof(FECHEADER), m_nFrameNo, 0, 0);
+		delete[] pFECPacket;
+		usleep(ndelay);
+		return 0;
+	}
+
+	FECEncodeSend(lpData, datalen, m_nFrameNo, ndelay);
+	return 0;
+}
+
+int CFECRtpSession::FECEncodeSend(void *pData, long datalen,
+		unsigned int FrameNo, int ndelay)
+{
+	int SZ;
+	void *code = 0;
+	int kk;
+	uchar* SendData = 0;
+	FECHEADER* fec_header;
+	PADHEADER* pad_header;
+	int lim = GF_SIZE + 1;
+	int *ixs = 0;
+	int redudant, i;
+	int lastpacketlen;
+	uchar **d_original, **d_src;
+
+	bool CodeResult = true;
+
+	SZ = GetRtpMaxLen();
+	try
+	{
+		kk = datalen / (SZ - sizeof(PADHEADER));
+	} catch (...)
+	{
+		return -1;
+	}
+	if (kk < 0)
+		return -1;
+	lastpacketlen = datalen % (SZ - sizeof(PADHEADER));
+	if (lastpacketlen != 0)
+		kk++;
+	d_original = (uchar**) malloc(kk * sizeof(void *));
+	if (d_original == 0)
+		return -2;
+
+	d_src = (uchar**) malloc(kk * sizeof(void *));
+	if ((d_original == 0) || (d_src == 0))
+	{
+		free(d_original);
+		return -3;
+	}
+	for (i = 0; i < kk; i++)
+	{
+		d_original[i] = 0;
+		d_src[i] = 0;
+	}
+
+	for (i = 0; i < kk; i++)
+	{
+		d_original[i] = (uchar*) malloc(SZ);
+		if (d_original[i] == 0)
+			goto fail;
+		d_src[i] = (uchar*) malloc(SZ);
+		if (d_src[i] == 0)
+			goto fail;
+	}
+	code = (*fec_new)(kk, lim);
+	if (code == 0)
+	{
+		goto fail;
+	}
+
+	ixs = (int*) malloc(kk * sizeof(int));
+	if (ixs == 0)
+		goto fail;
+
+	SendData = (uchar*) malloc(SZ + sizeof(FECHEADER));
+	if (SendData == 0)
+		goto fail;
+
+	for (i = 0; i < kk; i++)
+		ixs[i] = kk + i;
+
+	for (i = 0; i < kk; i++)
+	{
+		pad_header = (PADHEADER*) d_original[i];
+		if ((i != (kk - 1)) || (lastpacketlen == 0))
+		{
+			pad_header->paddled = UNPAD;
+			pad_header->padlen = 0;
+
+			memcpy(d_original[i] + sizeof(PADHEADER), (uchar*) pData + i * (SZ
+					- sizeof(PADHEADER)), SZ - sizeof(PADHEADER));
+		}
+		else
+		{
+			pad_header->paddled = ISPAD;
+			pad_header->padlen = SZ - sizeof(PADHEADER) - lastpacketlen;
+			memcpy(d_original[i] + sizeof(PADHEADER), (uchar*) pData + i * (SZ
+					- sizeof(PADHEADER)), lastpacketlen);
+			memset(d_original[i] + sizeof(PADHEADER) + lastpacketlen, 'A', SZ
+					- sizeof(PADHEADER) - lastpacketlen);
+		}
+	}
+
+	int maxpacket;
+
+	if (m_nRedundentRate <= 0)
+	{
+		maxpacket = 0;
+	}
+	else if (m_nRedundentRate > 200)
+	{
+
+		maxpacket = 0;
+	}
+	else if (m_nRedundentRate > 100)
+	{
+		maxpacket = (int) ((m_nRedundentRate - 100) * kk / 100) + 1;
+		if (maxpacket > kk)
+		{
+			maxpacket = kk;
+		}
+
+		if (maxpacket > MAXFECPACKET - kk)
+		{
+			maxpacket = MAXFECPACKET - kk;
+		}
+	}
+	else
+	{
+		if (kk < 5)
+		{
+			maxpacket = kk;
+
+			if (maxpacket > MAXFECPACKET - kk)
+			{
+				maxpacket = MAXFECPACKET - kk;
+			}
+		}
+		else
+		{
+			maxpacket = (int) (m_nRedundentRate * kk / 100) + 5;
+
+			if (maxpacket > kk)
+			{
+				maxpacket = kk;
+			}
+			if (maxpacket > MAXFECPACKET - kk)
+			{
+				maxpacket = MAXFECPACKET - kk;
+			}
+		}
+	}
+
+	for (i = 0; i < maxpacket; i++)
+	{
+		try
+		{
+			fec_encode((fec_parms *) code, (unsigned char**) d_original,
+					(unsigned char*) (d_src[i]), ixs[i], SZ);
+		} catch (...)
+		{
+			CodeResult = false;
+		}
+	}
+
+	if (CodeResult == false)
+		goto fail;
+	redudant = 0;
+
+	if ((redudant != -1))
+	{
+		for (i = 0; i < kk; i++)
+		{
+			memset(SendData, 0, SZ + sizeof(FECHEADER));
+			fec_header = (FECHEADER*) SendData;
+			fec_header->FecCoded = FECCODED;
+			fec_header->OriginalK = kk;
+			fec_header->OrigiCol = i;
+			fec_header->PacketSize = SZ;
+			fec_header->RedunN = lim;
+			memcpy(SendData + sizeof(FECHEADER), d_original[i], SZ);
+
+			SendPacketEx(SendData, SZ + sizeof(FECHEADER), FrameNo, 0, 0);
+			usleep(ndelay);
+		}
+	}
+
+	if (kk > 20)
+	{
+		if (redudant == -1)
+		{
+			redudant = 1;
+		}
+		else if (kk > 20)
+		{
+			redudant = +5;
+		}
+	}
+
+	if (redudant >= kk)
+	{
+		redudant = kk;
+	}
+
+	if (kk + redudant >= MAXFECPACKET)
+		redudant = MAXFECPACKET - kk;
+
+	for (i = 0; i < maxpacket; i++)
+	{
+		memset(SendData, 0, SZ + sizeof(FECHEADER));
+		fec_header = (FECHEADER*) SendData;
+		fec_header->FecCoded = FECCODED;
+		fec_header->OriginalK = kk;
+		fec_header->OrigiCol = kk + i;
+		fec_header->PacketSize = SZ;
+		fec_header->RedunN = lim;
+		memcpy(SendData + sizeof(FECHEADER), d_src[i], SZ);
+
+		SendPacketEx(SendData, SZ + sizeof(FECHEADER), FrameNo, 0, 0);
+		usleep(ndelay);
+	}
+
+	if (SendData != 0)
+		free(SendData);
+	if (code != 0)
+		fec_free((fec_parms *) code);
+	for (i = 0; i < kk; i++)
+	{
+		free(d_original[i]);
+		free(d_src[i]);
+	}
+	free(d_original);
+	free(d_src);
+	free(ixs);
+	return 0;
+	fail: if (SendData != 0)
+		free(SendData);
+	if (code != 0)
+		fec_free((fec_parms *) code);
+	for (i = 0; i < kk; i++)
+	{
+		if (d_original[i] != 0)
+			free(d_original[i]);
+		if (d_src[i] != 0)
+			free(d_src[i]);
+	}
+	if (d_original != 0)
+		free(d_original);
+	if (d_src != 0)
+		free(d_src);
+	if (ixs != 0)
+		free(ixs);
+	return -5;
+}
+
+void CFECRtpSession::UpdateFrames()
+{
+	int framecount;
+	FRAMEINFO * p;
+	FRAMEINFOLIST::iterator itera;
+
+	framecount = m_PreSendFrameList.size();
+	if (framecount == 0)
+		return;
+
+	for (itera = m_PreSendFrameList.begin(); itera != m_PreSendFrameList.end(); ++itera)
+	{
+		p = *itera;
+		m_usLatestVideoSeq = p->us_latestseq;
+		m_oldVideotimestamp = p->ul_timestamp;
+		ProcessFrame(p->pData, p->l_datalen);
+		RemoveFrame(p);
+		p = 0;
+	}
+	m_PreSendFrameList.clear();
+	return;
+
+	for (itera = m_PreSendFrameList.begin(); itera != m_PreSendFrameList.end(); ++itera)
+	{
+		p = *itera;
+		if (p->us_latestseq == uint16_t(m_usLatestVideoSeq + 1))
+		{
+			m_usLatestVideoSeq = p->us_latestseq;
+			m_oldVideotimestamp = p->ul_timestamp;
+			ProcessFrame(p->pData, p->l_datalen);
+			RemoveFrame(p);
+			p = 0;
+			m_PreSendFrameList.erase(itera);
+			UpdateFrames();
+			return;
+		}
+	}
+
+	if (framecount < 3)
+		return;
+
+	FRAMEINFO *fff;
+	FRAMEINFOLIST::iterator kkk;
+	kkk = m_PreSendFrameList.begin();
+	fff = *kkk;
+	for (itera = kkk; itera != m_PreSendFrameList.end(); ++itera)
+	{
+		p = *itera;
+		if (fff->ul_timestamp > p->ul_timestamp)
+		{
+			kkk = itera;
+			fff = p;
+		}
+	}
+
+	m_usLatestVideoSeq = fff->us_latestseq;
+	m_oldVideotimestamp = fff->ul_timestamp;
+	ProcessFrame(fff->pData, fff->l_datalen);
+	RemoveFrame(fff);
+	fff = 0;
+	m_PreSendFrameList.erase(kkk);
+
+	return;
+
+}
+
+void CFECRtpSession::ProcessFrame(unsigned char *recvdata, int recvlen)
+{
+	return;
+
+}
+
+void CFECRtpSession::RemoveFrame(FRAMEINFO *p)
+{
+	if (p->FECCoded)
+		delete p->pData;
+	else if (!p->FECCoded)
+		delete (p->pData - sizeof(FECHEADER));
+	delete p;
+}



Mime
View raw message