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_)